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
Diff: cli_TS_nortos.cpp
- 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 +// } +} +*/ +