Touch screen drivers control dashboard for miniature locomotive. Features meters for speed, volts, power. Switches for lights, horns. Drives multiple STM3_ESC brushless motor controllers for complete brushless loco system as used in "The Brute" - www.jons-workshop.com

Dependencies:   TS_DISCO_F746NG mbed Servo LCD_DISCO_F746NG BSP_DISCO_F746NG QSPI_DISCO_F746NG AsyncSerial FastPWM

Revision:
10:0bdfd342f393
Parent:
7:3b1f44cd4735
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cli_TS_nortos.cpp	Fri Jun 22 14:35:00 2018 +0000
@@ -0,0 +1,398 @@
+//Loco_TS_2018
+#include "mbed.h"
+//#include "BufferedSerial.h"
+#include "AsyncSerial.hpp"
+#include <cctype>
+#include "Electric_Loco.h"
+using namespace std;
+
+//extern  int I_Am    ()  ;      //  Returns boards id number as ASCII char '0', '1' etc. Code for Broadcast = '\r'
+//typedef double  fl_typ;  //
+
+struct parameters pccom, lococom;
+void    clicore (struct parameters & a) ;
+const int   BROADCAST   = '\r';
+
+//  WithOUT RTOS
+extern  Serial pc;
+extern  AsyncSerial com;
+extern  void    send_test   ()  ;
+
+void    null_cmd (struct parameters & a)
+{
+    pc.printf   ("At null_cmd, parameters : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
+}
+
+extern  struct  multi_bogie_options      detected_bogie_options;
+
+/*
+struct  single_bogie_options   {
+    char    motoradir, motorbdir, gang, svo1, svo2, comm_src, id, wheeldia, motpin, wheelgear, spare;
+}   ;
+*/
+bool    validate_mode_bytes (char * bytes)  {
+    int q;
+    for (int i = 0; i < numof_eeprom_options; i++)  {
+        q = (int)bytes[i];
+        if  (i == ID)
+            q |= '0';
+        if  (q < option_list[i].min || q > option_list[i].max)  
+            return  false;
+    }
+    return  true;
+}
+
+extern  uint32_t    sys_timer_32Hz;
+char * globdest = 0;    //  findable by code here responding to gbb
+bool    globflag;    //  findable by code here responding to gbb
+
+bool    get_bogie_bytes (int bogie_id, char * dest)   { //  bogie_id could be e.g. 3, or '3' NOTE 22/06/2018 yet to write matching fn in bogie code
+    uint32_t    localtime = sys_timer_32Hz + 50;    //  for timeout
+    bogie_id |= '0';                    //  ***** NOTE ***** THIS IS A BLOCKING FUNCTION
+    globdest = dest;
+    globflag = false;
+    com.printf  ("%cgbb\r", bogie_id);              //  issue gbb command to get bogie bytes to be coded into bogie
+    pc.printf   ("Issued %cgbb\r\n", bogie_id);
+    while   (!globflag && (localtime > sys_timer_32Hz))   {
+        clicore    (pccom);
+        clicore    (lococom);
+    }
+    return  globflag;   //  Returns false on timeout
+}
+
+void    make_option_bytes_from_dbls   (double * src, char * dest)   {   //  cli has sorted text string into array of doubles
+    for (int i = 0; i < numof_eeprom_options; i++)  {                   //  Turn this to string of mode bytes as stored in eeprom
+        dest[i] = (char)src[i];
+    }
+}
+
+char *    make_str_from_option_bytes  (char * src, char * dest)   {       //  Use for easy readback to pc
+    dest[0] = 0;    //  string null terminator
+    for (int i = 0; i < numof_eeprom_options; i++)  {
+        if  (i)
+            strcat  (dest, " ");    //  single space between outputs, no leading or trailing space
+        sprintf (dest + strlen(dest), "%d", (int)src[i]);
+    }
+    return  dest;
+}
+
+void    buggertest  (char * src)  {     //  src is string of option bytes read from eeprom
+    
+}
+void    mode_cmd (struct parameters & a)
+{
+    int error = 0, q;
+//    bool    valid_params = false;
+    pc.printf   ("At mode_cmd, numof parameters found=%d : numof parameters required=%d\r\n", a.numof_dbls, numof_eeprom_options);
+    for (int i = 0; i < numof_eeprom_options; i++)  {
+        q = (int)a.dbl[i];
+        if  (i == ID)
+            q |= '0';
+//        badf = false;
+        if  (q < option_list[i].min || q > option_list[i].max)  {
+//            badf = true;
+            error++;
+        }
+//        pc.printf   ("Parameter %s, entered %d, %s\r\n",option_list[i].t , q, badf ? "Bad":"Good");
+    }
+    if  (a.numof_dbls == numof_eeprom_options && !error)  {   //  correct num of options presented, proceed to blow eeproms
+        pc.printf   ("Congrats - looks like valid input!!\r\n");
+//        sprintf (txt, "%cmode",(int)a.dbl[ID]);
+        com.putc    ((int)a.dbl[ID]); //  have already checked is valid in range
+        com.printf  ("mode");
+        for (int i = 0; i < numof_eeprom_options; i++)
+            com.printf  (" %d", (int)a.dbl[i]);
+        com.putc    ('\r');
+        pc.printf   ("Have sent mode parameters down to %d\r\n", (int)a.dbl[ID]);
+    }
+    else    {   //  report only
+    }
+}
+
+
+void    menucmd (struct parameters & a);
+
+void    kd_cmd (struct parameters & a)  //  kick the watchdog
+{
+}
+
+void    uptem_cmd (struct parameters & a)  //  get temperature reading from bogie
+{
+    int bog_id = (int)a.dbl[0] | '0';
+    int temp = (int)a.dbl[1];
+    pc.printf   ("Read Temp %d from bogie id %d\r\n", temp, bog_id);
+}
+
+void    gbb_cmd (struct parameters & a)  //  handling bogie response to get bogie constants - bogie returns as string of nums in hex format
+{   //  decode bogie bytes and place in global array 'globdest', setting global 'globflag' when done. Code issuing 'gbb' deals with timeout
+    pc.printf   ("Arrived at gbb_cmd\r\n");
+    if  (globdest == 0) {
+        pc.printf   ("Fatal null ptr in gbb_cmd\r\n");
+        return;
+    }
+    pc.printf   ("Responding to gbb back from bogie\r\n");
+        for (int i = 0; i < numof_eeprom_options; i++)  {
+            globdest[i] = (char)a.dbl[i];
+        }
+        globflag = true;
+}
+
+void    upbc_cmd (struct parameters & a)  //  get bogie constants - wheel dia, motor pinion, wheel gear ** SUPERCEDED BY 'gbb'
+{
+    int bog_id = (int)a.dbl[0] | '0';
+    int wheeldia = (int)a.dbl[1];
+    int motorpin = (int)a.dbl[2];
+    int wheelgear = (int)a.dbl[3];
+    pc.printf   ("Read bogie constants from bogie id %d,wheel dia %d, motorpin %d, wheel gear %d\r\n", bog_id, wheeldia, motorpin, wheelgear);
+    for (int i = 0; i < MAX_BOGIES; i++)    {
+        if  (detected_bogie_options.bogie[i].p[ID] == bog_id)  {
+            detected_bogie_options.bogie[i].p[WHEELDIA]    = wheeldia; 
+            detected_bogie_options.bogie[i].p[MOTPIN]      = motorpin;
+            detected_bogie_options.bogie[i].p[WHEELGEAR]   = wheelgear;
+            pc.printf   ("Stored in detected_bogie_options [%d]\r\n", i);
+            i = MAX_BOGIES;
+        }
+    }
+}
+
+extern  void    rpm_push    (struct parameters & a)  ;
+void    uprpm_cmd (struct parameters & a)  //  controller rec'd rpm from driver boards
+{
+    rpm_push    (a);
+//    a.gp_i ^= 1;    //  toggle lsb
+}
+
+void    uprdi_cmd (struct parameters & a)  //  controller rec'd rpm from driver boards
+{
+//    pc.printf   ("RPM %d %d\r\n", (int)a.dbl[0], (int)a.dbl[1]);
+}
+
+
+/*void    who_cmd (struct parameters & a)
+{
+    int i = I_Am    ();
+    if  (I_Am() == a.target_unit)
+        pc.printf ("Hi there, I am %c\r\n", a.target_unit);
+}*/
+
+struct kb_command  {
+    const char * cmd_word;         //  points to text e.g. "menu"
+    const char * explan;
+    void (*f)(struct parameters &);   //  points to function
+}  ;
+
+struct  kb_command const command_list[] = {
+    {"ls", "Lists available commands", menucmd},
+    {"?", "Lists available commands, same as ls", menucmd},
+//    {"fw", "forward", fw_cmd},
+//    {"re", "reverse", re_cmd},
+//    {"rb", "regen brake 0 to 99 %", rb_cmd},
+//    {"hb", "hand brake", hb_cmd},
+//    {"v", "set motors V percent RANGE 0 to 100", v_cmd},
+//    {"i", "set motors I percent RANGE 0 to 100", i_cmd},
+//    {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd},
+//    {"who", "search for connected units, e.g. 3who returs 'Hi there' if found", who_cmd},
+    {"mode", "read or set params in eeprom", mode_cmd},
+//    {"erase", "set eeprom contents to all 0xff", erase_cmd},
+    {"kd", "kick the dog", kd_cmd},
+//    {"rpm", "rpm reading from 2 motors", uprpm_cmd},
+    {"nu", "do nothing", null_cmd},
+};
+
+const int numof_menu_items = sizeof(command_list) / sizeof(kb_command);
+void    menucmd (struct parameters & a)
+{
+//    struct kb_command const * cl = command_list;
+    pc.printf("\r\n\nTS_2018 Locomotive Touch Screen Controller\r\nAt menucmd function - listing commands:-\r\n");
+    for(int i = 0; i < numof_menu_items; i++)
+        pc.printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan);
+    pc.printf("End of List of Commands\r\n");
+}
+
+struct  kb_command const loco_command_list[] = {
+    {"ls", "Lists available commands", menucmd},
+    {"?", "Lists available commands, same as ls", menucmd},
+    {"rpm", "rpm reading from 2 motors", uprpm_cmd},
+    {"rdi", "rpm reading from 2 motors", uprdi_cmd},
+    {"tem", "report temperature", uptem_cmd},
+    {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", upbc_cmd},
+    {"gbb", "get bogie bytes, all of them", gbb_cmd},
+    {"nu", "do nothing", null_cmd},
+}   ;
+
+
+/*struct  parameters  {
+    struct kb_command const * clist;
+    char    cmd_line[120];
+    char    * cmd_line_ptr;
+    int32_t position_in_list, numof_dbls, target_unit, numof_menu_items;
+    double  dbl[MAX_PARAMS];
+    bool    respond;
+}   ;
+*/
+int getc    (int which_port)
+{
+    if  (which_port == 0)
+        return  pc.getc ();
+    if  (which_port == 1)
+        return  com.getc    ();
+    return  -1;
+}
+int readable    (int which_port)
+{
+    if  (which_port == 0)
+        return  pc.readable ();
+    if  (which_port == 1)
+        return  com.readable    ();
+    return  -1;
+
+}
+
+void setup_pccom ()
+{
+    pccom.clist = command_list;
+    pccom.numof_menu_items = sizeof(command_list) / sizeof(kb_command);
+    pccom.com_no    = 0;
+    pccom.cl_index  = 0;
+    pccom.gp_i      = 0;    //  general puropse integer, not used to 30/4/2018
+}
+
+void    setup_lococom ()
+{
+    lococom.clist = loco_command_list;
+    lococom.numof_menu_items = sizeof(loco_command_list) / sizeof(kb_command);
+    lococom.com_no  = 1;
+    lococom.cl_index    = 0;
+    lococom.gp_i        = 0;    //  general puropse integer, toggles 0 / 1 to best guess source of rpm
+}
+
+void    clicore (struct parameters & a)
+{
+    int ch;
+    char * pEnd;
+    while   (readable(a.com_no))    {
+        ch = getc   (a.com_no);
+        if(ch != '\r')  {   //  was this the 'Enter' key?
+//        if(ch != '\r' && ch != '\n')  //  was this the 'Enter' key?
+//            if  (ch != '\n')    a.cmd_line[a.cl_index++] = ch;  //  added char to command being assembled
+            a.cmd_line[a.cl_index++] = ch;  //  added char to command being assembled
+        }
+        else    {   //  key was CR, may or may not be command to lookup
+            a.target_unit = BROADCAST;    //  Broadcast
+            a.cmd_line_ptr = a.cmd_line;
+            a.cmd_line[a.cl_index] = 0; //  null terminate command string
+            if(a.cl_index)    {   //  If have got some chars to lookup
+                int i, wrdlen;
+                if  (isdigit(a.cmd_line[0]))  {   //  Look for command with prefix digit
+                    a.cmd_line_ptr++;     //  point past identified digit prefix
+                    a.target_unit = a.cmd_line[0];  //  '0' to '9'
+                    //pc.printf ("Got prefix %c\r\n", cmd_line[0]);
+                }
+                for (i = 0; i < a.numof_menu_items; i++)   {   //  Look for input match in command list
+                    wrdlen = strlen(a.clist[i].cmd_word);
+                    if(strncmp(a.clist[i].cmd_word, a.cmd_line_ptr, wrdlen) == 0 && !isalpha(a.cmd_line_ptr[wrdlen]))  {   //  If match found
+                        for (int k = 0; k < MAX_PARAMS; k++)    {
+                            a.dbl[k] = 0.0;
+                        }
+                        a.position_in_list = i;
+                        a.numof_dbls = 0;
+                        pEnd = a.cmd_line_ptr + wrdlen;
+                        while   (*pEnd)  {          //  Assemble all numerics as doubles
+                            a.dbl[a.numof_dbls++] = strtod    (pEnd, &pEnd);
+                            while   (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd)  {
+                                pEnd++;
+                            }
+                        }
+                        //pc.printf   ("\r\n");   //  Not allowed as many may output this.
+                        //for (int k = 0; k < param_block.numof_dbls; k++)
+                        //    pc.printf   ("Read %.3f\r\n", param_block.dbl[k]);
+//                            param_block.times[i] = clock();
+//                            if  ((param_block.target_unit == BROADCAST) && (I_Am() == '0'))
+//                                param_block.respond = true;
+                        a.clist[i].f(a);   //  execute command
+                        i = a.numof_menu_items + 1;    //  to exit for loop
+                    }   //  end of match found
+                }       // End of for numof_menu_items
+                if(i == a.numof_menu_items)
+                    pc.printf("No Match Found for CMD [%s]\r\n", a.cmd_line);
+            }           //  End of If have got some chars to lookup
+            //pc.printf("\r\n>");
+            a.cl_index = 0;
+        }               // End of else key was CR, may or may not be command to lookup
+    }                   //  End of while (pc.readable())
+}
+
+
+/*
+New - March 2018
+Using opto isolated serial port, paralleled up using same pair to multiple boards running this code.
+New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to.
+Commands without prefix digit - broadcast to all units, none to respond.
+Only units recognising its address from prefix digit may respond. This avoids bus contention.
+But for BROADCAST commands, '0' may respond on behalf of the group
+*/
+//void    command_line_interpreter    (void const *argument)
+/*void    command_line_interpreter    ()
+{
+    const int MAX_CMD_LEN = 120;
+    static  char    cmd_line[MAX_CMD_LEN + 4];
+    static  int     cl_index = 0;
+    int ch;
+    char * pEnd, * cmd_line_ptr;
+    static struct  parameters  param_block  ;
+    while  (pc.readable()) {
+        ch = pc.getc();
+//            if  (cl_index > MAX_CMD_LEN)  {   //  trap out stupidly long command lines
+//                pc.printf   ("Error!! Stupidly long cmd line\r\n");
+//                cl_index = 0;
+//            }
+        if(ch != '\r')  //  was this the 'Enter' key?
+            cmd_line[cl_index++] = ch;  //  added char to command being assembled
+        else    {   //  key was CR, may or may not be command to lookup
+            param_block.target_unit = BROADCAST;    //  Broadcast
+            cmd_line_ptr = cmd_line;
+            cmd_line[cl_index] = 0; //  null terminate command string
+            if(cl_index)    {   //  If have got some chars to lookup
+                int i, wrdlen;
+                if  (isdigit(cmd_line[0]))  {   //  Look for command with prefix digit
+                    cmd_line_ptr++;     //  point past identified digit prefix
+                    param_block.target_unit = cmd_line[0];  //  '0' to '9'
+                    //pc.printf ("Got prefix %c\r\n", cmd_line[0]);
+                }
+                for (i = 0; i < numof_menu_items; i++)   {   //  Look for input match in command list
+                    wrdlen = strlen(command_list[i].cmd_word);
+                    if(strncmp(command_list[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(cmd_line_ptr[wrdlen]))  {   //  If match found
+                        for (int k = 0; k < MAX_PARAMS; k++)    {
+                            param_block.dbl[k] = 0.0;
+                        }
+                        param_block.position_in_list = i;
+                        param_block.numof_dbls = 0;
+                        pEnd = cmd_line_ptr + wrdlen;
+                        while   (*pEnd)  {          //  Assemble all numerics as doubles
+                            param_block.dbl[param_block.numof_dbls++] = strtod    (pEnd, &pEnd);
+                            while   (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd)  {
+                                pEnd++;
+                            }
+                        }
+                        //pc.printf   ("\r\n");   //  Not allowed as many may output this.
+                        //for (int k = 0; k < param_block.numof_dbls; k++)
+                        //    pc.printf   ("Read %.3f\r\n", param_block.dbl[k]);
+//                            param_block.times[i] = clock();
+//                            if  ((param_block.target_unit == BROADCAST) && (I_Am() == '0'))
+//                                param_block.respond = true;
+                        command_list[i].f(param_block);   //  execute command
+                        i = numof_menu_items + 1;    //  to exit for loop
+                    }   //  end of match found
+                }       // End of for numof_menu_items
+                if(i == numof_menu_items)
+                    pc.printf("No Match Found for CMD [%s]\r\n", cmd_line);
+            }           //  End of If have got some chars to lookup
+            //pc.printf("\r\n>");
+            cl_index = 0;
+        }               // End of else key was CR, may or may not be command to lookup
+    }                   //  End of while (pc.readable())
+//        Thread::wait(20);  //  Using RTOS on this project
+//    }
+}
+*/
+