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