omap3530/beagle_drivers/byd_touch/common/controller.cpp
author Lukasz Forynski <lukasz.forynski@gmail.com>
Tue, 02 Nov 2010 00:33:23 +0000
branchBeagle_BSP_dev
changeset 95 450a8cf0c020
parent 85 d93b485c1325
permissions -rw-r--r--
updated byd touch controller handling. needs debugging and update.

// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// lukasz.forynski@gmail.com
//
// Contributors:
//
// Description:
// omap3530/beagle_drivers/byd_touch/common/controller.cpp
//
#include <drivers/iic.h>
#include <drivers/iic_channel.h>
#include <assp/omap3530_assp/omap3530_gpio.h>
#include "controller.h"

//#define VERBOSE_DEBUG
#ifdef VERBOSE_DEBUG
#define LOG_FUNCTION_CALL Kern::Printf("%s()", __FUNCTION__)
#else
#define LOG_FUNCTION_CALL
#endif

TTouchControllerInterface::TTouchControllerInterface() :
	iSpiTransactionHeader(KHeader),
	iSpiTxTransfer(TIicBusTransfer::EMasterWrite, KBufGranulatity, &iSpiWriteBuffer),
	iSpiRxTransfer(TIicBusTransfer::EMasterRead, KBufGranulatity, &iSpiReadBuffer),
	iSpiTransaction(&iSpiTransactionHeader, &iSpiTxTransfer)
	{
	// after all above - make the transaction full duplex using the Rx buffer
	iSpiTransaction.SetFullDuplexTrans(&iSpiRxTransfer);

	// set buffer length only once..
	iSpiWriteBuffer.SetLength(iSpiWriteBuffer.MaxLength());
	iSpiReadBuffer.SetLength(iSpiReadBuffer.MaxLength());

	// and set SPI addressing / bus configuration
	iSpiBusId = 0;
	SET_BUS_TYPE(iSpiBusId, DIicBusChannel::ESpi);
	SET_CHAN_NUM(iSpiBusId, KSpiModule);
	SET_SLAVE_ADDR(iSpiBusId, KSpiSlaveAddr);
	}


// Writes number of bytes stored in the write buffer - to the controller.
// aNumOfBytes specifies number of bytes including first byte of address.
// The write buffer should contain the data from index=1 and it's length should be set
// to number of registers to update + 1 (one byte for the address / command)
TInt TTouchControllerInterface::WriteMultiple(TUint8 aStartAddress, TInt aNumBytes)
	{
	LOG_FUNCTION_CALL;
	if(aNumBytes != iSpiWriteBuffer.Length())
		{
#ifdef VERBOSE_DEBUG
		Kern::Printf("Transfer buffers are not properly set, line: %d", __LINE__);
#endif
		return KErrArgument;
		}
	iSpiReadBuffer.SetLength(aNumBytes);
	iSpiWriteBuffer[0] = KWriteCommand | (aStartAddress << 1);
	return IicBus::QueueTransaction(iSpiBusId, &iSpiTransaction);
	}


// Reads number of bytes and stores them into the read buffer
// aNumOfBytes specifies number of bytes (excluding first byte of address)
// The read buffer will contain the received data starting from index=1 (TODO: consider MidTPtr)
TInt TTouchControllerInterface::ReadMultiple(TUint8 aStartAddress, TInt aNumBytes)
	{
	LOG_FUNCTION_CALL;
	TInt r = KErrNone;

	// if trying to read from address different that currently stored - first update the read register..
	if(iCurrentReadStart != aStartAddress)
		{
		r = Write(KMasterReadStartAddr, aStartAddress);
		if(r != KErrNone)
			{
			return r;
			}
		iCurrentReadStart = aStartAddress;
		}

	// make sure buffers are set to the requested size
	iSpiReadBuffer.SetLength(aNumBytes + 1);
	iSpiWriteBuffer.SetLength(aNumBytes + 1);
	iSpiWriteBuffer[0] = KReadCommand;

	return IicBus::QueueTransaction(iSpiBusId, &iSpiTransaction);
	}

TInt TTouchControllerInterface::Write(TUint8 aRegAddress, TUint8 aValue)
	{
	LOG_FUNCTION_CALL;
	iSpiWriteBuffer.SetLength(2);
	iSpiReadBuffer.SetLength(2);
	iSpiWriteBuffer[0] = KWriteCommand | (aRegAddress << 1);
	iSpiWriteBuffer[1] = aValue;


#ifdef VERBOSE_DEBUG
	for (int i = 0; i < iSpiWriteBuffer.Length(); i++)
		Kern::Printf("WR0[i]: %d", iSpiWriteBuffer[i]);

	for (int i = 0; i < iSpiReadBuffer.Length(); i++)
		Kern::Printf("W0[i]: %d", iSpiReadBuffer[i]);
#endif
	TInt r = IicBus::QueueTransaction(iSpiBusId, &iSpiTransaction);

#ifdef VERBOSE_DEBUG
	for (int i = 0; i < iSpiReadBuffer.Length(); i++)
		Kern::Printf("W1[i]: %d", iSpiReadBuffer[i]);
#endif
	return r;
	}


TInt TTouchControllerInterface::Read(TUint8 aRegAddress, TUint8& aValue)
	{
	LOG_FUNCTION_CALL;
	TInt r = ReadMultiple(aRegAddress, 2);

	if(r == KErrNone)
		{
		aValue = iSpiReadBuffer[1];
		}
	return r;
	}


//(TODO: consider MidTPtr)
inline TDes& TTouchControllerInterface::ReadBuff()
	{
	return iSpiReadBuffer;
	}

//(TODO: consider MidTPtr)
inline TDes& TTouchControllerInterface::WriteBuff()
	{
	return iSpiWriteBuffer;
	}


// Touch controller implementation
TouchController::TouchController() :
	iCallback(NULL)
	{
	}

TouchController::TouchController(TVoidCallback aCallback) :
	iCallback(aCallback)
	{
	}

TInt TouchController::HardReset()
	{
	LOG_FUNCTION_CALL;
	TInt r = GPIO::SetPinMode(KResetPin, GPIO::EEnabled);
	if(r == KErrNone)
		{
		r = GPIO::SetPinDirection(KResetPin, GPIO::EOutput);
		if(r == KErrNone)
			{
#ifdef RESET_LOW
			GPIO::SetOutputState(KResetPin, GPIO::ELow);
#else
			GPIO::SetOutputState(KResetPin, GPIO::EHigh);
#endif
			Kern::NanoWait(25000); // should be > 10us
#ifdef RESET_LOW

			GPIO::SetOutputState(KResetPin, GPIO::EHigh);
#else
			GPIO::SetOutputState(KResetPin, GPIO::ELow);
#endif
			}
		}
	return r;
	}
TInt TouchController::SoftReset()
	{
	return iInterface.Write(KControl_0, KControl_0_SWRST);
	}

TInt TouchController::Configure(TTouchMode aMode)
	{
	LOG_FUNCTION_CALL;
	TDes& writeBuffer = iInterface.WriteBuff();
	writeBuffer.SetLength(14);

	// value for KControl_0 register in writeBuffer[1]
	switch(aMode)
		{
		case EModeSingle:
			writeBuffer[1] = KControl_0_MODE_SINGLE;
			break;
		case EModeMulti:
			writeBuffer[1] = KControl_0_MODE_MULTI;
			break;
		case EModeGesture:
			writeBuffer[1] = KControl_0_MODE_GESTURE;
			break;
		}

//	const TUint8 KWindowXStart_Msb = 0x4; // R/W
//	const TUint8 KWindowXStart_Lsb = 0x5; // R/W
//	const TUint8 KWindowXStop_Msb  = 0x6; // R/W
//	const TUint8 KWindowXStop_Lsb  = 0x7; // R/W
//	const TUint8 KWindowYStart_Msb = 0x8; // R/W
//	const TUint8 KWindowYStart_Lsb = 0x9; // R/W
//	const TUint8 KWindowYStop_Msb  = 0xa; // R/W
//	const TUint8 KWindowYStop_Lsb  = 0xb; // R/W
//	const TUint8 KMasterReadStartAddr = 0xc; // R/W

	writeBuffer[2] = (TInt8)(KControl_1_PAT_100 | KControl_1_PVT_200); // KControl_1 // TODO: update these values..
	writeBuffer[3] = (TInt8)(KNumColumns << KControl_2_C_SHIFT);       // KControl_2 // TODO: update these values..
	writeBuffer[4] = (TInt8)(KNumRows    << KControl_3_R_SHIFT);       // KControl_3 // TODO: update these values..

	writeBuffer[5] = 0; // KWindowXStart_Msb // TODO: update these values..
	writeBuffer[6] = 0; // KWindowXStart_Lsb // TODO: update these values..
	writeBuffer[7] = 0; // KWindowXStop_Msb // TODO: update these values..
	writeBuffer[8] = 0; // KWindowXStop_Lsb // TODO: update these values..

	writeBuffer[9] = 0; // KWindowYStart_Msb // TODO: update these values..
	writeBuffer[10] = 0; // KWindowYStart_Lsb // TODO: update these values..
	writeBuffer[11] = 0; // KWindowYStop_Msb // TODO: update these values..
	writeBuffer[12] = 0; // KWindowYStop_Lsb // TODO: update these values..
	writeBuffer[13] = 0; // KMasterReadStartAddr // TODO: update these values..

	return iInterface.WriteMultiple(KControl_0, 14);
	}

TInt TouchController::SetTouchMode(TTouchMode aMode)
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[0] &= ~KControl_0_MODE_MASK; // clear all mode bits
	switch(aMode)
		{
		case EModeSingle:
			iCtrlRegsCache[0] |= KControl_0_MODE_SINGLE;
			break;
		case EModeMulti:
			iCtrlRegsCache[0] |= KControl_0_MODE_MULTI;
			break;
		case EModeGesture:
			iCtrlRegsCache[0] |= KControl_0_MODE_GESTURE;
			break;
		}

	return iInterface.Write(KControl_0, iCtrlRegsCache[0]);
	}


TInt TouchController::SetResolution(TResolution aResolution)
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[0] &= ~KControl_0_RM_12; // clear all mode bits
	if(aResolution == ERes12Bits)
		{
		iCtrlRegsCache[0] |= KControl_0_RM_12; // set bit
		}
	return iInterface.Write(KControl_0, iCtrlRegsCache[0]);
	}


TInt TouchController::SetLongerSamplingRate(TUint aRate)
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[0] &= ~KControl_0_LST_MASK; // clear bits..
	iCtrlRegsCache[0] |= aRate & KControl_0_LST_MASK; // set new value..
	return iInterface.Write(KControl_0, iCtrlRegsCache[0]);
	}


TInt TouchController::SetIrqActiveTime(TUint aIrqActiveTime)
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[1] &= ~KControl_1_PAT_MASK; // clear bits..
	iCtrlRegsCache[1] |= (aIrqActiveTime << KControl_1_PAT_SHIFT) & KControl_1_PAT_MASK; // set new value..
	return iInterface.Write(KControl_1, iCtrlRegsCache[1]);
	}


TInt TouchController::SetPanelVoltageStabTime(TUint aVoltageStabilizationTime)
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[1] &= ~KControl_1_PVT_MASK; // clear bits..
	iCtrlRegsCache[1] |= (aVoltageStabilizationTime << KControl_1_PVT_SHIFT) & KControl_1_PVT_MASK; // set new value..
	return iInterface.Write(KControl_1, iCtrlRegsCache[1]);
	}


TInt TouchController::SetNumberOfColumns(TUint aNumberOfColumns)
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[2] &= ~KControl_2_C_MASK; // clear bits..
	iCtrlRegsCache[2] |= (aNumberOfColumns << KControl_2_C_SHIFT) & KControl_2_C_MASK;
	return iInterface.Write(KControl_2, iCtrlRegsCache[2]);
	}


TInt TouchController::SetNumberOfRows(TUint aNumberOfRows)
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[3] &= ~KControl_3_R_SHIFT; // clear bits..
	iCtrlRegsCache[3] |= (aNumberOfRows << KControl_3_R_SHIFT) & KControl_3_R_MASK; // set new value..
	return iInterface.Write(KControl_3, iCtrlRegsCache[3]);
	}


TInt TouchController::EnableWindowMode(TPoint aStart, TPoint aStop)
	{
	LOG_FUNCTION_CALL;
	TDes& writeBuffer = iInterface.WriteBuff();
	writeBuffer.SetLength(9);

	// setup window points
	writeBuffer[0] = KWriteCommand | (KWindowXStart_Msb << 1); // address of first register to write..
	writeBuffer[1] = (TUint8)(aStart.iX >> 8); // KWindowXStart_Msb
	writeBuffer[2] = (TUint8)(aStart.iX);      // KWindowXStart_Lsb
	writeBuffer[3] = (TUint8)(aStop.iX >> 8);  // KWindowXStop_Msb
	writeBuffer[4] = (TUint8)(aStop.iX);       // KWindowXStop_Lsb
	writeBuffer[5] = (TUint8)(aStart.iY >> 8); // KWindowYStart_Msb
	writeBuffer[6] = (TUint8)(aStart.iY);      // KWindowYStart_Lsb
	writeBuffer[7] = (TUint8)(aStop.iY >> 8);  // KWindowYStop_Msb
	writeBuffer[8] = (TUint8)(aStop.iY);       // KWindowYStop_Lsb

	return iInterface.WriteMultiple(KWindowXStart_Msb, 9);
	}

TInt TouchController::DisableWindowMode()
	{
	LOG_FUNCTION_CALL;
	iCtrlRegsCache[1] &= ~KControl_1_WS; // clear enable bit..
	return iInterface.Write(KControl_1, iCtrlRegsCache[1]);
	}

TInt TouchController::NumOfTouches()
	{
	TUint8 val = 0;
	TInt r = iInterface.Read(KTouchNumberAndType, val);
	if (r == KErrNone)
		{
		r = val;
		}
	return r;
	}

TInt TouchController::GetMeasurements(TPoint* aPoints, TInt& aNumPoints)
	{
	LOG_FUNCTION_CALL;
	TInt r = KErrArgument;
	TInt num_points = 0;

	if(aPoints)
		{
		r = iInterface.ReadMultiple(KTouchNumberAndType, 14);

		if(r == KErrNone)
			{
			TDes& readBuffer = iInterface.ReadBuff();

			// check how many points is there to read..
			TUint8 val = readBuffer[1]; // TODO: update this if MidTPtr could be used..
	//		Kern::Printf("KTouchNumberAndType %x", val);

			// if in multi mode - read all received, but only up to one otherwise..
			num_points = val & (val & KTouchNumberAndType_MULTI ? KTouchNumberAndType_TouchNMask : 1);

			// read the coordinates..
			for (TInt i = 0; i < num_points; i++) // if anything was touched at all..
				{
				// get X coordinate
				aPoints[i].iX |= TInt(readBuffer[(i << 2) + 1] << 8); // X_H
				aPoints[i].iX =  TInt(readBuffer[(i << 2) + 2]);      // X_L

				// get Y coordinate
				aPoints[i].iY |= TInt(readBuffer[(i << 2) + 3] << 8); // Yx_H
				aPoints[i].iY =  TInt(readBuffer[(i << 2) + 4]);      // Y_L
				}

			aNumPoints = num_points;
			}
		}
	return r;
	}