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@12:a25bdf135348, 2019-01-14 (annotated)
- Committer:
- JonFreeman
- Date:
- Mon Jan 14 16:39:41 2019 +0000
- Revision:
- 12:a25bdf135348
- Parent:
- 11:a573664b1a59
- Child:
- 14:6bcec5ac21ca
Tidied, better documented, more OOP, interim release
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JonFreeman | 5:21a8ac83142c | 1 | //Loco_TS_2018 |
JonFreeman | 4:67478861c670 | 2 | #include "mbed.h" |
JonFreeman | 5:21a8ac83142c | 3 | #include "AsyncSerial.hpp" |
JonFreeman | 4:67478861c670 | 4 | #include <cctype> |
JonFreeman | 4:67478861c670 | 5 | #include "Electric_Loco.h" |
JonFreeman | 4:67478861c670 | 6 | using namespace std; |
JonFreeman | 4:67478861c670 | 7 | |
JonFreeman | 4:67478861c670 | 8 | const int BROADCAST = '\r'; |
JonFreeman | 4:67478861c670 | 9 | |
JonFreeman | 4:67478861c670 | 10 | // WithOUT RTOS |
JonFreeman | 4:67478861c670 | 11 | extern Serial pc; |
JonFreeman | 12:a25bdf135348 | 12 | extern AsyncSerial com2escs; |
JonFreeman | 12:a25bdf135348 | 13 | extern error_handling_Jan_2019 Controller_Error ; |
JonFreeman | 12:a25bdf135348 | 14 | extern const char const_version_string[] ; // Version string, readable from serial ports |
JonFreeman | 4:67478861c670 | 15 | |
JonFreeman | 12:a25bdf135348 | 16 | extern STM3_ESC_Interface My_STM3_ESC_boards ; |
JonFreeman | 12:a25bdf135348 | 17 | |
JonFreeman | 12:a25bdf135348 | 18 | /*genio::genio (int dtype, int dlen) { // constructor |
JonFreeman | 11:a573664b1a59 | 19 | d_type = dtype; |
JonFreeman | 11:a573664b1a59 | 20 | d_len = dlen; |
JonFreeman | 11:a573664b1a59 | 21 | for (int i = 0; i < MAX_PARAMS; i++) { |
JonFreeman | 12:a25bdf135348 | 22 | si[i] = 0; |
JonFreeman | 11:a573664b1a59 | 23 | dbl[i] = 0.0; |
JonFreeman | 11:a573664b1a59 | 24 | } |
JonFreeman | 12:a25bdf135348 | 25 | count = 0; // running total of times called |
JonFreeman | 12:a25bdf135348 | 26 | available = false; // bool |
JonFreeman | 12:a25bdf135348 | 27 | //available = 0; // if using integer rather than bool |
JonFreeman | 11:a573664b1a59 | 28 | } |
JonFreeman | 11:a573664b1a59 | 29 | |
JonFreeman | 12:a25bdf135348 | 30 | void genio::store (struct parameters & a) { // copies up to MAX_PARAMS into int and double arrays |
JonFreeman | 12:a25bdf135348 | 31 | count++; // number of times this response rec'd this session |
JonFreeman | 11:a573664b1a59 | 32 | available = true; |
JonFreeman | 12:a25bdf135348 | 33 | 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 ? |
JonFreeman | 12:a25bdf135348 | 34 | si[i] = (int32_t)a.dbl[i]; |
JonFreeman | 11:a573664b1a59 | 35 | dbl[i] = a.dbl[i]; |
JonFreeman | 11:a573664b1a59 | 36 | } |
JonFreeman | 11:a573664b1a59 | 37 | } |
JonFreeman | 11:a573664b1a59 | 38 | |
JonFreeman | 12:a25bdf135348 | 39 | bool genio::read (int32_t ** addr) { |
JonFreeman | 11:a573664b1a59 | 40 | if (!available) |
JonFreeman | 11:a573664b1a59 | 41 | return false; |
JonFreeman | 11:a573664b1a59 | 42 | available = false; |
JonFreeman | 12:a25bdf135348 | 43 | *addr = si; // int32_t ui[MAX_PARAMS]; |
JonFreeman | 11:a573664b1a59 | 44 | return true; |
JonFreeman | 11:a573664b1a59 | 45 | } |
JonFreeman | 12:a25bdf135348 | 46 | */ |
JonFreeman | 12:a25bdf135348 | 47 | |
JonFreeman | 12:a25bdf135348 | 48 | command_line_interpreter_core::command_line_interpreter_core (int p, int menulen, struct kb_command const * clistp) { |
JonFreeman | 12:a25bdf135348 | 49 | clist = clistp; |
JonFreeman | 12:a25bdf135348 | 50 | a.numof_menu_items = menulen; |
JonFreeman | 12:a25bdf135348 | 51 | a.numof_cl_values_read = 0; |
JonFreeman | 12:a25bdf135348 | 52 | portio = p; |
JonFreeman | 12:a25bdf135348 | 53 | cl_index = 0; |
JonFreeman | 12:a25bdf135348 | 54 | } |
JonFreeman | 12:a25bdf135348 | 55 | |
JonFreeman | 12:a25bdf135348 | 56 | int command_line_interpreter_core::clreadable () { |
JonFreeman | 12:a25bdf135348 | 57 | if (portio == 0) |
JonFreeman | 12:a25bdf135348 | 58 | return pc.readable(); |
JonFreeman | 12:a25bdf135348 | 59 | return com2escs.readable(); |
JonFreeman | 12:a25bdf135348 | 60 | } |
JonFreeman | 12:a25bdf135348 | 61 | |
JonFreeman | 12:a25bdf135348 | 62 | void command_line_interpreter_core::clputc (int c) { |
JonFreeman | 12:a25bdf135348 | 63 | if (portio == 0) |
JonFreeman | 12:a25bdf135348 | 64 | pc.putc (c); |
JonFreeman | 12:a25bdf135348 | 65 | else |
JonFreeman | 12:a25bdf135348 | 66 | com2escs.putc (c); |
JonFreeman | 12:a25bdf135348 | 67 | } |
JonFreeman | 12:a25bdf135348 | 68 | |
JonFreeman | 12:a25bdf135348 | 69 | int command_line_interpreter_core::clgetc () { |
JonFreeman | 12:a25bdf135348 | 70 | if (portio == 0) |
JonFreeman | 12:a25bdf135348 | 71 | return pc.getc(); |
JonFreeman | 12:a25bdf135348 | 72 | return com2escs.getc(); |
JonFreeman | 12:a25bdf135348 | 73 | } |
JonFreeman | 12:a25bdf135348 | 74 | |
JonFreeman | 11:a573664b1a59 | 75 | |
JonFreeman | 5:21a8ac83142c | 76 | void null_cmd (struct parameters & a) |
JonFreeman | 5:21a8ac83142c | 77 | { |
JonFreeman | 4:67478861c670 | 78 | pc.printf ("At null_cmd, parameters : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]); |
JonFreeman | 4:67478861c670 | 79 | } |
JonFreeman | 4:67478861c670 | 80 | |
JonFreeman | 4:67478861c670 | 81 | void menucmd (struct parameters & a); |
JonFreeman | 4:67478861c670 | 82 | |
JonFreeman | 4:67478861c670 | 83 | void kd_cmd (struct parameters & a) // kick the watchdog |
JonFreeman | 4:67478861c670 | 84 | { |
JonFreeman | 4:67478861c670 | 85 | } |
JonFreeman | 4:67478861c670 | 86 | |
JonFreeman | 11:a573664b1a59 | 87 | void upmph_cmd (struct parameters & a) // controller rec'd mph from driver boards |
JonFreeman | 11:a573664b1a59 | 88 | { |
JonFreeman | 12:a25bdf135348 | 89 | My_STM3_ESC_boards.mph_update (a.dbl[1]); |
JonFreeman | 5:21a8ac83142c | 90 | } |
JonFreeman | 5:21a8ac83142c | 91 | |
JonFreeman | 4:67478861c670 | 92 | |
JonFreeman | 12:a25bdf135348 | 93 | void TSver_cmd (struct parameters & a) // Report current TS software version to pc |
JonFreeman | 4:67478861c670 | 94 | { |
JonFreeman | 12:a25bdf135348 | 95 | pc.printf ("ver %s\r\n", const_version_string); |
JonFreeman | 12:a25bdf135348 | 96 | } |
JonFreeman | 12:a25bdf135348 | 97 | |
JonFreeman | 12:a25bdf135348 | 98 | void boards_cmd (struct parameters & a) { |
JonFreeman | 12:a25bdf135348 | 99 | int boards[MAX_ESCS], count = 0; |
JonFreeman | 12:a25bdf135348 | 100 | My_STM3_ESC_boards.get_boards_list (boards); |
JonFreeman | 12:a25bdf135348 | 101 | while (boards[count] && count < MAX_ESCS) |
JonFreeman | 12:a25bdf135348 | 102 | count++; |
JonFreeman | 12:a25bdf135348 | 103 | pc.printf ("Board Count = %d\r\n", count); |
JonFreeman | 12:a25bdf135348 | 104 | if (count) { |
JonFreeman | 12:a25bdf135348 | 105 | pc.printf ("Boards found ^"); |
JonFreeman | 12:a25bdf135348 | 106 | for (int i = 0; i < count; i++) |
JonFreeman | 12:a25bdf135348 | 107 | pc.printf ("%c ", boards[i]); |
JonFreeman | 12:a25bdf135348 | 108 | pc.printf ("\r\n"); |
JonFreeman | 12:a25bdf135348 | 109 | } |
JonFreeman | 12:a25bdf135348 | 110 | else |
JonFreeman | 12:a25bdf135348 | 111 | pc.printf ("No STM3_ESC boards found\r\n"); |
JonFreeman | 12:a25bdf135348 | 112 | } |
JonFreeman | 12:a25bdf135348 | 113 | |
JonFreeman | 12:a25bdf135348 | 114 | void who_cmd (struct parameters & a) // Have read "whon" back from STM3_ESC where 'n' is STM3_Esc board ID number (ascii digit) |
JonFreeman | 12:a25bdf135348 | 115 | { |
JonFreeman | 12:a25bdf135348 | 116 | int v = (int)a.dbl[0] | '0'; |
JonFreeman | 12:a25bdf135348 | 117 | if (a.numof_cl_values_read == 1 && isdigit(v)) { |
JonFreeman | 12:a25bdf135348 | 118 | // pc.printf ("who%c, vals read %d\r\n", (int)a.dbl[0] | '0', a.numof_cl_values_read); |
JonFreeman | 12:a25bdf135348 | 119 | My_STM3_ESC_boards.set_board_ID (v);// set_board_id (v); // just to test and prove can not add same board twice |
JonFreeman | 12:a25bdf135348 | 120 | } |
JonFreeman | 12:a25bdf135348 | 121 | else |
JonFreeman | 12:a25bdf135348 | 122 | pc.printf ("Garbage response to 'who', numof vals %d, value %c\r\n", a.numof_cl_values_read, v); |
JonFreeman | 12:a25bdf135348 | 123 | } |
JonFreeman | 12:a25bdf135348 | 124 | |
JonFreeman | 12:a25bdf135348 | 125 | void ver_req_cmd (struct parameters & a) // Touch Screen controller requesting version string from one specific ESC board |
JonFreeman | 12:a25bdf135348 | 126 | { |
JonFreeman | 12:a25bdf135348 | 127 | pc.printf ("ver_req_cmd not yet implemented\r\n"); |
JonFreeman | 12:a25bdf135348 | 128 | } |
JonFreeman | 4:67478861c670 | 129 | |
JonFreeman | 4:67478861c670 | 130 | struct kb_command { |
JonFreeman | 4:67478861c670 | 131 | const char * cmd_word; // points to text e.g. "menu" |
JonFreeman | 4:67478861c670 | 132 | const char * explan; |
JonFreeman | 4:67478861c670 | 133 | void (*f)(struct parameters &); // points to function |
JonFreeman | 4:67478861c670 | 134 | } ; |
JonFreeman | 4:67478861c670 | 135 | |
JonFreeman | 4:67478861c670 | 136 | struct kb_command const command_list[] = { |
JonFreeman | 4:67478861c670 | 137 | {"ls", "Lists available commands", menucmd}, |
JonFreeman | 4:67478861c670 | 138 | {"?", "Lists available commands, same as ls", menucmd}, |
JonFreeman | 12:a25bdf135348 | 139 | {"ver", "report const_version_string", TSver_cmd}, // Report TS controller version |
JonFreeman | 12:a25bdf135348 | 140 | {"boards", "List STM3_ESC boards connected", boards_cmd}, |
JonFreeman | 4:67478861c670 | 141 | {"kd", "kick the dog", kd_cmd}, |
JonFreeman | 4:67478861c670 | 142 | {"nu", "do nothing", null_cmd}, |
JonFreeman | 4:67478861c670 | 143 | }; |
JonFreeman | 4:67478861c670 | 144 | |
JonFreeman | 5:21a8ac83142c | 145 | struct kb_command const loco_command_list[] = { |
JonFreeman | 5:21a8ac83142c | 146 | {"ls", "Lists available commands", menucmd}, |
JonFreeman | 5:21a8ac83142c | 147 | {"?", "Lists available commands, same as ls", menucmd}, |
JonFreeman | 12:a25bdf135348 | 148 | {"who", "Reads 'whon' response from STM3_ESC where 'n' is board num ascii from eeprom", who_cmd}, |
JonFreeman | 12:a25bdf135348 | 149 | {"ver", "report const_version_string", ver_req_cmd}, // Request software version of one specific ESC board |
JonFreeman | 11:a573664b1a59 | 150 | {"mph", "bogie mph reading", upmph_cmd}, // 22/06/2018 |
JonFreeman | 5:21a8ac83142c | 151 | {"nu", "do nothing", null_cmd}, |
JonFreeman | 5:21a8ac83142c | 152 | } ; |
JonFreeman | 5:21a8ac83142c | 153 | |
JonFreeman | 5:21a8ac83142c | 154 | |
JonFreeman | 12:a25bdf135348 | 155 | void menucmd (struct parameters & a) |
JonFreeman | 5:21a8ac83142c | 156 | { |
JonFreeman | 12:a25bdf135348 | 157 | pc.printf("\r\n\nTS_2018 Locomotive Touch Screen Controller\r\nAt menucmd function - listing commands:-\r\n"); |
JonFreeman | 12:a25bdf135348 | 158 | for(int i = 0; i < a.numof_menu_items; i++) |
JonFreeman | 12:a25bdf135348 | 159 | pc.printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan); |
JonFreeman | 12:a25bdf135348 | 160 | pc.printf("End of List of Commands\r\n"); |
JonFreeman | 5:21a8ac83142c | 161 | } |
JonFreeman | 5:21a8ac83142c | 162 | |
JonFreeman | 4:67478861c670 | 163 | |
JonFreeman | 12:a25bdf135348 | 164 | /** |
JonFreeman | 4:67478861c670 | 165 | New - March 2018 |
JonFreeman | 4:67478861c670 | 166 | Using opto isolated serial port, paralleled up using same pair to multiple boards running this code. |
JonFreeman | 4:67478861c670 | 167 | New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to. |
JonFreeman | 4:67478861c670 | 168 | Commands without prefix digit - broadcast to all units, none to respond. |
JonFreeman | 4:67478861c670 | 169 | Only units recognising its address from prefix digit may respond. This avoids bus contention. |
JonFreeman | 4:67478861c670 | 170 | But for BROADCAST commands, '0' may respond on behalf of the group |
JonFreeman | 4:67478861c670 | 171 | */ |
JonFreeman | 12:a25bdf135348 | 172 | command_line_interpreter_core pcli (0, sizeof(command_list) / sizeof(kb_command), command_list); |
JonFreeman | 12:a25bdf135348 | 173 | command_line_interpreter_core ploco (1, sizeof(loco_command_list) / sizeof(kb_command), loco_command_list); |
JonFreeman | 12:a25bdf135348 | 174 | |
JonFreeman | 12:a25bdf135348 | 175 | void command_line_interpreter_core::sniff () { // look for recieved commands and act upon them |
JonFreeman | 5:21a8ac83142c | 176 | int ch; |
JonFreeman | 12:a25bdf135348 | 177 | char * pEnd; |
JonFreeman | 12:a25bdf135348 | 178 | while (clreadable()) { |
JonFreeman | 12:a25bdf135348 | 179 | ch = clgetc (); |
JonFreeman | 12:a25bdf135348 | 180 | if(ch != '\r') {// was this the 'Enter' key? |
JonFreeman | 12:a25bdf135348 | 181 | if (ch != '\n') { // Ignore line feeds |
JonFreeman | 12:a25bdf135348 | 182 | cmd_line[cl_index++] = ch; // added char to command being assembled |
JonFreeman | 12:a25bdf135348 | 183 | if (cl_index >= MAX_CMD_LINE_LEN-2) { |
JonFreeman | 12:a25bdf135348 | 184 | cl_index = 0; // Line is garbage anyway, so might as well junk the lot ? |
JonFreeman | 12:a25bdf135348 | 185 | pc.printf ("cl_index=%d TOO LONG in clicore\r\n", cl_index); |
JonFreeman | 12:a25bdf135348 | 186 | Controller_Error.set (FAULT_COM_LINE_LEN, 1); |
JonFreeman | 12:a25bdf135348 | 187 | } |
JonFreeman | 12:a25bdf135348 | 188 | } // endof if(ch != '\n') ignore line feeds |
JonFreeman | 12:a25bdf135348 | 189 | } // endof if(ch != '\r') |
JonFreeman | 5:21a8ac83142c | 190 | else { // key was CR, may or may not be command to lookup |
JonFreeman | 12:a25bdf135348 | 191 | target_unit = BROADCAST; // Broadcast |
JonFreeman | 5:21a8ac83142c | 192 | cmd_line_ptr = cmd_line; |
JonFreeman | 5:21a8ac83142c | 193 | cmd_line[cl_index] = 0; // null terminate command string |
JonFreeman | 5:21a8ac83142c | 194 | if(cl_index) { // If have got some chars to lookup |
JonFreeman | 5:21a8ac83142c | 195 | int i, wrdlen; |
JonFreeman | 5:21a8ac83142c | 196 | if (isdigit(cmd_line[0])) { // Look for command with prefix digit |
JonFreeman | 5:21a8ac83142c | 197 | cmd_line_ptr++; // point past identified digit prefix |
JonFreeman | 12:a25bdf135348 | 198 | target_unit = cmd_line[0]; // '0' to '9' |
JonFreeman | 12:a25bdf135348 | 199 | //pc.printf ("Got prefix %c\r\n", a.cmd_line[0]); |
JonFreeman | 5:21a8ac83142c | 200 | } |
JonFreeman | 12:a25bdf135348 | 201 | for (i = 0; i < a.numof_menu_items; i++) { // Look for input match in command list |
JonFreeman | 12:a25bdf135348 | 202 | wrdlen = strlen(clist[i].cmd_word); |
JonFreeman | 12:a25bdf135348 | 203 | if(strncmp(clist[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(cmd_line_ptr[wrdlen])) { // If match found |
JonFreeman | 5:21a8ac83142c | 204 | for (int k = 0; k < MAX_PARAMS; k++) { |
JonFreeman | 12:a25bdf135348 | 205 | a.dbl[k] = 0.0; |
JonFreeman | 5:21a8ac83142c | 206 | } |
JonFreeman | 12:a25bdf135348 | 207 | //position_in_list = i; |
JonFreeman | 12:a25bdf135348 | 208 | a.numof_cl_values_read = 0; |
JonFreeman | 5:21a8ac83142c | 209 | pEnd = cmd_line_ptr + wrdlen; |
JonFreeman | 5:21a8ac83142c | 210 | while (*pEnd) { // Assemble all numerics as doubles |
JonFreeman | 12:a25bdf135348 | 211 | a.dbl[a.numof_cl_values_read++] = strtod (pEnd, &pEnd); |
JonFreeman | 5:21a8ac83142c | 212 | while (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd) { |
JonFreeman | 5:21a8ac83142c | 213 | pEnd++; |
JonFreeman | 4:67478861c670 | 214 | } |
JonFreeman | 5:21a8ac83142c | 215 | } |
JonFreeman | 5:21a8ac83142c | 216 | //pc.printf ("\r\n"); // Not allowed as many may output this. |
JonFreeman | 12:a25bdf135348 | 217 | //for (int k = 0; k < param_block.a.numof_cl_values_read; k++) |
JonFreeman | 5:21a8ac83142c | 218 | // pc.printf ("Read %.3f\r\n", param_block.dbl[k]); |
JonFreeman | 4:67478861c670 | 219 | // param_block.times[i] = clock(); |
JonFreeman | 4:67478861c670 | 220 | // if ((param_block.target_unit == BROADCAST) && (I_Am() == '0')) |
JonFreeman | 4:67478861c670 | 221 | // param_block.respond = true; |
JonFreeman | 12:a25bdf135348 | 222 | clist[i].f(a); // execute command |
JonFreeman | 12:a25bdf135348 | 223 | i = a.numof_menu_items + 1; // to exit for loop |
JonFreeman | 5:21a8ac83142c | 224 | } // end of match found |
JonFreeman | 5:21a8ac83142c | 225 | } // End of for numof_menu_items |
JonFreeman | 12:a25bdf135348 | 226 | if(i == a.numof_menu_items) { |
JonFreeman | 5:21a8ac83142c | 227 | pc.printf("No Match Found for CMD [%s]\r\n", cmd_line); |
JonFreeman | 12:a25bdf135348 | 228 | Controller_Error.set (FAULT_COM_NO_MATCH, 1); |
JonFreeman | 12:a25bdf135348 | 229 | } |
JonFreeman | 5:21a8ac83142c | 230 | } // End of If have got some chars to lookup |
JonFreeman | 5:21a8ac83142c | 231 | cl_index = 0; |
JonFreeman | 5:21a8ac83142c | 232 | } // End of else key was CR, may or may not be command to lookup |
JonFreeman | 5:21a8ac83142c | 233 | } // End of while (pc.readable()) |
JonFreeman | 12:a25bdf135348 | 234 | } |
JonFreeman | 4:67478861c670 | 235 | |
JonFreeman | 12:a25bdf135348 | 236 |