-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.s
2717 lines (2468 loc) · 50.8 KB
/
main.s
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
CHIP SN8F2288
//{{SONIX_CODE_OPTION
; Options for Lenovo Compact Keyboard
.Code_Option Fcpu "Fosc/4"
.Code_Option Fslow "Flosc/2"
.Code_Option High_CLK "12M_X'tal"
.Code_Option LVD "LVD_M"
.Code_Option Reset_Pin "P07"
.Code_Option Rst_Length "No"
.Code_Option Security "Enable"
.Code_Option Watch_Dog "Enable" ; On except for Green/Powerdown modes
//}}SONIX_CODE_OPTION
.DATA
_canary_check EQU 0x2880
_flasher EQU 0x2890
UTX EQU P0.6 ; S15
URX EQU P0.5 ; S10
tpSCL EQU P2.4
tpSCLM EQU P2M.4
tpSDA EQU P2.5
tpSDAM EQU P2M.5
tpIRQ EQU P2.6
S0 EQU P2.2
S0M EQU P2M.2
S1 EQU P2.0
S1M EQU P2M.0
S2 EQU P4.0
S2M EQU P4M.0
S3 EQU P4.5
S3M EQU P4M.5
S4 EQU P4.1
S4M EQU P4M.1
S5 EQU P2.1
S5M EQU P2M.1
S6 EQU P4.4
S6M EQU P4M.4
S7 EQU P4.2
S7M EQU P4M.2
S8 EQU P4.3
S8M EQU P4M.3
S9 EQU P2.3
S9M EQU P2M.3
S10 EQU P0.5
S10M EQU P0M.5
S11 EQU P0.4
S11M EQU P0M.4
S12 EQU P4.6
S12M EQU P4M.6
S13 EQU P4.7
S13M EQU P4M.7
S14 EQU P0.3
S14M EQU P0M.3
S15 EQU P0.6
S15M EQU P0M.6
R0 EQU P1.0
R0M EQU P1M.0
R1 EQU P1.7
R1M EQU P1M.7
R2 EQU P1.2
R2M EQU P1M.2
R3 EQU P1.1
R3M EQU P1M.1
R4 EQU P1.4
R4M EQU P1M.4
R5 EQU P1.3
R5M EQU P1M.3
R6 EQU P1.5
R6M EQU P1M.5
R7 EQU P1.6
R7M EQU P1M.6
EP0_BYTES EQU 8
EP1_BYTES EQU 8
EP2_BYTES EQU 8
bmRequestType DS 1
bRequest DS 1
wValueLo DS 1
wValueHi DS 1
wIndexLo DS 1
wIndexHi DS 1
wLengthLo DS 1
wLengthHi DS 1
txPtrLo DS 1
txPtrHi DS 1
txSizeLo DS 1
txSizeHi DS 1
txPktLen DS 1
txTmpCnt DS 1
usbState DS 1
usbStateSetupInvalid EQU usbState.0
usbStateSetAddress EQU usbState.1
usbStateIn0Done EQU usbState.3
usbStateZeroPad EQU usbState.4
usbStateStringCnt EQU usbState.5
usbStateCopyRAM EQU usbState.6
usbStateHTDData EQU usbState.7
usbState2 DS 1
usbStateAddressValid EQU usbState2.0
usbStateEnterFlasher EQU usbState2.1
systemState DS 1
enableUart EQU systemState.0
xlatVal1 DS 1
xlatVal2 DS 1
kbdRow DS 1
kbdRowsLow DS 1
bootKeyIdx DS 1
bootKeyVal DS 1
keyStateIdx DS 1
keyStateVal DS 1
modifierState1 DS 1 ; 224-231
modifierState2 DS 1 ; FN key
bootKeys0 DS 1
bootKeys1 DS 1
bootKeys2 DS 1
bootKeys3 DS 1
bootKeys4 DS 1
bootKeys5 DS 1
keyState0 DS 1 ; 0-7
keyState1 DS 1 ; 8-15
keyState2 DS 1 ; 16-
keyState3 DS 1 ; 24-
keyState4 DS 1 ; 32-
keyState5 DS 1 ; 40-
keyState6 DS 1 ; 48-
keyState7 DS 1 ; 56-
keyState8 DS 1 ; 64-
keyState9 DS 1 ; 72-
keyState10 DS 1 ; 80-
keyState11 DS 1 ; 88-
keyState12 DS 1 ; 96-
keyState13 DS 1 ; 104-
keyState14 DS 1 ; 112-
keyState15 DS 1 ; 120-
keyState16 DS 1 ; 128-
keyState17 DS 1 ; 136-
extraState0 DS 1
i2cTxData DS 1
i2cRxData DS 1
i2cBitCnt DS 1
tpData0 DS 1
tpData1 DS 1
tpData2 DS 1
tpData3 DS 1
tpData4 DS 1
ramClearEnd DS 1
keyNONE EQU keyState0.0
keyErrorRollOver EQU keyState0.1 ; Too many keys pressed or scan error
keyA EQU keyState0.4
keyB EQU keyState0.5
keyC EQU keyState0.6
keyD EQU keyState0.7
keyE EQU keyState1.0 ; 8
keyF EQU keyState1.1
keyG EQU keyState1.2
keyH EQU keyState1.3
keyI EQU keyState1.4
keyJ EQU keyState1.5
keyK EQU keyState1.6
keyL EQU keyState1.7
keyM EQU keyState2.0 ; 16
keyN EQU keyState2.1
keyO EQU keyState2.2
keyP EQU keyState2.3
keyQ EQU keyState2.4
keyR EQU keyState2.5
keyS EQU keyState2.6
keyT EQU keyState2.7
keyU EQU keyState3.0 ; 24
keyV EQU keyState3.1
keyW EQU keyState3.2
keyX EQU keyState3.3
keyY EQU keyState3.4
keyZ EQU keyState3.5
key1 EQU keyState3.6
key2 EQU keyState3.7
key3 EQU keyState4.0 ; 32
key4 EQU keyState4.1
key5 EQU keyState4.2
key6 EQU keyState4.3
key7 EQU keyState4.4
key8 EQU keyState4.5
key9 EQU keyState4.6
key0 EQU keyState4.7
keyRETURN EQU keyState5.0 ; 40
keyESC EQU keyState5.1
keyBACKSPACE EQU keyState5.2
keyTAB EQU keyState5.3
keySPACE EQU keyState5.4
keyMINUS EQU keyState5.5
keyEQUALS EQU keyState5.6
keyLEFTBRACKET EQU keyState5.7
keyRIGHTBRACKET EQU keyState6.0 ; 48
keyBACKSLASH EQU keyState6.1
keyNONUSHASH EQU keyState6.2
keySEMICOLON EQU keyState6.3
keyAPOSTROPHE EQU keyState6.4
keyGRAVE EQU keyState6.5
keyCOMMA EQU keyState6.6
keyPERIOD EQU keyState6.7
keySLASH EQU keyState7.0 ; 56
keyCAPSLOCK EQU keyState7.1
keyF1 EQU keyState7.2
keyF2 EQU keyState7.3
keyF3 EQU keyState7.4
keyF4 EQU keyState7.5
keyF5 EQU keyState7.6
keyF6 EQU keyState7.7
keyF7 EQU keyState8.0 ; 64
keyF8 EQU keyState8.1
keyF9 EQU keyState8.2
keyF10 EQU keyState8.3
keyF11 EQU keyState8.4
keyF12 EQU keyState8.5
keyPRINTSCREEN EQU keyState8.6
keySCROLLLOCK EQU keyState8.7
keyPAUSE EQU keyState9.0 ; 72
keyINSERT EQU keyState9.1
keyHOME EQU keyState9.2
keyPAGEUP EQU keyState9.3
keyDELETE EQU keyState9.4
keyEND EQU keyState9.5
keyPAGEDOWN EQU keyState9.6
keyRIGHT EQU keyState9.7
keyLEFT EQU keyState10.0 ; 80
keyDOWN EQU keyState10.1
keyUP EQU keyState10.2
keyNUMLOCK EQU keyState10.3
keyKPDIV EQU keyState10.4
keyKPMUL EQU keyState10.5
keyKPMINUS EQU keyState10.6
keyKPPLUS EQU keyState10.7
keyKPENTER EQU keyState11.0 ; 88
keyKP1 EQU keyState11.1
keyKP2 EQU keyState11.2
keyKP3 EQU keyState11.3
keyKP4 EQU keyState11.4
keyKP5 EQU keyState11.5
keyKP6 EQU keyState11.6
keyKP7 EQU keyState11.7
keyKP8 EQU keyState12.0 ; 96
keyKP9 EQU keyState12.1
keyKP0 EQU keyState12.2
keyKPCOLON EQU keyState12.3
keyNONUSBACKSLASH EQU keyState12.4
keyAPPLICATION EQU keyState12.5
keyPOWER EQU keyState12.6
keyKPEQUALS EQU keyState12.7 ; 103
keyFIND EQU keyState15.6 ; 126
keyMUTE EQU keyState15.7 ; 127
keyVOLUMEUP EQU keyState16.0 ; 128
keyVOLUMEDOWN EQU keyState16.1 ; 129
keyINTERNATIONAL1 EQU keyState16.7 ; 135
keyINTERNATIONAL2 EQU keyState17.0
keyINTERNATIONAL3 EQU keyState17.1
keyINTERNATIONAL4 EQU keyState17.2
keyINTERNATIONAL5 EQU keyState17.3
keyINTERNATIONAL6 EQU keyState17.4
keyINTERNATIONAL7 EQU keyState17.5
keyINTERNATIONAL8 EQU keyState17.6
keyINTERNATIONAL9 EQU keyState17.7 ; 143
keySLEEP EQU extraState0.0
keyBRIGHTNESSUP EQU extraState0.1
keyBRIGHTNESSDOWN EQU extraState0.2
keyCAMERATOGGLE EQU extraState0.3
keyMICTOGGLE EQU extraState0.4
keyXMUTE EQU extraState0.5
keyXVOLUP EQU extraState0.6
keyXVOLDOWN EQU extraState0.7
; keyKPMEMSTORE EQU 208
; keyKPMEMRECALL EQU 209
; keyKPMEMCLEAR EQU 210
; keyKPMEMADD EQU 211
; keyKPMEMSUBTRACT EQU 212
; keyKPMEMMULTIPLY EQU 213
; keyKPMEMDIVIDE EQU 214
keyLCTRL EQU modifierState1.0 ; 224
keyLSHIFT EQU modifierState1.1
keyLALT EQU modifierState1.2
keyLGUI EQU modifierState1.3
keyRCTRL EQU modifierState1.4
keyRSHIFT EQU modifierState1.5
keyRALT EQU modifierState1.6
keyRGUI EQU modifierState1.7 ; 231
keyFN EQU modifierState2.0
stateFnLock EQU modifierState2.1
stateFnCtrlSwap EQU modifierState2.2
stateHiddenESC EQU modifierState2.3
.CODE
ORG 0x0 ; Reset vector
; Jump to bootloader, checks canary and continues execution at 0x10 if found
JMP _canary_check
ORG 0x8 ; Interrupt vector
JMP _flasher
ORG 0x10 ; Bootloader jumps here on successful canary check, start of payload execution
_start:
JMP _preinit
_default_settings0:
DB 0 ; Set to 1 to enable debugging over UART
DB 0 ; Set to 1 to enable FN/CTRL swap
_default_settings1:
DB 0 ; Set to 1 to enable FN lock for F-key row
DB 0 ; Still unused
_read_settings:
B0MOV Y, #_default_settings0$M
B0MOV Z, #_default_settings0$L
MOVC
CMPRS A, #0
B0BSET enableUart
B0BTS0 R.0
B0BSET stateFnCtrlSwap
B0MOV A, R
B0MOV Y, #_default_settings1$M
B0MOV Z, #_default_settings1$L
MOVC
CMPRS A, #0
B0BSET stateFnLock
RET
_preinit:
; Set stack pointer and disable interrupts
MOV A, #7
B0MOV STKP, A
MOV A, #0
B0MOV RBANK, A
; Jump into bootloader if watchdog triggered or undefined reset source
B0BTS1 FNT0
JMP _flasher ; NT0 == 0 => watchdog reset or undefined reason
; Light up the power LED (P5.3/PWM0)
B0BCLR P5.3 ; Set to low level to light up
B0BSET P5M.3 ; Set to output
; DS indicates watchdog may start running before CPU
; Tickle it once so we have a well-defined time left
MOV A, #0x5a
B0MOV WDTR, A
; Set up P0.6/UTX (UART TX)
; FIXME: PnUR is write-only, B0BSET/B0BCLR are likely broken
B0BSET P0UR.6 ; Enable pull-up (UART idle is high)
B0BCLR P0M.6 ; Set to input (TXEN will override to output)
MOV A, #0x60 ; Baud 115200
B0MOV URBRC, A
MOV A, #0x90 ; 24MHz clock, TX enabled, 8n1, 1-byte mode
B0MOV URTX, A
; Send a message that we are alive
MOV A, #1 ; enableUart
B0MOV systemState, A ; will be cleared by ram clear later
MOV A, #'H'
CALL _uart_tx
MOV A, #'i'
CALL _uart_tx
MOV A, #'!'
CALL _uart_tx
MOV A, #13
CALL _uart_tx
MOV A, #10
CALL _uart_tx
; Jump into bootloader if "Return" key (S10/R6) is held
B0BSET P0M.5 ; Set S10 to output
B0BCLR P1M.5 ; Set R6 to input
B0BSET P1UR.5 ; Enable pull-up on R6
B0BSET S10 ; Set S10 high
CALL _delayshort
B0BTS1 R6 ; Jump if R6 is low
JMP @F
B0BCLR S10 ; Set S10 low
CALL _delayshort
B0BTS1 R6 ; Jump if R6 is low
JMP _return_held
@@:
; Jump into bootloader if P0.5/P0.6 are shorted (URX/UTX)
B0BCLR 0xa9.4 ; Switch UTX back to GPIO
B0BSET P0M.6 ; Set UTX to output
B0BCLR P0M.5 ; Set URX to input
B0BSET P0UR.5 ; Enable pull-up on URX
B0BSET UTX ; Set P0.6/UTX high
CALL _delayshort
B0BTS1 URX ; Jump if P0.5/URX is low
JMP @F
B0BCLR UTX ; Set P0.6/UTX low
CALL _delayshort
B0BTS1 URX ; Jump if P0.5/URX is low
JMP _uart_shorted
@@:
; Reset either from undervoltage (power-on) or external reset
; Cold reset state per datasheet:
; - Clock is 12MHz PLL synced to external oscillator
; - IOs set to input
; Clear RAM
B0MOV Y, #0
B0MOV Z, #ramClearEnd$L
MOV A, #0
@@:
B0MOV @YZ, A
DECMS Z
JMP @B
B0MOV @YZ, A
CALL _read_settings
; Setup GPIO
CALL _gpio_init
; Setup USB registers
CALL _usb_init
CALL _i2c_tp_init
_mainloop:
; Tickle watchdog
MOV A, #0x5a
B0MOV WDTR, A
; Check for any events that need handling
B0BTS0 FEP0SETUP ; Jump if SETUP packet rx'd
JMP _usb_setup
B0BTS0 FEP0OUT
JMP _usb_ep0_out
B0BTS0 FEP0IN
JMP _usb_ep0_in
B0BTS0 FBUS_RST
JMP _usb_reset
B0BTS0 FSOF
JMP _usb_sof
B0BTS0 FSUSPEND
JMP _usb_suspend
B0BTS1 tpIRQ ; Level-triggered, reset by reading data over I2C
JMP _tp_update
; Rinse and repeat
JMP _mainloop
_usb_suspend:
MOV A, #'P'
CALL _uart_tx
MOV A, #'D'
CALL _uart_tx
; enter suspend
B0BCLR 0xa9.4 ; Switch UTX to INPUT
B0BCLR P5M.3 ; Disable power LED
; output low on sense lines
B0BSET S0M
B0BSET S1M
B0BSET S2M
B0BSET S3M
B0BSET S4M
B0BSET S5M
B0BSET S6M
B0BSET S7M
B0BSET S8M
B0BSET S9M
B0BSET S10M
B0BSET S11M
B0BSET S12M
B0BSET S13M
B0BSET S14M
B0BSET S15M
B0BSET FCPUM0 ; Enter sleep mode
NOP
NOP
; exit suspend
CALL _gpio_init
; did host wake us?
B0BTS1 FSUSPEND
JMP @F
; key-press wake?
MOV A, #'!'
CALL _uart_tx
; Signal K state to wake host
; Drive D+ low, D- high (K state)
MOV A, #0x05
B0MOV UPID, A
; FIXME: Wait at least 1ms, no longer than 15ms
CALL _delayshort
CALL _delayshort
CALL _delayshort
CALL _delayshort
CALL _delayshort
CALL _delayshort
; Revert back to default
MOV A, #0x00
B0MOV UPID, A
@@:
MOV A, #'W'
CALL _uart_tx
MOV A, #'U'
CALL _uart_tx
JMP _mainloop
_usb_sof:
B0BCLR FSOF
; Check for cross-talk from too many depressed keys
CALL _kbd_count_rows_low
; Read the columns
CALL _kbd_sense
; Release the scanned row
CALL _kbd_set_row_input
; Increment row
INCMS kbdRow
MOV A, #0x07
AND kbdRow, A
; Lower the next row
CALL _kbd_set_row_output
; Update boot keys
CALL _kbd_update_boot_keys
; Update EP1 buffer
CALL _kbd_write_ep1
B0MOV A, bootKeys0
OR A, bootKeys1
B0BTS0 FZ ; Jump if kbdState is zero
JMP _mainloop
MOV A, #' '
CALL _uart_tx
MOV A, #'K'
CALL _uart_tx
B0MOV A, kbdRow
CALL _uart_hex
B0MOV A, bootKeys0
CALL _uart_hex
B0MOV A, bootKeys1
CALL _uart_hex
JMP _mainloop
_mouse_write_ep2:
B0BTS0 FUE2M0 ; Skip if zero
RET
; FUE2M0 is zero (NAK)
MOV A, #32 ; EP2 begins at offset 32
B0MOV UDP0, A
B0BTS0 keyFN
JMP _mouse_write_ep2_alt
B0MOV A, tpData1 ; Button byte
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, tpData2 ; X-axis
B0MOV UDR0_W, A
INCMS UDP0
MOV A, #0
SUB A, tpData3 ; Y-axis (inverted)
B0MOV UDR0_W, A
INCMS UDP0
MOV A, #0 ; Wheel
B0MOV UDR0_W, A
INCMS UDP0
MOV A, #0 ; AC Pan
B0MOV UDR0_W, A
JMP _mouse_write_ep2_exit
_mouse_write_ep2_alt:
MOV A, #0
B0BTS0 tpData1.0
OR A, #8 ; Button4 (back)
B0BTS0 tpData1.1
OR A, #16 ; Button5 (forward)
B0MOV UDR0_W, A
INCMS UDP0
MOV A, #0 ; X-axis
B0MOV UDR0_W, A
INCMS UDP0
MOV A, #0 ; Y-axis
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, tpData3 ; Wheel
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, tpData2 ; AC Pan
B0MOV UDR0_W, A
_mouse_write_ep2_exit:
MOV A, #5 ; EP2 count is 5
B0MOV UE2R_C, A
; Set EP2 to ACK
B0BSET FUE2M0
RET
_kbd_write_ep1:
B0BTS0 FUE1M0 ; Skip if zero
RET
; FUE1M0 is zero (NAK)
MOV A, #8 ; EP1 begins at offset 8
B0MOV UDP0, A
B0MOV A, modifierState1
B0MOV UDR0_W, A
INCMS UDP0
MOV A, #0 ; reserved byte
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, bootKeys0
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, bootKeys1
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, bootKeys2
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, bootKeys3
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, bootKeys4
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, bootKeys5
B0MOV UDR0_W, A
INCMS UDP0
B0MOV A, extraState0
B0MOV UDR0_W, A
INCMS UDP0
MOV A, #9 ; EP1 count is 9
B0MOV UE1R_C, A
; Set EP1 to ACK
B0BSET FUE1M0
; MOV A, #','
; CALL _uart_tx
RET
_usb_reset:
MOV A, #13
CALL _uart_tx
MOV A, #10
CALL _uart_tx
MOV A, #'R'
CALL _uart_tx
CALL _usb_init
; Wait until reset is de-asserted
_usb_reset_wait:
B0BTS0 FBUS_RST
JMP _usb_reset_wait
JMP _mainloop
_gpio_init:
; Enable all pull-ups
MOV A, #0xff
B0MOV P0UR, A
B0MOV P1UR, A
B0MOV P2UR, A
B0MOV P4UR, A
B0MOV P5UR, A
; Enable P1 wakeup
B0MOV P1W, A
; Switch all to input
MOV A, #0x00
B0MOV P0M, A
B0MOV P1M, A
B0MOV P2M, A
B0MOV P4M, A
B0MOV P5M, A
; Set port output data to 0
B0MOV P0, A
B0MOV P1, A
B0MOV P2, A
B0MOV P4, A
B0MOV P5, A
; Reset kbd scan state
B0MOV kbdRow, A
; Re-light LED
B0BCLR P5.3 ; Set to low level to light up
B0BSET P5M.3 ; Set to output
; Check if debug UART is enabled
B0BTS0 enableUart
B0BSET 0xa9.4 ; Switch UTX back to UART
;; Set UTX/URX to open-drain
;MOV A, #0x0c
;B0MOV P1OC, A
RET
_usb_init:
MOV A, #0
B0MOV usbState, A
B0MOV usbState2, A
B0MOV USTATUS, A
MOV A, #32
B0MOV EP2FIFO_ADDR, A
MOV A, #0x80
B0MOV UDA, A ; Set address to 0 and enable
B0MOV UE1R, A ; Enable EP1, set to NAK
B0MOV UE2R, A ; Enable EP2, set to NAK
B0BSET FDP_PU_EN ; Enable D+ pull-up
B0BSET FSOF_INT_EN ; Enable SOF interrupt request
RET
_kbd_update_boot_keys:
; Update boot interface key bytes
B0BTS0 keyErrorRollOver ; Jump if rollover error
JMP _kbd_update_boot_keys_rollover
MOV A, #0
B0MOV bootKeys0, A
B0MOV bootKeys1, A
B0MOV bootKeys2, A
B0MOV bootKeys3, A
B0MOV bootKeys4, A
B0MOV bootKeys5, A
B0MOV bootKeyVal, A
B0MOV Y, A
MOV A, #bootKeys0$L
B0MOV bootKeyIdx, A
MOV A, #keyState0$L
B0MOV keyStateIdx, A
_kbd_update_boot_keys_loop:
B0MOV A, keyStateIdx
MOV Z, A
B0MOV A, @YZ
B0BTS0 FZ ; Jump if zero
JMP _kbd_update_boot_keys_nextbyte
B0MOV keyStateVal, A
B0MOV R, #0x8
@@:
RRCM keyStateVal
B0BTS1 FC ; Jump if not carry set
JMP _kbd_update_boot_keys_nextbit
; Write the boot key value
B0MOV A, bootKeyIdx
MOV Z, A
; Check if we still have space
SUB A, #1
SUB A, #bootKeys5$L
B0BTS0 FC ; Jump if carry set
JMP _kbd_update_boot_keys_rollover
; Write the value
B0MOV A, bootKeyVal
B0MOV @YZ, A
; Update pointer
INCMS bootKeyIdx
_kbd_update_boot_keys_nextbit:
INCMS bootKeyVal
DECMS R
JMP @B
JMP @F
_kbd_update_boot_keys_nextbyte:
MOV A, #8
ADD bootKeyVal, A
@@:
INCMS keyStateIdx
; Check if we the idx has reached the bitfield end
MOV A, keyStateIdx
SUB A, #1
SUB A, #keyState17
B0BTS1 FC ; Jump if not carry set
JMP _kbd_update_boot_keys_loop
; normal exit
RET
_kbd_update_boot_keys_rollover:
MOV A, #1
B0MOV bootKeys0, A
B0MOV bootKeys1, A
B0MOV bootKeys2, A
B0MOV bootKeys3, A
B0MOV bootKeys4, A
B0MOV bootKeys5, A
RET
_kbd_sense:
B0MOV A, kbdRow
AND A, #0x7
.ALIGN 16
B0ADD PCL, A
JMP _kbd_sense_row0
JMP _kbd_sense_row1
JMP _kbd_sense_row2
JMP _kbd_sense_row3
JMP _kbd_sense_row4
JMP _kbd_sense_row5
JMP _kbd_sense_row6
JMP _kbd_sense_row7
_key_get_fnrow:
B0BTS0 keyFN
JMP @F
B0BCLR FC
B0BTS0 stateFnLock
B0BSET FC
RET
@@:
B0BSET FC
B0BTS0 stateFnLock
B0BCLR FC
RET
_key_esc_clear:
B0BCLR keyESC
B0BCLR stateHiddenESC
RET
_key_esc_set:
B0BTS0 keyFN
JMP @F
B0BSET keyESC
RET
@@:
; Make sure we only toggle once until ESC is released
B0BTS0 stateHiddenESC
RET
B0BSET stateHiddenESC
; Toggle stateFnLock
MOV A, #0x02
XOR modifierState2, A
RET
_key_f4_clear:
B0BCLR keyF4
B0BCLR keyMICTOGGLE
RET
_key_f4_set:
CALL _key_get_fnrow
B0BTS0 FC
JMP @F
B0BSET keyF4
RET
@@:
B0BSET keyMICTOGGLE
RET
_key_f5_clear:
B0BCLR keyF5
B0BCLR keyBRIGHTNESSDOWN
RET
_key_f5_set:
CALL _key_get_fnrow
B0BTS0 FC
JMP @F
B0BSET keyF5
RET
@@:
B0BSET keyBRIGHTNESSDOWN
RET
_key_f6_clear:
B0BCLR keyF6
B0BCLR keyBRIGHTNESSUP
RET
_key_f6_set:
CALL _key_get_fnrow
B0BTS0 FC
JMP @F
B0BSET keyF6
RET
@@:
B0BSET keyBRIGHTNESSUP
RET
_kbd_sense_row0:
; DB keyESC, keyF4, keyNONUSBACKSLASH, keyNONE, keyG, keyH, keyF6, keyINTERNATIONAL4
B0BTS0 S0
CALL _key_esc_clear
B0BTS1 S0
CALL _key_esc_set
B0BTS0 S1
CALL _key_f4_clear
B0BTS1 S1
CALL _key_f4_set
B0BTS0 S2
B0BCLR keyNONUSBACKSLASH
B0BTS1 S2
B0BSET keyNONUSBACKSLASH
B0BTS0 S3
B0BCLR keyNONE
B0BTS1 S3
B0BSET keyNONE
B0BTS0 S4
B0BCLR keyG
B0BTS1 S4
B0BSET keyG
B0BTS0 S5
B0BCLR keyH
B0BTS1 S5
B0BSET keyH
B0BTS0 S6
CALL _key_f6_clear
B0BTS1 S6
CALL _key_f6_set
B0BTS0 S7
B0BCLR keyINTERNATIONAL4
B0BTS1 S7
B0BSET keyINTERNATIONAL4
; DB keyAPOSTROPHE, keyNONE, keyF5, keyNONE, keyLALT, keyNONE, keyUP, keyNONE
B0BTS0 S8
B0BCLR keyAPOSTROPHE
B0BTS1 S8
B0BSET keyAPOSTROPHE
B0BTS0 S9
B0BCLR keyNONE
B0BTS1 S9
B0BSET keyNONE
B0BTS0 S10
CALL _key_f5_clear
B0BTS1 S10
CALL _key_f5_set
B0BTS0 S11
B0BCLR keyNONE
B0BTS1 S11
B0BSET keyNONE
B0BTS0 S12
B0BCLR keyLALT
B0BTS1 S12
B0BSET keyLALT
B0BTS0 S13
B0BCLR keyNONE
B0BTS1 S13
B0BSET keyNONE
B0BTS0 S14
B0BCLR keyUP
B0BTS1 S14
B0BSET keyUP
B0BTS0 S15
B0BCLR keyNONE
B0BTS1 S15
B0BSET keyNONE
RET
_key_f3_clear:
B0BCLR keyF3
B0BCLR keyVOLUMEUP
RET
_key_f3_set:
CALL _key_get_fnrow
B0BTS0 FC
JMP @F
B0BSET keyF3
RET
@@:
B0BSET keyVOLUMEUP
RET
_kbd_sense_row1:
; DB keyTAB, keyF3, keyCAPSLOCK, keyNONE, keyT, keyY, keyRIGHTBRACKET, keyF7
B0BTS0 S0