Thread: [Firebug-cvs] fireboard/beta/apps/GPS2 Makefile,NONE,1.1 README,NONE,1.1 SODebug.h,NONE,1.1 TestMTS4
Brought to you by:
doolin
From: David M. D. <do...@us...> - 2005-09-19 17:41:18
|
Update of /cvsroot/firebug/fireboard/beta/apps/GPS2 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10324 Added Files: Makefile README SODebug.h TestMTS400.nc TestMTS400M.nc sensorboardApp.h Log Message: GPS test application code clean up. --- NEW FILE: SODebug.h --- // printf style output for debugging // // Copyright (c) 2004 by Sensicast, Inc. // All rights including that of resale granted to Crossbow, Inc. // // Permission to use, copy, modify, and distribute this software and its // documentation for any purpose, without fee, and without written // agreement is hereby granted, provided that the above copyright // notice, the (updated) modification history and the author appear in // all copies of this source code. // // Permission is also granted to distribute this software under the // standard BSD license as contained in the TinyOS distribution. // // @Author: Michael Newman // #ifndef SOdebugEdit #define SOdebugEdit 1 // // Modification History: // 25Jan04 MJNewman 1: Created. #include <stdarg.h> //turn off debug output by default #ifndef SO_DEBUG #define SO_DEBUG 0 #endif // Assume we are not a dot by default #ifndef SO_DEBUG_DOT #define SODEBUG_DOT 0 #endif // Most of this module is off unless enabled #if (SO_DEBUG) //#include <stdio.h> // This varaiable is shared by many possible users of SOdebug. // The rest of the code is duplicated!. static const char hex[] = "0123456789ABCDEF"; #if (!SO_DEBUG_DOT) //init comm port (57.6K baud, mica2 only, use 19K baud for mica2dot, mica....) for debug // TinyOS is using 57.6K and seems to reset the baud rate periodically. // Use only 57.6K baud unless TinyOS is sorted out. static void init_debug(){ atomic { outp(0,UBRR0H); #if 1 // 56K with 0% error clock is 7.3728Mhz outp(15, UBRR0L); //set baud rate outp((1<<U2X),UCSR0A); // Set UART double speed #else // 19.K with 0% error clock is 7.3728Mhz outp(47, UBRR0L); //set baud rate outp((1<<U2X),UCSR0A); // Set UART double speed #endif outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C); // Set frame format: 8 data-bits, 1 stop-bit inp(UDR0); outp((1 << TXEN) ,UCSR0B); // Enable uart reciever and transmitter } } #else //init comm port (19K baud) for mica2dot for debug static void init_debug(){ atomic { outp(0,UBRR0H); // Set baudrate to 19.2 KBps outp(12, UBRR0L); outp(0,UCSR0A); // Disable U2X and MPCM outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C); inp(UDR0); outp((1 << TXEN) ,UCSR0B); } } #endif // output a char to the uart void UARTPutChar(char c) { if (c == '\n') { loop_until_bit_is_set(UCSR0A, UDRE); outb(UDR0,'\r'); loop_until_bit_is_set(UCSR0A, TXC); }; loop_until_bit_is_set(UCSR0A, UDRE); outb(UDR0,c); loop_until_bit_is_set(UCSR0A, TXC); return; } // Simplified printf int printf(const uint8_t *format, ...) { static bool debugStarted; uint8_t format_flag; uint32_t u_val=0; uint32_t div_val; uint8_t base; uint8_t *ptr; bool longNumber = FALSE; bool temp; va_list ap; va_start (ap, format); atomic temp = debugStarted; if (!temp) { init_debug(); atomic debugStarted = 1; }; if (format == NULL) format = "NULL\n"; for (;;) /* Until full format string read */ { if (!longNumber) { // Assume char after %l is d or xX while ((format_flag = *format++) != '%') /* Until '%' or '\0' */ { if (!format_flag) { return 0; // not bothering with count of chars output }; UARTPutChar(format_flag); }; }; switch (format_flag = *format++) { case 'c': format_flag = va_arg(ap, int); default: UARTPutChar(format_flag); continue; case 'S': case 's': ptr = va_arg(ap,char *); while ((format_flag = *ptr++)) { UARTPutChar(format_flag); }; continue; #if 0 case 't': { #define SECONDS_IN_ONE_DAY 86400 base = 10; if (currentSeconds/86400) {//print days div_val = 10000; u_val = currentSeconds/SECONDS_IN_ONE_DAY; do { UARTPutChar(hex[u_val / div_val]); u_val %= div_val; div_val /= base; } while (div_val); UARTPutChar(' '); UARTPutChar('d'); UARTPutChar('a'); UARTPutChar('y'); UARTPutChar('s'); UARTPutChar(' '); } // //hours div_val = 10; u_val = (currentSeconds % 86400)/3600; do { UARTPutChar(hex[u_val / div_val]); u_val %= div_val; div_val /= base; } while (div_val); UARTPutChar(':'); // //minutes div_val = 10; u_val = (INT16)((currentSeconds % 86400)%3600)/60; do { UARTPutChar(hex[u_val / div_val]); u_val %= div_val; div_val /= base; } while (div_val); UARTPutChar(':'); // //seconds div_val = 10; u_val = (INT16)(currentSeconds%60); do { UARTPutChar(hex[u_val / div_val]); u_val %= div_val; div_val /= base; } while (div_val); } continue; #endif // 't' time output case 'l': longNumber = TRUE; continue; case 'o': base = 8; if (!longNumber) div_val = 0x8000; else div_val = 0x40000000; goto CONVERSION_LOOP; case 'u': case 'i': case 'd': base = 10; if (!longNumber) div_val = 10000; else div_val = 1000000000; goto CONVERSION_LOOP; case 'x': base = 16; if (!longNumber) div_val = 0x1000; else div_val = 0x10000000; CONVERSION_LOOP: { if (!longNumber) u_val = va_arg(ap,int); else u_val = va_arg(ap,long); if ((format_flag == 'd') || (format_flag == 'i')) { bool isNegative; if (!longNumber) isNegative = (((int)u_val) < 0); else isNegative = (((long)u_val) < 0); if (isNegative) { u_val = - u_val; UARTPutChar('-'); }; while (div_val > 1 && div_val > u_val) { div_val /= 10; }; } // truncate signed values to a 16 bits for hex output if ((format_flag == 'x') && (!longNumber)) u_val &= 0xffff; do { UARTPutChar(hex[u_val / div_val]); u_val %= div_val; div_val /= base; } while (div_val); longNumber = FALSE; }; break; }; }; } #endif // SO_DEBUG #define SO_NO_DEBUG 0 #if (SO_DEBUG) #define SODbg(__x,__args...) { \ char bStatus; \ if(__x != SO_NO_DEBUG){ \ bStatus=bit_is_set(SREG,7); \ cli(); \ printf(__args); \ if (bStatus) sei(); \ }; \ } #else #define SODbg(__x,__args...) #endif #endif //SOdebugEdit --- NEW FILE: TestMTS400.nc --- /****************************************************************************** * Controls GPS for testing purposes. This is an isolated test of the * GPS. See discussion in TestMTS400M.nc for more info on operational * strategy. * * "Copyright (c) 2005 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Author: Michael Newman * * Modification History: * 8Sep05 MJNewman: Created. *****************************************************************************/ includes sensorboardApp; configuration TestMTS400 { } implementation { components Main, TestMTS400M, MicaWbSwitch, GenericComm as Comm, TimerC, Voltage, NMEAC, LedsC, UARTGpsPacket, ADCC; Main.StdControl -> TestMTS400M; Main.StdControl -> TimerC; TestMTS400M.CommControl -> Comm; // Wiring for gps TestMTS400M.GpsControl -> UARTGpsPacket; TestMTS400M.GpsSend -> UARTGpsPacket.SendVar; TestMTS400M.GpsReceive -> UARTGpsPacket; TestMTS400M.GpsCmd -> UARTGpsPacket.GpsCmd; //UARTGpsPacket.GpsCmd; TestMTS400M.Leds -> LedsC; TestMTS400M.Timer -> TimerC.Timer[unique("Timer")]; TestMTS400M.nmea -> NMEAC; } --- NEW FILE: Makefile --- include ../Makelocal COMPONENT=TestMTS400 SENSORBOARD=mts400 #MSG_SIZE=120 XBOWROOT=$(TOSROOT)/contrib/xbow/tos CWD = $(shell pwd) FIREBOARDROOT=$(CWD)/../../.. PFLAGS = -I$(XBOWROOT)/interfaces PFLAGS += -I$(XBOWROOT)/system PFLAGS += -I$(XBOWROOT)/platform/$(PLATFORM) #PFLAGS += -I$(XBOWROOT)/AXStack/$(PLATFORM) #PFLAGS += -I$(XBOWROOT)/lib PFLAGS += -I$(FIREBOARDROOT)/beta/tos/sensorboards/$(SENSORBOARD) PFLAGS += -I$(FIREBOARDROOT)/beta/tos/sensorboards/$(SENSORBOARD)/GPS PFLAGS += -I$(FIREBOARDROOT)/interfaces # control debugging printfs 1 is on 0 is off PFLAGS += -DSO_DEBUG=1 PFLAGS += -DFEATURE_GPS_ONLY=1 PFLAGS += -DNMEA_MESSAGE_TESTING=1 #include ../MakeXbowlocal #include ${TOSROOT}/tools/make/Makerules include ${TOSROOT}/apps/Makerules --- NEW FILE: TestMTS400M.nc --- /****************************************************************************** * Controls GPS for testing purposes. This is an isolated test of the * GPS. * * NOTES: * -Intersema pressure sensor control lines are shared with gps control lines * -Cannot enable gps rx/tx and intersema at same time * * Strategy: * 1. Turn on gps power and leave on * 2. Continuously report GPS packets as they come from the GPS. * 3. A timer fires periodically. When a counted number of timer events * occurs reconfigure the GPS by sending a message to the GPS. After an * additional counted number of timer events reconfigure the GPS back. * * "Copyright (c) 2005 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Author: Michael Newman * * Modification History: * 8Sep05 MJNewman: Created. *****************************************************************************/ module TestMTS400M { provides interface StdControl; uses { //communication interface StdControl as CommControl; //gps // interface I2CSwitchCmds as GpsCmd; interface GpsCmd; interface StdControl as GpsControl; interface SendVarLenPacket as GpsSend; interface ReceiveMsg as GpsReceive; interface NMEA as nmea; interface Timer; interface Leds; } } implementation { #define TIMER_PERIOD 1000 // timer period in msec // Turn on to send a message every Minute or so that tell the GPS to // turn on or off one of the GPS messages. This allows testing to see // if messages are making it out to the GPS. #ifndef NMEA_MESSAGE_TESTING #define NMEA_MESSAGE_TESTING 0 #endif #define MIN(_a,_b) ((_a < _b) ? _a : _b) #include "SODebug.h" #include "gps.h" #include "NMEA.h" enum { GPSstateUnknown, GPSstateStart, GPSstatePowerOn, GPSstateReady, } GPSstate; static void dumpGPSstate() { switch (GPSstate) { default: case GPSstateUnknown: SODbg(DBG_USR2, "?GPSstate %d?\n",GPSstate); break; case GPSstateStart: SODbg(DBG_USR2,"GPSstateStart\n"); break; case GPSstatePowerOn: SODbg(DBG_USR2,"GPSstatePowerOn\n"); break; case GPSstateReady: SODbg(DBG_USR2,"GPSstateReady\n"); break; } return; } #if NMEA_MESSAGE_TESTING // Test code to determine if messages can be sent to the GPS. MJNewman // 15Aug05 //#define NMEA_ENABLE "$PSRF103,05,00,01,01*20\r\n" //VTG on //#define NMEA_DISABLE "$PSRF103,05,00,00,01*21\r\n" //VTG off //#define NMEA_ENABLE "$PSRF103,00,00,02,01*26\r\n" //GGA on 2 sec //#define NMEA_ENABLE "$PSRF103,00,00,08,01*2C\r\n" //GGA on 8 sec #define NMEA_ENABLE "\r\n\r\n$PSRF103,01,00,01,01*24\r\n" //GLL on #define NMEA_ENABLE_LENGTH strlen(NMEA_ENABLE) #define NMEA_DISABLE "\r\n\r\n$PSRF103,01,00,00,01*25\r\n" //GLL off #define NMEA_DISABLE_LENGTH strlen(NMEA_DISABLE) #if 0 #define CHANGE_TO_SIRF_MODE "$PSRF100,0,4800,8,1,0*0F\r\n" #define CHANGE_TO_SIRF_LENGTH strlen(CHANGE_TO_SIRF_MODE) static const uint8_t const CHANGE_TO_NMEA_MODE[] = { 0xA0, 0xA2, 0x00, 0x18, 0x81, 0x02, 0x01, 0x01, 0x00, 0x01, 0x05, 0x01, 0x05, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x12, 0xC0, 0x01, 0x6A, 0xB0, 0xB3 }; #define CHANGE_TO_NMEA_LENGTH sizeof(CHANGE_TO_NMEA_MODE) #define NMEA_ENABLE CHANGE_TO_NMEA_MODE #define NMEA_ENABLE_LENGTH CHANGE_TO_NMEA_LENGTH #define NMEA_DISABLE CHANGE_TO_SIRF_MODE #define NMEA_DISABLE_LENGTH strlen(CHANGE_TO_SIRF_MODE) #endif // send message to the GPS to enable VTG messages on a 1 second cycle task void enableNMEAmessage() { #if 0 readStep_t localStep; atomic localStep = readStep; if (localStep != GPS_REQUESTED) { // Wait until GPS is safely on post enableNMEAmessage(); return; }; #endif if ( call GpsSend.send((char *)NMEA_ENABLE , NMEA_ENABLE_LENGTH) == SUCCESS) { SODbg(DBG_USR2,"GPS ENable NMEA\n"); return; }; post enableNMEAmessage(); return; } #endif event result_t GpsSend.sendDone(uint8_t *sendPtr, result_t status) { #if NMEA_MESSAGE_TESTING // SODbg(DBG_USR2, "GPS %s commanded: %s",((status == SUCCESS) ? "OK" : "FAIL"),(char *)sendPtr); #endif return SUCCESS; } #if NMEA_MESSAGE_TESTING task void disableNMEAmessage() { #if 0 readStep_t localStep; atomic localStep = readStep; if (localStep != GPS_REQUESTED) { // Wait until GPS is safely on post enableNMEAmessage(); return; }; #endif if ( call GpsSend.send(NMEA_DISABLE, NMEA_DISABLE_LENGTH) == SUCCESS) { SODbg(DBG_USR2,"GPS DISable NMEA\n"); return; } post disableNMEAmessage(); return; } #endif command result_t StdControl.init() { atomic { GPSstate = GPSstateStart; } call Leds.init(); call Leds.greenOn(); call GpsControl.init(); SODbg(DBG_USR2,"InitComplete\n"); return SUCCESS; } command result_t StdControl.start() { SODbg(DBG_USR2,"Starting GPS\n"); call GpsControl.start(); call Timer.start(TIMER_REPEAT, TIMER_PERIOD); //start up sensor measurements return SUCCESS; } static void dumpGPSmsg(char *string,int length) { #if 1 if (string[0] == '$') { // echo the GPS message int i; for (i=0;i < length;i += 1) { SODbg(DBG_USR2, "%c",string[i]); if (string[i] == '*') break; }; SODbg(DBG_USR2, "\n"); }; #endif return; } command result_t StdControl.stop() { call GpsControl.stop(); call GpsCmd.TxRxSwitch(0); // ???timing of switch setting call GpsCmd.PowerSwitch(0); call Timer.stop(); call CommControl.stop(); return SUCCESS; } /****************************************************************************** * Timer fired, test GPS, humidity/temp * async for test only *****************************************************************************/ event result_t Timer.fired() { switch (GPSstate) { default: case GPSstateUnknown: dumpGPSstate(); GPSstate = GPSstateStart; //... case GPSstateStart: SODbg(DBG_USR2, "Turn GPS power ON\n"); if (call GpsCmd.PowerSwitch(1) != SUCCESS) { SODbg(DBG_USR2, "PowerSwitch failed wait for retry\n"); }; return SUCCESS; case GPSstatePowerOn: SODbg(DBG_USR2, "Turn GPS switches ON\n"); if (call GpsCmd.TxRxSwitch(1) != SUCCESS) { SODbg(DBG_USR2, "TxRxSwitch failed wait for retry\n"); }; return SUCCESS; case GPSstateReady: break; }; call Leds.redToggle(); #if NMEA_MESSAGE_TESTING { static uint8_t cycleCount; cycleCount += 1; if (cycleCount == 5) { SODbg(DBG_USR2, "Trying NMEA On\n"); post enableNMEAmessage(); return SUCCESS; }; if (cycleCount == 30) { SODbg(DBG_USR2, "Trying NMEA OFF\n"); post disableNMEAmessage(); return SUCCESS; }; if (cycleCount >= 60) { cycleCount = 0; }; } #endif // NMEA_MESSAGE_TESTING return SUCCESS; } // When a packet is received from the GPS we retain a pointer to // that packet and hand a pointer to another buffer back to the // lower level. Each sucessive message swaps buffers, establishing // a double buffering scheme. static GPS_Msg gpsData; // contributed buffer for double buffering static GPS_Msg *pGPSdata = &gpsData; // buffer to dump // Report and handle the content of a message that came in from the // GPS and is stored inpGGAdata. task void handleGPSmessage() { char * leadtek_string; // if gps have been scaned then stop receiving gps uart packet leadtek_string = pGPSdata->data; if (leadtek_string[0] == '$') { dumpGPSmsg(leadtek_string,MIN(sizeof(pGPSdata->data),pGPSdata->length)); #if 0 if (is_gga_string_m(leadtek_string)) { call nmea.gga_parse(gga_data_ptr, leadtek_string); } else if (is_gsa_string(pGPSdata->data)) { call nmea.gsa_parse(gsa_data_ptr, leadtek_string); } else if (is_gva_string(data)) { call nmea.gsv_parse(gsv_data_ptr, leadtek_string); } else if (is_gll_string(data)) { call nmea.gll_parse(gll_data_ptr, leadtek_string); } else if (is_rmc_string(data)) { call nmea.rmc_parse(rmc_data_ptr, leadtek_string); } else if (is_vtg_string(data)) { call nmea.vtg_parse(vtg_data_ptr, leadtek_string); } else if (is_mss_string(data)) { call nmea.mss_parse(mss_data_ptr, leadtek_string); } else if (is_ltc_string(data)) { call nmea.ltc_parse(ltc_data_ptr, leadtek_string); } else { // signal error }; #endif }; if (leadtek_string[0] == (char)0xA0) { #if 1 //??? remove when the rest of the Sirf code is available SODbg(DBG_USR2,"SIRF Packet\n"); #else uint8_t sirftype; sirftype = sirf.get_type(data); switch sirftype { case SIRF2: call sirf.id2_parse(leadtek_string); break; case SIRF28: call sirf.id28_parse(leadtek_string); break; default: // Unexpected SIRF type, this might be normal it // also might want to signal an error. break; }; #endif }; } // A gps message has been collected from the receiver. Log it and // set off a task to report it. // // Inputs: // pData really a pointer to a GGA_data block // Returns: // new buffer for lower level to use event TOS_MsgPtr GpsReceive.receive(TOS_MsgPtr pData) { GPS_Msg *pTemp; pTemp = pGPSdata; pGPSdata = (GPS_Msg *)pData; post handleGPSmessage(); return (TOS_MsgPtr)pTemp; } // Log the power condition reported by the GPS so we can test it // later. event result_t GpsCmd.PowerSet(uint8_t PowerState){ SODbg(DBG_USR2,"GPS power %s\n",(PowerState) ? "ON" : "OFF"); if (PowerState) { GPSstate += 1; }; dumpGPSstate(); return SUCCESS; } event result_t GpsCmd.TxRxSet(uint8_t rtstate) { // gps tx/rx switches set to on or off SODbg(DBG_USR2,"GPS switches %s\n",(rtstate) ? "ON" : "OFF"); if (rtstate) { GPSstate += 1; }; dumpGPSstate(); return SUCCESS; } } --- NEW FILE: sensorboardApp.h --- // $Id: sensorboardApp.h,v 1.1 2005/09/19 17:41:05 doolin Exp $ #ifndef SENSORBOARDAPP_H #define SENSORBOARDAPP_H #include "NMEA.h" typedef struct XSensorHeader { uint8_t board_id; uint8_t packet_id; // 3 uint8_t node_id; uint8_t rsvd; }__attribute__ ((packed)) XSensorHeader; typedef struct GGAMsg { uint8_t hour; uint8_t minute; uint8_t lat_deg; uint8_t long_deg; uint32_t dec_sec; uint32_t lat_dec_min; uint32_t long_dec_min; uint8_t nsewind; uint8_t fixed; } __attribute__ ((packed)) GGAMsg; typedef struct XSensorMTS400DataMsg { uint16_t vref; uint16_t humidity; uint16_t temperature; uint16_t cal_wrod1; uint16_t cal_wrod2; uint16_t cal_wrod3; uint16_t cal_wrod4; uint16_t intersematemp; uint16_t pressure; uint16_t taoch0; uint16_t taoch1; uint16_t accel_x; uint16_t accel_y; } __attribute__ ((packed)) XSensorMTS400DataMsg; enum { AM_XSXMSG = 0, }; typedef struct weather_data { uint16_t vref; uint16_t humidity; uint16_t temperature; uint16_t cal_word1; uint16_t cal_word2; uint16_t cal_word3; uint16_t cal_word4; uint16_t intersematemp; uint16_t pressure; uint16_t taosch0; uint16_t taosch1; } Weather_Data; enum { AM_WEATHER_DATA = 251, }; typedef struct XDataMsg { XSensorHeader xSensorHeader; union { XSensorMTS400DataMsg data1; GGAMsg dataGps; GGA_Data gga_data; Weather_Data weather_data; }xData; } __attribute__ ((packed)) XDataMsg; #endif /* SENSORBOARDAPP_H */ --- NEW FILE: README --- README Description: Test the observation of GPS data from the MTS400 in isolation from other sensors on that board. Also test the ability to send commands to the GPS. |