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

Committer:
claytong
Date:
Wed Jan 25 20:32:53 2012 +0000
Revision:
0:82ff15078322
1.0 (initial public release)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
claytong 0:82ff15078322 1 /*---------------------------------------------------------------------------
claytong 0:82ff15078322 2
claytong 0:82ff15078322 3 QRSS Receiver Application
claytong 0:82ff15078322 4
claytong 0:82ff15078322 5 by Clayton ZL3TKA/VK1TKA
claytong 0:82ff15078322 6 clayton@isnotcrazy.com
claytong 0:82ff15078322 7
claytong 0:82ff15078322 8 I2S Hardware Driver Routines
claytong 0:82ff15078322 9
claytong 0:82ff15078322 10 ---------------------------------------------------------------------------*/
claytong 0:82ff15078322 11 // include files
claytong 0:82ff15078322 12
claytong 0:82ff15078322 13 #include "I2S_Rx.h"
claytong 0:82ff15078322 14
claytong 0:82ff15078322 15 // Definitions
claytong 0:82ff15078322 16
claytong 0:82ff15078322 17 // (bit 12) Source burst size = 1
claytong 0:82ff15078322 18 // (bit 15) Destination burst size = 1
claytong 0:82ff15078322 19 // (bit 18) Source Width = 32 bits
claytong 0:82ff15078322 20 // (bit 21) Destination Width = 32 bits
claytong 0:82ff15078322 21 // (bit 26) Source Increment
claytong 0:82ff15078322 22 // (bit 27) Destination Increment
claytong 0:82ff15078322 23 // (bit 31) enable INT
claytong 0:82ff15078322 24 #define DMA_CONTROL ( (0x00 << 12) | (0x00 << 15) | (0x02 << 18) | (0x02 << 21) | (0 << 26) | (1 << 27) | (1U << 31) )
claytong 0:82ff15078322 25 #define DMA_TC_MASK 0xFFF
claytong 0:82ff15078322 26
claytong 0:82ff15078322 27 // Macros
claytong 0:82ff15078322 28
claytong 0:82ff15078322 29 // Local Data
claytong 0:82ff15078322 30
claytong 0:82ff15078322 31 // pointer to receiver - for use by IRQ routine
claytong 0:82ff15078322 32 static TI2SReceiver * pI2SReceiver;
claytong 0:82ff15078322 33
claytong 0:82ff15078322 34 // Global Data
claytong 0:82ff15078322 35
claytong 0:82ff15078322 36 // Function Prototypes
claytong 0:82ff15078322 37
claytong 0:82ff15078322 38 //---------------------------------------------------------------------------
claytong 0:82ff15078322 39 // IRQ Routines
claytong 0:82ff15078322 40 //---------------------------------------------------------------------------
claytong 0:82ff15078322 41
claytong 0:82ff15078322 42 //---------------------------------------------------------------------------
claytong 0:82ff15078322 43 //
claytong 0:82ff15078322 44 // DMA Int routine - test and call the object handler if appropriate
claytong 0:82ff15078322 45 //
claytong 0:82ff15078322 46 void DMA_IRQHandler(void)
claytong 0:82ff15078322 47 {
claytong 0:82ff15078322 48 uint32_t regVal;
claytong 0:82ff15078322 49
claytong 0:82ff15078322 50 // read Int TC (terminal count) Status register
claytong 0:82ff15078322 51 regVal = LPC_GPDMA->DMACIntTCStat;
claytong 0:82ff15078322 52 // clear interrupts
claytong 0:82ff15078322 53 LPC_GPDMA->DMACIntTCClear |= regVal;
claytong 0:82ff15078322 54 // test for receiver DMA channel int
claytong 0:82ff15078322 55 if ( regVal&1 )
claytong 0:82ff15078322 56 pI2SReceiver->DMA_Interrupt();
claytong 0:82ff15078322 57 }
claytong 0:82ff15078322 58
claytong 0:82ff15078322 59 //---------------------------------------------------------------------------
claytong 0:82ff15078322 60 // I2S RECEIVER FUNCTIONS
claytong 0:82ff15078322 61 //---------------------------------------------------------------------------
claytong 0:82ff15078322 62
claytong 0:82ff15078322 63 //---------------------------------------------------------------------------
claytong 0:82ff15078322 64 //
claytong 0:82ff15078322 65 // TI2SReceiver constructor
claytong 0:82ff15078322 66 //
claytong 0:82ff15078322 67 TI2SReceiver::TI2SReceiver( TBufferPool &BuffPol ) :
claytong 0:82ff15078322 68 EmptyBuffersPool( BuffPol ),
claytong 0:82ff15078322 69 bRunning( false ),
claytong 0:82ff15078322 70 ulBufferCount( 0 ),
claytong 0:82ff15078322 71 ulBufferAllocations( 0 ),
claytong 0:82ff15078322 72 ulBufferFailures( 0 )
claytong 0:82ff15078322 73 {
claytong 0:82ff15078322 74 // Set up I2S pointer for the IRQ routine
claytong 0:82ff15078322 75 pI2SReceiver = this;
claytong 0:82ff15078322 76
claytong 0:82ff15078322 77 // Enable I2S in the PCONP register (I2S is disabled on reset)
claytong 0:82ff15078322 78 LPC_SC->PCONP |= (1 << 27);
claytong 0:82ff15078322 79
claytong 0:82ff15078322 80 // Connect the I2S sigals to port pins (P0.23 - P0.25)
claytong 0:82ff15078322 81 LPC_PINCON->PINSEL1 &= ~( (0x3<<14) | (0x3<<16) | (0x3<<18) );
claytong 0:82ff15078322 82 LPC_PINCON->PINSEL1 |= ( (0x2<<14) | (0x2<<16) | (0x2<<18) );
claytong 0:82ff15078322 83 }
claytong 0:82ff15078322 84
claytong 0:82ff15078322 85 //---------------------------------------------------------------------------
claytong 0:82ff15078322 86 //
claytong 0:82ff15078322 87 // TI2SReceiver Initialise operation
claytong 0:82ff15078322 88 //
claytong 0:82ff15078322 89 void TI2SReceiver::Init()
claytong 0:82ff15078322 90 {
claytong 0:82ff15078322 91 // Enable I2S in the PCONP register (I2S is disabled on reset)
claytong 0:82ff15078322 92 LPC_SC->PCONP |= (1 << 27);
claytong 0:82ff15078322 93
claytong 0:82ff15078322 94 // Connect the I2S sigals to port pins (P0.23 - P0.25)
claytong 0:82ff15078322 95 LPC_PINCON->PINSEL1 &= ~( (0x3<<14) | (0x3<<16) | (0x3<<18) );
claytong 0:82ff15078322 96 LPC_PINCON->PINSEL1 |= ( (0x2<<14) | (0x2<<16) | (0x2<<18) );
claytong 0:82ff15078322 97
claytong 0:82ff15078322 98 // Stop reception
claytong 0:82ff15078322 99 LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6);
claytong 0:82ff15078322 100
claytong 0:82ff15078322 101 // Disable DMA
claytong 0:82ff15078322 102 LPC_GPDMACH0->DMACCControl = 0;
claytong 0:82ff15078322 103
claytong 0:82ff15078322 104 // Initialise DMA
claytong 0:82ff15078322 105 LPC_SC->PCONP |= (1 << 29); // Enable GPDMA clock
claytong 0:82ff15078322 106 LPC_GPDMA->DMACConfig = 0x01; // Enable DMA channels, little endian
claytong 0:82ff15078322 107 while ( !(LPC_GPDMA->DMACConfig & 0x01) ) ;
claytong 0:82ff15078322 108
claytong 0:82ff15078322 109 // Set up DMA Int routine
claytong 0:82ff15078322 110 NVIC_SetVector( DMA_IRQn, (uint32_t)DMA_IRQHandler );
claytong 0:82ff15078322 111 NVIC_EnableIRQ( DMA_IRQn );
claytong 0:82ff15078322 112 }
claytong 0:82ff15078322 113
claytong 0:82ff15078322 114 //---------------------------------------------------------------------------
claytong 0:82ff15078322 115 //
claytong 0:82ff15078322 116 // TI2SReceiver Start operation
claytong 0:82ff15078322 117 //
claytong 0:82ff15078322 118 void TI2SReceiver::Start()
claytong 0:82ff15078322 119 {
claytong 0:82ff15078322 120 // Stop reception
claytong 0:82ff15078322 121 LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6);
claytong 0:82ff15078322 122 LPC_GPDMACH0->DMACCConfig = 0;
claytong 0:82ff15078322 123 LPC_GPDMACH0->DMACCControl = 0;
claytong 0:82ff15078322 124 bRunning = false;
claytong 0:82ff15078322 125 LPC_GPDMA->DMACIntTCClear = 0x01; // clear DMA0 flags
claytong 0:82ff15078322 126 LPC_GPDMA->DMACIntErrClr = 0x01;
claytong 0:82ff15078322 127
claytong 0:82ff15078322 128 // Enable DMA
claytong 0:82ff15078322 129 // Get new buffer and set up the DMA
claytong 0:82ff15078322 130 StartDMATransfer();
claytong 0:82ff15078322 131
claytong 0:82ff15078322 132 // Slave receive mode. 32 bit data, stereo
claytong 0:82ff15078322 133 LPC_I2S->I2SDMA1 = (0x1<<0) | (0x02<<8); // channel 1 = Rx DMA
claytong 0:82ff15078322 134 LPC_I2S->I2SRXMODE = 0;
claytong 0:82ff15078322 135 LPC_I2S->I2SDAI = 0x03 | (0x1<<5) | (0x1F<<6);
claytong 0:82ff15078322 136 bRunning = true;
claytong 0:82ff15078322 137 }
claytong 0:82ff15078322 138
claytong 0:82ff15078322 139 //---------------------------------------------------------------------------
claytong 0:82ff15078322 140 //
claytong 0:82ff15078322 141 // TI2SReceiver Stop operation
claytong 0:82ff15078322 142 //
claytong 0:82ff15078322 143 void TI2SReceiver::Stop()
claytong 0:82ff15078322 144 {
claytong 0:82ff15078322 145 bRunning = false;
claytong 0:82ff15078322 146
claytong 0:82ff15078322 147 // Stop reception
claytong 0:82ff15078322 148 LPC_I2S->I2SDMA1 = 0;
claytong 0:82ff15078322 149 LPC_I2S->I2SDAI = 0x03 | (0x1<<3) | (0x1<<4) | (0x1<<5) | (0x1F<<6);
claytong 0:82ff15078322 150 LPC_GPDMACH0->DMACCConfig = 0;
claytong 0:82ff15078322 151 LPC_GPDMACH0->DMACCControl = 0;
claytong 0:82ff15078322 152
claytong 0:82ff15078322 153 // clear out buffers
claytong 0:82ff15078322 154 ReceivedBuffers.Flush();
claytong 0:82ff15078322 155 CurrentRxBuffer.Release();
claytong 0:82ff15078322 156 }
claytong 0:82ff15078322 157
claytong 0:82ff15078322 158 //---------------------------------------------------------------------------
claytong 0:82ff15078322 159 //
claytong 0:82ff15078322 160 // Debug routine -
claytong 0:82ff15078322 161 // Read samples from the I2S by polling it
claytong 0:82ff15078322 162 // Returns number of samples read
claytong 0:82ff15078322 163 //
claytong 0:82ff15078322 164 int TI2SReceiver::PolledRead( int32_t *piBuffer, int iLen )
claytong 0:82ff15078322 165 {
claytong 0:82ff15078322 166 int iCnt = 0;
claytong 0:82ff15078322 167 while ( iLen>0 )
claytong 0:82ff15078322 168 {
claytong 0:82ff15078322 169 // wait for something in the FIFO
claytong 0:82ff15078322 170 if ( ((LPC_I2S->I2SSTATE>>8)&0xF)==0 )
claytong 0:82ff15078322 171 continue;
claytong 0:82ff15078322 172 // Read it out to the buffer
claytong 0:82ff15078322 173 *piBuffer = LPC_I2S->I2SRXFIFO;
claytong 0:82ff15078322 174 piBuffer++;
claytong 0:82ff15078322 175 iLen--;
claytong 0:82ff15078322 176 iCnt++;
claytong 0:82ff15078322 177 }
claytong 0:82ff15078322 178 return iCnt;
claytong 0:82ff15078322 179 }
claytong 0:82ff15078322 180
claytong 0:82ff15078322 181 //---------------------------------------------------------------------------
claytong 0:82ff15078322 182 //
claytong 0:82ff15078322 183 // Debug routine -
claytong 0:82ff15078322 184 // Read status register
claytong 0:82ff15078322 185 //
claytong 0:82ff15078322 186 uint32_t TI2SReceiver::Status()
claytong 0:82ff15078322 187 {
claytong 0:82ff15078322 188 return LPC_I2S->I2SSTATE;
claytong 0:82ff15078322 189 }
claytong 0:82ff15078322 190 //---------------------------------------------------------------------------
claytong 0:82ff15078322 191 //
claytong 0:82ff15078322 192 // Debug routine -
claytong 0:82ff15078322 193 // Report Status
claytong 0:82ff15078322 194 //
claytong 0:82ff15078322 195 void TI2SReceiver::Report()
claytong 0:82ff15078322 196 {
claytong 0:82ff15078322 197 printf( "C-%d\r\n", ulBufferCount );
claytong 0:82ff15078322 198 printf( "F-%d\r\n", ulBufferFailures );
claytong 0:82ff15078322 199 /*
claytong 0:82ff15078322 200 printf( "I2S Buffers Counter - %d\r\n", ulBufferCount );
claytong 0:82ff15078322 201 printf( "I2S Buffer Failures - %d\r\n", ulBufferFailures );
claytong 0:82ff15078322 202 printf( "I2S Buffer Allocations - %d\r\n", ulBufferAllocations );
claytong 0:82ff15078322 203 printf( "I2S Status Register: 0x%08X\r\n", LPC_I2S->I2SSTATE );
claytong 0:82ff15078322 204 printf( "I2S DMA1 Register: 0x%08X\r\n", LPC_I2S->I2SDMA1 );
claytong 0:82ff15078322 205 printf( "I2S DMA2 Register: 0x%08X\r\n", LPC_I2S->I2SDMA2 );
claytong 0:82ff15078322 206 printf( "DMA Enabled Register: 0x%08X\r\n", LPC_GPDMA->DMACEnbldChns );
claytong 0:82ff15078322 207 printf( "DMA TC Status Register: 0x%08X\r\n", LPC_GPDMA->DMACIntTCStat );
claytong 0:82ff15078322 208 printf( "DMA Err Status Register: 0x%08X\r\n", LPC_GPDMA->DMACIntErrStat );
claytong 0:82ff15078322 209 printf( "DMA Config Register: 0x%08X\r\n", LPC_GPDMA->DMACConfig );
claytong 0:82ff15078322 210 printf( "DMA0 Control Register: 0x%08X\r\n", LPC_GPDMACH0->DMACCControl );
claytong 0:82ff15078322 211 printf( "DMA0 Config Register: 0x%08X\r\n", LPC_GPDMACH0->DMACCConfig );
claytong 0:82ff15078322 212 */
claytong 0:82ff15078322 213 }
claytong 0:82ff15078322 214
claytong 0:82ff15078322 215 //---------------------------------------------------------------------------
claytong 0:82ff15078322 216 //
claytong 0:82ff15078322 217 // DMA Interrupt Routine
claytong 0:82ff15078322 218 //
claytong 0:82ff15078322 219 void TI2SReceiver::DMA_Interrupt( )
claytong 0:82ff15078322 220 {
claytong 0:82ff15078322 221 // exit if receiver is not running
claytong 0:82ff15078322 222 if ( !bRunning )
claytong 0:82ff15078322 223 return;
claytong 0:82ff15078322 224
claytong 0:82ff15078322 225 // Queue current buffer
claytong 0:82ff15078322 226 CurrentRxBuffer.SetLength( 99999 ); // set length to full buffer size
claytong 0:82ff15078322 227 ReceivedBuffers.Write( CurrentRxBuffer );
claytong 0:82ff15078322 228 ulBufferCount++;
claytong 0:82ff15078322 229
claytong 0:82ff15078322 230 // Get new buffer and set up the DMA
claytong 0:82ff15078322 231 StartDMATransfer();
claytong 0:82ff15078322 232 }
claytong 0:82ff15078322 233
claytong 0:82ff15078322 234 //---------------------------------------------------------------------------
claytong 0:82ff15078322 235 //
claytong 0:82ff15078322 236 // Start a new DMA transfer
claytong 0:82ff15078322 237 //
claytong 0:82ff15078322 238 void TI2SReceiver::StartDMATransfer()
claytong 0:82ff15078322 239 {
claytong 0:82ff15078322 240 int32_t *pDataPtr;
claytong 0:82ff15078322 241 int iBufSize;
claytong 0:82ff15078322 242
claytong 0:82ff15078322 243 // uses DMA0 and sets it up with new buffer (or a dummy buffer if none available)
claytong 0:82ff15078322 244 // DMA channel 0 Source is I2S DMA1 = RX FIFO, Destination is memory
claytong 0:82ff15078322 245
claytong 0:82ff15078322 246 // count DMA allocations
claytong 0:82ff15078322 247 ulBufferAllocations++;
claytong 0:82ff15078322 248
claytong 0:82ff15078322 249 // get a buffer
claytong 0:82ff15078322 250 pDataPtr = NULL;
claytong 0:82ff15078322 251 if ( EmptyBuffersPool.Create(CurrentRxBuffer) )
claytong 0:82ff15078322 252 { // got a buffer
claytong 0:82ff15078322 253 pDataPtr = (int32_t *)(CurrentRxBuffer.SamplePtr());
claytong 0:82ff15078322 254 iBufSize = CurrentRxBuffer.Size() * 2; // size = samples*2 (samples are I/Q)
claytong 0:82ff15078322 255 CurrentRxBuffer.Timestamp( LPC_TIM2->TC ); // Set timestamp
claytong 0:82ff15078322 256 }
claytong 0:82ff15078322 257 // check for buffer
claytong 0:82ff15078322 258 if ( pDataPtr==NULL )
claytong 0:82ff15078322 259 { // failed to get a buffer - use the dumy buffer
claytong 0:82ff15078322 260 ulBufferFailures++;
claytong 0:82ff15078322 261 pDataPtr = aulDummyBuffer;
claytong 0:82ff15078322 262 iBufSize = I2S_DUMMY_BUFFER_SIZE;
claytong 0:82ff15078322 263 }
claytong 0:82ff15078322 264
claytong 0:82ff15078322 265 // clear any ints
claytong 0:82ff15078322 266 LPC_GPDMA->DMACIntTCClear = 0x01; // clear DMA0 flags
claytong 0:82ff15078322 267 LPC_GPDMA->DMACIntErrClr = 0x01;
claytong 0:82ff15078322 268
claytong 0:82ff15078322 269 // write source addr
claytong 0:82ff15078322 270 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)(&(LPC_I2S->I2SRXFIFO));
claytong 0:82ff15078322 271
claytong 0:82ff15078322 272 // write destination
claytong 0:82ff15078322 273 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)pDataPtr;
claytong 0:82ff15078322 274
claytong 0:82ff15078322 275 // write LL address - use 0 for single transfer
claytong 0:82ff15078322 276 LPC_GPDMACH0->DMACCLLI = 0;
claytong 0:82ff15078322 277
claytong 0:82ff15078322 278 // write control & config
claytong 0:82ff15078322 279 LPC_GPDMACH0->DMACCControl = (iBufSize & DMA_TC_MASK) | DMA_CONTROL;
claytong 0:82ff15078322 280 LPC_GPDMACH0->DMACCConfig = 0x08001 | (0x05 << 1) | (0x02 << 11);
claytong 0:82ff15078322 281 }
claytong 0:82ff15078322 282
claytong 0:82ff15078322 283 //---------------------------------------------------------------------------
claytong 0:82ff15078322 284 // END
claytong 0:82ff15078322 285 //---------------------------------------------------------------------------