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

cli_TS_nortos.cpp

Committer:
JonFreeman
Date:
2019-01-14
Revision:
12:a25bdf135348
Parent:
11:a573664b1a59
Child:
14:6bcec5ac21ca

File content as of revision 12:a25bdf135348:

//Loco_TS_2018
#include "mbed.h"
#include "AsyncSerial.hpp"
#include <cctype>
#include "Electric_Loco.h"
using namespace std;

const int   BROADCAST   = '\r';

//  WithOUT RTOS
extern  Serial pc;
extern  AsyncSerial com2escs;
extern  error_handling_Jan_2019   Controller_Error    ;
extern  const   char   const_version_string[] ;  //  Version string, readable from serial ports

extern  STM3_ESC_Interface    My_STM3_ESC_boards   ;

/*genio::genio    (int dtype, int dlen)  {    //  constructor
    d_type = dtype;
    d_len = dlen;
    for (int i = 0; i < MAX_PARAMS; i++)    {
        si[i] = 0;
        dbl[i] = 0.0;
    }
    count = 0;  //  running total of times called
    available = false;  //  bool
    //available = 0; // if using integer rather than bool
}

void    genio::store   (struct parameters & a)  {   //  copies up to MAX_PARAMS into int and double arrays
    count++;            //  number of times this response rec'd this session
    available = true;
    for (int i = 0; i < d_len; i++) {   //  dlen //  loaded on setup indicating expected num of parameters to handle. Why not just use MAX_PARAMS ?
        si[i] = (int32_t)a.dbl[i];
        dbl[i] = a.dbl[i];
    }
}

bool    genio::read    (int32_t ** addr)  {
    if  (!available)
        return  false;
    available = false;
    *addr = si;         //      int32_t    ui[MAX_PARAMS];
    return  true;
}
*/

command_line_interpreter_core::command_line_interpreter_core    (int p, int menulen, struct kb_command const * clistp)  {
    clist = clistp;
    a.numof_menu_items = menulen;
    a.numof_cl_values_read = 0;
    portio = p;
    cl_index = 0;
}

int     command_line_interpreter_core::clreadable    ()  {
    if  (portio == 0)
        return  pc.readable();
    return  com2escs.readable();
}  

void    command_line_interpreter_core::clputc    (int c)  {
    if  (portio == 0)
        pc.putc (c);
    else
        com2escs.putc   (c);
}  

int     command_line_interpreter_core::clgetc    ()  {
    if  (portio == 0)
        return  pc.getc();
    return  com2escs.getc();
}  


void    null_cmd (struct parameters & a)
{
    pc.printf   ("At null_cmd, parameters : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
}

void    menucmd (struct parameters & a);

void    kd_cmd (struct parameters & a)  //  kick the watchdog
{
}

void    upmph_cmd (struct parameters & a)  //  controller rec'd mph from driver boards
{
    My_STM3_ESC_boards.mph_update  (a.dbl[1]);
}


void    TSver_cmd (struct parameters & a)  //   Report current TS software version to pc
{
    pc.printf   ("ver %s\r\n", const_version_string);
}

void    boards_cmd  (struct parameters & a) {
    int boards[MAX_ESCS], count = 0;
    My_STM3_ESC_boards.get_boards_list   (boards);
    while  (boards[count] && count < MAX_ESCS)
        count++;
    pc.printf   ("Board Count = %d\r\n", count);
    if  (count) {
        pc.printf   ("Boards found ^");
        for (int i = 0; i < count; i++)
            pc.printf   ("%c ", boards[i]);
        pc.printf   ("\r\n");
    }
    else
        pc.printf   ("No STM3_ESC boards found\r\n");
}

void    who_cmd (struct parameters & a)  //   Have read "whon" back from STM3_ESC where 'n' is STM3_Esc board ID number (ascii digit)
{
    int v = (int)a.dbl[0] | '0';
    if  (a.numof_cl_values_read == 1 && isdigit(v)) {
//        pc.printf   ("who%c, vals read %d\r\n", (int)a.dbl[0] | '0', a.numof_cl_values_read);
        My_STM3_ESC_boards.set_board_ID  (v);//        set_board_id    (v);  //  just to test and prove can not add same board twice
    }
    else
        pc.printf   ("Garbage response to 'who', numof vals %d, value %c\r\n", a.numof_cl_values_read, v);
}

void    ver_req_cmd (struct parameters & a)  //   Touch Screen controller requesting version string from one specific ESC board
{
    pc.printf   ("ver_req_cmd not yet implemented\r\n");
}

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},
    {"ver", "report const_version_string", TSver_cmd},        //  Report TS controller version
    {"boards", "List STM3_ESC boards connected", boards_cmd},
    {"kd", "kick the dog", kd_cmd},
    {"nu", "do nothing", null_cmd},
};

struct  kb_command const loco_command_list[] = {
    {"ls", "Lists available commands", menucmd},
    {"?", "Lists available commands, same as ls", menucmd},
    {"who", "Reads 'whon' response from STM3_ESC where 'n' is board num ascii from eeprom", who_cmd},
    {"ver", "report const_version_string", ver_req_cmd},    //  Request software version of one specific ESC board
    {"mph", "bogie mph reading", upmph_cmd},    //  22/06/2018
    {"nu", "do nothing", null_cmd},
}   ;


void    menucmd (struct parameters & a)
{
    pc.printf("\r\n\nTS_2018 Locomotive Touch Screen Controller\r\nAt menucmd function - listing commands:-\r\n");
    for(int i = 0; i < a.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");
}


/**
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
*/
command_line_interpreter_core   pcli    (0, sizeof(command_list) / sizeof(kb_command), command_list);
command_line_interpreter_core   ploco   (1, sizeof(loco_command_list) / sizeof(kb_command), loco_command_list);

void    command_line_interpreter_core::sniff    ()  {   //  look for recieved commands and act upon them
    int ch;
    char * pEnd;
    while   (clreadable())    {
        ch = clgetc   ();
        if(ch != '\r')  {//  was this the 'Enter' key?
            if  (ch != '\n')    {   //  Ignore line feeds
                cmd_line[cl_index++] = ch;  //  added char to command being assembled
                if  (cl_index >= MAX_CMD_LINE_LEN-2)  {
                    cl_index = 0;     //  Line is garbage anyway, so might as well junk the lot ?
                    pc.printf   ("cl_index=%d TOO LONG in clicore\r\n", cl_index);
                    Controller_Error.set    (FAULT_COM_LINE_LEN, 1);
                }
            }       //  endof if(ch != '\n')    ignore line feeds
        }           //  endof if(ch != '\r')    
        else    {   //  key was CR, may or may not be command to lookup
            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
                    target_unit = cmd_line[0];  //  '0' to '9'
                    //pc.printf ("Got prefix %c\r\n", a.cmd_line[0]);
                }
                for (i = 0; i < a.numof_menu_items; i++)   {   //  Look for input match in command list
                    wrdlen = strlen(clist[i].cmd_word);
                    if(strncmp(clist[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(cmd_line_ptr[wrdlen]))  {   //  If match found
                        for (int k = 0; k < MAX_PARAMS; k++)    {
                            a.dbl[k] = 0.0;
                        }
                        //position_in_list = i;
                        a.numof_cl_values_read = 0;
                        pEnd = cmd_line_ptr + wrdlen;
                        while   (*pEnd)  {          //  Assemble all numerics as doubles
                            a.dbl[a.numof_cl_values_read++] = 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.a.numof_cl_values_read; 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;
                        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", cmd_line);
                    Controller_Error.set    (FAULT_COM_NO_MATCH, 1);
                }
            }           //  End of If have got some chars to lookup
            cl_index = 0;
        }               // End of else key was CR, may or may not be command to lookup
    }                   //  End of while (pc.readable())
}