Repository navigation
Expand file tree
/
Copy pathapp.s
More file actions
4789 lines (4615 loc) · 120 KB
/
Copy pathapp.s
File metadata and controls
4789 lines (4615 loc) · 120 KB
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
AREA DATA, DATA, READWRITE
EXPORT sys_time
EXPORT ACTIVE_GAME
EXPORT JOYSTICK_X_VALUE
EXPORT JOYSTICK_Y_VALUE
EXPORT btn1_last_handled_time
EXPORT btn2_last_handled_time
EXPORT btn3_last_handled_time
EXPORT btn4_last_handled_time
EXPORT btn5_last_handled_time
sys_time DCD 0 ; 32-bit variable for system time (ms)
ACTIVE_GAME DCB 0 ; 8-bit variable for active game (0 = Main Menu, 1 = Game 1, etc.)
LAST_DRAW_TIME DCW 0
INPUT_BUFFER DCB 0
;####################################################INTERRUPT VARAIBLES#######################################################
btn1_last_handled_time DCD 0 ; 32-bit variable for last handled time (ms)
btn2_last_handled_time DCD 0 ; 32-bit variable for last handled time (ms)
btn3_last_handled_time DCD 0 ; 32-bit variable for last handled time (ms)
btn4_last_handled_time DCD 0 ; 32-bit variable for last handled time (ms)
btn5_last_handled_time DCD 0 ; 32-bit variable for last handled time (ms)
;####################################################END INTERRUPT VARAIBLES#######################################################
;####################################################Menu VARAIBLES#######################################################
HOVERED_GAME DCD 0 ; Variable to store the currently hovered game
HOVERED_GAME_X DCD 0 ; X coordinate of the hovered game border
HOVERED_GAME_Y DCD 0 ; Y coordinate of the hovered game border
;###################################################END Menu VARAIBLES#######################################################
;####################################################JOYSTICK VARAIBLES#######################################################
ACTIVE_COORDINATE DCB 0
JOYSTICK_X_VALUE DCB 0 ; Raw ADC value for X-axis
JOYSTICK_Y_VALUE DCB 0 ; Raw ADC value for Y-axis
JOYSTICK_SW_STATE DCB 0 ; 0 = released, 1 = pressed
JOYSTICK_SW_LAST_HANDLED_TIME DCD 0 ; For debouncing joystick switch
JOYSTICK_NEUTRAL_LOW DCW 1800 ; Lower threshold for neutral zone (approx 4095/2 - delta)
JOYSTICK_NEUTRAL_HIGH DCW 2200 ; Upper threshold for neutral zone (approx 4095/2 + delta)
;####################################################END JOYSTICK VARAIBLES####################################################### ALIGN
;--===============================================================--
;|--| STM32F103C8T6 |--| ARM Cortex-M3 |--| ARM Assembly |--|
;|--| =================Important Definitions:================== |--|
;|--| ============ Delay in ms, use R5 as counter ============= |--|
;|--| ================== Active Game => VAR =================== |--|
;|--| ===================== 0 == Main Menu ==================== |--|
;|--| ===================== 1 == Game 1... ==================== |--|
;|--| ===================== Game Over ========================= |--|
;--===============================================================--
INCLUDE hal.s
IMPORT gamelogo
; Characters import
IMPORT char_48 ; 0
IMPORT char_49 ; 1
IMPORT char_50 ; 2
IMPORT char_51 ; 3
IMPORT char_52 ; 4
IMPORT char_53 ; 5
IMPORT char_54 ; 6
IMPORT char_55 ; 7
IMPORT char_56 ; 8
IMPORT char_57 ; 9
; Alphabet (A-Z)
IMPORT char_65 ; A
IMPORT char_66 ; B
IMPORT char_67 ; C
IMPORT char_68 ; D
IMPORT char_69 ; E
IMPORT char_70 ; F
IMPORT char_71 ; G
IMPORT char_72 ; H
IMPORT char_73 ; I
IMPORT char_74 ; J
IMPORT char_75 ; K
IMPORT char_76 ; L
IMPORT char_77 ; M
IMPORT char_78 ; N
IMPORT char_79 ; O
IMPORT char_80 ; P
IMPORT char_81 ; Q
IMPORT char_82 ; R
IMPORT char_83 ; S
IMPORT char_84 ; T
IMPORT char_85 ; U
IMPORT char_86 ; V
IMPORT char_87 ; W
IMPORT char_88 ; X
IMPORT char_89 ; Y
IMPORT char_90 ; Z
EXPORT __main
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT ADC1_2_IRQHandler
EXPORT SysTick_Handler
;==============================PONG IMPORTS=================================
IMPORT PONG_LOGO
IMPORT PONG
IMPORT PONG_ball_pos
IMPORT PONG_lbat
IMPORT PONG_score1
IMPORT PONG_score2
IMPORT PONG_bg_color
IMPORT PONG_fg_color
IMPORT PONG_txt_color
IMPORT PONG_state
IMPORT PONG_RESET
IMPORT PONG_LOOP
IMPORT PONG_lbat_x
IMPORT PONG_rbat_x
IMPORT PONG_ball_hdim
IMPORT PONG_pad_hheight
IMPORT PONG_pad_hwidth
IMPORT PONG_GAME_MODE
IMPORT PONG_BAT_DOWN
IMPORT PONG_BAT_UP
IMPORT PONG_rbat
;===============================END PONG IMPORTS=================================
;===============================Maze Imports=================================
IMPORT MAZEGEN_WALL
IMPORT MAZEGEN_PATH
IMPORT MAZE_HEIGHT
IMPORT MAZE_WIDTH
IMPORT MAZE_BLOCK_DIM
IMPORT MAZE_layout
IMPORT MAZE_pos
IMPORT MAZE_prng_state
IMPORT MAZE_TIMER_MINUTE
IMPORT MAZE_TIMER_SECOND
IMPORT MAZE_SECOND_TIMER
IMPORT MAZE_GAME_STATE
IMPORT MAZE_RESET
IMPORT MAZE_GENERATE
IMPORT MAZE_SOLVER
IMPORT MAZE_CHECK_WIN_CONDITION
IMPORT MAZE_LOGO
IMPORT MAZE_WALL
IMPORT MAZE_PATH
IMPORT MAZEGEN_PATH_SOL
IMPORT MAZE_KNIGHT
IMPORT MAZE_MOVE_DOWN
IMPORT MAZE_MOVE_LEFT
IMPORT MAZE_MOVE_RIGHT
IMPORT MAZE_MOVE_UP
;===============================END Maze Imports=================================
;===============================Start Snake Imports==============================
IMPORT SNAKE_prng_state
IMPORT SNAKE_HEAD
IMPORT SNAKE_LENGTH
IMPORT SNAKE_FOOD_POS
IMPORT SNAKE_SCORE
IMPORT SNAKE_GAME_OVER
IMPORT SNAKE_GO_DOWN
IMPORT SNAKE_GO_UP
IMPORT SNAKE_GO_LEFT
IMPORT SNAKE_GO_RIGHT
IMPORT SNAKE_LOOP
IMPORT SNAKE_RESET
IMPORT SNAKE_LOGO
;===============================END Snake Imports================================
;===============================Start XO Imports================================
IMPORT XO_LOGO
IMPORT GameBoard
IMPORT GAME_STATUS
IMPORT ACTIVE_CELL
IMPORT BOARD_DIM
IMPORT XO_O_COLOR
IMPORT XO_X_COLOR
IMPORT XO_HOVER_COLOR
IMPORT XO_WALL_COLOR
IMPORT XO_BCK_COLOR
IMPORT XO_INIT_GAME
IMPORT CHECK_DRAW_X
IMPORT CHECK_DRAW_O
IMPORT CHECK_WINNING
IMPORT CurrentPlayer
;===============================END XO Imports================================
;===============================Start AIM Imports================================
IMPORT AIM_VEL
IMPORT AIM_PRNG_STATE
IMPORT AIM_SCORE
IMPORT AIM_POS
IMPORT AIM_OBJ1_POS
IMPORT AIM_OBJ2_POS
IMPORT AIM_OBJ3_POS
IMPORT TARGET_R
IMPORT AIM_BCK
IMPORT AIM_CURSOR_COLOR
IMPORT AIM_OBJ_COLOR
IMPORT AIM_RESET
IMPORT AIM_SHOOT
IMPORT AIM_LOOP
IMPORT AIM_GAME_STATE
IMPORT AIM_TIMER
IMPORT AIM_SECOND_TIMER
IMPORT AIM_SCORE_TIMER_COLOR
IMPORT AIM_LOGO
;===============================END AIM Imports================================
;===============================Start DINO Imports================================
IMPORT DINO_LOOP
IMPORT DINO_RESET
IMPORT DINO_CHARACTER
IMPORT DINOSTATE
IMPORT DINOSTATE_INPUT
IMPORT DINO_HEAD_ERASED
IMPORT DINO_X
IMPORT DINO_Y
IMPORT DINO_W
IMPORT DINO_H
IMPORT LAST_SPAWN_TIME
IMPORT DINO_VELOCITY
IMPORT OB1_TYPE
IMPORT OB1_ACTIVE
IMPORT OB1_X
IMPORT OB1_Y
IMPORT OB1_W
IMPORT OB1_H
IMPORT OB2_TYPE
IMPORT OB2_ACTIVE
IMPORT OB2_X
IMPORT OB2_Y
IMPORT OB2_W
IMPORT OB2_H
IMPORT OB3_TYPE
IMPORT OB3_ACTIVE
IMPORT OB3_X
IMPORT OB3_Y
IMPORT OB3_W
IMPORT OB3_H
IMPORT DINO_LOGO
;===============================END DINO Imports================================
;===============================Start SnakeLadder Imports================================
IMPORT PLAYER_ONE_COLOR
IMPORT PLAYER_TWO_COLOR
IMPORT SNAKELDR_CELL_COLOR
IMPORT SNAKELDR_WALL_COLOR
IMPORT LADDER_ONE_POS
IMPORT LADDER_TWO_POS
IMPORT LADDER_THREE_POS
IMPORT SNAKE_ONE_POS
IMPORT SNAKE_TWO_POS
IMPORT SNAKE_THREE_POS
IMPORT SNAKELDR_CurrentPlayer
IMPORT PLAYER_ONE_POS
IMPORT PLAYER_TWO_POS
IMPORT SNAKELDR_GAME_STATUS
IMPORT PLAYER_MOVES
IMPORT SNAKE_LADDER_INIT_GAME
IMPORT INCREMENT_POSITION
IMPORT CHECK_LADDER_START
IMPORT CHECK_SNAKE_START
IMPORT SNAKELDR_LADDER_COLOR
IMPORT SNAKELDR_SNAKE_COLOR
IMPORT GET_PLAYER_MOVES
IMPORT INCREMENT_POSITION
IMPORT CHECK_LADDER_START
IMPORT CHECK_SNAKE_START
IMPORT TOGGLE_PLAYER
IMPORT SnakeLadder_LOGO
;===============================END SnakeLadder Imports================================
;IMPORT MEMORY_LOGO
IMPORT MODULO
AREA MYCODE, CODE, READONLY
ENTRY
__main FUNCTION
BL _init
BL TFT_INIT ; Call TFT_INIT to initialize the TFT LCD
LDR R0, =0x0 ; Load the color value
BL FILL_SCREEN ; Call FILL_SCREEN to fill the screen with the color
BL RESET_MENU
BL PONG_RESET
BL SNAKE_RESET
BL DRAW_MENU
LDR R0, =ACTIVE_GAME ; Load the address of ACTIVE_GAME
MOV R11, #0
STRB R11, [R0]
MAIN_LOOP
LDR R0, =ACTIVE_GAME ; Load the address of ACTIVE_GAME
LDRB R11, [R0]
CMP R11, #0 ; Check if R11 is 0 (Main Menu)
BEQ END_MAINLOOP
CMP R11, #1 ; Check if R11 is 1
BEQ DRAW_GAME1_LBL ; If R11 is 1, branch to DRAW_GAME1
CMP R11, #3
BEQ DRAW_GAME3_LBL
CMP R11, #5
BEQ DRAW_GAME5_LBL ; Aim Game
CMP R11, #6
BEQ DRAW_GAME6_LBL
B END_MAINLOOP
DRAW_GAME1_LBL
BL DRAW_GAME1
B END_MAINLOOP
DRAW_GAME3_LBL
BL DRAW_GAME3
B END_MAINLOOP
DRAW_GAME5_LBL
BL DRAW_GAME5
B END_MAINLOOP
DRAW_GAME6_LBL
BL DRAW_GAME6
B END_MAINLOOP
END_MAINLOOP
B MAIN_LOOP
_init
push {r0-r12, lr} ; Save registers
;#################################Select system Clock Source#######################################
; Enable HSI clock
ldr r0, =RCC_BASE
ldr r1 , =RCC_CR_OFFSET
add r0, r0, r1 ; Read RCC_CR
ldr R1, [R0]
orr r1, r1, #0x01 ; Set HSION bit to enable HSI clock
str r1, [r0] ; Write back to RCC_CR
WAIT_HSI ldr r1, [r0] ; Read RCC_CR again
AND r1, #0x02 ; Check if HSIRDY bit is set
CMP r1, #0x02 ; Compare with 0x02
BNE WAIT_HSI ; Wait until HSI is ready
; Select HSI as PLL source Set PLL multiplication factor to 8
ldr r0, =RCC_BASE
ldr r1, =RCC_CFGR_OFFSET
add r0, r0 , r1
ldr r1, [r0] ; Read RCC_CFGR
and r1, r1, #0xFFFEFFFF ; Select HSI as PLL source (clear PLLSRC bit)
orr r1, r1, #0x380000 ; Set PLLMUL[3:0] to 0x0F (16x)
str r1, [r0] ; Write back to RCC_CFGR
; Enable PLL
ldr r0, =RCC_BASE
ldr r1 , =RCC_CR_OFFSET
add r0, r0, r1 ; Read RCC_CR
ldr r1, [r0] ; Read RCC_CR again
orr r1, r1, #0x1000000 ; ; Set PLLON bit to enable PLL
str r1, [r0] ; Write back to RCC_CR
WAIT_PLL ldr r1, [r0] ; Read RCC_CR again
AND r1, #0x2000000 ; Check if PLLRDY bit is set
CMP r1, #0x2000000
BNE WAIT_PLL ; Wait until PLL is ready
ldr r0, =RCC_BASE
ldr r1, =RCC_CFGR_OFFSET
add r0, r0 , r1
ldr r1, [r0] ; Read RCC_CFGR
orr r1, r1, #0x02 ; Set SW[1:0] to select PLL as system clock
str r1, [r0] ; Write back to RCC_CFGR
WAIT_SWS ldr r1, [r0] ; Read RCC_CFGR again
AND r1, #0x08 ; Check if SWS[1:0] is set to 0x02 (PLL)
CMP r1, #0x08 ; Compare with 0x0C
BNE WAIT_SWS ; Wait until PLL is selected as system clock
;##################################End Select System Clock Source#######################################
;##################################Start Systick Enable#######################################
ldr r0, =SysTick_BASE ; Load SysTick base address
ldr r1, =SysTick_CTRL_OFFSET ; Load SysTick_CTRL offset
add r0, r0, r1 ; Calculate SysTick_CTRL address
ldr r1, [r0] ; Read SysTick_CTRL
orr r1, r1, #0x07 ; Enable SysTick with HSI/8 clock and enable interrupt
str r1, [r0] ; Write back to SysTick_CTRL
ldr r0, =SysTick_BASE ; Load SysTick base address
ldr r1, =SysTick_RELOAD_VALUE_OFFSET ; Load SysTick_RELOAD_VALUE offset
add r0, r0, r1 ; Calculate SysTick_RELOAD_VALUE address
ldr r1, =0x0F9FF ; Set reload value to 63999 (tick everey 1 ms)
str r1, [r0] ; Write to SysTick_RELOAD_VALUE
ldr r0, =SysTick_BASE ; Load SysTick base address
ldr r1, =SysTick_CURRENT_VALUE_OFFSET ; Load SysTick_CURRENT_VALUE offset
add r0, r0, r1 ; Calculate SysTick_CURRENT_VALUE address
ldr r1, =0x00 ; Set current value to 0
str r1, [r0] ; Write to SysTick_CURRENT_VALUE
;##################################End Systick Enable#######################################
;#################################Enable ADC1, GPIOA, GPIOB & AFIO Clocks#######################################
ldr r0, =RCC_BASE
ldr r1, =RCC_APB2ENR_OFFSET
add r0, r0, r1
ldr r1, [r0] ; Read RCC_APB2ENR
LDR R2, =0x20D
orr r1, r1, R2 ; Enable ADC1, GPIOA, GPIOB & AFIO clock
str r1, [r0] ; Write back to RCC_APB2ENR
;##################################End Enable GPIOA, GPIOB & AFIO Clocks#######################################
;#################################Configure GPIOA and GPIOB#######################################
; Configure GPIOA (PA0 PA1 PA2 PA3 PA5) as input, for
ldr r0, =GPIOA_BASE
ldr r1, =GPIOx_CRL_OFFSET
add r0, r0, r1
LDR r1, =0x888888 ; Set mode to input mode / pull-up - pull-down for PA0 - PA3, PA5
str r1, [r0] ; Write to GPIOA_CRL
; Set GPIOB B0, B1 to be floating input
ldr r0, =GPIOB_BASE
ldr r1, =GPIOx_CRL_OFFSET
add r0, r0, r1
ldr r1, [r0]
AND r1, r1, #0x00
str r1, [r0]
; Define (PA8 - PA12) as output for control port
ldr r0, =GPIOA_BASE
ldr r1, =GPIOx_CRH_OFFSET
add r0, r0, r1
LDR r1, =0x00033333 ; Set mode to output 50MHz, push-pull for PA8 - PA12
str r1, [r0] ; Write to GPIOA_CRH
; Configure the GPIOA input ports with pull-up resistors
ldr r0, =GPIOA_BASE
ldr r1, =GPIOx_BSRR_OFFSET
add r0, r0, r1
MOV r1, #0x2F ; Pull up the pins PA0 - PA3, PA5
str r1, [r0] ; Write to GPIOA_BSRR
; Configure GPIOB high as output for data port
ldr r0, =GPIOB_BASE
ldr r1, =GPIOx_CRH_OFFSET
add r0, r0, r1
MOV r1, #0x33333333 ; Set mode to output 50MHZ, push-pull for PB8-PB15
str r1, [r0] ; Write to GPIOB_CRH
;##################################End Configure GPIOA and GPIOB#######################################
;##################################Start ADC1 config############################################
; SMPR2: Configure sample time for channel 0 (Joystick X on PB0) and 1 (Joystick Y on PB1)
; Let's use 71.5 cycles: 0b101
ldr r0, =ADC1_BASE
ldr r1, =ADC1_SMPR2_OFFSET
add r1, r0, r1 ; Address of ADC_SMPR2
ldr r2, [r1]
ldr r3, =0x36000000
orr r2, r3
str r2, [r1]
; SQR1 (1 conversion in sequence)
ldr r1, =ADC1_SQR1_OFFSET
add r1, r0, r1
ldr r2, [r1]
bic r2, r2, #0x00F00000 ; Clear L bits (bits 23-20 for number of conversions)
; We'll do one channel at a time.
;orr r2, r2, #0x00100000
str r2, [r1]
ldr r0, =ADC1_BASE
ldr r1, =ADC1_SQR3_OFFSET
add r1, r0, r1 ; r1 → &ADC1->SQR3
ldr r2, [r1]
bic r2, r2, #0x1F ; clear SQ1 (bits 4:0)
;ORR R2, R2, #9
;LSL R2, R2, #8
orr r2, r2, #8 ; SQ1 = 8 (channel 8 = PB0)
str r2, [r1]
; Turn ADC On (ADON=1 in CR2) - first time to wake up, second time after config
ldr r0, =ADC1_BASE
ldr r1, =ADC1_CR2_OFFSET
add r1, r0, r1 ; Address of ADC_CR2
ldr r2, [r1]
orr r2, r2, #ADC_CR2_ADON
str r2, [r1]
; Wait for ADC to stabilize (a short delay)
mov r5, #10 ; Small delay
bl DELAY_MS ; Use your existing delay function
; ADC Calibration
ldr r0, =ADC1_BASE
ldr r1, =ADC1_CR2_OFFSET
add r1, r0, r1
ldr r2, [r1]
orr r2, r2, #ADC_CR2_CAL ; Start calibration
str r2, [r1]
ADC_CAL_WAIT
ldr r2, [r1]
tst r2, #ADC_CR2_CAL ; Check if CAL bit is still set
bne ADC_CAL_WAIT ; Loop if still calibrating
ldr r0, =ADC1_BASE
ldr r1, =ADC1_CR2_OFFSET
add r1, r0, r1 ; Address of ADC_CR2
ldr r2, [r1]
orr r2, r2, #ADC_CR2_ADON
str r2, [r1]
; ADC Configuration:
; CR1: SCAN mode off, interrupts off for now
ldr r0, =ADC1_BASE
ldr r1, =ADC1_CR1_OFFSET
add r1, r0, r1 ; Address of ADC_CR1
mov r2, #(0 << 8) ; Default: SCAN=0, AWDSGL=0etc.
;orr r2, r2, #(1 << 5)
str r2, [r1]
; CR2: ADON=1 (already on), CONT=1 (continuous conversion), ALIGN=0 (right)
ldr r0, =ADC1_BASE
ldr r1, =ADC1_CR2_OFFSET
add r1, r0, r1 ; Address of ADC_CR2
MOV R2, #3 ; CONT AND ADON
str r2, [r1]
;##################################END ADC1 config############################################
;#################################Configure NVIC ########################################
ldr r0, =NVIC_BASE ; Load NVIC base address
ldr r1, =NVIC_AIRCR_OFFSET ; Load NVIC_AIRCR offset
add r0, r0, r1 ; Calculate NVIC_AIRCR address
ldr r1, [r0] ; Read NVIC_AIRCR
orr r1, r1, #0x0200 ; Set the priority group to 2 bits for pre-emption and 2 bits for sub-priority
str r1, [r0] ; Write back to NVIC_AIRCR
;#################################End Configure NVIC ########################################
;#################################Enable Interrupts for Arcade Buttons#######################################
; Map EXTI0 to EXTI3 to GPIOA
ldr r0, =AFIO_BASE
ldr r1, =AFIO_EXTICR1_OFFSET
add r0, r0, r1
ldr r1, [r0] ; Set EXTI0 to EXTI3 to GPIOA
mov r2, #0xFFFF
bic r1, r1, r2 ; Clear Lower 16 bits
str r1, [r0] ; Write to AFIO_EXTICR1
ldr r0, =AFIO_BASE
ldr r1, =AFIO_EXTICR2_OFFSET
add r0, r0, r1
ldr r1, [r0] ; Set EXTI0 to EXTI3 to GPIOA
mov r2, #0xFFFF
bic r1, r1, r2 ; Clear Lower 16 bits
str r1, [r0] ; Write to AFIO_EXTICR2
; Unmask EXTI0 to EXTI3 lines' interrupts
ldr r0, =EXTI_BASE
ldr r1, =EXTI_IMR_OFFSET
add r0, r0, r1
ldr r1, [r0] ; Read EXTI_IMR
orr r1, r1, #0x2F ; Unmask EXTI0 to EXTI3
str r1, [r0] ; Write to EXTI_IMR
; Enable interrupt on falling edge for EXTI0 to EXTI3 lines, since arcade buttons' pins are pulled-up
ldr r0, =EXTI_BASE
ldr r1, =EXTI_FTSR_OFFSET
add r0, r0, r1
ldr r1, [r0] ; Read EXTI_FTSR
orr r1, r1, #0x2F ; Enable falling edge trigger for EXTI0 to EXTI3
str r1, [r0] ; Write to EXTI_FTSR
; Enable NVIC interrupts for EXTI0 to EXTI3 lines
ldr r0, =NVIC_BASE ; Load NVIC base address
ldr r1, =NVIC_ISER_ONE_OFFSET ; Load NVIC_ISER0 offset
add r0, r0, r1 ; Calculate NVIC_ISER0 address
ldr r1, [r0] ; Read NVIC_ISER0
ldr r2, =0x8003C0 ; 0x8403C0 for ADC INT
orr r1, r1, r2 ; Enable interrupts for EXTI0 to EXTI3, ISER0 bits 6 - 9
str r1, [r0] ; Write back to NVIC_ISER0
; Set the preemption priority and subpriority for EXTI0 to EXTI3 interrupts
ldr r0, =NVIC_BASE ; Load NVIC base address
ldr r1, =NVIC_IPR_TWO_OFFSET ;Load NVIC_IPR2 offset
add r0, r0, r1 ;Calculate NVIC_IPR2 address
ldr r1, [r0] ;Read NVIC_IPR2
mov r2, #0x10000
LSL r2, r2, #16
orr r1, r1, r2 ;Set the priority for EXTI1 & EXTI0 (Premrption to 0, sub priority of EXTI1 is 1 and EXTI0 is 0, lower priority number means higher priority)
str r1, [r0] ;Write back to NVIC_IPR2
ldr r0, =NVIC_BASE ;Load NVIC base address
ldr r1, =NVIC_IPR_THREE_OFFSET ;Load NVIC_IPR2 offset
add r0, r0, r1 ;Calculate NVIC_IPR3 address
ldr r1, [r0] ;Read NVIC_IPR3
MOV r2, #0x3020
orr r1, r1, r2 ;Set the priority for EXTI3 & EXTI2 (Premrption to 0, sub priority of EXTI3 is 3 and EXTI2 is 2)
str r1, [r0] ;Write back to NVIC_IPR3
ldr r0, =NVIC_BASE
ldr r1, =NVIC_IPR_SIX_OFFSET
add r0, r0, r1
ldr r1, [r0]
MOV r2, #0x00
ROR r2, r2, #8
ORR r1, r1, r2
str r1, [r0]
;#################################End Enable Interrupts for Arcade Buttons#######################################
pop {r0-r12, lr}
bx lr
LTORG
ENDFUNC
;###########################################ADC Functions################################################
START_ADC1_CH8_CONVERSION FUNCTION
PUSH {R0-R3,LR}
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SQR3_OFFSET
ADD R0, R0, R1 ; Address of ADC_SQR3
MOV R1, #8 ; R3 = channel number
STR R1, [R0] ; Set first sequence conversion to channel R0
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
MVN R2, #2
AND R1, R1, R2
STR R1, [R0] ; Clear EOC
; 2. Start ADC conversion (Set SWSTART bit in ADC_CR2)
WAIT_CH8_EOC_LOOP
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
TST R1, #2 ; Check EOC
BEQ WAIT_CH8_EOC_LOOP
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
MVN R2, #2
AND R1, R1, R2
STR R1, [R0] ; Clear EOC
LDR R0, =ADC1_BASE
LDR R1, =ADC1_DR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
LSR R1, R1, #2
MOV R2, #10
UDIV R1, R2
CMP R1, #100
BLE JS_SKIP_CAP_X_AT_100
MOV R1, #100
JS_SKIP_CAP_X_AT_100
CMP R1, #45
BGE JS_X_COMPARE_55
SUB R1, R1, #50
B JS_X_UPDATE_VAL
JS_X_COMPARE_55
CMP R1, #55
MOVLE R1, #0
SUBGT R1, R1, #50
JS_X_UPDATE_VAL
RSB R1, R1, #0 ; This was a hardware limitation, so we need to invert the value
LDR R0, =JOYSTICK_X_VALUE
STRB R1, [R0]
POP {R0-R3,LR}
BX LR
ENDFUNC
START_ADC1_CH9_CONVERSION FUNCTION
PUSH {R0-R3,LR}
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SQR3_OFFSET
ADD R0, R0, R1 ; Address of ADC_SQR3
MOV R1, #9 ; R3 = channel number
STR R1, [R0] ; Set first sequence conversion to channel R0
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
MVN R2, #2
AND R1, R1, R2
STR R1, [R0] ; Clear EOC
; 2. Start ADC conversion (Set SWSTART bit in ADC_CR2)
WAIT_CH9_EOC_LOOP
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
TST R1, #2 ; Check EOC
BEQ WAIT_CH9_EOC_LOOP
LDR R0, =ADC1_BASE
LDR R1, =ADC1_SR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
MVN R2, #2
AND R1, R1, R2
STR R1, [R0] ; Clear EOC
LDR R0, =ADC1_BASE
LDR R1, =ADC1_DR_OFFSET
ADD R0, R0, R1
LDR R1, [R0]
LSR R1, R1, #2
MOV R2, #10
UDIV R1, R2
CMP R1, #100
BLE JS_SKIP_CAP_Y_AT_100
MOV R1, #100
JS_SKIP_CAP_Y_AT_100
CMP R1, #45
BGE JS_Y_COMPARE_55
SUB R1, R1, #50
B JS_Y_UPDATE_VAL
JS_Y_COMPARE_55
CMP R1, #55
MOVLE R1, #0
SUBGT R1, R1, #50
JS_Y_UPDATE_VAL
MOV R2, #-1
MUL R1, R1, R2 ; To Make it start at top left
RSB R1, R1, #0 ; This was a hardware limitation, so we need to invert the value
LDR R0, =JOYSTICK_Y_VALUE
STRB R1, [R0]
POP {R0-R3,LR}
BX LR
ENDFUNC
; #######################################################START MISC FUNCTIONS#######################################################
DELAY_MS PROC
PUSH {R0-R3, LR} ; Save registers and link register
LDR R1, =sys_time ; Load address of sys_time
LDR R2, [R1] ; R2 = current sys_time
ADD R3, R2, R5 ; R3 = sys_time + delay_ms (target time)
DELAY_MS_LOOP
LDR R2, [R1] ; R2 = current sys_time
CMP R2, R3 ; Compare current sys_time with target time
BLT DELAY_MS_LOOP ; Branch if less than (not enough time has passed)
POP {R0-R3, LR} ; Restore registers and return
BX LR
ENDP
LTORG
;#######################################################END MISC FUNCTIONS#######################################################
;#######################################################START Drawing Functions#####################################################
;========================================================================
; DRAW_CHAR (ARM Assembly)
; Draws a monochrome 16×16 glyph by expanding a 1-bit bitmap into
; full-color pixels. Call with:
; R0 = start X coordinate
; R1 = start Y coordinate
; R3 = address of glyph data (width, height, then row masks)
; R4 = foreground color (16-bit RGB565)
; R5 = background color (16-bit RGB565)
;========================================================================
DRAW_CHAR FUNCTION
PUSH {R6,R7,R8,R9,R10,R11,LR}
PUSH {R4, R5}
LDR R4, [R3], #4 ; Load width from image address
LDR R5, [R3], #4 ; Load height from image address
MOV R2, #0x2A ; Set Column Address command
BL TFT_COMMAND_WRITE
LSR R2, R0, #8 ; Get high byte of Start X coordinate
BL TFT_DATA_WRITE ; Send high byte of Start X coordinate
AND R2, R0, #0xFF ; Get low byte of Start X coordinate
BL TFT_DATA_WRITE ; Send low byte of Start X coordinate
ADD R6, R4, R0
SUB R6, R6, #1 ; Calculate End X coordinate (Start X + Width - 1)
LSR R2, R6, #8 ; Get high byte of End X coordinate
BL TFT_DATA_WRITE ; Send high byte of End X coordinate
AND R2, R6, #0xFF ; Get low byte of End X coordinate
BL TFT_DATA_WRITE ; Send low byte of End X coordinate
MOV R2, #0x2B ; Set Page Address command
BL TFT_COMMAND_WRITE
LSR R2, R1, #8 ; Get high byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send high byte of Start Y coordinate
AND R2, R1, #0xFF ; Get low byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send low byte of Start Y coordinate
ADD R6, R5, R1
SUB R6, R6, #1 ; Calculate End Y coordinate (Start Y + Height - 1)
LSR R2, R6, #8 ; Get high byte of End Y coordinate
BL TFT_DATA_WRITE ; Send high byte of End Y coordinate
AND R2, R6, #0xFF ; Get low byte of End Y coordinate
BL TFT_DATA_WRITE ; Send low byte of End Y coordinate
POP {R4, R5}
MOV R2, #0x2C ; Memory Write command
BL TFT_COMMAND_WRITE
MOV R6, #8
CHAR_ROW_LOOP
LDR R7, [R3], #4
ROR R7, #16
MOV R8, #32
CHAR_COLUMN_LOOP
LSLS R7, #1
BCS CHAR_DRAW_TXT
MOV R2, R5, LSR #8 ; Extract high byte
BL TFT_DATA_WRITE ; Send high byte of pixel color
AND R2, R5, #0xFF ; Extract low byte
BL TFT_DATA_WRITE ; Send low byte of pixel color
B CHAR_COLUMN_CHECK
CHAR_DRAW_TXT
MOV R2, R4, LSR #8 ; Extract high byte
BL TFT_DATA_WRITE ; Send high byte of pixel color
AND R2, R4, #0xFF ; Extract low byte
BL TFT_DATA_WRITE ; Send low byte of pixel color
CHAR_COLUMN_CHECK
SUB R8, R8, #1
CMP R8, #0
BNE CHAR_COLUMN_LOOP
SUB R6, R6, #1
CMP R6, #0
BNE CHAR_ROW_LOOP
POP {R6,R7,R8,R9,R10,R11,LR}
BX LR
ENDFUNC
;@@@@@@@@@@@@@@@DRAW RECT
; All landscape
; R0 Has Start X
; R1 Has Start Y
; R3 Has Width
; R4 Has Height
; R5 Has Color
DRAW_RECT FUNCTION
PUSH {LR}
MOV R2, #0x2A ; Set Column Address command
BL TFT_COMMAND_WRITE
LSR R2, R0, #8 ; Get high byte of Start X coordinate
BL TFT_DATA_WRITE ; Send high byte of Start X coordinate
AND R2, R0, #0xFF ; Get low byte of Start X coordinate
BL TFT_DATA_WRITE ; Send low byte of Start X coordinate
ADD R0, R0, R3 ; Add Width to X coordinate for end X
SUBS R0, R0, #1 ; Subtract 1 to get the correct end X coordinate
LSR R2, R0, #8 ; Get high byte of End X coordinate
BL TFT_DATA_WRITE ; Send high byte of End X coordinate
AND R2, R0, #0xFF ; Get low byte of End X coordinate
BL TFT_DATA_WRITE ; Send low byte of End X coordinate
MOV R2, #0x2B ; Set Page Address command
BL TFT_COMMAND_WRITE
LSR R2, R1, #8 ; Get high byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send high byte of Start Y coordinate
AND R2, R1, #0xFF ; Get low byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send low byte of Start Y coordinate
ADD R1, R1, R4 ; Add Height to Y coordinate for end Y
SUBS R0, R0, #1 ; Subtract 1 to get the correct end X coordinate
LSR R2, R1, #8 ; Get high byte of End Y coordinate
BL TFT_DATA_WRITE ; Send high byte of End Y coordinate
AND R2, R1, #0xFF ; Get low byte of End Y coordinate
BL TFT_DATA_WRITE ; Send low byte of End Y coordinate
MOV R2, #0x2C ; Memory Write command
BL TFT_COMMAND_WRITE
MUL R3, R3, R4 ; Calculate total pixels (Width * Height)
RECT_DRAW_LOOP
LSR R2, R5, #8 ; Extract high byte of pixel color
BL TFT_DATA_WRITE ; Send high byte of pixel color
AND R2, R5, #0xFF ; Extract low byte of pixel color
BL TFT_DATA_WRITE ; Send low byte of pixel color
SUBS R3, R3, #1 ; Decrement pixel count
BNE RECT_DRAW_LOOP ; Loop until all pixels are drawn
POP {LR}
BX LR
ENDFUNC
;@@@@@@@@@@@@@@@DRAW IMAGE
; All landscape
; R0 Has Start X
; R1 Has Start Y
; R3 Has image address, first 16 bytes of an image contain width and height
DRAW_IMAGE FUNCTION
PUSH {R0-R7, LR}
LDR R4, [R3], #4 ; Load width from image address
LDR R5, [R3], #4 ; Load height from image address
MOV R2, #0x2A ; Set Column Address command
BL TFT_COMMAND_WRITE
LSR R2, R0, #8 ; Get high byte of Start X coordinate
BL TFT_DATA_WRITE ; Send high byte of Start X coordinate
AND R2, R0, #0xFF ; Get low byte of Start X coordinate
BL TFT_DATA_WRITE ; Send low byte of Start X coordinate
ADD R6, R4, R0
SUB R6, R6, #1 ; Calculate End X coordinate (Start X + Width - 1)
LSR R2, R6, #8 ; Get high byte of End X coordinate
BL TFT_DATA_WRITE ; Send high byte of End X coordinate
AND R2, R6, #0xFF ; Get low byte of End X coordinate
BL TFT_DATA_WRITE ; Send low byte of End X coordinate
MOV R2, #0x2B ; Set Page Address command
BL TFT_COMMAND_WRITE
LSR R2, R1, #8 ; Get high byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send high byte of Start Y coordinate
AND R2, R1, #0xFF ; Get low byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send low byte of Start Y coordinate
ADD R6, R5, R1
SUB R6, R6, #1 ; Calculate End Y coordinate (Start Y + Height - 1)
LSR R2, R6, #8 ; Get high byte of End Y coordinate
BL TFT_DATA_WRITE ; Send high byte of End Y coordinate
AND R2, R6, #0xFF ; Get low byte of End Y coordinate
BL TFT_DATA_WRITE ; Send low byte of End Y coordinate
MOV R2, #0x2C ; Memory Write command
BL TFT_COMMAND_WRITE
MUL R6, R4, R5 ; Calculate total pixels (Width * Height)
IMAGE_DRAW_LOOP
LDRH R0, [R3], #2 ; Load pixel color from image address
MOV R2, R0, LSR #8 ; Extract high byte
BL TFT_DATA_WRITE ; Send high byte of pixel color
AND R2, R0, #0xFF ; Extract low byte
BL TFT_DATA_WRITE ; Send low byte of pixel color
SUBS R6, R6, #1 ; Decrement pixel count
BNE IMAGE_DRAW_LOOP ; Loop until all pixels are drawn
POP {R0-R7, LR}
BX LR
ENDFUNC
; Draw run length encoded image
; All landscape
; R0 Has Start X
; R1 Has Start Y
; R3 Has image address
DRAW_RLE_IMAGE FUNCTION
PUSH {R0-R12, LR}
LDRH R7, [R3], #2 ; Read the count of repitions
LDRH R4, [R3], #2 ; Load width from image address
LDRH R5, [R3], #2 ; Load height from image address
MOV R2, #0x2A ; Set Column Address command
BL TFT_COMMAND_WRITE
LSR R2, R0, #8 ; Get high byte of Start X coordinate
BL TFT_DATA_WRITE ; Send high byte of Start X coordinate
AND R2, R0, #0xFF ; Get low byte of Start X coordinate
BL TFT_DATA_WRITE ; Send low byte of Start X coordinate
ADD R6, R4, R0
SUB R6, R6, #1 ; Calculate End X coordinate (Start X + Width - 1)
LSR R2, R6, #8 ; Get high byte of End X coordinate
BL TFT_DATA_WRITE ; Send high byte of End X coordinate
AND R2, R6, #0xFF ; Get low byte of End X coordinate
BL TFT_DATA_WRITE ; Send low byte of End X coordinate
MOV R2, #0x2B ; Set Page Address command
BL TFT_COMMAND_WRITE
LSR R2, R1, #8 ; Get high byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send high byte of Start Y coordinate
AND R2, R1, #0xFF ; Get low byte of Start Y coordinate
BL TFT_DATA_WRITE ; Send low byte of Start Y coordinate
ADD R6, R5, R1
SUB R6, R6, #1 ; Calculate End Y coordinate (Start Y + Height - 1)
LSR R2, R6, #8 ; Get high byte of End Y coordinate
BL TFT_DATA_WRITE ; Send high byte of End Y coordinate
AND R2, R6, #0xFF ; Get low byte of End Y coordinate
BL TFT_DATA_WRITE ; Send low byte of End Y coordinate
MOV R2, #0x2C ; Memory Write command
BL TFT_COMMAND_WRITE
OUTER_RLE_LOOP
LDRH R4, [R3], #2 ; Repition of the color
LDRH R0, [R3], #2
INNER_RLE_LOOP
MOV R2, R0, LSR #8 ; Extract high byte
BL TFT_DATA_WRITE ; Send high byte of pixel color
AND R2, R0, #0xFF ; Extract low byte
BL TFT_DATA_WRITE ; Send low byte of pixel color
SUB R4, R4, #1
CMP R4, #0
BNE INNER_RLE_LOOP
SUB R7, R7, #1
CMP R7, #0
BNE OUTER_RLE_LOOP
POP {R0-R12, LR}
BX LR
ENDFUNC
FILL_SCREEN FUNCTION
PUSH {R1-R12, LR}
; Extract high and low bytes from R0 (COLOR)
MOV R1, R0
AND R1, R0, #0xFF ; Get the low byte (lower 8 bits)
LSR R0, R0, #8 ; Get the high byte (upper 8 bits)
; Set Column Address
MOV R2, #0x2A
BL TFT_COMMAND_WRITE
MOV R2, #0x00
BL TFT_DATA_WRITE
MOV R2, #0x00
BL TFT_DATA_WRITE
MOV R2, #0x01
BL TFT_DATA_WRITE
MOV R2, #0xDF ; Max column (319)
BL TFT_DATA_WRITE
; Set Page Address
MOV R2, #0x2B
BL TFT_COMMAND_WRITE
MOV R2, #0x00
BL TFT_DATA_WRITE
MOV R2, #0x00
BL TFT_DATA_WRITE
MOV R2, #0x01
BL TFT_DATA_WRITE
MOV R2, #0x3F ; Max row (479)
BL TFT_DATA_WRITE
; Memory Write
MOV R2, #0x2C
BL TFT_COMMAND_WRITE
; Fill screen with color
MOV R3, #153600 ; Total pixels (320x240 since 16-bit per pixel)
TFT_Loop
MOV R2, R0 ; Send high byte
BL TFT_DATA_WRITE
MOV R2, R1 ; Send low byte
BL TFT_DATA_WRITE
SUBS R3, R3, #1
BNE TFT_Loop
POP {R1-R12, LR}
BX LR
ENDFUNC
; Function to draw an X shape
; Parameters:
; R0 = Start X coordinate
; R1 = Start Y coordinate
; R4 = Thickness
; R5 = Color
DRAW_X FUNCTION
PUSH {R0-R12, LR}