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()) }