Test software for SatChat prototype hardware Platform - MAX32630FTHR

Dependencies:   USBDevice max32630fthr

Committer:
koziniec
Date:
Thu Sep 21 01:24:44 2017 +0000
Revision:
16:c5634210628d
Parent:
15:7d75ecaeabdb
Test software for SatChat prototype hardware

Who changed what in which revision?

UserRevisionLine numberNew contents of line
koziniec 15:7d75ecaeabdb 1 /* BLACK CODE INCLUDE START
koziniec 15:7d75ecaeabdb 2 External libraries are worrying!
koziniec 15:7d75ecaeabdb 3 Keep it simple and avoid anything non essential or obscure.
koziniec 15:7d75ecaeabdb 4 Consider copying functions from libraries into the code so
koziniec 15:7d75ecaeabdb 5 we have control. */
koziniec 0:59c04ca89ae2 6 #include "mbed.h"
koziniec 0:59c04ca89ae2 7 #include "max32630fthr.h"
koziniec 1:b8cb82927f33 8 #include <stdbool.h>
koziniec 15:7d75ecaeabdb 9 /* BLACK CODE INCLUDE END */
koziniec 15:7d75ecaeabdb 10
koziniec 15:7d75ecaeabdb 11 /* BLACK CODE DEFINE START */
koziniec 13:ff0b39177386 12 #define ON 0
koziniec 13:ff0b39177386 13 #define OFF 1
koziniec 13:ff0b39177386 14 #define EXIT_SUCCESS 0
koziniec 13:ff0b39177386 15 #define EXIT_FAILURE 1
koziniec 15:7d75ecaeabdb 16 /* BLACK CODE DEFINE END */
koziniec 14:8ff04e82bda2 17
koziniec 15:7d75ecaeabdb 18 /* BLACK CODE GLOBAL VAR START */
koziniec 15:7d75ecaeabdb 19 const int GPS_TIMEOUT=180; //Wait three minutes maximum for GPS.
koziniec 9:b8a60ade343e 20 char gpsfix_last_utc_time[11] = {0};
koziniec 9:b8a60ade343e 21 char gpsfix_last_utc_date[7] = {0};
koziniec 9:b8a60ade343e 22 char gpsfix_longtitude[12] = {0};
koziniec 9:b8a60ade343e 23 char gpsfix_latitude[12] = {0};
koziniec 9:b8a60ade343e 24 char gpsfix_speed[8] = {0}; //Set but not used
koziniec 9:b8a60ade343e 25 char gpsfix_course[7] = {0}; //Set but not used
koziniec 9:b8a60ade343e 26 char gpsfix_variation[7] = {0}; //Set but not used
koziniec 9:b8a60ade343e 27 char gpsfix_mag_var_ew[1] = {0};//Set but not used
koziniec 11:a9c16968e7f6 28 char gpsfix_ns = 0;
koziniec 11:a9c16968e7f6 29 char gpsfix_ew = 0;
koziniec 13:ff0b39177386 30 bool gps_data_present = false; //If this is false we can't even use stale GPS data.
koziniec 15:7d75ecaeabdb 31 /* BLACK CODE GLOBAL VAR END */
koziniec 15:7d75ecaeabdb 32
koziniec 15:7d75ecaeabdb 33 /* BLACK CODE PERIPHERAL INIT START */
koziniec 15:7d75ecaeabdb 34 DigitalOut red_led(LED1,1);
koziniec 15:7d75ecaeabdb 35 DigitalOut green_led(LED2,1);
koziniec 15:7d75ecaeabdb 36 DigitalOut gps_led(LED3,1); //Blue
koziniec 15:7d75ecaeabdb 37 Serial pc(USBTX, USBRX);
koziniec 15:7d75ecaeabdb 38 Serial gps(P5_3, P5_4, 9600);
koziniec 15:7d75ecaeabdb 39 I2C i2c(P5_7,P6_0); // SDA, SCL
koziniec 15:7d75ecaeabdb 40 /* BLACK CODE PERIPHERAL INIT END */
koziniec 9:b8a60ade343e 41
koziniec 1:b8cb82927f33 42 void gps_power(bool state)
koziniec 15:7d75ecaeabdb 43 /* BLACK CODE
koziniec 15:7d75ecaeabdb 44 MAX32630FTHR routine to control the output of the 3v3 line.
koziniec 15:7d75ecaeabdb 45 This is achieved by issuing commands to the MAX14690 controller.
koziniec 15:7d75ecaeabdb 46 In this case when the GPS is shutdown we clear any serial
koziniec 15:7d75ecaeabdb 47 data to avoid issues with mbeds buggy serial code */
koziniec 1:b8cb82927f33 48 {
koziniec 1:b8cb82927f33 49 char data[2];
koziniec 1:b8cb82927f33 50 data[0] = 0x16; //MAX14690 LDO3cfg register
koziniec 16:c5634210628d 51 printf("GPS Power:");
koziniec 13:ff0b39177386 52 if (state == ON) {
koziniec 1:b8cb82927f33 53 data[1] = 0xE2; //Enable LDO3
koziniec 14:8ff04e82bda2 54 i2c.write( 0x50, data, 2 );
koziniec 14:8ff04e82bda2 55 gps_led=ON;
koziniec 16:c5634210628d 56 printf("ON\n\r");
koziniec 14:8ff04e82bda2 57 } else {
koziniec 14:8ff04e82bda2 58 data[1] = 0xE0; //Disable LDO3
koziniec 14:8ff04e82bda2 59 i2c.write( 0x50, data, 2 );
koziniec 14:8ff04e82bda2 60 gps_led=OFF;
koziniec 14:8ff04e82bda2 61 while (gps.readable()) {
koziniec 14:8ff04e82bda2 62 char dummy = gps.getc(); //Empty serial buffer because overflows reveal MBED bugs :-(
koziniec 14:8ff04e82bda2 63 }
koziniec 16:c5634210628d 64 printf("OFF\n\r");
koziniec 1:b8cb82927f33 65 }
koziniec 1:b8cb82927f33 66 }
koziniec 1:b8cb82927f33 67
koziniec 13:ff0b39177386 68 int get_epoch_from_last_gps_time(void)
koziniec 15:7d75ecaeabdb 69 /* BLACK CODE
koziniec 15:7d75ecaeabdb 70 Given appropriate global char arrays of time and date information,
koziniec 15:7d75ecaeabdb 71 return a unix time epoch.
koziniec 15:7d75ecaeabdb 72 */
koziniec 12:a895e3581542 73 {
koziniec 12:a895e3581542 74 struct tm t;
koziniec 13:ff0b39177386 75 time_t epoch;
koziniec 12:a895e3581542 76 char two_char_str[3] = {0};
koziniec 12:a895e3581542 77 memcpy(two_char_str, gpsfix_last_utc_date+4, 2);
koziniec 12:a895e3581542 78 t.tm_year = atoi(two_char_str)+100; //Years since 1900
koziniec 12:a895e3581542 79 memcpy(two_char_str, gpsfix_last_utc_date+2, 2);
koziniec 12:a895e3581542 80 t.tm_mon = atoi(two_char_str)-1; // Month, 0 - jan gpsfix_last_utc_date
koziniec 12:a895e3581542 81 memcpy(two_char_str, gpsfix_last_utc_date, 2);
koziniec 12:a895e3581542 82 t.tm_mday = atoi(two_char_str); // Day of the month gpsfix_last_utc_date
koziniec 12:a895e3581542 83 memcpy(two_char_str, gpsfix_last_utc_time, 2);
koziniec 12:a895e3581542 84 t.tm_hour = atoi(two_char_str);
koziniec 12:a895e3581542 85 memcpy(two_char_str, gpsfix_last_utc_time+2, 2);
koziniec 12:a895e3581542 86 t.tm_min = atoi(two_char_str);
koziniec 13:ff0b39177386 87 memcpy(two_char_str, gpsfix_last_utc_time+4, 2);
koziniec 12:a895e3581542 88 t.tm_sec = atoi(two_char_str);
koziniec 12:a895e3581542 89 t.tm_isdst = 0; // Is DST on? 1 = yes, 0 = no, -1 = unknown
koziniec 13:ff0b39177386 90 epoch = mktime(&t);
koziniec 13:ff0b39177386 91 return epoch;
koziniec 15:7d75ecaeabdb 92 //BLACK CODE
koziniec 12:a895e3581542 93 }
koziniec 12:a895e3581542 94
koziniec 13:ff0b39177386 95 int gps_update(void)
koziniec 15:7d75ecaeabdb 96 /* BLACK CODE
koziniec 15:7d75ecaeabdb 97 gps_update
koziniec 15:7d75ecaeabdb 98 Reads NMEA data from a serial interface defined as "gps".
koziniec 15:7d75ecaeabdb 99 The function waits for a valid $GPRMC sentence. It then decodes the sentence and populates the
koziniec 15:7d75ecaeabdb 100 following global variables which are assumed to exist.
koziniec 15:7d75ecaeabdb 101
koziniec 15:7d75ecaeabdb 102 gpsfix_last_utc_time[11] = {0}; char gpsfix_last_utc_date[7] = {0};char gpsfix_longtitude[12] = {0};
koziniec 15:7d75ecaeabdb 103 char gpsfix_latitude[12] = {0}; char gpsfix_speed[8] = {0}; char gpsfix_course[7] = {0};
koziniec 15:7d75ecaeabdb 104 char gpsfix_variation[7] = {0}; char gpsfix_mag_var_ew[1] = {0}; char gpsfix_ns = 0; char gpsfix_ew = 0;
koziniec 15:7d75ecaeabdb 105
koziniec 15:7d75ecaeabdb 106 The following are also assumed to be part of the global declarations.
koziniec 15:7d75ecaeabdb 107 #define EXIT_SUCCESS 0
koziniec 15:7d75ecaeabdb 108 #define EXIT_FAILURE 1
koziniec 15:7d75ecaeabdb 109 const int GPS_TIMEOUT=180;
koziniec 15:7d75ecaeabdb 110 a gps_power() function that controls power to the GPS unit.
koziniec 15:7d75ecaeabdb 111
koziniec 15:7d75ecaeabdb 112 If the function is successful it returns a 0. If a valid fix is not obtined within the GPS_TIMEOUT
koziniec 15:7d75ecaeabdb 113 period a 1 is returned.
koziniec 15:7d75ecaeabdb 114
koziniec 15:7d75ecaeabdb 115 The code has been tested with a uBlox 6M but other GPS units may work.
koziniec 15:7d75ecaeabdb 116 The code is deliberately blocking as the mbed OS seems to crash on serial interrupts and buffer overflow.
koziniec 15:7d75ecaeabdb 117 The serial port is continuously read while waiting for a fix. Once a fix is obtained or a timeout occurs
koziniec 15:7d75ecaeabdb 118 the GPS is powered down and remaining data read out of the buffer.
koziniec 15:7d75ecaeabdb 119 */
koziniec 1:b8cb82927f33 120 {
koziniec 13:ff0b39177386 121 gps_power(ON);
koziniec 13:ff0b39177386 122 time_t gps_on_time = time(NULL); //Start time for GPS timeout calculation.
koziniec 13:ff0b39177386 123 bool wait_for_fix = true; //Set this to false once a fix is obtained.
koziniec 13:ff0b39177386 124 while (wait_for_fix) { //Keep monitoring the GPS until we get a fix.
koziniec 14:8ff04e82bda2 125 if ((time(NULL) - gps_on_time) > GPS_TIMEOUT) {
koziniec 13:ff0b39177386 126 gps_power(OFF);
koziniec 13:ff0b39177386 127 return EXIT_FAILURE; //Return an error if the GPS takes too long for a fix.
koziniec 13:ff0b39177386 128 }
koziniec 7:4218bb385ca4 129 int checksum = 0;
koziniec 13:ff0b39177386 130 char nmea_sentence[83] = {0}; //NMEA length max is 82 + 1 terminator. Fill with NULL terminators to save doing it later.
koziniec 8:b4a6c632c809 131 while (gps.getc()!='$'); //wait for start of sentence
koziniec 1:b8cb82927f33 132 int nmea_index = 0;
koziniec 7:4218bb385ca4 133 nmea_sentence[nmea_index] = '$'; //Manually insert the '$' because we don't want it included in the checksum loop
koziniec 8:b4a6c632c809 134 char nmea_char = gps.getc(); //get sentence first char from GPS
koziniec 15:7d75ecaeabdb 135 while (nmea_char != '*') { //Loop, building sentence and calc'ing CS until a * is seen
koziniec 15:7d75ecaeabdb 136 checksum ^= nmea_char; //Calc checksum as we read sentence
koziniec 7:4218bb385ca4 137 if ((nmea_sentence[nmea_index] == ',')&&(nmea_char == ',')) {
koziniec 15:7d75ecaeabdb 138 nmea_sentence[++nmea_index] = ' '; //Pad consecutive comma with a space to make it possible to use strtok with empty values
koziniec 3:1dff075c1c88 139 }
koziniec 15:7d75ecaeabdb 140 nmea_sentence[++nmea_index] = nmea_char; //build the sentence with the next character
koziniec 13:ff0b39177386 141 if (nmea_index > 81) {
koziniec 13:ff0b39177386 142 nmea_index=81; //Don't overflow sentence buffer
koziniec 1:b8cb82927f33 143 }
koziniec 7:4218bb385ca4 144 nmea_char = gps.getc(); //get next char from GPS
koziniec 1:b8cb82927f33 145 }
koziniec 13:ff0b39177386 146 //Last character was the '*' so next two are CS
koziniec 8:b4a6c632c809 147 char hex_checksum[3] = {0};
koziniec 8:b4a6c632c809 148 hex_checksum[0] = gps.getc();
koziniec 8:b4a6c632c809 149 hex_checksum[1] = gps.getc();
koziniec 13:ff0b39177386 150 if (checksum == (int)strtol(hex_checksum, NULL, 16) ) { //Compare calc and read checksums.
koziniec 9:b8a60ade343e 151 //Valid sentence so check if it's a GPRMC
koziniec 9:b8a60ade343e 152 const char gprmc[7] = "$GPRMC";
koziniec 9:b8a60ade343e 153 char *token;
koziniec 9:b8a60ade343e 154 token = strtok(nmea_sentence, ",");
koziniec 16:c5634210628d 155 if (strcmp(token,gprmc) == 0) { //GPRMC
koziniec 16:c5634210628d 156 pc.printf( " %s\n\r", token ); //Get the time
koziniec 9:b8a60ade343e 157 if (token != NULL) {
koziniec 9:b8a60ade343e 158 token = strtok(NULL, ",");
koziniec 13:ff0b39177386 159 if (*token != 32) { //If there is a time present (anything but a space), record it.
koziniec 13:ff0b39177386 160 //pc.printf("Time: %s\n\r",token);
koziniec 14:8ff04e82bda2 161 gps_led =! gps_led; //Flash blue LED
koziniec 11:a9c16968e7f6 162 memcpy(gpsfix_last_utc_time, token, sizeof gpsfix_last_utc_time - 1);
koziniec 11:a9c16968e7f6 163 }
koziniec 9:b8a60ade343e 164 }
koziniec 9:b8a60ade343e 165 if (token != NULL) {
koziniec 9:b8a60ade343e 166 token = strtok(NULL, ",");
koziniec 16:c5634210628d 167 if (*token == 'V') {
koziniec 16:c5634210628d 168 pc.printf("VOID");
koziniec 16:c5634210628d 169 }
koziniec 13:ff0b39177386 170 }
koziniec 12:a895e3581542 171 if (*token == 'A') { //Is this an 'A'ctive (valid) fix?
koziniec 10:349d4fa9037f 172 pc.printf("Got a fix\n\r");
koziniec 13:ff0b39177386 173 gps_power(OFF); //Yes - No need for GPS now
koziniec 12:a895e3581542 174 wait_for_fix = false; //Stop looping now we have a fix.
koziniec 10:349d4fa9037f 175 if (token != NULL) {
koziniec 10:349d4fa9037f 176 token = strtok(NULL, ",");
koziniec 16:c5634210628d 177 pc.printf("Latitude: %s\n\r",token);
koziniec 11:a9c16968e7f6 178 memcpy(gpsfix_latitude, token, sizeof gpsfix_latitude - 1);
koziniec 10:349d4fa9037f 179 }
koziniec 10:349d4fa9037f 180 if (token != NULL) {
koziniec 10:349d4fa9037f 181 token = strtok(NULL, ",");
koziniec 16:c5634210628d 182 pc.printf("North/South: %s\n\r",token);
koziniec 11:a9c16968e7f6 183 gpsfix_ns = *token;
koziniec 10:349d4fa9037f 184 }
koziniec 10:349d4fa9037f 185 if (token != NULL) {
koziniec 10:349d4fa9037f 186 token = strtok(NULL, ",");
koziniec 16:c5634210628d 187 pc.printf("Longitude: %s\n\r",token);
koziniec 11:a9c16968e7f6 188 memcpy(gpsfix_longtitude, token, sizeof gpsfix_longtitude - 1);
koziniec 10:349d4fa9037f 189 }
koziniec 10:349d4fa9037f 190 if (token != NULL) {
koziniec 10:349d4fa9037f 191 token = strtok(NULL, ",");
koziniec 16:c5634210628d 192 pc.printf("East/West: %s\n\r",token);
koziniec 11:a9c16968e7f6 193 gpsfix_ew = *token;
koziniec 10:349d4fa9037f 194 }
koziniec 10:349d4fa9037f 195 if (token != NULL) {
koziniec 10:349d4fa9037f 196 token = strtok(NULL, ",");
koziniec 15:7d75ecaeabdb 197 //pc.printf("Speed in knots: %s\n\r",token);
koziniec 10:349d4fa9037f 198 }
koziniec 10:349d4fa9037f 199 if (token != NULL) {
koziniec 10:349d4fa9037f 200 token = strtok(NULL, ",");
koziniec 11:a9c16968e7f6 201 //pc.printf("True course: %s\n\r",token);
koziniec 10:349d4fa9037f 202 }
koziniec 10:349d4fa9037f 203 if (token != NULL) {
koziniec 10:349d4fa9037f 204 token = strtok(NULL, ",");
koziniec 16:c5634210628d 205 pc.printf("Date: %s\n\r",token);
koziniec 11:a9c16968e7f6 206 memcpy(gpsfix_last_utc_date, token, sizeof gpsfix_last_utc_date - 1);
koziniec 10:349d4fa9037f 207 }
koziniec 10:349d4fa9037f 208 if (token != NULL) {
koziniec 10:349d4fa9037f 209 token = strtok(NULL, ",");
koziniec 11:a9c16968e7f6 210 //pc.printf("Variation: %s\n\r",token);
koziniec 10:349d4fa9037f 211 }
koziniec 10:349d4fa9037f 212 if (token != NULL) {
koziniec 10:349d4fa9037f 213 token = strtok(NULL, ",");
koziniec 11:a9c16968e7f6 214 //pc.printf("Variation East/West: %s\n\r",token);
koziniec 10:349d4fa9037f 215 }
koziniec 10:349d4fa9037f 216 }
koziniec 9:b8a60ade343e 217 }
koziniec 8:b4a6c632c809 218 }
koziniec 1:b8cb82927f33 219 }
koziniec 13:ff0b39177386 220 return EXIT_SUCCESS;
koziniec 15:7d75ecaeabdb 221 //BLACK CODE
koziniec 12:a895e3581542 222 }
koziniec 1:b8cb82927f33 223
koziniec 13:ff0b39177386 224 main()
koziniec 16:c5634210628d 225 { /*Set the power button behaviour.
koziniec 16:c5634210628d 226 char data[2];
koziniec 16:c5634210628d 227 data[0] = 0x1A; //MAX14690 BootCfg register
koziniec 16:c5634210628d 228 data[1] = 0x30; //Always-On Mode, off state via PWR_OFF_CMD
koziniec 16:c5634210628d 229 i2c.write( 0x50, data, 2 );
koziniec 16:c5634210628d 230 */
koziniec 16:c5634210628d 231
koziniec 15:7d75ecaeabdb 232 //Set the voltage to 3v3 for the GPS.
koziniec 16:c5634210628d 233 char data[2];
koziniec 1:b8cb82927f33 234 data[0] = 0x17; //MAX14690 LDO3Vset register
koziniec 0:59c04ca89ae2 235 data[1] = 0x19; //3.3V
koziniec 0:59c04ca89ae2 236 i2c.write( 0x50, data, 2 );
koziniec 13:ff0b39177386 237 gps_power(OFF);
koziniec 15:7d75ecaeabdb 238
koziniec 16:c5634210628d 239 while (1) {
koziniec 16:c5634210628d 240 if (gps_update()==EXIT_SUCCESS) {
koziniec 16:c5634210628d 241 gps_data_present = true;
koziniec 16:c5634210628d 242 int gps_epoch = get_epoch_from_last_gps_time();
koziniec 16:c5634210628d 243 set_time(gps_epoch);
koziniec 16:c5634210628d 244 pc.printf("Got a GPS fix and time.\n\r");
koziniec 16:c5634210628d 245 } else {
koziniec 16:c5634210628d 246 pc.printf("GPS timed out and we have no existing fix.\n\r");
koziniec 16:c5634210628d 247 pc.printf("We can send an Iridium packet but coordinates are rough.\n\r");
koziniec 13:ff0b39177386 248 }
koziniec 16:c5634210628d 249 time_t seconds = time(NULL);
koziniec 16:c5634210628d 250 //printf("Time as a basic string = %s", ctime(&seconds));
koziniec 16:c5634210628d 251 wait(60);
koziniec 16:c5634210628d 252 seconds = time(NULL);
koziniec 13:ff0b39177386 253
koziniec 16:c5634210628d 254 wait(33);
koziniec 16:c5634210628d 255 seconds = time(NULL);
koziniec 16:c5634210628d 256 printf("Time as a basic string = %s", ctime(&seconds));
koziniec 16:c5634210628d 257 wait(60);
koziniec 16:c5634210628d 258 }
koziniec 16:c5634210628d 259 }
koziniec 0:59c04ca89ae2 260
koziniec 0:59c04ca89ae2 261
koziniec 7:4218bb385ca4 262
koziniec 7:4218bb385ca4 263
koziniec 7:4218bb385ca4 264
koziniec 0:59c04ca89ae2 265
koziniec 7:4218bb385ca4 266
koziniec 0:59c04ca89ae2 267
koziniec 7:4218bb385ca4 268