Terry Koziniec / Mbed OS SatChat-GPS-test

Dependencies:   USBDevice max32630fthr

Files at this revision

API Documentation at this revision

Comitter:
koziniec
Date:
Tue Jul 04 17:24:55 2017 +0000
Parent:
14:8ff04e82bda2
Child:
16:c5634210628d
Commit message:
Essential documentation of the GPS BLACK CODE is completed.; Time to move onto the RockBlock code.

Changed in this revision

BLACKCODE.txt Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLACKCODE.txt	Tue Jul 04 17:24:55 2017 +0000
@@ -0,0 +1,29 @@
+An EPIRB is a crucial piece of safety equipment.  Someone's life could be placed at risk if it fails or behaves in an unpredictable manner.
+An open EPIRB encourages development and feature enhancement which is a good thing but is potentially at odds with safety.  What if you
+change the user interface and the user can't figure out how to send an SOS?  What if you introduce a bug and unit crashes?
+
+To address this issue, open EPIRB uses a two phase start up.  When you initially power on the device it enters a minimum functionality mode
+during which one of two messages can be sent.  A routine positional update which logs the operator's current GPS location via the Iridium
+Satellite constellation or an SOS message.  After a brief period the minimum functionality phase ends and the full functionality begins.
+In the full functionality phase it is possible to do everything that can be done in the minimum functionality mode as well as sending and
+receiving short text messages, regularly logging position and any other functions that are yet to be thought of.
+
+Every piece of configuration and code necessary to achieve minimum functionality is known as BLACK CODE. To achieve reliability BLACK CODE
+changes are not made trivially.  They should be limited to bug fixes, usability and perhaps improving readibility and understanding of the code.
+Before making a change to BLACK CODE, ask yourself how this enhances the reliability of the unit.  This is an area of minimum functionality and
+not a place to add new features.  Adding a new feature increases the chance of failure and consequently increases the risk that a needed SOS 
+won't be sent.  When it is necessary to make BLACK CODE changes it is essential the changes are thoroughly thought through, tested and approved
+by the client. Any additional libraries, functions or variables must be labelled as BLACK if any BLACK CODE relies on it. 
+
+Only BLACK CODE should run until the end of the minimum functionality period.  In fact, a good test of the code base is to delete everything that
+isn't BLACK and show that an SOS can still be sent.
+
+After the minimum functionality period expires, functionality is deliverd by regular code (non BLACK).  Here careful coding and rigourous testing
+should also occur but development and functionality are encouraged.
+
+REUSE OF BLACK CODE
+The full functionality program space is encouraged to reuse BLACK code as this serves to further exercise and test these crucial components. If there is a
+proposal for substantial changes to be made to BLACK CODE functions, it is recommended that the BLACK CODE functions be replicated in their new form
+and labelled as RED CODE. The full functionality code should then call on the experimental RED CODE to allow debugging and field evaluation to
+occur without jeapordising the stability of the BLACK CODE code base.  Once the RED CODE is thouroughly debugged, tested and documented it can
+be considered for inclusion as BLACK CODE.  Thus the full functionality code becomes a testing environment for the minimum functionality code base.
\ No newline at end of file
--- a/main.cpp	Mon Jul 03 16:50:59 2017 +0000
+++ b/main.cpp	Tue Jul 04 17:24:55 2017 +0000
@@ -1,20 +1,22 @@
-
+/*  BLACK CODE INCLUDE START
+    External libraries are worrying!
+    Keep it simple and avoid anything non essential or obscure.
+    Consider copying functions from libraries into the code so
+    we have control. */
 #include "mbed.h"
 #include "max32630fthr.h"
 #include <stdbool.h>
+/*  BLACK CODE INCLUDE END */
+
+/*  BLACK CODE DEFINE START */
 #define ON 0
 #define OFF 1
 #define EXIT_SUCCESS 0
 #define EXIT_FAILURE 1
-const int GPS_TIMEOUT=180;            //Wait three minutes maximum for GPS.
+/*  BLACK CODE DEFINE END */
 
-Serial pc(USBTX, USBRX);
-Serial gps(P5_3, P5_4, 9600);
-I2C i2c(P5_7,P6_0); // SDA, SCL
-
-DigitalOut red_led(LED1,1);
-DigitalOut green_led(LED2,1);
-DigitalOut gps_led(LED3,1); //Blue
+/*  BLACK CODE GLOBAL VAR START */
+const int GPS_TIMEOUT=180;            //Wait three minutes maximum for GPS.
 char gpsfix_last_utc_time[11] = {0};
 char gpsfix_last_utc_date[7] = {0};
 char gpsfix_longtitude[12] = {0};
@@ -26,8 +28,23 @@
 char gpsfix_ns = 0;
 char gpsfix_ew = 0;
 bool gps_data_present = false;  //If this is false we can't even use stale GPS data.
+/*  BLACK CODE GLOBAL VAR END */
+
+/*  BLACK CODE PERIPHERAL INIT START */
+DigitalOut red_led(LED1,1);
+DigitalOut green_led(LED2,1);
+DigitalOut gps_led(LED3,1); //Blue
+Serial pc(USBTX, USBRX);
+Serial gps(P5_3, P5_4, 9600);
+I2C i2c(P5_7,P6_0); // SDA, SCL
+/*  BLACK CODE PERIPHERAL INIT END */
 
 void gps_power(bool state)
+/*  BLACK CODE
+    MAX32630FTHR routine to control the output of the 3v3 line.
+    This is achieved by issuing commands to the MAX14690 controller.
+    In this case when the GPS is shutdown we clear any serial
+    data to avoid issues with mbeds buggy serial code  */
 {
     char    data[2];
     data[0] = 0x16;     //MAX14690 LDO3cfg register
@@ -46,6 +63,10 @@
 }
 
 int get_epoch_from_last_gps_time(void)
+/*  BLACK CODE
+    Given appropriate global char arrays of time and date information,
+    return a unix time epoch.
+*/
 {
     struct tm t;
     time_t epoch;
@@ -65,9 +86,34 @@
     t.tm_isdst = 0;        // Is DST on? 1 = yes, 0 = no, -1 = unknown
     epoch = mktime(&t);
     return epoch;
+    //BLACK CODE
 }
 
 int gps_update(void)
+/*  BLACK CODE
+    gps_update
+    Reads NMEA data from a serial interface defined as "gps".
+    The function waits for a valid $GPRMC sentence. It then decodes the sentence and populates the
+    following global variables which are assumed to exist.
+    
+    gpsfix_last_utc_time[11] = {0}; char gpsfix_last_utc_date[7] = {0};char gpsfix_longtitude[12] = {0};
+    char gpsfix_latitude[12] = {0}; char gpsfix_speed[8] = {0}; char gpsfix_course[7] = {0};
+    char gpsfix_variation[7] = {0}; char gpsfix_mag_var_ew[1] = {0}; char gpsfix_ns = 0; char gpsfix_ew = 0;
+    
+    The following are also assumed to be part of the global declarations.
+    #define EXIT_SUCCESS 0
+    #define EXIT_FAILURE 1
+    const int GPS_TIMEOUT=180;
+    a gps_power() function that controls power to the GPS unit.
+    
+    If the function is successful it returns a 0.  If a valid fix is not obtined within the GPS_TIMEOUT 
+    period a 1 is returned.
+    
+    The code has been tested with a uBlox 6M but other GPS units may work.
+    The code is deliberately blocking as the mbed OS seems to crash on serial interrupts and buffer overflow.
+    The serial port is continuously read while waiting for a fix. Once a fix is obtained or a timeout occurs
+    the GPS is powered down and remaining data read out of the buffer.
+*/
 {
     gps_power(ON);
     time_t gps_on_time = time(NULL);    //Start time for GPS timeout calculation.
@@ -83,12 +129,12 @@
         int nmea_index = 0;
         nmea_sentence[nmea_index] = '$';    //Manually insert the '$' because we don't want it included in the checksum loop
         char nmea_char = gps.getc();        //get sentence first char from GPS
-        while (nmea_char != '*') {          //Loop building sentence and calc'ing CS until *
-            checksum ^= nmea_char;         //Calc checksum as we read sentence
+        while (nmea_char != '*') {          //Loop, building sentence and calc'ing CS until a * is seen
+            checksum ^= nmea_char;          //Calc checksum as we read sentence
             if ((nmea_sentence[nmea_index] == ',')&&(nmea_char == ',')) {
-                nmea_sentence[++nmea_index] = ' ';  //Pad consecutive comma with a space to make it possible to use strtok with empty values
+                nmea_sentence[++nmea_index] = ' ';      //Pad consecutive comma with a space to make it possible to use strtok with empty values
             }
-            nmea_sentence[++nmea_index] = nmea_char; //build the sentence with the next character
+            nmea_sentence[++nmea_index] = nmea_char;    //build the sentence with the next character
             if (nmea_index > 81) {
                 nmea_index=81;          //Don't overflow sentence buffer
             }
@@ -99,7 +145,6 @@
         hex_checksum[0] = gps.getc();
         hex_checksum[1] = gps.getc();
         if (checksum == (int)strtol(hex_checksum, NULL, 16) ) {     //Compare calc and read checksums.
-
             //Valid sentence so check if it's a GPRMC
             const char gprmc[7] = "$GPRMC";
             char *token;
@@ -146,7 +191,7 @@
                     }
                     if (token != NULL) {
                         token = strtok(NULL, ",");
-                        pc.printf("Speed in knots: %s\n\r",token);
+                        //pc.printf("Speed in knots: %s\n\r",token);
                     }
                     if (token != NULL) {
                         token = strtok(NULL, ",");
@@ -170,20 +215,26 @@
         }
     }
     return EXIT_SUCCESS;
+    //BLACK CODE
 }
 
 main()
-{
+/*  Start of BLACK CODE region.  This area provides minimal SOS and position
+    updating. It needs to be robust and well tested. Put all the fancy stuff 
+    outside this area.  Changes here should be limited to fixing bugs and
+    simplifying the code.
+*/
+{   //Set the power button behaviour.
     char    data[2];
     data[0] = 0x1A;     //MAX14690 BootCfg register
     data[1] = 0x30;     //Always-On Mode, off state via PWR_OFF_CMD
     i2c.write( 0x50, data, 2 );
-
+    //Set the voltage to 3v3 for the GPS.
     data[0] = 0x17;     //MAX14690 LDO3Vset register
     data[1] = 0x19;     //3.3V
     i2c.write( 0x50, data, 2 );
     gps_power(OFF);
-    wait(2);
+
     pc.printf("\n\n\rOpen EPIRB - Simple mode\n\r");
     pc.printf("Press and hold both side buttons to signal rescue needed\n\r");
     pc.printf("Full functionality will start in:");
@@ -191,7 +242,7 @@
         time_t seconds = time(NULL);    //get current epoch
         pc.printf("%d",i);
         while(time(NULL) - seconds < 1) {
-            if (true/*button_combination()==SOS_PRESSED*/) {
+            if (false/*button_combination()==SOS_PRESSED*/) {
                 //do the emergency code
                 if (gps_update()==EXIT_SUCCESS) {
                     gps_data_present = true;
@@ -211,7 +262,8 @@
         }
         pc.printf("\b");            //Backspace
     }
-    // normal functionality lives here
+/*  END OF BLACK CODE REGION - Put all the fancy stuff down here
+*/
     pc.printf("\n\rStarting normal operation\n\r");
 /*
     if (true) {         //Temp simulation