-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTwinkleTwinkie_iron_badge.asm
2279 lines (1979 loc) · 65.3 KB
/
TwinkleTwinkie_iron_badge.asm
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
; <- everything after a semiconlon is a comment
;#########################################################################################################################################################
;Copyright (c) 2019 Peter Shabino
;
;Permission is hereby granted, free of charge, to any person obtaining a copy of this hardware, software, and associated documentation files
;(the "Product"), to deal in the Product without restriction, including without limitation the rights to use, copy, modify, merge, publish,
;distribute, sublicense, and/or sell copies of the Product, and to permit persons to whom the Product is furnished to do so, subject to the
;following conditions:
;
;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Product.
;
;THE PRODUCT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
;FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
;WITH THE PRODUCT OR THE USE OR OTHER DEALINGS IN THE PRODUCT.
;#########################################################################################################################################################
; 11May2019 V0 PJS New
; 12May2019 V1 PJS started carlieplex code using IRQs
; 23May2019 V2 PJS mode switch, animation timer, and first mode (blue breating) done
; 01Jun2019 V3 PJS added mode saving to flash and new patterns (cap't, mistake #2, rainbow!)
; 18Jun2019 V4 PJS added breathing green, red, yellow, purple, orange, and pink. Also added solid version of all the previous colors plus blue. Updated timers on 2 animations to slow them down.
; 20Jun2019 V5 PJS added 5 more color patterns to the 2 dot rotate and single dot chase
; Pre compiler definition. Just like C these statements are processed before the compile happens.
#define CODE_VER_STRING "Peter Shabino 20Jun2019 code for Twinkle Twinkie Iron Badge V5 www.wire2wire.org!" ;Just in ROM !!!
; Wiring pin list just for easy referance no affect on the code
;****************************************************************************************
; port list [SSOP20]
; Vdd(1)
; Vss(20)
; RA0(19) [ICSPDAT]
; RA1(18) [ICSPCLK]
; RA2(17) D1-6B D9,D15
; RA3(4) [#MCLR] select button in
; RA4(3) D1-6R D7,D13
; RA5(2) D1-6G D8,D14
; RB4(13) D7-12G D2,D17
; RB5(12) D7-12R D1,D16
; RB6(11) D7-12B D3,D18
; RB7(10)
; RC0(16) SCL
; RC1(15) SDA
; RC2(14)
; RC3(7)
; RC4(6)
; RC5(5) D13-18B D6,D12
; RC6(8) D13-18G D5,D11
; RC7(9) D13-18R D4,D10
;****************************************************************************************
; The following links configure the "fuses" on older devices these could only be configured one time at programming. Some newer devices let you update some of them run time.
; These are core options like clock source, speed, read protection, etc.
; Easiest way to configure these in MPLABX is to go Windows->Target memory views->Configureation bits this will pop up a new tab in the lower right window with descriptions
; of each bit and pull downs with the available settings. Once you make all yor choces click the "Generate Source Code to Output" button. When you click the button the
; "Output - config bits source" tab will pop to the front with the following flags configured in it. Copy paste here and your done.
#include "p16f15344.inc"
; CONFIG1
; __config 0xFFFC
__CONFIG _CONFIG1, _FEXTOSC_OFF & _RSTOSC_EXT1X & _CLKOUTEN_OFF & _CSWEN_ON & _FCMEN_ON
; CONFIG2
; __config 0xF7FC
__CONFIG _CONFIG2, _MCLRE_OFF & _PWRTE_ON & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON
; CONFIG3
; __config 0xFF9F
__CONFIG _CONFIG3, _WDTCPS_WDTCPS_31 & _WDTE_OFF & _WDTCWS_WDTCWS_7 & _WDTCCS_SC
; CONFIG4
; __config 0xFFFF
__CONFIG _CONFIG4, _BBSIZE_BB512 & _BBEN_OFF & _SAFEN_OFF & _WRTAPP_OFF & _WRTB_OFF & _WRTC_OFF & _WRTSAF_OFF & _LVP_OFF
; CONFIG5
; __config 0xFFFF
__CONFIG _CONFIG5, _CP_OFF
; max speed, BOR enabled, No boot block or SAF, no read or write protect enabled
; <spaghetti>
; No need to use this just a place to put named constants to make tweeking multi use constants easier
;------------------
; constants
;------------------
TMR1L_value equ 0xC0 ; the TMR1 values set the display scan rate. Too slow (smaller value) and it will filcker. Too high (larger value) and the firmware will endlessly get stuck in the IRQ loop.
TMR1H_value equ 0xFF
max_color_depth equ 0x10 ; the max_color_depth sets how many bits of PWM the code tries to emulate. The more bits the more potential color combinations you can have. The draw back is this increases the number of full IRQ loops per cycle. Too high the display will filcker.
mode_save equ 0x8FE0
org 0FE0h
de 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
de 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
; there are 3 major memory ranges in the PIC. Ram, Flash, and user data
; -- Ram are fixed registers you can read and write from with a single cycle. Some control special functions like IO while otheres are just storage locations
; See page 38+ of http://ww1.microchip.com/downloads/en/DeviceDoc/PIC16-L-F15324-44-data-sheet-40001889B.pdf for the full map.
; Due to the size of the memory map and the lack of bits in the instructions the map is broken up in to banks. You need to make sure the correct bank is selected before read/write our you will get the wrong data
; exception is the core register bank and the common RAM (I call it global below) which is at the same addresses in EVERY bank of ram.
; -- Flash is where the user program is stored / run from. To byte wise reads from it are relatively easy. Writes are difficult and typically have to be done a word line at a time (32 words in this case). User has to manage the erase and program cycles.
; this part only has a single page of flash. So no need to worry about crossing flash page boundarys (special care is needed to switch banks back and forth properly)
; more info on page 32 of http://ww1.microchip.com/downloads/en/DeviceDoc/PIC16-L-F15324-44-data-sheet-40001889B.pdf.
; -- User data are special ranges that have different rules from the bulk flash area. Some parts have byte wise single instruction read / write. Otheres have special boot areas and so on. Not using any of those in this program.
; the eq command allows setting a lable to a specific value. I use this to lay out my memory map here. No need to do this at all but your future self and others looking at the code will thank you later.
;------------------
; vars (0x20 - 0x6f) bank 0
;------------------
led_seq equ 0x20
led1r equ 0x21
led1g equ 0x22
led1b equ 0x23
led2r equ 0x24
led2g equ 0x25
led2b equ 0x26
led3r equ 0x27
led3g equ 0x28
led3b equ 0x29
led4r equ 0x2a
led4g equ 0x2b
led4b equ 0x2c
led5r equ 0x2d
led5g equ 0x2e
led5b equ 0x2f
;led6r equ 0x30 ; skip led not used (if enabled again remap everything...)
;led6g equ 0x31
;led6b equ 0x32
led7r equ 0x30
led7g equ 0x31
led7b equ 0x32
led8r equ 0x33
led8g equ 0x34
led8b equ 0x35
led9r equ 0x36
led9g equ 0x37
led9b equ 0x38
led10r equ 0x39
led10g equ 0x3a
led10b equ 0x3b
;led11r equ 0x3e ; skip led not used (if enabled again remap everything...)
;led11g equ 0x3f
;led11b equ 0x40
;led12r equ 0x41 ; skip led not used (if enabled again remap everything...)
;led12g equ 0x42
;led12b equ 0x43
led13r equ 0x3c
led13g equ 0x3d
led13b equ 0x3e
led14r equ 0x3f
led14g equ 0x40
led14b equ 0x41
led15r equ 0x42
led15g equ 0x43
led15b equ 0x44
led16r equ 0x45
led16g equ 0x46
led16b equ 0x47
led17r equ 0x48
led17g equ 0x49
led17b equ 0x4a
led18r equ 0x4b
led18g equ 0x4c
led18b equ 0x4d
; space for full LED map if needed.
irq_temp equ 0x56
fake_pwm equ 0x57
debounce equ 0x58
mode equ 0x59
stat equ 0x5a
bulk_red equ 0x5b
bulk_green equ 0x5c
bulk_blue equ 0x5d
ann_seq0 equ 0x5e
ann_seq1 equ 0x5f
ann_seq2 equ 0x60
ann_seq3 equ 0x61
LFSR_0 equ 0x62
LFSR_1 equ 0x63
LFSR_2 equ 0x64
LFSR_3 equ 0x65
LFSR_count equ 0x66
temp equ 0x67
;------------------
; vars (0xa0 - 0xef) bank 1
;------------------
;------------------
; vars (0x120 - 0x16f) bank 2
;------------------
;------------------
; vars (0x1a0 - 0xaef) bank 3
;------------------
;------------------
; vars (0x220 - 0xe6f) bank 4
;------------------
;------------------
; vars (0x2a0 - 0x2ef) bank 5
;------------------
;------------------
; vars (0x320 - 0x32f) bank 6
;------------------
;------------------
; vars (0x70 - 0x7F) global regs (lats 16 bytes of every bank point back to these locations)
;------------------
gtemp equ 0x70
; There are 2 special addresses in the memory map 0x0 and 0x4.
; 0x0 is where the micro starts running when it comes out of reset. This is typically just a jump to the start of the initilization code.
; 0x4 is where the micro jumps to ever time a interrup is active.
;put the following at address 0000h
org 0000h
goto START ;vector to initialization sequence
;###########################################################################################################################
; intrupt routine
; if reading thought the code for the first time skip down to the "START" lable and come back here later.
;###########################################################################################################################
;put the following at address 0004h
org 0004h
; following regs are autosaved to shadow register on interrupt.
; W
; STATUS (except TO and PD)
; BSR
; FSR
; PCLATH
; the retfie instruction will restore them from the shadow regs.
; make sure to set to a known value when you start processing the interrupt as they could be set to anyting at this point.
;------------------
movlw d'14'
movwf BSR
;------------------
btfss PIR4, 0 ; is timer 1 IRQ active
goto IRQ_not_tmr1
bcf PIR4, 0 ; clear timer 1 flag
;------------------
movlw d'4'
movwf BSR
;------------------
; reset timer 1 (can be issues updating timer 1 while running. So stop then reset it)
bcf T1CON, 0 ; timer off
movlw TMR1H_value ; update values
movwf TMR1H
movlw TMR1L_value
movwf TMR1L
bsf T1CON, 0 ; timer on
;------------------
clrf BSR ; bank 0
;------------------
; turn off all the LEDs (make them inputs)
movlw 0x34
iorwf TRISA, F
movlw 0x70
iorwf TRISB, F
movlw 0xE0
iorwf TRISC, F
; make sure led_seq is in range if over will jump to who knows where
movlw 0x0F ; 15 skipping unused LEDs
subwf led_seq, W ; C = 0 if W > F, C = 1 W <= F
btfss STATUS, C
goto IRQ_bank_scan
clrf led_seq
incf fake_pwm, F ; update the PWM bank to the next step.
movlw max_color_depth ; count 0 to full on
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
clrf fake_pwm
IRQ_bank_scan
; set the common pin high for the led selected.
movf led_seq, W
movwf irq_temp
bcf STATUS, C
rlf irq_temp, f ; multiply by 2
bcf STATUS, C
rlf irq_temp, W ; multiply by 2
; jump lookup table
brw
bsf LATB, 5 ; D1
bcf TRISB, 5 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATB, 4 ; D2
bcf TRISB, 4 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATB, 6 ; D3
bcf TRISB, 6 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATC, 7 ; D4
bcf TRISC, 7 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATC, 6 ; D5
bcf TRISC, 6 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
; bsf LATC, 5 ; D6 skip not used
; bcf TRISC, 5 ; make it a output
; goto IRQ_set_common_done
; nop ; required for spacing on the jumps
bsf LATA, 4 ; D7
bcf TRISA, 4 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATA, 5 ; D8
bcf TRISA, 5 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATA, 2 ; D9
bcf TRISA, 2 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATC, 7 ; D10
bcf TRISC, 7 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
; bsf LATC, 6 ; D11 skip not used
; bcf TRISC, 6 ; make it a output
; goto IRQ_set_common_done
; nop ; required for spacing on the jumps
; bsf LATC, 5 ; D12 skip not used
; bcf TRISC, 5 ; make it a output
; goto IRQ_set_common_done
; nop ; required for spacing on the jumps
bsf LATA, 4 ; D13
bcf TRISA, 4 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATA, 5 ; D14
bcf TRISA, 5 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATA, 2 ; D15
bcf TRISA, 2 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATB, 5 ; D16
bcf TRISB, 5 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATB, 4 ; D17
bcf TRISB, 4 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
bsf LATB, 6 ; D18
bcf TRISB, 6 ; make it a output
goto IRQ_set_common_done
nop ; required for spacing on the jumps
IRQ_set_common_done
clrf FSR0H
movlw led1r
movwf FSR0L
movf led_seq, W
addwf FSR0L, F ; set FSR0 to 3x led_seq
addwf FSR0L, F
addwf FSR0L, F
; set the RGB lines low for which you want to turn on for this led
; bank 1 (led 1 thru 6).
;movlw 0x06
movlw 0x05 ; skip unused LEDS
subwf led_seq, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank1_chk
; red
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank0_red
bcf LATA, 4
bcf TRISA, 4
IRQ_bank0_red
; green
incf FSR0L, F
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank0_green
bcf LATA, 5
bcf TRISA, 5
IRQ_bank0_green
; blue
incf FSR0L, F
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_banks_done
bcf LATA, 2
bcf TRISA, 2
goto IRQ_banks_done
IRQ_bank1_chk
; bank 2 (led 7 thru 12).
;movlw 0x0C ; 12
movlw 0x09 ; 9 skip unused LEDS
subwf led_seq, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank2_chk
; red
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank1_red
bcf LATB, 5
bcf TRISB, 5
IRQ_bank1_red
; green
incf FSR0L, F
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank1_green
bcf LATB, 4
bcf TRISB, 4
IRQ_bank1_green
; blue
incf FSR0L, F
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_banks_done
bcf LATB, 6
bcf TRISB, 6
goto IRQ_banks_done
IRQ_bank2_chk
; bank 3 (led 13 thru 18).
; red
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank2_red
bcf LATC, 7
bcf TRISC, 7
IRQ_bank2_red
; green
incf FSR0L, F
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_bank2_green
bcf LATC, 6
bcf TRISC, 6
IRQ_bank2_green
; blue
incf FSR0L, F
movf INDF0, W ; check if led should be on for this fake PWM cycle
subwf fake_pwm, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto IRQ_banks_done
bcf LATC, 5
bcf TRISC, 5
IRQ_banks_done
; Wiring pin list just for easy referance no affect on the code
;****************************************************************************************
; port list [SSOP20]
; Vdd(1)
; Vss(20)
; RA0(19) [ICSPDAT]
; RA1(18) [ICSPCLK]
; RA2(17) D1-6B D9,D15
; RA3(4) [#MCLR] select button in
; RA4(3) D1-6R D7,D13
; RA5(2) D1-6G D8,D14
; RB4(13) D7-12G D2,D17
; RB5(12) D7-12R D1,D16
; RB6(11) D7-12B D3,D18
; RB7(10)
; RC0(16) SCL
; RC1(15) SDA
; RC2(14)
; RC3(7)
; RC4(6)
; RC5(5) D13-18B D6,D12
; RC6(8) D13-18G D5,D11
; RC7(9) D13-18R D4,D10
;****************************************************************************************
; increment the timer sequence
incf led_seq, F
IRQ_not_tmr1
retfie
;###########################################################################################################################
; end of IRQ code
;###########################################################################################################################
; this is a lable. Compiler will automatically replace these with addresses when used in goto and branch statements.
START
; init crap
;------------------
; the ram memory is broken up into into multiple pages. This command sets the current page to 0 where I want to start my init work.
clrf BSR ; bank 0
;------------------
clrf INTCON ; disable interupts
clrf LATA ; set all IOs low
clrf LATB ; set all IOs low
clrf LATC ; set all IOs low
movlw 0xFF
movwf TRISA ; all LED IOs to inputs (tristate), MCLR as input (can only be a input)
movlw 0x70
movwf TRISB ; all LED IOs to inputs (tristate), others as outputs to keep them from floating (draws more power than just driving them low)
movlw 0xE0
movwf TRISC ; all LED IOs to inputs (tristate), others as outputs to keep them from floating (draws more power than just driving them low) I2C is pins C0 and C1
; clear vars
movlw 0x20 ; start of bank 0 vars
movwf FSR0L
clrf FSR0H
movlw 0x50 ; clear all of bank other than globals
movwf gtemp
init_bank0_loop
clrf INDF0
incf FSR0L
decfsz gtemp, F
goto init_bank0_loop
; LFSR CANOT BE 0!!!! If it is it will never return any value other than 0.
movwf 0x44
movwf LFSR_0
movwf LFSR_1
movwf LFSR_2
movwf LFSR_3
;------------------
movlw d'4'
movwf BSR
;------------------
; set up timer1. This is used to drive the interrupt that updates the LEDs
movlw TMR1H_value
movwf TMR1H
movlw TMR1L_value
movwf TMR1L
clrf T1GATE ; T1GPPS (not used)
movlw 0x01
movwf T1CLK ; Fosc/4
clrf T1GCON ; gate disable timer always counts
movlw 0x07
movwf T1CON ; do not sync, 16 bit reads, timer 1 on
;------------------
movlw d'14'
movwf BSR
;------------------
bsf PIE4, 0 ; enable timer 1 IRQ
bcf PIR4, 0 ; clear timer 1 flag
;------------------
movlw d'62'
movwf BSR
;------------------
; configure properties of the IO pins.
clrf ANSELA ; set io to be a digital pin not analog
clrf WPUA ; weak pull ups disabled
clrf ODCONA ; push pull not open drain selected.
clrf SLRCONA ; max slew rate (hard edges)
clrf INLVLA ; pick TTL voltage levels over ST levels for interrupt on change comparitor (if used)
clrf ANSELB ; set io to be a digital pin not analog
clrf WPUB ; weak pull ups disabled
clrf ODCONB ; push pull not open drain selected.
clrf SLRCONB ; max slew rate (hard edges)
clrf INLVLB ; pick TTL voltage levels over ST levels for interrupt on change comparitor (if used)
clrf ANSELC ; set io to be a digital pin not analog
clrf WPUC ; weak pull ups disabled
clrf ODCONC ; push pull not open drain selected.
clrf SLRCONC ; max slew rate (hard edges)
clrf INLVLC ; pick TTL voltage levels over ST levels for interrupt on change comparitor (if used)
;------------------
clrf BSR ; bank 0
;------------------
movlw 0xE0 ; global, PE, and Timer 0 on
movwf INTCON ; enable interrupts
; grab the saved mode value from flash
movlw HIGH(mode_save)
movwf FSR0H
movlw LOW(mode_save)
movwf FSR0L
movf INDF0, W
movwf mode
;--------------------------------------------------------------------------------------------------------------------------------------------------
MAINLOOP
;------------------
clrf BSR ; bank 0
;------------------
; deboune the button incremetn the mode when the button is pressed
bcf STATUS, C ; carry bit is used in the rotate command
btfsc PORTA, 3 ; select button
bsf STATUS, C ; if the button was high set carry high. Else leave low
rrf debounce, F ; rotate bit in
; look at last status of the button and branck to the proper code
btfss stat, 0
goto button_was_low
; button was last high (not pressed) wait for a press
movf debounce, W
btfss STATUS, Z ; if Z = 1 the value of debounce is zero meaning the button was down for at least 8 cycles
goto button_no_change
bcf stat, 0 ; set status to indicate button was low last
incf mode, F ; add one to the mode bit
movf mode, W
movwf gtemp ; save temporarily to a global var for use in the flash write seq below
; reset the delay timer if running.
;------------------
movlw d'11'
movwf BSR
;------------------
clrf T0CON0 ; turn off timer
; save the new mode value to flash so it can be retrieved on power cycle
;------------------
movlw d'16'
movwf BSR
;------------------
; erase row
movlw LOW(mode_save)
movwf NVMADRL
movlw HIGH(mode_save)
andlw 0x7F
movwf NVMADRH
movlw 0x14 ; flash regs, erase, write enable
movwf NVMCON1
call _unlock_flash ; special sequence to do a write or clear to flash
bcf NVMCON1, WREN ; disable writes
; mode save offset
movlw LOW(mode_save)
movwf NVMADRL
movlw HIGH(mode_save)
andlw 0x7F
movwf NVMADRH
;point at the data buffer
movlw 0x24 ; flash regs, load latches only, write enable
movwf NVMCON1
mode_data_loop
movf gtemp, W ; just saving the mode value to all 32 bytes. Only realy needs to be in the first one.
movwf NVMDATL ; load the data byte
clrf NVMDATH
movf NVMADRL, W
andlw 0x1F ; mask off the bottom 5 bits
xorlw 0x1F ; check if = 31
btfsc STATUS, Z
goto mode_start_flash_write
call _unlock_flash ; special sequence to do a write or clear to flash
incf NVMADRL, F
goto mode_data_loop
mode_start_flash_write
bcf NVMCON1, LWLO ; flip the bit to do the actual write to flash vs just loading the data registers
call _unlock_flash ; special sequence to do a write or clear to flash
bcf NVMCON1, WREN ; disable writes
;------------------
clrf BSR ; bank 0
;------------------
; clear out the animation seq counters since a new animation was picked
clrf ann_seq0
clrf ann_seq1
clrf ann_seq2
goto button_no_change
button_was_low
; last update the button was low (pressed) wait till it is released before restarting the press detect.
comf debounce, W
btfss STATUS, Z ; if Z = 1 the value of debounce is zero meaning the button was down for at least 8 cycles
goto button_no_change
bsf stat, 0 ; set status to indicate button was high last
button_no_change
; check if the delay timer is running
;------------------
movlw d'11'
movwf BSR
;------------------
btfss T0CON0, 7 ; timer on bit
goto delay_not_running
;------------------
movlw d'14'
movwf BSR
;------------------
; if delay timer is running check if it has timed out yet
btfss PIR0, 5
goto MAINLOOP ; hop back to the start of the loop to check the mode button while in a led delay.
; timer has rolled over clean up and turn it off
bcf PIR0, 5 ; clear timer 0 flag
;------------------
movlw d'11'
movwf BSR
;------------------
clrf T0CON0 ; turn off timer
delay_not_running
;------------------
clrf BSR ; bank 0
;------------------
; check which mode we are in and use the propper pattern
; --------------------------------------------------------------------------------------------------------------------------------------------------
; Request: Pulsing [color] with it going slightly lighter and back to full [color].
; --------------------------------------------------------------------------------------------------------------------------------------------------
movlw 0x07 ; check if mode is in range
subwf mode, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C ; if the result is 0 skip the jump
goto not_mode0_6
movlw 0x10 ; check if over max if so reset to 0
subwf ann_seq0, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto mode0_ramp_down
; ramp up
movf mode, W
movwf ann_seq1
call _pallet_cycle ; ann_seq1 is used to control this which is = to mode in this case
movf ann_seq0, W
addwf bulk_blue, F
addwf bulk_red, F
addwf bulk_green, F
call _set_all
movlw 0x10 ; delay value from 0.017s to ~4.2s in 256 steps (0.017s per step)
call _delay
incf ann_seq0, F
; this value sets the max ramp rate!!!!!
movlw 0x05 ; check if over if so advance to the next stage
subwf ann_seq0, W ; C = 0 if W > F, C = 1 W <= F
btfss STATUS, C
goto MAINLOOP
; if at max use a longer delay (resets the delay set up before
movlw 0x10 ; delay value from 0.017s to ~4.2s in 256 steps (0.017s per step)
call _delay
; set seq to ramp down on next run
movlw 0x10
iorwf ann_seq0, F
goto MAINLOOP
mode0_ramp_down
; ramp down
decf bulk_blue, F
decf bulk_red, F
decf bulk_green, F
call _set_all
movlw 0x10 ; delay value from 0.017s to ~4.2s in 256 steps (0.017s per step)
call _delay
decf ann_seq0, F
movf ann_seq0, W
xorlw 0x11 ; check if over max mode if so reset to 0
btfss STATUS, Z
goto MAINLOOP
; if at min use a longer delay (resets the delay set up before
movlw 0x20 ; delay value from 0.017s to ~4.2s in 256 steps (0.017s per step)
call _delay
; reset counter to 0
clrf ann_seq0
goto MAINLOOP
not_mode0_6
; --------------------------------------------------------------------------------------------------------------------------------------------------
; Request: Rotating Infinity Stone Colors around the edge with "Pulsing" yellow" in the center.
; --------------------------------------------------------------------------------------------------------------------------------------------------
movf mode, W ; grap the mode and shove it in W
xorlw 0x07 ; exclusive or value with W (if W == value then the result will be 0)
btfss STATUS, Z ; if the result is 0 skip the jump
goto not_mode7
clrf ann_seq1
call _inf5_cycle
call _rotate_set_outer_ring
incf ann_seq1,F ; used by inf5 cycle to get color to return
incf ann_seq2,F ; used by outer ring to pick led
;call _clear_RGB
call _rotate_set_outer_ring
incf ann_seq2,F ; used by outer ring to pick led
; triple LED
call _rotate_set_outer_ring
incf ann_seq2,F ; used by outer ring to pick led
call _inf5_cycle
call _rotate_set_outer_ring
incf ann_seq1,F ; used by inf5 cycle to get color to return
incf ann_seq2,F ; used by outer ring to pick led
;call _clear_RGB
call _rotate_set_outer_ring
incf ann_seq2,F ; used by outer ring to pick led
call _inf5_cycle
call _rotate_set_outer_ring
incf ann_seq1,F ; used by inf5 cycle to get color to return
incf ann_seq2,F ; used by outer ring to pick led
;call _clear_RGB
call _rotate_set_outer_ring
incf ann_seq2,F ; used by outer ring to pick led
; triple LED
call _rotate_set_outer_ring
incf ann_seq2,F ; used by outer ring to pick led
call _inf5_cycle
call _rotate_set_outer_ring
incf ann_seq1,F ; used by inf5 cycle to get color to return
incf ann_seq2,F ; used by outer ring to pick led
;call _clear_RGB
call _rotate_set_outer_ring
incf ann_seq2,F ; used by outer ring to pick led
call _inf5_cycle
call _rotate_set_outer_ring
incf ann_seq1,F ; used by inf5 cycle to get color to return
incf ann_seq2,F ; used by outer ring to pick led
;call _clear_RGB
call _rotate_set_outer_ring
incf ann_seq2,F ; used by outer ring to pick led
;call _clear_RGB
;call _rotate_set_outer_ring
;incf ann_seq2,F ; used by outer ring to pick led
;call _rotate_set_outer_ring
;incf ann_seq2,F ; used by outer ring to pick led
; this check is to prevent the display from getting stuck since the rotate == the number of leds.
movlw 0x0C ; if greater than 12 rest to 0
subwf ann_seq2, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
clrf ann_seq2
not_mode7_skip
incf ann_seq2,F ; used by outer ring to pick led
; yellow pulse
movlw 0xFF
movwf led8r
movwf led8g
movwf led9r
movwf led9g
movwf led15r
movwf led15g
movlw 0x10 ; check if over max if so reset to 0
subwf ann_seq0, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
goto mode7_ramp_down
; ramp up
movf ann_seq0, W
movwf led8b
movwf led9b
movwf led15b
incf ann_seq0, F
; this value sets the max ramp rate!!!!!
movlw 0x08 ; check if over max mode if so reset to 0
subwf ann_seq0, W ; C = 0 if W > F, C = 1 W <= F
btfss STATUS, C
goto mode7_done
; set seq to ramp down on next run
movlw 0x10
iorwf ann_seq0, F
goto mode7_done
mode7_ramp_down
; ramp down
movf ann_seq0, W ; invert value
andlw 0x0F ; mask off upper bits
movwf led8b
movwf led9b
movwf led15b
decf ann_seq0, F
movf ann_seq0, W
xorlw 0x10 ; check if over max mode if so reset to 0
btfss STATUS, Z
goto mode7_done
; reset counter to 0
clrf ann_seq0
mode7_done
movlw 0x08 ; delay value from 0.017s to ~4.2s in 256 steps (0.017s per step)
call _delay
goto MAINLOOP
not_mode7
; --------------------------------------------------------------------------------------------------------------------------------------------------
; found this animation while working on the previous one looked oool so lef it in. Chasing stones
; --------------------------------------------------------------------------------------------------------------------------------------------------
movf mode, W ; grap the mode and shove it in W
xorlw 0x08 ; exclusive or value with W (if W == value then the result will be 0)
btfss STATUS, Z ; if the result is 0 skip the jump
goto not_mode8
call _inf5_cycle
call _rotate_set_outer_ring
incf ann_seq1,F ; used by inf5 cycle to get color to return
incf ann_seq2,F ; used by outer ring to pick led
movlw 0xff
movwf bulk_red
movwf bulk_green
clrf bulk_blue
movf ann_seq0, W
andlw 0x01
btfss STATUS, Z
goto not_mode8_skip
movlw 0x08
movwf bulk_blue
not_mode8_skip
call _rotate_set_inner_ring_ccw
incf ann_seq0,F ; toss in a bight led every 4 (1 more than previous update)
incf ann_seq3,F ; used by inner ring to pick led
movlw 0x04 ; delay value from 0.017s to ~4.2s in 256 steps (0.017s per step)
call _delay
goto MAINLOOP
not_mode8
; --------------------------------------------------------------------------------------------------------------------------------------------------
; set LEDS to random values
; --------------------------------------------------------------------------------------------------------------------------------------------------
movf mode, W ; grap the mode and shove it in W
xorlw 0x09 ; exclusive or value with W (if W == value then the result will be 0)
btfss STATUS, Z ; if the result is 0 skip the jump
goto not_mode9
movlw 0x12 ; if greater than 12 rest to 0
subwf ann_seq0, W ; C = 0 if W > F, C = 1 W <= F
btfsc STATUS, C
clrf ann_seq0
clrf FSR1H ; set up indirect register to start of led bank
movlw led1r ; start of LED regs
movwf FSR1L
movf ann_seq0, W
addwf FSR1L ; add 3x seq number
addwf FSR1L ; add 3x seq number
addwf FSR1L ; add 3x seq number
call _CYCLE_LFSR
andlw 0x0F