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 Communications Module
claytong 0:82ff15078322 9
claytong 0:82ff15078322 10
claytong 0:82ff15078322 11 ---------------------------------------------------------------------------*/
claytong 0:82ff15078322 12 // include files
claytong 0:82ff15078322 13
claytong 0:82ff15078322 14 #include "comms.h"
claytong 0:82ff15078322 15
claytong 0:82ff15078322 16 // Definitions
claytong 0:82ff15078322 17
claytong 0:82ff15078322 18 #define COMMS_DEBUG 0
claytong 0:82ff15078322 19
claytong 0:82ff15078322 20 // Macros
claytong 0:82ff15078322 21
claytong 0:82ff15078322 22 // Local Data
claytong 0:82ff15078322 23
claytong 0:82ff15078322 24 // Global Data
claytong 0:82ff15078322 25
claytong 0:82ff15078322 26
claytong 0:82ff15078322 27 // Function Prototypes
claytong 0:82ff15078322 28
claytong 0:82ff15078322 29 //---------------------------------------------------------------------------
claytong 0:82ff15078322 30 // API METHODS
claytong 0:82ff15078322 31 //---------------------------------------------------------------------------
claytong 0:82ff15078322 32
claytong 0:82ff15078322 33 //---------------------------------------------------------------------------
claytong 0:82ff15078322 34 //
claytong 0:82ff15078322 35 // Initialisation Method
claytong 0:82ff15078322 36 //
claytong 0:82ff15078322 37 void TCommunications::Init()
claytong 0:82ff15078322 38 {
claytong 0:82ff15078322 39 eState = ST_START_ETH;
claytong 0:82ff15078322 40 iBufferCount = 0;
claytong 0:82ff15078322 41 PollTimer.start();
claytong 0:82ff15078322 42 CommandTimer.start();
claytong 0:82ff15078322 43 uiTestModeInc = 0;
claytong 0:82ff15078322 44 }
claytong 0:82ff15078322 45
claytong 0:82ff15078322 46 //---------------------------------------------------------------------------
claytong 0:82ff15078322 47 //
claytong 0:82ff15078322 48 // Processing Method
claytong 0:82ff15078322 49 // Main state machine
claytong 0:82ff15078322 50 //
claytong 0:82ff15078322 51 void TCommunications::Poll()
claytong 0:82ff15078322 52 {
claytong 0:82ff15078322 53 UDPSocketErr udpErr;
claytong 0:82ff15078322 54 EthernetErr ethErr;
claytong 0:82ff15078322 55
claytong 0:82ff15078322 56 switch ( eState )
claytong 0:82ff15078322 57 {
claytong 0:82ff15078322 58 case ST_START_ETH: // Initialise the Ethernet interface
claytong 0:82ff15078322 59 EthernetUpLED = 0;
claytong 0:82ff15078322 60 RunningLED = 0;
claytong 0:82ff15078322 61 ethErr = eth.setup( 25000 );
claytong 0:82ff15078322 62 if ( ethErr == ETH_OK )
claytong 0:82ff15078322 63 {
claytong 0:82ff15078322 64 const char * pcHWAddr = eth.getHwAddr();
claytong 0:82ff15078322 65 IpAddr ip = eth.getIp();
claytong 0:82ff15078322 66 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] );
claytong 0:82ff15078322 67 printf("mbed IP Address is %d.%d.%d.%d\r\n", ip[0], ip[1], ip[2], ip[3] );
claytong 0:82ff15078322 68 }
claytong 0:82ff15078322 69 // Set up UDP
claytong 0:82ff15078322 70 ServerSocket.setOnEvent( this, &TCommunications::onUDPSocketEvent );
claytong 0:82ff15078322 71 MyPort.setIp( IpAddr() );
claytong 0:82ff15078322 72 MyPort.setPort( QRSS_UDP_PORT );
claytong 0:82ff15078322 73 ServerSocket.bind( MyPort );
claytong 0:82ff15078322 74 udpErr = ServerSocket.bind( MyPort );
claytong 0:82ff15078322 75 if ( udpErr != UDPSOCKET_OK )
claytong 0:82ff15078322 76 {
claytong 0:82ff15078322 77 printf("UDP Bind error %d\r\n", udpErr);
claytong 0:82ff15078322 78 break;
claytong 0:82ff15078322 79 }
claytong 0:82ff15078322 80 // to poll state, and force sending of poll message
claytong 0:82ff15078322 81 printf("*POLL_SERVER State*\r\n" );
claytong 0:82ff15078322 82 eState = ST_POLL_SERVER;
claytong 0:82ff15078322 83 iPPSCount = POLL_MSG_PERIOD;
claytong 0:82ff15078322 84 bGotCmnd = false;
claytong 0:82ff15078322 85 break;
claytong 0:82ff15078322 86
claytong 0:82ff15078322 87 case ST_POLL_SERVER: // Poll the server and wait for it to start the system
claytong 0:82ff15078322 88 EthernetUpLED = 1;
claytong 0:82ff15078322 89 RunningLED = 0;
claytong 0:82ff15078322 90 if ( (iPPSCount>=POLL_MSG_PERIOD) || (PollTimer.read_ms()>POLL_TIMEOUT) )
claytong 0:82ff15078322 91 { // Send a poll message
claytong 0:82ff15078322 92 iPPSCount = 0;
claytong 0:82ff15078322 93 ServerAddr = dnsService.resolveName( szServerName );
claytong 0:82ff15078322 94 if ( ServerAddr.isNull() )
claytong 0:82ff15078322 95 {
claytong 0:82ff15078322 96 printf("DNS Failed - *START_ETH State*\r\n" );
claytong 0:82ff15078322 97 eState = ST_START_ETH;
claytong 0:82ff15078322 98 break;
claytong 0:82ff15078322 99 }
claytong 0:82ff15078322 100 ServerPort.setIp( ServerAddr );
claytong 0:82ff15078322 101 ServerPort.setPort( QRSS_UDP_PORT );
claytong 0:82ff15078322 102 if ( !SendPollMessage() )
claytong 0:82ff15078322 103 {
claytong 0:82ff15078322 104 printf("*START_ETH State*\r\n" );
claytong 0:82ff15078322 105 eState = ST_START_ETH;
claytong 0:82ff15078322 106 break;
claytong 0:82ff15078322 107 }
claytong 0:82ff15078322 108 }
claytong 0:82ff15078322 109 if ( bGotCmnd )
claytong 0:82ff15078322 110 {
claytong 0:82ff15078322 111 bGotCmnd = false;
claytong 0:82ff15078322 112 if ( uiCommand!=0 )
claytong 0:82ff15078322 113 { // start
claytong 0:82ff15078322 114 uiNCOPhaseInc = uiNCO;
claytong 0:82ff15078322 115 uiTestModeInc = uiTestOsc;
claytong 0:82ff15078322 116 printf("*RUNNING State*\r\n" );
claytong 0:82ff15078322 117 eState = ST_RUNNING;
claytong 0:82ff15078322 118 iBufferCount = 0;
claytong 0:82ff15078322 119 CommandTimer.reset();
claytong 0:82ff15078322 120 }
claytong 0:82ff15078322 121 }
claytong 0:82ff15078322 122 break;
claytong 0:82ff15078322 123
claytong 0:82ff15078322 124 case ST_RUNNING: // Running - transfer data to the server
claytong 0:82ff15078322 125 EthernetUpLED = 1;
claytong 0:82ff15078322 126 RunningLED = 1;
claytong 0:82ff15078322 127 if ( (iPPSCount>=POLL_MSG_PERIOD) || (PollTimer.read_ms()>POLL_TIMEOUT) )
claytong 0:82ff15078322 128 { // Send a poll message
claytong 0:82ff15078322 129 iPPSCount = 0;
claytong 0:82ff15078322 130 if ( !SendPollMessage() )
claytong 0:82ff15078322 131 {
claytong 0:82ff15078322 132 printf("*START_ETH State*\r\n" );
claytong 0:82ff15078322 133 eState = ST_START_ETH;
claytong 0:82ff15078322 134 break;
claytong 0:82ff15078322 135 }
claytong 0:82ff15078322 136 }
claytong 0:82ff15078322 137 if ( bGotCmnd )
claytong 0:82ff15078322 138 {
claytong 0:82ff15078322 139 bGotCmnd = false;
claytong 0:82ff15078322 140 CommandTimer.reset();
claytong 0:82ff15078322 141 if ( uiCommand==0 )
claytong 0:82ff15078322 142 { // stop
claytong 0:82ff15078322 143 printf("*POLL_SERVER State*\r\n" );
claytong 0:82ff15078322 144 eState = ST_POLL_SERVER;
claytong 0:82ff15078322 145 iPPSCount = POLL_MSG_PERIOD;
claytong 0:82ff15078322 146 iBufferCount = 0;
claytong 0:82ff15078322 147 }
claytong 0:82ff15078322 148 }
claytong 0:82ff15078322 149 if ( CommandTimer.read_ms()>RUNNING_TIMEOUT )
claytong 0:82ff15078322 150 {
claytong 0:82ff15078322 151 printf("Timeout - *POLL_SERVER State*\r\n" );
claytong 0:82ff15078322 152 eState = ST_POLL_SERVER;
claytong 0:82ff15078322 153 iPPSCount = POLL_MSG_PERIOD;
claytong 0:82ff15078322 154 iBufferCount = 0;
claytong 0:82ff15078322 155 }
claytong 0:82ff15078322 156 break;
claytong 0:82ff15078322 157 }
claytong 0:82ff15078322 158
claytong 0:82ff15078322 159 }
claytong 0:82ff15078322 160
claytong 0:82ff15078322 161 //---------------------------------------------------------------------------
claytong 0:82ff15078322 162 //
claytong 0:82ff15078322 163 // RecordPPSTimestamps Method
claytong 0:82ff15078322 164 // Records timestamps of events (1PPS or capture of LO divider)
claytong 0:82ff15078322 165 //
claytong 0:82ff15078322 166 void TCommunications::RecordPPSTimestamps( uint32_t uiPPSCapture, uint32_t uiLOscCapture,
claytong 0:82ff15078322 167 TGPSController::TGPSData &GPSInfo )
claytong 0:82ff15078322 168 {
claytong 0:82ff15078322 169 int ii;
claytong 0:82ff15078322 170
claytong 0:82ff15078322 171 #if COMMS_DEBUG>0
claytong 0:82ff15078322 172 printf( "PPS-Timestamp:Time %d Count %d PPSCap %u LOCap %u PPS %u LO %u\r\n",
claytong 0:82ff15078322 173 LastGPSInfo.iGPSTimeSeconds, iPPSCount, uiPPSCapture, uiLOscCapture,
claytong 0:82ff15078322 174 uiPPSCapture-auiPPSCaptures[0], uiLOscCapture-auiLOscCaptures[0] );
claytong 0:82ff15078322 175 #endif
claytong 0:82ff15078322 176
claytong 0:82ff15078322 177 // clear the captures if GPS is non-operation
claytong 0:82ff15078322 178 if ( GPSInfo.iGPSQuality<=0 )
claytong 0:82ff15078322 179 { // GPS is offline
claytong 0:82ff15078322 180 uiPPSCapture = 0;
claytong 0:82ff15078322 181 uiLOscCapture = 0;
claytong 0:82ff15078322 182 }
claytong 0:82ff15078322 183
claytong 0:82ff15078322 184 // shuffle the queue along
claytong 0:82ff15078322 185 for ( ii=7; ii>0; ii-- )
claytong 0:82ff15078322 186 {
claytong 0:82ff15078322 187 auiPPSCaptures[ii] = auiPPSCaptures[ii-1];
claytong 0:82ff15078322 188 auiLOscCaptures[ii] = auiLOscCaptures[ii-1];
claytong 0:82ff15078322 189 }
claytong 0:82ff15078322 190 // record newest data
claytong 0:82ff15078322 191 auiPPSCaptures[0] = uiPPSCapture;
claytong 0:82ff15078322 192 auiLOscCaptures[0] = uiLOscCapture;
claytong 0:82ff15078322 193 LastGPSInfo = GPSInfo;
claytong 0:82ff15078322 194
claytong 0:82ff15078322 195 // count event
claytong 0:82ff15078322 196 iPPSCount++;
claytong 0:82ff15078322 197
claytong 0:82ff15078322 198 }
claytong 0:82ff15078322 199
claytong 0:82ff15078322 200 //---------------------------------------------------------------------------
claytong 0:82ff15078322 201 //
claytong 0:82ff15078322 202 // Pass sample data for sending. Send when buffer is full
claytong 0:82ff15078322 203 //
claytong 0:82ff15078322 204 void TCommunications::SendSamples( uint32_t uiTimestamp, TDataSample sSample )
claytong 0:82ff15078322 205 {
claytong 0:82ff15078322 206 if ( eState!=ST_RUNNING )
claytong 0:82ff15078322 207 return;
claytong 0:82ff15078322 208
claytong 0:82ff15078322 209 if ( iBufferCount==0 )
claytong 0:82ff15078322 210 { // Build buffer header
claytong 0:82ff15078322 211 pucBuffDataPtr = (uint8_t *)auiDataBuffer;
claytong 0:82ff15078322 212 WriteWord( pucBuffDataPtr, COMM_DATA_MSG, iBufferCount );
claytong 0:82ff15078322 213 WriteWord( pucBuffDataPtr, uiTimestamp, iBufferCount );
claytong 0:82ff15078322 214 }
claytong 0:82ff15078322 215 // append data
claytong 0:82ff15078322 216 *((TDataSample*)pucBuffDataPtr) = sSample;
claytong 0:82ff15078322 217 pucBuffDataPtr += SAMPLE_SET_SIZE;
claytong 0:82ff15078322 218 iBufferCount += SAMPLE_SET_SIZE;
claytong 0:82ff15078322 219 // send buffer when full
claytong 0:82ff15078322 220 if ( iBufferCount>=COMMS_DATABUFF_SIZE )
claytong 0:82ff15078322 221 { // send message
claytong 0:82ff15078322 222 int iRet = ServerSocket.sendto( (char *)auiDataBuffer ,iBufferCount, &ServerPort );
claytong 0:82ff15078322 223 if ( iRet!=iBufferCount )
claytong 0:82ff15078322 224 printf("Sent Error - %d\r\n", iRet );
claytong 0:82ff15078322 225 iBufferCount = 0;
claytong 0:82ff15078322 226 }
claytong 0:82ff15078322 227 }
claytong 0:82ff15078322 228
claytong 0:82ff15078322 229 //---------------------------------------------------------------------------
claytong 0:82ff15078322 230 // PRIVATE METHODS
claytong 0:82ff15078322 231 //---------------------------------------------------------------------------
claytong 0:82ff15078322 232
claytong 0:82ff15078322 233 //---------------------------------------------------------------------------
claytong 0:82ff15078322 234 //
claytong 0:82ff15078322 235 // UDP Callback Method
claytong 0:82ff15078322 236 //
claytong 0:82ff15078322 237 void TCommunications::onUDPSocketEvent( UDPSocketEvent evnt )
claytong 0:82ff15078322 238 {
claytong 0:82ff15078322 239 if ( evnt==UDPSOCKET_READABLE )
claytong 0:82ff15078322 240 {
claytong 0:82ff15078322 241 uint8_t aucInBf[COMMS_CNTRLBUFF_SIZE];
claytong 0:82ff15078322 242 Host FromHost;
claytong 0:82ff15078322 243 int iLen;
claytong 0:82ff15078322 244 while ( 1 )
claytong 0:82ff15078322 245 {
claytong 0:82ff15078322 246 iLen = ServerSocket.recvfrom( (char *)aucInBf, COMMS_CNTRLBUFF_SIZE, &FromHost );
claytong 0:82ff15078322 247 if ( iLen<=0 )
claytong 0:82ff15078322 248 break;
claytong 0:82ff15078322 249 if ( iLen!=COMM_CMND_MSG_LENGTH )
claytong 0:82ff15078322 250 continue;
claytong 0:82ff15078322 251 if ( ReadWord(&(aucInBf[0]))!=COMM_CMND_MSG )
claytong 0:82ff15078322 252 continue;
claytong 0:82ff15078322 253 if ( ReadWord(&(aucInBf[4]))!=COMM_MSG_VERSION )
claytong 0:82ff15078322 254 continue;
claytong 0:82ff15078322 255 // have a real message!
claytong 0:82ff15078322 256 uiCommand = ReadWord( &(aucInBf[8]) );
claytong 0:82ff15078322 257 uiNCO = ReadWord( &(aucInBf[12]) );
claytong 0:82ff15078322 258 uiTestOsc = ReadWord( &(aucInBf[16]) );
claytong 0:82ff15078322 259 bGotCmnd = true;
claytong 0:82ff15078322 260 #if COMMS_DEBUG>0
claytong 0:82ff15078322 261 printf("Command %d\r\n", uiCommand );
claytong 0:82ff15078322 262 printf("NCO %d\r\n", uiNCO );
claytong 0:82ff15078322 263 printf("Test %d\r\n", uiTestOsc );
claytong 0:82ff15078322 264 #endif
claytong 0:82ff15078322 265 }
claytong 0:82ff15078322 266 }
claytong 0:82ff15078322 267 }
claytong 0:82ff15078322 268
claytong 0:82ff15078322 269 //---------------------------------------------------------------------------
claytong 0:82ff15078322 270 //
claytong 0:82ff15078322 271 // Send a UDP Poll Message
claytong 0:82ff15078322 272 //
claytong 0:82ff15078322 273 bool TCommunications::SendPollMessage()
claytong 0:82ff15078322 274 {
claytong 0:82ff15078322 275 // Build poll message
claytong 0:82ff15078322 276 uint8_t aucPollBuffer[150];
claytong 0:82ff15078322 277 uint8_t *pucPtr = aucPollBuffer;
claytong 0:82ff15078322 278 int iLen = 0;
claytong 0:82ff15078322 279 int iRet;
claytong 0:82ff15078322 280
claytong 0:82ff15078322 281 // reset the backup timer
claytong 0:82ff15078322 282 PollTimer.reset();
claytong 0:82ff15078322 283
claytong 0:82ff15078322 284 // Build Message
claytong 0:82ff15078322 285 WriteWord( pucPtr, COMM_POLL_MSG, iLen );
claytong 0:82ff15078322 286 WriteWord( pucPtr, COMM_MSG_VERSION, iLen );
claytong 0:82ff15078322 287 WriteWord( pucPtr, COMM_MSG_HW_ID, iLen );
claytong 0:82ff15078322 288 WriteWord( pucPtr, COMM_MSG_SW_VERSION, iLen );
claytong 0:82ff15078322 289 WriteWord( pucPtr, LastGPSInfo.iGPSQuality, iLen );
claytong 0:82ff15078322 290 WriteWord( pucPtr, LastGPSInfo.iGPSSatellites, iLen );
claytong 0:82ff15078322 291 WriteWord( pucPtr, LastGPSInfo.iGPSTimeSeconds, iLen );
claytong 0:82ff15078322 292 WriteWord( pucPtr, LastGPSInfo.iGPSLatMicroDegrees, iLen );
claytong 0:82ff15078322 293 WriteWord( pucPtr, LastGPSInfo.iGPSLongMicroDegrees, iLen );
claytong 0:82ff15078322 294 WriteWord( pucPtr, LastGPSInfo.iGPSAltitudeMeters, iLen );
claytong 0:82ff15078322 295 WriteWord( pucPtr, COMM_MSG_REF_CLOCK, iLen );
claytong 0:82ff15078322 296 WriteWord( pucPtr, COMM_MSG_RF_MIXER, iLen );
claytong 0:82ff15078322 297 WriteWord( pucPtr, COMM_MSG_SAMPLE_CLOCK, iLen );
claytong 0:82ff15078322 298 WriteWord( pucPtr, COMM_MSG_SAMPLE_DIVIDER, iLen );
claytong 0:82ff15078322 299 WriteWord( pucPtr, auiPPSCaptures[0], iLen );
claytong 0:82ff15078322 300 WriteWord( pucPtr, auiPPSCaptures[1], iLen );
claytong 0:82ff15078322 301 WriteWord( pucPtr, auiPPSCaptures[2], iLen );
claytong 0:82ff15078322 302 WriteWord( pucPtr, auiPPSCaptures[3], iLen );
claytong 0:82ff15078322 303 WriteWord( pucPtr, auiPPSCaptures[4], iLen );
claytong 0:82ff15078322 304 WriteWord( pucPtr, auiPPSCaptures[5], iLen );
claytong 0:82ff15078322 305 WriteWord( pucPtr, auiPPSCaptures[6], iLen );
claytong 0:82ff15078322 306 WriteWord( pucPtr, auiPPSCaptures[7], iLen );
claytong 0:82ff15078322 307 WriteWord( pucPtr, auiLOscCaptures[0], iLen );
claytong 0:82ff15078322 308 WriteWord( pucPtr, auiLOscCaptures[1], iLen );
claytong 0:82ff15078322 309 WriteWord( pucPtr, auiLOscCaptures[2], iLen );
claytong 0:82ff15078322 310 WriteWord( pucPtr, auiLOscCaptures[3], iLen );
claytong 0:82ff15078322 311 WriteWord( pucPtr, auiLOscCaptures[4], iLen );
claytong 0:82ff15078322 312 WriteWord( pucPtr, auiLOscCaptures[5], iLen );
claytong 0:82ff15078322 313 WriteWord( pucPtr, auiLOscCaptures[6], iLen );
claytong 0:82ff15078322 314 WriteWord( pucPtr, auiLOscCaptures[7], iLen );
claytong 0:82ff15078322 315 memcpy( pucPtr, COMM_MSG_NAME, COMM_MSGNAME_LEN );
claytong 0:82ff15078322 316 pucPtr += COMM_MSGNAME_LEN;
claytong 0:82ff15078322 317 iLen += COMM_MSGNAME_LEN;
claytong 0:82ff15078322 318
claytong 0:82ff15078322 319 // send message
claytong 0:82ff15078322 320 iRet = ServerSocket.sendto( (char *)aucPollBuffer ,iLen, &ServerPort );
claytong 0:82ff15078322 321 if ( iRet < 0 )
claytong 0:82ff15078322 322 return false;
claytong 0:82ff15078322 323 return true;
claytong 0:82ff15078322 324 }
claytong 0:82ff15078322 325
claytong 0:82ff15078322 326 //---------------------------------------------------------------------------
claytong 0:82ff15078322 327 // END
claytong 0:82ff15078322 328 //---------------------------------------------------------------------------