Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: TS_DISCO_F746NG mbed Servo LCD_DISCO_F746NG BSP_DISCO_F746NG QSPI_DISCO_F746NG AsyncSerial FastPWM
Diff: touch_handler.cpp
- Revision:
- 12:a25bdf135348
diff -r a573664b1a59 -r a25bdf135348 touch_handler.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/touch_handler.cpp Mon Jan 14 16:39:41 2019 +0000
@@ -0,0 +1,269 @@
+#include "mbed.h"
+#include "Electric_Loco.h"
+#include "TS_DISCO_F746NG.h"
+#include "LCD_DISCO_F746NG.h"
+
+/**
+void read_keypresses (struct ky_bd & a)
+Sets values in struct ky_bd, containing :
+ struct ky_bd { int count, slider_y; keystr key[MAX_TOUCHES + 1]; bool sli; } ;
+ struct keystr { int keynum; int x; int y; } ;
+ sets a.count to number of fingers found pressing buttons
+ fills a.key[].keynum with list of 'a.count' button return codes
+ fills corresponding a.key[].x and a.key[].y with finger coordinates
+ if button is SLIDER_BUTTON
+ sets a.sli true else sets false
+ sets a.slider_y with new slider y coordinate - 0 at top
+*/
+extern STM3_ESC_Interface My_STM3_ESC_boards ;
+extern void throttle (double p) ; // New Apr 2018 ; servo adjusts throttle lever on Honda GX120
+extern void read_keypresses (struct ky_bd & a) ;
+extern void draw_button_hilight (int but, int colour) ;
+extern void draw_button (struct button_specs & bu, int body_colour) ;
+extern void horn (int which, int onoff) ;
+
+extern Serial pc;
+/**
+int screen_touch_handler::viscous_drag (int up_viscosity, int dn_viscosity) ;
+ Usage
+ position = viscous_drag (a, b);
+ Uses latest slider_y and present 'position'
+ Returns a value for new position moved in direction by amount determined by difference but reduced more for high viscosity
+ This allows for different rates of control movement for rise and fall
+*/
+int screen_touch_handler::viscous_drag (int ip, double up_drag, double dn_drag) {
+ int s = (ip - position); // ip is final destination position of slider on scale
+ if (!s) // If no movement
+ return position;
+ int rv;
+ double d = (double) s;
+ if (up_drag < 0.1) up_drag = 0.1;
+ if (dn_drag < 0.1) dn_drag = 0.1; // avoiding DIV0 errors
+ if (s < 0) { // Finger has moved up the slider
+ rv = position - 1 + (int)(d / up_drag);
+ }
+ if (s > 0) { // Finger has moved down the slider
+ rv = position + 1 + (int)(d / dn_drag);
+ }
+ return rv;
+}
+
+void screen_touch_handler::flush () { // clear keyboard buffers
+ kybd_a.count = kybd_b.count = 0;
+ for (int i = 0; i <= MAX_TOUCHES; i++) {
+ kybd_a.key[i].keynum = kybd_b.key[i].keynum = 0;
+ }
+}
+/*
+Dealing with Keys Pressed
+ This time and Last time AUTOREPEAT
+ This time and !Last time NEW_PRESS
+ !This time and Last time NEW_RELEASE
+ !This time and !Last time not detectable as key not in either list
+*/
+
+/**
+bool in_list (struct ky_bd & a, int key)
+Scans current keyboard buffer searching for 'key'.
+Returns true if found, false otherwise
+*/
+bool screen_touch_handler::in_list (struct ky_bd & a, int key)
+{
+ int i = 0;
+ while (i < a.count)
+ if (key == a.key[i++].keynum)
+ return true;
+ return false;
+}
+
+void screen_touch_handler::motor_power () { // uses position to set motor volts and amps and Honda throttle
+ int b = NEUTRAL_VAL - position; // now got integer going positive for increasing power demand
+ double torque_req = ((double) b) / (double)(NEUTRAL_VAL - MIN_POS); // in range 0.0 to 1.0
+ if (torque_req < 0.0) torque_req = 0.0;
+ if (torque_req > 1.0) torque_req = 1.0;
+// pc.printf ("torque_rec = %.3f, last_V = %.3f\r\n", torque_req, last_V);
+ My_STM3_ESC_boards.set_I_limit (torque_req);
+ if (torque_req < 0.05) {
+ My_STM3_ESC_boards.set_V_limit (My_STM3_ESC_boards.last_V / 2.0);
+ throttle (torque_req * 6.0);
+ }
+ else { // torque_rec >= 0.05
+ throttle (0.3 + (torque_req / 2.0));
+ if (My_STM3_ESC_boards.last_V < 0.99)
+ My_STM3_ESC_boards.set_V_limit (My_STM3_ESC_boards.last_V + 0.05); // ramp voltage up rather than slam to max
+ } // endof if/else (torque_req < 0.05) {
+}
+
+
+void screen_touch_handler::HandleFingerInput () {
+ int key;
+ if (present_kybd == &kybd_b) { // swap keyboard buffers
+ present_kybd = &kybd_a;
+ previous_kybd = &kybd_b;
+ } else {
+ present_kybd = &kybd_b;
+ previous_kybd = &kybd_a;
+ }
+ read_keypresses (*present_kybd);
+
+// slider_state_machine (); // Takes care of all actions required of slider
+
+//void screen_touch_handler::slider_state_machine () {
+ int old_position = position; // Used at end to decide if screen update required
+ switch (next_state) {
+
+ case NEUTRAL_DRIFT: // slider is at 'N', loco not being driven or braked but may well be rolling
+ if (present_kybd->sli && previous_kybd->sli) { // finger is definitely on slider, found this time and last time
+ if (present_kybd->slider_y < NEUTRAL_VAL)
+ next_state = INTO_RUN;
+ if (present_kybd->slider_y > NEUTRAL_VAL)
+ next_state = INTO_REGEN_BRAKE;
+ }
+ break; // endof case NEUTRAL_DRIFT
+
+ case INTO_NEUTRAL_DRIFT:
+ My_STM3_ESC_boards.set_I_limit (0.0);
+ My_STM3_ESC_boards.set_V_limit (0.0);
+ throttle (0.0); // Honda revs to tickover
+ position = NEUTRAL_VAL; // 'position' is copy of slider_y after application of any viscous damping
+ next_state = NEUTRAL_DRIFT;
+ break;
+
+ case INTO_RUN: // cut motor power and set direction of travel
+ if (present_kybd->sli) { // finger is on slider
+ throttle (0.33);
+ if (direction) My_STM3_ESC_boards.message ("fw\r"); // Forward run command
+ else My_STM3_ESC_boards.message ("re\r"); // Reverse run command
+ next_state = RUN;
+ }
+ break; // endof case INTO_RUN
+
+ case INTO_REGEN_BRAKE: // cut motor power and set 'rb'
+ My_STM3_ESC_boards.message ("rb\r"); // Regen Brake command
+ throttle (0.0); // Wind Honda engine revs down to tickover
+ next_state = REGEN_BRAKE;
+ break; // endof case INTO_REGEN_BRAKE
+
+ case REGEN_BRAKE: // established in regenerative braking mode, loco may or may not be rolling
+ if (present_kybd->sli) { // finger is on slider. No action without finger
+ if (position != present_kybd->slider_y) { // update braking effort according to finger movement
+ position = viscous_drag (present_kybd->slider_y, 5.0, 5.0);
+ if (position <= NEUTRAL_VAL) // if position risen out of REGEN_BRAKE region
+ next_state = INTO_NEUTRAL_DRIFT;
+ else { // position is within REGEN_BRAKE area
+ double brake_effort = ((double)(position - NEUTRAL_VAL) / (double)(MAX_POS - NEUTRAL_VAL));
+ // brake_effort normalised to range 0.0 to 1.0
+ brake_effort *= 0.98; // upper limit to braking effort, observed effect before was quite fierce
+ My_STM3_ESC_boards.set_V_limit (sqrt(brake_effort)); // sqrt gives more linear feel to control
+ My_STM3_ESC_boards.set_I_limit (1.0);
+ } // endof else position is within REGEN_BRAKE area
+ } // endof if finger moved
+ } // endof finger is on slider
+ break; // endof case REGEN_BRAKE
+
+ case RUN: // remains in this state while finger remains on slider in run range. Drive effort determined by finger position
+ if (My_STM3_ESC_boards.last_V < 0.99)
+ My_STM3_ESC_boards.set_V_limit (My_STM3_ESC_boards.last_V + 0.05); // ramp voltage up rather than slam to max
+ if (present_kybd->sli) { // finger is on slider
+ if (position != present_kybd->slider_y) { // update driving power according to finger movement
+ position = viscous_drag (present_kybd->slider_y, 45.0, 20.0);
+ if (position >= NEUTRAL_VAL) // if position falen below RUN region
+ next_state = INTO_NEUTRAL_DRIFT;
+ else // Finger is still in RUN range
+ motor_power (); // class member already has position, sets volts, amps and throttle
+ } // endof update driving power according to finger movement
+ } // endof finger is on slider
+ else { // finger not on slider
+ throttle (0.0); // Honda revs down to tickover
+ next_state = RUN_DOWN;
+ }
+ break; // endof case RUN
+
+ case RUN_DOWN: // if finger removed during RUN, slider is to auto-glide back down to 'N'
+ if (present_kybd->sli) // finger is on slider
+ next_state = RUN;
+ else { // finger is not on slider
+ position = viscous_drag (NEUTRAL_VAL, 45.0, 20.0);
+ if (position >= NEUTRAL_VAL)
+ next_state = INTO_NEUTRAL_DRIFT;
+ else
+ motor_power ();
+ }
+ break; // endof RUN_DOWN
+
+ } // endof switch (next_state) {
+
+ if (position != old_position) { // partial screen rewrite is required
+ DrawSlider ();
+ }
+//} // endof void slider_state_machine () {
+
+
+ if (present_kybd->count || previous_kybd->count) { // at least one key pressed this time or last time
+
+ for (int i = 0; i < present_kybd->count; i++) { // PRESENT Do for all keys pressed on this pass
+ key = present_kybd->key[i].keynum;
+ if (in_list(*previous_kybd, key)) { // AUTOREPEAT This key is being pressed now and last time also
+// pc.printf ("Autorep key %d\r\n", key);
+ } // endof AUTOREPEAT This key is being pressed now and last time also
+ else { // NEW_PRESS key is a new keypress
+// pc.printf ("New Press %d\r\n", key);
+ draw_button_hilight (key, LCD_COLOR_YELLOW) ;
+ switch (key) { // Handle new touch screen button presses here - single action per press, not autorepeat
+ case SLIDER_BUTTON: // All slider action handled in state machine above
+ break;
+ case SPEEDO_BUTTON: // No action currently assigned to speedo button
+ break;
+ case VMETER_BUTTON: // Turn on high tone horn
+ horn (HI_HORN, 1);
+ break;
+ case AMETER_BUTTON: // Turn on low tone horn
+ horn (LO_HORN, 1);
+ break;
+ default:
+ pc.printf ("Unhandled keypress %d\r\n", key);
+ break;
+ } // endof switch (key) endof Handle new touch screen button presses here - single action per press, not autorepeat
+ } // endof NEW_PRESS key is a new keypress
+ } // endof PRESENT Do for all keys pressed on this pass
+
+ for (int i = 0; i < previous_kybd->count; i++) { // Do for all keys pressed on previous pass
+ key = previous_kybd->key[i].keynum;
+ if (!in_list(*present_kybd, key)) { // NEW_RELEASE
+// pc.printf ("New Release %d\r\n", key);
+ draw_button_hilight (key, LCD_COLOR_DARKBLUE) ;
+ switch (key) { // Handle new touch screen button RELEASEs here - single action per press, not autorepeat
+ case SLIDER_BUTTON: //
+ break;
+ case SPEEDO_BUTTON: //
+ break;
+ case VMETER_BUTTON: //
+ horn (HI_HORN, 0); // Turn hi-tone horn off (voltmeter key)
+ break;
+ case AMETER_BUTTON: //
+ horn (LO_HORN, 0); // Turn lo-tone horn off (powermeter key)
+ break;
+ default:
+ pc.printf ("Unhandled key release %d\r\n", key);
+ break;
+ } // endof switch (button)
+ } // endof NEW_RELEASE
+/* else { // DO NOT NEED SECOND FIND OF AUTOREPEAT
+ pc.printf ("Autorep2\r\n");
+ }*/
+ } // endof Do for all keys pressed on previous pass
+ } // endof at least one key pressed this time or last time
+ else { // no keys being pressed on this pass or previous pass
+// pc.printf ("no key being pressed\r\n");
+ } // endof no keys being pressed on this pass or previous pass
+} // endof void screen_touch_handler::HandleFingerInput () {
+
+ screen_touch_handler::screen_touch_handler () { // default constructor
+ present_kybd = & kybd_a;
+ previous_kybd = & kybd_b;
+ oldpos = 0;
+ position = MAX_POS - 2;
+ next_state = INTO_REGEN_BRAKE;
+ flush ();
+ }
+