QRSS Rx Network receiver. A receiver to sample a segment of RF spectrum and send this data to a server for further processing and display. NXP mbed Design Challenge entry (Honorable Mention). Published in Circuit Cellar, Feb 2012
Dependencies: NetServices mbed DNSResolver
I2S_Rx.cpp
- Committer:
- claytong
- Date:
- 2012-01-25
- Revision:
- 0:82ff15078322
File content as of revision 0:82ff15078322:
/*--------------------------------------------------------------------------- QRSS Receiver Application by Clayton ZL3TKA/VK1TKA clayton@isnotcrazy.com I2S Hardware Driver Routines ---------------------------------------------------------------------------*/ // include files #include "I2S_Rx.h" // Definitions // (bit 12) Source burst size = 1 // (bit 15) Destination burst size = 1 // (bit 18) Source Width = 32 bits // (bit 21) Destination Width = 32 bits // (bit 26) Source Increment // (bit 27) Destination Increment // (bit 31) enable INT #define DMA_CONTROL ( (0x00 << 12) | (0x00 << 15) | (0x02 << 18) | (0x02 << 21) | (0 << 26) | (1 << 27) | (1U << 31) ) #define DMA_TC_MASK 0xFFF // Macros // Local Data // pointer to receiver - for use by IRQ routine static TI2SReceiver * pI2SReceiver; // Global Data // Function Prototypes //--------------------------------------------------------------------------- // IRQ Routines //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // // DMA Int routine - test and call the object handler if appropriate // void DMA_IRQHandler(void) { uint32_t regVal; // read Int TC (terminal count) Status register regVal = LPC_GPDMA->DMACIntTCStat; // clear interrupts LPC_GPDMA->DMACIntTCClear |= regVal; // test for receiver DMA channel int if ( regVal&1 ) pI2SReceiver->DMA_Interrupt(); } //--------------------------------------------------------------------------- // I2S RECEIVER FUNCTIONS //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // // TI2SReceiver constructor // TI2SReceiver::TI2SReceiver( TBufferPool &BuffPol ) : EmptyBuffersPool( BuffPol ), bRunning( false ), ulBufferCount( 0 ), ulBufferAllocations( 0 ), ulBufferFailures( 0 ) { // Set up I2S pointer for the IRQ routine pI2SReceiver = this; // Enable I2S in the PCONP register (I2S is disabled on reset) LPC_SC->PCONP |= (1 << 27); // Connect the I2S sigals to port pins (P0.23 - P0.25) LPC_PINCON->PINSEL1 &= ~( (0x3<<14) | (0x3<<16) | (0x3<<18) ); LPC_PINCON->PINSEL1 |= ( (0x2<<14) | (0x2<<16) | (0x2<<18) ); } //--------------------------------------------------------------------------- // // TI2SReceiver Initialise operation // void TI2SReceiver::Init() { // Enable I2S in the PCONP register (I2S is disabled on reset) LPC_SC->PCONP |= (1 << 27); // Connect the I2S sigals to port pins (P0.23 - P0.25) LPC_PINCON->PINSEL1 &= ~( (0x3<<14) | (0x3<<16) | (0x3<<18) ); LPC_PINCON->PINSEL1 |= ( (0x2<<14) | (0x2<<16) | (0x2<<18) ); // Stop reception LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6); // Disable DMA LPC_GPDMACH0->DMACCControl = 0; // Initialise DMA LPC_SC->PCONP |= (1 << 29); // Enable GPDMA clock LPC_GPDMA->DMACConfig = 0x01; // Enable DMA channels, little endian while ( !(LPC_GPDMA->DMACConfig & 0x01) ) ; // Set up DMA Int routine NVIC_SetVector( DMA_IRQn, (uint32_t)DMA_IRQHandler ); NVIC_EnableIRQ( DMA_IRQn ); } //--------------------------------------------------------------------------- // // TI2SReceiver Start operation // void TI2SReceiver::Start() { // Stop reception LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6); LPC_GPDMACH0->DMACCConfig = 0; LPC_GPDMACH0->DMACCControl = 0; bRunning = false; LPC_GPDMA->DMACIntTCClear = 0x01; // clear DMA0 flags LPC_GPDMA->DMACIntErrClr = 0x01; // Enable DMA // Get new buffer and set up the DMA StartDMATransfer(); // Slave receive mode. 32 bit data, stereo LPC_I2S->I2SDMA1 = (0x1<<0) | (0x02<<8); // channel 1 = Rx DMA LPC_I2S->I2SRXMODE = 0; LPC_I2S->I2SDAI = 0x03 | (0x1<<5) | (0x1F<<6); bRunning = true; } //--------------------------------------------------------------------------- // // TI2SReceiver Stop operation // void TI2SReceiver::Stop() { bRunning = false; // Stop reception LPC_I2S->I2SDMA1 = 0; LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6); LPC_GPDMACH0->DMACCConfig = 0; LPC_GPDMACH0->DMACCControl = 0; // clear out buffers ReceivedBuffers.Flush(); CurrentRxBuffer.Release(); } //--------------------------------------------------------------------------- // // Debug routine - // Read samples from the I2S by polling it // Returns number of samples read // int TI2SReceiver::PolledRead( int32_t *piBuffer, int iLen ) { int iCnt = 0; while ( iLen>0 ) { // wait for something in the FIFO if ( ((LPC_I2S->I2SSTATE>>8)&0xF)==0 ) continue; // Read it out to the buffer *piBuffer = LPC_I2S->I2SRXFIFO; piBuffer++; iLen--; iCnt++; } return iCnt; } //--------------------------------------------------------------------------- // // Debug routine - // Read status register // uint32_t TI2SReceiver::Status() { return LPC_I2S->I2SSTATE; } //--------------------------------------------------------------------------- // // Debug routine - // Report Status // void TI2SReceiver::Report() { printf( "C-%d\r\n", ulBufferCount ); printf( "F-%d\r\n", ulBufferFailures ); /* printf( "I2S Buffers Counter - %d\r\n", ulBufferCount ); printf( "I2S Buffer Failures - %d\r\n", ulBufferFailures ); printf( "I2S Buffer Allocations - %d\r\n", ulBufferAllocations ); printf( "I2S Status Register: 0x%08X\r\n", LPC_I2S->I2SSTATE ); printf( "I2S DMA1 Register: 0x%08X\r\n", LPC_I2S->I2SDMA1 ); printf( "I2S DMA2 Register: 0x%08X\r\n", LPC_I2S->I2SDMA2 ); printf( "DMA Enabled Register: 0x%08X\r\n", LPC_GPDMA->DMACEnbldChns ); printf( "DMA TC Status Register: 0x%08X\r\n", LPC_GPDMA->DMACIntTCStat ); printf( "DMA Err Status Register: 0x%08X\r\n", LPC_GPDMA->DMACIntErrStat ); printf( "DMA Config Register: 0x%08X\r\n", LPC_GPDMA->DMACConfig ); printf( "DMA0 Control Register: 0x%08X\r\n", LPC_GPDMACH0->DMACCControl ); printf( "DMA0 Config Register: 0x%08X\r\n", LPC_GPDMACH0->DMACCConfig ); */ } //--------------------------------------------------------------------------- // // DMA Interrupt Routine // void TI2SReceiver::DMA_Interrupt( ) { // exit if receiver is not running if ( !bRunning ) return; // Queue current buffer CurrentRxBuffer.SetLength( 99999 ); // set length to full buffer size ReceivedBuffers.Write( CurrentRxBuffer ); ulBufferCount++; // Get new buffer and set up the DMA StartDMATransfer(); } //--------------------------------------------------------------------------- // // Start a new DMA transfer // void TI2SReceiver::StartDMATransfer() { int32_t *pDataPtr; int iBufSize; // uses DMA0 and sets it up with new buffer (or a dummy buffer if none available) // DMA channel 0 Source is I2S DMA1 = RX FIFO, Destination is memory // count DMA allocations ulBufferAllocations++; // get a buffer pDataPtr = NULL; if ( EmptyBuffersPool.Create(CurrentRxBuffer) ) { // got a buffer pDataPtr = (int32_t *)(CurrentRxBuffer.SamplePtr()); iBufSize = CurrentRxBuffer.Size() * 2; // size = samples*2 (samples are I/Q) CurrentRxBuffer.Timestamp( LPC_TIM2->TC ); // Set timestamp } // check for buffer if ( pDataPtr==NULL ) { // failed to get a buffer - use the dumy buffer ulBufferFailures++; pDataPtr = aulDummyBuffer; iBufSize = I2S_DUMMY_BUFFER_SIZE; } // clear any ints LPC_GPDMA->DMACIntTCClear = 0x01; // clear DMA0 flags LPC_GPDMA->DMACIntErrClr = 0x01; // write source addr LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)(&(LPC_I2S->I2SRXFIFO)); // write destination LPC_GPDMACH0->DMACCDestAddr = (uint32_t)pDataPtr; // write LL address - use 0 for single transfer LPC_GPDMACH0->DMACCLLI = 0; // write control & config LPC_GPDMACH0->DMACCControl = (iBufSize & DMA_TC_MASK) | DMA_CONTROL; LPC_GPDMACH0->DMACCConfig = 0x08001 | (0x05 << 1) | (0x02 << 11); } //--------------------------------------------------------------------------- // END //---------------------------------------------------------------------------