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

Revision:
0:82ff15078322
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/I2S_Rx.cpp	Wed Jan 25 20:32:53 2012 +0000
@@ -0,0 +1,285 @@
+/*---------------------------------------------------------------------------
+
+    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
+//---------------------------------------------------------------------------