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
00001 /*--------------------------------------------------------------------------- 00002 00003 QRSS Receiver Application 00004 00005 by Clayton ZL3TKA/VK1TKA 00006 clayton@isnotcrazy.com 00007 00008 I2S Hardware Driver Routines 00009 00010 ---------------------------------------------------------------------------*/ 00011 // include files 00012 00013 #include "I2S_Rx.h" 00014 00015 // Definitions 00016 00017 // (bit 12) Source burst size = 1 00018 // (bit 15) Destination burst size = 1 00019 // (bit 18) Source Width = 32 bits 00020 // (bit 21) Destination Width = 32 bits 00021 // (bit 26) Source Increment 00022 // (bit 27) Destination Increment 00023 // (bit 31) enable INT 00024 #define DMA_CONTROL ( (0x00 << 12) | (0x00 << 15) | (0x02 << 18) | (0x02 << 21) | (0 << 26) | (1 << 27) | (1U << 31) ) 00025 #define DMA_TC_MASK 0xFFF 00026 00027 // Macros 00028 00029 // Local Data 00030 00031 // pointer to receiver - for use by IRQ routine 00032 static TI2SReceiver * pI2SReceiver; 00033 00034 // Global Data 00035 00036 // Function Prototypes 00037 00038 //--------------------------------------------------------------------------- 00039 // IRQ Routines 00040 //--------------------------------------------------------------------------- 00041 00042 //--------------------------------------------------------------------------- 00043 // 00044 // DMA Int routine - test and call the object handler if appropriate 00045 // 00046 void DMA_IRQHandler(void) 00047 { 00048 uint32_t regVal; 00049 00050 // read Int TC (terminal count) Status register 00051 regVal = LPC_GPDMA->DMACIntTCStat; 00052 // clear interrupts 00053 LPC_GPDMA->DMACIntTCClear |= regVal; 00054 // test for receiver DMA channel int 00055 if ( regVal&1 ) 00056 pI2SReceiver->DMA_Interrupt(); 00057 } 00058 00059 //--------------------------------------------------------------------------- 00060 // I2S RECEIVER FUNCTIONS 00061 //--------------------------------------------------------------------------- 00062 00063 //--------------------------------------------------------------------------- 00064 // 00065 // TI2SReceiver constructor 00066 // 00067 TI2SReceiver::TI2SReceiver( TBufferPool &BuffPol ) : 00068 EmptyBuffersPool( BuffPol ), 00069 bRunning( false ), 00070 ulBufferCount( 0 ), 00071 ulBufferAllocations( 0 ), 00072 ulBufferFailures( 0 ) 00073 { 00074 // Set up I2S pointer for the IRQ routine 00075 pI2SReceiver = this; 00076 00077 // Enable I2S in the PCONP register (I2S is disabled on reset) 00078 LPC_SC->PCONP |= (1 << 27); 00079 00080 // Connect the I2S sigals to port pins (P0.23 - P0.25) 00081 LPC_PINCON->PINSEL1 &= ~( (0x3<<14) | (0x3<<16) | (0x3<<18) ); 00082 LPC_PINCON->PINSEL1 |= ( (0x2<<14) | (0x2<<16) | (0x2<<18) ); 00083 } 00084 00085 //--------------------------------------------------------------------------- 00086 // 00087 // TI2SReceiver Initialise operation 00088 // 00089 void TI2SReceiver::Init() 00090 { 00091 // Enable I2S in the PCONP register (I2S is disabled on reset) 00092 LPC_SC->PCONP |= (1 << 27); 00093 00094 // Connect the I2S sigals to port pins (P0.23 - P0.25) 00095 LPC_PINCON->PINSEL1 &= ~( (0x3<<14) | (0x3<<16) | (0x3<<18) ); 00096 LPC_PINCON->PINSEL1 |= ( (0x2<<14) | (0x2<<16) | (0x2<<18) ); 00097 00098 // Stop reception 00099 LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6); 00100 00101 // Disable DMA 00102 LPC_GPDMACH0->DMACCControl = 0; 00103 00104 // Initialise DMA 00105 LPC_SC->PCONP |= (1 << 29); // Enable GPDMA clock 00106 LPC_GPDMA->DMACConfig = 0x01; // Enable DMA channels, little endian 00107 while ( !(LPC_GPDMA->DMACConfig & 0x01) ) ; 00108 00109 // Set up DMA Int routine 00110 NVIC_SetVector( DMA_IRQn, (uint32_t)DMA_IRQHandler ); 00111 NVIC_EnableIRQ( DMA_IRQn ); 00112 } 00113 00114 //--------------------------------------------------------------------------- 00115 // 00116 // TI2SReceiver Start operation 00117 // 00118 void TI2SReceiver::Start() 00119 { 00120 // Stop reception 00121 LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6); 00122 LPC_GPDMACH0->DMACCConfig = 0; 00123 LPC_GPDMACH0->DMACCControl = 0; 00124 bRunning = false; 00125 LPC_GPDMA->DMACIntTCClear = 0x01; // clear DMA0 flags 00126 LPC_GPDMA->DMACIntErrClr = 0x01; 00127 00128 // Enable DMA 00129 // Get new buffer and set up the DMA 00130 StartDMATransfer(); 00131 00132 // Slave receive mode. 32 bit data, stereo 00133 LPC_I2S->I2SDMA1 = (0x1<<0) | (0x02<<8); // channel 1 = Rx DMA 00134 LPC_I2S->I2SRXMODE = 0; 00135 LPC_I2S->I2SDAI = 0x03 | (0x1<<5) | (0x1F<<6); 00136 bRunning = true; 00137 } 00138 00139 //--------------------------------------------------------------------------- 00140 // 00141 // TI2SReceiver Stop operation 00142 // 00143 void TI2SReceiver::Stop() 00144 { 00145 bRunning = false; 00146 00147 // Stop reception 00148 LPC_I2S->I2SDMA1 = 0; 00149 LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6); 00150 LPC_GPDMACH0->DMACCConfig = 0; 00151 LPC_GPDMACH0->DMACCControl = 0; 00152 00153 // clear out buffers 00154 ReceivedBuffers.Flush(); 00155 CurrentRxBuffer.Release(); 00156 } 00157 00158 //--------------------------------------------------------------------------- 00159 // 00160 // Debug routine - 00161 // Read samples from the I2S by polling it 00162 // Returns number of samples read 00163 // 00164 int TI2SReceiver::PolledRead( int32_t *piBuffer, int iLen ) 00165 { 00166 int iCnt = 0; 00167 while ( iLen>0 ) 00168 { 00169 // wait for something in the FIFO 00170 if ( ((LPC_I2S->I2SSTATE>>8)&0xF)==0 ) 00171 continue; 00172 // Read it out to the buffer 00173 *piBuffer = LPC_I2S->I2SRXFIFO; 00174 piBuffer++; 00175 iLen--; 00176 iCnt++; 00177 } 00178 return iCnt; 00179 } 00180 00181 //--------------------------------------------------------------------------- 00182 // 00183 // Debug routine - 00184 // Read status register 00185 // 00186 uint32_t TI2SReceiver::Status() 00187 { 00188 return LPC_I2S->I2SSTATE; 00189 } 00190 //--------------------------------------------------------------------------- 00191 // 00192 // Debug routine - 00193 // Report Status 00194 // 00195 void TI2SReceiver::Report() 00196 { 00197 printf( "C-%d\r\n", ulBufferCount ); 00198 printf( "F-%d\r\n", ulBufferFailures ); 00199 /* 00200 printf( "I2S Buffers Counter - %d\r\n", ulBufferCount ); 00201 printf( "I2S Buffer Failures - %d\r\n", ulBufferFailures ); 00202 printf( "I2S Buffer Allocations - %d\r\n", ulBufferAllocations ); 00203 printf( "I2S Status Register: 0x%08X\r\n", LPC_I2S->I2SSTATE ); 00204 printf( "I2S DMA1 Register: 0x%08X\r\n", LPC_I2S->I2SDMA1 ); 00205 printf( "I2S DMA2 Register: 0x%08X\r\n", LPC_I2S->I2SDMA2 ); 00206 printf( "DMA Enabled Register: 0x%08X\r\n", LPC_GPDMA->DMACEnbldChns ); 00207 printf( "DMA TC Status Register: 0x%08X\r\n", LPC_GPDMA->DMACIntTCStat ); 00208 printf( "DMA Err Status Register: 0x%08X\r\n", LPC_GPDMA->DMACIntErrStat ); 00209 printf( "DMA Config Register: 0x%08X\r\n", LPC_GPDMA->DMACConfig ); 00210 printf( "DMA0 Control Register: 0x%08X\r\n", LPC_GPDMACH0->DMACCControl ); 00211 printf( "DMA0 Config Register: 0x%08X\r\n", LPC_GPDMACH0->DMACCConfig ); 00212 */ 00213 } 00214 00215 //--------------------------------------------------------------------------- 00216 // 00217 // DMA Interrupt Routine 00218 // 00219 void TI2SReceiver::DMA_Interrupt( ) 00220 { 00221 // exit if receiver is not running 00222 if ( !bRunning ) 00223 return; 00224 00225 // Queue current buffer 00226 CurrentRxBuffer.SetLength( 99999 ); // set length to full buffer size 00227 ReceivedBuffers.Write( CurrentRxBuffer ); 00228 ulBufferCount++; 00229 00230 // Get new buffer and set up the DMA 00231 StartDMATransfer(); 00232 } 00233 00234 //--------------------------------------------------------------------------- 00235 // 00236 // Start a new DMA transfer 00237 // 00238 void TI2SReceiver::StartDMATransfer() 00239 { 00240 int32_t *pDataPtr; 00241 int iBufSize; 00242 00243 // uses DMA0 and sets it up with new buffer (or a dummy buffer if none available) 00244 // DMA channel 0 Source is I2S DMA1 = RX FIFO, Destination is memory 00245 00246 // count DMA allocations 00247 ulBufferAllocations++; 00248 00249 // get a buffer 00250 pDataPtr = NULL; 00251 if ( EmptyBuffersPool.Create(CurrentRxBuffer) ) 00252 { // got a buffer 00253 pDataPtr = (int32_t *)(CurrentRxBuffer.SamplePtr()); 00254 iBufSize = CurrentRxBuffer.Size() * 2; // size = samples*2 (samples are I/Q) 00255 CurrentRxBuffer.Timestamp( LPC_TIM2->TC ); // Set timestamp 00256 } 00257 // check for buffer 00258 if ( pDataPtr==NULL ) 00259 { // failed to get a buffer - use the dumy buffer 00260 ulBufferFailures++; 00261 pDataPtr = aulDummyBuffer; 00262 iBufSize = I2S_DUMMY_BUFFER_SIZE; 00263 } 00264 00265 // clear any ints 00266 LPC_GPDMA->DMACIntTCClear = 0x01; // clear DMA0 flags 00267 LPC_GPDMA->DMACIntErrClr = 0x01; 00268 00269 // write source addr 00270 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)(&(LPC_I2S->I2SRXFIFO)); 00271 00272 // write destination 00273 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)pDataPtr; 00274 00275 // write LL address - use 0 for single transfer 00276 LPC_GPDMACH0->DMACCLLI = 0; 00277 00278 // write control & config 00279 LPC_GPDMACH0->DMACCControl = (iBufSize & DMA_TC_MASK) | DMA_CONTROL; 00280 LPC_GPDMACH0->DMACCConfig = 0x08001 | (0x05 << 1) | (0x02 << 11); 00281 } 00282 00283 //--------------------------------------------------------------------------- 00284 // END 00285 //---------------------------------------------------------------------------
Generated on Wed Jul 13 2022 23:08:21 by 1.7.2