Electric Locomotive control system. Touch screen driver control, includes regenerative braking, drives 4 brushless motors, displays speed MPH, system volts and power
Dependencies: BSP_DISCO_F746NG FastPWM LCD_DISCO_F746NG SD_DISCO_F746NG TS_DISCO_F746NG mbed
graphics.cpp
00001 #include "mbed.h" 00002 #include "TS_DISCO_F746NG.h" 00003 #include "LCD_DISCO_F746NG.h" 00004 #include "Electric_Loco.h" 00005 00006 #define VOLTMETER_X 68 // Voltmeter screen position 00007 #define VOLTMETER_Y 68 00008 #define AMMETER_X 68 // Ammeter screen position - Now replaced by Power meter 00009 #define AMMETER_Y 202 00010 #define SPEEDO_X 274 // Speedometer screen position 00011 #define SPEEDO_Y 135 00012 #define V_A_SIZE 54 // Size of voltmeter and ammeter 00013 #define SPEEDO_SIZE 112 00014 00015 #define SPEEDO_BODY_COLOUR LCD_COLOR_BLACK 00016 #define SPEEDO_DIAL_COLOUR LCD_COLOR_WHITE 00017 #define SPEEDO_TEXT_COLOUR LCD_COLOR_BLUE 00018 00019 #define VMETER_BODY_COLOUR LCD_COLOR_BLACK 00020 #define VMETER_DIAL_COLOUR LCD_COLOR_WHITE 00021 #define VMETER_TEXT_COLOUR LCD_COLOR_BLUE 00022 00023 #define AMETER_BODY_COLOUR LCD_COLOR_BLACK 00024 #define AMETER_DIAL_COLOUR LCD_COLOR_WHITE 00025 #define AMETER_TEXT_COLOUR LCD_COLOR_BLUE 00026 00027 extern LCD_DISCO_F746NG lcd; 00028 extern TS_DISCO_F746NG touch_screen; 00029 extern Serial pc; 00030 00031 static const int char_widths[] = {5, 7, 11, 14, 17, 17} , 00032 meter_radius_min = 30, meter_radius_max = 120; 00033 00034 00035 // Uses our own generated sine and cosines from lookup table. For some unexplained reason, using inbuilt sin and cos fns cause display flicker ! 00036 extern double jcos (double angle); // Used in DrawNeedle, plain sin and cos functions cause display flicker !! 00037 extern double jsin (double angle); 00038 00039 /*void costabgen (int points) { 00040 double angle = 0.0; 00041 while (angle < 2.1 * PI) { 00042 pc.printf ("Angle %f, my cos %+f, c cos %+f\r\n", angle, jcos(angle), cos(angle)); 00043 // pc.printf ("Angle %f, my sin %+f, c sin %+f\r\n", angle, jsin(angle), sin(angle)); 00044 angle += PI / 24; 00045 } 00046 // double angle; 00047 *//* int step, perline = 0; 00048 double interval = PI / 2.0 / (double)points; 00049 pc.printf ("//At costabgen with %d points\r\n", points); 00050 pc.printf ("static const double costab[] = {\r\n"); 00051 for (step = 0; step <= points; step++) { 00052 angle = interval * (double)step; 00053 // pc.printf ("cos %+.3f = %+.3f\r\n", angle, cos(angle)); 00054 if (++perline == 8) { 00055 pc.printf ("%+.6f,\r\n", cos(angle)); 00056 perline = 0; 00057 } 00058 else 00059 pc.printf ("%+.6f, ", cos(angle)); 00060 wait (0.025); 00061 } 00062 pc.printf ("0.0\t}\t;\r\n//End of costab\r\n"); 00063 */ 00064 //} 00065 00066 /** 00067 * @brief Fills a triangle (between 3 points). 00068 * @param x1: Point 1 X position 00069 * @param y1: Point 1 Y position 00070 * @param x2: Point 2 X position 00071 * @param y2: Point 2 Y position 00072 * @param x3: Point 3 X position 00073 * @param y3: Point 3 Y position 00074 * @retval None 00075 */ 00076 static void FillTriangle(uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3) 00077 { 00078 int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 00079 yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 00080 curpixel = 0; 00081 00082 deltax = abs(x2 - x1); /* The difference between the x's */ 00083 deltay = abs(y2 - y1); /* The difference between the y's */ 00084 x = x1; /* Start x off at the first pixel */ 00085 y = y1; /* Start y off at the first pixel */ 00086 00087 if (x2 >= x1) { /* The x-values are increasing */ 00088 xinc1 = 1; 00089 xinc2 = 1; 00090 } else { /* The x-values are decreasing */ 00091 xinc1 = -1; 00092 xinc2 = -1; 00093 } 00094 00095 if (y2 >= y1) { /* The y-values are increasing */ 00096 yinc1 = 1; 00097 yinc2 = 1; 00098 } else { /* The y-values are decreasing */ 00099 yinc1 = -1; 00100 yinc2 = -1; 00101 } 00102 00103 if (deltax >= deltay) { /* There is at least one x-value for every y-value */ 00104 xinc1 = 0; /* Don't change the x when numerator >= denominator */ 00105 yinc2 = 0; /* Don't change the y for every iteration */ 00106 den = deltax; 00107 num = deltax / 2; 00108 num_add = deltay; 00109 num_pixels = deltax; /* There are more x-values than y-values */ 00110 } else { /* There is at least one y-value for every x-value */ 00111 xinc2 = 0; /* Don't change the x for every iteration */ 00112 yinc1 = 0; /* Don't change the y when numerator >= denominator */ 00113 den = deltay; 00114 num = deltay / 2; 00115 num_add = deltax; 00116 num_pixels = deltay; /* There are more y-values than x-values */ 00117 } 00118 00119 for (curpixel = 0; curpixel <= num_pixels; curpixel++) { 00120 lcd.DrawLine(x, y, x3, y3); 00121 00122 num += num_add; /* Increase the numerator by the top of the fraction */ 00123 if (num >= den) { /* Check if numerator >= denominator */ 00124 num -= den; /* Calculate the new numerator value */ 00125 x += xinc1; /* Change the x as appropriate */ 00126 y += yinc1; /* Change the y as appropriate */ 00127 } 00128 x += xinc2; /* Change the x as appropriate */ 00129 y += yinc2; /* Change the y as appropriate */ 00130 } 00131 } 00132 00133 double anglefix (double a) { // Ensures 0.0 <= angle <= + two PI 00134 while (a > PI) a -= 2.0 * PI; 00135 while (a < 0.0) a += 2.0 * PI; 00136 return a; 00137 } 00138 00139 class moving_coil_meter 00140 { 00141 int meter_radius, cent_x, cent_y, needle_len, scale_ticks, 00142 disc_colour, needle_colour, scale_colour, text_colour, body_colour, dec_places; 00143 double start_angle, end_angle, old_angle, value_min, value_max, rad_per_value, swept_angle, value_range; 00144 double Value; // This is the one that determines pointer angle 00145 00146 void DrawNeedle (double alpha, int colour) ; 00147 void DrawScaleGraduations(int colour) ; 00148 double get_pointer_angle (double value) ; 00149 int get_font () ; 00150 00151 public: 00152 00153 moving_coil_meter () { // constructor 00154 meter_radius = 100; 00155 value_min = -1.0; 00156 value_max = 1.0; 00157 cent_x = cent_y = 150; 00158 disc_colour = LCD_COLOR_BLACK; 00159 needle_colour = LCD_COLOR_WHITE; 00160 scale_colour = LCD_COLOR_MAGENTA; 00161 text_colour = LCD_COLOR_RED; 00162 body_colour = LCD_COLOR_CYAN; 00163 old_angle = 0.0; 00164 } 00165 00166 bool setup (int cx, int cy, int size, double lo, double hi, double start_ang, double end_ang, int scaleticks, char * units, int decimal_places) ; 00167 void set_colours (int bod_colour, int bgcol, int needlecol, int textcolour, int scalecol) ; 00168 void set_value (double v) ; 00169 } Voltmeter, Powermeter, Speedo; // 3 instances of moving coil meter graphic 00170 00171 void moving_coil_meter::set_colours (int bod_col, int bgcol, int needlecol, int textcol, int scalecol) { 00172 body_colour = bod_col; 00173 disc_colour = bgcol; 00174 needle_colour = needlecol; 00175 text_colour = textcol; 00176 scale_colour = scalecol; 00177 } 00178 00179 void moving_coil_meter::DrawNeedle (double alpha, int colour) 00180 { 00181 point pixpts[4]; 00182 int save_colour, ssa, sca; 00183 alpha = anglefix (alpha); 00184 double shortln = (needle_len / 18.7), 00185 sina = jsin(alpha), 00186 cosa = jcos(alpha); 00187 00188 save_colour = lcd.GetTextColor (); 00189 ssa = (int)(shortln * sina); 00190 sca = (int)(shortln * cosa); 00191 old_angle = alpha; 00192 pixpts[0].x = cent_x - ssa;//(int)(shortln * sin(alpha)); 00193 pixpts[0].y = cent_y - sca;//(int)(shortln * cos(alpha)); 00194 pixpts[1].x = cent_x + (int)(needle_len * cosa); 00195 pixpts[1].y = cent_y - (int)(needle_len * sina); // - as increasing y is downwards 00196 pixpts[2].x = cent_x + ssa;//(int)(shortln * sin(alpha)); 00197 pixpts[2].y = cent_y + sca;//(int)(shortln * cos(alpha)); 00198 lcd.SetTextColor (colour); 00199 lcd.FillCircle (cent_x, cent_y, (int)(needle_len / 15.0)); 00200 FillTriangle (pixpts[0].x, pixpts[1].x, pixpts[2].x, pixpts[0].y, pixpts[1].y, pixpts[2].y); 00201 lcd.SetTextColor (save_colour); 00202 } 00203 00204 void moving_coil_meter::DrawScaleGraduations (int colour) 00205 { 00206 int save_colour = lcd.GetTextColor (); 00207 int i, radius_inner = (int) meter_radius - 2, radius_outer = (int) (meter_radius * 0.9); 00208 double ang, cosang, sinang, angle_step; 00209 lcd.SetTextColor (colour); 00210 ang = start_angle; 00211 angle_step = (start_angle - end_angle) / scale_ticks; 00212 for (i = 0; i <= scale_ticks; i++) { // 00213 cosang = cos(ang); 00214 sinang = sin(ang); 00215 lcd.DrawLine (cent_x + radius_outer * cosang, cent_y - radius_outer * sinang, cent_x + radius_inner * cosang, cent_y - radius_inner * sinang); 00216 ang -= angle_step; 00217 } 00218 lcd.SetTextColor (save_colour); 00219 } 00220 00221 void displaytext (int x, int y, const int font, char * txt) ; 00222 00223 bool moving_coil_meter::setup (int cx, int cy, int size, double lo, double hi, double start_ang, double end_ang, int scaleticks, char * units, int decimal_places) 00224 { 00225 bool retval = true; 00226 int font, charwid, x_offset; 00227 if (size < meter_radius_min || size > meter_radius_max) 00228 return false; 00229 meter_radius = size; 00230 if (meter_radius > cx || meter_radius > cy) 00231 return false; 00232 int corner_rad = meter_radius / 6, 00233 screw_hole_offset = meter_radius * 92 / 100, 00234 screw_rad = meter_radius / 13; 00235 cent_x = cx; 00236 cent_y = cy; 00237 00238 start_angle = start_ang; 00239 end_angle = end_ang; 00240 value_min = lo; 00241 value_max = hi; 00242 scale_ticks = scaleticks; 00243 swept_angle = abs(start_angle - end_angle); 00244 value_range = (value_max - value_min); 00245 rad_per_value = swept_angle / value_range; 00246 dec_places = decimal_places; 00247 00248 needle_len = (int)(0.87 * (double)meter_radius); 00249 int oldcolour1 = lcd.GetTextColor (); 00250 int oldcolour2 = lcd.GetBackColor (); 00251 lcd.SetTextColor (body_colour); 00252 // Draw meter body as solid square with rounded corners, complete with mounting screw holes ! 00253 lcd.FillRect (cent_x - meter_radius, cent_y - meter_radius - corner_rad, meter_radius * 2, corner_rad); 00254 lcd.FillRect (cent_x - meter_radius, cent_y + meter_radius, meter_radius * 2, corner_rad + 1); 00255 lcd.FillRect (cent_x - meter_radius - corner_rad, cent_y - meter_radius, 1 +(meter_radius + corner_rad) * 2, meter_radius * 2); 00256 lcd.FillCircle (cent_x - meter_radius, cent_y - meter_radius, corner_rad); // meter box has rounded corners 00257 lcd.FillCircle (cent_x - meter_radius, cent_y + meter_radius, corner_rad); 00258 lcd.FillCircle (cent_x + meter_radius, cent_y - meter_radius, corner_rad); 00259 lcd.FillCircle (cent_x + meter_radius, cent_y + meter_radius, corner_rad); 00260 lcd.SetTextColor (LCD_COLOR_DARKGRAY); 00261 lcd.FillCircle (cent_x - screw_hole_offset, cent_y - screw_hole_offset, screw_rad); // panel mounting screw holes near corners 00262 lcd.FillCircle (cent_x - screw_hole_offset, cent_y + screw_hole_offset, screw_rad); 00263 lcd.FillCircle (cent_x + screw_hole_offset, cent_y - screw_hole_offset, screw_rad); 00264 lcd.FillCircle (cent_x + screw_hole_offset, cent_y + screw_hole_offset, screw_rad); 00265 lcd.SetTextColor (disc_colour); 00266 lcd.FillCircle (cent_x, cent_y, meter_radius); 00267 DrawScaleGraduations (scale_colour); //drew the green trace around active needle-sweep angle 00268 00269 font = get_font (); 00270 charwid = char_widths[font]; 00271 x_offset = charwid * strlen(units) / 2; 00272 lcd.SetTextColor (text_colour); 00273 lcd.SetBackColor (disc_colour); 00274 // displaytext (cent_x - x_offset, cent_y + (meter_radius * 7) / 19, font, units); 00275 displaytext (cent_x - x_offset, cent_y + (meter_radius * 6) / 19, font, units); 00276 lcd.SetBackColor (oldcolour2); 00277 lcd.SetTextColor (oldcolour1); 00278 return retval; 00279 } 00280 00281 int moving_coil_meter::get_font () 00282 { 00283 int font = meter_radius - meter_radius_min; 00284 font /= 17; 00285 if (font > 4) 00286 font = 4; 00287 if (font < 2) 00288 font = 2; 00289 return font; 00290 } 00291 00292 double moving_coil_meter::get_pointer_angle (double v) 00293 { 00294 double vabvmin, retval; 00295 if (v < value_min) v = value_min; 00296 if (v > value_max) v = value_max; 00297 Value = v; // clipped copy of supplied value 00298 vabvmin = v - value_min; 00299 retval = start_angle - (vabvmin * rad_per_value); 00300 return anglefix (retval); 00301 } 00302 00303 void moving_coil_meter::set_value (double meter_read_value) 00304 { 00305 char txt[32]; 00306 int x_offset, font, charwid, lenchk;//, 00307 DrawNeedle (old_angle, disc_colour); // un-draw needle 00308 DrawNeedle (get_pointer_angle (meter_read_value), needle_colour) ; // re-draw needle 00309 if (dec_places == ONE_DP) 00310 sprintf (txt, " %+.1f \0", meter_read_value); 00311 else 00312 sprintf (txt, " %+.0f \0", meter_read_value); 00313 lenchk = strlen(txt); 00314 font = get_font(); 00315 charwid = char_widths[font]; 00316 x_offset = charwid * lenchk / 2; 00317 lcd.SetTextColor (text_colour); 00318 lcd.SetBackColor (disc_colour); 00319 if (lenchk > 0 && lenchk < 9) 00320 displaytext (cent_x - x_offset, cent_y + (meter_radius * 11) / 19, font, txt); 00321 } 00322 //bool moving_coil_meter::setup (int cx, int cy, int size, double lo, double hi, double start_ang, double end_ang, 00323 // int scale_ticks, char * units) 00324 void vm_set () //x y size minv maxv min angle max angle, 00325 { 00326 Speedo.set_colours (SPEEDO_BODY_COLOUR, SPEEDO_DIAL_COLOUR, LCD_COLOR_RED, SPEEDO_TEXT_COLOUR, LCD_COLOR_BLACK); 00327 Speedo.setup (SPEEDO_X, SPEEDO_Y, SPEEDO_SIZE, 0.0, 12.0, 1.25 * PI, -0.25 * PI , 12, "MPH", ONE_DP); 00328 Voltmeter.set_colours (LCD_COLOR_BLACK, LCD_COLOR_WHITE, LCD_COLOR_RED, LCD_COLOR_BLUE, LCD_COLOR_MAGENTA); 00329 Voltmeter.setup (VOLTMETER_X, VOLTMETER_Y, V_A_SIZE, 22.0, 59.0, 1.25 * PI, -0.25 * PI , 30, "V", ONE_DP); 00330 Powermeter.set_colours (LCD_COLOR_BLACK, LCD_COLOR_WHITE, LCD_COLOR_RED, LCD_COLOR_BLUE, LCD_COLOR_BLUE); 00331 Powermeter.setup (AMMETER_X, AMMETER_Y, V_A_SIZE, -1400.0, 1400.0, 1.25 * PI, -0.25 * PI , 14, "Watt", NO_DPS); 00332 } 00333 00334 //void update_meters (double speed, double current, double voltage) 00335 void update_meters (double speed, double power, double voltage) 00336 { 00337 // Powermeter.set_value(voltage * current); 00338 Powermeter.set_value(power); 00339 Voltmeter.set_value (voltage); 00340 Speedo.set_value (speed); 00341 } 00342 00343 00344 00345 struct rect { struct point a, b; } ; 00346 00347 struct butt_on { 00348 struct rect area; 00349 int border_colour, body_colour; 00350 bool in_use, pressed;//, released; 00351 char txt1[12]; 00352 char txt2[12]; 00353 } ; 00354 00355 struct butt_on button[NUMOF_BUTTONS]; 00356 00357 int get_button_press (struct point & pt) ; 00358 int get_but_p (int x, int y) 00359 { 00360 struct point p; 00361 p.x = x; 00362 p.y = y; 00363 return get_button_press (p); 00364 } 00365 00366 00367 void read_keypresses (struct ky_bd & a) 00368 { 00369 int x; 00370 a.count = 0; 00371 a.sli = false; 00372 for (x = 0; x < MAX_TOUCHES; x++) 00373 a.ky[x].keynum = -1; 00374 int touches, but; 00375 TS_StateTypeDef TS_State; 00376 touch_screen.GetState(&TS_State); 00377 touches = TS_State.touchDetected; 00378 for (int h = 0; h < touches; h++) { 00379 but = get_but_p (TS_State.touchX[h], TS_State.touchY[h]); 00380 if (but > - 1) { 00381 a.ky[a.count].keynum = but; 00382 a.ky[a.count].x = TS_State.touchX[h]; 00383 a.ky[a.count].y = TS_State.touchY[h]; 00384 if (but == SLIDER) { 00385 a.sli = true; 00386 a.slider_y = a.ky[a.count].y; 00387 } 00388 a.count++; 00389 } 00390 } 00391 } 00392 00393 00394 void displaytext (int x, int y, char * txt) 00395 { 00396 lcd.DisplayStringAt(x, y, (uint8_t *)txt, LEFT_MODE); 00397 } 00398 00399 void displaytext (int x, int y, const int font, char * txt) 00400 { 00401 sFONT * const fp[] = {&Font8, &Font12, &Font16, &Font20, &Font24}; 00402 lcd.SetFont(fp[font]); 00403 displaytext (x, y, txt); 00404 } 00405 00406 void displaytext (int x, int y, const int font, uint32_t BCol, uint32_t TCol, char * txt) 00407 { 00408 uint32_t otc, obc; 00409 otc = lcd.GetTextColor(); 00410 obc = lcd.GetBackColor(); 00411 lcd.SetTextColor(TCol); 00412 lcd.SetBackColor(BCol); 00413 displaytext (x, y, font, txt); 00414 lcd.SetTextColor(otc); 00415 lcd.SetBackColor(obc); 00416 } 00417 00418 void draw_button (struct butt_on & bu) 00419 { 00420 int oldbgcolour; 00421 lcd.SetTextColor (bu.body_colour); 00422 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); 00423 oldbgcolour = lcd.GetBackColor(); 00424 lcd.SetBackColor(bu.body_colour); 00425 lcd.SetTextColor(LCD_COLOR_BLACK); 00426 if (strlen(bu.txt2) == 0) { 00427 displaytext (bu.area.a.x + 4, bu.area.a.y + 14, 4, bu.txt1); // largest font 4 00428 } else { 00429 displaytext (bu.area.a.x + 4, bu.area.a.y + 4, 3, bu.txt1); // not so large font 3 00430 displaytext (bu.area.a.x + 4, bu.area.a.y + 26, bu.txt2); 00431 } 00432 lcd.SetBackColor(LCD_COLOR_BLACK); 00433 lcd.SetTextColor(bu.border_colour); 00434 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); 00435 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); 00436 lcd.SetBackColor(oldbgcolour); 00437 } 00438 00439 void draw_button_hilight (int but, int colour) 00440 { 00441 if (but < 0 || but > NUMOF_BUTTONS) { 00442 pc.printf ("Button out of range in draw_button_hilight %d\r\n", but) ; 00443 } else { 00444 struct butt_on * bu = &button[but]; 00445 int oldbgcolour = lcd.GetBackColor();//, minx, miny, maxx, maxy; 00446 lcd.SetTextColor(colour); 00447 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); 00448 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); 00449 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); 00450 lcd.SetBackColor(oldbgcolour); 00451 } 00452 } 00453 00454 void draw_button (struct butt_on & bu, int body_colour) 00455 { 00456 bu.body_colour = body_colour; 00457 draw_button (bu); 00458 } 00459 00460 void setup_button (struct butt_on & bu, int x1, int y1, int dx, int dy, int bord, int body, char * txt1, char * txt2) 00461 { 00462 static const int margin = 3; 00463 int xsize = lcd.GetXSize(); 00464 int ysize = lcd.GetXSize(); 00465 int x2 = x1 + dx, y2 = y1 + dy; 00466 if (x1 < margin) x1 = margin; 00467 if (y1 < margin) y1 = margin; 00468 if (x2 > xsize - margin) x2 = xsize - margin; 00469 if (y2 > ysize - margin) y2 = ysize - margin; 00470 bu.area.a.x = x1; 00471 bu.area.a.y = y1; 00472 bu.area.b.x = x2; 00473 bu.area.b.y = y2; 00474 bu.border_colour = bord; 00475 bu.body_colour = body; 00476 strcpy (bu.txt1, txt1); 00477 strcpy (bu.txt2, txt2); 00478 bu.in_use = true; 00479 bu.pressed = false; 00480 draw_button(bu); 00481 } 00482 00483 bool ifpressed (int key) 00484 { 00485 return button[key].pressed; 00486 } 00487 00488 bool is_button_pressed (struct point & pt, struct butt_on & bu) 00489 { 00490 if (bu.in_use) { 00491 if (bu.area.a.x < pt.x && bu.area.b.x > pt.x 00492 && bu.area.a.y < pt.y && bu.area.b.y > pt.y) 00493 return true; 00494 } 00495 return false; 00496 } 00497 00498 bool keyrelease (int key) 00499 { 00500 bool rv = false; 00501 if (button[key].pressed) { 00502 rv = true; 00503 button[key].pressed = false; 00504 } 00505 return rv; 00506 } 00507 void setpressed (int key, bool torf) 00508 { 00509 button[key].pressed = torf; 00510 } 00511 void setinuse (int key, bool torf) 00512 { 00513 button[key].in_use = torf; 00514 } 00515 00516 00517 int get_button_press (struct point & pt) 00518 { 00519 for (int j = 0; j < NUMOF_BUTTONS; j++) 00520 if (button[j].in_use && is_button_pressed (pt, button[j])) 00521 return j; 00522 return -1; 00523 } 00524 00525 void setup_buttons () 00526 { 00527 setup_button (button[SPEEDO_BUT], 00528 SPEEDO_X - SPEEDO_SIZE, SPEEDO_Y - SPEEDO_SIZE, 00529 SPEEDO_SIZE * 2, SPEEDO_SIZE * 2, SPEEDO_BODY_COLOUR, LCD_COLOR_RED, " X", "") ; 00530 setup_button (button[VMETER_BUT], 00531 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", "") ; 00532 setup_button (button[AMETER_BUT], 00533 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", "") ; 00534 setup_button (button[SLIDER], SLIDERX, SLIDERY, SLIDERW, SLIDERH, LCD_COLOR_BLUE, LCD_COLOR_MAGENTA, "", "") ; 00535 } 00536 00537 00538 void SliderGraphic (struct slide & q) { 00539 int 00540 colr, 00541 oldbgcolr = lcd.GetBackColor (), 00542 oldtxtcolr = lcd.GetTextColor (); 00543 char txt[4]; 00544 txt[1] = 0; 00545 if (q.position > MAX_POS) 00546 q.position = MAX_POS; 00547 if (q.position < MIN_POS) 00548 q.position = MIN_POS; 00549 if (q.position == NEUTRAL_VAL) 00550 q.state = NEUTRAL_DRIFT; 00551 if (q.position > NEUTRAL_VAL) 00552 q.state = REGEN_BRAKE; 00553 if (q.position < NEUTRAL_VAL) 00554 if (q.state == REGEN_BRAKE) { // Ensure transition from BRAKE to RUN passes through NEUTRAL 00555 q.position = NEUTRAL_VAL; 00556 q.state = NEUTRAL_DRIFT; 00557 } 00558 else 00559 q.state = RUN; 00560 if (q.position == MAX_POS) { 00561 if (q.loco_speed < LOCO_HANDBRAKE_ESCAPE_SPEED) 00562 q.state = PARK; 00563 else { 00564 q.state = REGEN_BRAKE; 00565 q.position--; 00566 } 00567 } 00568 if (q.position != q.oldpos) { 00569 // Draw slider background colour rectangle overwriting previous circles 00570 // Redraw black vertical 00571 // Draw new circles 00572 // Write text char 00573 lcd.SetTextColor(LCD_COLOR_MAGENTA); 00574 lcd.FillRect (SLIDERX + 1, q.oldpos - BUTTON_RAD, SLIDERW - 2, SLIDERW); 00575 lcd.SetTextColor(LCD_COLOR_BLACK); 00576 lcd.FillRect (SLIDERX + (SLIDERW / 2) - 3, 6, 7, SLIDERH - 8); 00577 q.oldpos = q.position; 00578 lcd.SetTextColor(LCD_COLOR_WHITE); 00579 lcd.DrawCircle (CIRC_CTR, q.position, BUTTON_RAD); // seel also FillCircle 00580 lcd.DrawCircle (CIRC_CTR, q.position, BUTTON_RAD - 1); 00581 switch (q.state) { 00582 case RUN: 00583 txt[0] = 'R'; 00584 colr = LCD_COLOR_GREEN; 00585 break; 00586 case NEUTRAL_DRIFT: 00587 txt[0] = 'N'; 00588 colr = LCD_COLOR_BLUE; 00589 break; 00590 case REGEN_BRAKE: 00591 txt[0] = 'B'; 00592 colr = LCD_COLOR_ORANGE; 00593 break; 00594 case PARK: 00595 txt[0] = 'P'; 00596 colr = LCD_COLOR_RED; 00597 break; 00598 default: 00599 txt[0] = 'X'; 00600 colr = LCD_COLOR_CYAN; 00601 } // End of switch 00602 lcd.SetTextColor(colr); 00603 lcd.FillCircle (CIRC_CTR, q.position, BUTTON_RAD - 2); 00604 lcd.SetBackColor (colr); 00605 lcd.SetTextColor(LCD_COLOR_YELLOW); 00606 displaytext(SLIDERX + 17, q.position - 10, 4, txt); // largest font 00607 lcd.SetBackColor (LCD_COLOR_BLACK); 00608 } // End of else 00609 lcd.SetTextColor (oldtxtcolr); 00610 lcd.SetBackColor (oldbgcolr); 00611 // pc.printf ("SliderG %d, %d, %d\r\n", q.position, q.oldpos, q.state); 00612 } 00613 00614 00615 00616
Generated on Sun Jul 17 2022 14:01:42 by 1.7.2