-
Notifications
You must be signed in to change notification settings - Fork 1
/
CTS256A.LST
1923 lines (1919 loc) · 99.3 KB
/
CTS256A.LST
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
** TMS-7000 Tiny Assembler - v0.3.0-alpha - (C) 2024 GmEsoft, All rights reserved. **
Sat Aug 24 09:22:08 2024
Assembly of : CTS256A.asm
Output file : CTS256A.cim
Listing file : CTS256A.LST
1: ;** TMS-7000(tm) DISASSEMBLER V1.10beta3 - (c) 2015-20 GmEsoft, All rights reserved. **
2: ;
3: ; Tue Dec 27 08:39:46 2022
4: ;
5: ; Disassembly of : CTS256A.BIN
6: ; Equates file : CTS256A.EQU
7: ; Screening file : CTS256A.SCR
8:
9:
10: ;==============================================================================
11:
12: ; registers used by the text-to-speech code in the masked ROM...
13: 0000 REGA EQU R0 ; A register
14: 0000 XREGA EQU >0000 ; A register long address
15: 0001 REGB EQU R1 ; B register
16: 0001 XREGB EQU >0001 ; B register long address
17: 0002 INRDH EQU R2 ; input buffer read pointer MSB
18: 0003 INRDL EQU R3 ; input buffer read pointer LSB
19: 0003 INRD EQU R3 ; input buffer read pointer
20: 0004 INWRH EQU R4 ; input buffer write pointer MSB
21: 0005 INWRL EQU R5 ; input buffer write pointer LSB
22: 0005 INWR EQU R5 ; input buffer write pointer
23: 0006 OUTRDH EQU R6 ; output buffer read pointer MSB
24: 0007 OUTRDL EQU R7 ; output buffer read pointer LSB
25: 0007 OUTRD EQU R7 ; output buffer read pointer
26: 0008 OUTWRH EQU R8 ; output buffer write pointer MSB
27: 0009 OUTWRL EQU R9 ; output buffer write pointer LSB
28: 0009 OUTWR EQU R9 ; output buffer write pointer
29: 000A FLAGS1 EQU R10 ; flags 1
30: 000B FLAGS2 EQU R11 ; flags 2
31: 000C BUFPTRH EQU R12 ; buffer pointer MSB
32: 000D BUFPTRL EQU R13 ; buffer pointer MSB
33: 000D BUFPTR EQU R13 ; buffer pointer pair
34: 000D XBUFPTR EQU >000D ; temp register pair long address
35: 000E INRDPH EQU R14 ; next input buffer read pointer MSB
36: 000F INRDPL EQU R15 ; next input buffer read pointer LSB
37: 000F INRDP EQU R15 ; next input buffer read pointer
38: 0010 INRDBH EQU R16 ; backward input buffer read pointer MSB
39: 0011 INRDBL EQU R17 ; backward input buffer read pointer LSB
40: 0011 INRDB EQU R17 ; backward input buffer read pointer
41: 0012 PEPROMH EQU R18 ; EPROM scan pointer MSB
42: 0013 PEPROML EQU R19 ; EPROM scan pointer LSB
43: 0013 PEPROM EQU R19 ; EPROM scan pointer
44: 0012 INRDLH EQU R18 ; last input buffer read pointer MSB
45: 0013 INRDLL EQU R19 ; last input buffer read pointer LSB
46: 0013 INRDLX EQU R19 ; last input buffer read pointer
47: 0014 RULPTRH EQU R20 ; Rules pointer MSB
48: 0015 RULPTRL EQU R21 ; Rules pointer MSB
49: 0015 RULPTR EQU R21 ; Rules pointer
50: 0016 NXTCHR EQU R22 ; Next character (-$20 & $3F)
51: 0017 COUNTER EQU R23 ; Counter (RAM pages or chars)
52: 0018 LSTDLMH EQU R24 ; last delimiter position MSB
53: 0019 LSTDLML EQU R25 ; last delimiter position LSB
54: 0019 LSTDELM EQU R25 ; last delimiter position
55: 001B ISP0256 EQU R27 ; SP0256 write address
56: 001C INRDLBH EQU R28 ; last backward input buffer read pointer MSB
57: 001D INRDLBL EQU R29 ; last backward input buffer read pointer LSB
58: 001D INRDLB EQU R29 ; last backward input buffer read pointer
59: 001E INLWMH EQU R30 ; input buffer low water mark MSB
60: 001F INLWML EQU R31 ; input buffer low water mark LSB
61: 001F INLWMX EQU R31 ; input buffer low water mark
62: 0020 INHWMH EQU R32 ; input buffer low water mark MSB
63: 0021 INHWML EQU R33 ; input buffer low water mark LSB
64: 0021 INHWMX EQU R33 ; input buffer low water mark
65: 0022 INSTA1H EQU R34 ; input buffer start - 1 MSB
66: 0023 INSTA1L EQU R35 ; input buffer start - 1 LSB
67: 0023 INSTA1 EQU R35 ; input buffer start - 1
68: 0024 INENDH EQU R36 ; input buffer end MSB
69: 0025 INENDL EQU R37 ; input buffer end LSB
70: 0025 INEND EQU R37 ; input buffer end
71: 0026 OUTEN1H EQU R38 ; output buffer end + 1 MSB
72: 0027 OUTEN1L EQU R39 ; output buffer end + 1 LSB
73: 0027 OUTEND1 EQU R39 ; output buffer end + 1
74: 0028 INSTAH EQU R40 ; input buffer start MSB
75: 0029 INSTAL EQU R41 ; input buffer start LSB
76: 0029 INSTA EQU R41 ; input buffer start
77: 002A OUTSTAH EQU R42 ; output buffer start MSB
78: 002B OUTSTAL EQU R43 ; output buffer start LSB
79: 002B OUTSTA EQU R43 ; output buffer start
80: 002D PSP0256 EQU R45 ; SP0256 base pointer
81: 002F PPARINP EQU R47 ; Parallel input base pointer
82: 0030 JEPROMH EQU R48 ; EPROM jump vector MSB
83: 0031 JEPROM EQU R49 ; EPROM jump vector
84: 0032 OUTHWM EQU R50 ; output buffer high water mark
85: 0033 INFREEH EQU R51 ; number of free bytes in input buffer MSB
86: 0034 INFREEL EQU R52 ; number of free bytes in input buffer LSB
87: 0034 INFREE EQU R52 ; number of free bytes in input buffer
88: 0035 OUTFREH EQU R53 ; number of free bytes in output buffer MSB
89: 0036 OUTFREL EQU R54 ; number of free bytes in output buffer LSB
90: 0036 OUTFREE EQU R54 ; number of free bytes in output buffer
91: 0037 MATCHED EQU R55 ; matched chars counter
92: 0038 INLENH EQU R56 ; number of bytes in input buffer MSB
93: 0039 INLENL EQU R57 ; number of bytes in input buffer LSB
94: 0039 INLEN EQU R57 ; number of bytes in input buffer
95:
96: ; I/O ports...
97: 0100 IOCNT0 EQU P0 ; I/O Control register 0
98: 0104 APORT EQU P4 ; Port A
99: 0106 BPORT EQU P6 ; Port B
100: 0110 IOCNT1 EQU P16 ; I/O Control register 1
101: 0111 SSTAT EQU P17 ; read - Serial port Status
102: 0111 SMODE EQU P17 ; 1st write - Serial port Mode
103: 0111 SCTL0 EQU P17 ; 2nd and subsequent writes - Serial port Control register 0
104: 0114 T3DATA EQU P20 ; Timer 3 Data
105: 0115 SCTL1 EQU P21 ; Serial Control register 1
106: 0116 RXBUF EQU P22 ; Serial Receive Buffer
107: 0117 TXBUF EQU P23 ; Serial Transmit Buffer
108:
109:
110:
111:
112:
113: ;==============================================================================
114:
115: F000 AORG >F000
116:
117: ;==============================================================================
118:
119: ; Main entry point
120: F000 523A CTS256 MOV %>3A,B
121: F002 0D LDSP ; Init stack pointer 3B-XX
122: F003 8820002D MOVD %SP0256,PSP0256 ; PSP0256 := $2000 - Memory-mapped parallel output to SP0256A-AL2
123: F007 A2AA00 MOVP %>AA,IOCNT0 ; IOCNT0 = IOCNT0 := 1010 1010
124: ; Full Expansion;
125: ; Clear INT1, INT2 and INT3 flags
126: F00A A20A10 MOVP %>0A,IOCNT1 ; IOCNT1 = IOCNT1 := 0000 1010
127: ; Clear INT4 and INT5 flags
128: F00D 9104 MOVP APORT,B ; Read APORT = APORT
129: F00F 5307 AND %>07,B ; Get Serial mode
130: F011 5D00 CMP %>00,B ; Is it Parallel mode?
131: ; useful?
132: ; Jump if yes
133: F013 E239 JZ PARALL ; Start in parallel mode
134: F015 737F0A AND %>7F,FLAGS1 ; Clear FLAGS1.7, indicating serial mode
135: F018 8004 MOVP APORT,A ; Read APORT = APORT
136: F01A 2308 AND %>08,A ; Get Selectable Serial Config flag
137: F01C 2D00 CMP %>00,A ; Is it set?
138: ; useful?
139: ; Jump if not
140: F01E E207 JZ SER7N2 ; Serial fixed 7N2 config
141: F020 8A1000 LDA @>1000 ; Read serial config from $1000
142: F023 8211 MOVP A,SMODE ; Init P17 = SMODE with serial config
143: F025 E003 JMP SERSEL ; Serial selectable config
144:
145: F027 A2CB11 SER7N2 MOVP %>CB,SMODE ; P17 = SMODE := Fixed Serial 7N2 config
146: F02A A21511 SERSEL MOVP %>15,SCTL0 ; P17 = SCTL0 := OOO1 O1O1
147: ; Reset error flags; enable RX & TX
148: ; A := value for SCTL1 (prescaler)
149: F02D AAF03E LDA @SCT1TB(B) ; Table of values for SCTL1
150: F030 B8 PUSH A
151: ; A := value for T3DATA (timer3 reload)
152: F031 AAF046 LDA @T3DATB(B) ; Table of timer3 reload values T3DATA
153: F034 C9 POP B
154: F035 9215 MOVP B,SCTL1 ; set SCTL1
155: F037 8214 MOVP A,T3DATA ; set T3DATA
156: F039 A40110 ORP %>01,IOCNT1 ; enable T4
157: ; proceed with RAM setup
158: F03C E01A JMP INIRAM ; Init RAM config
159:
160: ; Table of values for SCTL1
161: F03E FF404340 SCT1TB BYTE >FF,>40,>43,>40,>43,>40,>40,>40
43404040
162:
163: ; Table of timer3 reload values T3DATA
164: F046 FF205707 T3DATB BYTE >FF,>20,>57,>07,>C2,>0F,>81,>03
C20F8103
165:
166: ; Start in parallel mode
167: F04E 74800A PARALL OR %>80,FLAGS1 ; Set FLAGS1.7, indicating parallel mode
168: F051 8802002F MOVD %PARINP,PPARINP ; PPARINP := $0200 parallel input mapped address
169: F055 A43000 ORP %>30,IOCNT0 ; IOCNT0 = IOCNT0, set .4=enable INT3, .5=clear INT3
170: ; Init RAM config
171: F058 9104 INIRAM MOVP APORT,B ; B := APORT = APORT
172: F05A 5310 AND %>10,B ; test APORT.4 = RAM buffer - 0=internal - 1=external
173: F05C 5D00 CMP %>00,B ; useful?
174: ; jump if internal
175: F05E E259 JZ INTRAM ; init internal RAM pointers
176:
177: F060 88300003 MOVD %CTSXRAM,INRD ; INRD := base RAM address = $3000
178: F064 980329 MOVD INRD,INSTA ; INSTA := INRD
179: F067 D802 PUSH INRDH
180: F069 D202 DEC INRDH
181: F06B 420222 MOV INRDH,INSTA1H ; INSTA1 := INRD - 1 ($2FFF)
182: F06E 72FF23 MOV %>FF,INSTA1L
183: F071 780202 ADD %>02,INRDH ; INRDH += 2 ($31)
184: F074 D517 CLR COUNTER ; COUNTER := 0 (page counter)
185: ; Init external RAM sizing loop
186:
187: F076 D302 IRAML0 INC INRDH ; ++INRDH
188: F078 7DF002 CMP %>F0,INRDH ; INRDH == $F0 ($F000 reached)?
189: ; Exit loop if yes
190: F07B E21E JZ IRAMX0
191: F07D D317 INC COUNTER ; ++COUNTER
192: F07F 7D1017 CMP %>10,COUNTER ; COUNTER == $10 (16 pages)?
193: ; exit loop if yes
194: F082 E217 JZ IRAMX0
195: F084 225A MOV %>5A,A ; A := $5A (RAM test pattern)
196: F086 9B03 STA *INRD ; *INRD := A
197: F088 B5 CLR A ; A := 0 (useful?)
198: F089 9A03 LDA *INRD ; A := *INRD
199: F08B 2D5A CMP %>5A,A ; A == $5A (test pattern)?
200: ; exit loop if not
201: F08D E60C JNZ IRAMX0
202: F08F B7 SWAP A ; A := $A5 (reverse bits)
203: F090 9B03 STA *INRD ; *INRD := A
204: F092 B5 CLR A ; A := 0 (useful?)
205: F093 9A03 LDA *INRD ; A := *INRD
206: F095 2DA5 CMP %>A5,A ; A == $A5 (test pattern)?
207: ; exit loop if not
208: F097 E602 JNZ IRAMX0
209: ; Test next RAM page
210: F099 E0DB JMP IRAML0
211:
212: F09B 420226 IRAMX0 MOV INRDH,OUTEN1H ; OUTEND1 := INRDH:$00 (end RAM addr + 1)
213: F09E D527 CLR OUTEN1L ; ATTENTION: page boundary !!
214: F0A0 7A0102 SUB %>01,INRDH ; --INRDH (why not DEC INRDH?)
215: F0A3 980307 MOVD INRD,OUTRD ; OUTRD := INRD = last RAM page addr (output buffer read ptr)
216: F0A6 98072B MOVD OUTRD,OUTSTA ; OUTSTA := OUTRD (output buffer start)
217: F0A9 7A0102 SUB %>01,INRDH ; --INRDH (why not DEC INRDH?)
218: F0AC 420224 MOV INRDH,INENDH ; INEND := INRDH:$FF (input buffer end)
219: F0AF 72FF25 MOV %>FF,INENDL
220: F0B2 D902 POP INRDH ; INRDH := $30
221: F0B4 72DF32 MOV %>DF,OUTHWM ; OUTHWM := $DF
222: F0B7 E01D JMP INIROM ; Init EPROM
223:
224: ; init internal RAM pointers
225: F0B9 88005129 INTRAM MOVD %>0051,INSTA ; INSTA := $0051 (input buffer start)
226: F0BD 88006525 MOVD %>0065,INEND ; INEND := $0065 (input buffer end)
227: F0C1 88005023 MOVD %>0050,INSTA1 ; INSTA1 := $0050 (input buffer start - 1)
228: F0C5 8800662B MOVD %>0066,OUTSTA ; OUTSTA := $0066 (output buffer start)
229: F0C9 88008027 MOVD %>0080,OUTEND1 ; OUTEND1 := $0080 (end RAM addr + 1)
230: F0CD 982903 MOVD INSTA,INRD ; INRD := $0051 (input buffer read ptr)
231: F0D0 982B07 MOVD OUTSTA,OUTRD ; OUTRD := $0066 (output buffer read ptr)
232: F0D3 720132 MOV %>01,OUTHWM ; OUTHWM := $01 (output high water mark)
233:
234: ; Init EPROM
235: F0D6 88000013 INIROM MOVD %>0000,PEPROM ; PEPROM := 0
236: F0DA C5 LF0DA CLR B ; B := 0 (5 signature bytes counter/index)
237: F0DB 781012 ADD %>10,PEPROMH ; ++PEPROMH (next page, starting at $1000)
238: F0DE 7DF012 CMP %>F0,PEPROMH ; $F0 reached? (ending at $F000)
239: ; Jump if yes
240: F0E1 E217 JZ INITOK ; Done peripherals init
241: F0E3 9A13 LF0E3 LDA *PEPROM ; Read signature byte
242: ; and compare it to the 5 first letters flags $80,$48,$28,$58,$85
243: F0E5 ADF526 CMPA @LTFLGS(B) ; Letter flags
244: ; next page if mismatch
245: F0E8 E6F0 JNZ LF0DA
246: F0EA C3 INC B ; next test byte
247: F0EB 5D05 CMP %>05,B ; done 5 bytes
248: ; Exit if yes => EPROM found
249: F0ED E204 JZ STAROM ; Boot in EPROM
250: F0EF D313 INC PEPROML ; next EPROM byte
251: F0F1 E0F0 JMP LF0E3 ; loop
252:
253: ; Boot in EPROM
254: F0F3 D313 STAROM INC PEPROML ; point to 1st byte following sig bytes
255: F0F5 981331 MOVD PEPROM,JEPROM ; JEPROM := PEPROM = EPROM entry point
256: F0F8 9C31 BR *JEPROM ; Boot in EPROM
257:
258: ; Done peripherals init
259: F0FA 720030 INITOK MOV %>00,JEPROMH ; JEPROMH := 0 (EPROM not present)
260: F0FD 8EF143 CALL @INIPTR ; Init buffer pointers and regs
261: F100 8EF1AC CALL @SAYOK ; Say O.K.
262: F103 E00B JMP LF110
263:
264: ;==============================================================================
265:
266: ; Polling loop
267: F105 76010B07 POLL BTJO %>01,FLAGS2,LF110 ; test FLAGS2.0 = any delimiter; jump if yes
268: F109 73EF0B AND %>EF,FLAGS2 ; reset FLAGS2.4 (found delimiter?)
269:
270: ; Idle loop (wait interrupt?)
271: F10C 77100BFC WTIDLE BTJZ %>10,FLAGS2,WTIDLE ; Idle loop (wait FLAGS2.4)
272: F110 4D0305 LF110 CMP INRDL,INWRL ; Input buffer read ptr LSB != write ptr LSB?
273: F113 E607 JNZ ENDPOL ; Exit polling loop if yes
274: F115 4D0204 CMP INRDH,INWRH ; Idem for MSB?
275: F118 E602 JNZ ENDPOL ; Exit polling loop if yes
276: F11A E0E9 JMP POLL ; Polling loop
277:
278: ; Exit polling loop
279: F11C 7D0038 ENDPOL CMP %>00,INLENH ; Chars in buffer MSB
280: F11F E605 JNZ LF126 ; exit ENDPOL loop if != 0
281: F121 7D0039 CMP %>00,INLENL ; Chars in buffer LSB
282: F124 E2F6 JZ ENDPOL ; loop if == 0
283:
284: ; Exit ENDPOL loop
285: F126 77080B09 LF126 BTJZ %>08,FLAGS2,LF133 ; FLAGS2.3 == 1 (output buffer full or too high)? Jump if not
286: F12A 7D0132 CMP %>01,OUTHWM ; Internal RAM?
287: ; jump if yes
288: F12D E211 JZ CLBUF1 ; Clear buffers if yes
289:
290: ; wait reset of bit 3 of FLAGS2
291: F12F 76080BFC W11B3 BTJO %>08,FLAGS2,W11B3 ; wait reset of bit 3 of FLAGS2 (output buffer low enough)
292: F133 8EF3E7 LF133 CALL @ENCODE ; Encode text to allophones
293: F136 4D0709 CMP OUTRDL,OUTWRL ; Output buffer empty?
294: F139 E2D5 JZ LF110 ; jump to input buffer polling loop if yes
295: F13B A40100 ORP %>01,IOCNT0 ; enable INT1* (SP0256) to send output
296: F13E E0D0 JMP LF110 ; jump to input buffer polling loop
297:
298: ; Clear buffers
299: F140 8CF1F0 CLBUF1 BR @CLBUF ; clear buffers - reinit
300:
301: ;==============================================================================
302:
303: ; Init buffer pointers and regs
304: F143 73000B INIPTR AND %>00,FLAGS2 ; FLAGS2 := 0 (why not CLR FLAGS2?)
305: F146 D537 CLR MATCHED ; MATCHED := 0 (matched chars to discard)
306: F148 D538 CLR INLENH ; INLENH := 0
307: F14A D539 CLR INLENL ; INLENL := 0
308: F14C A40106 ORP %>01,BPORT ; set BPORT.0 (DSR/BUSY)
309: F14F 982903 MOVD INSTA,INRD ; INRD := INSTA (input buffer start)
310: F152 982B07 MOVD OUTSTA,OUTRD ; OUTRD := OUTSTA (output buffer start)
311: F155 2220 MOV %>20,A ; A := $20
312: F157 9B03 STA *INRD ; *INRD := $20 (input buffer read ptr)
313: F159 8EF72B CALL @INCINRD ; inc INRD and roll to INSTA if == OUTSTA
314: F15C 980305 MOVD INRD,INWR ; INWR := INRD (input buffer write ptr)
315: F15F D803 PUSH INRDL ; save pointers
316: F161 D807 PUSH OUTRDL
317: F163 D806 PUSH OUTRDH
318: F165 D203 DEC INRDL ; OUTRD := ( OUTRD - INRD + 1 ) = input buffer size
319: F167 4A0307 SUB INRDL,OUTRDL
320: F16A 4B0206 SBB INRDH,OUTRDH
321: F16D 980734 MOVD OUTRD,INFREE ; INFREE := input buffer size - 1
322: F170 DB34 DECD INFREE
323: F172 B0 TSTA ; = CLR C
324: F173 DD06 RRC OUTRDH ; OUTRD /= 2
325: F175 DD07 RRC OUTRDL
326: F177 98071F MOVD OUTRD,INLWMX ; INLWMX := buffer size / 2 (and clears C)
327: F17A DD06 RRC OUTRDH ; OUTRD /= 2
328: F17C DD07 RRC OUTRDL
329: F17E B0 TSTA ; = CLR C
330: F17F DD06 RRC OUTRDH ; OUTRD /= 2
331: F181 DD07 RRC OUTRDL
332: F183 980721 MOVD OUTRD,INHWMX ; INHWMX := buffer size / 8
333: F186 D906 POP OUTRDH ; restore pointers
334: F188 D907 POP OUTRDL
335: F18A D903 POP INRDL
336: F18C 980709 MOVD OUTRD,OUTWR ; OUTWR := OUTRD = output buffer write ptr
337: F18F 980319 MOVD INRD,LSTDELM ; LSTDELM last delimiter ptr := INRD input buffer read ptr
338: F192 982736 MOVD OUTEND1,OUTFREE ; OUTFREE := OUTEND1 = end RAM address + 1
339: F195 4A2B36 SUB OUTSTAL,OUTFREE ; OUTFREE := ( OUTFREE - OUTSTA ) = output buffer size
340: F198 4B2A35 SBB OUTSTAH,OUTFREH
341: F19B 9104 MOVP APORT,B ; B := APORT
342: F19D 5380 AND %>80,B ; APORT.7 set? (Delimiter=any)
343: F19F 5D00 CMP %>00,B ; useful?
344: ; Jump if not
345: F1A1 E203 JZ LF1A6
346: F1A3 74010B OR %>01,FLAGS2 ; FLAGS2.0 := 1 if any delimiter
347: F1A6 05 LF1A6 EINT ; enable interrupts
348: F1A7 0A RETS
349:
350: ;==============================================================================
351:
352: ; "O-K\n"
353: F1A8 4F2D4B STROK TEXT 'O-K'
354: F1AB 0D BYTE >0D
355:
356: ; Say O.K.
357: AUDIBLE ; from datasheet
358: F1AC 73F90A SAYOK AND %>F9,FLAGS1 ; Clear FLAGS1.1 and FLAGS1.2: Write to input buffer
359: F1AF C5 CLR B
360: F1B0 AAF1A8 LF1B0 LDA @STROK(B) ; Get char
361: F1B3 8EF1E2 CALL @STINPB ; Store char in input buffer
362: F1B6 C3 INC B ; next char
363: F1B7 5D04 CMP %>04,B ; loop until 4 chars processed
364: F1B9 E6F5 JNZ LF1B0
365: F1BB 0A RETS ; return
366:
367: ;==============================================================================
368:
369: ; INT4 handler (serial interrupt)
370: F1BC A6021101 INT4 BTJOP %>02,SSTAT,INT3 ; Jump if P17.1 (RXRDY) == 1
371: F1C0 0B RETI ; else return from interrupt
372:
373: ; INT3 handler (parallel interrupt)
374: F1C1 B8 INT3 PUSH A ; save A from interrupt
375: F1C2 76800A0B BTJO %>80,FLAGS1,LF1D1 ; FLAGS1.7 (parallel mode) == 1? Jump if yes
376: F1C6 A3FE10 ANDP %>FE,IOCNT1 ; Reset IOCNT1.0 (disable serial INT4)
377: ; wait RXBUF ready with new character
378: F1C9 A70211FC WRXRDY BTJZP %>02,SSTAT,WRXRDY ; wait RXBUF ready with new character
379: F1CD 8016 MOVP RXBUF,A ; get A := RXBUF incoming character
380: F1CF E005 JMP LF1D6 ; handle incoming char in A
381:
382: ; Parallel mode
383: F1D1 A3EF00 LF1D1 ANDP %>EF,IOCNT0 ; Disable IOCNT0.0 = INT3*
384: F1D4 9A2F LDA *PPARINP ; Read char from parallel input ($0200)
385:
386: ; Handle incoming char
387: F1D6 8EF1E2 LF1D6 CALL @STINPB ; Store char in input buffer
388: F1D9 B9 POP A ; restore A from interrupt
389: F1DA 76200B03 BTJO %>20,FLAGS2,LF1E1 ; FLAGS2.5 == 1? (input buffer full) skip next instr if yes
390: F1DE 8EF28C CALL @ENINT ; re-enable parallel or serial interrupt
391: F1E1 0B LF1E1 RETI ; return from interrupt
392:
393: ;==============================================================================
394:
395: ; Store char in input buffer
396: F1E2 C8 STINPB PUSH B ; Save registers
397: F1E3 D80A PUSH FLAGS1
398: F1E5 D80C PUSH BUFPTRH
399: F1E7 D80D PUSH BUFPTRL
400: F1E9 73F90A AND %>F9,FLAGS1 ; reset FLAGS1.1 and FLAGS1.2: write to input buffer
401: F1EC 2D1B CMP %>1B,A ; <ESC>? => clear buffers
402: F1EE E614 JNZ NOTESC ; Skip if not
403:
404: ; clear buffers - reinit
405: F1F0 A3FE00 CLBUF ANDP %>FE,IOCNT0 ; Disable INT1* (SP0256)
406: F1F3 8EF143 CALL @INIPTR ; Init buffer pointers and regs
407: F1F6 523A MOV %>3A,B ; Init SP
408: F1F8 0D LDSP ;
409: F1F9 982D1B MOVD PSP0256,ISP0256 ; R26:27 := R44:45 (SP0256 device)
410: F1FC 9B1B STA *ISP0256 ; *R26:27 := A (SP0256 device)
411: F1FE 8EF28C CALL @ENINT ; Enable input interrupt (parallel or serial)
412: F201 8CF105 BR @POLL ; Polling loop
413:
414: ; Not <ESC>
415: F204 2D12 NOTESC CMP %>12,A ; <Ctrl-R>? => backspace until last delimiter
416: F206 E619 JNZ NOTCTR ; Skip if not
417:
418: ; Handle <Ctrl-R>
419: F208 76010B12 BTJO %>01,FLAGS2,LF21E ; FLAGS2.0 == 1 (any delimiter)? Exit if yes
420: F20C 4A1903 SUB LSTDLML,INRDL ; INRD (input buf read ptr) -= LSTDELM (last delimiter)
421: F20F 4B1802 SBB LSTDLMH,INRDH ; (may not work correctly if rolled...)
422: F212 4A0334 SUB INRDL,INFREEL ; INFREE (input buffer free size) -= INRD
423: F215 4B0233 SBB INRDH,INFREEH
424: F218 981903 MOVD LSTDELM,INRD ; INRD := LSTDELM (last delimiter position)
425: F21B 720139 MOV %>01,INLENL ; input buffer counter LSB(why?) := 1
426: F21E 8CF284 LF21E BR @XSTINP ; exit handler
427:
428: ; Not <Ctrl-R>
429: F221 2D08 NOTCTR CMP %>08,A ; <BkSp>?
430: F223 E623 JNZ NOTBKS ; Skip if not
431:
432: ; Handle <BkSp>
433: F225 4D0204 CMP INRDH,INWRH ; Input buffer pointers equal?
434: F228 E605 JNZ LF22F
435: F22A 4D0305 CMP INRDL,INWRL
436: F22D E255 JZ XSTINP ; If yes, exit handler
437: F22F D803 LF22F PUSH INRDL ; Save INRD
438: F231 D802 PUSH INRDH
439: F233 980503 MOVD INWR,INRD ; INRD := INWR input buffer write ptr
440: F236 8EF73B CALL @DECINRD ; dec INRD and roll if needed
441: F239 980305 MOVD INRD,INWR ; INWR := INRD
442: F23C D902 POP INRDH ; restore INRD
443: F23E D903 POP INRDL
444: F240 D334 INC INFREEL ; Inc INFREE input buffer free size
445: F242 E740 JNC XSTINP
446: F244 D333 INC INFREEH
447: F246 E03C JMP XSTINP ; exit handler
448:
449: ; Not <BkSp>: Handle other chars
450: F248 2D27 NOTBKS CMP %>27,A ; '''?
451: F24A E226 JZ STOCHR ; Jump if yes
452: F24C 2D7B CMP %>7B,A ; higher than 'z'?
453: F24E E40C JP DELIMT ; Jump if yes
454: F250 2D30 CMP %>30,A ; '0'..'9'?
455: F252 E108 JN DELIMT
456: F254 2D3A CMP %>3A,A
457: F256 E11A JN STOCHR
458: F258 2D41 CMP %>41,A ; >= 'A'?
459: F25A E516 JPZ STOCHR
460:
461: ; Delimiter (not letter/digit/')
462: F25C 76010B07 DELIMT BTJO %>01,FLAGS2,LF267 ; FLAGS2.0 set (any delimiter)? Jump if yes
463: F260 2D0D CMP %>0D,A ; <CR>?
464: F262 E606 JNZ LF26A ; skip if not
465: F264 74100B OR %>10,FLAGS2 ; FLAGS2.4 := 1 (found CR => exit idle loop)
466: F267 980319 LF267 MOVD INRD,LSTDELM ; LSTDELM := INRD (last delimiter position)
467: F26A 2480 LF26A OR %>80,A ; A.7 := 1 (set high bit) if delimiter
468: F26C D339 INC INLENL ; Increment INFREE (# of bytes in input buffer)
469: F26E E702 JNC STOCHR ; put char in buffer
470: F270 D338 INC INLENH
471:
472: ; put char in buffer
473: F272 8EF298 STOCHR CALL @RWBUFR ; write char in buffer
474: F275 77200B0B BTJZ %>20,FLAGS2,XSTINP ; FLAGS2.5 set (inp buffer full)? if not exit handler
475: F279 228D MOV %>8D,A ; A := <CR> + $80
476: F27B D339 INC INLENL ; Increment INFREE (# of bytes in input buffer)
477: F27D E702 JNC DINC1
478: F27F D338 INC INLENH
479: F281 8EF298 DINC1 CALL @RWBUFR ; write char in buffer
480: ; exit handler
481: F284 D90D XSTINP POP BUFPTRL ; Restore registers
482: F286 D90C POP BUFPTRH
483: F288 D90A POP FLAGS1
484: F28A C9 POP B
485: F28B 0A RETS ; end of input char handling
486:
487: ;==============================================================================
488:
489: ; FLAGS1:7 ? (enable INT3) : (enable INT4)
490: F28C 77800A04 ENINT BTJZ %>80,FLAGS1,ENINT4 ; enable INT4
491: F290 A41000 ORP %>10,IOCNT0
492: F293 0A RETS
493:
494: ; enable INT4
495: F294 A40110 ENINT4 ORP %>01,IOCNT1
496: F297 0A RETS
497:
498: ;==============================================================================
499:
500: ; select input or output buffer and read/store byte in it
501: F298 76020A2E RWBUFR BTJO %>02,FLAGS1,RDBUF ; FLAGS1.1 set? Jump if yes (read from either buffer)
502:
503: ; write to input or output buffer
504: F29C 76040A07 BTJO %>04,FLAGS1,WROBUF ; FLAGS1.2 set? Jump if yes (output buffer)
505:
506: ; write to input buffer
507: F2A0 98050D MOVD INWR,BUFPTR ; BUFPTR := INWR input buffer write ptr
508: F2A3 DB34 DECD INFREE ; Decrement # of free input buffer bytes
509: F2A5 E005 JMP WRBUF ; Store A in buffer
510:
511: ; write to output buffer
512: F2A7 98090D WROBUF MOVD OUTWR,BUFPTR ; BUFPTR := OUTWR output buffer write ptr
513: F2AA DB36 DECD OUTFREE ; Decr output buffer free size
514:
515: ; Write byte A to buffer
516: F2AC 9B0D WRBUF STA *BUFPTR ; *BUFPTR := A (store byte in buffer)
517: F2AE 8A000D LDA @XBUFPTR ; A := BUFPTR (why using LDA?)
518: F2B1 78010D ADD %>01,BUFPTRL ; Increment BUFPTR
519: F2B4 79000C ADC %>00,BUFPTRH
520: F2B7 8EF311 CALL @ROLBUFP ; Roll BUFPTR if needed
521: F2BA 76040A07 BTJO %>04,FLAGS1,WOBUFX ; FLAGS1.2 set? Jump if yes (output buffer)
522: F2BE 980D05 MOVD BUFPTR,INWR ; INWR := BUFPTR (inp buffer write ptr)
523: F2C1 8EF331 WRBUFX CALL @CHKBUF ; Check if inp or out buffer full or above HWM
524: F2C4 0A RETS ; return
525:
526: F2C5 980D09 WOBUFX MOVD BUFPTR,OUTWR ; OUTWR := BUFPTR (out buffer write ptr)
527: F2C8 E0F7 JMP WRBUFX ; Check buffer and return
528:
529: ; read from input or output buffer
530: F2CA 76040A0B RDBUF BTJO %>04,FLAGS1,RDOBUF ; FLAGS1.2 set? jump if yes (output buffer)
531:
532: ; read from input buffer
533: F2CE 98030D MOVD INRD,BUFPTR ; BUFPTR := INRD input buffer read ptr
534: F2D1 76020B0D BTJO %>02,FLAGS2,RDBUF1 ; FLAGS2.1 set? Jump if yes
535: F2D5 D337 INC MATCHED ; inc MATCHED if not... (matched chars to discard)
536: F2D7 E009 JMP RDBUF1 ; Read byte
537:
538: ; read from output buffer
539: F2D9 98070D RDOBUF MOVD OUTRD,BUFPTR ; BUFPTR := OUTRD out buffer read ptr
540: F2DC D336 INC OUTFREL ; Inc OUTFREE = Out free bytes? (TODO: clarify)
541: F2DE E702 JNC RDBUF1
542: F2E0 D335 INC OUTFREH
543:
544: ; Read A from buffer
545: F2E2 9A0D RDBUF1 LDA *BUFPTR ; Read byte
546: F2E4 76040A0B BTJO %>04,FLAGS1,LF2F3 ; FLAGS1.2 set? jump if yes (out buffer)
547:
548: F2E8 278005 BTJZ %>80,A,LF2F0 ; Is high bit set? Jump if not
549: F2EB 74010A OR %>01,FLAGS1 ; FLAGS1.0 := A.7 = char high bit = delimiter flag
550: F2EE E003 JMP LF2F3
551:
552: F2F0 73FE0A LF2F0 AND %>FE,FLAGS1 ; clear FLAGS1.0 = delimiter flag
553:
554: ; Incr buffer read pointer
555: F2F3 B8 LF2F3 PUSH A
556: F2F4 8A000D LDA @XBUFPTR ; A := BUFPTR (why?)
557: F2F7 78010D ADD %>01,BUFPTRL ; increment BUFPTR
558: F2FA 79000C ADC %>00,BUFPTRH
559: F2FD 8EF311 CALL @ROLBUFP ; Roll if needed
560: F300 76040A05 BTJO %>04,FLAGS1,ROBUFX ; jump if output buffer
561:
562: ; update input buffer read ptr
563: F304 980D03 MOVD BUFPTR,INRD ; INRD := BUFPTR
564: F307 B9 POP A ; restore character
565: F308 0A RETS ; return
566:
567: ; update output buffer read ptr
568: F309 980D07 ROBUFX MOVD BUFPTR,OUTRD ; OUTRD := BUFPTR
569: F30C 8EF335 CALL @CKOBUF ; Check if output buffer full or above HWM
570: F30F B9 POP A ; restore allophone
571: F310 0A RETS
572:
573: ;==============================================================================
574:
575: ; Roll BUFPTR according to active buffer (FLAGS1.2)
576: ; - if FLAGS1.2 set (output buffer active):
577: ; to OUTSTA (out buffer start) if reached OUTEND1 (out buffer end)
578: ; - if FLAGS1.2 not set (input buffer active):
579: ; to INSTA (in buffer start) if reached OUTSTA (in buffer end)
580: F311 76040A0E ROLBUFP BTJO %>04,FLAGS1,ROLOUT ; Roll output buffer
581: ; Roll input buffer
582: F315 4D2B0D ROLINP CMP OUTSTAL,BUFPTRL
583: F318 E608 JNZ LF322
584: F31A 4D2A0C CMP OUTSTAH,BUFPTRH
585: F31D E603 JNZ LF322
586: F31F 98290D MOVD INSTA,BUFPTR
587: F322 0A LF322 RETS
588:
589: ; Roll output buffer
590: F323 4D270D ROLOUT CMP OUTEN1L,BUFPTRL
591: F326 E608 JNZ LF330
592: F328 4D260C CMP OUTEN1H,BUFPTRH
593: F32B E603 JNZ LF330
594: F32D 982B0D MOVD OUTSTA,BUFPTR
595: F330 0A LF330 RETS
596:
597: ;==============================================================================
598:
599: ; Check if inp or out buffer full or above HWM
600: F331 77040A12 CHKBUF BTJZ %>04,FLAGS1,CKIBUF ; Send XON/XOFF if needed
601:
602: ; Check if output buffer full or above high water mark
603: F335 7D0135 CKOBUF CMP %>01,OUTFREH ; Only 1 free byte in output buffer?
604: F338 E209 JZ LF343 ; jump if yes
605: F33A 4D3236 CMP OUTHWM,OUTFREL ; OUTFREE > OUTHWM? (output counter >= HWM?)
606: F33D E404 JP LF343 ; jump if yes
607: F33F 74080B OR %>08,FLAGS2 ; set FLAGS2.3 (output buffer full)
608: F342 0A RETS
609:
610: F343 73F70B LF343 AND %>F7,FLAGS2 ; reset FLAGS2.3 (output buffer not full)
611: F346 0A RETS
612:
613: ; Check if input buffer full or above high water mark
614: F347 7D0033 CKIBUF CMP %>00,INFREEH ; Free bytes in input buffer?
615: F34A E40A JP LF356 ; jump if yes
616: F34C 7D0134 CMP %>01,INFREEL
617: F34F E405 JP LF356
618: F351 74200B OR %>20,FLAGS2 ; set FLAGS2.5 (input buffer full)
619: F354 E01B JMP TXOFF ; Send XOFF, clear DTR/BUSY*
620:
621: ; Input buffer not full
622: F356 4D1E33 LF356 CMP INLWMH,INFREEH ; INFREE inp buf free bytes < 1/2 size?
623: F359 E107 JN LF362 ; Jump if yes
624: F35B E41B JP TXON ; Else send XON, set DTR/BUSY*
625: F35D 4D1F34 CMP INLWML,INFREEL
626: F360 E516 JPZ TXON
627: F362 4D2033 LF362 CMP INHWMH,INFREEH ; INFREE inp buf free bytes < 1/8 size?
628: F365 E41D JP LF384 ; Jump if not
629: F367 E105 JN LF36E ; Else Send XOFF, clear DTR/BUSY*
630: F369 4D2134 CMP INHWML,INFREEL
631: F36C E416 JP LF384
632:
633: F36E 74040B LF36E OR %>04,FLAGS2 ; set FLAGS2.2: input buffer above HWM
634:
635: ; Send XOFF, clear DTR/BUSY*
636: F371 A3FE06 TXOFF ANDP %>FE,BPORT ; clear BPORT.0 (DSR/BUSY=true)
637: F374 A21317 MOVP %>13,TXBUF ; TXBUF := XOFF
638: F377 0A RETS
639:
640: ; Send XON, set DTR/BUSY*
641: F378 73DB0B TXON AND %>DB,FLAGS2
642: F37B 8EF28C CALL @ENINT ; FLAGS1:7 = parallel mode ? (enable INT3) : (enable INT4)
643: F37E A40106 ORP %>01,BPORT ; set BPORT.0 (DSR/BUSY=false)
644: F381 A21117 MOVP %>11,TXBUF ; TXBUF := XON
645: F384 0A LF384 RETS ; Return
646:
647: ;==============================================================================
648:
649: ; INT1 handler (SP0256)
650: F385 A3FE00 INT1 ANDP %>FE,IOCNT0 ; Disable IOCNT0.0 = INT1*
651: F388 B8 PUSH A ; save regs
652: F389 C8 PUSH B
653: F38A D80A PUSH FLAGS1
654: F38C D80C PUSH BUFPTRH
655: F38E D80D PUSH BUFPTRL
656: F390 74060A OR %>06,FLAGS1 ; select "read from output buffer"
657: F393 8EF298 CALL @RWBUFR ; do the read
658: F396 982D1B MOVD PSP0256,ISP0256 ; ISP0256 := PSP0256 SP0256 base address
659: F399 48001B ADD REGA,ISP0256 ; Add allophone code to the address
660: F39C 9B1B STA *ISP0256 ; Write any byte to that address (value doesn't care)
661: F39E D90D POP BUFPTRL ; restore regs
662: F3A0 D90C POP BUFPTRH
663: F3A2 D90A POP FLAGS1
664: F3A4 C9 POP B
665: F3A5 B9 POP A
666: F3A6 4D0709 CMP OUTRDL,OUTWRL ; Buffer empty?
667: F3A9 E203 JZ LF3AE ; skip if yes
668: F3AB A40100 ORP %>01,IOCNT0 ; else enable IOCNT0.0 = INT1*
669: F3AE 0B LF3AE RETI ; return from interrupt
670:
671: ;==============================================================================
672:
673: ; select rules set
674: F3AF 2D30 SELRUL CMP %>30,A ; A >='0'?
675: F3B1 E502 JPZ SELRUL1 ; jump if yes
676: F3B3 E02A JMP SELPCT ; < '0' => rules for punctuation
677:
678: F3B5 2D3A SELRUL1 CMP %>3A,A ; A >='9'+1?
679: F3B7 E508 JPZ SELRUL2 ; jump if yes
680: F3B9 88FF8E15 MOVD %RULNUM,RULPTR ; select rules for digits
681: F3BD 73DF0A AND %>DF,FLAGS1 ; Non-letters rules
682: F3C0 0A RETS ; done
683:
684: F3C1 2D41 SELRUL2 CMP %>41,A ; A >='A'?
685: F3C3 E502 JPZ SELRUL3 ; jump if yes
686: F3C5 E018 JMP SELPCT ; < 'A' => rules for punctuation
687:
688: F3C7 2D5B SELRUL3 CMP %>5B,A ; A >='Z'+1?
689: F3C9 E504 JPZ SELRUL4 ; jump if yes
690: F3CB 74200A OR %>20,FLAGS1 ; Letters rules
691: F3CE 0A RETS
692:
693: F3CF 2D61 SELRUL4 CMP %>61,A ; A >='a'?
694: F3D1 E502 JPZ SELRUL5 ; jump if yes
695: F3D3 E00A JMP SELPCT ; < 'a' => rules for punctuation
696:
697: F3D5 2D7B SELRUL5 CMP %>7B,A ; A >='z'+1?
698: F3D7 E506 JPZ SELPCT ; jump if yes
699: F3D9 2A20 SUB %>20,A ; A -= $20 (convert to upper case)
700: F3DB 74200A OR %>20,FLAGS1 ; Letters rules
701: F3DE 0A RETS ; done
702:
703: F3DF 73DF0A SELPCT AND %>DF,FLAGS1 ; Non-letters rules
704: F3E2 88F78C15 MOVD %RLPNCT,RULPTR ; Rules for punctuation
705: F3E6 0A RETS
706:
707: ;==============================================================================
708:
709: ; Encode text to allophones
710: F3E7 7D0030 ENCODE CMP %>00,JEPROMH ; EPROM active?
711: ; Skip if not
712: F3EA E202 JZ ENCODE1
713: F3EC 9C31 BR *JEPROM ; Jump in EPROM
714:
715: F3EE 980311 ENCODE1 MOVD INRD,INRDB ; INRDB := INRD (backward input buffer read ptr)
716: F3F1 8EF74B CALL @DECINRB ; dec INRDB and roll if needed
717:
718: ; Main encoder loop
719: F3F4 8EF70F ENCODL1 CALL @FETCH ; Fetch char and mask high bit
720: F3F7 77010A05 BTJZ %>01,FLAGS1,ENCODE2 ; FLAGS2.7 := FLAGS1.0 (delimiter flag)
721: F3FB 74800B OR %>80,FLAGS2
722: F3FE E003 JMP ENCODE3
723:
724: F400 737F0B ENCODE2 AND %>7F,FLAGS2
725: F403 8EF3AF ENCODE3 CALL @SELRUL ; select rules set
726: F406 77200A11 BTJZ %>20,FLAGS1,ENCODE4 ; FLAGS1.5 set (rules for letters)? jump if no
727:
728: F40A C5 CLR B ; useful?
729: F40B 2A41 SUB %>41,A ; A -= 'A'
730: F40D 2C02 MPY %>02,A ; AB := A * 2
731: F40F 5802 ADD %>02,B ; B += 2
732: F411 AAFFBC LDA @TABRUL(B) ; Index of rules tables
733: F414 D014 MOV A,RULPTRH ; RULPTRH := MSB of letter rules table
734: F416 AAFFBD LDA @TABRU1(B) ; Index of rules tables LSB
735: F419 D015 MOV A,RULPTRL ; RULPTRL := LSB of letter rules table
736:
737: F41B 5201 ENCODE4 MOV %>01,B ; B := 1 (number of '[') to seek
738: F41D 8EF488 CALL @RSEEKB ; right seek 1st '['
739:
740: ; Loop 2: Compare chars between [ ]
741: F420 8EF4C2 ENCODL2 CALL @CMPBKT ; compare in-brackets
742: F423 76100A40 BTJO %>10,FLAGS1,ENCODF1 ; FLAGS1.4 set (match failed)? Jump if yes
743:
744: ; Check patterns after ]
745: F427 98111D MOVD INRDB,INRDLB ; INRDLB := INRDB (save backward input buffer read ptr)
746: F42A 73BF0A AND %>BF,FLAGS1 ; clear FLAGS1.6 (read input using INRD)
747: F42D 8EF564 CALL @CHKPAT ; Check rule pattern
748: F430 76100A33 BTJO %>10,FLAGS1,ENCODF1 ; FLAGS1.4 set (match failed)? Jump if yes
749:
750: ; Check patterns before [
751: F434 8EF47E CALL @LSEEKB ; left seek '['
752: F437 74400A OR %>40,FLAGS1 ; set FLAGS1.6 (read input using INRDB)
753: F43A 8EF564 CALL @CHKPAT ; Check rule pattern
754: F43D 76100A39 BTJO %>10,FLAGS1,ENCODF2 ; FLAGS1.4 set (match failed)? Jump if yes
755:
756: ; Matching Rule found
757: F441 483734 ADD MATCHED,INFREEL ; INFREE += MATCHED (discard preceding chars)
758: F444 790033 ADC %>00,INFREEH
759: F447 D537 CLR MATCHED ; no more chars to discard
760:
761: ; Seek allophones to output
762: F449 73FD0B AND %>FD,FLAGS2 ; clear FLAGS2.1 (allow to count chars to discard in MATCHED)
763: F44C 5202 MOV %>02,B ; B := 2 (number of '[') to seek
764: F44E 8EF488 CALL @RSEEKB ; right seek 2nd '[' => 1st allophone
765:
766: ; Write allophones
767: F451 8EF49E CALL @WRALLO ; Write allophones
768:
769: ; Next input character
770: F454 980F03 MOVD INRDP,INRD ; INRD := INRDP - restore input buffer read ptr
771: F457 980311 MOVD INRD,INRDB ; INRDB := INRD - copy to backward input buffer read ptr
772: F45A 8EF74B CALL @DECINRB ; dec INRDB and roll to INEND if == INSTA1
773: F45D 77800B93 BTJZ %>80,FLAGS2,ENCODL1 ; High bit of char was set (delimiter)? Jump if not
774:
775: ; Finalize and return
776: F461 DB39 DECD INLEN ; dec INFREE (number of bytes in input buffer?)
777: F463 8EF347 CALL @CKIBUF ; Check if input buffer full or above high water mark
778: F466 0A RETS ; return
779:
780: ; Match failed after opening [ => seek next rule
781: F467 D315 ENCODF1 INC RULPTRL ; inc RULPTR rule pointer
782: F469 E702 JNC DINC2
783: F46B D314 INC RULPTRH
784: F46D 5202 DINC2 MOV %>02,B ; B := 2 (number of '[') to seek
785:
786: ; Loop: Seek next rule opening [
787: F46F 8EF488 ENCODL3 CALL @RSEEKB ; right seek 2nd or 3rd '[' => next pattern '['
788: F472 720137 MOV %>01,MATCHED ; MATCHED := 1 (one char to discard)
789: F475 73FD0B AND %>FD,FLAGS2 ; clear FLAGS2.1 (allow to count chars to free in MATCHED)
790: F478 E0A6 JMP ENCODL2 ; check next rule
791:
792: ; Match failed before opening [ => seek next rule
793: F47A 5203 ENCODF2 MOV %>03,B ; B := 3 (number of '[') to seek
794: F47C E0F1 JMP ENCODL3 ; right seek 3rd '[' and check next rule
795:
796: ;==============================================================================
797:
798: ; left seek '['
799: F47E 9A15 LSEEKB LDA *RULPTR ; A := *RULPTR
800: F480 274001 BTJZ %>40,A,LSEEBB1 ; A.6 set ('[' found)? jump if not
801: F483 0A RETS ; else return
802:
803: F484 DB15 LSEEBB1 DECD RULPTR ; dec RULPTR
804: F486 E0F6 JMP LSEEKB ; and loop
805:
806: ;==============================================================================
807:
808: ; right seek Bth '['
809: F488 D517 RSEEKB CLR COUNTER ; COUNTER := 0
810:
811: F48A 9A15 RSEEKB1 LDA *RULPTR ; A := *RULPTR
812: F48C 274007 BTJZ %>40,A,RSEEKB2 ; A.6 set ('[' found)? jump if not
813: F48F D317 INC COUNTER ; inc COUNTER
814: F491 3D17 CMP COUNTER,B ; jump if COUNTER != B
815: F493 E601 JNZ RSEEKB2
816: F495 0A RETS ; else return: found
817:
818: F496 D315 RSEEKB2 INC RULPTRL ; inc RULPTR
819: F498 E702 JNC DINC3
820: F49A D314 INC RULPTRH
821: F49C E0EC DINC3 JMP RSEEKB1 ; and loop
822:
823: ;==============================================================================
824:
825: ; Write allophones
826: F49E D517 WRALLO CLR COUNTER ; COUNTER := 0 (flag for exit)
827: F4A0 9A15 LDA *RULPTR ; A := *RULPTR
828: F4A2 2DFF CMP %>FF,A ; A == $FF?
829: F4A4 E21B JZ WRALLOX ; exit if yes: no allophone to send
830: F4A6 278002 BTJZ %>80,A,WRALLO1 ; A.7 set (']' found)? jump if not
831: F4A9 D317 INC COUNTER ; else inc COUNTER
832: F4AB 233F WRALLO1 AND %>3F,A ; mask A.6 and A.7
833: F4AD 73FD0A AND %>FD,FLAGS1 ; clear FLAGS1.1 (write in buffer)
834: F4B0 74040A OR %>04,FLAGS1 ; set FLAGS1.2 (output buffer)
835: F4B3 8EF298 CALL @RWBUFR ; write allophone in buffer
836: F4B6 D315 INC RULPTRL ; inc RULPTR
837: F4B8 E702 JNC DINC4 ;
838: F4BA D314 INC RULPTRH ;
839: F4BC 7D0117 DINC4 CMP %>01,COUNTER ; ']' found?
840: F4BF E6DD JNZ WRALLO ; loop if not
841: F4C1 0A WRALLOX RETS ; else return
842:
843: ;==============================================================================
844:
845: ; compare in-brackets
846: F4C2 980313 CMPBKT MOVD INRD,INRDLX ; INRDLX := INRD (input read ptr)
847: F4C5 73F70A AND %>F7,FLAGS1 ; clear FLAGS1.3
848: F4C8 77200A08 BTJZ %>20,FLAGS1,CMPNLTR ; FLAGS1.5 letter rules? jump if not
849: F4CC 9A15 LDA *RULPTR ; A := *RULPTR
850: F4CE 2DFF CMP %>FF,A ; A == $FF? (single letter/end of rules)
851: F4D0 E60B JNZ CMPLTR ; jump if not to letter rules
852: F4D2 E02E JMP CMPEND ; else exit (success)
853:
854: ; not letter rules: check 1st char, otherwise implicit
855: F4D4 2DFF CMPNLTR CMP %>FF,A ; A == $FF?
856: F4D6 E22A JZ CMPEND ; exit if yes (success)
857: F4D8 8EF73B CALL @DECINRD ; dec INRD and roll if needed
858: F4DB D237 DEC MATCHED ; dec MATCHED (matched chars to discard)
859:
860: ; letter rules
861: F4DD 8EF70F CMPLTR CALL @FETCH ; Fetch char and mask high bit
862: F4E0 2D61 CMP %>61,A ; lower case?
863: F4E2 E102 JN CMPLTR1 ; skip if not
864: F4E4 2A20 SUB %>20,A ; else adjust to upper case
865: F4E6 2A20 CMPLTR1 SUB %>20,A ; adjust to range 00-3F
866: F4E8 C0 MOV A,B ; B := A
867: F4E9 9A15 LDA *RULPTR ; A := *RULPTR
868: F4EB 278003 BTJZ %>80,A,CMPLTR2 ; A.7 set (']' found)? Skip if not
869: F4EE 74080A OR %>08,FLAGS1 ; else set FLAGS1.3
870: F4F1 233F CMPLTR2 AND %>3F,A ; mask A.6 and A.7
871: F4F3 3D00 CMP REGA,B ; A == B?
872: F4F5 E207 JZ CPMATCH ; jump if yes
873: F4F7 74100A OR %>10,FLAGS1 ; set FLAGS1.4: pattern match failed
874: F4FA 981303 MOVD INRDLX,INRD ; INRD := INRDLX
875: F4FD 0A RETS ; return (failed)
876:
877: F4FE 77080A0A CPMATCH BTJZ %>08,FLAGS1,CMPNEXT ; FLAGS1.3 set (']' found)? Jump if not
878:
879: ; pattern match successful
880: F502 98030F CMPEND MOVD INRD,INRDP ; INRDP := INRD - save input buffer read ptr
881: F505 73EF0A AND %>EF,FLAGS1 ; clear FLAGS1.4: pattern match successful
882: F508 74020B OR %>02,FLAGS2 ; set FLAGS2.1 - forbid to count matched chars to discard
883: F50B 0A RETS ; return
884:
885: ; next letter
886: F50C D315 CMPNEXT INC RULPTRL ; inc RULPTR
887: F50E E7CD JNC CMPLTR ;
888: F510 D314 INC RULPTRH ;
889: F512 E0C9 JMP CMPLTR ; and loop: check next char
890:
891: ;==============================================================================
892:
893: ; Get letter flags
894: F514 3216 GFLAGS MOV NXTCHR,B ; B := Next char
895: F516 5D3A CMP %>3A,B ; B > 'Z'-$20?
896: F518 E40A JP GFLAGX ; exit if yes
897: F51A 5D21 CMP %>21,B ; B < 'A'-$20?
898: F51C E106 JN GFLAGX ; exit if yes
899: F51E 5A21 SUB %>21,B ; B -= 'A' (could replace the CMP above!)
900: F520 AAF526 LDA @LTFLGS(B) ; Letter flags
901: F523 0A RETS ; done
902:
903: F524 B5 GFLAGX CLR A ; non-letter => clear all flags
904: F525 0A RETS ; done
905:
906: ; Letter flags
907: ; ------------
908: ; 7(80): Vowel
909: ; 6(40): Voiced consonant
910: ; 5(20): Sibilant
911: ; 4(10): Preceding long U
912: ; 3(08): Consonant
913: ; 2(04): Front vowel
914: ; 1(02): Back vowel
915: ; 0(01): Suffix ('E')
916: F526 80 LTFLGS BYTE >80 ; A 1000 0000 - EPROM sig check begin
917: F527 48 BYTE >48 ; B 0100 1000
918: F528 28 BYTE >28 ; C 0010 1000
919: F529 58 BYTE >58 ; D 0101 1000
920: F52A 85 BYTE >85 ; E 1000 0101 - EPROM sig check end
921: F52B 08 BYTE >08 ; F 0000 1000
922: F52C 68 BYTE >68 ; G 0110 1000
923: F52D 08 BYTE >08 ; H 0000 1000
924: F52E 84 BYTE >84 ; I 1000 0100
925: F52F 78 BYTE >78 ; J 0111 1000
926: F530 08 BYTE >08 ; K 0000 1000
927: F531 58 BYTE >58 ; L 0101 1000
928: F532 48 BYTE >48 ; M 0100 1000
929: F533 58 BYTE >58 ; N 0101 1000
930: F534 82 BYTE >82 ; O 1000 0010
931: F535 08 BYTE >08 ; P 0000 1000
932: F536 08 BYTE >08 ; Q 0000 1000
933: F537 58 BYTE >58 ; R 0101 1000
934: F538 38 BYTE >38 ; S 0011 1000
935: F539 18 BYTE >18 ; T 0001 1000
936: F53A 82 BYTE >82 ; U 1000 0010
937: F53B 48 BYTE >48 ; V 0100 1000
938: F53C 48 BYTE >48 ; W 0100 1000
939: F53D 28 BYTE >28 ; X 0010 1000
940: F53E 84 BYTE >84 ; Y 1000 0100
941: F53F 78 BYTE >78 ; Z 0111 1000
942:
943: ;==============================================================================
944:
945: ; Pattern jump table
946: F540 8CF69E PATBRT BR @PATVOW ; # 09 1+ vowels
947: F543 8CF6B4 BR @PATVOC ; . 0A voiced consonant: B D G J L M N R V W X
948: F546 8CF601 BR @PATSUF ; % 0B suffix: -ER(S) -E -ES -ED -ELY -ING -OR -MENT
949: F549 8CF6D7 BR @PATSIB ; & 0C sibilant: S C G Z X J CH SH
950: F54C 8CF6E2 BR @PATPLU ; @ 0D T S R D L Z N J TH CH SH preceding long U
951: F54F 8CF6BF BR @PAT1CO ; ^ 0E 1 consonant only
952: F552 8CF6C7 BR @PATFVO ; + 0F front vowel: E I Y
953: F555 8CF5EA BR @PAT0MC ; : 10 0+ consonants
954: F558 8CF5B9 BR @PAT1MC ; * 11 1+ consonants
955: F55B 8CF6CF BR @PATBVO ; > 12 back vowel: O U
956: F55E 8CF5B0 BR @PATNLT ; < 13 Anything other than a letter
957: F561 8CF5CC BR @PAT2MV ; ? 14 2+ vowels
958:
959: ;==============================================================================
960:
961: ; Check rule pattern
962: F564 76400A0A CHKPAT BTJO %>40,FLAGS1,CKPATL1 ; FLAGS1.6 set (scan direction left)? jump if yes
963: F568 5240 MOV %>40,B ; '[' mask
964: F56A D315 INC RULPTRL ; inc RULPTR rule ptr
965: F56C E702 JNC DINC5
966: F56E D314 INC RULPTRH
967: F570 E004 DINC5 JMP CHKPAT1 ; proceed
968:
969: F572 5280 CKPATL1 MOV %>80,B ; ']' mask
970: F574 DB15 DECD RULPTR ; dec RULPTR rule ptr
971:
972: ; check if boundary has been reached
973: F576 9A15 CHKPAT1 LDA *RULPTR ; get rule char
974: F578 6712 BTJZ B,A,CKPTCHR ; is '[' or ']'? jump if not
975: F57A 76400A04 BTJO %>40,FLAGS1,CKPATL2 ; FLAGS1.6 set (scan direction left)? jump if yes
976: F57E DB15 DECD RULPTR ; dec RULPTR rule ptr
977: F580 E006 JMP DINC6
978:
979: F582 D315 CKPATL2 INC RULPTRL ; inc RULPTR rule ptr
980: F584 E702 JNC DINC6
981: F586 D314 INC RULPTRH
982: F588 73EF0A DINC6 AND %>EF,FLAGS1 ; clear FLAGS1.4 rule pattern match failed
983: F58B 0A RETS ; return
984:
985: ; check rule char
986: F58C 8EF75B CKPTCHR CALL @GNEXT ; get next input char and move code to range 00-3F
987: F58F 9A15 LDA *RULPTR ; A := *RULPTR - load rule char
988: F591 2D15 CMP %>15,A ; A < $15? (pattern symbol)
989: F593 E10F JN CHKSYMB ; jump if yes
990: F595 4D0016 CKNXCHR CMP REGA,NXTCHR ; otherwise compare input char with rule char