updated SPI. Added template touch (byd_touch) -WORKING version,does not work-needs update as I missunderstood how the touchcontroller(chip) works. Submitting in order to share whatever there was-prior to going for holiday Beagle_BSP_dev
authorLukasz Forynski <lukasz.forynski@gmail.com>
Thu, 07 Oct 2010 00:37:22 +0100
branchBeagle_BSP_dev
changeset 85 d93b485c1325
parent 84 09e266454dcf
child 86 56c9b613f311
child 95 450a8cf0c020
updated SPI. Added template touch (byd_touch) -WORKING version,does not work-needs update as I missunderstood how the touchcontroller(chip) works. Submitting in order to share whatever there was-prior to going for holiday
omap3530/beagle_drivers/byd_touch/bld.inf
omap3530/beagle_drivers/byd_touch/common/controller.cpp
omap3530/beagle_drivers/byd_touch/common/controller.h
omap3530/beagle_drivers/byd_touch/xyin.mmp
omap3530/beagle_drivers/byd_touch/xyin/mconf.h
omap3530/beagle_drivers/byd_touch/xyin/xyin.cpp
omap3530/beagleboard/rom/kernel.iby
omap3530/omap3530_drivers/spi/master.cpp
omap3530/omap3530_drivers/spi/omap3530_spi.h
omap3530/omap3530_drivers/spi/omap3530_spi.inl
omap3530/omap3530_drivers/spi/test/d_spi_client_m.cpp
omap3530/omap3530_drivers/spi/test/t_spi_client_m.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/byd_touch/bld.inf	Thu Oct 07 00:37:22 2010 +0100
@@ -0,0 +1,20 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// 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:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+PRJ_PLATFORMS
+ARMV5
+
+PRJ_MMPFILES
+xyin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/byd_touch/common/controller.cpp	Thu Oct 07 00:37:22 2010 +0100
@@ -0,0 +1,335 @@
+// 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);
+	}
+
+TInt TTouchControllerInterface::Read(TUint8 aRegAddress, TUint8& aValue)
+	{
+	LOG_FUNCTION_CALL;
+	iSpiWriteBuffer[0] = KReadCommand;
+	iSpiWriteBuffer[1] = aRegAddress;
+	iSpiWriteBuffer[2] = 0; // TODO - might not be needed..
+#ifdef VERBOSE_DEBUG
+	for (int i = 0; i <KSpiPacketLength; i++)
+		Kern::Printf("R0[i]: %d", iSpiReadBuffer[1]);
+#endif
+	TInt r = IicBus::QueueTransaction(iSpiBusId, &iSpiTransaction);
+	if(r == KErrNone)
+		{
+		aValue = iSpiReadBuffer[2];
+		}
+#ifdef VERBOSE_DEBUG
+	for (int i = 0; i <KSpiPacketLength; i++)
+		Kern::Printf("R1[i]: %d", iSpiReadBuffer[1]);
+#endif
+	return r;
+	}
+
+TInt TTouchControllerInterface::Write(TUint8 aRegAddress, TUint8 aValue)
+	{
+	LOG_FUNCTION_CALL;
+	iSpiWriteBuffer[0] = KWriteCommand;
+	iSpiWriteBuffer[1] = aRegAddress;
+	iSpiWriteBuffer[2] = aValue;
+
+#ifdef VERBOSE_DEBUG
+	for (int i = 0; i < 3; i++)
+		Kern::Printf("WR0[i]: %d", iSpiWriteBuffer[i]);
+
+	for (int i = 0; i <KSpiPacketLength; i++)
+		Kern::Printf("W0[i]: %d", iSpiReadBuffer[1]);
+#endif
+	TInt r = IicBus::QueueTransaction(iSpiBusId, &iSpiTransaction);
+
+#ifdef VERBOSE_DEBUG
+	for (int i = 0; i <KSpiPacketLength; i++)
+		Kern::Printf("W1[i]: %d", iSpiReadBuffer[1]);
+#endif
+	return r;
+	}
+
+// Touch controller
+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)
+			{
+//			GPIO::SetOutputState(KResetPin, GPIO::ELow);
+			GPIO::SetOutputState(KResetPin, GPIO::EHigh);
+//			GPIO::SetOutputState(KResetPin, GPIO::ELow);
+
+			Kern::NanoWait(25000); // should be > 10us
+//			GPIO::SetOutputState(KResetPin, GPIO::EHigh);
+			GPIO::SetOutputState(KResetPin, GPIO::ELow);
+
+			}
+		}
+//	Kern::NanoWait(1000000);
+//	SoftReset();
+//	Kern::NanoWait(1000000);
+
+	iInterface.Write(KMasterReadStartAddr, X1_H);
+	return r;
+	}
+TInt TouchController::SoftReset()
+	{
+	LOG_FUNCTION_CALL;
+	for(TInt i = 0; i<4; i++)
+		{
+		iCtrlRegsCache[i] = 0;
+		}
+	return iInterface.Write(KControl_0, KControl_0_SWRST);
+	}
+
+TInt TouchController::SetTouchMode(TTouchMode aMode)
+	{
+	LOG_FUNCTION_CALL;
+	iCtrlRegsCache[0] &= ~KControl_0_MODE_MASK; // clear all mode bits
+	switch(aMode)
+		{
+		case ESingle:
+			iCtrlRegsCache[0] |= KControl_0_MODE_SINGLE;
+			break;
+		case EMulti:
+			iCtrlRegsCache[0] |= KControl_0_MODE_MULTI;
+			break;
+		case EGesture:
+			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;
+
+	TBool error_occured = EFalse;
+	// setup window points
+	TInt r = iInterface.Write(KWindowXStart_Msb, (TUint8)(aStart.iX >> 8));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	r = iInterface.Write(KWindowXStart_Lsb, (TUint8)(aStart.iX));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	r = iInterface.Write(KWindowYStart_Msb, (TUint8)(aStart.iY >> 8));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	r = iInterface.Write(KWindowYStart_Lsb, (TUint8)(aStart.iY));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	r = iInterface.Write(KWindowXStop_Msb, (TUint8)(aStop.iX >> 8));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	r = iInterface.Write(KWindowXStop_Lsb, (TUint8)(aStop.iX));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	r = iInterface.Write(KWindowYStop_Msb, (TUint8)(aStop.iY >> 8));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	r = iInterface.Write(KWindowYStop_Lsb, (TUint8)(aStop.iY));
+	if(r != KErrNone)
+		error_occured = ETrue;
+
+	// enable mode
+	if(!error_occured)
+		{
+		iCtrlRegsCache[1] |= ~KControl_1_WS; // set enable bit..
+		r = iInterface.Write(KControl_1, iCtrlRegsCache[1]);
+		}
+	else
+		{
+		r = KErrGeneral;
+		}
+	return r;
+	}
+
+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;
+	return iInterface.Read(KTouchNumberAndType, val);
+	}
+
+TInt TouchController::GetMeasurements(TPoint* aPoints, TInt& aNumPoints)
+	{
+	LOG_FUNCTION_CALL;
+	TInt r = KErrArgument;
+	TInt num_points = 0;
+	if(aPoints)
+		{
+		// check how many points is there to read..
+		TUint8 val = 0;
+		r = iInterface.Read(KTouchNumberAndType, val);
+
+		//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);
+
+		// setup the transaction:
+		for (TInt i = 0; i < num_points; i++) // if anything was touched at all..
+			{
+			// get X coordinate
+			r = iInterface.Read(X1_H + (i << 2), val);
+			if (r != KErrNone)
+				break;
+
+			aPoints[i].iX = TInt(val << 8);
+
+			r = iInterface.Read(X1_L + (i << 2) , val);
+			if (r != KErrNone)
+				break;
+
+			aPoints[i].iX |= TInt(val);
+
+			// get Y coordinate
+			r = iInterface.Read(Y1_H + (i << 2), val);
+			if (r != KErrNone)
+				break;
+
+			aPoints[i].iY = TInt(val << 8);
+
+			r = iInterface.Read(Y1_L + (i << 2) , val);
+			if (r != KErrNone)
+				break;
+
+			aPoints[i].iY |= TInt(val);
+			}
+		}
+
+	// update number of points
+	if (r != KErrNone)
+		{
+		aNumPoints = 0;
+		}
+	else
+		{
+		aNumPoints = num_points;
+		}
+	return r;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/byd_touch/common/controller.h	Thu Oct 07 00:37:22 2010 +0100
@@ -0,0 +1,227 @@
+// 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.h
+//
+
+#ifndef TOUCH_KEY_CONTROLLER_H_
+#define TOUCH_KEY_CONTROLLER_H_
+
+#include <drivers/iic.h>
+#include <e32def.h>
+
+
+// controller specific constants..
+const TUint KMaxNumPoints = 3;
+typedef void (*TVoidCallback) (TAny*);
+
+
+// spi specific constants..
+const TUint KSpiPacketLength = 4;
+const TUint KStartByte = 0x56 << 1;
+const TUint KWrite     = 0;
+const TUint KRead      = 1;
+const TUint KReadCommand  = KStartByte | KRead;
+const TUint KWriteCommand = KStartByte;
+const TUint KBufGranulatity = 8;
+
+// digitizer specific settings..
+const TUint KResetPin = 93; // This setting does not change (it goes through J4/J5 connectors)
+const TUint KDataReadyPin = 133; // DAV connected to the GPIO133 (Expansion header pin 15)
+
+const TUint KSpiModule = 2; // McSPI3
+const TUint KSpiSlaveAddr0 = 2; // for data18-data23 pin functions slave address 2=>CS0..
+const TUint KSpiSlaveAddr1 = 3; // ..slave address 3=>CS1 (pref!)
+const TUint KSpiSlaveAddr = KSpiSlaveAddr1;
+
+
+const TConfigSpiV01 KHeader =
+	{
+	ESpiWordWidth_8, //iWordWidth
+	375000,//,93750, //iClkSpeed
+	ESpiPolarityHighFallingEdge, //iClkMode
+	500, // iTimeoutPeriod
+	EBigEndian, // iEndianness
+	EMsbFirst, //iBitOrder
+	2, //iTransactionWaitCycles
+	ESpiCSPinActiveLow //iCsPinActiveMode
+	};
+
+// spi interface to the controller
+class TTouchControllerInterface
+	{
+public:
+	inline TTouchControllerInterface();
+	inline TInt Read(TUint8 aRegAddress, TUint8& aValue);
+	inline TInt Write(TUint8 aRegAddress, TUint8 aValue);
+	inline TInt Write(TUint8 aRegAddress, TUint8* aValues, TInt aNumOfItems);
+
+
+private:
+	// SPI duplex transaction with two transfers for each direction
+	TPckgBuf<TConfigSpiV01> iSpiTransactionHeader;
+	TBuf8<KSpiPacketLength> iSpiWriteBuffer;
+	TBuf8<KSpiPacketLength> iSpiReadBuffer;
+	TIicBusTransfer         iSpiTxTransfer;
+	TIicBusTransfer         iSpiRxTransfer;
+	TIicBusTransaction      iSpiTransaction;
+	TInt                    iSpiBusId;
+	};
+
+class TouchController
+	{
+public:
+	enum TTouchMode
+		{
+		ESingle = 0,
+		EMulti,
+		EGesture
+		};
+
+	enum TResolution
+		{
+		ERes10Bits = 0,
+		ERes12Bits
+		};
+
+	enum TGestureType
+		{
+		EClockwiseCircumvolve = 3,
+		EDragLeft             = 4,
+		EDragRight            = 5,
+		EDragUp               = 6,
+		EDragDown             = 7,
+		EZoomOut              = 8,
+		EZoomIn               = 9
+		};
+
+	TouchController();
+	TouchController(TVoidCallback aCallback);
+
+
+	TInt HardReset();
+	TInt SoftReset();
+	TInt SetTouchMode(TTouchMode aMode);
+	TInt SetResolution(TResolution aResolution);
+	TInt SetLongerSamplingRate(TUint aRate);
+	TInt SetIrqActiveTime(TUint aIrqActiveTime);
+	TInt SetPanelVoltageStabTime(TUint aVoltageStabilizationTime);
+	TInt SetNumberOfColumns(TUint aNumberOfColumns);
+	TInt SetNumberOfRows(TUint aNumberOfRows);
+	TInt EnableWindowMode(TPoint aXpoint, TPoint aYPoint);
+	TInt DisableWindowMode();
+	TInt GetMeasurements(TPoint* aPoints, TInt& aNumPoints);
+	TInt NumOfTouches();
+
+private:
+	TInt iCtrlRegsCache[4];
+	TTouchControllerInterface iInterface;
+	TVoidCallback iCallback;
+	};
+
+
+// BF6917 Register definitions
+const TUint8 KControl_0  = 0x0; // R/W
+const TUint8 KControl_0_SWRST        = 1 << 7;  // SW reset
+const TUint8 KControl_0_RM_12        = 1 << 6; // Resolution mode 12 bits if set, 10bits otherwise
+const TUint8 KControl_0_MODE_SINGLE  = 1 << 3; // single touch mode
+const TUint8 KControl_0_MODE_MULTI   = 5 << 3; // multi-touch mode
+const TUint8 KControl_0_MODE_GESTURE = 6 << 3; // gesture mode
+const TUint8 KControl_0_MODE_MASK    = 7 << 3; // gesture mode
+
+const TUint8 KControl_0_LST_MASK     = 0x7; // Longer sampling rate: from 5 to 120 ADC clocks sampling time
+const TUint8 KControl_0_LST_5        = 0 << 0; // 5   ADC clocks sampling time
+const TUint8 KControl_0_LST_10       = 1 << 0; // 10  ADC clocks sampling time
+const TUint8 KControl_0_LST_20       = 2 << 0; // 20  ADC clocks sampling time
+const TUint8 KControl_0_LST_40       = 3 << 0; // 40  ADC clocks sampling time
+const TUint8 KControl_0_LST_60       = 4 << 0; // 60  ADC clocks sampling time
+const TUint8 KControl_0_LST_80       = 5 << 0; // 80  ADC clocks sampling time
+const TUint8 KControl_0_LST_100      = 6 << 0; // 100 ADC clocks sampling time
+const TUint8 KControl_0_LST_120      = 7 << 0; // 120 ADC clocks sampling time
+
+
+// Pen Irq Active time (sensiveness)
+const TUint8 KControl_1  = 0x1; // R/W
+const TUint8 KControl_1_PAT_SHIFT = 5;
+const TUint8 KControl_1_PAT_MASK  = 7 << 5;
+const TUint8 KControl_1_PAT_100   = 0 << 5;
+const TUint8 KControl_1_PAT_87_5  = 1 << 5;
+const TUint8 KControl_1_PAT_75    = 2 << 5;
+const TUint8 KControl_1_PAT_62_5  = 3 << 5;
+const TUint8 KControl_1_PAT_50    = 4 << 5;
+const TUint8 KControl_1_PAT_37_5  = 5 << 5;
+const TUint8 KControl_1_PAT_25    = 6 << 5;
+const TUint8 KControl_1_PAT_12_5  = 7 << 5;
+
+//  Panel Voltage stabilization Time(sensiveness)
+const TUint8 KControl_1_PVT_SHIFT = 2;
+const TUint8 KControl_1_PVT_MASK = 7 << 2;
+const TUint8 KControl_1_PVT_200  = 0 << 2;
+const TUint8 KControl_1_PVT_175  = 1 << 2;
+const TUint8 KControl_1_PVT_150  = 2 << 2;
+const TUint8 KControl_1_PVT_125  = 3 << 2;
+const TUint8 KControl_1_PVT_100  = 4 << 2;
+const TUint8 KControl_1_PVT_75   = 5 << 2;
+const TUint8 KControl_1_PVT_50   = 6 << 2;
+const TUint8 KControl_1_PVT_25   = 7 << 2;
+const TUint8 KControl_1_WS       = 1 << 0; // Window mode enables
+
+
+const TUint8 KControl_2  = 0x2; // R/W
+const TUint8 KControl_2_C_SHIFT  = 3; // number of columns
+const TUint8 KControl_2_C_MASK = 0xf8;
+const TUint8 KControl_2_PR_SHIFT = 0; // pull-up resistance
+
+
+const TUint8 KControl_3  = 0x3; // R/W
+const TUint8 KControl_3_R_SHIFT  = 4; // number of rows
+const TUint8 KControl_3_R_MASK   = 0xF0; // number of rows
+
+const TUint8 KControl_2_R_TEST   = 1 << 3; // test mode select
+const TUint8 KControl_2_PS_SHIFT = 0; // processing scale (0-7)
+
+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
+
+
+//  data registers
+const TUint8 KTouchNumberAndType  = 0xd; //  R, Touch number and touch type
+const TUint8 KTouchNumberAndType_SINGLE = 0 << 3;
+const TUint8 KTouchNumberAndType_MULTI  = 1 << 3;
+const TUint8 KTouchNumberAndType_TouchNMask = 7; // touch number (0 - 3)
+
+
+const TUint8 X1_H   = 0xe; //  R, High byte of x1 measurement
+const TUint8 X1_L   = 0xf; //  R, Low  byte of x1 measurement
+const TUint8 Y1_H   = 0x10; // R, High byte of y1 measurement
+const TUint8 Y1_L   = 0x11; // R, Low  byte of y1 measurement
+const TUint8 X2_H   = 0x12; // R, High byte of x2 measurement
+const TUint8 X2_L   = 0x13; // R, Low  byte of x2 measurement
+const TUint8 Y2_H   = 0x14; // R, High byte of y2 measurement
+const TUint8 Y2_L   = 0x15; // R, Low  byte of y2 measurement
+const TUint8 X3_H   = 0x16; // R, High byte of x3 measurement
+const TUint8 X3_L   = 0x17; // R, Low  byte of x3 measurement
+const TUint8 Y3_H   = 0x18; // R, High byte of y3 measurement
+const TUint8 Y3_L   = 0x19; // R, Low  byte of y3 measurement
+const TUint8 Ges_H  = 0x1a; // R, High byte of gesture information
+const TUint8 Ges_L  = 0x1b; // R, Low  byte of gesture information
+const TUint8 TEST_H = 0x1c; // R, Low byte of the test result
+const TUint8 TEST_L = 0x1d; // R, Low byte of the test result
+
+
+#endif /* TOUCH_KEY_CONTROLLER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/byd_touch/xyin.mmp	Thu Oct 07 00:37:22 2010 +0100
@@ -0,0 +1,65 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// 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:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+// lukasz.forynski@gmail.com
+//
+// Description:
+// standard driver for a touch screen (digitizer).
+//
+
+
+#define __USING_ASSP_REGISTER_API__
+#define __USING_ASSP_INTERRUPT_API__
+
+#include            "beagle/variant.mmh"
+#include            "kernel/kern_ext.mmh"
+
+target              VariantTarget(byd_xyin,dll)
+targettype          kext
+linkas              byd_xyin.dll
+
+
+USERINCLUDE         inc
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+SYMBIAN_BASE_SYSTEMINCLUDE(assp)
+SYMBIAN_BASE_SYSTEMINCLUDE(drivers)
+SYMBIAN_BASE_SYSTEMINCLUDE(assp/omap3530_assp)
+SYMBIAN_BASE_SYSTEMINCLUDE(assp/omap3530_shared)
+SYMBIAN_BASE_SYSTEMINCLUDE(beagle)
+
+sourcepath         ../../../../../os/kernelhwsrv/kernel/eka/drivers/xyin
+source             d_xyin.cpp
+
+sourcepath         common
+source             controller.cpp
+
+sourcepath         xyin
+source             xyin.cpp
+
+
+library            VariantTarget(ecust,lib) 
+library            AsspTarget(gpio,lib)
+library            AsspTarget(prcm,lib)
+library            iic.lib
+
+// once the PRM is ready..
+//#ifdef USE_SYMBIAN_PRM
+//library          VariantTarget(power,lib)
+//#endif
+
+VENDORID           0x70000001
+
+capability         all
+
+noexportlibrary
+
+EPOCALLOWDLLDATA
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/byd_touch/xyin/mconf.h	Thu Oct 07 00:37:22 2010 +0100
@@ -0,0 +1,56 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// 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:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// template\template_variant\inc\mconf.h
+// Template Persistent Machine Configuration
+// 
+// WARNING: This file contains some APIs which are internal and are subject
+//          to change without notice. Such APIs should therefore not be used
+//          outside the Kernel and Hardware Services package.
+//
+
+#ifndef __MCONF_H__
+#define __MCONF_H__
+#include <kernel/kernel.h>
+
+class TDigitizerCalibrateValues
+    {
+public:
+    TInt iR11;
+    TInt iR12;
+    TInt iR21;
+    TInt iR22;
+    TInt iTx;
+    TInt iTy;
+    };
+
+class TTemplateMachineConfig : public TMachineConfig
+	{
+public:
+	TSoundInfoV1 iSoundInfo;
+    TOnOffInfoV1 iOnOffInfo;
+	TTimeK iMainBatteryInsertionTime;
+    Int64 iMainBatteryInUseMicroSeconds;
+	Int64 iExternalPowerInUseMicroSeconds;
+	Int64 iMainBatteryMilliAmpTicks;
+	TDigitizerCalibrateValues iCalibration;
+	TDigitizerCalibrateValues iCalibrationSaved;
+	TDigitizerCalibrateValues iCalibrationFactory;
+	};
+
+typedef TTemplateMachineConfig TActualMachineConfig;
+
+inline TActualMachineConfig& TheActualMachineConfig()
+	{return (TActualMachineConfig&)Kern::MachineConfig();}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/byd_touch/xyin/xyin.cpp	Thu Oct 07 00:37:22 2010 +0100
@@ -0,0 +1,1092 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// 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:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of a digitiser (touch-screen) driver.
+// This code assumes that an interrupt is generated on pen-down and pen-up events.
+//
+//
+
+#include <assp.h>
+#include <videodriver.h>
+#include <drivers/xyin.h>
+#include <assp/omap3530_assp/omap3530_gpio.h>
+#include <assp/omap3530_assp/omap3530_scm.h>
+#include "mconf.h"
+#include "../common/controller.h"
+
+
+// TODO replace DEBUG_PRINT(  with  __KTRACE_OPT(KHARDWARE,
+#define DEBUG_PRINT(x) x
+
+const TInt KXyinThreadPriority = 33; // might need to be updated..
+_LIT(KXyinThreadName, "DigitizerThread");
+//
+// TO DO: (mandatory)
+//
+// Define the following constants that describe the digitiser position & dimensions
+// This is only example code... you need to modify it for your hardware
+
+// digitiser origin & size in pixels
+const TUint	KConfigXyOffsetX	= 0;		// digitiser origin - same as display area
+const TUint	KConfigXyOffsetY	= 0;
+const TUint	KConfigXyWidth		= 640;		// 640 pixels per line
+const TUint	KConfigXyHeight		= 480;		// 480 lines per panel
+
+// digitiser dimensions in digitiser co-ordinates
+const TInt KConfigXyBitsX   = 12;
+const TInt KConfigXyBitsY   = 12;
+const TInt KConfigXySpreadX = 1 << KConfigXyBitsX;  // maximum valid X spread
+const TInt KConfigXySpreadY = 1 << KConfigXyBitsY;  // maximum valid Y spread
+const TInt KConfigXyMinX    = 0;                    // minimum valid X value
+const TInt KConfigXyMinY    = 0;                    // minimum valid Y value
+const TInt KConfigXyMaxX    = KConfigXySpreadX - 1; // maximum valid X value
+const TInt KConfigXyMaxY    = KConfigXySpreadY - 1; // maximum valid Y value
+
+
+// Define a 2x2 matrix and two constants Tx and Ty to convert digitiser co-ordinates
+// to pixels such that
+//
+// (X<<16 Y<<16)	=	(x y)	x	(R11 R12)	+	(Tx Ty)
+//									(R21 R22)
+// or :
+//
+// X = (x*R11 + y*R21 + TX) >> 16;
+// Y = (x*R12 + y*R22 + TY) >> 16;
+
+//
+// where x,y are digitiser coordinates, Tx,Ty are constant offsets and X,Y are screen
+// coordinates. Left shifting by 16 bits is used so as not to lose precision.
+//
+// These are default values to be used before calibration has taken place
+// These are best set by observation.
+// The example values given below are for a digitiser whose origin is at bottom left
+// (the screen origin is at top left)
+const TInt		KConfigXyR11		= (KConfigXyWidth << 16) / KConfigXySpreadX;		// 10240
+const TInt		KConfigXyR12		= 0;
+const TInt		KConfigXyR21		= 0;
+const TInt		KConfigXyR22		= - ((KConfigXyHeight << 16) / KConfigXySpreadY);	// -7680
+const TInt		KConfigXyTx			= 0;
+const TInt		KConfigXyTy			= (KConfigXyHeight << 16) / KConfigXySpreadY;
+
+//
+// TO DO: (optional)
+//
+// Define the following constants that describe the digitiser behaviour
+// This is only example code... you need to modify it for your hardware
+
+// After taking a sample, wait for the specified number of nano-kernel ticks (normally 1 ms)
+// before taking the next sample
+const TInt		KInterSampleTime	= 1;
+
+// After a group of samples has been processed by the DDigitiser::ProcessRawSample() DFC,
+// wait for the specified number of nano-kernel ticks before taking the next sample
+const TInt		KInterGroupTime		= 1;
+
+// After a pen-down interrupt,
+// wait for the specified number of nano-kernel ticks before taking the next sample
+const TInt		KPenDownDelayTime	= 2;
+
+// If powering up the device with the pen down,
+// wait for the specified number of nano-kernel ticks before taking the next sample
+const TInt		KPenUpPollTime		= 30;
+
+// After a pen-up interrupt,
+// wait for the specified number of nano-kernel ticks before calling PenUp()
+const TInt		KPenUpDebounceTime	= 10;
+
+// number of samples to discard on pen-down
+const TInt		KConfigXyPenDownDiscard	= 1;
+
+// number of samples to discard on pen-up
+const TInt		KConfigXyPenUpDiscard	= 1;
+
+// offset in pixels to cause movement in X direction
+const TInt		KConfigXyAccThresholdX	= 12;
+
+// offset in pixels to cause movement in Y direction
+const TInt		KConfigXyAccThresholdY	= 12;
+
+// number of samples to average - MUST be <= KMaxXYSamples
+const TInt		KConfigXyNumXYSamples	= 2;
+
+// disregard extremal values in each 4-sample group
+const TBool		KConfigXyDisregardMinMax= EFalse;
+
+
+// obsolete constants :
+const TInt		KConfigXyDriveXRise		= 0;
+const TInt		KConfigXyDriveYRise		= 0;
+const TInt		KConfigXyMaxJumpX		= 0;
+const TInt		KConfigXyMaxJumpY		= 0;
+
+
+
+/******************************************************
+ * Main Digitiser Class
+ ******************************************************/
+
+//
+// TO DO: (optional)
+//
+// Add any private functions and data you require
+//
+NONSHARABLE_CLASS(DTemplateDigitiser) : public DDigitiser
+
+	{
+public:
+	enum TState
+		{
+		E_HW_PowerUp,
+		E_HW_PenUpDebounce,
+		E_HW_CollectSample
+		};
+
+public:
+	// from DDigitiser - initialisation
+	DTemplateDigitiser();
+	virtual TInt DoCreate();
+	void SetDefaultConfig();
+
+	// from DDigitiser - signals to hardware-dependent code
+	virtual void WaitForPenDown();
+	virtual void WaitForPenUp();
+	virtual void WaitForPenUpDebounce();
+	virtual void DigitiserOn();
+	virtual void DigitiserOff();
+	virtual void FilterPenMove(const TPoint& aPoint);
+	virtual void ResetPenMoveFilter();
+
+	// from DDigitiser - machine-configuration related things
+	virtual TInt DigitiserToScreen(const TPoint& aDigitiserPoint, TPoint& aScreenPoint);
+	virtual void ScreenToDigitiser(TInt& aX, TInt& aY);
+	virtual TInt SetXYInputCalibration(const TDigitizerCalibration& aCalibration);
+	virtual TInt CalibrationPoints(TDigitizerCalibration& aCalibration);
+	virtual TInt SaveXYInputCalibration();
+	virtual TInt RestoreXYInputCalibration(TDigitizerCalibrationType aType);
+	virtual void DigitiserInfo(TDigitiserInfoV01& aInfo);
+
+	// from DPowerHandler
+	virtual void PowerDown(TPowerState);
+	virtual void PowerUp();
+
+public:
+	// implementation
+	void TakeSample();
+	void PenInterrupt();
+	void DigitiserPowerUp();
+	void DoPowerUp();
+
+private:
+	static void TimerCallback(TAny* aPtr);
+	static void TimerIntCallback(TAny* aPtr);
+	static void TakeReadingDfc(TAny* aPtr);
+	static void PowerUpDfc(TAny* aPtr);
+	static void PowerDownDfc(TAny* aPtr);
+	static void PenIsr(TAny* aPtr);
+
+	TouchController iController;
+	NTimer iTimer;
+	NTimer iTimerInt;
+	TDfc iTakeReadingDfc;
+	TDfc iPowerDownDfc;
+	TDfc iPowerUpDfc;
+	TInt iSamplesCount;
+	TState iState;
+	TUint8 iPoweringDown;
+
+	TSize iScreenSize;
+	TActualMachineConfig& iMachineConfig;
+	};
+
+/******************************************************
+ * Digitiser main code
+ ******************************************************/
+
+
+/**
+Creates a new instance of DDigitiser.
+Called by extension entry point (PIL) to create a DDigitiser-derived object.
+
+@return	a pointer to a DTemplateDigitiser object
+*/
+DDigitiser* DDigitiser::New()
+	{
+	return new DTemplateDigitiser;
+	}
+
+DTemplateDigitiser::DTemplateDigitiser() :
+		iTimer(TimerCallback,this),
+		iTimerInt(TimerIntCallback,this),
+		iTakeReadingDfc(TakeReadingDfc,this,5),
+		iPowerDownDfc(PowerDownDfc,this,5),
+		iPowerUpDfc(PowerUpDfc,this,5),
+		iMachineConfig(TheActualMachineConfig())
+	{
+	}
+
+
+TInt DTemplateDigitiser::DoCreate()
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("DTemplateDigitiser::DoCreate"));
+	DEBUG_PRINT(Kern::Printf("DTemplateDigitiser::DoCreate"));
+
+	if (Kern::ColdStart())
+		{
+		__KTRACE_OPT(KEXTENSION,Kern::Printf("Resetting digitiser calibration"));
+
+		// Emergency digitiser calibration values
+		iMachineConfig.iCalibration.iR11 = KConfigXyR11;
+		iMachineConfig.iCalibration.iR12 = KConfigXyR12;
+		iMachineConfig.iCalibration.iR21 = KConfigXyR21;
+		iMachineConfig.iCalibration.iR22 = KConfigXyR22;
+		iMachineConfig.iCalibration.iTx = KConfigXyTx;
+		iMachineConfig.iCalibration.iTy = KConfigXyTy;
+		}
+
+	// create a DFCQ for this driver
+	TInt r = Kern::DfcQCreate(iDfcQ, KXyinThreadPriority, &KXyinThreadName);
+	if(r != KErrNone)
+		{
+		__KTRACE_OPT(KIIC, Kern::Printf("Digitizer: DFC Queue creation failed, ch: %d, r = %d\n", r));
+		return r;
+		}
+	iTakeReadingDfc.SetDfcQ(iDfcQ);
+	iPowerDownDfc.SetDfcQ(iDfcQ);
+	iPowerUpDfc.SetDfcQ(iDfcQ);
+
+
+#ifdef USE_SYMBIAN_PRM
+	// register power handler
+	Add();
+#endif
+
+	// setup the DAV (data ready/available) pin by binding to the GPIO pin..
+	r = GPIO::BindInterrupt(KDataReadyPin, PenIsr, this);
+	if(r != KErrNone)
+		{
+		Kern::Printf("GPIO::BindInterrupt() failed for pin %d, r=%d", KDataReadyPin, r);
+		return r;
+		}
+
+	r = GPIO::SetPinDirection(KDataReadyPin, GPIO::EInput);
+	if(r == KErrNone)
+		{
+		r = GPIO::SetInterruptTrigger(KDataReadyPin, GPIO::EEdgeRising);
+		if(r == KErrNone)
+			{
+			GPIO::SetDebounceTime(KDataReadyPin, 500);
+			SCM::SetPadConfig(CONTROL_PADCONF_MMC2_DAT0, SCM::EMsw, SCM::EMode4 | SCM::EInputEnable); // 133 (mmc2dat1)
+			r = GPIO::SetPinMode(KDataReadyPin, GPIO::EEnabled);
+			}
+		}
+
+	if (r == KErrNone)
+		{
+		// set up the default configuration
+		SetDefaultConfig();
+
+		// some of the pre-configuration of the touch controller could be done here..
+		iController.HardReset();
+		iController.SetTouchMode(TouchController::ESingle);
+
+		TPoint winStart, winStop;
+		winStart.iX = 0;
+		winStart.iY = 0;
+		winStop.iX = 0xfff;
+		winStop.iY = 0xfff;
+		iController.EnableWindowMode(winStart, winStop);
+
+		iController.SetNumberOfRows(8);
+		iController.SetNumberOfColumns(8);
+
+		DigitiserPowerUp();
+		}
+	return r;
+	}
+
+/**
+Initialise the DDigitiser::iCfg structure
+*/
+void DTemplateDigitiser::SetDefaultConfig()
+	{
+	iCfg.iPenDownDiscard = KConfigXyPenDownDiscard;		// number of samples to discard on pen-down
+	iCfg.iPenUpDiscard = KConfigXyPenUpDiscard;			// number of samples to discard on pen-up
+	iCfg.iDriveXRise = KConfigXyDriveXRise;				// number of milliseconds to wait when driving horizontal edges
+	iCfg.iDriveYRise = KConfigXyDriveYRise;				// number of milliseconds to wait when driving vertical edges
+	iCfg.iMinX = KConfigXyMinX;							// minimum valid X value
+	iCfg.iMaxX = KConfigXyMaxX;							// maximum valid X value
+	iCfg.iSpreadX = KConfigXySpreadX;					// maximum valid X spread
+	iCfg.iMinY = KConfigXyMinY;							// minimum valid Y value
+	iCfg.iMaxY = KConfigXyMaxY;							// maximum valid Y value
+	iCfg.iSpreadY = KConfigXySpreadY;					// maximum valid Y spread
+	iCfg.iMaxJumpX = KConfigXyMaxJumpX;					// maximum X movement per sample (pixels)
+	iCfg.iMaxJumpY = KConfigXyMaxJumpY;					// maximum Y movement per sample (pixels)
+	iCfg.iAccThresholdX = KConfigXyAccThresholdX;		// offset in pixels to cause movement in X direction
+	iCfg.iAccThresholdY = KConfigXyAccThresholdY;		// offset in pixels to cause movement in Y direction
+	iCfg.iNumXYSamples = KConfigXyNumXYSamples;			// number of samples to average
+	iCfg.iDisregardMinMax = KConfigXyDisregardMinMax;	// disregard extremal values in each 4-sample group
+	}
+
+/**
+Takes a sample from the digitiser.
+Called in the context of a DFC thread.
+*/
+void DTemplateDigitiser::TakeSample()
+	{
+#ifdef USE_SYMBIAN_PRM
+	TTemplatePowerController::WakeupEvent();	// notify of pendown (wakeup event) and let the power controller sort
+							 					// out if it needs propagation
+#endif
+
+	// TO DO: (mandatory)
+	// Read from appropriate hardware register to determine whether digitiser panel is being touched
+	// Set penDown to ETrue if touched or EFalse if not touched.
+	//
+
+//	DEBUG_PRINT(Kern::Printf("TS: S%d PD%d Sp%d", (TInt)iState, penDown?1:0, iSamplesCount));
+	TInt penDown = iController.NumOfTouches();
+	Kern::Printf("Num touches: %d", penDown);
+	if (iState==E_HW_PowerUp)
+		{
+		// waiting for pen to go up after switch on due to pen down or through the HAL
+		// coverity[dead_error_condition]
+		// The next line should be reachable when this template file is edited for use
+		if (!penDown)							// pen has gone up -> transition to new state
+			{
+			iState=E_HW_CollectSample;
+			iSamplesCount=0;						// reset sample buffer
+
+			// TO DO: (mandatory)
+			// Write to the appropriate hardware register to clear the digitiser interrupt
+			//
+
+			// TO DO: (mandatory)
+			// Write to the appropriate hardware register(s) to allow the hardware
+			// to detect when the digitizer panel is touched
+			//
+
+//			Interrupt::Enable(KIntIdDigitiser);		// enable pen-down interrupt
+
+ 			// TO DO: (mandatory)
+			// Write to the appropriate hardware register to enable the digitiser interrupt
+			//
+
+			}
+		else									// pen is still down, wait a bit longer in this state
+			{
+			iTimer.OneShot(KPenUpPollTime);
+			}
+		return;
+		}
+
+	if (!penDown)
+		{
+		if (iState==E_HW_PenUpDebounce)
+			{
+			iState=E_HW_CollectSample;	// back to initial state, no samples collected
+			iSamplesCount=0;			// reset sample buffer
+			// Need to lock the kernel to simulate ISR context and thus defer preemption,
+			// since PenUp() expects an ISR context and calls TDfc::Add().
+			NKern::Lock();
+			PenUp();					// adds DFC
+			NKern::Unlock();
+			}
+		else							// iState=E_HW_CollectSample
+			{
+			iState=E_HW_PenUpDebounce;
+			iTimer.OneShot(KPenUpDebounceTime);		// wait a bit to make sure pen still up
+			}
+		return;
+		}
+	else if (iState==E_HW_PenUpDebounce)	// pen down
+		{
+		// false alarm - pen is down again
+		iState=E_HW_CollectSample;		// take a new set of samples
+		iSamplesCount=0;				// reset sample buffer
+		}
+	// default: pen down and iState=E_HW_CollectSample
+	// TO DO: (mandatory)
+	// Read from appropriate hardware register to get the current digitiser coordinates
+	// of the point that is being touched. Set aResults accordingly.
+	// This is only example code... you need to modify it for your hardware
+	//
+	TPoint aResults;
+
+	TPoint points[4];
+	TInt num_points = 0;
+	TInt r = iController.GetMeasurements(points, num_points);
+	Kern::Printf("Measurments: (r: %d)", r);
+	for(TInt i = 0; i < 4/* num_points*/; i++)
+		{
+		Kern::Printf("%d: iX: %d, iY: %d",i, points[i].iX, points[i].iY);
+		}
+
+	// X axis
+	iX[iSamplesCount] = aResults.iX;
+	// Y axis
+	iY[iSamplesCount] = aResults.iY;
+
+	DEBUG_PRINT(Kern::Printf("Raw: X=%d Y=%d",iX[iSamplesCount],iY[iSamplesCount]));
+
+	// Put the hardware back into pen-detect mode
+
+	// TO DO: (mandatory)
+	// Write to the appropriate hardware register(s) to allow the hardware
+	// to detect when the digitizer panel is touched
+	//
+
+	// count samples collected - if it's less than minimum,
+	// schedule the reading of another sample
+	if (++iSamplesCount < iCfg.iNumXYSamples)	// iX[] and iY[] are 4 levels deep in xyin.h...
+		{
+		if(KInterSampleTime > 0)				// need to check this config param as it might be zero!
+			iTimer.OneShot(KInterSampleTime);	// haven't got a complete group yet, so queue timer to sample again
+		else
+			iTakeReadingDfc.Enque();
+		return;
+		}
+
+	// Have a complete group of samples so pass up to processing layer (PIL)
+
+	// Need to lock the kernel to simulate ISR context and thus defer preemption,
+	// since RawSampleValid() expects an ISR context and calls TDfc::Add().
+	NKern::Lock();
+	RawSampleValid();		// adds DFC
+	NKern::Unlock();
+	}
+
+/**
+Request for an interrupt to be generated when the pen is next down
+Called by PIL at startup or when pen leaves digitiser after pen-up event issued
+*/
+void DTemplateDigitiser::WaitForPenDown()
+	{
+	// Called at startup or when pen leaves digitiser after pen-up event issued
+	DEBUG_PRINT(Kern::Printf("WD: PowerDownMask %x",iPoweringDown));
+	if (iPoweringDown)
+		{
+		// powering down
+
+		// TO DO: (mandatory)
+		// Write to the appropriate hardware register(s) to allow the hardware
+		// to detect when the digitizer panel is touched and wakes up the system if in standby
+		//
+
+		//
+		// TO DO: (optional)
+		//
+		// Relinquish request on power resources
+		// This will place the peripheral hardware in a low power "Sleep" mode which is Interrupt detection capable
+		// EXAMPLE ONLY
+#ifdef USE_SYMBIAN_PRM
+		TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
+		aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 50 /* a percentage */);
+		aManager -> SharedBResource1() -> Release();
+#endif
+
+		iPoweringDown = EFalse;
+		PowerDownDone();
+		}
+	else
+		{
+
+		// TO DO: (mandatory)
+		// Write to the appropriate hardware register to clear the digitiser interrupt
+		//
+
+		// TO DO: (mandatory)
+		// Write to the appropriate hardware register(s) to allow the hardware
+		// to detect when the digitizer panel is touched
+		//
+
+		if ((iTimer.iState == NTimer::EIdle) && (iTimerInt.iState == NTimer::EIdle))
+			{
+			GPIO::EnableInterrupt(KDataReadyPin); // enable pen-down interrupt
+			}
+		}
+	}
+
+/**
+Called by PIL after it has processed a group of raw samples while pen is down.
+Used to indicate that the iX, iY buffers may be re-used
+*/
+void DTemplateDigitiser::WaitForPenUp()
+	{
+	DEBUG_PRINT(Kern::Printf("WU"));
+	iState = E_HW_CollectSample;
+	iSamplesCount = 0;					// reset sample buffer
+	if(KInterGroupTime > 0)				// need to check this config param as it might be zero!
+		{
+		iTimer.OneShot(KInterGroupTime);
+		}
+	else
+		{
+		iTakeReadingDfc.Enque();
+		}
+	}
+
+/**
+Called by PIL if the group of samples collected is not good enough
+Used to indicate that the iX, iY buffers may be re-used
+*/
+void DTemplateDigitiser::WaitForPenUpDebounce()
+	{
+	DEBUG_PRINT(Kern::Printf("WUDB"));
+	iState = E_HW_CollectSample;
+	iSamplesCount = 0;			// reset sample buffer
+	if(KInterGroupTime > 0)					// need to check this config param as it might be zero!
+		iTimer.OneShot(KInterGroupTime);
+	else
+		iTakeReadingDfc.Enque();
+	}
+
+/**
+Pen up/down interrupt service routine (ISR)
+*/
+static TUint IsrCnt = 0;
+void DTemplateDigitiser::PenInterrupt()
+    {
+	DEBUG_PRINT(Kern::Printf("I: %d  ", IsrCnt++));
+
+//	Interrupt::Clear(KIntIdDigitiser);	// should already have been cleared
+//	GPIO::DisableInterrupt(KDataReadyPin);
+
+	// TO DO: (mandatory)
+	// Read from appropriate hardware register to determine whether digitiser panel is being touched
+	// Set penDown to ETrue if touched or EFalse if not touched.
+	// This is only example code... you need to modify it for your hardware
+//	GPIO::DisableInterrupt(KDataReadyPin);
+
+
+//	TBool penDown = iController.NumOfTouches();
+	TBool penDown = 1;
+
+	// coverity[dead_error_condition]
+	if(!penDown)					// pen up
+		{
+
+		// TO DO: (mandatory)
+		// Write to the appropriate hardware register to clear the digitiser interrupt
+		//
+
+		// TO DO: (mandatory)
+		// Write to the appropriate hardware register(s) to allow the hardware
+		// to detect when the digitizer panel is touched
+		//
+
+		return;						// ... and exit!
+		}
+
+//	Interrupt::Disable(KIntIdDigitiser);		// do NOT disable the capability to generate interrupts at the source
+
+    // Add the timing of pen interrupts as entropy data for the RNG
+//	Interrupt::AddTimingEntropy();
+
+	if(0)
+//	if (KPenDownDelayTime>0)					// need to check this config param as it might be zero!
+		{
+		iTimerInt.OneShot(KPenDownDelayTime);	// start a debounce timer which will queue a DFC to process the interrupt
+		}
+	else
+		{
+
+		// TO DO: (mandatory)
+		// Write to the appropriate hardware register to clear the digitiser interrupt
+		// This will re-trigger the interrupt mechanism to catch the next interrupt...
+		//
+
+		iTakeReadingDfc.Add();
+		}
+	}
+
+
+
+void DTemplateDigitiser::TimerCallback(TAny* aPtr)
+	{
+	DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
+	DEBUG_PRINT(Kern::Printf("T"));
+	pD->iTakeReadingDfc.Add();
+	}
+
+/**
+Debounce timer callback
+schedules a DFC to process a pen-down interrupt
+
+@param aPtr	a pointer to DTemplateDigitiser
+*/
+void DTemplateDigitiser::TimerIntCallback(TAny* aPtr)
+	{
+	DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
+	DEBUG_PRINT(Kern::Printf("TI"));
+//	GPIO::DisableInterrupt(KDataReadyPin);
+	// clear xy interrupt -> re-triggers the interrupt mechanism to catch the next IRQ
+
+	// TO DO: (mandatory)
+	// Write to the appropriate hardware register to clear the digitiser interrupt
+	//
+
+	pD->iTakeReadingDfc.Add();
+	}
+
+/**
+Pen-up/down interrupt handler
+
+@param aPtr	a pointer to DTemplateDigitiser
+*/
+void DTemplateDigitiser::PenIsr(TAny* aPtr)
+	{
+	DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
+	pD->PenInterrupt();
+	}
+
+/**
+DFC for taking a sample
+
+@param aPtr	a pointer to DTemplateDigitiser
+*/
+void DTemplateDigitiser::TakeReadingDfc(TAny* aPtr)
+	{
+	DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
+	pD->TakeSample();
+	}
+
+
+void DTemplateDigitiser::PowerUp()
+	{
+	iPowerUpDfc.Enque();			// queue a DFC in this driver's context
+	}
+
+void DTemplateDigitiser::PowerUpDfc(TAny* aPtr)
+	{
+	DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
+	pD->DoPowerUp();
+	}
+
+void DTemplateDigitiser::DoPowerUp()
+	{
+	__KTRACE_OPT(KPOWER, Kern::Printf("DTemplateDigitiser::PowerUpDfc()"));
+	DigitiserOn();
+	PowerUpDone();			// must be called from a different thread than PowerUp()
+	}
+
+/**
+Turn the digitiser on
+May be called as a result of a power transition or from the HAL
+If called from HAL, then the digitiser may be already be on (iPointerOn == ETrue)
+*/
+void DTemplateDigitiser::DigitiserOn()
+	{
+	__KTRACE_OPT(KPOWER,Kern::Printf("DTemplateDigitiser::DigitiserOn() iPointerOn=%d", iPointerOn));
+
+	if (!iPointerOn)				// may have been powered up already
+		DigitiserPowerUp();
+	}
+
+/**
+Power-up the digitiser. Assumes digitiser is off.
+*/
+void DTemplateDigitiser::DigitiserPowerUp()
+	{
+	__KTRACE_OPT(KPOWER, Kern::Printf("DigitiserPowerUp"));
+	iPointerOn = ETrue;		// now turned on
+
+	// TO DO: (mandatory)
+	// Write to the appropriate hardware register to clear the digitiser interrupt
+	//
+
+	//
+	// TO DO: (optional)
+	//
+	// Reassert request on power resources
+	// This will move the peripheral hardware out of low power "Sleep" mode back to fully operational
+	// EXAMPLE ONLY
+	//
+#ifdef USE_SYMBIAN_PRM
+	TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
+	aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 100 /* a percentage */);
+	aManager -> SharedBResource1() -> Use();
+#endif
+	// TO DO: (mandatory)
+	// Write to the appropriate hardware register(s) to allow the hardware
+	// to detect when the digitizer panel is touched
+	//
+
+	iState = E_HW_PowerUp;	// so we wait for pen up if necessary
+	iTakeReadingDfc.Enque();
+	}
+
+
+void DTemplateDigitiser::PowerDown(TPowerState /*aPowerState*/)
+	{
+	iPoweringDown = ETrue;
+	iPowerDownDfc.Enque();						// queue a DFC in this driver's context
+	}
+
+
+void DTemplateDigitiser::PowerDownDfc(TAny* aPtr)
+	{
+	DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
+	pD->DigitiserOff();
+	}
+
+
+
+/**
+Turn the digitiser off
+May be called as a result of a power transition or from the HAL
+If called from Power Manager, then the digitiser may be already be off (iPointerOn == EFalse)
+if the platform is in silent running mode
+*/
+void DTemplateDigitiser::DigitiserOff()
+	{
+	__KTRACE_OPT(KPOWER,Kern::Printf("DTemplateDigitiser::DigitiserOff() iPointerOn=%d", iPointerOn));
+	if (iPointerOn)		// can have been powered down from HAL
+		{
+		iPointerOn = EFalse;
+//		Interrupt::Disable(KIntIdDigitiser);
+
+		// TO DO: (mandatory)
+		// Write to the appropriate hardware register to disable the digitiser interrupt
+		//
+
+		iTimer.Cancel();
+		iTimerInt.Cancel();
+		iTakeReadingDfc.Cancel();
+		if (iState != E_HW_CollectSample)
+			{
+			// Need to lock the kernel to simulate ISR context and thus defer preemption,
+			// since PenUp() expects an ISR context and calls TDfc::Add().
+			NKern::Lock();
+			PenUp();		// adds DFC (will call WaitForPenDown)
+			NKern::Unlock();
+			}
+		else
+			{
+
+			// TO DO: (mandatory)
+			// Write to the appropriate hardware register(s) to allow the hardware
+			// to detect when the digitizer panel is touched and wakes up the system if in standby
+			//
+
+			//
+			// TO DO: (optional)
+			//
+			// Relinquish request on power resources as we are being powered down
+			// This will place the peripheral hardware in a low power "Sleep" mode which is Interrupt detection capable
+			// EXAMPLE ONLY
+			//
+#ifdef USE_SYMBIAN_PRM
+			TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
+			aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 0 /* a percentage */);
+			aManager -> SharedBResource1() -> Release();
+#endif
+			if (iPoweringDown)			// came here through PowerDown
+				{
+				iPoweringDown = EFalse;
+				PowerDownDone();
+				}
+			}
+		}
+	else	// already powered down (by HAL)
+		{
+			if (iPoweringDown)			// came here through PowerDown
+				{
+				iPoweringDown = EFalse;
+				PowerDownDone();
+				}
+		}
+	}
+
+
+
+
+/**
+Convert digitiser coordinates to screen coordinates
+
+@param aDigitiserPoint the digitiser coordinates
+@param aScreenPoint A TPoint supplied by the caller.
+					On return, set to the converted screen coordinates in pixels.
+
+@return KErrNone if successful
+*/
+TInt DTemplateDigitiser::DigitiserToScreen(const TPoint& aDigitiserPoint, TPoint& aScreenPoint)
+	{
+	NKern::LockSystem();
+	TInt R11 = iMachineConfig.iCalibration.iR11;
+	TInt R12 = iMachineConfig.iCalibration.iR12;
+	TInt R21 = iMachineConfig.iCalibration.iR21;
+	TInt R22 = iMachineConfig.iCalibration.iR22;
+	TInt TX = iMachineConfig.iCalibration.iTx;
+	TInt TY = iMachineConfig.iCalibration.iTy;
+	NKern::UnlockSystem();
+	TInt X = aDigitiserPoint.iX;
+	TInt Y = aDigitiserPoint.iY;
+
+	aScreenPoint.iX = (X*R11 + Y*R21 + TX) >> 16;
+	aScreenPoint.iY = (X*R12 + Y*R22 + TY) >> 16;
+
+	DEBUG_PRINT(Kern::Printf("DtS: Dp.x %d, Dp.y %d, Sp.x %d, Sp.y %d", X,Y,aScreenPoint.iX,aScreenPoint.iY));
+
+	return KErrNone;
+	}
+
+/**
+Convert screen coordinates back into digitiser coordinates
+using the current constants from the superpage
+
+@param aX The screen X coordinate in pixels; On return, set to the digitiser X coordinate.
+@param aY The screen Y coordinate in pixels; On return, set to the digitiser Y coordinate.
+*/
+void DTemplateDigitiser::ScreenToDigitiser(TInt& aX, TInt& aY)
+	{
+	NKern::LockSystem();
+	Int64 R11 = iMachineConfig.iCalibration.iR11;
+	Int64 R12 = iMachineConfig.iCalibration.iR12;
+	Int64 R21 = iMachineConfig.iCalibration.iR21;
+	Int64 R22 = iMachineConfig.iCalibration.iR22;
+	Int64 TX = iMachineConfig.iCalibration.iTx;
+	Int64 TY = iMachineConfig.iCalibration.iTy;
+	NKern::UnlockSystem();
+	Int64 X = aX;
+	Int64 Y = aY;
+	//
+	// Xd=(Xs<<16)*R22-(Ys<<16)*R21-(TX*R22)+(TY*R21)
+	//	  -------------------------------------------
+	//				   (R22*R11)-(R21*R12)
+	//
+	//
+	// Yd=(Xs<<16)*R12-(Ys<<16)*R11-(TX*R12)+(TY*R11)
+	//	  -------------------------------------------
+	//				   (R21*R12)-(R22*R11)
+	//
+	// where Xd and Yd are digitiser coordinates
+	//		 Xs and Ys are supplied screen coordinates
+	//
+	X<<=16;
+	Y<<=16;
+
+	Int64 d=Int64(R21)*Int64(R12)-Int64(R22)*Int64(R11);
+
+	Int64 r=(X*R12)-(Y*R11)-(TX*R12)+(TY*R11);
+
+	r=r/d;
+
+	aY=(TInt)r;
+
+	r=(X*R22)-(Y*R21)-(TX*R22)+(TY*R21);
+
+	r=r/(-d);
+
+	aX=(TInt)r;
+	}
+
+/**
+Calculate values for R11, R12, R21, R22, TX and TY
+
+@param aCalibration the screen coordinates of points touched
+@return KErrNone if successful
+*/
+TInt DTemplateDigitiser::SetXYInputCalibration(const TDigitizerCalibration& aCalibration)
+	{
+	TInt R11,R12,R21,R22,TX,TY;
+	//
+	// Get coords of expected points
+	//
+	TDigitizerCalibration cal;
+	TInt ret=CalibrationPoints(cal);
+	if (ret!=KErrNone)
+		return ret;
+
+	TInt Xp1=cal.iTl.iX;
+	TInt Yp1=cal.iTl.iY;
+	TInt Xp2=cal.iBl.iX;
+	TInt Yp2=cal.iBl.iY;
+	TInt Xp3=cal.iBr.iX;
+	TInt Yp3=cal.iBr.iY;
+	//
+	// Get coords of points touched in screen coordinates
+	//
+	TInt X1=aCalibration.iTl.iX;
+	TInt Y1=aCalibration.iTl.iY;
+	TInt X2=aCalibration.iBl.iX;
+	TInt Y2=aCalibration.iBl.iY;
+	TInt X3=aCalibration.iBr.iX;
+	TInt Y3=aCalibration.iBr.iY;
+	//
+	// Convert back to raw digitiser coordinates
+	//
+	ScreenToDigitiser(X1,Y1);
+	ScreenToDigitiser(X2,Y2);
+	ScreenToDigitiser(X3,Y3);
+	//
+	// (Y1-Y2)(Xp1-Xp3) - (Y1-Y3)(Xp1-Xp2)
+	// ----------------------------------- = R11
+	// (Y1-Y2)(X1-X3)	- (Y1-Y3)(X1-X2)
+	//
+	Int64 r=((Int64(Y1-Y2)*Int64(Xp1-Xp3))-(Int64(Y1-Y3)*Int64(Xp1-Xp2)));
+	r<<=16;
+	r/=(Int64(Y1-Y2)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X1-X2));
+	R11=(TInt)r;
+	//
+	// (Y1-Y2)(Yp1-Yp3) - (Y1-Y3)(Yp1-Yp2)
+	// ----------------------------------- = R12
+	// (Y1-Y2)(X1-X3)	- (Y1-Y3)(X1-X2)
+	//
+	r=((Int64(Y1-Y2)*Int64(Yp1-Yp3))-(Int64(Y1-Y3)*Int64(Yp1-Yp2)));
+	r<<=16;
+	r/=(Int64(Y1-Y2)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X1-X2));
+	R12=(TInt)r;
+	//
+	// (X1-X3)(Xp2-Xp3) - (X2-X3)(Xp1-Xp3)
+	// ----------------------------------- = R21
+	// (Y2-Y3)(X1-X3)	- (Y1-Y3)(X2-X3)
+	//
+	r=(((X1-X3)*(Xp2-Xp3))-((X2-X3)*(Xp1-Xp3)));
+	r<<=16;
+	r/=(Int64(Y2-Y3)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X2-X3));
+	R21=(TInt)r;
+	//
+	// (X1-X3)(Yp2-Yp3) - (X2-X3)(Yp1-Yp3)
+	// ----------------------------------- = R22
+	// (Y2-Y3)(X1-X3)	- (Y1-Y3)(X2-X3)
+	//
+	r=((Int64(X1-X3)*Int64(Yp2-Yp3))-(Int64(X2-X3)*Int64(Yp1-Yp3)));
+	r<<=16;
+	r/=(Int64(Y2-Y3)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X2-X3));
+	R22=(TInt)r;
+	//
+	// TX = Xp1 - X1*R11 - Y1*R21
+	//
+   TX=(Xp1<<16)-(X1*R11)-(Y1*R21);
+	//
+	// TY = Yp1 - X1*R12 - Y1*R22
+	//
+	TY=(Yp1<<16)-(X1*R12)-(Y1*R22);
+
+	//
+	// Write new values into the superpage
+	//
+	NKern::LockSystem();
+	iMachineConfig.iCalibration.iR11 = R11;
+	iMachineConfig.iCalibration.iR12 = R12;
+	iMachineConfig.iCalibration.iR21 = R21;
+	iMachineConfig.iCalibration.iR22 = R22;
+	iMachineConfig.iCalibration.iTx = TX;
+	iMachineConfig.iCalibration.iTy = TY;
+	NKern::UnlockSystem();
+
+	return(KErrNone);
+	}
+
+/**
+Informs the user-side calibration application where to draw
+the cross-hairs on the screen
+
+@param aCalibration On return contains the for points on the screen (in screen coordinates)
+					where the cross-hairs should be drawn
+@return KErrNone if succcessful
+*/
+TInt DTemplateDigitiser::CalibrationPoints(TDigitizerCalibration& aCalibration)
+	{
+	TVideoInfoV01Buf buf;
+	TVideoInfoV01& vidinfo=buf();
+	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalCurrentModeInfo, (TAny*)&buf, NULL);
+	if (r!=KErrNone)
+		return r;
+	iScreenSize=vidinfo.iSizeInPixels;
+
+    aCalibration.iBl.iX = aCalibration.iTl.iX = iScreenSize.iWidth/10;
+    aCalibration.iTr.iY = aCalibration.iTl.iY = iScreenSize.iHeight/10;
+    aCalibration.iBr.iY = aCalibration.iBl.iY = iScreenSize.iHeight-iScreenSize.iHeight/10;
+    aCalibration.iTr.iX = aCalibration.iBr.iX = iScreenSize.iWidth-iScreenSize.iWidth/10;
+    return r;
+	}
+/**
+Saves the digitiser calibration to the persistent machine configuration area
+so that it can be restored after a power-down/up
+
+@return KErrNone if succcessful
+*/
+TInt DTemplateDigitiser::SaveXYInputCalibration()
+	{
+	NKern::LockSystem();
+	iMachineConfig.iCalibrationSaved = iMachineConfig.iCalibration;
+	NKern::UnlockSystem();
+	return(KErrNone);
+	}
+
+/**
+Restores the digitiser calibration from the persistent machine configuration area
+following a power-up
+
+@param aType indicates whether to restore factory or saved settings
+@return KErrNone if succcessful
+*/
+TInt DTemplateDigitiser::RestoreXYInputCalibration(TDigitizerCalibrationType aType)
+	{
+	TInt r=KErrNone;
+	NKern::LockSystem();
+	switch (aType)
+		{
+		case EFactory:
+			iMachineConfig.iCalibration=iMachineConfig.iCalibrationFactory;
+			break;
+		case ESaved:
+			iMachineConfig.iCalibration=iMachineConfig.iCalibrationSaved;
+			break;
+		default:
+			r=KErrNotSupported;
+			break;
+		}
+	NKern::UnlockSystem();
+	return r;
+	}
+
+/**
+Gets the digitiser configuration information
+
+@param aInfo On return, contains information about the digitiser's dimensions etc.
+*/
+void DTemplateDigitiser::DigitiserInfo(TDigitiserInfoV01& aInfo)
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("DTemplateDigitiser::DigitiserInfo"));
+	aInfo.iDigitiserSize.iWidth=KConfigXyWidth;
+	aInfo.iDigitiserSize.iHeight=KConfigXyHeight;
+	aInfo.iOffsetToDisplay.iX=KConfigXyOffsetX;
+	aInfo.iOffsetToDisplay.iY=KConfigXyOffsetY;
+	}
+
+/**
+Issues a pen move event if the distance from the last point is greater than the threshold
+
+@param aPoint the pen position in screen coordinates
+*/
+void DTemplateDigitiser::FilterPenMove(const TPoint& aPoint)
+	{
+	TPoint offset=aPoint;
+	offset.iX-=iLastPos.iX;
+	offset.iY-=iLastPos.iY;
+	if (Abs(offset.iX)>=iCfg.iAccThresholdX || Abs(offset.iY)>=iCfg.iAccThresholdY)
+		{
+		iLastPos=aPoint;
+		IssuePenMoveEvent(aPoint);
+		}
+	}
+
+/**
+Reset the pen move filter
+*/
+void DTemplateDigitiser::ResetPenMoveFilter()
+	{
+	}
+
--- a/omap3530/beagleboard/rom/kernel.iby	Tue Sep 28 02:37:35 2010 +0100
+++ b/omap3530/beagleboard/rom/kernel.iby	Thu Oct 07 00:37:22 2010 +0100
@@ -19,67 +19,69 @@
 
 
 
-primary[VARID]=		\Epoc32\Release\ARMV5\##BUILD##\_omap3530_EKERN.EXE              \sys\bin\ekern.exe
-extension[VARID]=	\Epoc32\Release\ARMV5\##BUILD##\_omap3530_KAOMAP3530.DLL         \sys\bin\kaomap3530.dll
+primary[VARID]=  \Epoc32\Release\ARMV5\##BUILD##\_omap3530_EKERN.EXE        \sys\bin\ekern.exe
+extension[VARID]= \Epoc32\Release\ARMV5\##BUILD##\_omap3530_KAOMAP3530.DLL  \sys\bin\kaomap3530.dll
 #include <rom\omapshared\mstick.iby>
 
 // Removed BTRACEX
-//extension[VARID]=	\Epoc32\Release\ARMV5\##BUILD##\_omap3530_BTRACEX.LDD            \sys\bin\btracex.ldd
+//extension[VARID]= \Epoc32\Release\ARMV5\##BUILD##\_omap3530_BTRACEX.LDD   \sys\bin\btracex.ldd
 
-extension[VARID]=   \Epoc32\Release\ARMV5\##BUILD##\_omap3530_prcm.dll               \sys\bin\prcm.dll
-extension[VARID]=   \Epoc32\Release\ARMV5\##BUILD##\_omap3530_uart.dll               \sys\bin\uart.dll
-variant[VARID]=		\Epoc32\Release\ARMV5\##BUILD##\_##VARIANT##_ECUST.DLL              \sys\bin\ecust.dll
-extension[VARID]=	\Epoc32\Release\ARMV5\##BUILD##\_omap3530_EXMONCOMMON.DLL        \sys\bin\exmoncommon.dll
-extension[VARID]=	\Epoc32\Release\ARMV5\##BUILD##\_omap3530_EXMONDEBUG.DLL         \sys\bin\exmondebug.dll
-extension[VARID]=	\Epoc32\Release\ARMV5\##BUILD##\_omap3530_GPIO.DLL            	\sys\bin\gpio.dll
-extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_LED.DLL		\sys\bin\led.dll
-extension[VARID]=	\Epoc32\Release\ARMV5\##BUILD##\_omap3530_I2C.DLL                \sys\bin\I2C.DLL
+extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_prcm.dll         \sys\bin\prcm.dll
+extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_uart.dll         \sys\bin\uart.dll
+variant[VARID]=  \Epoc32\Release\ARMV5\##BUILD##\_##VARIANT##_ECUST.DLL     \sys\bin\ecust.dll
+extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_EXMONCOMMON.DLL  \sys\bin\exmoncommon.dll
+extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_EXMONDEBUG.DLL   \sys\bin\exmondebug.dll
+extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_GPIO.DLL         \sys\bin\gpio.dll
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_LED.DLL       \sys\bin\led.dll
+extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_I2C.DLL          \sys\bin\i2c.DLL
 
 // Uncommnet to include West Bridge Astoria Symbian Storage driver 
-//extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_WB.DLL		\sys\bin\wb.dll
-//extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\wb.dll		\sys\bin\wb.dll
+//extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_WB.DLL      \sys\bin\wb.dll
+//extension[VARID]=\epoc32\release\ARMV5\##BUILD##\wb.dll                   \sys\bin\wb.dll
 
-//extension[VARID]=	\Epoc32\Release\ARMV5\##BUILD##\_##VARIANT##_resman.pdd		\sys\bin\resman.pdd
-//extension[VARID]=	\Epoc32\Release\##KMAIN##\##BUILD##\resman.ldd				\sys\bin\resman.ldd
+//extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_##VARIANT##_resman.pdd  \sys\bin\resman.pdd
+//extension[VARID]=\Epoc32\Release\##KMAIN##\##BUILD##\resman.ldd           \sys\bin\resman.ldd
 
 #include <rom/omapshared/tps65950.iby>
 #include <rom/omap3530/spi.iby>
 
-device[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_EUART.PDD				\sys\bin\euart.pdd
-device[VARID]=\Epoc32\Release\ARMV5\##BUILD##\ECOMM.LDD						\sys\bin\ecomm.ldd
+extension[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_##VARIANT##_byd_xyin.dll  \sys\bin\byd_xyin.dll
+
+device[VARID]=\Epoc32\Release\ARMV5\##BUILD##\_omap3530_EUART.PDD           \sys\bin\euart.pdd
+device[VARID]=\Epoc32\Release\ARMV5\##BUILD##\ECOMM.LDD                     \sys\bin\ecomm.ldd
 
 #ifdef TSHELL_SERIAL
 //Use VT100 Over Serial
-#define EDISP_DRV	\EDISP_VT100.DLL
+#define EDISP_DRV \EDISP_VT100.DLL
 #else
-	extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_lcd.dll				\sys\bin\lcd.dll
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_lcd.dll         \sys\bin\lcd.dll
 #ifdef SERIALMOUSE
 #ifdef BASE_ROM
-	extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_serialmouse_tshell.DLL	\sys\bin\eserialmouse.dll
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_serialmouse_tshell.DLL \sys\bin\eserialmouse.dll
 #else
-	extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_serialmouse.DLL		\sys\bin\eserialmouse.dll
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_serialmouse.DLL  \sys\bin\eserialmouse.dll
 #endif
 #else
-	extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_omap3530_serialkeyboard.DLL	\sys\bin\ekeyb.dll
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_omap3530_serialkeyboard.DLL  \sys\bin\ekeyb.dll
 #endif
 #endif
 
-file[VARID]=		\epoc32\release\##KMAIN##\##BUILD##\_##VARIANT##_EKDATA.DLL				\sys\bin\ekdata.dll
-extension[VARID]=	\epoc32\release\##KMAIN##\##BUILD##\ELOCD.LDD							\sys\bin\elocd.ldd
-extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_MEDINT.PDD				\sys\bin\medint.pdd
+file[VARID]=\epoc32\release\##KMAIN##\##BUILD##\_##VARIANT##_EKDATA.DLL   \sys\bin\ekdata.dll
+extension[VARID]=\epoc32\release\##KMAIN##\##BUILD##\ELOCD.LDD            \sys\bin\elocd.ldd
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_MEDINT.PDD  \sys\bin\medint.pdd
 
 // Uncommnet to include West Bridge Astoria Symbian Storage driver 
-//extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_MEDWB.PDD				\sys\bin\medwb.pdd
-device[VARID]=		\epoc32\release\##KMAIN##\##BUILD##\PIPELIB.LDD							\sys\bin\pipelib.ldd
-extension[VARID]=	\epoc32\release\##KMAIN##\##BUILD##\EXSTART.DLL							\sys\bin\exstart.dll
+//extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_MEDWB.PDD \sys\bin\medwb.pdd
+device[VARID]=\epoc32\release\##KMAIN##\##BUILD##\PIPELIB.LDD             \sys\bin\pipelib.ldd
+extension[VARID]=\epoc32\release\##KMAIN##\##BUILD##\EXSTART.DLL          \sys\bin\exstart.dll
 
 #ifdef INCLUDE_USB
-extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_omap3530_USBCC.DLL					\sys\bin\USBCC.DLL
-device[VARID]=	\epoc32\release\##KMAIN##\##BUILD##\USBC.LDD							\sys\bin\EUSBC.LDD
-extension[VARID]=	\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_USBV.DLL				\sys\bin\usbv.DLL
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_omap3530_USBCC.DLL      \sys\bin\usbcc.DLL
+device[VARID]=\epoc32\release\##KMAIN##\##BUILD##\USBC.LDD                \sys\bin\eusbc.LDD
+extension[VARID]=\epoc32\release\ARMV5\##BUILD##\_##VARIANT##_USBV.DLL    \sys\bin\usbv.DLL
 #endif
 
-#define	EUSER_DLL	../../ARMV5/##BUILD##/_omap3530_euser.dll
+#define EUSER_DLL ../../ARMV5/##BUILD##/_omap3530_euser.dll
 
 #ifdef TEST_ROM
 #include <rom\##VARIANT##\test.iby>
--- a/omap3530/omap3530_drivers/spi/master.cpp	Tue Sep 28 02:37:35 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/master.cpp	Thu Oct 07 00:37:22 2010 +0100
@@ -185,9 +185,15 @@
 		slaveAddr &= 1; // modulo 2 (i.e. 2 CS for McSPI3)
 		}
 
+	// reconfigure pins if needed..
+	if(slavePinSet != iCurrSlavePinSet)
+		{
+		iCurrSlavePinSet = slavePinSet;
+		SetupSpiPins(iChannelNumber, iCurrSlavePinSet);
+		}
+
 	// store configuration parameters
 	iCurrSS          = slaveAddr;
-	iCurrSlavePinSet = slavePinSet;
 	iCurrHeader      = newHeader; //copy the header..
 
 	return KErrNone;
@@ -199,12 +205,6 @@
 	{
 	DBGPRINT(Kern::Printf("ConfigureInterface()"));
 
-	// make sure pins are set up properly (only for McSPI3)
-	if(iCurrSlavePinSet == 2)
-		{
-		SetupSpiPins(iChannelNumber, iCurrSlavePinSet);
-		}
-
 	// soft reset the SPI..
 	TUint val = AsspRegister::Read32(iHwBase + MCSPI_SYSCONFIG);
 	val = MCSPI_SYSCONFIG_SOFTRESET;  // issue reset
@@ -272,6 +272,8 @@
 //	val |= MCSPI_CHxCONF_FFER; // fifo enable for receive.. (TODO)
 #endif
 
+	val |= (iCurrHeader.iTransactionWaitCycles & 3) << MCSPI_CHxCONF_TCS_SHIFT;
+
 	// update the register..
 	AsspRegister::Write32(iHwBase + MCSPI_CHxCONF(iCurrSS), val);
 
@@ -291,6 +293,8 @@
 	// Set the MS bit to 0 to provide the clock (ie. to setup as master)
 #ifndef SINGLE_MODE
 	AsspRegister::Write32(iHwBase + MCSPI_MODULCTRL, MCSPI_MODULCTRL_MS_MASTER);
+	// change the pad config - now the SPI drives the line appropriately..
+	SetCsActive(iChannelNumber, iCurrSS, iCurrSlavePinSet);
 #else
 	AsspRegister::Write32(iHwBase + MCSPI_MODULCTRL, MCSPI_MODULCTRL_MS_MASTER | MCSPI_MODULCTRL_SINGLE);
 #endif
@@ -801,16 +805,17 @@
 	{
 	DBGPRINT(Kern::Printf("DSpiMasterBeagle::ExitComplete, aErr %d, aComplete %d", aErr, aComplete));
 
-	// make sure CS is in inactive state (for the current / last transaction) on error
-	// TODO: add extendable transaction support (..i.e. with no de-assertion of CS pin between such transactions)
-	SetCsInactive(iChannelNumber, iCurrSS, iCurrHeader.iSSPinActiveMode, iCurrSlavePinSet);
-
-	// disable this channel
-	AsspRegister::Modify32(iHwBase + MCSPI_CHxCTRL(iCurrSS), MCSPI_CHxCTRL_EN, 0);
 
 	// in the case of error - make sure to reset the channel
 	if(aErr != KErrNone)
 		{
+		// make sure CS is in inactive state (for the current / last transaction) on error
+		// TODO: add extendable transaction support (..i.e. with no de-assertion of CS pin between such transactions)
+		SetCsInactive(iChannelNumber, iCurrSS, iCurrHeader.iSSPinActiveMode, iCurrSlavePinSet);
+
+		// disable this channel
+		AsspRegister::Modify32(iHwBase + MCSPI_CHxCTRL(iCurrSS), MCSPI_CHxCTRL_EN, 0);
+
 		AsspRegister::Write32(iHwBase + MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
 		iCurrSS = -1; // make sure the interface will be re-configured at next transaction
 		}
@@ -863,7 +868,8 @@
 		// check if word width and clock are supported
 		if(SpiWordWidth(header.iWordWidth) < KMinSpiWordWidth ||
 		   SpiClkValue(header.iClkSpeedHz) < 0 || // == KErrNotSupported
-		   header.iBitOrder == ELsbFirst) // this SPI only transmits MSB fist
+		   header.iBitOrder == ELsbFirst ||  // this SPI only transmits MSB fist
+		   (TUint)header.iTransactionWaitCycles > KMaxTransactionWaitTime) // max 3(+.5) cycles between words
 			{
 #ifdef _DEBUG
 			if(header.iBitOrder == ELsbFirst)
@@ -872,7 +878,11 @@
 				DBG_ERR(Kern::Printf("iClkSpeedHz: %d is not supported", header.iClkSpeedHz));
 			if((SpiWordWidth(header.iWordWidth)+ 1) >> MCSPI_CHxCONF_WL_OFFSET < KMinSpiWordWidth)
 				DBG_ERR(Kern::Printf("iWordWidth: %d is not supported, min value is: %d",
-						              SpiWordWidth(header.iWordWidth), KMinSpiWordWidth));
+						             SpiWordWidth(header.iWordWidth), KMinSpiWordWidth));
+			if((TUint)header.iTransactionWaitCycles > 3)
+				DBG_ERR(Kern::Printf("iTransactionWaitCycles: %d is not supported, value should be from 0 to %d",
+				                     header.iTransactionWaitCycles, KMaxTransactionWaitTime));
+
 			DumpHeader(header);
 #endif
 			r = KErrNotSupported;
--- a/omap3530/omap3530_drivers/spi/omap3530_spi.h	Tue Sep 28 02:37:35 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/omap3530_spi.h	Thu Oct 07 00:37:22 2010 +0100
@@ -209,6 +209,8 @@
 const TUint MCSPI_CHxCONF_TCS_1_5 = 1 << 25; // 0x1: 1.5 clock cycles
 const TUint MCSPI_CHxCONF_TCS_2_5 = 2 << 25; // 0x2: 2.5 clock cycles
 const TUint MCSPI_CHxCONF_TCS_3_5 = 3 << 25; // 0x3: 3.5 clock cycles
+const TUint MCSPI_CHxCONF_TCS_SHIFT = 25;
+const TUint KMaxTransactionWaitTime = 3;
 
 const TUint MCSPI_CHxCONF_SBPOL = 1 << 24; // Start bit polarity (0: spi word is command, 1: spi word is data)
 const TUint MCSPI_CHxCONF_SBE   = 1 << 23; // Start bit enable - 0x1: Start bit D/CX added before transfer.
--- a/omap3530/omap3530_drivers/spi/omap3530_spi.inl	Tue Sep 28 02:37:35 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/omap3530_spi.inl	Thu Oct 07 00:37:22 2010 +0100
@@ -26,7 +26,7 @@
 	__ASSERT_DEBUG( aModule != 2 ? !aPinSetId : ETrue, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // only channel 3 supports other pin configurations
 
 	// set the pin to the opposite to the currently active CS mode..
-	const TPinConfig& csConf = ModulePinConfig[aModule].iCs[aChannel];
+	const TPinConfig& csConf = ModulePinConfig[aModule + aPinSetId].iCs[aChannel];
 	__ASSERT_DEBUG(csConf.iAddress, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // don't try to use non-existing CS!
 
 	// now switch the pin mode..(making sure it is at the proper level before that)
--- a/omap3530/omap3530_drivers/spi/test/d_spi_client_m.cpp	Tue Sep 28 02:37:35 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/test/d_spi_client_m.cpp	Thu Oct 07 00:37:22 2010 +0100
@@ -317,7 +317,7 @@
 	TUint32 busId = 0;
 	SET_BUS_TYPE(busId, DIicBusChannel::ESpi);
 	SET_CHAN_NUM(busId, 2);   // THis is the ModuleNumber, i.e. McSPIx (minus one), e.g. 2 for McSPI3
-	SET_SLAVE_ADDR(busId, 0); // THis is the ChannelNumber (Slave number of the above McSPIx)
+	SET_SLAVE_ADDR(busId, 2); // THis is the ChannelNumber (Slave number of the above McSPIx)
 
 	// create header
 	const TConfigSpiV01 KHeader =
@@ -499,14 +499,14 @@
 	// create header
 	const TConfigSpiV01 KHeader =
 		{
-		ESpiWordWidth_8, //iWordWidth
-		1500000, //iClkSpeed 3MHz (could use SpiFreqHz(32))
-		ESpiPolarityLowRisingEdge, //iClkMode
-		500, // iTimeoutPeriod
-		EBigEndian, // iEndianness
-		EMsbFirst, //iBitOrder
-		0, //iTransactionWaitCycles
-		ESpiCSPinActiveLow //iCsPinActiveMode
+		ESpiWordWidth_8,           // iWordWidth
+		3000000,                   // iClkSpeed 3MHz
+		ESpiPolarityLowRisingEdge, // iClkMode
+		500,                       // iTimeoutPeriod
+		EBigEndian,                // iEndianness
+		EMsbFirst,                 // iBitOrder
+		0,                         // iTransactionWaitCycles
+		ESpiCSPinActiveLow         // iCsPinActiveMode
 		};
 
 	TPckgBuf<TConfigSpiV01> header(KHeader);
--- a/omap3530/omap3530_drivers/spi/test/t_spi_client_m.cpp	Tue Sep 28 02:37:35 2010 +0100
+++ b/omap3530/omap3530_drivers/spi/test/t_spi_client_m.cpp	Thu Oct 07 00:37:22 2010 +0100
@@ -72,6 +72,7 @@
 	test.Next(_L("TestSynchronousOperation()"));
 
 	test.Next(_L("HalfDuplexSingleWrite()"));
+	while(1)
 	TestError(testLdd.HalfDuplexSingleWrite());
 
 	test.Next(_L("HalfDuplexMultipleWrite()"));