// File: Terminal.c //------------------------------------------------------------------------------ // Author: Giovanni de Sanctis // Email: info@lateral-technologies.com //------------------------------------------------------------------------------ // Date: Dec 2018 // Implements the serial interface //------------------------------------------------------------------------------ #include "mcc_generated_files/device_config.h" //For __delay_ms #include "Terminal.h" #include "Definitions.h" #include "Power.h" #include "Servos.h" #include "LEDs.h" #include "JDY08.h" #include enum { ST_IDLE, ST_USER_MOVE_INIT, ST_USER_LEDS_INIT, ST_USER_MOVE, ST_USER_LEDS, ST_AUTO } st; #define MAX_USER_PRESETS 4u #define MAX_AUTO_G 3u //We need 3 groups max for automode #define LEN_AUTO_T 3u //We need 3 timing parameters for automode #define MIN_AUTO_T 15u //Min time that can be specified (seconds) #define MAX_AUTO_T 240u //Max time that can be specified (seconds) #define ERR_NOERR 0u #define ERR_OUTOFRANGE 1u #define ERR_UNKNOWNTYPE 2u #define ERR_UNEXPECTED 3u #define ERR_MISSINGTOKEN 4u //Error messages #define ERR_OUTOFRANGE_STR "OUT OF RANGE" #define ERR_UNKNOWN_TYPE_STR "UNKNOWN TYPE" #define ERR_UNEXPECTED_TOKEN_STR "UNEXPECTED TOKEN" #define ERR_MISSING_TOKEN_STR "MISSING PARAMETER" #define ERR_ERROR_STR "ERROR" #define MAX_PFX_LEN 6u #define MSG_BEGIN "BEGIN " #define MSG_END "END " //Commands char const * const CMD_SHUTDN = "SHUTDOWN"; char const * const CMD_PING = "PING"; char const * const CMD_BATT = "BATT"; char const * const CMD_VER = "VER"; char const * const CMD_ULEDS = "USERLEDS"; char const * const CMD_UMOVE = "USERMOVE"; char const * const CMD_AUTO = "AUTOMODE"; char const * const CMD_ABORT = "STOPAUTO"; //Responses char const * const RES_OK ="OK"; char const * const RES_ERR="ERR"; uint8_t parCycles; //Number of cycles in the parsed move or leds pattern uint8_t parUserMem; //User mem preset to host the specified move uint8_t parNum; //Number of positions to expect uint8_t parPtrA; //Pointer to the servo1 positions (MAX_PATTERNS) int8_t parStep[MAX_MOVES]; #else int8_t parStep[MAX_PATTERNS]; #endif //Send a concatenation of 2 strings to the BT module //This is used to send a BEGIN/END+CmdName message void sendCompMex(const char* str1, char* str2) { char str[MAX_PFX_LEN+MAX_CMD_LEN+1]; uint8_t pd,ps; pd=0; for (ps=0; ps<=MAX_PFX_LEN && str1[ps]; ps++) str[pd++]=str1[ps]; for (ps=0; ps=MIN_AUTO_T && val<=MAX_AUTO_T) parPos.autm.t[parPtrT++]=(uint8_t)val; else error = ERR_OUTOFRANGE; else error = ERR_UNEXPECTED; break; default: error = ERR_UNKNOWNTYPE; break; } } if (error==0) { if (st==ST_USER_MOVE) { setUserMove(parUserMem-1u,parNum,parCycles,parPos.move.pos1,parPos.move.pos2,parStep); } else if (st==ST_USER_LEDS) { setUserLeds(parUserMem-1u,parNum,parCycles,parPos.leds.pos,parStep); } else { setAuto(parPos.autm.t[0],parPos.autm.t[1],parPos.autm.t[2],parPos.autm.grps); } } //Check that all the positions and step timings have been received if (error==0 && st!=ST_AUTO) { if (parNum>parPtrA || parNum>parPtrS) error=ERR_MISSINGTOKEN; //If defining a move then check the pointer for the Servo2 as well if (st==ST_USER_MOVE && parNum>parPtrS) error=ERR_MISSINGTOKEN; } switch (error) { case ERR_NOERR: btSendStr(RES_OK,0); break; case ERR_OUTOFRANGE: btSendStr(ERR_OUTOFRANGE_STR,0); break; case ERR_UNKNOWNTYPE: btSendStr(ERR_UNKNOWN_TYPE_STR,0); break; case ERR_UNEXPECTED: btSendStr(ERR_UNEXPECTED_TOKEN_STR,0); break; case ERR_MISSINGTOKEN:btSendStr(ERR_MISSING_TOKEN_STR,0); break; default: btSendStr(ERR_ERROR_STR,0); break; } } } //If ack for move end then send out END MOVE message // and clear current move string if (ack==ACK_END_MOVE) { sendCompMex(MSG_END,currMoveStr); currMoveStr[0]=0; } //If ack for leds end then send out END LEDS message // and clear current leds string if (ack==ACK_END_LEDS) { sendCompMex(MSG_END,currLedsStr); currLedsStr[0]=0; } }