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
Diff: comms.cpp
- 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 +//---------------------------------------------------------------------------