-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
isp_timi_mates.spin2
1875 lines (1487 loc) · 62.5 KB
/
isp_timi_mates.spin2
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....... isp_timi_mates.spin2
'' Purpose.... the spin2 Mates Serial controller object
''
'' An object used for communicating with BBM Devices, over serial port.
''
'' This object contains various methods for sending and retrieving data
'' relating to display widgets, their states and parameters and
'' the health of the controller
''
'' Authors.... Stephen M Moraco
'' -- Copyright (c) 2023 Iron Sheep Productions, LLC
'' -- see below for terms of use
'' E-mail..... stephen@ironsheep.biz
'' Started.... May 2023
'' Updated.... 12 May 2023
''
'' =================================================================================================
''
CON ' --- Mates Commands ---
{
Represent possible commands to send to devices over a serial port.
Attributes
----------
MATES_CMD_SET_PAGE - commmand sent by controller to set current page.
MATES_CMD_GET_PAGE - commmand sent by controller to get index of current page.
MATES_CMD_SET_WIDGET_VALUE - commmand sent by controller to set value of a widget.
MATES_CMD_GET_WIDGET_VALUE - commmand sent by controller to get the value of a widget.
MATES_CMD_SET_WIDGET_PARAM - commmand sent by controller to set the value of a parameter associated with a widget.
MATES_CMD_GET_WIDGET_PARAM - commmand sent by controller to get the value of a parameter associated with a widget.
MATES_CMD_SET_BACKLIGHT - commmand sent by controller to set the intensity of device backlight.
MATES_CMD_CLR_PRINT_AREA - commmand sent by controller to clear Print Area widgets.
MATES_CMD_SET_PRINT_COLR - commmand sent by controller to set the colour of Print Area widgets.
MATES_CMD_SYSTEM_RESET - commmand sent by controller to request a soft system reset.
MATES_CMD_PIN_MODE - commmand sent by controller to designate available pins as input or output.
MATES_CMD_DIGITAL_WRITE - commmand sent by controller to control an IO pin set as output.
MATES_CMD_DIGITAL_READ - commmand sent by controller to read a specified pin set as input.
MATES_CMD_BTN_EVENT_COUNT - commmand sent by controller to query the number of button events recorded.
MATES_CMD_NEXT_BTN_EVENT - commmand sent by controller to query the next button recorded.
MATES_CMD_SWP_EVENT_COUNT - commmand sent by controller to query the number of swipe events recorded.
MATES_CMD_NEXT_SWP_EVENT - commmand sent by controller to query the next swipe recorded.
MATES_CMD_UPDATE_TEXT_AREA - commmand sent by controller to update the contents of a Text Area widget.
MATES_CMD_APPEND_PRINT_AREA - commmand sent by controller to append data to a Print Area widget.
MATES_CMD_SCREENSHOT - commmand sent by controller to request RAW 16-bit pixel information.
MATES_CMD_SET_WIDGET_32VAL - commmand sent by controller to change the 32 bit value of compatible widgets.
MATES_CMD_APPEND_SCOPE_DATA - commmand sent by controller to append data to a Scope widget.
MATES_CMD_UPDATE_DOT_MATRIX - commmand sent by controller to update data displayed by a Dot Matrix widget.
}
MATES_CMD_SET_PAGE = $0000
MATES_CMD_GET_PAGE = $0001
MATES_CMD_SET_WIDGET_VALUE = $0002
MATES_CMD_GET_WIDGET_VALUE = $0003
MATES_CMD_SET_WIDGET_PARAM = $0004
MATES_CMD_GET_WIDGET_PARAM = $0005
MATES_CMD_SET_BACKLIGHT = $0006
MATES_CMD_CLR_PRINT_AREA = $0007
MATES_CMD_SET_PRINT_COLR = $0008
MATES_CMD_SYSTEM_RESET = $0009
MATES_CMD_PIN_MODE = $000A
MATES_CMD_DIGITAL_WRITE = $000B
MATES_CMD_DIGITAL_READ = $000C
MATES_CMD_BTN_EVENT_COUNT = $000D
MATES_CMD_NEXT_BTN_EVENT = $000E
MATES_CMD_SWP_EVENT_COUNT = $000F
MATES_CMD_NEXT_SWP_EVENT = $0010
MATES_CMD_UPDATE_TEXT_AREA = $FFFF
MATES_CMD_APPEND_PRINT_AREA = $FFFE
MATES_CMD_SCREENSHOT = $FFFD
MATES_CMD_SET_WIDGET_32VAL = $FFFC
MATES_CMD_APPEND_SCOPE_DATA = $FFFB
MATES_CMD_UPDATE_DOT_MATRIX = $FFFA
NOT_SET = -1
None = INT_32_MAX
OBJ
serIO : "isp_serial" ' timi serial input/output
nstr : "jm_nstrings" ' number-to-string
CON ' --- PUBLIC Interface ---
DAT
pin_tx LONG NOT_SET
pin_rx LONG NOT_SET
pin_rst LONG NOT_SET
ioBaudRate LONG NOT_SET
matesError LONG MATES_ERROR_NONE
' --- Mates Library Versions at time of port to spin2 ---
matesStudioCompatVer BYTE "1.0.16",0
matesControllerLibVer BYTE "1.0.8", 0
pub null()
'' {This is not a top-level object}
PUB start(pinTx, pinRx, pinReset, baudRate) : bDidSucceed | pullupVal
'' Start simple serial comms on given pins at baudrate
pin_tx := pinTx
pin_rx := pinRx
pin_rst := pinReset
ioBaudRate := baudRate
serIO.startx(pin_rx, pin_tx, ioBaudRate, serIO.PU_NONE)
debug("Initializing Serial port @ ", udec_(ioBaudRate), " baud")
pullupVal := pullUpValueForEnum(serIO.PU_3K3)
pinclear(pin_rst) ' clear pin of smart mode
pinfloat(pin_rst) ' reset
wrpin(pin_rst, pullupVal) ' configure pull-up
pinhigh(pin_rst)
bDidSucceed := hardReset()
if bDidSucceed
bDidSucceed := sync(TRUE, 5000)
PRI pullUpValueForEnum(pullupRqst) : pullup
case pullupRqst
serIO.PU_NONE : pullup := P_HIGH_FLOAT ' use external pull-up
serIO.PU_1K5 : pullup := P_HIGH_1K5 ' 1.5k
serIO.PU_3K3 : pullup := P_HIGH_1MA ' acts like ~3.3k
other : pullup := P_HIGH_15K ' 15K
PUB stop()
'' Stop underlying serial device and release pins
serIO.stop()
PUB error(): latestError
'' Return latest Mates Error Code
latestError := matesError
CON ' --- Mates Library at time of port to spin2 ---
PUB hardReset() : bDidSucceed | startTimeMSec, timeDeltaMSec
'' Uses hardware driven signal to hard reset Timi device
'' Returns the boolean response from the reset
if pin_rst == NOT_SET
softReset()
else
debug("Hard Resetting module ...")
matesHwReset()
startTimeMSec := getms()
bDidSucceed := waitForAck(MATES_BOOT_TIMEOUT)
timeDeltaMSec := (getms() - startTimeMSec)
if bDidSucceed == TRUE
debug("SUCCESS after ", udec_(timeDeltaMSec), " ms")
else
debug("Timed out after ", udec_(timeDeltaMSec), " ms")
PUB softReset() : bDidSucceed | startTimeMSec, timeDeltaMSec
'' Sends a serial command to the connected Timi device to trigger a reset
'' Returns the boolean response from the reset
debug("Resetting module using command ...")
write_command(MATES_CMD_SYSTEM_RESET)
startTimeMSec := getms()
bDidSucceed := waitForAck(MATES_BOOT_TIMEOUT)
timeDeltaMSec := (getms() - startTimeMSec)
if bDidSucceed
debug("Done after ", udec_(timeDeltaMSec), " ms")
else
debug("Timed out after ", udec_(timeDeltaMSec), " ms")
PRI sync(bResetToPage0, timeout) : bDidSucceed | page, startTimeMSec
' Attempts to synchronize with the display module by sending simple read page commands
' at certain interval until a proper response is received
debug("TIMI: Synchronizing with the module...")
bDidSucceed := TRUE
page := -1
startTimeMSec := getms()
repeat
if (timeout > 0) and (getms() - startTimeMSec >= timeout)
' Set Error
debug("Timeout Error")
bDidSucceed := FALSE
quit
if bDidSucceed
page := getPage()
while page == -1
if bDidSucceed
delayMS(100)
serIO.rxflush()
debug("TIMI: Sync get curr page...")
page := getPage()
if page == -1
debug("Sync Error")
bDidSucceed := FALSE
else
if bResetToPage0 and page <> 0
debug("TIMI: Reset To Page 0...")
setPage(0, MATES_RESPONSE_TIMEOUT)
PUB setBacklight(backlightValue) : bDidSucceed
'' Sets the intensity of the backlight of connected device: where {backlightValue} is [0-255]
'' Returns the boolean response from the backlight command
debug("Setting backlight to ", sdec_(backlightValue), " ...")
check_argument_value(@"backlightValue", backlightValue, RTE_UINT8)
write_command(MATES_CMD_SET_BACKLIGHT)
write_int16(backlightValue)
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
PUB setPage(pageIndex, timeout) : bDidSucceed
'' Sets the page to be displayed on the connected device
'' {pageIndex} index of page to set as current. Value must be within the uint16 datatype range
'' {timeout} overrides the default timeout, in case Page needs more time to draw
'' Returns T/F where T indicates success
debug("setPage(", udec_(pageIndex), ")...")
bDidSucceed := setPageShowingDebug(pageIndex, timeout, FALSE)
PRI setPageShowingDebug(pageIndex, pageDrawTimeout, bShowDebug) : bDidSucceed
' Sets the page to be displayed on the connected device
' {pageIndex} index of page to set as current. Value must be within the uint16 datatype range
' {timeout} overrides the default timeout, in case Page needs more time to draw
' {bShowDebug} whether to log messages or skip (typically when syncing)
' Returns T/F where T indicates success
if (bShowDebug)
debug("Navigating to page ", sdec_(pageIndex), " ...")
check_argument_value(@"pageIndex", pageIndex, RTE_UINT16)
write_command(MATES_CMD_SET_PAGE)
write_int16(pageIndex)
bDidSucceed := waitForAck(pageDrawTimeout)
PUB getPage() : pageIdx
'' Returns {pageIdx} the index of the current page displayed by the connected device
pageIdx := getPageShowingDebug(FALSE)
PRI getPageShowingDebug(bShowDebug) : pageIdx
' get the index of the current page displayed by the connected device
' {bShowDebug} whether to log messages or skip (typically when syncing)
' Return the current page index
if (bShowDebug)
debug("Querying active page ....")
write_command(MATES_CMD_GET_PAGE)
pageIdx := read_response()
if (bShowDebug)
debug(" -- At page ", sdec_(pageIdx), " ...")
PUB setWidgetValueById(widgetId, widgetValue) : bDidSucceed
'' Sets the value of a specific widget based on the provided identifier
'' {widgetId} the unique id of the desired widget. Value must be within the int16 datatype range
'' {widgetValue} the value the corresponding widget will be set to. Value must exist within the int16 datatype range
'' Returns T/F where T indicates success
check_argument_value(@"widgetId", widgetId, RTE_INT16)
check_argument_value(@"value", widgetValue, RTE_INT16)
debug("Setting widget (", uhex_(widgetId), ") value to {", sdec_(widgetValue), "} ...")
write_command(MATES_CMD_SET_WIDGET_VALUE)
write_int16(widgetId)
write_int16(widgetValue)
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
PUB getWidgetValueById(widgetId) : widgetValue
'' Gets the value of a widget based on the {widgetId}
'' {widgetId} the unique id of the target widget. Value must be within the uint16 datatype range.
'' Returns {widgetValue} an integer corresponding to widget value.
check_argument_value(@"widgetId", widgetId, RTE_INT16)
debug("Query widget (", uhex_(widgetId), ") value ...")
write_command(MATES_CMD_GET_WIDGET_VALUE)
write_int16(widgetId)
widgetValue := read_response()
PUB setWidgetValueByIndex(widgetType, widgetIndex, widgetValue) : bDidSucceed | widgetId
'' Sets the value of a specific widget based on the index within a widget type
'' {widgetType} the unique type of widget to be changed
'' {widgetIndex} the index of the widget, of a specific type. Value must be within the uint8 datatype range.
'' {widgetValue} the value the corresponding widget will be set to. Value must be within the int16 datatype range.
'' Returns T/F where T indicates success
widgetId := getWidgetId(widgetType, widgetIndex)
bDidSucceed := setWidgetValueById(widgetId, widgetValue)
PUB getWidgetValueByIndex(widgetType, widgetIndex) : widgetValue | widgetId
'' Gets the value of a specific widget based on the index within a widget type
'' {widgetType} the unique type of widget to be queried
'' {widgetIndex} the index of the widget, of a specific type. Value must be within the uint8 datatype range.
'' Returns {widgetValue} an integer corresponding to widget value.
widgetId := getWidgetId(widgetType, widgetIndex)
widgetValue := getWidgetValueById(widgetId)
PUB setLedDigitsShortValue(widgetIndex, widgetValue) : bDidSucceed
'' Sets the value of specifically int16 LED Digits widgets based on the widget index
'' {widgetIndex} the index of the LED Digits widget. Value must be within uint8 datatype range.
'' {widgetValue} the value the corresponding widget will be set to. Values must be within the int16 datatype range.
'' Returns T/F where T indicates success
bDidSucceed := setWidgetValueByIndex(MATES_LED_DIGITS, widgetIndex, widgetValue)
PUB setLedDigitsLongValue(widgetIndex, widgetValue) : bDidSucceed | widgetId
'' Sets the value of specifically int32 LED Digits widgets based on the widget index
'' {widgetIndex} the index of the LED Digits widget. Value must be within uint8 datatype range.
'' {widgetValue} the value the corresponding widget will be set to. Values must be within the int32 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"value", widgetValue, RTE_INT32)
widgetId := getWidgetId(MATES_LED_DIGITS, widgetIndex)
bDidSucceed := set_widget_value_32bit(widgetId, widgetValue, RTE_INT32)
PUB setLedDigitsFloatValue(widgetIndex, floatWidgetValue) : bDidSucceed | widgetId
'' Sets the value of specifically float32 LED Digits widgets based on the widget index
'' {widgetIndex} the index of the LED Digits widget. Value must be within uint8 datatype range.
'' {floatWidgetValue} the value the corresponding widget will be set to. Values must be within the float32 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"value", floatWidgetValue, RTE_FLOAT32)
widgetId := getWidgetId(MATES_LED_DIGITS, widgetIndex)
bDidSucceed := set_widget_value_32bit(widgetId, floatWidgetValue, RTE_FLOAT32)
PUB setSpectrumValue(spectrumId, gaugeIndex, widgetValue) : bDidSucceed
'' Sets the value of specifically Spectrum widgets based the spectrum id and gauge index
'' {spectrumId} the id of the relevant Spectrum widget. Value must be within the int16 datatype range.
'' {gaugeIndex} the gauge index within the target Spectrum widget. Value must be within the uint8 datatype range.
'' {widgetValue} the value the corresponding widget will be set to. Value must be within the uint8 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"spectrumId", spectrumId, RTE_INT16)
check_argument_value(@"gaugeIndex", gaugeIndex, RTE_UINT8)
check_argument_value(@"value", widgetValue, RTE_UINT8)
bDidSucceed := setWidgetValueById(spectrumId, (gaugeIndex << 8) | widgetValue)
PUB setLedSpectrumValue(ledSpectrumIndex, gaugeIndex, widgetValue) : bDidSucceed | widgetId
'' Sets the value of specific LED Spectrum widgets based on the gauge index
'' {ledSpectrumIndex} the index of the desired LED Spectrum widget. Value must be within the uint8 datatype range.
'' {gaugeIndex} the gauge index within the target LED Spectrum widget. Value must be within the uint8 datatype range.
'' {widgetValue} the value the corresponding widget will be set to. Value must be within the uint8 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"gaugeIndex", gaugeIndex, RTE_UINT8)
check_argument_value(@"value", widgetValue, RTE_UINT8)
widgetId := getWidgetId(MATES_LED_SPECTRUM, ledSpectrumIndex)
bDidSucceed := setWidgetValueById(widgetId, (gaugeIndex << 8) | widgetValue)
PUB setMediaSpectrumValue(mediaIndex, gaugeIndex, widgetValue) : bDidSucceed | widgetId
'' Sets the value of specific Media Spectrum widgets based on the Media Spectrum index and the gauge index.
'' {mediaIndex} the index of the Media Spectrum widget. Value must be within the uint8 datatype range.
'' {gaugeIndex} the index of the desired gauge. Value must be within the uint8 datatype range.
'' {widgetValue} the value the corresponding widget will be set to. Value must be within the uint8 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"gaugeIndex", gaugeIndex, RTE_UINT8)
check_argument_value(@"value", widgetValue, RTE_UINT8)
widgetId := getWidgetId(MATES_MED_SPECTRUM, mediaIndex)
bDidSucceed := setWidgetValueById(widgetId, (gaugeIndex << 8) | widgetValue)
PUB setWidgetParamById(widgetId, param, widgetValue) : bDidSucceed
'' Sets the value of a widget parameter based on widget id and parameter id.
'' {widgetId} the unique id of the target widget. Value must be within the int16 datatype range.
'' {param} the unique id of the target parameter. Value must be within the int16 datatype range.
'' {widgetValue} the value the corresponding parameter will be set to. Value must be within the int16 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"widgetId", widgetId, RTE_INT16)
check_argument_value(@"param", param, RTE_INT16)
check_argument_value(@"value", widgetValue, RTE_INT16)
debug("Set widget (", uhex_(widgetId), ") parameter (", uhex_(param), ") to {", udec_(widgetValue), "} ...")
write_command(MATES_CMD_SET_WIDGET_PARAM)
write_int16(widgetId)
write_int16(param)
write_int16(widgetValue)
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
PUB getWidgetParamById(widgetId, param) : targetParamValue
'' Gets the value of a widget parameter based on widget id and parameter id.
'' {widgetId} the unique id of the target widget. Value must be within the int16 datatype range.
'' {param} the unique id of the target parameter. Value must be within the int16 datatype range.
'' Returns and integer containing the target parameter value.
check_argument_value(@"widgetId", widgetId, RTE_INT16)
check_argument_value(@"param", param, RTE_INT16)
debug("Query widget (", uhex_(widgetId), ") parameter (", uhex_(param), ") ...")
write_command(MATES_CMD_GET_WIDGET_PARAM)
write_int16(widgetId)
write_int16(param)
targetParamValue := read_response()
PUB setWidgetParamByIndex(widgetType, widgetIndex, param, widgetValue) : bDidSucceed | widgetId
'' Sets the value of a widget parameter based on widget index and parameter id.
'' {widgetType} the type of the target widget.
'' {widgetIndex} the index of the target widget. Value must be within the uint8 datatype range.
'' {param} the unique id of the target parameter. Value must be within the int16 datatype range.
'' {widgetValue} the value the corresponding parameter will be set to. Value must be within the int16 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"widgetIndex", widgetIndex, RTE_UINT8)
check_argument_value(@"param", param, RTE_INT16)
check_argument_value(@"value", widgetValue, RTE_INT16)
widgetId := getWidgetId(widgetType, widgetIndex)
bDidSucceed := setWidgetParamById(widgetId, param, widgetValue)
PUB getWidgetParamByIndex(widgetType, widgetIndex, param) : widgetValue | widgetId
'' Gets the value of a widget parameter based on widget index and parameter id.
'' {widgetType} the type of the target widget.
'' {widgetIndex} the index of the target widget. Value must be within the uint8 datatype range.
'' {param} the unique id of the target parameter. Value must be within the int16 datatype range.
'' Returns {widgetValue} the target parameter value
check_argument_value(@"widgetIndex", widgetIndex, RTE_UINT8)
check_argument_value(@"param", param, RTE_INT16)
widgetId := getWidgetId(widgetType, widgetIndex)
widgetValue := getWidgetParamById(widgetId, param)
PUB setBufferSize(size)
'' setBufferSize(size): Currently NOT SUPPORTED
{
Currently unused (also undocumented).
Sets Buffer Size. Provided for future development.
Args
size
- new size of buffer
Returns
void.
}
{
if not 0 < size <= MATES_STRING_MAX_BUFFER_SIZE
debug("Buffer size of (", udec_(size), ") outside the range of min:1 to max:", udec_(MATES_STRING_MAX_BUFFER_SIZE))
mates_buffer_size := size
'}
PUB clearTextArea(textAreaIndex) : bDidSucceed
'' Clears a targeted Text Area
'' {textAreaIndex} the index of the target Text Area widget. Value must be within the uint16 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"textAreaIndex", textAreaIndex, RTE_UINT16)
debug("Clear TextArea ", udec_word_(textAreaIndex), " ...")
write_command(MATES_CMD_UPDATE_TEXT_AREA)
write_int16(textAreaIndex)
write_int8(0)
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
PUB updateTextArea(textAreaIndex, pString) : bDidSucceed
'' Updates the text displayed within Text Area widget
'' {textAreaIndex} the index of the target Text Area widget. Value must be within the uint16 datatype range.
'' {pString} the string to be displayed. Must be a zero terminated string.
'' Returns T/F where T indicates success
check_argument_value(@"textAreaIndex", textAreaIndex, RTE_UINT16)
debug("Update TextArea ", udec_word_(textAreaIndex), " ...")
write_command(MATES_CMD_UPDATE_TEXT_AREA)
write_int16(textAreaIndex)
write_string(pString) ' no zero term byte!
write_int8(0) ' add zero term byte!
bDidSucceed := waitForAck(MATES_RESPONSE_LTIMEOUT)
PUB clearPrintArea(printAreaIndex) : bDidSucceed
'' Clears a targeted Print Area
'' {printAreaIndex} the index of the target Print Area widget. Value must be within the uint16 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"printAreaIndex", printAreaIndex, RTE_UINT16)
debug("Clear PrintArea ", udec_word_(printAreaIndex), " ...")
write_command(MATES_CMD_CLR_PRINT_AREA)
write_int16(printAreaIndex)
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
PUB setPrintAreaColor565(printAreaIndex, rgb565Value) : bDidSucceed
'' Sets the color of a PrintArea Widget based on an rgb565 value
'' {printAreaIndex} the index of the target Print Area widget. Value must be within the uint16 datatype range
'' {rgb565Value} the color to set widget to. Value must be within the uint16 datatype range.
'' Returns T/F where T indicates success
check_argument_value(@"printAreaIndex", printAreaIndex, RTE_UINT16)
check_argument_value(@"rgb565", rgb565Value, RTE_UINT16)
write_command(MATES_CMD_SET_PRINT_COLR)
write_int16(printAreaIndex)
write_uint16(rgb565Value)
debug("Set PrintArea (", udec_(printAreaIndex), ") color to {", uhex_(rgb565Value), "} ...")
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
PUB setPrintAreaColorRGB(printAreaIndex, redValue, greenValue, blueValue) : bDidSucceed | rgb565Value
'' Sets the color of a PrintArea Widget
'' {printAreaIndex} the index of the target Print Area widget. Value must be within the uint16 datatype range
'' {redValue} the red concentration of the color to set widget to. Value must be within the uint8 datatype range
'' {greenValue} the green concentration of the color to set widget to. Value must be within the uint8 datatype range
'' {blueValue} the blue concentration of the color to set widget to. Value must be within the uint8 datatype range
'' Returns T/F where T indicates success
check_argument_value(@"printAreaIndex", printAreaIndex, RTE_UINT16)
check_argument_value(@"red", redValue, RTE_UINT8)
check_argument_value(@"green", greenValue, RTE_UINT8)
check_argument_value(@"blue", blueValue, RTE_UINT8)
rgb565Value := construct_rgb565_value(redValue, greenValue, blueValue)
bDidSucceed := setPrintAreaColor565(printAreaIndex, rgb565Value)
PUB appendArrayToPrintArea(printAreaIndex, pBytes, byteCount) : bDidSucceed | char, byteIdx
'' Appends {pBytes} a list of integers to the {printAreaIndex} Print Area widget
'' {printAreaIndex} index of the target Scope widget
'' {pBytes} pointer to list of uint8 values to be appended to Print Area widget
'' {byteCount} the number of uint8 values to be appended
'' Returns T/F where T indicates success
check_argument_value(@"printAreaIndex", printAreaIndex, RTE_UINT16)
debug("Append byte array to PrintArea ", udec_word_(printAreaIndex), " ...")
write_command(MATES_CMD_APPEND_PRINT_AREA)
write_int16(printAreaIndex)
write_int16(byteCount)
repeat byteIdx from 0 to byteCount - 1
char := BYTE[pBytes][byteIdx]
check_argument_value(@"print area array item", char, RTE_UINT8)
write_uint8(char)
bDidSucceed := waitForAck(MATES_RESPONSE_LTIMEOUT)
PUB appendStringToPrintArea(printAreaIndex, pString) : bDidSucceed
'' Appends {pString} to the {printAreaIndex} Print Area widget
'' {printAreaIndex} index of the target Print Area widget
'' {pString} the string to be appended to the Print Area
'' Returns T/F where T indicates success
check_argument_value(@"printAreaIndex", printAreaIndex, RTE_UINT16)
debug("Append string [", zstr_(pString), "] to PrintArea ", udec_word_(printAreaIndex), " ...")
write_command(MATES_CMD_APPEND_PRINT_AREA)
write_int16(printAreaIndex)
write_int16(strsize(pString))
write_string(pString) ' no zero term byte!
bDidSucceed := waitForAck(MATES_RESPONSE_LTIMEOUT)
PUB appendToScopeWidget(scopeIndex, pWordBuffer, countWords) : bDidSucceed
'' Appends {pWordBuffer} a list of integers to the {scopeIndex} Scope widget
'' {scopeIndex} index of the target Scope widget
'' {pWordBuffer} pointer to list of uint16 values to be appended to scope widget
'' {countWords} the number of uint16 values to be appended
'' Returns T/F where T indicates success
check_argument_value(@"scopeIndex", scopeIndex, RTE_UINT16)
debug("Appending values to Scope ", udec_word(scopeIndex), " ...")
write_command(MATES_CMD_APPEND_SCOPE_DATA)
write_int16(scopeIndex)
write_int16(countWords)
write_int16_buffer(pWordBuffer, countWords)
bDidSucceed := waitForAck(MATES_RESPONSE_LTIMEOUT)
PUB updateDotMatrixWidget(matrixIndex, pString) : bDidSucceed | string_to_write
'' Writes {pString} to the {matrixIndex} Dot Matrix widget
'' {matrixIndex} index of the target widget
'' {pString} pointer to zero terminated string to be displayed
'' Returns T/F where T indicates success
check_argument_value(@"matrix_index", matrixIndex, RTE_UINT16)
'debug("Updating DotMatrix ", udec_word_(matrixIndex), " ...")
write_command(MATES_CMD_UPDATE_DOT_MATRIX)
write_int16(matrixIndex)
write_int16(strsize(pString))
write_string(pString) ' no zero term byte!
bDidSucceed := waitForAck(MATES_RESPONSE_LTIMEOUT)
PUB getButtonEventCount() : countButtonEvents
'' Gets the number of events recorded from applicable button widgets
'' Returns {countButtonEvents} the number of events recorded
debug("Query number of button events...")
write_command(MATES_CMD_BTN_EVENT_COUNT)
countButtonEvents := read_response()
PUB getNextButtonEvent() : widgetId
'' Gets the next event source logged from applicable buttons
'' Returns {widgetId} an integer corresponding to the button widget ID
debug("Query the next recorded button event...")
write_command(MATES_CMD_NEXT_BTN_EVENT)
widgetId := read_response()
PUB getSwipeEventCount(): eventCount
'' Gets the number of events recorded from swipe gestures
'' Returns {eventCount} an integer corresponding to the number of events
debug("Query number of swipe events...")
write_command(MATES_CMD_SWP_EVENT_COUNT)
eventCount := read_response()
PUB getNextSwipeEvent() : swipeEvent
'' Gets the next swipe event value
'' Returns {swipeEvent} an integer corresponding to the swipe event
debug("Query the next recorded swipe event...")
write_command(MATES_CMD_NEXT_SWP_EVENT)
swipeEvent := read_response()
PUB getVersion() : pVerString
'' Helper function to obtain the version of the Python Mates Controller library
'' Returns {pVerString} string response of library version
pVerString := @matesControllerLibVer
PUB getCompatibility() : pVerString
'' Helper function to obtain the version of the Mates Studio compatible with this library version
'' Returns {pVerString} string response of Mates Studio version compatible with this library
pVerString := @matesStudioCompatVer
PUB printVersion()
'' Debugging function to print the version of the Mates Studio compatible along with this specific library version.
debug("Mates Studio - Compatible Version : ", zstr_(getCompatibility()))
debug("Mates Controller - Library Version: ", zstr_(getVersion()))
PUB getError() : latestError
'' Helper function to obtain the current error state of the Mates Controller
'' REturns {latestError} MatesError response of current error
latestError := matesError
PUB takeScreenshot() : bDidSucceed, pImage | w, h
'' takeScreenshot() NOT supported!!
{
Sends a serial command to the connected device to request pixel information.
Args
void.
Returns
boolean response indicating command success or failure.
Image instance created using the pixel data
}
{
debug("Requesting screenshot from module ...")
write_command(MATES_CMD_SCREENSHOT)
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
if not bDidSucceed
return FALSE, None
w := read_int16()
h := read_int16()
chk := w ^ h
debug("Expecting a {}x{} image ({} bytes) ...".format(w, h, 2 * w * h))
image := Image.new("RGB", (w, h))
pixel_map := image.load()
for y in range(h)
for x in range(w)
pixel := read_int16()
r := (pixel & 0xF800) >> 8
g := (pixel & 0x07E0) >> 3
b := (pixel & 0x001F) << 3
' pixel_map[x, y] := r << 16 | g << 8 | b
pixel_map[x, y] := b << 16 | g << 8 | r
chk ^= pixel
return (chk == read_response()), image
'}
PUB saveScreenshot(pFilenameStr) : bDidSave
'' saveScreenshot() NOT supported!!
{
Takes a screenshot and saves it to a file.
Args
filename (str)
- the filename (file path) to use when saving the image file
Returns
boolean response indicating command success or failure.
}
{
res, image := takeScreenshot()
if not res
bDidSave := FALSE
image.save(filename)
bDidSave := TRUE
'}
CON ' ---- private functions below ----
PRI matesHwReset()
' assert hardware reset pin
if pin_rst <> NOT_SET
pinlow(pin_rst)
waitus(150) ' Windows UI does ~150 uS
pinhigh(pin_rst)
waitus(150)
PRI write_command(matesCommand) | BYTE cmdBffr[3]
cmdBffr.BYTE[0] := MATES_COMMAND_START_BYTE
cmdBffr.BYTE[1] := (matesCommand & $ff00) >> 8
cmdBffr.BYTE[2] := matesCommand & $ff
'debug("write_command(): cmd: ", uhex_byte_array_(@cmdBffr, 3))
write_bytes(@cmdBffr, 3)
PRI write_int8(int8Value)
serIO.tx(int8Value)
PRI write_uint8(uint8Value)
serIO.tx(uint8Value)
PRI write_int16(int16Value) | BYTE valBffr[2]
valBffr.BYTE[0] := (int16Value & $ff00) >> 8
valBffr.BYTE[1] := int16Value & $ff
write_bytes(@valBffr, 2)
PRI write_uint16(uint16Value) | BYTE valBffr[2]
valBffr.BYTE[0] := (uint16Value & $ff00) >> 8
valBffr.BYTE[1] := uint16Value & $ff
write_bytes(@valBffr, 2)
PRI write_int32(int32Value) | valBffr
valBffr.BYTE[0] := int32Value & $ff000000 >> 24
valBffr.BYTE[1] := int32Value & $ff0000 >> 16
valBffr.BYTE[2] := int32Value & $ff00 >> 8
valBffr.BYTE[3] := int32Value & $ff
write_bytes(@valBffr, 4)
PRI write_float(floatValue) | valBffr
valBffr.BYTE[0] := floatValue & $ff000000 >> 24
valBffr.BYTE[1] := floatValue & $ff0000 >> 16
valBffr.BYTE[2] := floatValue & $ff00 >> 8
valBffr.BYTE[3] := floatValue & $ff
write_bytes(@valBffr, 4)
PRI write_string(pString)
serIO.str(pString) ' write string with no zero term byte!
PRI write_int16_buffer(pInt16Ar, countOfInt16s) | wordIdx
repeat wordIdx from 0 to countOfInt16s - 1
write_int16(WORD[pInt16Ar][wordIdx])
PRI write_bytes(pBytes, byteCount) | byteIdx
repeat byteIdx from 0 to byteCount - 1
serIO.tx(BYTE[pBytes][byteIdx])
PRI waitForAck(timeoutMSec) : bDidSucceed | ack, charByte
charByte := serIO.rxtime(timeoutMSec)
' check timeout based upon returned byte
if charByte == -1
matesError := MATES_ERROR_COMMAND_TIMEOUT
debug("EEE: waitForAck() timedout")
bDidSucceed := FALSE
bDidSucceed := charByte == MATES_SAFE_ACK ? TRUE : FALSE
if bDidSucceed == FALSE
matesError := MATES_ERROR_COMMAND_FAILED
debug("EEE: waitForAck() unexpected Value")
matesError := MATES_ERROR_NONE
PRI read_int16(charTimeoutMSec) : int16Value | bTimedOut, WORD rdBytes
rdBytes := 0
rdBytes.byte[1] := serIO.rxtime(charTimeoutMSec)
bTimedOut := rdBytes.byte[1] == -1
rdBytes.byte[0] := serIO.rxtime(charTimeoutMSec)
bTimedOut |= rdBytes.byte[0] == -1
' check timeout based upon returned byte length
if bTimedOut
debug("Response timeout")
matesError := MATES_ERROR_RESPONSE_TIMEOUT
int16Value := None
else
int16Value := rdBytes
PRI read_response() : int16Value | tmpValue
if not waitForAck(MATES_RESPONSE_TIMEOUT)
int16Value := -1
else
tmpValue := read_int16(MATES_RESPONSE_TIMEOUT)
if matesError == MATES_ERROR_RESPONSE_TIMEOUT
int16Value := None
else
debug(" -- response: ", sdec_(tmpValue))
int16Value := tmpValue
PRI set_widget_value_32bit(widgetId, widgetValue32Bit, eRangeType) : bDidSucceed | bShoudWrite
debug("Set widget (", uhex_(widgetId), ") value to {", sdec_(widgetValue32Bit), "} ...")
bDidSucceed := bShoudWrite := FALSE
if eRangeType == RTE_INT32 or eRangeType == RTE_UINT32
bShoudWrite := TRUE
elseif eRangeType == RTE_FLOAT32
bShoudWrite := TRUE
else
debug("set_widget_value_32bit() type not 32bits, Abort")
if bShoudWrite
write_command(MATES_CMD_SET_WIDGET_32VAL)
write_int16(widgetId)
if eRangeType <> RTE_FLOAT32
check_argument_value(@"ivalue", widgetValue32Bit, RTE_INT32)
write_int32(widgetValue32Bit)
else
check_argument_value(@"fvalue", widgetValue32Bit, RTE_FLOAT32)
write_float(widgetValue32Bit)
bDidSucceed := waitForAck(MATES_RESPONSE_TIMEOUT)
PRI construct_rgb565_value(redValue, greenValue, blueValue) : rgb565Value
{
Constructs a 16 bit rgb565 value.
Args
redValue - Unsigned 8 bit integer value of red concentration.
greenValue - Unsigned 8 bit integer value of green concentration.
blueValue - Unsigned 8 bit integer value of blue concentration.
Returns
16 bit rgb565 value.
}
check_argument_value(@"red", redValue, RTE_UINT8)
check_argument_value(@"green", greenValue, RTE_UINT8)
check_argument_value(@"blue", blueValue, RTE_UINT8)
rgb565Value := 0
rgb565Value |= ((redValue & $F8) << 8)
rgb565Value |= ((greenValue & $FC) << 3)
rgb565Value |= ((blueValue & $F8) >> 3)
PRI check_argument_value(pArgName, argValue, eRangeType) | arg_min, arg_max
arg_min, arg_max := getRangeForType(eRangeType)
if not arg_min <= argValue <= arg_max
case eRangeType
RTE_FLOAT32:
' float value
debug("Value ERROR: [", zstr_(pArgName), "] of {", udec_(argValue), "} outside the {", zstr_(stringForRangeType(eRangeType)), "} range of {", sdec_(arg_min), "} to {", sdec_(arg_max), "}")
RTE_UINT8:
RTE_UINT16:
RTE_UINT32:
' unsigned value
debug("Value ERROR: [", zstr_(pArgName), "] of {", udec_(argValue), "} outside the {", zstr_(stringForRangeType(eRangeType)), "} range of {", sdec_(arg_min), "} to {", sdec_(arg_max), "}")
other:
' signed value
debug("Value ERROR: [", zstr_(pArgName), "] of {", sdec_(argValue), "} outside the {", zstr_(stringForRangeType(eRangeType)), "} range of {", sdec_(arg_min), "} to {", sdec_(arg_max), "}")
PRI getWidgetId(widget_type, widget_index) : widgetId | widgetIdValue
{
Helper function to obtain the ID of a widget based on its index and type.
Args
widget_type: MatesWidget
the type of the target widget.
widget_index the index of the target widget.
Returns
boolean response indicating command success or failure.
}
check_argument_value(@"widget_index", widget_index, RTE_INT8)
widgetIdValue := (widget_type << 8) | widget_index
widgetId := widgetIdValue <= 32767 ? widgetIdValue : widgetIdValue - 65536
CON ' --- PRIVATE (Utility) Methods/Constants ---
CON ' --- data and datatype limits required by the BBM controller ---
MATES_COMMAND_START_BYTE = "$"
MATES_BOOT_TIMEOUT = 5000 ' ms, 5 sec
MATES_STRING_BUFFER_SIZE = 250
MATES_STRING_MAX_BUFFER_SIZE = 32000 ' max allowable is 32767 but usually not required anyway
MATES_SAFE_ACK = $06
MATES_RESPONSE_TIMEOUT = 1000 ' ms, 1 sec
MATES_RESPONSE_LTIMEOUT = 2000 ' ms, 2 sec
MATES_MIN_BACKLIGHT = 0
MATES_MAX_BACKLIGHT = 15
CHAR_BYTE_LENGTH = 1
WORD_BYTE_LENGTH = 2
INT_BYTE_LENGTH = 4
UINT_8_MIN = 0
UINT_8_MAX = 255 ' 2**8 - 1
INT_8_MIN = -128 ' -(2**8)/2
INT_8_MAX = 127 ' (2**8)/2 - 1
UINT_16_MIN = 0
UINT_16_MAX = 65535 ' 2**16 - 1
INT_16_MIN = -32768 ' -(2**16)/2
INT_16_MAX = 32767 ' (2**16)/2 - 1
UINT_32_MIN = 0
UINT_32_MAX = 4294967295 ' 2**32 - 1
INT_32_MIN = -2147483648 ' -(2**32)/2
INT_32_MAX = 2147483647 ' (2**32)/2 - 1
FLOAT_32_MIN = $ff7fffff ' -2**128
FLOAT_32_MAX = $7f7fffff ' 2**128
' NOTE: https://www.h-schmidt.net/FloatConverter/IEEE754.html
' found using the above and playing with 2e128 and -2e128
' types enum
#0, RTE_UINT8, RTE_INT8, RTE_UINT16, RTE_INT16, RTE_UINT32, RTE_INT32, RTE_FLOAT32, RTE_MAX
TYPE_RANGE_ENTRY_LONG_CT = 2
TYPE_RANGE_MAX_IDX = RTE_MAX
DAT
datatype_ranges LONG 0[TYPE_RANGE_MAX_IDX * TYPE_RANGE_ENTRY_LONG_CT]
PRI range_init()
' initialize our range for type table
initRange(RTE_INT8, INT_8_MIN, INT_8_MAX)
initRange(RTE_UINT16, UINT_16_MIN, UINT_16_MAX)
initRange(RTE_INT16, INT_16_MIN, INT_16_MAX)
initRange(RTE_UINT32, UINT_32_MIN, UINT_32_MAX)
initRange(RTE_INT32, INT_32_MIN, INT_32_MAX)
initRange(RTE_FLOAT32, FLOAT_32_MIN, FLOAT_32_MAX)
PRI initRange(nType, nRngMin, nRngMax) | offset
' init a single entry in our table
offset := nType * TYPE_RANGE_ENTRY_LONG_CT
datatype_ranges[offset + 0] := nRngMin
datatype_ranges[offset+ 1] := nRngMax
PRI getRangeForType(eRangeType) : nRangeMin, nRangeMax
' return the current range for a given type
if eRangeType >= 0 and eRangeType < RTE_MAX
nRangeMin := datatype_ranges[eRangeType * TYPE_RANGE_ENTRY_LONG_CT + 0]
nRangeMax := datatype_ranges[eRangeType * TYPE_RANGE_ENTRY_LONG_CT + 1]
else
nRangeMin := 0
nRangeMax := 0