# HG changeset patch # User Lukasz Forynski # Date 1286408242 -3600 # Node ID d93b485c1325c2ed628bcead8f4e1220cf89ba11 # Parent 09e266454dcf3de83197952f83a243ec19066a9a 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 diff -r 09e266454dcf -r d93b485c1325 omap3530/beagle_drivers/byd_touch/bld.inf --- /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 diff -r 09e266454dcf -r d93b485c1325 omap3530/beagle_drivers/byd_touch/common/controller.cpp --- /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 +#include +#include +#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 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; + } + diff -r 09e266454dcf -r d93b485c1325 omap3530/beagle_drivers/byd_touch/common/controller.h --- /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 +#include + + +// 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 iSpiTransactionHeader; + TBuf8 iSpiWriteBuffer; + TBuf8 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_ */ diff -r 09e266454dcf -r d93b485c1325 omap3530/beagle_drivers/byd_touch/xyin.mmp --- /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 + diff -r 09e266454dcf -r d93b485c1325 omap3530/beagle_drivers/byd_touch/xyin/mconf.h --- /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 + +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 diff -r 09e266454dcf -r d93b485c1325 omap3530/beagle_drivers/byd_touch/xyin/xyin.cpp --- /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 +#include +#include +#include +#include +#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() + { + } + diff -r 09e266454dcf -r d93b485c1325 omap3530/beagleboard/rom/kernel.iby --- 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 // 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 #include -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 diff -r 09e266454dcf -r d93b485c1325 omap3530/omap3530_drivers/spi/master.cpp --- 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; diff -r 09e266454dcf -r d93b485c1325 omap3530/omap3530_drivers/spi/omap3530_spi.h --- 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. diff -r 09e266454dcf -r d93b485c1325 omap3530/omap3530_drivers/spi/omap3530_spi.inl --- 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) diff -r 09e266454dcf -r d93b485c1325 omap3530/omap3530_drivers/spi/test/d_spi_client_m.cpp --- 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 header(KHeader); diff -r 09e266454dcf -r d93b485c1325 omap3530/omap3530_drivers/spi/test/t_spi_client_m.cpp --- 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()"));