-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprog.S
2217 lines (1784 loc) · 52.5 KB
/
prog.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
; ****************************************************************************
;
; Program
;
; ****************************************************************************
#include "include.inc"
.text
; bridges
.global _EERead
_EERead: jmp EERead
.global _EEWrite
_EEWrite: jmp EEWrite
; key names for display
.global DispName
DispName:
.asciz "0" ; 0x00 digit 0
.asciz "1" ; 0x01 digit 1
.asciz "2" ; 0x02 digit 2
.asciz "3" ; 0x03 digit 3
.asciz "4" ; 0x04 digit 4
.asciz "5" ; 0x05 digit 5
.asciz "6" ; 0x06 digit 6
.asciz "7" ; 0x07 digit 7
.asciz "8" ; 0x08 digit 8
.asciz "9" ; 0x09 digit 9
.asciz "0A" ; 0x0a digit 0A
.asciz "0B" ; 0x0b digit 0B
.asciz "0C" ; 0x0c digit 0C
.asciz "0D" ; 0x0d digit 0D
.asciz "0E" ; 0x0e digit 0E
.asciz "0F" ; 0x0f digit 0F
.asciz "E'" ; 0x10 label E'
.asciz "A" ; 0x11 label A
.asciz "B" ; 0x12 label B
.asciz "C" ; 0x13 label C
.asciz "D" ; 0x14 label D
.asciz "E" ; 0x15 label E
.asciz "A'" ; 0x16 label A'
.asciz "B'" ; 0x17 label B'
.asciz "C'" ; 0x18 label C'
.asciz "D'" ; 0x19 label D'
.asciz "A''" ; 0x1a label A''
.asciz "B''" ; 0x1b label B''
.asciz "C''" ; 0x1c label C''
.asciz "D''" ; 0x1d label D''
.asciz "E''" ; 0x1e label E''
.asciz "F" ; 0x1f label F
.asciz "" ; 0x20
.asciz "2nd" ; 0x21 2nd
.asciz "INV" ; 0x22 INV
.asciz "ln x" ; 0x23 Ln x
.asciz "CE" ; 0x24 CE
.asciz "CLR" ; 0x25 CLR
.asciz "SBR Ind" ; 0x26 SBR Ind
.asciz "HIR Ind" ; 0x27 HIR Ind
.asciz "log" ; 0x28 log
.asciz "CP" ; 0x29 CP
.asciz "" ; 0x2a
.asciz "code" ; 0x2b code
.asciz "log2" ; 0x2c log2
.asciz "rand" ; 0x2d rand
.asciz "" ; 0x2e
.asciz "" ; 0x2f
.asciz "tan" ; 0x30 tan
.asciz "LRN" ; 0x31 LRN
.asciz "x<->t" ; 0x32 x<>t
.asciz "x^2" ; 0x33 x^2
.byte CHAR_ROOT
.asciz "x" ; 0x34 Vx
.asciz "1/x" ; 0x35 1/x
.asciz "Pgm" ; 0x36 Pgm
.asciz "P->R" ; 0x37 P->R
.asciz "sin" ; 0x38 sin
.asciz "cos" ; 0x39 cos
.asciz "Temp" ; 0x3a Temp
.asciz "x<->y" ; 0x3b x<>y
.asciz "sinh" ; 0x3c sinh
.asciz "cosh" ; 0x3d cosh
.asciz "tanh" ; 0x3e tanh
.asciz "" ; 0x3f
.asciz "Ind" ; 0x40 Ind
.asciz "SST" ; 0x41 SST
.asciz "STO" ; 0x42 STO
.asciz "RCL" ; 0x43 RCL
.asciz "SUM" ; 0x44 SUM
.asciz "y^x" ; 0x45 y^x
.asciz "Ins" ; 0x46 Ins
.asciz "CMs" ; 0x47 CMs
.asciz "Exc" ; 0x48 Exc
.asciz "Prd" ; 0x49 Prd
.asciz "Bat" ; 0x4a Bat
.asciz "x!" ; 0x4b n!
.asciz "ln x!" ; 0x4c ln n!
.asciz "log x!" ; 0x4d log n!
.asciz "mod2" ; 0x4e mod2 (floor)
.asciz "" ; 0x4f
.asciz "|x|" ; 0x50 |x|
.asciz "BST" ; 0x51 BST
.asciz "EE" ; 0x52 EE
.asciz "(" ; 0x53 (
.asciz ")" ; 0x54 )
.asciz ":" ; 0x55 :
.asciz "Del" ; 0x56 Del
.asciz "Eng" ; 0x57 Eng
.asciz "Fix" ; 0x58 Fix
.asciz "Int" ; 0x59 Int
.asciz "LCD" ; 0x5a LCD
.asciz "<<" ; 0x5b <<
.asciz ">>" ; 0x5c >>
.asciz "round" ; 0x5d round
.asciz "mod" ; 0x5e mod (trunc)
.asciz "" ; 0x5f
.asciz "Deg" ; 0x60 Deg
.asciz "GTO" ; 0x61 GTO
.asciz "Pgm Ind" ; 0x62 Pgm Ind
.asciz "Exc Ind" ; 0x63 Exc Ind
.asciz "Prd Ind" ; 0x64 Prd Ind
.asciz "x" ; 0x65 x
.asciz "Pause" ; 0x66 Pause
.asciz "x=t" ; 0x67 x=t
.asciz "Nop" ; 0x68 Nop
.asciz "Op" ; 0x69 Op
.asciz "Rel" ; 0x6a Rel
.asciz "Inc Ind" ; 0x6b Inc Ind
.asciz "Reg Ind" ; 0x6c Reg Ind
.asciz "IF Ind" ; 0x6d IF Ind
.asciz "AND" ; 0x6e & AND
.asciz "" ; 0x6f
.asciz "Rad" ; 0x70 Rad
.asciz "SBR" ; 0x71 SBR
.asciz "STO Ind" ; 0x72 STO Ind
.asciz "RCL Ind" ; 0x73 RCL Ind
.asciz "SUM Ind" ; 0x74 SUM Ind
.asciz "-" ; 0x75 -
.asciz "Lbl" ; 0x76 Lbl
.asciz "x>=t" ; 0x77 x>=t
.asciz "Stat+" ; 0x78 Stat+
.asciz "Mean" ; 0x79 Avrg x (Mean)
.asciz "IF" ; 0x7a If
.asciz "" ; 0x7b
.asciz "" ; 0x7c
.asciz "" ; 0x7d
.asciz "XOR" ; 0x7e ~ XOR
.asciz "" ; 0x7f
.asciz "Grad" ; 0x80 Grad
.asciz "RST" ; 0x81 RST
.asciz "HIR" ; 0x82 HIR
.asciz "GTO Ind" ; 0x83 GTO Ind
.asciz "Op Ind" ; 0x84 Op Ind
.asciz "+" ; 0x85 +
.asciz "St flg" ; 0x86 St Flg
.asciz "If flg" ; 0x87 If Flg
.asciz "D.MS" ; 0x88 D.MS
.asciz "pi" ; 0x89 pi
.asciz "Reg" ; 0x8a Reg
.asciz "HEX" ; 0x8b HEX
.asciz "BIN" ; 0x8c BIN
.asciz "OCT" ; 0x8d OCT
.asciz "OR" ; 0x8e | OR
.asciz "" ; 0x8f
.asciz "List" ; 0x90 List
.asciz "R/S" ; 0x91 R/S
.asciz "RTN" ; 0x92 RTN
.asciz "." ; 0x93 .
.asciz "+/-" ; 0x94 +/-
.asciz "=" ; 0x95 =
.asciz "Write" ; 0x96 Write
.asciz "Dsz" ; 0x97 Dsz
.asciz "Adv" ; 0x98 Adv
.asciz "Prt" ; 0x99 Prt
.asciz "" ; 0x9a
.asciz "DEC" ; 0x9b DEC
.asciz "Inc" ; 0x9c Inc
.asciz "NOT" ; 0x9d NOT
.asciz "%" ; 0x9e %
.asciz "" ; 0x9f
.balign 2
.global DispNameErr
DispNameErr:
.asciz "" ; invalid code
.balign 2
.global DispNameEmpty
DispNameEmpty:
.asciz "...empty" ; 0xff
.balign 2
; ----- key instruction type, to get key code length
.global KeyLen
KeyLen:
TYPE(1,1) ; #define KEY_0 0x00 // digit 0
; #define KEY_1 0x01 // digit 1
TYPE(1,1) ; #define KEY_2 0x02 // digit 2
; #define KEY_3 0x03 // digit 3
TYPE(1,1) ; #define KEY_4 0x04 // digit 4
; #define KEY_5 0x05 // digit 5
TYPE(1,1) ; #define KEY_6 0x06 // digit 6
; #define KEY_7 0x07 // digit 7
TYPE(1,1) ; #define KEY_8 0x08 // digit 8
; #define KEY_9 0x09 // digit 9
TYPE(1,1) ; #define KEY_0A 0x0a // digit 0A
; #define KEY_0B 0x0b // digit 0B
TYPE(1,1) ; #define KEY_0C 0x0c // digit 0C
; #define KEY_0D 0x0d // digit 0D
TYPE(1,1) ; #define KEY_0E 0x0e // digit 0E
; #define KEY_0F 0x0f // digit 0F
TYPE(1,1) ; #define KEY_E2 0x10 // label E'
; #define KEY_A 0x11 // label A
TYPE(1,1) ; #define KEY_B 0x12 // label B
; #define KEY_C 0x13 // label C
TYPE(1,1) ; #define KEY_D 0x14 // label D
; #define KEY_E 0x15 // label E
TYPE(1,1) ; #define KEY_A2 0x16 // label A'
; #define KEY_B2 0x17 // label B'
TYPE(1,1) ; #define KEY_C2 0x18 // label C'
; #define KEY_D2 0x19 // label D'
TYPE(1,1) ; #define KEY_A3 0x1a // label A''
; #define KEY_B3 0x1b // label B''
TYPE(1,1) ; #define KEY_C3 0x1c // label C''
; #define KEY_D3 0x1d // label D''
TYPE(1,1) ; #define KEY_E3 0x1e // label E''
; #define KEY_F 0x1f // label F
TYPE(1,1) ; #define KEY_FRAC 0x20 // a/b (fraction)
; #define KEY_2ND 0x21 // 2nd
TYPE(1,1) ; #define KEY_INV 0x22 // INV
; #define KEY_LNX 0x23 // Ln x
TYPE(1,1) ; #define KEY_CE 0x24 // CE
; #define KEY_CLR 0x25 // CLR
TYPE(2,2) ; #define KEY_SBR_IND 0x26 // SBR Ind
; #define KEY_HIR_IND 0x27 // HIR Ind
TYPE(1,1) ; #define KEY_LOG 0x28 // log
; #define KEY_CP 0x29 // CP
TYPE(1,1) ; 0x2a //
; #define KEY_CODE 0x2b // code
TYPE(1,1) ; #define KEY_LG2 0x2c // log2
; #define KEY_RAND 0x2d // rand
TYPE(1,1) ; 0x2e //
; 0x2f //
TYPE(1,1) ; #define KEY_TAN 0x30 // tan
; #define KEY_LRN 0x31 // LRN
TYPE(1,1) ; #define KEY_XT 0x32 // x<>t
; #define KEY_X2 0x33 // x^2
TYPE(1,1) ; #define KEY_SQR 0x34 // Vx
; #define KEY_1X 0x35 // 1/x
TYPE(2,1) ; #define KEY_PGM 0x36 // Pgm
; #define KEY_PR 0x37 // P->R
TYPE(1,1) ; #define KEY_SIN 0x38 // sin
; #define KEY_COS 0x39 // cos
TYPE(1,1) ; #define KEY_TEMP 0x3a // Temp
; #define KEY_XY 0x3b // x<>y
TYPE(1,1) ; #define KEY_SINH 0x3c // sinh
; #define KEY_COSH 0x3d // cosh
TYPE(1,1) ; #define KEY_TANH 0x3e // tanh
; 0x3f //
TYPE(2,1) ; #define KEY_IND 0x40 // Ind
; #define KEY_SST 0x41 // SST
TYPE(2,2) ; #define KEY_STO 0x42 // STO
; #define KEY_RCL 0x43 // RCL
TYPE(2,1) ; #define KEY_SUM 0x44 // SUM
; #define KEY_POW 0x45 // y^x
TYPE(1,1) ; #define KEY_INS 0x46 // Ins
; #define KEY_CMS 0x47 // CMs
TYPE(2,2) ; #define KEY_EXC 0x48 // Exc
; #define KEY_PRD 0x49 // Prd
TYPE(1,1) ; #define KEY_BAT 0x4a // Bat
; #define KEY_FACT 0x4b // n!
TYPE(1,1) ; #define KEY_LNFACT 0x4c // ln n!
; #define KEY_LOGFACT 0x4d // log n!
TYPE(1,1) ; #define KEY_MOD2 0x4e // mod2 (floor)
; 0x4f //
TYPE(1,1) ; #define KEY_ABS 0x50 // |x|
; #define KEY_BST 0x51 // BST
TYPE(1,1) ; #define KEY_EE 0x52 // EE
; #define KEY_LPAR 0x53 // (
TYPE(1,1) ; #define KEY_RPAR 0x54 // )
; #define KEY_DIV 0x55 // :
TYPE(1,1) ; #define KEY_DEL 0x56 // Del
; #define KEY_ENG 0x57 // Eng
TYPE(2+TIND,1) ; #define KEY_FIX 0x58 // Fix
; #define KEY_INT 0x59 // Int
TYPE(2+TIND,1) ; #define KEY_LCD 0x5a // LCD
; #define KEY_LEFT 0x5b // <<
TYPE(1,1) ; #define KEY_RIGHT 0x5c // >>
; #define KEY_ROUND 0x5d // round
TYPE(1,1) ; #define KEY_MOD 0x5e // mod (trunc)
; 0x5f //
TYPE(1,2+TADR) ; #define KEY_DEG 0x60 // Deg
; #define KEY_GTO 0x61 // GTO
TYPE(2,2) ; #define KEY_PGM_IND 0x62 // Pgm Ind
; #define KEY_EXC_IND 0x63 // Exc Ind
TYPE(2,1) ; #define KEY_PRD_IND 0x64 // Prd Ind
; #define KEY_MUL 0x65 // x
TYPE(1,2+TADR) ; #define KEY_PAU 0x66 // Pause
; #define KEY_EQ 0x67 // x=t
TYPE(1,2) ; #define KEY_NOP 0x68 // Nop
; #define KEY_OP 0x69 // Op
TYPE(2,2) ; #define KEY_REL 0x6a // REL
; #define KEY_INC_IND 0x6b // Inc Ind
TYPE(3,4+TADR) ; #define KEY_REG_IND 0x6c // Reg Ind
; #define KEY_IF_IND 0x6d // If Ind
TYPE(1,1) ; #define KEY_AND 0x6e // AND &
; 0x6f //
TYPE(1,2+TADR) ; #define KEY_RAD 0x70 // Rad
; #define KEY_SBR 0x71 // SBR
TYPE(2,2) ; #define KEY_STO_IND 0x72 // STO Ind
; #define KEY_RCL_IND 0x73 // RCL Ind
TYPE(2,1) ; #define KEY_SUM_IND 0x74 // SUM Ind
; #define KEY_SUB 0x75 // -
TYPE(2,2+TADR) ; #define KEY_LBL 0x76 // Lbl
; #define KEY_GE 0x77 // x>=t
TYPE(1,1) ; #define KEY_STA 0x78 // Stat+
; #define KEY_AVR 0x79 // Avrg x (Mean)
TYPE(4+TADR,1) ; #define KEY_IF 0x7a // If
; 0x7b //
TYPE(1,1) ; 0x7c //
; 0x7d //
TYPE(1,1) ; #define KEY_XOR 0x7e // XOR ~
; 0x7f //
TYPE(1,1) ; #define KEY_GRD 0x80 // Grad
; #define KEY_RST 0x81 // RST
TYPE(2,2) ; #define KEY_HIR 0x82 // HIR
; #define KEY_GTO_IND 0x83 // GTO Ind
TYPE(2,1) ; #define KEY_OP_IND 0x84 // Op Ind
; #define KEY_ADD 0x85 // +
TYPE(2+TIND,3+TIND+TADR) ; #define KEY_STF 0x86 // St Flg
; #define KEY_IFF 0x87 // If Flg
TYPE(1,1) ; #define KEY_DMS 0x88 // D.MS
; #define KEY_PI 0x89 // pi
TYPE(3,1) ; #define KEY_REG 0x8a // Reg
; #define KEY_HEX 0x8b // HEX
TYPE(1,1) ; #define KEY_BIN 0x8c // BIN
; #define KEY_OCR 0x8d // OCT
TYPE(1,1) ; #define KEY_OR 0x8e // OR |
; 0x8f //
TYPE(1,1) ; #define KEY_LST 0x90 // List
; #define KEY_RS 0x91 // R/S
TYPE(1,1) ; #define KEY_RTN 0x92 // RTN
; #define KEY_DOT 0x93 // .
TYPE(1,1) ; #define KEY_NEG 0x94 // +/-
; #define KEY_RES 0x95 // =
TYPE(1,3+TIND+TADR) ; #define KEY_WRT 0x96 // Write
; #define KEY_DSZ 0x97 // Dsz
TYPE(1,1) ; #define KEY_ADV 0x98 // Adv
; #define KEY_PRT 0x99 // Prt
TYPE(1,1) ; #define KEY_PHI 0x9a // phi
; #define KEY_DEC 0x9b // DEC
TYPE(2,1) ; #define KEY_INC 0x9c // Inc
; #define KEY_NOT 0x9d // NOT
TYPE(1,1) ; #define KEY_PERC 0x9e // %
; 0x9f //
.balign 2
; ----------------------------------------------------------------------------
; Get program address in ROM module (not for main program)
; ----------------------------------------------------------------------------
; INPUT: R24 = program index (1,...)
; OUTPUT: R31:R30 = program address in ROM
; DESTROYS: R0
; ----------------------------------------------------------------------------
.global GetProgAddr
GetProgAddr:
ldi r30,lo8(Module)
ldi r31,hi8(Module)
add r30,r24
adc r31,R_ZERO
add r30,r24
adc r31,R_ZERO
lpm r0,Z+
lpm r31,Z
mov r30,r0
subi r30,lo8(-(Module)) ; program address LOW
sbci r31,hi8(-(Module))
ret
; ----------------------------------------------------------------------------
; Open program (fatal error if program index is not valid)
; ----------------------------------------------------------------------------
; INPUT: R24 = program index (0=main)
; DESTROYS: R31, R30, R24, R0
; ----------------------------------------------------------------------------
.global OpenProg
OpenProg:
; ----- check program index
ldd r30,Y+DATA_PROGNUM ; number of programs in module
inc r30
cp r24,r30 ; check program index
brcs 2f ; program index is OK
jmp Fatal ; fatal error
; ----- set new program index
2: std Y+DATA_PROGINX,r24 ; current program index
std Y+DATA_PROGNEXT,r24 ; next program index
; ----- main program
std Y+DATA_PROGBEG,R_ZERO ; begin address = 0
std Y+DATA_PROGBEG+1,R_ZERO
ldi r30,lo8(PROG_NUM) ; end address
ldi r31,hi8(PROG_NUM)
tst r24 ; main program?
breq 6f ; main program
; ----- get program address
; INPUT: R24 = program index (1,...)
; OUTPUT: R31:R30 = program address in ROM
; DESTROYS: R0
rcall GetProgAddr ; address of program begin
std Y+DATA_PROGBEG,r30
std Y+DATA_PROGBEG+1,r31
; ----- get program end
; INPUT: R24 = program index (1,...)
; OUTPUT: R31:R30 = program address in ROM
; DESTROYS: R0
inc r24 ; next index
rcall GetProgAddr ; address of program end
6: std Y+DATA_PROGEND,r30
std Y+DATA_PROGEND+1,r31
ret
; ----------------------------------------------------------------------------
; Get display name of program byte
; ----------------------------------------------------------------------------
; INPUT: R24 = code
; OUTPUT: R31:R30 = ASCIIZ text in ROM
; DESTROYS: R25
; ----------------------------------------------------------------------------
.global GetDispName
GetDispName:
; ----- empty
ldi r30,lo8(DispNameEmpty)
ldi r31,hi8(DispNameEmpty)
cpi r24,0xff
breq 8f
; ----- invalid code
ldi r30,lo8(DispNameErr)
ldi r31,hi8(DispNameErr)
cpi r24,MAXKEY+1
brcc 8f
; ----- find text
ldi r30,lo8(DispName)
ldi r31,hi8(DispName)
tst r24
breq 8f
2: lpm r25,Z+
tst r25
brne 2b
dec r24
brne 2b
8: ret
; ----------------------------------------------------------------------------
; Load one byte from program
; ----------------------------------------------------------------------------
; INPUT: R27:R26 (X) = address (can be out of range)
; OUTPUT: R24 = byte (0 if invalid)
; R27:R26 (X+1) = new address, increased by 1 (not changed on error)
; CY = invalid address (R27:R26 not changed)
; DESTROYS: -
; ----------------------------------------------------------------------------
.global LoadByte
LoadByte:
; ----- push registers
push r30
push r31
; ----- check start of program
clr r24 ; R24 <- invalid code 0
ldd r30,Y+DATA_PROGBEG ; end of program
ldd r31,Y+DATA_PROGBEG+1
cp r26,r30
cpc r27,r31
brcs 6f ; invalid pointer
; ----- check end of program
ldd r30,Y+DATA_PROGEND ; end of program
ldd r31,Y+DATA_PROGEND+1
sbiw r30,1 ; program end - 1
cp r30,r26 ; check pointer
cpc r31,r27 ; set CY = invalid pointer
brcs 6f ; invalid pointer
; ----- check main program
ldd r24,Y+DATA_PROGINX ; current program index
tst r24 ; main program?
brne 2f ; running program from ROM
; ----- read byte from EEPROM
; INPUT: R27:R26 = source address
; OUTPUT: R24 = data
; DESTROYS: -
rcall _EERead
adiw r26,1
rjmp 4f
; ----- read byte from ROM
2: movw r30,r26 ; Z <- pointer
lpm r24,Z+ ; load byte
movw r26,r30 ; X <- new pointer
4: clc ; NC, operation OK
; ----- pop registers
6: pop r31
pop r30
ret
; ----------------------------------------------------------------------------
; Load one byte from program, increments address (stop program on overflow)
; ----------------------------------------------------------------------------
; OUTPUT: R24 = byte (0 on error)
; CY = invalid address (address not changed)
; DESTROYS: -
; ----------------------------------------------------------------------------
.global LoadPrg
LoadPrg:
; ----- push registers
push r26
push r27
; ----- prepare current address -> X
ldd r26,Y+DATA_ADDR
ldd r27,Y+DATA_ADDR+1
; ----- load byte
; INPUT: R27:R26 (X) = address (can be out of range)
; OUTPUT: R24 = byte (0 if invalid)
; R27:R26 (X+1) = new address, increased by 1 (not changed on error)
; CY = invalid address (R27:R26 not changed)
; DESTROYS: -
rcall LoadByte
std Y+DATA_ADDR,r26
std Y+DATA_ADDR+1,r27 ; save new pointer
brcc 8f ; pointer is OK
; stop running on end of memory
CLR_RUNNING ; stop program (do not modify C flag)
; ----- pop registers
8: pop r27
pop r26
ret
; ----------------------------------------------------------------------------
; Convert BCD to BIN (R24)
; ----------------------------------------------------------------------------
; INPUT: R24 = BCD code
; OUTPUT: R24 = BIN code
; R1 = 0
; DESTROYS: R0
; ----------------------------------------------------------------------------
.global Bcd2Bin
Bcd2Bin:
push r25
ldi r25,10
mov r0,r25
mov r25,r24 ; byte
swap r25
andi r25,0x0f ; first digit
mul r25,r0 ; first digit * 10 -> R1:R0
andi r24,0x0f ; second digit
add r24,r0 ; add first digit
clr r1 ; clear R1
pop r25
ret
; ----------------------------------------------------------------------------
; Convert BIN to BCD (R24)
; ----------------------------------------------------------------------------
; INPUT: R24 = BIN code
; OUTPUT: R24 = BCD code
; R1 = 0
; DESTROYS: R0
; ----------------------------------------------------------------------------
.global Bin2Bcd
Bin2Bcd:
; ----- push registers
push r25
push r23
; ----- divide number / 10 -> R24
mov r25,r24 ; save input number
; INPUT: R24 = dividend (N0)
; OUTPUT: R24 = quotient (Q0), 0..25
; R1=0
; DESTROYS: R0
call DivB10
; ----- multiply number back * 10 and subtract from input number
ldi r23,10
mul r23,r24
sub r25,r0
clr r1 ; restore R1 (R_ZERO)
; ----- compose numbers
swap r24
or r24,r25
; ----- pop registers
pop r23
pop r25
ret
; ----------------------------------------------------------------------------
; Load one byte from program, with possible indirect by KEY_IND
; ----------------------------------------------------------------------------
; OUTPUT: R24 = byte
; CY = BCD format (from program), NC = BIN format (from indirect memory)
; R1 = 0
; DESTROYS: R31, R30, R27..R24, R_M1..R_M10, R0
; ----------------------------------------------------------------------------
.global LoadPrgInd
LoadPrgInd:
; ----- load byte and check indirect
; OUTPUT: R24 = byte (0 on error)
; CY = invalid address (address not changed)
; DESTROYS: -
rcall LoadPrg ; load byte, increments address
cpi r24,KEY_IND ; indirect?
sec ; set BCD flag
brne 4f ; not indirect
; ----- load addres of indirect memory and convert it to BIN format
; OUTPUT: R24 = byte (0 on error)
; CY = invalid address (address not changed)
; DESTROYS: -
rcall LoadPrg ; load next byte
; INPUT: R24 = BCD code
; OUTPUT: R24 = BIN code
; R1 = 0
; DESTROYS: R0
rcall Bcd2Bin ; convert to bin
; ----- check memory index, fatal on error
LoadPrgInd2:
cpi r24,USER_NUM ; check memory index
brcs 2f ; index is OK
jmp Fatal ; error
; ----- load indirected content (ignore sign), memory is in BIN format
2: subi r24,-USER_FIRST
; INPUT: R24 = index of the number
; OUTPUT: R1 = 0
; DESTROYS: R31, R30, R27..R24, R0
; CALCULATOR STACK: +1
rcall _CalcGetMem ; get memory
; OUTPUT: R24 = unsigned integer
; C flag is set = overflow valid range
; Z flag is set = number is positive or 0 (breq), NZ = number is negative (brne)
; DESTROYS: R31, R30, R25, R_M1..R_M10
; CALCULATOR STACK: -1
call CalcUnstackB ; get number
clc ; BIN flag
4: ret
; ----------------------------------------------------------------------------
; Start InKey and wait for a key
; ----------------------------------------------------------------------------
; OUTPUT: R24 = key
; DESTROYS: -
; ----------------------------------------------------------------------------
StartInKey:
; DESTROYS: -
rcall FlagSetInKey ; set input flag
; DESTROYS: -
rcall DispFlags
; OUTPUT: R24 = key code
; DESTROYS: -
; NOTE: Enables interrupts
rjmp WaitKey
; ----------------------------------------------------------------------------
; Stop InKey (saves R24)
; ----------------------------------------------------------------------------
; DESTROYS: -
; ----------------------------------------------------------------------------
StopInKey:
; DESTROYS: -
rcall FlagClrInKey ; clear input flag
; DESTROYS: -
rjmp DispFlags
; ----------------------------------------------------------------------------
; Load 1 digit with indirect (from user or from program)
; ----------------------------------------------------------------------------
; OUTPUT: R24 = typically digit 0..15 (0 on break), but can be 0..0xFF
; C is set on invalid key from keyboard, break input (in such case R24 = 0)
; R1 = 0
; DESTROYS: R31, R30, R27..R25, R_M1..R_M10, R0
; ----------------------------------------------------------------------------
.global Load1Dig
Load1Dig:
; ----- check if running
; program is running
IFN_RUNNING ; if not running
rjmp 2f ; skip if not running
; ----- running, load byte from program or from indirect memory (result can be > 15)
; OUTPUT: R24 = byte
; CY = BCD format (from program), NC = BIN format (from indirect memory)
; R1 = 0
; DESTROYS: R31, R30, R27..R24, R_M1..R_M10, R0
rcall LoadPrgInd ; load byte with indirect
clc ; OK (R24 can be 0..0xFF)
ret
; ----- not running, load key from keyboard
; start wait mode and wait for a key -> R24
; OUTPUT: R24 = key
; DESTROYS: -
2: rcall StartInKey
; stop wait mode
; DESTROYS: -
rcall StopInKey
; check digit
cpi r24,16
brcs 8f ; key is OK
; ----- indirect, load from memory
Load1Dig2:
; indirect
cpi r24,KEY_IND
brne 6f ; not indirect, invalid key, break
; load register indirect
; OUTPUT: R24 = typically 0..159 (0 on break), but can be 0..0xFF
; C is set on invalid key from keyboard, break input (in such case R24 = 0)
; R1 = 0
; DESTROYS: R31, R30, R27..R25, R_M1..R_M10, R0
rcall Load2Dig2
brcs 7f ; no key, break input
; OUTPUT: R24 = unsigned integer
; NC flag is clear
; DESTROYS: R31, R30, R25, R_M1..R_M10, R0
rjmp LoadPrgInd2 ; load value or Fatal on invalid memory index
; ----- invalid key, break input, return key to keyboard
; INPUT: R24 = key HEX code
; DESTROYS: -
6: rcall ReturnKey ; return key
7: clr r24 ; returns 0
sec ; set error flag
ret
8: clc ; flag OK
ret
; ----------------------------------------------------------------------------
; Load 2 digits (from user with indirect or from program)
; ----------------------------------------------------------------------------
; OUTPUT: R24 = typically 0..159 (0 on break), but can be 0..0xFF
; C is set on invalid key from keyboard, break input (in such case R24 = 0)
; R1 = 0
; DESTROYS: R31, R30, R27..R25, R_M1..R_M10, R0
; ----------------------------------------------------------------------------
.global Load2Dig
Load2Dig:
; ----- check if running
; program is running
IFN_RUNNING ; if not running
rjmp 4f ; skip if not running
; ----- running, load byte from program or from indirect memory (result can be > 159)
; OUTPUT: R24 = byte (0 on error)
; CY = invalid address (address not changed)
; DESTROYS: -
rcall LoadPrg ; load byte (without indirect)
; INPUT: R24 = BCD code
; OUTPUT: R24 = BIN code
; R1 = 0
; DESTROYS: R0
rcall Bcd2Bin ; convert BCD to BIN
clc ; OK (R24 can be 0..0xFF)
ret
; ----- not running, load key from keyboard
Load2Dig2:
; start wait mode and get first key
; OUTPUT: R24 = key
; DESTROYS: -
4: rcall StartInKey
; check 1st key
cpi r24,16
brcs 2f ; digit is OK
; ----- not valid digit key, stop wait mode and load indirect
; DESTROYS: -
rcall StopInKey
; DESTROYS: R31, R30, R27..R24, R_M1..R_M10, R0
rjmp Load1Dig2 ; indirect, load from memory, or invalid key
; ----- load 2nd key and stop wait mode
2: push r24
; OUTPUT: R24 = key code
; DESTROYS: -
; NOTE: Enables interrupts
rcall WaitKey
; DESTROYS: -
rcall StopInKey
pop r25 ; 1st key
; ----- invalid 2nd key
; check 2nd key
cpi r24,16
brcs 2f ; key is OK
; INPUT: R24 = key HEX code
; DESTROYS: -
rcall ReturnKey ; return key
mov r24,r25 ; only one key
clc ; flag NC = 1 key is OK
ret
; ----- compose both key together (as BIN code)
; add keys
2: ldi r30,10
mul r30,r25
add r24,r0 ; add keys
clr r1 ; restore zero register
clc ; flag NC = number is OK
ret
; ----------------------------------------------------------------------------
; Load 2 HEX digits (from program, 2 digits from user, or as a key)
; ----------------------------------------------------------------------------
; OUTPUT: R24 = byte
; DESTROYS: R25
; ----------------------------------------------------------------------------
.global Load2Hex
Load2Hex:
; ----- if running, load byte from program
; program is running
IF_RUNNING ; if running
; OUTPUT: R24 = byte (0 on error)
; CY = invalid address (address not changed)
; DESTROYS: -
rjmp LoadPrg ; load byte (without indirect)
; ----- start wait mode and get key
; OUTPUT: R24 = key
; DESTROYS: -
rcall StartInKey
; ----- if not valid digit, return key
; check 1st key
cpi r24,16 ; check valid digit
brcs 4f ; digit is OK
; DESTROYS: -
rjmp StopInKey ; not valid digit, stop wait mode and return key
; ----- wait for 2nd digit and stop wait mode
4: push r24
; OUTPUT: R24 = key code
; DESTROYS: -
; NOTE: Enables interrupts
rcall WaitKey ; wait for a key
; DESTROYS: -
rcall StopInKey ; stop wait mode
pop r25 ; 1st digit
; ----- if 2nd digit is not valid, return only 1st digit
; check 2nd key
cpi r24,16
brcs 2f ; valid digit
; INPUT: R24 = key HEX code
; DESTROYS: -
rcall ReturnKey ; return key
mov r24,r25 ; 1st digit
ret
; ----- compose bith digits
; add keys
2: swap r25
or r24,r25
ret
; ----------------------------------------------------------------------------
; Load key length flag
; ----------------------------------------------------------------------------
; INPUT: R24 = key code
; OUTPUT: R24 = key flags (code base length 1..3, flags TIND, TADR)
; DESTROYS: -
; ----------------------------------------------------------------------------
.global LoadKeyLen
LoadKeyLen:
; ----- push registers
push r30
push r31
; ----- limit invalid code (change to NOP)
cpi r24,MAXKEY+1
brcs 2f
clr r24
; ----- load byte
2: push r24
ldi r30,lo8(KeyLen)
ldi r31,hi8(KeyLen)