This library is designed to create and run state graphs. It supports hierarchical states and parallel states execution.

utt_foobar.h

Committer:
martin13
Date:
2019-02-12
Revision:
3:d4d69d0d8381
Parent:
2:5e2336b52d0a
Child:
4:22b4462fcb26

File content as of revision 3:d4d69d0d8381:

#ifndef __UTT_FOOBAR_H__
#define __UTT_FOOBAR_H__

#include "StateMachine.h"
#include "Logger.h"


// different commands to set the update rate from once a second (1 Hz) to 10 times a second (10Hz)
// Note that these only control the rate at which the position is echoed, to actually speed up the
// position fix you must also send one of the position fix rate commands below too.
#define PMTK_SET_NMEA_UPDATE_100_MILLIHERTZ  "$PMTK220,10000*2F" // Once every 10 seconds, 100 millihertz.
#define PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ  "$PMTK220,5000*1B"  // Once every 5 seconds, 200 millihertz.
#define PMTK_SET_NMEA_UPDATE_1HZ  "$PMTK220,1000*1F"
#define PMTK_SET_NMEA_UPDATE_5HZ  "$PMTK220,200*2C"
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"
// Position fix update rate commands.
#define PMTK_API_SET_FIX_CTL_100_MILLIHERTZ  "$PMTK300,10000,0,0,0,0*2C" // Once every 10 seconds, 100 millihertz.
#define PMTK_API_SET_FIX_CTL_200_MILLIHERTZ  "$PMTK300,5000,0,0,0,0*18"  // Once every 5 seconds, 200 millihertz.
#define PMTK_API_SET_FIX_CTL_1HZ  "$PMTK300,1000,0,0,0,0*1C"
#define PMTK_API_SET_FIX_CTL_5HZ  "$PMTK300,200,0,0,0,0*2F"
// Can't fix position faster than 5 times a second!


#define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C"
#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17"

// turn on only the second sentence (GPRMC)
#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on GPRMC and GGA
#define PMTK_SET_NMEA_OUTPUT_RMCGGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn on ALL THE DATA
#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn off output
#define PMTK_SET_NMEA_OUTPUT_OFF "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"

// to generate your own sentences, check out the MTK command datasheet and use a checksum calculator
// such as the awesome http://www.hhhh.org/wiml/proj/nmeaxor.html

#define PMTK_LOCUS_STARTLOG  "$PMTK185,0*22"
#define PMTK_LOCUS_STOPLOG "$PMTK185,1*23"
#define PMTK_LOCUS_STARTSTOPACK "$PMTK001,185,3*3C"
#define PMTK_LOCUS_QUERY_STATUS "$PMTK183*38"
#define PMTK_LOCUS_ERASE_FLASH "$PMTK184,1*22"
#define LOCUS_OVERLAP 0
#define LOCUS_FULLSTOP 1

#define PMTK_ENABLE_SBAS "$PMTK313,1*2E"
#define PMTK_ENABLE_WAAS "$PMTK301,2*2E"

// standby command & boot successful message
#define PMTK_STANDBY "$PMTK161,0*28"
#define PMTK_STANDBY_SUCCESS "$PMTK001,161,3*36"  // Not needed currently
#define PMTK_AWAKE "$PMTK010,002*2D"

// ask for the release and version
#define PMTK_Q_RELEASE "$PMTK605*31"

// request for updates on antenna status 
#define PGCMD_ANTENNA "$PGCMD,33,1*6C" 
#define PGCMD_NOANTENNA "$PGCMD,33,0*6D" 

// how long to wait when we're looking for a response
#define MAXWAITSENTENCE 5

class Foo : public State{

public:

    static const char* OUTCOME_BAR;

    Foo(const char* uuid, UserData *ud): 
      State(uuid){ 
        /* Capture UserData, see in utt_foobar_with_ud.h example. */ 
        
        gps_Serial = new RawSerial(D10, D2);
        gps_Serial->baud(9600);
        nnema = new char[129];
        
        sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
        sendCommand(PMTK_SET_NMEA_UPDATE_5HZ);
        sendCommand(PMTK_API_SET_FIX_CTL_5HZ);
        sendCommand(PGCMD_ANTENNA);
    }
    
    void sendCommand(const char *str) {
        gps_Serial->printf(str);
    }
    
    virtual void onEntry(){ 
        /* Do something before onExecute() */
    }
    
    virtual const char* onExecute(){
        /* Do something */
        
        int offset = 0;
        memset(nnema,'x',129);
        
        
        while(gps_Serial->readable()){
            
            char c = gps_Serial->getc();
            //Logger::info("%c",c);
            nnema[offset++] = c;
        }      
        //nnema[++offset] = '\0';
        
        Logger::info("%i = %s",offset, nnema);
        
        return OUTCOME_BAR;
    }
    
    virtual void onExit(){
        /* Do something before exit state */
    }
    
private:
    RawSerial *gps_Serial;
    char* nnema;
};

const char* Foo::OUTCOME_BAR = "OUTCOME_BAR";

class Bar : public State{

public:

    static const char* OUTCOME_FOO;

    Bar(const char* uuid, UserData *ud):
      State(uuid){ 
        /* Capture UserData, see in utt_foobar_with_ud.h example. */ 
    }
    
    virtual void onEntry(){ 
        /* Do something before onExecute() */
    }
    
    virtual const char* onExecute(){
        /* Do something */
        wait(1);
        return OUTCOME_FOO;
    }
    
    virtual void onExit(){
        /* Do something before exit state */
    }
};

const char* Bar::OUTCOME_FOO = "OUTCOME_FOO";

class FooBar : public StateMachine{

public:

    FooBar(const char* uuid):
        StateMachine(uuid),
        foo(NULL), bar(NULL)
    {
        // States instance with StateMachine context
        foo = this->Instance<Foo>("FOO");
        bar = this->Instance<Bar>("BAR");
        
        // Connect Foo to Bar
        this->connect(STATE(foo), Foo::OUTCOME_BAR, STATE(bar));
        
        // Connect Bar to Foo
        this->connect(STATE(bar), Bar::OUTCOME_FOO, STATE(foo));
        
        // Set the first state calling when the state machine starts
        this->setInitialState(STATE(foo)); 
    }

private:
    Foo *foo;
    Bar *bar;
};

// Preempt state mahine button
InterruptIn button(PC_13);

void unit_test(){
    
    FooBar foobar("FOOBAR_SM");
    
    button.rise(&foobar, &FooBar::preempt);
    
    foobar.printGraph();
    
    Logger::info("STATE MACHINE FINISHED WITH OUTCOME \"%s\"",foobar.execute()); 
}


#endif /* #ifndef __UTT_FOOBAR_H__*/