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
graphics.cpp
- Committer:
- JonFreeman
- Date:
- 2019-03-04
- Revision:
- 14:6bcec5ac21ca
- Parent:
- 12:a25bdf135348
File content as of revision 14:6bcec5ac21ca:
#include "mbed.h" #include "TS_DISCO_F746NG.h" #include "LCD_DISCO_F746NG.h" #include "Electric_Loco.h" extern LCD_DISCO_F746NG lcd; extern TS_DISCO_F746NG touch_screen; extern Serial pc; /* moving_coil_meter Voltmeter ( LCD_COLOR_BLACK, // Frame / body colour LCD_COLOR_WHITE, // Dial face colour LCD_COLOR_RED, // Moving needle colour LCD_COLOR_BLUE, // Text colour for Units e.g. 'V' and e.g. '32.7' LCD_COLOR_MAGENTA, // Scale graduations colour VOLTMETER_X, // X co-ord, centre of meter VOLTMETER_Y, // Y co-ord, centre of meter V_A_SIZE, // Meter is square with rounded corners. This is meter dial face radius 22.0, // Scale not limited to e.g. 0 to 10. This is reading at anti-clock limit 59.0, // This is reading at full scale deflection 1.25 * PI, // Angle of needle at anti-clockwise limit -0.25 * PI , // Angle of needle at full scale deflection (clockwise max) 30, // Number of scale graduation marks drwan "V", // Text for Units, e.g. 'V' or 'MPH' ONE_DP, // NO_DPS or ONE_DP - supports only no decimal places or one false) ; // true to show '+' or '-', false to supress sign display */ /*moving_coil_meter Voltmeter ( LCD_COLOR_BLACK, LCD_COLOR_WHITE, LCD_COLOR_RED, LCD_COLOR_BLUE, LCD_COLOR_MAGENTA, VOLTMETER_X, VOLTMETER_Y, V_A_SIZE, 22.0, 61.0, 1.25 * PI, -0.25 * PI , 20, "V", ONE_DP, false), Powermeter ( LCD_COLOR_BLACK, LCD_COLOR_WHITE, LCD_COLOR_RED, LCD_COLOR_BLUE, LCD_COLOR_BLUE, AMMETER_X, AMMETER_Y, V_A_SIZE, -1400.0, 1400.0, 1.25 * PI, -0.25 * PI , 14, "Watt", NO_DPS, false), Speedo ( SPEEDO_BODY_COLOUR, SPEEDO_DIAL_COLOUR, LCD_COLOR_RED, SPEEDO_TEXT_COLOUR, LCD_COLOR_BLACK, SPEEDO_X, SPEEDO_Y, SPEEDO_SIZE, 0.0, 12.0, 1.25 * PI, -0.25 * PI , 12, "MPH", ONE_DP, false); // 3 instances of moving coil meter graphic */ void displaytext (int x, int y, const int font, char * txt) ; extern uint32_t odometer_out () ; void rewrite_odometer () { char dist[20]; sprintf (dist, "%06dm", odometer_out()); // 12th June 2018 changed 05 to 06 to allow correct display of tot distance > 99999 metres lcd.SetTextColor (LCD_COLOR_BLACK); displaytext (241, 224, 2, dist); } struct rect { struct point a, b; } ; struct button_specs { struct rect area; int border_colour, body_colour; bool in_use, pressed;//, released; char txt1[12]; char txt2[12]; } ; struct button_specs button[NUMOF_BUTTONS]; int get_button_press (struct point & pt) ; int get_but_p (int x, int y) { struct point p; p.x = x; p.y = y; return get_button_press (p); } /** 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 */ void read_keypresses (struct ky_bd & a) { int x; a.count = 0; a.sli = false; for (x = 0; x < MAX_TOUCHES; x++) a.key[x].keynum = -1; int touches, but; TS_StateTypeDef TS_State; touch_screen.GetState(&TS_State); touches = TS_State.touchDetected; for (int h = 0; h < touches; h++) { but = get_but_p (TS_State.touchX[h], TS_State.touchY[h]); if (but > - 1) { a.key[a.count].keynum = but; a.key[a.count].x = TS_State.touchX[h]; a.key[a.count].y = TS_State.touchY[h]; if (but == SLIDER_BUTTON) { a.sli = true; a.slider_y = a.key[a.count].y; } a.count++; } } } void displaytext (int x, int y, char * txt) { lcd.DisplayStringAt(x, y, (uint8_t *)txt, LEFT_MODE); } void displaytext (int x, int y, const int font, char * txt) { sFONT * const fp[] = {&Font8, &Font12, &Font16, &Font20, &Font24}; lcd.SetFont(fp[font]); displaytext (x, y, txt); } void displaytext (int x, int y, const int font, uint32_t BCol, uint32_t TCol, char * txt) { uint32_t otc, obc; otc = lcd.GetTextColor(); obc = lcd.GetBackColor(); lcd.SetTextColor(TCol); lcd.SetBackColor(BCol); displaytext (x, y, font, txt); lcd.SetTextColor(otc); lcd.SetBackColor(obc); } void draw_button (struct button_specs & bu) { int oldbgcolour; lcd.SetTextColor (bu.body_colour); lcd.FillRect(bu.area.a.x + 2, bu.area.a.y + 2, bu.area.b.x - bu.area.a.x - 2, bu.area.b.y - bu.area.a.y - 2); //, bu.body_colour); oldbgcolour = lcd.GetBackColor(); lcd.SetBackColor(bu.body_colour); lcd.SetTextColor(LCD_COLOR_BLACK); if (strlen(bu.txt2) == 0) { displaytext (bu.area.a.x + 4, bu.area.a.y + 14, 4, bu.txt1); // largest font 4 } else { displaytext (bu.area.a.x + 4, bu.area.a.y + 4, 3, bu.txt1); // not so large font 3 displaytext (bu.area.a.x + 4, bu.area.a.y + 26, bu.txt2); } lcd.SetBackColor(LCD_COLOR_BLACK); lcd.SetTextColor(bu.border_colour); lcd.DrawRect(bu.area.a.x, bu.area.a.y, bu.area.b.x - bu.area.a.x, bu.area.b.y - bu.area.a.y); //, bu.border_colour); lcd.DrawRect(bu.area.a.x + 1, bu.area.a.y + 1, bu.area.b.x - bu.area.a.x - 1, bu.area.b.y - bu.area.a.y - 1); //, bu.border_colour); lcd.SetBackColor(oldbgcolour); } void draw_button_hilight (int but, int colour) { if (but < 0 || but > NUMOF_BUTTONS) { pc.printf ("Button out of range in draw_button_hilight %d\r\n", but) ; } else { struct button_specs * bu = &button[but]; int oldbgcolour = lcd.GetBackColor();//, minx, miny, maxx, maxy; lcd.SetTextColor(colour); lcd.DrawRect(bu->area.a.x - 1, bu->area.a.y - 1, bu->area.b.x - bu->area.a.x + 2, bu->area.b.y - bu->area.a.y + 2); lcd.DrawRect(bu->area.a.x - 2, bu->area.a.y - 2, bu->area.b.x - bu->area.a.x + 4, bu->area.b.y - bu->area.a.y + 4); lcd.DrawRect(bu->area.a.x - 2, bu->area.a.y - 3, bu->area.b.x - bu->area.a.x + 5, bu->area.b.y - bu->area.a.y + 6); lcd.SetBackColor(oldbgcolour); } } void draw_button (struct button_specs & bu, int body_colour) { bu.body_colour = body_colour; draw_button (bu); } void setup_button (struct button_specs & bu, int x1, int y1, int dx, int dy, int bord, int body, char * txt1, char * txt2) { static const int margin = 3; int xsize = lcd.GetXSize(); int ysize = lcd.GetXSize(); int x2 = x1 + dx, y2 = y1 + dy; if (x1 < margin) x1 = margin; if (y1 < margin) y1 = margin; if (x2 > xsize - margin) x2 = xsize - margin; if (y2 > ysize - margin) y2 = ysize - margin; bu.area.a.x = x1; bu.area.a.y = y1; bu.area.b.x = x2; bu.area.b.y = y2; bu.border_colour = bord; bu.body_colour = body; strcpy (bu.txt1, txt1); strcpy (bu.txt2, txt2); bu.in_use = true; bu.pressed = false; draw_button(bu); } /*bool ifpressed (int key) { return button[key].pressed; } */ bool is_button_pressed (struct point & pt, struct button_specs & bu) { if (bu.in_use) { if ( bu.area.a.x < pt.x && bu.area.b.x > pt.x && bu.area.a.y < pt.y && bu.area.b.y > pt.y) return true; } return false; } int get_button_press (struct point & pt) { for (int j = 0; j < NUMOF_BUTTONS; j++) if (button[j].in_use && is_button_pressed (pt, button[j])) return j; return -1; } void setup_buttons () { setup_button (button[SPEEDO_BUTTON], SPEEDO_X - SPEEDO_SIZE, SPEEDO_Y - SPEEDO_SIZE, SPEEDO_SIZE * 2, SPEEDO_SIZE * 2, SPEEDO_BODY_COLOUR, LCD_COLOR_RED, " X", "") ; setup_button (button[VMETER_BUTTON], VOLTMETER_X - V_A_SIZE, VOLTMETER_Y - V_A_SIZE, V_A_SIZE * 2, V_A_SIZE * 2, VMETER_BODY_COLOUR, LCD_COLOR_RED, " Y", "") ; setup_button (button[AMETER_BUTTON], AMMETER_X - V_A_SIZE, AMMETER_Y - V_A_SIZE, V_A_SIZE * 2, V_A_SIZE * 2, AMETER_BODY_COLOUR, LCD_COLOR_RED, " Z", "") ; setup_button (button[SLIDER_BUTTON], SLIDERX, SLIDERY, SLIDERW, SLIDERH, LCD_COLOR_BLUE, LCD_COLOR_MAGENTA, "", "") ; } void screen_touch_handler::DrawSlider () { uint32_t colr, oldbgcolr = lcd.GetBackColor (), oldtxtcolr = lcd.GetTextColor (); char txt[4]; txt[1] = 0; if (position > MAX_POS) position = MAX_POS; if (position < MIN_POS) position = MIN_POS; if (position != oldpos) { // Draw slider background colour rectangle overwriting previous circles // Redraw black vertical // Draw new circles // Write text char lcd.SetTextColor(LCD_COLOR_MAGENTA); lcd.FillRect (SLIDERX + 1, oldpos - BUTTON_RAD, SLIDERW - 2, SLIDERW); lcd.SetTextColor(LCD_COLOR_BLACK); lcd.FillRect (SLIDERX + (SLIDERW / 2) - 3, 6, 7, SLIDERH - 8); oldpos = position; lcd.SetTextColor(LCD_COLOR_WHITE); lcd.DrawCircle (CIRC_CTR, position, BUTTON_RAD); // seel also FillCircle lcd.DrawCircle (CIRC_CTR, position, BUTTON_RAD - 1); switch (next_state) { case RUN_DOWN: case RUN: txt[0] = 'R'; colr = LCD_COLOR_GREEN; break; case INTO_NEUTRAL_DRIFT: case NEUTRAL_DRIFT: case INTO_RUN: txt[0] = 'N'; colr = LCD_COLOR_BLUE; break; case REGEN_BRAKE: case INTO_REGEN_BRAKE: txt[0] = 'B'; colr = LCD_COLOR_ORANGE; break; default: txt[0] = 'X'; colr = LCD_COLOR_CYAN; // pc.printf ("State %d\r\n", next_state); } // End of switch lcd.SetTextColor(colr); lcd.FillCircle (CIRC_CTR, position, BUTTON_RAD - 2); lcd.SetBackColor (colr); lcd.SetTextColor(LCD_COLOR_YELLOW); displaytext(SLIDERX + 17, position - 10, 4, txt); // largest font lcd.SetBackColor (LCD_COLOR_BLACK); } // End of else lcd.SetTextColor (oldtxtcolr); lcd.SetBackColor (oldbgcolr); }