generated from othneildrew/Best-README-Template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtft.c
1732 lines (1458 loc) · 82.4 KB
/
tft.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
@file tft.c
@brief Implementation of an menu framework the EVE Library of Rudolph Riedel. Meant to display and manage menus, their elements and dynamic graphs (implemented for XMC4700 and DAVE)
@version 3.0 (base lib version was 1.13)
@date 2020-09-05
@initialauthor Rudolph Riedel
@author Rene Santeler (V2.0 together with Stefan Reinmüller) @ MCI 2020/21 (initially created by Rudolph Riedel, completely reworked by RS )
@section History
2.0 (adapted from Rudolph Riedel base version 1.13 - below changes are from RS 2020/21)
- Added color scheme, adaptable banner, dynamic graph implementation (TFT_graph_static & TFT_graph_stepdata), a display init which adds the static part of a graph to static DL (TFT_graph_static), a display init to show a bitmap (TFT_display_init_screen), ...
- Adapted TFT_init to only do the most necessary thins for init (no static DL creation! you need to call one afterwards before using TFT_display!)
- by Rene Santeler & Stefan Reinmüller
3.0
- Adapted everything to be a abstracted menu-framework
- Added menu structure
- Added keypad and swipe feature
- Added TFT elements (TFT_label, TFT_header, TFT_textbox, TFT_control, TFT_graph_...)
- by Rene Santeler
See https://brtchip.com/eve-toolchains/ for helpful Tools
*/
////// TODO: Early on all display_static functions were build to be able to use, or not use burst mode. For now they are set to always use burst. If no problems with this occur, the functions can be stripped of this functionality.
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "Libraries/FT800-FT813-5.x/EVE.h"
#include "tft_data.h"
#include "globals.h"
// Note: The globals must implement the types int_buffer_t (e.g. uint16_t) float_buffer_t (e.g. float) and the function poly_calc
#include "menu.h"
// Note: This TFT "framework" has to be used by an "menu" module which actually defines the user/menu code. It must implement following:
// Defines: TFT_MENU_SIZE (overall size of the menu_objects), TFT_MAIN_MENU_SIZE (highest index used to represent main menus, available by swiping - rest are sub-menus)
// Menu function pointer arrays: TFT_display_cur_Menu__fptr_arr, TFT_touch_cur_Menu__fptr_arr, TFT_display_static_cur_Menu__fptr_arr (at the end of the menu control functions (TFT_display_static, TFT_display and TFT_touch) the function referenced to this pointer is executed)
// Menu objects and the covering array: An object for every menu, representing it's size, header and behavior, as as well as the array "menu_objects" which holds all of them ordered
// TFT_display_get_values(): Used to get data from the display
#include "tft.h"
/////////// External variables /////////////////////////////////////////////////////////////////
// TFT_MENU_SIZE is declared in menu.c and must be changed if menus are added or removed
// TFT_MAIN_MENU_SIZE is declared in menu.c. It states to where the main menus (accessible via swipe an background) are listed. All higher menus are considered submenus (control on how to get there is on menu.c)
// An array of menu struct's that holds general information about the menus (see menu struct in tft.h for definition and menu.c for initialization)
extern menu* menu_objects[TFT_MENU_SIZE];
/// Menu function pointers - At the end of the TFT_display_static, TFT_display and TFT_touch the function referenced to this pointer is executed
extern void (*TFT_display_cur_Menu__fptr_arr[TFT_MENU_SIZE])(void);
extern void (*TFT_touch_cur_Menu__fptr_arr[TFT_MENU_SIZE])(uint8_t tag, uint8_t* toggle_lock, uint8_t swipeInProgress, uint8_t *swipeEvokedBy, int32_t *swipeDistance_X, int32_t *swipeDistance_Y);
extern void (*TFT_display_static_cur_Menu__fptr_arr[TFT_MENU_SIZE])(void);
// Function to get values from the display
extern void TFT_display_get_values(void);
// Function to calculate the result of an polynomial
extern float poly_calc (float c_x, float* f_coefficients, uint8_t order);
// Source type definitions
#ifndef int_buffer_t
typedef uint16_t int_buffer_t;
#endif
#ifndef float_buffer_t
typedef float float_buffer_t;
#endif
/////////// Internal variables /////////////////////////////////////////////////////////////////
/// General Variables
static uint8_t tft_active = 0; // Prevents TFT_display of doing anything if EVE_init isn't successful or TFT_init wasn't called
static uint8_t toggle_lock = 0; // "Debouncing of touches" -> If something is touched, this is set to prevent button evaluations. As soon as the is nothing pressed any more this is reset to 0
static char str_buf[100] = ""; // Character buffer used by str_insert and TFT_label
/// Menu control
static int8_t TFT_cur_menuIdx = 1; // Index of currently used menu (TFT_display, TFT_touch, ...).
static int8_t TFT_last_MenuIdx = -1; // Index of last used menu (TFT_display_static). If this differs from TFT_cur_MenuIdx the initial TFT_display_static function of the menu is executed. Also helpful to determine what was the last menu during the TFT_display_static.
static uint32_t keypadControlKeyBgColor = MAIN_BTNCOLOR;
static uint32_t keypadControlKeyFgColor = MAIN_BTNCTSCOLOR;
static uint32_t mainBgColor = MAIN_BGCOLOR;
/// Memory-map definitions
#define MEM_LOGO 0x00000000 // Start-address of logo, needs about 20228 bytes of memory. Will be written by TFT_display_init_screen and overwritten by TFT_graph_static (and everything else...)
#define MEM_DL_STATIC (EVE_RAM_G_SIZE - 4096) // 0xff000 -> Start-address of the static part of the display-list. Defined as the upper 4k of gfx-mem (WARNING: If static part gets bigger than 4k it gets clipped. IF dynamic part gets so big that it touches the last 4k (1MiB-4k) it overwrites the static part)
static uint32_t num_dl_static; // Amount of bytes in the static part of our display-list
/// Scroll feature
static int8_t TFT_refresh_static = 0;
static int16_t TFT_cur_ScrollV = 0;
static int16_t TFT_last_ScrollV = 0;
static int16_t TFT_UpperBond = 0; // Defines up to which point elements are displayed. Needed to not scroll elements from main area into header or similar. Set by TFT_header, used by all element display functions.
/// Swipe feature (TFT_touch)
static SwipeDetection swipeDetect = None;
static uint8_t swipeInProgress = 0;
static uint8_t swipeEvokedBy = 0; // The tag that initiated the swipe (needed to run an action based on which element was initially touched when the swipe began)
static int32_t swipeInitialTouch_X = 32768; // X position of the initial touch of an swipe
static int32_t swipeInitialTouch_Y = 32768;
static uint8_t swipeEndOfTouch_Debounce = 0; // Counts the number of successive cycles without an touch (tag 0). Used to determine when an swipe is finished
static int32_t swipeDistance_X = 0; // Distance (in px) between the initial touch and the current position of an swipe
static int32_t swipeDistance_Y = 0;
/// Keypad feature (TFT_touch)
static keypadTypes keypadType = Standard;
static uint8_t keypadActive = 0;
static uint8_t keypadEvokedBy = 0; // The tag that initiated the keypad (needed to only edit this element with the keypad)
static uint8_t keypadKeypressFinished = 0;
static uint8_t keypadCurrentKey = 0; // Integer value (tag) of the currently pressed key. The function that uses it must reset it to 0!
static uint8_t keypadShiftActive = 0; // Determines the shown set of characters
static uint8_t keypadEndOfKeypress_Debounce = 0; // Counts the number of successive cycles without an touch (tag 0). Used to determine when an keypress is finished
static uint8_t keypadInitialLock = 0; // When keyboard is activated the keypadInitialLock is set so it only starts accepting input after the finger is first lifted (otherwise it would recognize the random button the aligns with the activating button as a keypress)
static const char backspace_char = 46; // The code that needs to be used for the selected backspace character. It is the offset of the extended ASCII code ('<<' = 174, minus the offset of 128 => 46). Need to use font 19 for extended ASCII characters!
#define KEYPAD_ACTIVE_TARGET_HEIGTH 72 // target offset of the text from upper border of the TFT (position so that it can easily be edited/seen) in pixel
// TAG ASSIGNMENT
// 0 No touch
// 1 Background (swipe area)
// 32-126 Keyboard Common Buttons
// 60 Keyboard Left <
// 62 Keyboard Right >
// 94 Keyboard Shift Key (^)
// 127 Keyboard Backspace (displayed character is different, see 'backspace_char'!)
// 128 Keyboard Enter
/// Textbox feature
static uint8_t textbox_cursor_pos = 0;
// Array of function pointers for every used "EVE_cmd_dl..." function. First one is normal, second one is to be used within a burst mode.
static void (*EVE_cmd_dl__fptr_arr[])(uint32_t) = {EVE_cmd_dl, EVE_cmd_dl_burst};
static void (*EVE_cmd_text__fptr_arr[])(int16_t, int16_t, int16_t, uint16_t, const char*) = {EVE_cmd_text, EVE_cmd_text_burst};
static void (*EVE_cmd_text_var__fptr_arr[])(int16_t, int16_t, int16_t, uint16_t, const char*, uint8_t, ...) = {EVE_cmd_text_var, EVE_cmd_text_var_burst};
static void (*EVE_cmd_number__fptr_arr[])(int16_t, int16_t, int16_t, uint16_t, int32_t) = {EVE_cmd_number, EVE_cmd_number_burst};
static void str_insert(char* target, uint8_t* len, char ch, int8_t pos){
/// Insert a character 'ch' at given position 'pos' of a string 'target'.
/// Note: 'len' will be automatically increased (string gets longer)! Does not work for strings longer than 99 characters
// Copy actual text in front of the new char to the buffer
strncpy(str_buf, target, pos);
// Copy the rest of the text one character behind the new on
strcpy(&str_buf[pos+1], &target[pos]);
// Add new character
str_buf[pos] = ch;
// Copy buffer back to target
strcpy(target,str_buf);
// Increase length
(*len)++;
}
void TFT_keypad_open(uint8_t evokedBy, enum keypadTypes type){
/// Open a keypad for the according evoker (control element - e.g. tag of an textbox)
// Only open keypad if it isn't open
if(keypadActive == 0){
// Activate Keypad and set type
keypadActive = 1;
keypadEvokedBy = evokedBy;
keypadType = type;
// When keyboard is activated the keypadInitialLock is set so it only starts accepting input after the finger is first lifted (otherwise it would recognize the random button the aligns with the activating button as a keypress)
keypadInitialLock = 1;
}
}
void TFT_keypad_close(){
/// Close and reset the keypad
// Deactivate Keypad and reset control variables
keypadActive = 0;
keypadEvokedBy = 0;
keypadType = Standard;
keypadKeypressFinished = 0;
}
void TFT_setMenu(int16_t idx){
/// Set the current menu to the one of given index and reset environment (keypad, scroll, upperbond)
/// If used with already set menu index or -1 the display with refresh the static part
//Let TFT_display_static() run on next TFT_display() cycle
TFT_refresh_static = 1;
// Set new index (used by all function pointers and menu based objects)
if(idx >= 0)
TFT_cur_menuIdx = idx;
// If the menu changed - reset features
if(TFT_cur_menuIdx != TFT_last_MenuIdx){ //keypadActive &&
// Set upper bond
TFT_UpperBond = menu_objects[idx]->upperBond;
// Close keypad if necessary
TFT_keypad_close();
// Reset scroll
TFT_cur_ScrollV = 0;
}
}
void TFT_setColor(uint8_t burst, int32_t textColor, int32_t fgColor, int32_t bgColor, int32_t gradColor){
/// Write the to be used colors to the TFT. Used by all graphic elements.
/// Parameters set to -1 will be ignored! Use this to only set certain color.
///
/// textColor ... Textcolor used by every text
/// fgColor ... Foreground color used by control elements like buttons and such
/// bgColor ... Background color used by control elements like buttons and such
/// gradColor ... Gradient color used by control elements like buttons and such
///
/// Uses tft-global variables:
/// EVE Library ...
if(burst){
if(textColor >= 0)
EVE_cmd_dl_burst(DL_COLOR_RGB | textColor);
if(fgColor >= 0)
EVE_cmd_fgcolor_burst(fgColor);
if(bgColor >= 0)
EVE_cmd_bgcolor_burst(bgColor);
if(gradColor >= 0)
EVE_cmd_gradcolor_burst(gradColor);
}
else{
if(textColor >= 0)
EVE_cmd_dl(DL_COLOR_RGB | textColor);
if(fgColor >= 0)
EVE_cmd_fgcolor(fgColor);
if(bgColor >= 0)
EVE_cmd_bgcolor(bgColor);
if(gradColor >= 0)
EVE_cmd_gradcolor(gradColor);
}
}
void TFT_graph_static(uint8_t burst, graph* gph, uint32_t axisColor, uint32_t gridColor){
/// Write the non-dynamic parts of an Graph to the TFT (axes & labels, grids and values, axis-arrows but no data). Can be used once during init of a static background or at recurring display list build in TFT_display() completely coded by RS 02.01.2021.
///
/// burst ... determines if the normal or the burst version of the EVE Library is used to transmit DL command (0 = normal, 1 = burst).
/// x ... beginning of left edge of the graph (Note that the vertical axis starts at "x+padding" and that some Grid values might be at a position prior to x). In full Pixels
/// y ... beginning of upper edge of the graph (Note this is the position of the axis-arrow point and that the horizontal axis label might be at a position prior to y). In full Pixels
/// width ... width of the actual graph data area in full Pixels
/// height ... height of the actual graph data area in full Pixels
/// padding ... clearance from the outer corners (x,y) to the axes
/// amp_max ... maximum represented value of amplitude (e.g. 10 Volts), will be used at 100% horizontal line
/// cx_max ... maximum represented value of time (e.g. 2.2 Seconds), will be used at 100% horizontal line
/// h_grid_lines ... number of horizontal grid lines
/// v_grid_lines ... number of vertical grid lines
///
/// Note: The predefined GRAPH_AXISCOLOR and GRAPH_GRIDCOLOR are used directly!
// Internal offsets and sizes
const uint8_t arrow_offset = 5; // Offset of the ARROW HEAD corners
const uint8_t grid_linewidth = 9; // linewidth of the grid in 1/16 pixel (16=1px)
#define axis_lbl_txt_size 26 // Font for axis labels
#define grid_lbl_txt_size 20 // Font for grid labels
#define PADDING_X_LABELS 15 // Keep padding for x-axis labels static (height doesn't change with content)
const uint8_t h_ax_lbl_comp_x = 6; // Offset used to print the horizontal axis label at the right position (text width compensation)
const uint8_t h_ax_lbl_comp_y = 20; // Offset used to print the horizontal axis label at the right position (text height compensation)
const uint8_t v_ax_lbl_comp_x = 2; // Offset used to print the vertical axis label at the right position (text width compensation)
const uint8_t v_ax_lbl_comp_y = 22; // Offset used to print the vertical axis label at the right position (text height compensation)
const uint8_t h_grid_lbl_comp_x = 3; // Offset used to print the horizontal grid labels (numbers) at the right position (text width compensation)
const uint8_t h_grid_lbl_comp_y = 13; // Offset used to print the horizontal grid labels (numbers) at the right position (text height compensation)
const uint8_t v_grid_lbl_comp_x = 7; // Offset used to print the vertical grid labels (numbers) at the right position (text width compensation)
const uint8_t v_grid_lbl_comp_y = 0; // Offset used to print the vertical grid labels (numbers) at the right position (text height compensation)
// Determine current position (with scroll value)
uint16_t curY = gph->y - TFT_cur_ScrollV;
/// Calculate pixels between lines and labels of the grid
// Used by grid lines and labels (space between them)
float widthPerSection = (float)(gph->width)/gph->v_grid_lines;
float heightPerSection = (float)(gph->height)/gph->h_grid_lines;
/// Axes LABELS
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | axisColor);
(*EVE_cmd_text__fptr_arr[burst])(gph->x + gph->padding + h_ax_lbl_comp_x, gph->y + gph->padding - h_ax_lbl_comp_y, axis_lbl_txt_size, 0, gph->y_label);
(*EVE_cmd_text__fptr_arr[burst])(gph->x + gph->padding + gph->width + v_ax_lbl_comp_x, gph->y + gph->padding + gph->height - v_ax_lbl_comp_y, axis_lbl_txt_size, EVE_OPT_RIGHTX, gph->x_label);
/// AXES lines
//(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | GRAPH_AXISCOLOR);
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | EVE_LINES);
// left vertical line (Amplitude)
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding, curY));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding, curY + gph->padding + gph->height + gph->padding));
// bottom horizontal line (Time)
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x , curY + gph->padding + gph->height ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + gph->width + gph->padding, curY + gph->padding + gph->height ));
/// GRID lines
(*EVE_cmd_dl__fptr_arr[burst])(LINE_WIDTH(grid_linewidth)); /* size is in 1/16 pixel */
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | gridColor);
// vertical grid
for(int i=1; i<=(int)floor(gph->v_grid_lines); i++){
// y-position at upper and lower corner; x-position from left with padding and width of graph divided by number of gridlines - times current line
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + (uint16_t)(widthPerSection*(float)i), curY + gph->padding ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + (uint16_t)(widthPerSection*(float)i), curY + gph->padding + gph->height ));
}
// horizontal grid
for(int i=1; i<=(int)floor(gph->h_grid_lines); i++){
// x-position at left and right corner; y-position from top y, padding and height divided by number of gridlines - times current line
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding , curY + gph->padding + gph->height - (uint16_t)(heightPerSection*(float)i) ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + gph->width, curY + gph->padding + gph->height - (uint16_t)(heightPerSection*(float)i) ));
}
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
/// Grid VALUES
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | axisColor);
// vertical grid (x)
for(int i=1; i<=(int)ceil(gph->v_grid_lines); i++){ // "ceil" and "i-1" at val -> print also the 0 value
// Calc time at current vertical line
float val = (gph->cx_max/gph->v_grid_lines*(float)(i-1));
// If its a pure integer write it as number, else convert and write it to string
if((val - (float)((uint32_t)val)) == 0){ //val % 1.0 == 0
(*EVE_cmd_number__fptr_arr[burst])(gph->x + gph->padding + (uint16_t)(widthPerSection*(float)(i-1)) + h_grid_lbl_comp_x, curY + gph->height + h_grid_lbl_comp_y, grid_lbl_txt_size, 0, (int32_t)val); //EVE_OPT_RIGHTX| + 18
}
else{
char buffer[32]; // buffer for float to string conversion
sprintf(buffer, "%.1lf", val); // float to string conversion
(*EVE_cmd_text__fptr_arr[burst])(gph->x + gph->padding + (uint16_t)(widthPerSection*(float)(i-1)) + h_grid_lbl_comp_x, curY + gph->height + h_grid_lbl_comp_y, grid_lbl_txt_size, 0, buffer);
}
}
// horizontal grid (y)
//(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | GRAPH_AXISCOLOR);
for(int i=1; i<=(int)floor(gph->h_grid_lines); i++){ // "floor" and "i" at val -> don't print the 0 value
// Calc amplitude at current horizontal line
float val = (gph->amp_max/gph->h_grid_lines*(float)i);
// If its a pure integer write it as number, else convert and write it to string
if((val - (float)((uint32_t)val)) == 0){ //val % 1.0 == 0
(*EVE_cmd_number__fptr_arr[burst])(gph->x - v_grid_lbl_comp_x , curY + gph->padding + gph->height - (uint16_t)(heightPerSection*(float)i) + v_grid_lbl_comp_y, grid_lbl_txt_size, 0, (int32_t)val); //EVE_OPT_RIGHTX|
}
else{
char buffer[32]; // buffer for float to string conversion
sprintf(buffer, "%.1lf", val); // float to string conversion
(*EVE_cmd_text__fptr_arr[burst])(gph->x - v_grid_lbl_comp_x , curY + gph->padding + gph->height - (uint16_t)(heightPerSection*(float)i) + v_grid_lbl_comp_y, grid_lbl_txt_size, 0, buffer);
}
}
/// ARROWS on axes
//(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | GRAPH_AXISCOLOR);
// bottom vertical arrow (Amplitude)
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | EVE_LINE_STRIP);
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + arrow_offset, curY + arrow_offset ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding , curY ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding - arrow_offset, curY + arrow_offset ));
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
// bottom horizontal arrow (Time)
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | EVE_LINE_STRIP);
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + gph->width + gph->padding - arrow_offset, curY + gph->padding + gph->height + arrow_offset ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + gph->width + gph->padding , curY + gph->padding + gph->height ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(gph->x + gph->padding + gph->width + gph->padding - arrow_offset, curY + gph->padding + gph->height - arrow_offset ));
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
}
void TFT_header_static(uint8_t burst, menu* men){
/// Write the non-dynamic parts of a menu to the TFT (banner, divider line & header text). Can be used once during init of a static background or at recurring display list build in TFT_display_[menu]()
///
/// burst Determines if the normal or the burst version of the EVE Library is used to transmit DL command (0 = normal, 1 = burst).
/// layout Banner line strip edge positions. Array of 4 elements [Y1,X1,Y2,X2] (from left to right: Y1 is held horizontal till X1, increasing till X2/Y2 and finally held horizontal at Y2 till EVE_HSIZE)
/// bannerColor Color of the banner surface
/// dividerColor Color of the line at the edge of the banner
/// headerColor Color of the text
/// headerText Name of the current menu (header text)
///
/// Uses tft-global variables:
/// EVE Library ...
/// EVE_cmd_dl__fptr_arr, EVE_cmd_text__fptr_arr Function pointer for "EVE_cmd_dl..." function with or without burst
/// Draw Banner and divider line on top (line strip edge positions from left to right: Y1 is held horizontal till X1, increasing till X2/Y2 and finally held horizontal at Y2 till EVE_HSIZE)
// Banner
(*EVE_cmd_dl__fptr_arr[burst])(TAG(1)); /* give everything considered background area tag 1 -> used for wipe feature*/
(*EVE_cmd_dl__fptr_arr[burst])(LINE_WIDTH(1*16)); /* size is in 1/16 pixel */
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | men->bannerColor);
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | EVE_EDGE_STRIP_A);
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(0 , men->headerLayout[0]));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(men->headerLayout[1], men->headerLayout[0]));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(men->headerLayout[3], men->headerLayout[2]));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(EVE_HSIZE , men->headerLayout[2]));
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
// Divider
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | men->dividerColor);
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | EVE_LINE_STRIP);
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(0 , men->headerLayout[0]));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(men->headerLayout[1], men->headerLayout[0]));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(men->headerLayout[3], men->headerLayout[2]));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(EVE_HSIZE , men->headerLayout[2]));
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
// Add header text
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | men->headerColor);
(*EVE_cmd_text__fptr_arr[burst])(20, 15, 30, 0, men->headerText);
// Reset current tag to prevent next elements from being considered background
(*EVE_cmd_dl__fptr_arr[burst])(TAG(0));
}
void TFT_label_display(uint8_t burst, label* lbl){
/// Write a text/label to the TFT. Can be used once during init of a static background TFT_display_static() or at recurring display list build in TFT_display()
/// Use num_src to display values (see description below and at struct)
///
/// burst Determines if the normal or the burst version of the EVE Library is used to transmit DL command (0 = normal, 1 = burst).
/// x
/// y
/// font
/// options
/// text Name of the current menu (Header)
/// num_src A pointer to the numeric source this label represents. Set to 0 if its a pure text label. If set to 1 the string in text is used to format the source
/// ignoreScroll
///
/// Uses tft-global variables:
/// EVE Library ...
/// EVE_cmd_dl__fptr_arr, EVE_cmd_text__fptr_arr Function pointer for "EVE_cmd_dl..." function with or without burst
/// TFT_cur_ScrollV, TFT_UpperBond
/// str_buf
///
/// Limitations: num_src conversion only works with strings shorter than 99 characters (using global buffer 'str_buf')
// Determine desired y position based on scroll and ignore scroll
uint16_t curY = lbl->y;
if(lbl->ignoreScroll == 0){
// Determine current position (with scroll value)
curY -= TFT_cur_ScrollV;
}
// Only show label if it is inside display or ignores scroll
if(lbl->ignoreScroll || (curY > TFT_UpperBond && curY < EVE_VSIZE)){
// Do not recognize touches on label
(*EVE_cmd_dl__fptr_arr[burst])(TAG(0));
// If label is a number related one (srcType not 0 = srcTypeNone), convert number according to text and print string
// Note: This could be more efficient if we only convert when needed and/or lower the refresh rate (store calculated values).
if(lbl->numSrc.srcType != srcTypeNone){
/// If a numerical source is assigned to the textbox, refresh the text
// ... for integer source
if(lbl->numSrc.srcType == srcTypeInt)
// If the offset is not given use integer directly, else use offset to determine which value is to be used
if(lbl->numSrc.srcOffset == NULL)
(*EVE_cmd_text_var__fptr_arr[burst])(lbl->x, curY, lbl->font, EVE_OPT_FORMAT | lbl->options, lbl->text, 1 ,(int32_t)*lbl->numSrc.intSrc);
else
(*EVE_cmd_text_var__fptr_arr[burst])(lbl->x, curY, lbl->font, EVE_OPT_FORMAT | lbl->options, lbl->text, 1 ,(int32_t)( lbl->numSrc.intSrc[*lbl->numSrc.srcOffset]) );
// ... for floating source
else if(lbl->numSrc.srcType == srcTypeFloat){
// Split float value into integral/fractional part and print them according to lbl->text
float intPart, fracPart;
/// If the offset is not given use floatSrc directly, else use offset to determine which value is to be used
if(lbl->numSrc.srcOffset == NULL)
fracPart = modff( *lbl->numSrc.floatSrc, &intPart);
else
fracPart = modff(lbl->numSrc.floatSrc[*lbl->numSrc.srcOffset], &intPart);
// Print the string while using text as format and raising the fraction to the power of 10 given by fracExp
if(lbl->fracExp == 0)
(*EVE_cmd_text_var__fptr_arr[burst])(lbl->x, curY, lbl->font, EVE_OPT_FORMAT | lbl->options, lbl->text, 2 ,FLOAT_TO_INT16(intPart) ); //"%d"
else
(*EVE_cmd_text_var__fptr_arr[burst])(lbl->x, curY, lbl->font, EVE_OPT_FORMAT | lbl->options, lbl->text, 2 ,FLOAT_TO_INT16(intPart), FLOAT_TO_INT16(fabsf( fracPart*(pow10f((float)lbl->fracExp)))) ); //"%d.%.2d"
}
}
// No source given -> print pure text
else{
(*EVE_cmd_text__fptr_arr[burst])(lbl->x, curY, lbl->font, lbl->options, lbl->text);
}
}
}
void TFT_control_display(control* ctrl){
/// Display a user control element (button/toggle) to the TFT. Adapts the y coordinate automatically to current vertical scroll (use ignoreScroll property of control struct if wanted otherwise)
/// Meant to be used at recurring display list build in TFT_display().
/// Note: Use TFT_setColor(...) before calling this!
///
/// x Position of left control edge in full Pixels.
/// y Position of upper control edge in full Pixels.
/// w0 Width of the control
/// h0 Height of the control
/// mytag The touch tag of the control. Note: Use a global define to set this in object and use it inside TFT_touch_[menu]() inside tag switch.
/// options Options that can be applied to the control (For toggles: EVE_OPT_FLAT, EVE_OPT_FORMAT, for buttons: Same as for toggles but additionally EVE_OPT_FILL with standard EVE_OPT_3D)
/// state Toggles: state of the toggle - 0 off - 65535 on, Buttons: Bitwise or'ed with options
/// font Font of the control text
/// textColor Color of the text
/// text Text displayed in the control
/// ignoreScroll If set to 1 the global TFT_cur_ScrollV is ignored
///
/// Uses tft-global variables:
/// EVE Library ...
/// TFT_cur_ScrollV, TFT_UpperBond
uint16_t curY = ctrl->y;
if(ctrl->ignoreScroll == 0){
// Determine current position (with scroll value)
curY -= TFT_cur_ScrollV;
}
// Only show control if it is inside display
if(ctrl->ignoreScroll || (curY > TFT_UpperBond && curY < EVE_VSIZE)){
// Set assigned Tag
EVE_cmd_dl_burst(TAG(ctrl->mytag)); /* do not use the following objects for touch-detection */
// Draw Element
switch (ctrl->controlType) {
case Button:
EVE_cmd_button_burst(ctrl->x, curY, ctrl->w0, ctrl->h0, ctrl->font, ctrl->options | ctrl->state, ctrl->text);
break;
case Toggle:
EVE_cmd_toggle_burst(ctrl->x, curY, ctrl->w0, ctrl->font, ctrl->options, ctrl->state, ctrl->text);
break;
}
/// Reset tag
EVE_cmd_dl_burst(TAG(0));
}
}
void TFT_textbox_static(uint8_t burst, textbox* tbx){
/// Write the non-dynamic parts of an textbox to the TFT (background & frame). Can be used once during init of a static background or at recurring display list build in TFT_display()
/// If mytag is 0 the textbox is considered read only with grey background. Else its read/write with white background
///
/// burst Determines if the normal or the burst version of the EVE Library is used to transmit DL command (0 = normal, 1 = burst).
/// x Position of left textbox edge. In full Pixels.
/// y Position of upper textbox edge. In full Pixels.
/// labelOffsetX Distance between x and the actual start of the textbox (space needed for label).
/// width Width of the actual textbox data area in full Pixels.
/// labelText Text of the preceding label.
/// mytag To be assigned tag for touch recognition.
///
/// Uses tft-global variables:
/// EVE Library ...
/// EVE_cmd_dl__fptr_arr Function pointer for "EVE_cmd_dl..." function with or without burst
/// TEXTBOX_HEIGTH, TEXTBOX_PAD_V
/// TFT_cur_ScrollV, TFT_UpperBond
///
/// Limitations: The frame is hard-coded black
// Determine current position (with scroll value)
uint16_t curY = tbx->y - TFT_cur_ScrollV;
// Only show textbox if it is inside display
if(curY > TFT_UpperBond && curY < EVE_VSIZE){
/// Write label
(*EVE_cmd_text__fptr_arr[burst])(tbx->x, curY + TEXTBOX_PAD_V, 26, 0, tbx->labelText); // +7 to get same
/// Calculate coordinates
uint16_t abs_x_left = tbx->x + tbx->labelOffsetX;
uint16_t abs_x_right = tbx->x + tbx->labelOffsetX + tbx->width;
uint16_t abs_y_top = curY;
uint16_t abs_y_bottom = curY + TEXTBOX_HEIGTH;
/// Set background color and tag based on mytag
if(tbx->mytag == 0){ // read-only
// Read-only: Set no touch tag and grey background color
(*EVE_cmd_dl__fptr_arr[burst])(TAG(0));
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | LIGHTGREY);
}
else{
// Read/Write: Set actual tag and white background color
(*EVE_cmd_dl__fptr_arr[burst])(TAG(tbx->mytag));
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | WHITE);
}
/// Background rectangle
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | EVE_RECTS);
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(abs_x_left , abs_y_top ));
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(abs_x_right, abs_y_bottom));
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
/// Frame
(*EVE_cmd_dl__fptr_arr[burst])(DL_COLOR_RGB | BLACK);
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | EVE_LINE_STRIP);
// start point
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(abs_x_left, abs_y_top));
// left vertical
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(abs_x_left, abs_y_bottom));
// bottom horizontal
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(abs_x_right, abs_y_bottom));
// right vertical
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(abs_x_right, abs_y_top));
// bottom horizontal
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(abs_x_left, abs_y_top));
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
/// Reset tag
(*EVE_cmd_dl__fptr_arr[burst])(TAG(0));
}
}
uint8_t TFT_textbox_touch(textbox* tbx){
/// Manage input from keyboard and manipulate text. Used at recurring touch evaluation in TFT_touch(). Return 1 if OK/Enter is presses, else 0
/// Note: Set textbox_cursor_pos initial before entering this the first time. Check TAG ASSIGNMENT above - this refers to the conventions given there!
///
/// mytag The tag of the current control element (code only responds for this textbox if keypadEvokedBy is mytag)
/// text The string that shall be manipulated
/// text_maxlen Maximum length of the manipulated text (this will not add characters if length is at maximum)
/// text_curlen Current length of the manipulated text (this will change length according to input)
///
/// Uses tft-global variables:
/// EVE Library ...
/// keypad: keypadActive, keypadEvokedBy, keypadCurrentKey, keypadKeypressFinished
/// textbox_cursor_pos
/// If the keyboard is active and evoked by the current textbox, manipulate text according to input
if(keypadActive && keypadEvokedBy == tbx->mytag){
/// If a finished keypress is detected and the current key is in valid range - manipulate text according to keypad input
if(keypadKeypressFinished && keypadCurrentKey >= 32 && keypadCurrentKey <= 128){
// Enter key - finish textbox input
if(keypadCurrentKey == 128){
// Close/reset keypad
TFT_textbox_setStatus(tbx, 0, 0);
// Mark keypress as handled (keypress is now processed -> wait till the next one comes)
keypadKeypressFinished = 0;
keypadCurrentKey = 0;
// Return 1 to mark that enter was presses (user code may do something now)
return 1;
}
else {
// Backspace - Delete last character
if(keypadCurrentKey == 127){
// Remove last character (if cursor is inside of string)
if(textbox_cursor_pos >= 1 && textbox_cursor_pos <= *(tbx->text_curlen)){
// Overwrite previous char with rest of string
strcpy(&(tbx->text[textbox_cursor_pos-1]), &(tbx->text[textbox_cursor_pos]));
// Decrease text length and move cursor back
(*(tbx->text_curlen))--;
textbox_cursor_pos--;
}
}
// Left - Move cursor back (if cursor is inside of string)
else if(keypadCurrentKey == 60){
if(textbox_cursor_pos > 0)
textbox_cursor_pos--;
}
// Right - Move cursor forth (if cursor is inside of string)
else if(keypadCurrentKey == 62){
if(textbox_cursor_pos < *(tbx->text_curlen))
textbox_cursor_pos++;
}
// Actual character - Add at position if the string isn't at max length
else if(*(tbx->text_curlen) < ((tbx->text_maxlen)-1)){
str_insert(tbx->text, (tbx->text_curlen), (char)keypadCurrentKey, textbox_cursor_pos);
textbox_cursor_pos++;
}
// Mark keypress as handled (keypress is now processed -> wait till the next one comes)
keypadKeypressFinished = 0;
keypadCurrentKey = 0;
}
} // end if - keypadKeypressFinished && keypadCurrentKey in range
} // end if - keyboard active && evoked by me
return 0;
}
void TFT_textbox_display(textbox* tbx){
/// Write the dynamic parts of an textbox to the TFT (text & cursor). Used at recurring display list build in TFT_display()
///
/// x Position of left textbox edge. In full Pixels.
/// y Position of upper textbox edge. In full Pixels.
/// labelOffsetX Distance between x and the actual start of the textbox (space needed for label).
/// mytag The tag of the current control element (cursor is only shown if keypadEvokedBy is mytag).
/// text The string that shall be displayed.
///
/// Uses tft-global variables:
/// EVE Library ...
/// keypad: keypadActive, keypadEvokedBy
/// textbox_cursor_pos
/// TEXTBOX_PAD_V, TEXTBOX_PAD_H
/// str_buf
///
/// Limitations: Made for font size 26. Make sure the text can't be longer than the textbox width!
// Cursor and control variables (static: will keep value between function executions)
static char cursor = '|';
static uint32_t lastBlink = 0;
// Determine current position (with scroll value)
uint16_t curY = tbx->y + TEXTBOX_PAD_V - TFT_cur_ScrollV;
// Only show text if it is inside display
if(curY > TFT_UpperBond && curY < EVE_VSIZE){
/// Set tag
EVE_cmd_dl_burst(TAG(tbx->mytag));
/// Set text color
EVE_cmd_dl_burst(DL_COLOR_RGB | BLACK);
/// If the keyboard is active, show textbox text with cursor - else just write text directly
if(keypadActive && keypadEvokedBy == tbx->mytag){ //
// Toggle cursor every 550ms
if(SYSTIMER_GetTime() > (lastBlink + 550000)){
lastBlink = SYSTIMER_GetTime();
if(cursor == '|')
cursor = ' ';
else
cursor = '|';
}
/// Copy text to buffer but add the cursor
// Copy actual text previous to the cursor to the buffer
strncpy(str_buf, tbx->text, textbox_cursor_pos);
// Add cursor
str_buf[textbox_cursor_pos] = cursor;
// Copy rest of string past cursor to the buffer
strcpy(&str_buf[textbox_cursor_pos+1], &(tbx->text[textbox_cursor_pos]));
// Write buffer as text
EVE_cmd_text_burst(tbx->x + tbx->labelOffsetX + TEXTBOX_PAD_H,curY, 26, 0, str_buf);
}
// textbox is inactive
else{
// If textbox is a number related one (srcType not 0 = srcTypeNone), convert number according to text and print string
// Note: This could be more efficient if we only convert when needed and/or lower the refresh rate (store calculated values).
if(tbx->numSrc.srcType != srcTypeNone){
/// If a numerical source is assigned to the textbox, refresh the text
// ... for integer source
if(tbx->numSrc.srcType == srcTypeInt)
// If the offset is not given, use integer directly, else use offset to determine which value is to be used
if(tbx->numSrc.srcOffset == NULL){
EVE_cmd_text_var_burst(tbx->x + tbx->labelOffsetX + TEXTBOX_PAD_H, curY, 26, EVE_OPT_FORMAT, tbx->numSrcFormat, 1 ,(int32_t)*tbx->numSrc.intSrc);
}
else
EVE_cmd_text_var_burst(tbx->x + tbx->labelOffsetX + TEXTBOX_PAD_H, curY, 26, EVE_OPT_FORMAT, tbx->numSrcFormat, 1 ,(int32_t)( tbx->numSrc.intSrc[*tbx->numSrc.srcOffset]) );
// ... for floating source
else if(tbx->numSrc.srcType == srcTypeFloat){
// Split float value into integral/fractional part and print them according to tbx->text
float intPart, fracPart;
/// If the offset is not given, use floatSrc directly, else use offset to determine which value is to be used
if(tbx->numSrc.srcOffset == NULL)
fracPart = modff(*tbx->numSrc.floatSrc, &intPart);
else
fracPart = modff(tbx->numSrc.floatSrc[*tbx->numSrc.srcOffset], &intPart);
// Print the string while using text as format and raising the fraction to the power of 10 given by fracExp
EVE_cmd_text_var_burst(tbx->x + tbx->labelOffsetX + TEXTBOX_PAD_H, curY, 26, EVE_OPT_FORMAT, tbx->numSrcFormat, 2 ,FLOAT_TO_INT16(intPart), FLOAT_TO_INT16(fabsf( fracPart*(pow10f((float)tbx->fracExp)))) ); //"%d.%.2d"
}
}
// No source given -> print pure text
else{
EVE_cmd_text_burst(tbx->x + tbx->labelOffsetX + TEXTBOX_PAD_H, curY, 26, 0, tbx->text);
}
}
/// Reset tag
EVE_cmd_dl_burst(TAG(0));
}
}
static void TFT_textbox_setCursor(const textbox* tbx, int16_t position){
/// Sets the position of the global textbox cursor.
/// Internal function - use TFT_textbox_setStatus to set this from outside.
/// -1 ... Set to end
/// 0 ... Set to begin
/// x ... Set to position x if "x <= len"
/// TODO: interpret e.g. -4 as 4th char from behind
// Set cursor based on parameter position
switch (position) {
case -1:
// Set to end
textbox_cursor_pos = *tbx->text_curlen;
break;
default:
// if position less than length - set to given position
if(position <= *tbx->text_curlen)
textbox_cursor_pos = position;
break;
}
}
void TFT_textbox_setStatus(textbox* tbx, uint8_t active, int16_t cursorPos){
/// Controls the state of an textbox (open, set cursor & close). Meant to be called by an menu specific TFT_touch_[menu]() on touch of the textbox tag.
/// If called with an inactive textbox and active=1 this opens the wanted keypad and sets the scroll so the textbox is visible above the keypad.
/// If called with an already active textbox, this changes the cursor position.
/// If called with an active textbox and active=0 this writes the input back to the source (if numeric source is linked), resets the scroll and closes the keypad.
// If textbox shall be active but isn't - set scroll, activate keypad and set cursor
if(active == 1 && tbx->active == 0){
/// If a numeric source is given, write the source to the text (so it can be edited as text)
// Integer source
if(tbx->numSrc.srcType == srcTypeInt){
// If the offset is not given, use integer directly, else use offset to determine which value is to be used
if(tbx->numSrc.srcOffset == NULL)
sprintf(tbx->text, tbx->numSrcFormat, *tbx->numSrc.intSrc); // string to integer conversion
else
sprintf(tbx->text, tbx->numSrcFormat, tbx->numSrc.intSrc[*tbx->numSrc.srcOffset]); // string to integer conversion with offset
// Refresh text length
*tbx->text_curlen = strlen(tbx->text);
}
// Fractional source
else if(tbx->numSrc.srcType == srcTypeFloat){
// Split float value into integral/fractional part and print them according to tbx->text
float intPart, fracPart;
/// If the offset is not given, use floatSrc directly, else use offset to determine which value is to be used
if(tbx->numSrc.srcOffset == NULL)
fracPart = modff( *tbx->numSrc.floatSrc, &intPart);
else
fracPart = modff(tbx->numSrc.floatSrc[*tbx->numSrc.srcOffset], &intPart);
// Print the string while using text as format and raising the fraction to the power of 10 given by fracExp
sprintf(tbx->text, tbx->numSrcFormat, FLOAT_TO_INT16(intPart), FLOAT_TO_INT16(fabsf( fracPart*(pow10f((float)tbx->fracExp)))) ); // string to integer conversion
//,FLOAT_TO_INT16(intPart), FLOAT_TO_INT16(fabsf( fracPart*(pow10f((float)tbx->fracExp)))) ); //"%d.%.2d"
// Refresh text length
*tbx->text_curlen = strlen(tbx->text);
}
// Set vertical scroll so that the textbox can be seen
TFT_cur_ScrollV = tbx->y - KEYPAD_ACTIVE_TARGET_HEIGTH;
tbx->active = 1;
// Activate Keypad and set cursor to given position
TFT_keypad_open(tbx->mytag, tbx->keypadType);
TFT_textbox_setCursor(tbx, cursorPos);
}
// If textbox shall be active and already is - update cursor position
if(active == 1 && tbx->active == 1){
// Activate Keypad and set cursor to given position
TFT_textbox_setCursor(tbx, cursorPos);
}
// If textbox shall be deactivated - Write back content and reset scroll/keypad
else{
// If a numeric source is given, write the text back to source (save)
if(tbx->numSrc.srcType == srcTypeInt){
if(tbx->numSrc.srcOffset == NULL)
*tbx->numSrc.intSrc = FLOAT_TO_INT16(atoff(tbx->text));//strtof(tbx->text, 0);
else
tbx->numSrc.intSrc[*tbx->numSrc.srcOffset] = FLOAT_TO_INT16(atoff(tbx->text));//strtof(tbx->text, 0);
}
else if(tbx->numSrc.srcType == srcTypeFloat){
if(tbx->numSrc.srcOffset == NULL)
*tbx->numSrc.floatSrc = atoff(tbx->text); //strtof(tbx->text, 0); //(float_buffer_t)
else
tbx->numSrc.floatSrc[*tbx->numSrc.srcOffset] = atoff(tbx->text);
}
// Reset vertical scroll to normal
TFT_cur_ScrollV = 0;
tbx->active = 0;
// Deactivate Keypad and set cursor to end
TFT_keypad_close();
}
}
void TFT_primitive(uint8_t burst, uint16_t primitive, uint16_t point_size, uint16_t line_width, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2){
/// Draw a EVE graphics primitives. See parameter description and Bridgetec EVE programming guide for details.
/// If x2 and y2 are zero they are ignored! Use this to give the used primitive the right amount of vertices.
/// Idea: This would be nicer as an variadic function with as many x/y coordinates as needed
///
/// burst ... determines if the normal or the burst version of the EVE Library is used to transmit DL command (0 = normal, 1 = burst).
/// primitive ... the EVE graphics primitive (like EVE_POINTS, EVE_RECTS, EVE_LINES, EVE_LINE_STRIP, EVE_EDGE_STRIP_R, EVE_EDGE_STRIP_L, EVE_EDGE_STRIP_A, EVE_EDGE_STRIP_B)
/// point_size ... the size used for point primitives - set to 0 or NULL if unsed!
/// line_width ... the size used for line primitives - set to 0 or NULL if unsed!
/// x1 ... beginning of left edge of the first primitive
/// y1 ... beginning of upper edge of the first primitive
/// x2 ... beginning of left edge of the optional second primitive
/// y2 ... beginning of upper edge of the optional second primitive
// Determine current position (with scroll value)
uint16_t curY1 = y1 - TFT_cur_ScrollV;
uint16_t curY2 = y2 - TFT_cur_ScrollV;
// Set point size or line width if given (size in 1/16 pixel)
if(point_size)
(*EVE_cmd_dl__fptr_arr[burst])(POINT_SIZE(point_size));
if(line_width)
(*EVE_cmd_dl__fptr_arr[burst])(LINE_WIDTH(line_width));
// Draw primitive
(*EVE_cmd_dl__fptr_arr[burst])(DL_BEGIN | primitive);
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(x1 , curY1));
if(x2 != 0 && y2 != 0)
(*EVE_cmd_dl__fptr_arr[burst])(VERTEX2F(x2 , curY2));
(*EVE_cmd_dl__fptr_arr[burst])(DL_END);
}
void TFT_graph_pixeldata_i(graph* gph, int_buffer_t buf[], uint16_t buf_size, uint16_t *buf_curidx, uint32_t datacolor){
/// Write the dynamic parts of an Graph to the TFT (data and markers). Used at recurring display list build in TFT_display() completely coded by RS 02.01.2021.
/// Every data-point is assumed to be at one pixel of the screen. Make this as wide as there are elements in the data-array.
///
/// x ... beginning of left edge of the graph (Note that the vertical axis starts at "x+padding" and that some Grid values might be at a position prior to x). In full Pixels
/// y ... beginning of upper edge of the graph (Note this is the position of the axis-arrow point and that the horizontal axis label might be at a position prior to y). In full Pixels
/// width ... width of the actual graph data area in full Pixels
/// height ... height of the actual graph data area in full Pixels
/// padding ... clearance from the outer corners (x,y) to the axes
/// y_max ... maximum expected value of input (e.g. for 12bit ADC 4095), will represent 100%
/// buf[] ... Array of data values
/// buf_size ... size of array of data values
/// *buf_curidx ... current position (index of most recent value)
/// graphmode ... 0 = frame-mode, 1 = roll-mode
/// datacolor ... 24bit color (as 32 bit integer with leading 0's) used for the dataline
/// markercolor ... 24bit color (as 32 bit integer with leading 0's) used for the current position line
/// Note: No predefined graph settings are used direct (#define ...)!
// Determine current position (with scroll value)
uint16_t curY = gph->y - TFT_cur_ScrollV;
/// Display current DATA as line strip in frame or roll mode
EVE_cmd_dl_burst(DL_COLOR_RGB | datacolor);
EVE_cmd_dl_burst(DL_BEGIN | EVE_LINE_STRIP);
/// Display graph frame-mode
if(gph->graphmode == 0){
// Print values in the order they are stored
for (int x_cur = 0; x_cur < buf_size; ++x_cur) {
EVE_cmd_dl_burst(VERTEX2F(gph->x + gph->padding + x_cur, curY + gph->padding + gph->height - (uint16_t)(( ((float)buf[x_cur]) / ((float)gph->y_max) )*(float)(gph->height)) )); //if(frameover==1) printf("%lf %lf\n", ((((float)(buf[x_cur]))/((float)gph->y_max))*(float)(gph->height)), (float)buf[gph->x]);
}
}
/// Display graph roll-mode
else {
// Print newest value always at the rightmost corner with all older values to the right
// => Start Display x position at rightmost corner and decrement till 0 (last run will make it -1 at the end but it isn't used after that)
// => Start Arrayindex i at current index and decrement every loop. If i goes below 0, reset to max index and decrement further till
// value before current is hit.
int16_t i = *buf_curidx;
for (int16_t x_cur = buf_size-1; x_cur >= 0; x_cur--) {
// if index goes below 0 set to highest buffer index
if(i < 0){i = buf_size-1;}
// Send next point for EVE_LINE_STRIP at current x+padding and normalized buffer value
EVE_cmd_dl_burst(VERTEX2F(gph->x + gph->padding + x_cur, curY + gph->padding + gph->height - (uint16_t)(( ((float)buf[i]) / ((float)gph->y_max) )*(float)(gph->height)) )); // EVE_cmd_dl_burst(VERTEX2F(gph->x + gph->padding + x_cur, EVE_VSIZE - ((uint16_t)(buf[i]/y_div) + margin + gph->padding)));
// decrement index
i--;
}
}
// End EVE_LINE_STRIP and therefore DATA
EVE_cmd_dl_burst(DL_END);
/// Draw current POSITION MARKER in frame mode
if(gph->graphmode == 0){
EVE_cmd_dl_burst(DL_COLOR_RGB | 0xff0000);
EVE_cmd_dl_burst(DL_BEGIN | EVE_LINE_STRIP);
EVE_cmd_dl_burst(VERTEX2F(gph->x + gph->padding + *buf_curidx, curY + gph->padding - 5 ));
EVE_cmd_dl_burst(VERTEX2F(gph->x + gph->padding + *buf_curidx, curY + gph->padding + gph->height + 5 ));
EVE_cmd_dl_burst(DL_END);
}
/////////////// GRAPH END
}
void TFT_graph_pixeldata_f(graph* gph, float_buffer_t buf[], uint16_t buf_size, uint16_t *buf_curidx, uint32_t datacolor){
/// This is a copy of the above function! It taken a float buffer and will later be merged to its origin.
// Determine current position (with scroll value)
uint16_t curY = gph->y - TFT_cur_ScrollV;
/// Display current DATA as line strip in frame or roll mode
EVE_cmd_dl_burst(DL_COLOR_RGB | datacolor);
EVE_cmd_dl_burst(DL_BEGIN | EVE_LINE_STRIP);
/// Display graph frame-mode
if(gph->graphmode == 0){
// Print values in the order they are stored
for (int x_cur = 0; x_cur < buf_size; ++x_cur) {
EVE_cmd_dl_burst(VERTEX2F(gph->x + gph->padding + x_cur, curY + gph->padding + gph->height - (uint16_t)(( ((float)buf[x_cur]) / ((float)gph->y_max) )*(float)(gph->height)) )); //if(frameover==1) printf("%lf %lf\n", ((((float)(buf[x_cur]))/((float)gph->y_max))*(float)(gph->height)), (float)buf[gph->x]);
}
}
/// Display graph roll-mode
else {