--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/navienginebsp/ne1_tb/test/csi/d_csi.cpp Tue Sep 28 18:00:05 2010 +0100
@@ -0,0 +1,1445 @@
+/*
+* 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 "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:
+*
+*/
+
+
+#ifdef STANDALONE_CHANNEL
+#include <drivers/iic_transaction.h>
+#include "csi_master.h"
+#include "csi_slave.h"
+#else
+#include <drivers/iic.h>
+#endif
+#include <drivers/iic_channel.h>
+#include <drivers/gpio.h>
+#include "cs42l51.h"
+
+#include "d_csi.h"
+
+#define __KTRACE(s)
+//#define __KTRACE(s) __KTRACE_OPT(KIIC, s)
+
+const TInt KMaxNumChannels = 1; // we only support one client at the time
+
+// generic check-error macro - to not put this manually on each operation.
+#define CHECK_ERR(r) \
+ if(r != KErrNone){ \
+ __KTRACE(Kern::Printf("d_csi.cpp, line: %d returned r=%d", __LINE__, r)); \
+ return r;}
+
+// Default Test Header
+const TConfigSpiV01 DefaultHeader =
+ {
+ ESpiWordWidth_8, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityLowRisingEdge, //iClkMode
+ 500, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow //iCsPinActiveMode
+ };
+
+_LIT(KLddRootName,"d_csi");
+_LIT(KIicClientThreadName,"IicClientLddThread");
+
+// Constructor
+DDeviceIicClient::DDeviceIicClient()
+ {
+ __KTRACE(Kern::Printf("DDeviceIicClient::DDeviceIicClient()"));
+ iParseMask = 0; // No info, no PDD, no Units
+ iUnitsMask = 0;
+ iVersion = TVersion(KIicClientMajorVersionNumber,
+ KIicClientMinorVersionNumber, KIicClientBuildVersionNumber);
+ }
+
+// Destructor
+DDeviceIicClient::~DDeviceIicClient()
+ {
+ __KTRACE(Kern::Printf("DDeviceIicClient::~DDeviceIicClient()"));
+ }
+
+// Install the device driver.
+TInt DDeviceIicClient::Install()
+ {
+ __KTRACE(Kern::Printf("DDeviceIicClient::Install()"));
+ return (SetName(&KLddRootName));
+ }
+
+void DDeviceIicClient::GetCaps(TDes8& aDes) const
+// Return the IicClient capabilities.
+ {
+ TPckgBuf<TCapsIicClient> b;
+ b().version = TVersion(KIicClientMajorVersionNumber, KIicClientMinorVersionNumber, KIicClientBuildVersionNumber);
+ Kern::InfoCopy(aDes, b);
+ }
+
+// Create a channel on the device.
+TInt DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)
+ {
+ __KTRACE(Kern::Printf("DDeviceIicClient::Create(DLogicalChannelBase*& aChannel)"));
+
+ if (iOpenChannels >= KMaxNumChannels)
+ {
+ return KErrOverflow;
+ }
+ aChannel = new DChannelIicClient;
+ return aChannel ? KErrNone : KErrNoMemory;
+ }
+
+DChannelIicClient::DChannelIicClient()
+ {
+ iClient = &Kern::CurrentThread();
+ iSlaveCallback = NULL;
+ // Increase the DThread's ref count so that it does not close without us
+ iClient->Open();
+ }
+
+DChannelIicClient::~DChannelIicClient()
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::~DChannelIicClient()"));
+ iDfcQue->Destroy();
+
+ //free memory:
+ delete iSpiHeader;
+#ifdef STANDALONE_CHANNEL
+#ifdef MASTER_MODE
+ if(iMasterChannel)
+ delete iMasterChannel;
+#endif/*MASTER_MODE*/
+
+#ifdef SLAVE_MODE
+ if(iSlaveChannel)
+ delete iSlaveChannel;
+#endif/*SLAVE_MODE*/
+#endif
+
+ // decrement the DThread's reference count
+ Kern::SafeClose((DObject*&) iClient, NULL);
+ }
+
+TInt DChannelIicClient::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/,
+ const TVersion& /*aVer*/)
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::DoCreate(), UNIT %d", aUnit));
+ TInt r = KErrNone;
+
+ // Bus Realisation Config iCsiBusId;
+ iCsiBusId = 0;
+ SET_BUS_TYPE(iCsiBusId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(iCsiBusId,KCodecChannelNumber);
+ SET_SLAVE_ADDR(iCsiBusId,14);
+
+#ifdef STANDALONE_CHANNEL
+#ifdef MASTER_MODE
+ // create channel 0 - as master..
+ iMasterChannel = DCsiChannelMaster::New(0, DIicBusChannel::ESpi, DIicBusChannel::EFullDuplex);
+ if (!iMasterChannel)
+ {
+ __KTRACE_OPT(KIIC, Kern::Printf("Error no memory"));
+ return KErrNoMemory;
+ }
+#endif /*MASTER_MODE*/
+
+#ifdef SLAVE_MODE
+ // and created channel 1 - as slave..
+ iSlaveChannel = DCsiChannelSlave::New(1, DIicBusChannel::ESpi, DIicBusChannel::EFullDuplex);
+ if (!iSlaveChannel)
+ {
+ __KTRACE_OPT(KIIC, Kern::Printf("Error no memory"));
+ #ifdef MASTER_MODE
+ delete iMasterChannel; //Free memory
+ #endif
+ return KErrNoMemory;
+ }
+#endif /*SLAVE_MODE*/
+
+
+#endif/*STANDALONE_CHANNEL*/
+
+ r = Kern::DynamicDfcQCreate(iDfcQue, KIicClientThreadPriority, KIicClientThreadName);
+ if(r == KErrNone)
+ {
+ iSpiHeader = new TConfigSpiBufV01(DefaultHeader);
+ if(iSpiHeader)
+ {
+ SetDfcQ(iDfcQue);
+ iMsgQ.Receive();
+ }
+ else
+ {
+ r = KErrNoMemory;
+ }
+ }
+ return r;
+ }
+
+void DChannelIicClient::HandleMsg(TMessageBase* aMsg)
+ {
+ TThreadMessage& m = *(TThreadMessage*) aMsg;
+ TInt id = m.iValue;
+
+ if (id == ECloseMsg)
+ {
+ // make sure, we've released the SlaveChannel on closure..
+ DoControl(RBusCsiTestClient::EReleaseSlaveChannel, NULL, NULL);
+
+ iMsgQ.iMessage->Complete(KErrNone, EFalse);
+ return;
+ }
+ else if (id == KMaxTInt)
+ {
+ DoCancel(m.Int0());
+ m.Complete(KErrNone, ETrue);
+ return;
+ }
+
+ if (id < 0)
+ {
+ TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
+ TInt r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
+ if (r != KErrNone)
+ {
+ Kern::RequestComplete(iClient, pS, r);
+ }
+ m.Complete(KErrNone, ETrue);
+ }
+ else
+ {
+ TInt r = DoControl(id, m.Ptr0(), m.Ptr1());
+ m.Complete(r, ETrue);
+ }
+ }
+
+void DChannelIicClient::DoCancel(TInt aMask)
+ {
+ // Cancel an outstanding request.
+ // Not implemented.
+ return;
+ }
+
+#ifdef MASTER_MODE
+TInt DChannelIicClient::QueueTransaction(TInt aBusId, TIicBusTransaction* aTransaction, TIicBusCallback *aCallback/*=NULL*/)
+ {
+#ifndef STANDALONE_CHANNEL
+ if(!aCallback)
+ return IicBus::QueueTransaction(aBusId, aTransaction);
+ else
+ return IicBus::QueueTransaction(aBusId, aTransaction, aCallback);
+#else
+ if(iMasterChannel)
+ {
+ aTransaction->iBusId = aBusId;
+ if(!aCallback)
+ return iMasterChannel->QueueTransaction(aTransaction);
+ else
+ return iMasterChannel->QueueTransaction(aTransaction, aCallback);
+ }
+ else
+ return KErrGeneral; //iMaster not initialised? - channels not created?
+#endif
+ }
+#endif /*MASTER_MODE*/
+
+#ifdef SLAVE_MODE
+TInt DChannelIicClient::RegisterRxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
+ {
+#ifdef STANDALONE_CHANNEL
+ if(iSlaveChannel)
+ return iSlaveChannel->RegisterTxBuffer(aRxBuffer, aBufGranularity, aNumWords, aOffset);
+ else
+ return KErrGeneral;
+#else
+ return IicBus::RegisterRxBuffer(aChannelId, aRxBuffer, aBufGranularity, aNumWords, aOffset);
+#endif
+ }
+
+TInt DChannelIicClient::RegisterTxBuffer(TInt aChannelId, TPtr8 aRxBuffer, TInt8 aBufGranularity, TInt8 aNumWords, TInt8 aOffset)
+ {
+#ifdef STANDALONE_CHANNEL
+ if(iSlaveChannel)
+ return iSlaveChannel->RegisterTxBuffer(aRxBuffer, aBufGranularity, aNumWords, aOffset);
+ else
+ return KErrGeneral;
+#else
+ return IicBus::RegisterTxBuffer(aChannelId, aRxBuffer, aBufGranularity, aNumWords, aOffset);
+#endif
+ }
+
+TInt DChannelIicClient::CaptureChannel(TInt aBusId, TDes8* aConfigHdr, TIicBusSlaveCallback* aCallback, TInt& aChannelId, TBool aAsynch)
+ {
+#ifdef STANDALONE_CHANNEL
+ if(iSlaveChannel)
+ return iSlaveChannel->CaptureChannel(aConfigHdr, aCallback, aChannelId, aAsynch);
+ else
+ return KErrGeneral;
+#else
+ return IicBus::CaptureChannel(aBusId, aConfigHdr, aCallback, aChannelId, aAsynch);
+#endif
+ }
+
+
+TInt DChannelIicClient::ReleaseChannel(TInt aChannelId)
+ {
+#ifdef STANDALONE_CHANNEL
+ if(iSlaveChannel)
+ return iSlaveChannel->ReleaseChannel();
+ else
+ return KErrGeneral;
+#else
+ return IicBus::ReleaseChannel(aChannelId);
+#endif
+ }
+
+TInt DChannelIicClient::SetNotificationTrigger(TInt aChannelId, TInt aTrigger)
+ {
+#ifdef STANDALONE_CHANNEL
+ if(iSlaveChannel)
+ return iSlaveChannel->SetNotificationTrigger(aTrigger);
+ else
+ return KErrGeneral;
+#else
+ return IicBus::SetNotificationTrigger(aChannelId, aTrigger);
+#endif
+ }
+#endif /*SLAVE_MODE*/
+
+// This test tests the timeout for the half-duplex Write requests.
+// it creates a transaction with one transfer.
+// Clk 200kHz actually sets the clock to 260000 kHz. With 8bit granularity - gives 25kB/s
+// 32,5 bytes should be transferred in 1ms
+// so e.g. setting the timeout to 1ms and the transfer size to more than that 32 bytes should
+// cause a transfer timeout for transmission.
+// test case:
+// 1. setting timeout to 1ms with buffer 128 bytes - should result in KErrTImeout return value.
+// 2. setting timeout to 5ms (~160 bytes transfer) - should result in KErrNone return value.
+#ifdef MASTER_MODE
+TInt DChannelIicClient::TestTransferTimeout()
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::TestTransferTimeout()"));
+ TInt r = KErrNone;
+
+ TUint32 busId = 0;
+ SET_BUS_TYPE(busId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(busId,0);
+ SET_SLAVE_ADDR(busId,13); // test it with any number between 1-32
+
+ // Create a transaction header
+ const TConfigSpiV01 TestHeader =
+ {
+ ESpiWordWidth_8, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityLowRisingEdge, //iClkMode
+ 1, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow //iCsPinActiveMode
+ };
+
+ TPckgBuf<TConfigSpiV01> header(TestHeader);
+
+ // create transfer object
+ TBuf8<128> transfer_buf; // buffer..
+ transfer_buf.SetLength(transfer_buf.MaxLength());
+
+ TIicBusTransfer transfer(TIicBusTransfer::EMasterWrite, 8, &transfer_buf);
+
+ // Create a transaction using header and transfer..
+ TIicBusTransaction transaction1(&header, &transfer);
+
+ // this transaction should return KErrTimeout
+ r = QueueTransaction(busId, &transaction1);
+
+ if (r != KErrTimedOut)
+ {
+ __KTRACE(Kern::Printf("no timeout??, r= %d", r));
+ return r;
+ }
+
+ // change the timeout to and create another transaction..
+ header().iTimeoutPeriod = 6; // it works for 4 too (~130Bytes)
+ transfer_buf.SetLength(transfer_buf.MaxLength());
+ TIicBusTransfer transfer2(TIicBusTransfer::EMasterWrite, 8, &transfer_buf);
+
+ TIicBusTransaction transaction2(&header, &transfer2);
+
+ // this transaction should return KErrNone
+ r = QueueTransaction(busId, &transaction2);
+
+ if (r != KErrNone)
+ {
+ __KTRACE(Kern::Printf("Transaction failed, r= %d", r));
+ }
+
+ return r;
+ }
+
+TInt DChannelIicClient::TestHalfDuplexTransaction()
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::TestHalfDuplexTransaction()"));
+ TInt r = KErrNone;
+
+ TUint32 busId = 0;
+ SET_BUS_TYPE(busId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(busId,0);
+ SET_SLAVE_ADDR(busId,13); // test it with any number between 1-32
+
+ // create header
+ const TConfigSpiV01 TestHeader =
+ {
+ ESpiWordWidth_8, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityLowRisingEdge, //iClkMode
+ 500, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow //iCsPinActiveMode
+ };
+
+ TPckgBuf<TConfigSpiV01> header(TestHeader);
+
+ // create transfer object
+ TBuf8<32> txTransferBuf; // buffer..
+ TBuf8<32> rxTransferBuf; // buffer..
+ for (TInt i = 0; i < txTransferBuf.MaxLength(); ++i)
+ {
+ txTransferBuf.Append(i);
+ }
+ txTransferBuf.SetLength(txTransferBuf.MaxLength());
+ rxTransferBuf.SetLength(rxTransferBuf.MaxLength());
+
+ // combine some transfers -in one transaction.
+ TIicBusTransfer txTransfer(TIicBusTransfer::EMasterWrite, 8, &txTransferBuf);
+ TIicBusTransfer rxTransfer(TIicBusTransfer::EMasterRead, 8, &rxTransferBuf);
+ txTransfer.LinkAfter(&rxTransfer);
+
+ TIicBusTransfer txTransfer2(TIicBusTransfer::EMasterWrite, 8, &txTransferBuf);
+ rxTransfer.LinkAfter(&txTransfer2);
+
+ TIicBusTransfer rxTransfer2(TIicBusTransfer::EMasterRead, 8, &rxTransferBuf);
+ txTransfer2.LinkAfter(&rxTransfer2);
+
+ // Create a transaction using header and list of transfers..
+ TIicBusTransaction transaction(&header, &txTransfer);
+
+ // queue the transaction - it should complete successful
+ r = QueueTransaction(busId, &transaction);
+
+ return r;
+ }
+
+TInt DChannelIicClient::TestBulkTransfer()
+ {
+ //Create a Transaction object which contains 2 Transfers. of buffer sizes say 256 and 64
+ const TUint8 KTrBuf1Length = 128;
+ const TUint8 KTrBuf2Length = 64;
+
+ TUint32 busId = 0;
+ SET_BUS_TYPE(busId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(busId,0);
+ SET_SLAVE_ADDR(busId,5);
+
+ // create header
+ const TConfigSpiV01 TestHeader =
+ {
+ ESpiWordWidth_16, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityLowRisingEdge, //iClkMode
+ 3000, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow //iCsPinActiveMode
+ };
+
+ TPckgBuf<TConfigSpiV01> header(TestHeader);
+
+ TBuf8<KTrBuf1Length> transBuf1;
+ TBuf8<KTrBuf2Length> transBuf2;
+ TInt r = KErrNone;
+
+ for (TInt i = 0; i < KTrBuf1Length; ++i)
+ {
+ transBuf1.Append(i + '0');
+ }
+
+ for (TInt i = 0; i < KTrBuf2Length; ++i)
+ {
+ transBuf2.Append(i + 'a');
+ }
+
+ transBuf1.SetLength(KTrBuf1Length);
+ transBuf2.SetLength(KTrBuf2Length);
+
+ //TIicBusTransfer trans1;
+ TIicBusTransfer trans1(TIicBusTransfer::TIicBusTransfer::EMasterWrite, 8, &transBuf2);
+ TIicBusTransfer trans2(TIicBusTransfer::TIicBusTransfer::EMasterRead, 8, &transBuf1);
+ trans1.LinkAfter(&trans2);
+
+ // for the other direction - re-use buffers..(they will be interleaved)
+ TIicBusTransfer trans3(TIicBusTransfer::TIicBusTransfer::EMasterRead, 8, &transBuf1);
+ TIicBusTransfer trans4(TIicBusTransfer::TIicBusTransfer::EMasterWrite, 8, &transBuf2);
+ trans3.LinkAfter(&trans4);
+
+ // transaction
+ TIicBusTransaction trans(&header, &trans1); // this will set the transaction with trans1 and trans2
+ trans.SetFullDuplexTrans(&trans3); // and this will add trans3 and trans4 for the other direction
+
+ r = QueueTransaction(busId, &trans);
+
+ return r;
+ }
+
+// Testing CSI interface with AudioCodec:
+// this involves several CSI write transactions to set-up the AudioCodec
+// and configure it to generate the sound (of a particular frequency)
+
+// CSI configuration parameters needed to transmit data to the Codec
+// these are used as the transaction header object.
+const TConfigSpiV01 KCodecSpiV01Config =
+ {
+ ESpiWordWidth_8, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityHighFallingEdge, //iClkMode
+ 100, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow //iCsPinActiveMode
+ };
+
+// helper function - to update buffer data and queue the transaction with the updated data
+TInt DChannelIicClient::QueueRegisterWriteTransaction(TInt16 aRegister,
+ TInt16 aValue, TIicBusTransaction* aTrans, TInt aConfig)
+ {
+ iTransBuff().iRegister = aRegister;
+ iTransBuff().iData = aValue;
+ TInt r = QueueTransaction(aConfig, aTrans);
+ return r;
+ }
+
+// this method configures the codec and sets its registers to create a sound of
+// requested frequency, duration time, volume and the time..etc..
+// to set these params we will be using single transactions - reusing all objects created on the stack:
+// - transaction (TIicBusTransaction),
+// - header object (TConfigSpiV01 - embedded in TPckgBuf<TConfigSpiV01> headerBuff)
+// - TIicBusRealisationConfig - busId / config
+
+TInt DChannelIicClient::TestAudioCodecBeep(TUint8 aFreq, TUint8 aTime,
+ TUint8 aOffTime, TUint8 aVolume, TBool aRepeat /*=0*/)
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::TestAudioCodecBeep()"));
+
+ // enable and configure pin 25 - it is connected to the chip's reset line
+ GPIO::SetPinMode(KCodecResetPin, GPIO::EEnabled);
+ GPIO::SetPinDirection(KCodecResetPin, GPIO::EOutput);
+ GPIO::SetDebounceTime(KCodecResetPin, 0);
+
+ // Bus Realisation Config
+ TUint32 iCsiBusId = 0;
+ SET_BUS_TYPE(iCsiBusId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(iCsiBusId,KCodecChannelNumber);
+ SET_SLAVE_ADDR(iCsiBusId,KCodecCSPin); // use codec's CS pin number as a Slave address
+
+ TInt config = iCsiBusId;
+
+ // create header
+ TPckgBuf<TConfigSpiV01> header(KCodecSpiV01Config);
+
+ // create transfer object - use iTransBuff member, which contains RCS42AudioCodec::TCodecConfigData
+ TIicBusTransfer transfer(TIicBusTransfer::EMasterWrite, 8, &iTransBuff);
+ TIicBusTransaction transaction(&header, &transfer);
+
+ // setup the transaction - to use this header and transfer object
+ transaction.SetHalfDuplexTrans(&header, &transfer);
+
+ // fill the TCodecConfigData.Address only once, it won't change..
+ iTransBuff().iAddress = KCodecWriteCommand;
+
+ // power-up sequence..
+ // put !reset line high to start the power-up sequence..
+ // GPIO::SetOutputState(KCodecResetPin, GPIO::ELow);
+ GPIO::SetOutputState(KCodecResetPin, GPIO::EHigh);
+
+ TInt r = KErrNone;
+
+ r = QueueRegisterWriteTransaction(KHwCS42L51PwrCtrl, KHtCS42L51PwrCtrl_PDN, &transaction, config);
+ CHECK_ERR(r);
+
+ r = QueueRegisterWriteTransaction(KHwCS42L51PwrCtrl, KHtCS42L51PwrCtrl_PDN_ALL, &transaction, config);
+ CHECK_ERR(r);
+
+ // freeze all registers.. until are set-up.
+ r = QueueRegisterWriteTransaction(KHwCS42L51DACControl, KHtCS42L51DACControl_FREEZE, &transaction, config);
+ CHECK_ERR(r);
+
+ //Set Mic power control and speed control register(0x03)
+ r = QueueRegisterWriteTransaction(KHwCS42L51MicPwrSpeed, KHtCS42L51MicPwrSpeed_AUTO, &transaction, config);
+ CHECK_ERR(r);
+
+ // interface control (0x04) // serial port settings..
+ // I2s, Slave, SDOUT->SDIN internally connected.. Digimix->ON?
+ // use I2S format, Slave, Digital & Mic mix
+ TUint16 val = (KHCS42L51CtrlI2sUpto24bit << KHsCS42L51CtrlFormat)
+ | KHtCS42L51Ctrl_DIGMIX | KHtCS42L51Ctrl_MICMIX;
+ r = QueueRegisterWriteTransaction(KHwCS42L51Ctrl, val, &transaction, config);
+ CHECK_ERR(r);
+
+ // DAC output select (0x08)
+ // 7 6 5 4 3 2 1 0
+ // HP_GAIN2 HP_GAIN1 HP_GAIN0 DAC_SNGVOL INV_PCMB INV_PCMA DACB_MUTE DACA_MUTE
+ r = QueueRegisterWriteTransaction(KHwCS42L51DACOutputControl, KHtCS42L51DACOutputControl_DAC_SNGVOL, &transaction, config);
+ CHECK_ERR(r);
+
+ // ALCX & PGAX ctrl, A(0x0A), B (0x0B)
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_PGA_A_Control, 0, &transaction, config);
+ CHECK_ERR(r);
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_PGA_B_Control, 0, &transaction, config);
+ CHECK_ERR(r);
+
+ // ADCx Mixer Volume Ctrl A(0x0E), B (0x0F)
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_ADC_A_MixVolume, 0x10, &transaction, config);
+ CHECK_ERR(r);
+
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_ADC_B_MixVolume, 0x10, &transaction, config);
+ CHECK_ERR(r);
+
+ // PCMx Volume Ctrl A(0x10), B (0x11)
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_PCM_A_MixVolume, 0x10, &transaction, config);
+ CHECK_ERR(r);
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_PCM_B_MixVolume, 0x10, &transaction, config);
+ CHECK_ERR(r);
+
+ // Volume Control: AOUTA (Address 16h) & AOUTB (Address 17h)
+ //send next one..
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_Out_A_Volume, 0x10, &transaction, config);
+ CHECK_ERR(r);
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_Out_B_Volume, 0x10, &transaction, config);
+ CHECK_ERR(r);
+
+ // DAC Control (Address 09h)
+ // 7 6 5 4 3 2 1 0
+ // DATA_SEL1 DATA_SEL0 FREEZE Reserved DEEMPH AMUTE DAC_SZC1 DAC_SZC0
+ // DATA_SEL1 DATA_SEL0:
+ // 00 - PCM Serial Port to DAC
+ // 01 - Signal Processing Engine to DAC
+ // 10 - ADC Serial Port to DAC (11 - Reserved)
+ r = QueueRegisterWriteTransaction(KHwCS42L51DACControl, (1 << KHsCS42L51DACControl_DATA_SEL), &transaction, config);
+ CHECK_ERR(r);
+
+ // power-up sequence..end - clear PDN ..after loading register settings..
+ r = QueueRegisterWriteTransaction(KHwCS42L51PwrCtrl, 0, &transaction, config);
+ CHECK_ERR(r);
+
+ // now - the codec is ready to generate the beep of requested frequency..
+ // Set the beep frequency and time..
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_Beep_FQ_Time, (aFreq
+ << KHsCS42L51ALC_Beep_FQ) | (aTime & KHmCS42L51ALC_Beep_Time_Mask), &transaction, config);
+ CHECK_ERR(r);
+
+ // Set the Volume and off time
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_Beep_Off_Volume,
+ (aOffTime << KHsCS42L51ALC_Beep_Off) | (aVolume & KHmCS42L51ALC_Beep_Volume_Mask),
+ &transaction, config);
+ CHECK_ERR(r);
+
+ // set the 'repeat' bit and enable the beep..
+ r = QueueRegisterWriteTransaction(KHwCS42L51ALC_Beep_Conf_Tone,
+ (aRepeat ? KHtCS42L51ALC_Beep_Conf_Tone_REPEAT : 0) |
+ KHtCS42L51ALC_Beep_Conf_Tone_BEEP, &transaction, config);
+ CHECK_ERR(r);
+
+ NKern::Sleep(500); // give it some time to play ;)
+
+ // power down the codec:
+ r = QueueRegisterWriteTransaction(KHwCS42L51PwrCtrl, KHtCS42L51PwrCtrl_PDN, &transaction, config);
+ CHECK_ERR(r);
+
+ GPIO::SetOutputState(KCodecResetPin, GPIO::ELow);
+ return KErrNone;
+ }
+
+
+// Test Transaction with different configuration settings
+// 1) Different Header settinngs (TConfigSpiBufV01))
+// 2) Different Bus Config settings (Bus Realisation Config)
+TInt DChannelIicClient::TestConfigParams(TInt aBusId)
+ {
+ TInt r = KErrNone;
+
+ const TUint8 KTrasferBufferLength = 120;
+
+ //First Create a Half Duplex Transfer List of 3 Transfers of Type W,R,W
+ TBuf8<KTrasferBufferLength> trBuf1;
+ TBuf8<KTrasferBufferLength> trBuf2;
+
+ TIicBusTransfer hdTrasfer1(TIicBusTransfer::EMasterWrite, 8, &trBuf1);
+ TIicBusTransfer hdTrasfer2(TIicBusTransfer::EMasterRead, 8, &trBuf2);
+
+ //Link the Half Duplex Transfers 1->2
+ hdTrasfer1.LinkAfter(&hdTrasfer2);
+
+ //Create A Ful Duplex Transfer of 3 Transfers of type ,R,W,R
+ TBuf8<KTrasferBufferLength> trBuf3;
+ TBuf8<KTrasferBufferLength> trBuf4;
+
+ TIicBusTransfer fdTrasfer1(TIicBusTransfer::EMasterRead, 8, &trBuf3);
+ TIicBusTransfer fdTrasfer2(TIicBusTransfer::EMasterWrite, 8, &trBuf4);
+
+ //Link the Full Duplex Transfers 1->2
+ fdTrasfer1.LinkAfter(&fdTrasfer2);
+
+ for (TUint i = 0; i < KTrasferBufferLength; i++)
+ {
+ //Fill the Buffers associated with Write Transfer with some data
+ trBuf1.Append(i + '0');
+ trBuf4.Append(i + 'A');
+ }
+
+ trBuf1.SetLength(KTrasferBufferLength);
+ trBuf2.SetLength(KTrasferBufferLength);
+ trBuf3.SetLength(KTrasferBufferLength);
+ trBuf4.SetLength(KTrasferBufferLength);
+
+ // Create a transaction using header and transfer..
+ TIicBusTransaction fdTransaction(iSpiHeader, &hdTrasfer1);
+
+ fdTransaction.SetFullDuplexTrans(&fdTrasfer1);
+
+ // Queue Transaction
+ r = QueueTransaction(aBusId, &fdTransaction);
+
+ return r;
+ }
+
+
+// Test Duplex Transaction
+// Construct two chain of combined transfers for the transaction:
+// 1) A Half Duplex Transfer with a Read , Write and Read operation
+// 2) A Full Duplex Transfer with a Write, Read and Write Operation.
+TInt DChannelIicClient::TestDuplexTransaction()
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::TestDuplexTransaction\n"));
+
+ TInt r = KErrNone;
+
+ TUint32 busId = 0;
+ SET_BUS_TYPE(busId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(busId,0);
+ SET_SLAVE_ADDR(busId,1);
+
+ // create header
+ const TConfigSpiV01 DefaultHeader =
+ {
+ ESpiWordWidth_8, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityLowRisingEdge, //iClkMode
+ 1000, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow//iCsPinActiveMode
+ };
+
+ const TUint8 KTrasferBufferLength = 120;
+
+ TConfigSpiBufV01 header(DefaultHeader);
+
+ //First Create a Half Duplex Transfer List of 3 Transfers of Type W,R,W
+ TBuf8<KTrasferBufferLength> trBuf1;
+ TBuf8<KTrasferBufferLength> trBuf2;
+ TBuf8<KTrasferBufferLength> trBuf3;
+
+ TIicBusTransfer hdTrasfer1(TIicBusTransfer::EMasterWrite, 8, &trBuf1);
+ TIicBusTransfer hdTrasfer2(TIicBusTransfer::EMasterRead, 8, &trBuf2);
+ TIicBusTransfer hdTrasfer3(TIicBusTransfer::EMasterWrite, 8, &trBuf3);
+
+ //Link the Half Duples Transfers 1->2->3
+ hdTrasfer1.LinkAfter(&hdTrasfer2);
+ hdTrasfer2.LinkAfter(&hdTrasfer3);
+
+ //Create A Ful Duples Transfer of 3 Transfers of type ,R,W,R
+ TBuf8<KTrasferBufferLength> trBuf4;
+ TBuf8<KTrasferBufferLength> trBuf5;
+ TBuf8<KTrasferBufferLength> trBuf6;
+
+ TIicBusTransfer fdTrasfer1(TIicBusTransfer::EMasterRead, 8, &trBuf4);
+ TIicBusTransfer fdTrasfer2(TIicBusTransfer::EMasterWrite, 8, &trBuf5);
+ TIicBusTransfer fdTrasfer3(TIicBusTransfer::EMasterRead, 8, &trBuf6);
+
+ //Link the Full Duples Transfers 1->2->3
+ fdTrasfer1.LinkAfter(&fdTrasfer2);
+ fdTrasfer2.LinkAfter(&fdTrasfer3);
+
+ for (TUint i = 0; i < KTrasferBufferLength; i++)
+ {
+ //Fill the Buffers associated with Write Transfer with some data
+ trBuf1.Append(i + '0');
+ trBuf3.Append(i + 'A');
+ trBuf5.Append(i + 'a');
+ //Read Buffers
+ trBuf2.Append('$');
+ trBuf4.Append('?');
+ trBuf6.Append('*');
+ }
+
+ trBuf1.SetLength(KTrasferBufferLength);
+ trBuf2.SetLength(KTrasferBufferLength);
+ trBuf3.SetLength(KTrasferBufferLength);
+ trBuf4.SetLength(KTrasferBufferLength);
+ trBuf5.SetLength(KTrasferBufferLength);
+ trBuf6.SetLength(KTrasferBufferLength);
+
+ // Create a transaction using header and transfer..
+ TIicBusTransaction fdTransaction(&header, &hdTrasfer1);
+ fdTransaction.SetFullDuplexTrans(&fdTrasfer1);
+
+ //Queue Transaction
+ r = QueueTransaction(busId, &fdTransaction);
+
+ return r;
+ }
+
+// Callback for Master's asynchronous transactions
+// this is called whenever the transaction has been finished.
+void DChannelIicClient::AsyncTransCallbackFunc(TIicBusTransaction* aTransaction, TInt /*aBusId*/, TInt aResult, TAny* aParam)
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::AsyncTransCallbackFunc aResult =%d\n",aResult));
+ TCallBckRequest<3> *cr = (TCallBckRequest<3>*)aParam;
+
+ // complete request..
+ Kern::RequestComplete(cr->iClient, cr->iReqStatus, aResult);
+
+ // now can finally delete cr object = wchich will delete 1-6 (i don't like that..TIicBusTransaction has all this info..)
+ delete cr;
+ if(aTransaction)
+ delete aTransaction;
+ }
+
+/*
+Test Asynchronous Transaction
+with a chain of HD(HalfDuplex) transfers: Read -> Write -> Read
+
+ Memory management for asynchronous transactions: we create the following on the heap:
+ 1. transaction header (in DoRequest),
+ 2. transaction
+ 3. transfers for transaction (chained in linked-list)
+ 4. buffers for transfers
+ 5. IIC callback object (TIicBusCallback)
+ 6. callback request - which stores pointers to callback object(TIicBusCallback),
+ and pointers to the client and the request status object (used by RequestComplete)
+
+ All of these need to be deleted in the AsyncTransCallbackFunc
+ (at the end of transaction)
+*/
+const TUint8 KTrasferBufferLength = 120;
+
+TInt DChannelIicClient::TestAsynTransaction(TRequestStatus* aStatus, TConfigSpiBufV01* aSpiHeader, TInt aBusId)
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::TestAsynTransaction\n"));
+ TInt r = KErrNone;
+
+ // Store required RequestComplete pointers in our TCbRequest (6.)
+ TCallBckRequest<3> *cbRequest = new TCallBckRequest<3>(iClient, aStatus, aSpiHeader);
+
+ //Create the CallBack Function (5.)
+ TIicBusCallback *callback = new TIicBusCallback(AsyncTransCallbackFunc, (TAny*)cbRequest, iDfcQue, 5); // 5 arbitrary
+ cbRequest->iCallback = callback;
+
+ // create buffers (4.)
+ HBuf8* trBuf1 = HBuf8::New(KTrasferBufferLength);
+ cbRequest->iBuffers[0] = trBuf1;
+ HBuf8* trBuf2 = HBuf8::New(KTrasferBufferLength);
+ cbRequest->iBuffers[1] = trBuf2;
+ HBuf8* trBuf3 = HBuf8::New(KTrasferBufferLength);
+ cbRequest->iBuffers[2] = trBuf3;
+
+ // create transfers..(3.)
+ TIicBusTransfer* hdTrasfer1 = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, trBuf1);
+ cbRequest->iTransfers[0] = hdTrasfer1;
+ TIicBusTransfer* hdTrasfer2 = new TIicBusTransfer(TIicBusTransfer::EMasterWrite, 8, trBuf2);
+ cbRequest->iTransfers[1] = hdTrasfer2;
+ TIicBusTransfer* hdTrasfer3 = new TIicBusTransfer(TIicBusTransfer::EMasterRead, 8, trBuf3);
+ cbRequest->iTransfers[2] = hdTrasfer3;
+
+ // Create a transaction using header and transfer..(2.)
+ TIicBusTransaction* transaction = new TIicBusTransaction(aSpiHeader, hdTrasfer1);
+
+ if(!trBuf1 || !trBuf2 || !trBuf2 ||
+ !hdTrasfer1 || !hdTrasfer2 || !hdTrasfer3 ||
+ !transaction || ! cbRequest || !callback)
+ {
+ delete cbRequest;
+ __KTRACE(Kern::Printf("No memory for allocating transfer buffers"));
+ return KErrNoMemory;
+ }
+
+
+ // put some dummy data in buffers..
+ for (TUint i = 0; i < KTrasferBufferLength; ++i)
+ {
+ //Fill the Buffers associated with Write Transfer with some data
+ trBuf1->Append(i + '0');
+ trBuf2->Append(i + 'a');
+ trBuf3->Append(i + 'A');
+ }
+
+ //Link the transfers 1->2->3
+ hdTrasfer1->LinkAfter(hdTrasfer2);
+ hdTrasfer2->LinkAfter(hdTrasfer3);
+
+ // Queue Transaction
+ r = QueueTransaction(aBusId, transaction, callback);
+ return r;
+ }
+#endif/*MASTER_MODE*/
+
+// =======================
+// Slave channel tests
+//
+// callbackForOneduplex asynchronous transaction..
+void DChannelIicClient::MasterCallbackFunc(TIicBusTransaction* aTransction,
+ TInt aBusId,
+ TInt aResult,
+ TAny* aParam)
+ {
+// DChannelIicClient* a = (DChannelIicClient*) aParam;
+ __KTRACE(Kern::Printf("MasterCallbackFunc, aResult = %d", aResult));
+ }
+
+#ifdef MASTER_MODE
+// this method asynchronously queues one duplex transaction using
+// the buffers, which are part of the DChannelIicClient().
+TInt DChannelIicClient::QueueOneDuplexTransaction(TInt aSize)
+ {
+ __KTRACE(Kern::Printf("QueueOneDuplexTransaction, aSize = %d", aSize));
+
+ TInt r = KErrNone;
+ if(aSize > KMaxSlaveTestBufferSize)
+ {
+ return KErrArgument;
+ }
+
+ TUint32 busId = 0;
+ SET_BUS_TYPE(busId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(busId,0);
+ SET_SLAVE_ADDR(busId,13); // test it with any number between 1-32
+
+ // create header
+ const TConfigSpiV01 TestHeader =
+ {
+ ESpiWordWidth_8, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityLowRisingEdge, //iClkMode
+ 500, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow //iCsPinActiveMode
+ };
+ TPckgBuf<TConfigSpiV01> header(TestHeader);
+
+ TBuf8<KMaxSlaveTestBufferSize> txBuf; // buffer..
+ TBuf8<KMaxSlaveTestBufferSize> rxBuf; // buffer..
+
+ // create transfer object
+ for (TInt i = 0; i < aSize; ++i)
+ {
+ txBuf.Append(i);
+ }
+ rxBuf.SetLength(aSize);
+
+ // combine some transfers -in one transaction.
+ TIicBusTransfer txTransfer(TIicBusTransfer::EMasterWrite, 8, &txBuf);
+ TIicBusTransfer rxTransfer(TIicBusTransfer::EMasterRead, 8, &rxBuf);
+
+ // Create a transaction using header and list of transfers..
+ iMasterTransaction.SetHalfDuplexTrans(&header, &txTransfer);
+ iMasterTransaction.SetFullDuplexTrans(&rxTransfer);
+
+ // queue the transaction
+ r = QueueTransaction(busId, &iMasterTransaction);
+
+ return r;
+ }
+#endif /*MASTER_MODE*/
+
+#ifdef SLAVE_MODE
+TInt DChannelIicClient::RegisterSlaveBuffers()
+ {
+ __KTRACE(Kern::Printf("RegisterSlaveBuffers(), size %d", iSlaveBufSize));
+ TInt r = KErrNone;
+ // put some data in the buffer - so we could see-if this is actually beeing transfered...
+ for(TInt i = 0; i < iSlaveBufSize; ++i)
+ {
+ iTxBuf.Append(i);
+ }
+
+ TPtr8 rxBuf(0, 0);
+ TPtr8 txBuf(0, 0);
+
+ rxBuf.Set((TUint8*) iRxBuf.Ptr(), iSlaveBufSize, iRxBuf.MaxLength());
+ txBuf.Set((TUint8*) iTxBuf.Ptr(), iSlaveBufSize, iTxBuf.MaxLength());
+
+ r = RegisterRxBuffer(iChannelId, rxBuf, 8, iSlaveBufSize, 0);
+
+ if(r != KErrNone)
+ {
+ __KTRACE(Kern::Printf("Error Register Rx Buffer, r %d", r));
+ }
+ else
+ {
+ r = RegisterTxBuffer(iChannelId, txBuf, 8, iSlaveBufSize, 0);
+ }
+
+ return r;
+ }
+
+TInt DChannelIicClient::CaptureSlaveChannel(TInt aBufSize, TBool aAsynch /* = EFalse*/)
+ {
+ if(aBufSize > KMaxSlaveTestBufferSize)
+ {
+ return KErrArgument;
+ }
+
+ TInt r = KErrNone;
+ TUint32 slaveBusId = 0;
+ SET_BUS_TYPE(slaveBusId,DIicBusChannel::ESpi);
+ SET_CHAN_NUM(slaveBusId,1);
+
+ // create header
+ const TConfigSpiV01 TestHeader =
+ {
+ ESpiWordWidth_8, //iWordWidth
+ 260000, //iClkSpeed
+ ESpiPolarityLowRisingEdge, //iClkMode
+ 500, // iTimeoutPeriod
+ EBigEndian, // iEndianness
+ EMsbFirst, //iBitOrder
+ 0, //iTransactionWaitCycles
+ ESpiCSPinActiveLow //iCsPinActiveMode
+ };
+
+ TPckgBuf<TConfigSpiV01> header(TestHeader);
+
+ // create callback objects for slave tests..
+ if (!iSlaveCallback)
+ {
+ iSlaveCallback = new TIicBusSlaveCallback(SlaveCallbackFunc, (TAny*) this, iDfcQue, 0);
+ }
+
+ if (!iMasterCallback)
+ {
+ iMasterCallback = new TIicBusCallback(MasterCallbackFunc, (TAny*) this, iDfcQue, 0);
+ }
+
+ if (!(iSlaveCallback && iMasterCallback))
+ {
+ if(iSlaveCallback)
+ {
+ delete iSlaveCallback;
+ }
+
+ if(iMasterCallback)
+ {
+ delete iMasterCallback;
+ }
+ return KErrNoMemory;
+ }
+
+ TInt channelId = 0;
+ // capture channel..
+ r = CaptureChannel(slaveBusId, &header, iSlaveCallback, channelId, aAsynch);
+ if (r != KErrNone)
+ {
+ __KTRACE(Kern::Printf("Error capturing the channel, r %d", r));
+ }
+ else
+ {
+ iSlaveBufSize = aBufSize;
+
+ if(!aAsynch)
+ {
+ iChannelId = channelId;
+ __KTRACE(Kern::Printf("channelId %d", iChannelId));
+ r = RegisterSlaveBuffers();
+ }
+ }
+
+ return r;
+ }
+
+TInt DChannelIicClient::ReleaseSlaveChannel()
+ {
+ TInt r = KErrNone;
+ // release the channel
+
+ if (iChannelId)
+ {
+ r = ReleaseChannel(iChannelId);
+ if (r == KErrNone)
+ {
+ iChannelId = 0;
+ if(iSlaveCallback)
+ {
+ delete iSlaveCallback;
+ iSlaveCallback = NULL;
+ }
+
+ if(iMasterCallback)
+ {
+ delete iMasterCallback;
+ iMasterCallback = NULL;
+ }
+ }
+ else
+ {
+ __KTRACE(Kern::Printf("Error releasing the channel, r %d", r));
+ }
+ }
+ // else // if the channel was released already - silently return KErrNone..
+
+ return r;
+ }
+
+#ifdef _DEBUG
+void PrintTrigger(TInt aTrigger)
+ {
+ Kern::Printf("\naReturn:");
+ if(aTrigger & ETxAllBytes){Kern::Printf("ETxAllBytes");}
+ if(aTrigger & ETxOverrun){Kern::Printf("ETxOverrun");}
+ if(aTrigger & ETxUnderrun){Kern::Printf("ETxUnderrun");}
+
+ if(aTrigger & ERxAllBytes){Kern::Printf("ERxAllBytes");}
+ if(aTrigger & ERxOverrun){Kern::Printf("ERxOverrun");}
+ if(aTrigger & ERxUnderrun){Kern::Printf("ERxUnderrun");}
+
+ if(aTrigger & EGeneralBusError){Kern::Printf("EGeneralBusError");}
+ if(aTrigger & EAsyncCaptChan){Kern::Printf("EAsyncCaptChan");}
+
+ Kern::Printf("\n");
+ }
+#endif
+
+
+void DChannelIicClient::SlaveCallbackFunc(TInt aChannelId, TInt aReturn,
+ TInt aTrigger, TInt16 aRxWords, TInt16 aTxWords, TAny* aParam)
+ {
+ __KTRACE(Kern::Printf("SlaveClientCallbackFunc(),aChannelId=0x%x,aReturn=%d,aTrigger=0x%x,aRxWords=0x%x,aTxWords=0x%x,aParam=0x%x\n",aChannelId,aReturn,aTrigger,aRxWords,aTxWords,aParam));
+
+ DChannelIicClient* aClient = (DChannelIicClient*) aParam;
+ if(aClient)
+ {
+ if(aTrigger & (EAsyncCaptChan))
+ {
+ if(aReturn == KErrCompletion)
+ {
+ aClient->iChannelId = aChannelId;
+ __KTRACE(Kern::Printf("channelId %d", aChannelId));
+ TInt r = aClient->RegisterSlaveBuffers();
+ //AsyncCaptChan expects a KErrCompletion returned.
+ //If RegisterSlaveBuffers fails, the error code will be assigned to aReturn,
+ //then passed back to client.
+ if(r != KErrNone)
+ aReturn = r;
+ }
+
+ Kern::RequestComplete(aClient->iClient, aClient->iSlaveReqStatus, aReturn);
+ return;
+ }
+
+ if(aTrigger & (EGeneralBusError))
+ {
+#ifdef _DEBUG
+ Kern::Printf("\n\naRxWords %d", aRxWords);
+ Kern::Printf("aTxWords %d", aTxWords);
+ PrintTrigger(aReturn);
+#endif
+ Kern::RequestComplete(aClient->iClient, aClient->iSlaveReqStatus, KErrGeneral);
+ return;
+ }
+
+ TInt r = KErrNone;
+ // if there was an underrun/overrun
+ if(aTrigger & ETxUnderrun)
+ {
+ TPtr8 txBuf(0, 0);
+
+ txBuf.Set((TUint8*) aClient->iTxBuf.Ptr(), aClient->iTxBuf.MaxLength(), aClient->iTxBuf.MaxLength());
+
+ // use aTxWords as an offset..
+ if(aTxWords + 32 <= KMaxSlaveTestBufferSize)
+ {
+ r = aClient->RegisterTxBuffer(aClient->iChannelId, txBuf, 8, 32, aTxWords);
+ if (r != KErrNone)
+ {
+ Kern::Printf("Error Register Tx Buffer, r %d", r);
+ }
+ else
+ {
+ r = aClient->SetNotificationTrigger(aClient->iChannelId, ETxAllBytes);
+ if (r != KErrNone)
+ {
+ Kern::Printf("Error setting notification trigger, r %d", r);
+ }
+ }
+
+ // updated the buffer - so return..
+ return;
+ }
+ }
+
+ // if we've finished..
+ if(aReturn & (ETxAllBytes | ERxAllBytes))
+ {
+ //PrintTrigger(aReturn);
+ Kern::RequestComplete(aClient->iClient, aClient->iSlaveReqStatus, KErrNone);
+ }
+
+#if 0
+ TInt8* ptr = (TInt8*)aClient->iRxBuf.Ptr();
+ for(TInt i = 0; i < aRxWords; ++i)
+ {
+ Kern::Printf("Rx item %d: %x", i, (TInt8)*(ptr+i));
+ }
+#endif
+
+ if(aTrigger & (/*ERxAllBytes |*/ ETxAllBytes))
+ {
+ Kern::RequestComplete(aClient->iClient, aClient->iSlaveReqStatus, KErrNone);
+ }
+ }
+ else
+ {
+ Kern::RequestComplete(aClient->iClient, aClient->iSlaveReqStatus, KErrGeneral);
+ }
+
+ }
+
+TInt DChannelIicClient::SetSlaveNotificationTrigger(TUint32 aTrigger)
+ {
+ TInt r = KErrNone;
+ __KTRACE(Kern::Printf("DChannelIicClient::SetSlaveNotificationTrigger() aTrigger=0x%x", aTrigger));
+
+ if (!iChannelId)
+ {
+ __KTRACE(Kern::Printf("Channel not captured..Call CaptureSlaveChannel() first.."));
+ return KErrArgument;
+ }
+
+ // ERxAllBytes = 0x01,
+ // ERxUnderrun = 0x02,
+ // ERxOverrun = 0x04,
+ // ETxAllBytes = 0x08,
+ // ETxUnderrun = 0x10,
+ // ETxOverrun = 0x20,
+ // EGeneralBusError = 0x40
+
+ r = SetNotificationTrigger(iChannelId, aTrigger);
+
+ if (r != KErrNone)
+ {
+ __KTRACE(Kern::Printf("Error setting notification trigger, r %d", r));
+ }
+
+ return r;
+ }
+#endif /*SLAVE_MODE*/
+
+// to handle synchronous requests from the client
+TInt DChannelIicClient::DoControl(TInt aId, TAny* a1, TAny* a2)
+ {
+ TInt r = KErrNone;
+ switch (aId)
+ {
+ case RBusCsiTestClient::ETestAudioCodecBeep:
+ {
+#ifdef MASTER_MODE
+ r = TestAudioCodecBeep(0, 7, 3, 5);
+#else/* MASTER_MODE */
+ r = KErrNotSupported;
+#endif/* MASTER_MODE */
+ break;
+ }
+ case RBusCsiTestClient::ETestTransferTimeout:
+ {
+#ifdef MASTER_MODE
+ r = TestTransferTimeout();
+#else/* MASTER_MODE */
+ r = KErrNotSupported;
+#endif/* MASTER_MODE */
+ break;
+ }
+ case RBusCsiTestClient::ETestTestHalfDuplex:
+ {
+#ifdef MASTER_MODE
+ r = TestHalfDuplexTransaction();
+#else /* MASTER_MODE */
+ r = KErrNotSupported;
+#endif /* MASTER_MODE */
+ break;
+ }
+ case RBusCsiTestClient::ETestBulkTransfer:
+ {
+#ifdef MASTER_MODE
+ r = TestBulkTransfer();
+#else/* MASTER_MODE */
+ r = KErrNotSupported;
+#endif/* MASTER_MODE */
+ break;
+ }
+ case RBusCsiTestClient::ETestDuplexTransaction:
+ {
+#ifdef MASTER_MODE
+ r = TestDuplexTransaction();
+#else/* MASTER_MODE */
+ r = KErrNotSupported;
+#endif/* MASTER_MODE */
+ break;
+ }
+ case RBusCsiTestClient::ETestConfigParams:
+ {
+ // This is an asynchronous transaction - so we're using iSpiHeader member
+ // to copy the data from the user.
+#ifdef MASTER_MODE
+ r = Kern::ThreadDesRead(iClient, (TDes8*) a1, *iSpiHeader, 0, KChunkShiftBy0);
+ if(r == KErrNone)
+ {
+ // a2 is a BusConfig value
+ r = TestConfigParams((TInt)a2);
+ }
+#else/* MASTER_MODE */
+ r = KErrNotSupported;
+#endif/* MASTER_MODE */
+ break;
+ }
+ case RBusCsiTestClient::ECaptureSlaveChannel:
+ {
+#ifdef SLAVE_MODE
+ r = CaptureSlaveChannel((TInt)a1);
+#else/* SLAVE_MODE */
+ r = KErrNotSupported;
+#endif/* SLAVE_MODE */
+ break;
+ }
+ case RBusCsiTestClient::EReleaseSlaveChannel:
+ {
+#ifdef SLAVE_MODE
+ r = ReleaseSlaveChannel();
+#else/* SLAVE_MODE */
+ r = KErrNotSupported;
+#endif/* SLAVE_MODE */
+ break;
+ }
+ case RBusCsiTestClient::EQueueOneDuplexTransaction:
+ {
+#ifdef MASTER_MODE
+ r = QueueOneDuplexTransaction((TInt)a1);
+#else/* MASTER_MODE */
+ r = KErrNotSupported;
+#endif/* MASTER_MODE */
+ break;
+ }
+ default:
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::DoControl():Unrecognized value for aId=0x%x\n", aId));
+ r = KErrArgument;
+ break;
+ }
+ }
+ return r;
+ }
+
+// to handle asynchronous requests from the client
+TInt DChannelIicClient::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::DoRequest(aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n",
+ aId, aStatus, a1, a2));
+
+ TInt r = KErrNone;
+ switch (aId)
+ {
+ case RBusCsiTestClient::ETestAsynTransaction:
+ {
+#ifdef MASTER_MODE
+ // Create a header, and copy it's content from the User.
+ // it will be deleted after the transaction is completed.
+ TConfigSpiBufV01* spiHeader = new TConfigSpiBufV01;
+ if(spiHeader)
+ {
+ r = Kern::ThreadDesRead(iClient, (TDes8*) a1, *spiHeader, 0, KChunkShiftBy0);
+ if(r == KErrNone)
+ {
+ // a2 is a BusConfig value
+ r = TestAsynTransaction(aStatus, spiHeader, (TInt) a2);
+ }
+ else
+ {
+ delete spiHeader;
+ }
+ }
+ else
+ {
+ r = KErrNoMemory;
+ }
+#else
+ r = KErrNotSupported;
+#endif/*MASTER_MODE*/
+ break;
+ }
+
+ case (RBusCsiTestClient::ECaptureSlaveChannelAsync):
+ {
+#ifdef SLAVE_MODE
+ // a1 - size
+ iSlaveReqStatus = aStatus;
+ r = CaptureSlaveChannel((TInt) a1, ETrue);
+#else
+ r = KErrNotSupported;
+#endif/*SLAVE_MODE*/
+ break;
+ }
+
+ case (RBusCsiTestClient::ESetSlaveNotificationTrigger):
+ {
+#ifdef SLAVE_MODE
+ // a1 = trigger
+ iSlaveReqStatus = aStatus;
+ r = SetSlaveNotificationTrigger((TUint32) a1);
+#else
+ r = KErrNotSupported;
+#endif
+ break;
+ }
+
+ default:
+ {
+ __KTRACE(Kern::Printf("DChannelIicClient::DoRequest(): unrecognized value for aId=0x%x\n", aId));
+ r = KErrArgument;
+ break;
+ }
+ }
+ return r;
+ }
+
+// LDD entry point
+DECLARE_STANDARD_LDD()
+ {
+ return new DDeviceIicClient;
+ }
+