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/comms.cpp	Wed Jan 25 20:32:53 2012 +0000
@@ -0,0 +1,328 @@
+/*---------------------------------------------------------------------------
+
+    QRSS Receiver Application
+        
+    by Clayton ZL3TKA/VK1TKA
+    clayton@isnotcrazy.com
+
+    Communications Module
+
+
+---------------------------------------------------------------------------*/
+// include files
+
+#include "comms.h"
+
+// Definitions
+
+#define COMMS_DEBUG     0
+
+// Macros
+
+// Local Data
+
+// Global Data
+
+
+// Function Prototypes
+
+//---------------------------------------------------------------------------
+//  API METHODS
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+//
+//  Initialisation Method
+//
+void TCommunications::Init()
+{
+    eState = ST_START_ETH;
+    iBufferCount = 0;
+    PollTimer.start();
+    CommandTimer.start();
+    uiTestModeInc = 0;
+}
+
+//---------------------------------------------------------------------------
+//
+//  Processing Method
+//      Main state machine
+//
+void TCommunications::Poll()
+{
+    UDPSocketErr udpErr;
+    EthernetErr ethErr;
+    
+    switch ( eState )
+    {
+      case ST_START_ETH:    // Initialise the Ethernet interface
+        EthernetUpLED = 0;
+        RunningLED = 0;
+        ethErr = eth.setup( 25000 );
+        if ( ethErr == ETH_OK ) 
+        {
+            const char * pcHWAddr = eth.getHwAddr();
+            IpAddr ip = eth.getIp();
+            printf("mbed MAC Address is %02X-%02X-%02X-%02X-%02X-%02X\r\n", pcHWAddr[0], pcHWAddr[1], pcHWAddr[2], pcHWAddr[3], pcHWAddr[4], pcHWAddr[5] );
+            printf("mbed IP Address is %d.%d.%d.%d\r\n", ip[0], ip[1], ip[2], ip[3] );
+        } 
+        // Set up UDP
+        ServerSocket.setOnEvent( this, &TCommunications::onUDPSocketEvent );
+        MyPort.setIp( IpAddr() );
+        MyPort.setPort( QRSS_UDP_PORT );
+        ServerSocket.bind( MyPort );
+        udpErr = ServerSocket.bind( MyPort );
+        if ( udpErr != UDPSOCKET_OK )
+        {
+            printf("UDP Bind error %d\r\n", udpErr);
+            break;
+        }
+        // to poll state, and force sending of poll message
+        printf("*POLL_SERVER State*\r\n" );
+        eState = ST_POLL_SERVER;
+        iPPSCount = POLL_MSG_PERIOD;
+        bGotCmnd = false;
+        break;
+
+      case ST_POLL_SERVER:  // Poll the server and wait for it to start the system
+        EthernetUpLED = 1;
+        RunningLED = 0;
+        if ( (iPPSCount>=POLL_MSG_PERIOD) || (PollTimer.read_ms()>POLL_TIMEOUT) )
+        {   // Send a poll message
+            iPPSCount = 0;
+            ServerAddr = dnsService.resolveName( szServerName );
+            if ( ServerAddr.isNull() )
+            {
+                printf("DNS Failed - *START_ETH State*\r\n" );
+                eState = ST_START_ETH;
+                break;
+            }
+            ServerPort.setIp( ServerAddr );
+            ServerPort.setPort( QRSS_UDP_PORT );
+            if ( !SendPollMessage() )
+            {
+                printf("*START_ETH State*\r\n" );
+                eState = ST_START_ETH;
+                break;
+            }
+        }
+        if ( bGotCmnd )
+        {
+            bGotCmnd = false;
+            if ( uiCommand!=0 )
+            {   // start
+                uiNCOPhaseInc = uiNCO;
+                uiTestModeInc = uiTestOsc;
+                printf("*RUNNING State*\r\n" );
+                eState = ST_RUNNING;
+                iBufferCount = 0;
+                CommandTimer.reset();
+            }
+        }
+        break;
+        
+      case ST_RUNNING:       // Running - transfer data to the server
+        EthernetUpLED = 1;
+        RunningLED = 1;
+        if ( (iPPSCount>=POLL_MSG_PERIOD) || (PollTimer.read_ms()>POLL_TIMEOUT) )
+        {   // Send a poll message
+            iPPSCount = 0;
+            if ( !SendPollMessage() )
+            {
+                printf("*START_ETH State*\r\n" );
+                eState = ST_START_ETH;
+                break;
+            }
+        }
+        if ( bGotCmnd )
+        {
+            bGotCmnd = false;
+            CommandTimer.reset();
+            if ( uiCommand==0 )
+            {   // stop
+                printf("*POLL_SERVER State*\r\n" );
+                eState = ST_POLL_SERVER;
+                iPPSCount = POLL_MSG_PERIOD;
+                iBufferCount = 0;
+            }
+        }
+        if ( CommandTimer.read_ms()>RUNNING_TIMEOUT )
+        {
+            printf("Timeout - *POLL_SERVER State*\r\n" );
+            eState = ST_POLL_SERVER;
+            iPPSCount = POLL_MSG_PERIOD;
+            iBufferCount = 0;
+        }
+        break;
+    }
+
+}
+
+//---------------------------------------------------------------------------
+//
+//  RecordPPSTimestamps Method
+//      Records timestamps of events (1PPS or capture of LO divider)
+//
+void TCommunications::RecordPPSTimestamps( uint32_t uiPPSCapture, uint32_t uiLOscCapture, 
+                                            TGPSController::TGPSData &GPSInfo )
+{
+    int ii;
+
+    #if COMMS_DEBUG>0
+      printf( "PPS-Timestamp:Time %d  Count %d  PPSCap %u  LOCap %u    PPS %u   LO %u\r\n", 
+                    LastGPSInfo.iGPSTimeSeconds, iPPSCount, uiPPSCapture, uiLOscCapture,
+                    uiPPSCapture-auiPPSCaptures[0], uiLOscCapture-auiLOscCaptures[0]    );
+    #endif                            
+
+    // clear the captures if GPS is non-operation
+    if ( GPSInfo.iGPSQuality<=0 )
+    {   // GPS is offline
+        uiPPSCapture = 0;
+        uiLOscCapture = 0;
+    }
+
+    // shuffle the queue along
+    for ( ii=7; ii>0; ii-- )
+    {
+        auiPPSCaptures[ii] = auiPPSCaptures[ii-1];
+        auiLOscCaptures[ii] = auiLOscCaptures[ii-1];
+    }
+    // record newest data
+    auiPPSCaptures[0] = uiPPSCapture;
+    auiLOscCaptures[0] = uiLOscCapture;
+    LastGPSInfo = GPSInfo;
+
+    // count event
+    iPPSCount++;
+
+}
+
+//---------------------------------------------------------------------------
+//
+//  Pass sample data for sending. Send when buffer is full
+//
+void TCommunications::SendSamples( uint32_t uiTimestamp, TDataSample sSample )
+{
+    if ( eState!=ST_RUNNING )
+        return;
+
+    if ( iBufferCount==0 )
+    {   // Build buffer header
+        pucBuffDataPtr = (uint8_t *)auiDataBuffer;
+        WriteWord( pucBuffDataPtr, COMM_DATA_MSG,  iBufferCount );
+        WriteWord( pucBuffDataPtr, uiTimestamp,  iBufferCount );
+    }
+    // append data
+    *((TDataSample*)pucBuffDataPtr) = sSample;
+    pucBuffDataPtr += SAMPLE_SET_SIZE;
+    iBufferCount += SAMPLE_SET_SIZE;
+    // send buffer when full
+    if ( iBufferCount>=COMMS_DATABUFF_SIZE )
+    {   // send message
+        int iRet = ServerSocket.sendto( (char *)auiDataBuffer ,iBufferCount, &ServerPort );
+        if ( iRet!=iBufferCount )
+            printf("Sent Error - %d\r\n", iRet );
+        iBufferCount = 0;
+    }
+}
+
+//---------------------------------------------------------------------------
+//  PRIVATE METHODS
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+//
+//  UDP Callback Method
+//
+void TCommunications::onUDPSocketEvent( UDPSocketEvent evnt )
+{
+    if ( evnt==UDPSOCKET_READABLE ) 
+    {
+        uint8_t aucInBf[COMMS_CNTRLBUFF_SIZE];
+        Host    FromHost;
+        int     iLen;
+        while ( 1 )
+        {
+            iLen = ServerSocket.recvfrom( (char *)aucInBf, COMMS_CNTRLBUFF_SIZE, &FromHost );
+            if ( iLen<=0 )
+                break;
+            if ( iLen!=COMM_CMND_MSG_LENGTH )
+                continue;
+            if ( ReadWord(&(aucInBf[0]))!=COMM_CMND_MSG )
+                continue;
+            if ( ReadWord(&(aucInBf[4]))!=COMM_MSG_VERSION )
+                continue;
+            // have a real message!
+            uiCommand = ReadWord( &(aucInBf[8]) );
+            uiNCO = ReadWord( &(aucInBf[12]) );
+            uiTestOsc = ReadWord( &(aucInBf[16]) );
+            bGotCmnd = true;
+            #if COMMS_DEBUG>0
+             printf("Command %d\r\n", uiCommand );
+             printf("NCO %d\r\n", uiNCO );
+             printf("Test %d\r\n", uiTestOsc );
+            #endif
+        }
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+//  Send a UDP Poll Message
+//
+bool TCommunications::SendPollMessage()
+{
+    // Build poll message
+    uint8_t     aucPollBuffer[150];
+    uint8_t    *pucPtr = aucPollBuffer;
+    int         iLen = 0; 
+    int         iRet;
+
+    // reset the backup timer
+    PollTimer.reset();
+    
+    // Build Message
+    WriteWord( pucPtr, COMM_POLL_MSG,                       iLen );
+    WriteWord( pucPtr, COMM_MSG_VERSION,                    iLen );
+    WriteWord( pucPtr, COMM_MSG_HW_ID,                      iLen );
+    WriteWord( pucPtr, COMM_MSG_SW_VERSION,                 iLen );
+    WriteWord( pucPtr, LastGPSInfo.iGPSQuality,             iLen );
+    WriteWord( pucPtr, LastGPSInfo.iGPSSatellites,          iLen );
+    WriteWord( pucPtr, LastGPSInfo.iGPSTimeSeconds,         iLen );
+    WriteWord( pucPtr, LastGPSInfo.iGPSLatMicroDegrees,     iLen );
+    WriteWord( pucPtr, LastGPSInfo.iGPSLongMicroDegrees,    iLen );
+    WriteWord( pucPtr, LastGPSInfo.iGPSAltitudeMeters,      iLen );
+    WriteWord( pucPtr, COMM_MSG_REF_CLOCK,                  iLen );
+    WriteWord( pucPtr, COMM_MSG_RF_MIXER,                   iLen );
+    WriteWord( pucPtr, COMM_MSG_SAMPLE_CLOCK,               iLen );
+    WriteWord( pucPtr, COMM_MSG_SAMPLE_DIVIDER,             iLen );
+    WriteWord( pucPtr, auiPPSCaptures[0],                   iLen );
+    WriteWord( pucPtr, auiPPSCaptures[1],                   iLen );
+    WriteWord( pucPtr, auiPPSCaptures[2],                   iLen );
+    WriteWord( pucPtr, auiPPSCaptures[3],                   iLen );
+    WriteWord( pucPtr, auiPPSCaptures[4],                   iLen );
+    WriteWord( pucPtr, auiPPSCaptures[5],                   iLen );
+    WriteWord( pucPtr, auiPPSCaptures[6],                   iLen );
+    WriteWord( pucPtr, auiPPSCaptures[7],                   iLen );
+    WriteWord( pucPtr, auiLOscCaptures[0],                  iLen );
+    WriteWord( pucPtr, auiLOscCaptures[1],                  iLen );
+    WriteWord( pucPtr, auiLOscCaptures[2],                  iLen );
+    WriteWord( pucPtr, auiLOscCaptures[3],                  iLen );
+    WriteWord( pucPtr, auiLOscCaptures[4],                  iLen );
+    WriteWord( pucPtr, auiLOscCaptures[5],                  iLen );
+    WriteWord( pucPtr, auiLOscCaptures[6],                  iLen );
+    WriteWord( pucPtr, auiLOscCaptures[7],                  iLen );
+    memcpy( pucPtr, COMM_MSG_NAME, COMM_MSGNAME_LEN );
+    pucPtr += COMM_MSGNAME_LEN;
+    iLen += COMM_MSGNAME_LEN;
+        
+    // send message
+    iRet = ServerSocket.sendto( (char *)aucPollBuffer ,iLen, &ServerPort );
+    if ( iRet < 0 )
+        return false;
+    return true;
+}
+
+//---------------------------------------------------------------------------
+//  END
+//---------------------------------------------------------------------------