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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
|
;
TITLE EUMEL fuer RUC 64180, 6502 Teil & Diskroutinen
;
;****************************************************************
;
; EUMEL 1.8.0 with RUC180-Card on BASIS 108
;
; 6502 DISK-Driver und Motherboard I/O
;
; Stand (1.8) : 14.01.87, mit neuem Puffer-Handling
; : 27.05.87, mit Hardcopy auf SHIFT CTRL F12
; : 26.06.87, Druckerspooler loeschen mit Task 8
; Version 23.09.85 ./. 22.11.85
;
;****************************************************************
;
.6502
.radix 16
;
;----------------------------------------------------------------
;
; Globale Variable
;
GLOBAL DES6502, PRG6502, LEN65, ST6502
;
;----------------------------------------------------------------
;
; Konstanten
;
XOFF EQU 13 ; CTRL-S
XON EQU 11 ; CTRL-Q
;
; Adressen
;
KeyBoard equ 0C000
Keyext equ 0C008
KeyStr equ 0C010
VIDBNK equ 0C00C
prackn equ 0C1C1
prport equ 0C090
speaker equ 0C030
serial_stat equ 0C099
SER_DAT EQU 0C098H ;Serial Interface Data
SER_COM EQU 0C09AH ;Serial Command Register
SER_CTR EQU 0C09BH ;Serial Control Register
analog_1 EQU $C063
analogreset EQU $C070
; Floppy Hardware
phase0 equ 0C080
phase1 equ 0C082
phase2 equ 0C084
phase3 equ 0C086
mtroff equ 0C088
mtron equ 0C089
drive0 equ 0C08A
Q6off equ 0C08C
Q6on equ 0C08D
Rstate equ 0C08E
Wstate equ 0C08F
;
INCLUDE ZPAGE.INC ;Zero Page Adressen
;
; sonstiges
;
bit_z equ 24
fast_step equ $0E ; etwas weniger als 3 ms Track-Wechselzeit
pagerr macro adr
if high(*-start) ne high(adr-start)
.printx 'Page-Error'
endif
endm
cseg
PRG6502:
.phase 0C00
DES6502: ; 6502-Startadresse zum kopieren
start: ; Label fuer Pageboundcheck
nible1: ; Anfang des Nibble-Buffers
defm '6502-Teil'
ST6502: ; Startadresse 6502-Teil Initialisierung
include BOOT.INC
include NIBLE.INC
write_data
SEC
LDA Q6on,X
LDA Rstate,X
BMI wrdat99
LDA nible2
STA temp2
LDA #0FF
STA Wstate,X ; 5
ORA Q6off,X ; 4
PHA ; 3
PLA ; 4 [sta..sta[
NOP ; 2
LDY #04 ; 2
wrdat1 PHA ; 3 3
PLA ; 4 4
JSR wrt_nibl1 ;+13 15 13
DEY ;--- 2
BNE wrdat1 ; 40 + 3
; --- ---
; 20+ 20 = 40
pagerr wrdat1
; -1
LDA #0D5 ; 2
JSR wrt_nibl ; 15 +15
LDA #0AA ; 2 ---
JSR wrt_nibl ;+15 36
LDA #0AD ;---
JSR wrt_nibl ; 32 15
TYA ; 2
LDY #56 ; 2
wrdat11 BNE wrdat3 ; 3
wrdat2 LDA nible2,Y ; 0 4
wrdat3 EOR nible2-1,Y ; 5 5
TAX ; 2 2
LDA to_nibble,X ; 4 4
LDX slot10z ; 3 3
; --- ---
; 36 18
STA Q6on,X ; 5
LDA Q6off,X ; 4
DEY ; 2
BNE wrdat2 ; 3
; ---
; 14 + 18 = 32
; -1
LDA temp2 ; 3
NOP ; 2
wrdat4 EOR nible1,Y ; 4 4
TAX ; 2 2
LDA to_nibble,X ; 4 4
LDX slot10 ; 4 4
; --- ---
; 32 14
STA Q6on,X ; 5
LDA Q6off,X ; 4
LDA nible1,Y ; 4
INY ; 2
BNE wrdat4 ; 3
; ---
; 18+ 14 = 32
pagerr wrdat11
TAX ; 2
LDA to_nibble,X ; 4
LDX slot10z ; 3
JSR wrt_nibl2 ; 6 15
LDA #0DE ; --- 2
JSR wrt_nibl ; 32 15
LDA #0AA ; ---
JSR wrt_nibl ; 32
LDA #0EB
JSR wrt_nibl
LDA #0FF
JSR wrt_nibl
LDA Rstate,X
wrdat99
LDA Q6off,X
wrdat999
dey
bne wrdat999 ; PostErase-Delay 1 ms
RTS
read_hdr
sei
LDY #0FC
STY temp2
rdhdr0
INY
BNE rdhdr1
INC temp2
BEQ fail
rdhdr1
LDA Q6off,X
BPL rdhdr1
rdhdr11 CMP #0D5
BNE rdhdr0
NOP
rdhdr2 LDA Q6off,X
BPL rdhdr2
CMP #0AA
BNE rdhdr11
LDY #03
rdhdr3 LDA Q6off,X
BPL rdhdr3
CMP #96
BNE rdhdr11
pagerr rdhdr1
LDA #00
nxthByte STA chk_sum
rdhdr4 LDA Q6off,X
BPL rdhdr4
ROL A
STA temp2
rdhdr5 LDA Q6off,X
BPL rdhdr5
AND temp2
STA chk_in_hdr,Y
EOR chk_sum
DEY
BPL nxthbyte
TAY
BNE fail
rdhdr6 LDA Q6off,X
bpl rdhdr6
cmp #0DE
BNE fail
NOP
rdhdr7 LDA Q6off,X
BPL rdhdr7
CMP #0AA
BNE fail
CLC
RTS
fail
SEC
RTS
moving
LDY #0
mov0 LDA Q6off,X
JSR mov1
PHA ; 3
PLA ; 4
CMP Q6off,X ; 4
BNE mov1 ;----
DEY ; 21 uS
BNE mov0
mov1 RTS
read_data
TXA
ORA #8C
STA ld1+1
STA ld2+1
STA ld3+1
STA ld4+1
STA ld5+1
LDA user_data
LDY user_data+1
STA st5+1
STY st5+2
SEC
SBC #54
BCS rddat1
DEY
SEC
rddat1
STA st3+1
STY st3+2
SBC #57
BCS rddat2
DEY
rddat2
STA st2+1
STY st2+2
LDY #20
nxt_begin
DEY
BEQ fail
wait_begin
waitb0 LDA Q6off,X
BPL waitb0
waitb00 EOR #0D5
BNE nxt_begin
NOP
waitb1 LDA Q6off,X
BPL waitb1
CMP #0AA
BNE waitb00
NOP
waitb2 LDA Q6off,X
BPL waitb2
CMP #0AD
BNE waitb00
LDY #0AA
LDA #0
rloop1 STA temp2
ld1 LDX Q6off+60 ; addr modified by read init !
BPL ld1
LDA to_bits-96,X
STA nible2-0AA,Y
EOR temp2
INY
BNE rloop1
;
; read nible from disk and convert to user data
;
LDY #0AA
BNE ld2
rloop2
st2 STA 1000,Y
ld2 LDX Q6off+60 ; modified by read init
BPL ld2
EOR to_bits-96,X
LDX nible2-0AA,Y
EOR to_bytes+0,X
INY
BNE rloop2
PHA
AND #0FC
LDY #0AA
ld3 LDX Q6off+60 ; modified by read init
BPL ld3
EOR to_bits-96,X
LDX nible2-0AA,Y
EOR to_bytes+1,X
st3 STA 1000,Y
INY
BNE ld3
ld4 LDX Q6off+60 ; modified by read init
BPL ld4
AND #0FC
LDY #0AC
rloop5 EOR to_bits-96,X
LDX nible2-0AC,Y
EOR to_bytes+2,X
st5 STA 1000,Y
ld5 LDX Q6off+60 ; modified by read init
BPL ld5
INY
BNE rloop5
AND #0FC
EOR to_bits-96,X
LDX slot10z
TAY
BNE chk_fail
rloop6 LDA Q6off,X
BPL rloop6
CMP #0DE
BEQ read_ok
pagerr wait_begin
chk_fail
SEC
db bit_z
read_ok
clc
PLA
LDY #55
STA (user_data),Y
RTS
seekT lda iob_trk
seekL
jsr trk_to_ph
cmp phase0,X
cmp phase1,X
cmp phase2,X
cmp phase3,X
LDY disk_no
LDA head_table,y ; da steht der Kopf jetzt
STA head_pos
lda dest_phase
sta head_table,y ; da soll er nachher stehen
seekH
cmp head_pos
BEQ seek_rts
LDA #0
STA temp2
seekh0 LDA head_pos
STA phase
SEC
SBC dest_phase
BEQ seekh5
BCS seekh1
EOR #0FF
INC head_pos
BCC seekh2
seekh1 ADC #0FE
DEC head_pos
seekh2 CMP temp2
BCC seekh3
LDA temp2
seekh3 CMP #8
BCS seekh4
TAY
seekh4 SEC
JSR step
LDA time0,Y
JSR step_wait
LDA phase
CLC
JSR step1
LDA time1,Y
JSR step_wait
INC temp2
BNE seekh0
seekh5 JSR step_wait
CLC
step LDA head_pos
step1 AND #3
ROL A
ORA slot10z
TAX
LDA phase0,X
LDX slot10z
seek_rts RTS
;-------------------------------;
make_nibl
LDY #56
LDA #0
maken0 STA nible2-1,Y
DEY
BNE maken0
maken1 LDX #55
maken2 LDA (user_data),Y
AND #0FC
STA nible1,Y
EOR (user_data),Y
INY
CMP #02
ORA nible2,X
ROR A
ROR A
STA nible2,X
DEX
BPL maken2
CPY #02
BNE maken1
RTS
; ds 10
Dsk_RW
ldx #0A9 ; LDA #xx
lda def_byte
and #$20 ; Bit 5 ?
bne rw_0 ; Fast Step - use abs. value
; Slow Step - use MotorOn/Off-Tables
ldx #0C9 ; CMP #xx
rw_0: stx step_wait
lda #fast_step ; Set Step Rate
bit def_byte
bmi rw_1 ; Bit7: Controller-Typ
; Bit7=0 => Ehring
lsr a ; bei Ehring 2-fache Phases => halbe Steprate
rw_1: sta step_wait+1 ; Steprate
lda disk_no
LSR A
TAY
LDA slotn,Y
STA slot10
sta slot10z
adc #0
STA iob_drv
include TRACK.INC
trk_to_ph: ; IN: A = track / OUT: A,dest_phase = phase
sta dest_phase
; Select Side 0
bit def_byte ; Bit7: 1=Erphi-Controller
; Bit6: 1=Erphi-Format
bvc ehring_format ; Bit6 = 0 => Ehring-Format
lsr dest_phase ; Erphi-Format
bcc side0
; Select Side 1
; Erphi: mtroff, Q6on, mtron
; Ehring: mtroff,mtron
side1: lda mtroff,x
bit def_byte
bpl side1_2
; Erphi-Side-1-Select
lda Q6on,x
side1_2:
lda mtron,x
jmp ph_mult
ehring_format:
cmp #$50 ; Track >= 80 ?
bcc side0 ; nein: Select Side 0
sbc #$50
sta dest_phase
jmp side1
; Select Side 0
; Ehring: lda cn00,x
; Erphi : mtroff, Q6off, mtron
side0: bit def_byte
bmi erphi_s0 ; Bit7 = 1 => Erphi-Controller
txa ; Ehring-Side-0-Select
lsr a
lsr a
lsr a
lsr a
ora #$C0
sta ehr_sel+2
ehr_sel:lda $C600
jmp ph_mult
erphi_s0: ; Erphi-Side-0-Select
cmp mtroff,x
cmp Q6off,x
cmp mtron,x
ph_mult:
lda def_byte ; Bit 0..1: 0 = 1 Step/Track
and #03 ; 1 = 2 Steps/Track
tay ; 2 = 4 Steps/Track
beq ph_mult2
ph_mult1:
asl dest_phase
dey
bne ph_mult1
ph_mult2:
lda dest_phase
rts
;---------------------------------------------------------------------------
;
; D I S K R W
; Eingang: iob_trk, sektor, def_byte, disk_no, param, last_track
; dma, ilv_tbl,
; Ausgang: iob_err
; Daten: x000..xFFF (Ein Track, Sektoren in log. Reihenfolge)
; 64180 darf nicht auf den Applebus, Aufruf mit JSR
;
;---------------------------------------------------------------------------
DISKRW:
jsr lock_bus
lda iob_trk ; Track fuer Read/Write
bit param ; 0 = Write, FF = Read
bpl writecmd
cmp last_track ; Muss auf neuen Track positioniert
bne readtrack ; werden ?
ldy sektor
ldx ilv_tble,y
lda sec_tble,x
beq readtrack ; Sektor nicht ok
ldx ilv_tble+1,y
lda sec_tble,x
beq readtrack
lda #00 ; Nein, somit auch kein Lesefehler
sta iob_err
jmp unlock_bus
readtrack:
sei
lda #10 ; Track muss ganz neu gelesen werden
sta sec_cnt ; das sind 16 Sektoren a 256 Byte
lda #00 ; Kennzeichen fuer Einlesen
ldx #0F
sec_1_loop: sta sec_tble,x ; Sektortabelle = Kennzeichen setzen
dex
bpl sec_1_loop
bmi readwrite
writecmd:
sei
ldx #02 ; Bei Write nur 512 Byte schreiben
stx sec_cnt
ldx #0F
lda #$FF ; Kennzeichen fuer 'nicht Einlesen'
sec_2_loop: sta sec_tble,x
dex
bpl sec_2_loop
ldy sektor ; gewuenschter 1. Sektor
ldx ilv_tble,y ; logisch --> physisch umrechnen
lda #00 ; Kennzeichen 'Sektor schreiben'
sta sec_tble,x
ldx ilv_tble+1,y ; 2. Sektor logisch --> physisch
sta sec_tble,x ; Auch schreiben
lda last_track
cmp iob_trk ; Anderer Track als der letzte ?
beq readwrite
jsr readwrite ; Ja
lda #$FF ; Muss bei Read neu eingelesen werden,
; da die anderen 14 Sektoren zum
; letzen Track gehoeren
sta last_track
rts
readwrite:
lda #00
tay
tax
interlv_2:
ora #dma_4k ; Cachebereich (4k) fuer Track
sty dma,x
inx
sta dma,x
inx
clc
adc #0B ; Interleave 3
and #0F ; MOD 16
cpx #20 ; 16 Sektoren
bne interlv_2
lda #0F ; Step Rate
sta iob_err
jsr dsk_rw ; Disk Operation
lda iob_err ; Fehlerkennzeichen
beq no_err
ldy sektor
ldx ilv_tble,y
lda sec_tble,x
beq is_err ; Fehler im 1. Teil des Blocks ?
ldx ilv_tble+1,y
lda sec_tble,x
beq is_err ; Fehler im 2. Teil des Blocks ?
; nein,
lda #0
sta iob_err ; Zumindest dieser Block ok
beq no_err ; Always
is_err:
lda #$FF ; Track muss neu gelesen werden
db bit_a ; Skip 2 Bytes
no_err: lda iob_trk ; last_track := track
sta last_track
jmp unlock_bus
;----------------------------------------------------------------------------
;
; A N A L 6 5
; Eingang: param = 1..4 (Analogschalternummer)
; Ausgang: analogwert = 0..255
;
;---------------------------------------------------------------------------
ANAL65:
sei
jsr lock_bus
ldx param ; Nummer des Analogports
lda analogreset ; Timer starten
ldy #00
nop
nop
readanalog:
lda analog_1,x ; Analogwert lesen
bpl anaready
iny
bne readanalog ; Bis Bit 7 auf 0
pagerr readanalog
dey ; Maximum 255
anaready: sty analogwert
cli
jmp unlock_bus
;
INCLUDE GRAFIK65.MAC
;
irqvec:
sta Asave ; Akku retten
pla
pha
and #10 ; BRK -Bit ?
bne brkirq
lda Asave
jmp irq ; Interrupt ausfuehren
brkirq:
lda main_ROM
lda Asave
jmp BREAK ; Alte BREAK-Routine
resvec:
lda main_ROM ; ROM einschalten
jmp RESET ; Alte RESET-Routine
;****************************************************************
;
; B E L L
;
; => Akustisches Signal
beep sei
jsr lock_bus
lda #$32 ; Laenge
; Frequenz = 5000/X Hz
beep1 ldx param ; 3
beep2 ldy #$12 ; 2
beep3 dey ; 2
bne beep3 ; + 3
; ----
; 89 = 5 * 18 - 1
nop ; 2
nop ; 2
nop ; 2
dex ; 2
bne beep2 ; 3
; ----
; 102 * X * 0.9775 us
; = 99.7ms (f ~ 10kHz/X)
; -1 (Branch)
bit speaker ; 4
sec ; 2
sbc #1 ; 2
bne beep1 ; 3
; -----
; (14 + 102 * X) * A States Dauer
; 0.9775 * (14 + 102 * X) * A us
cli
jmp unlock_bus
;*******************************************************************
;
; Zugriffskontrolle fuer 64180 auf 6502-Bus
;
lock_bus:
lda #$FF
sta bus_locked
ldx SLOT180
lda wait180,x
rts
unlock_bus:
lda #$00
sta bus_locked
ldx SLOT180
lda start180,x
rts
;*******************************************************************
;
; Input-Buffer Handler
;
; Der Buffer darf nicht voll sein!
; Interrupts bei Receive-Buffer disabled
; Eingang: A = Zeichen
; X = Bufferdescriptor Offset
; Ausgang: X intakt
; A veraendert
; SEC, wenn Puffer voll war
putbuf:
sei
putbuf0:
pha
lda free,x ; Test, ob Puffer voll
ora free+1,x
beq putbuf4
pla
sta (in,x) ; Zeichen in Puffer schreiben
inc in,x ; Schreibzeiger erhoehen
bne putbuf1
inc in+1,x
lda in+1,x ; Puffer-Ende ?
cmp end,x
bcc putbuf1
lda beg,x ; Ringpuffer, wieder auf Pufferanfang setzen
sta in+1,x
putbuf1:
dec wait_flg ; Warten, bis update vorbei
inc full,x ; Belegten Platz vergroessern
bne putbuf2
inc full+1,x
putbuf2: ; Dieser Wert wird auch von FROUT benutzt!
lda free,x ; Freiplatz verringern
bne putbuf3
dec free+1,x
putbuf3:
dec free,x
inc wait_flg ; Update gelaufen
clc ; Zeichen uebernommen
rts
putbuf4:
pla
sec
rts ; Puffer war voll
;*******************************************************************
;
; Output-Buffer Handler
;
; Interrupts bei Transmit-Buffer disabled
; Der Buffer darf nicht leer sein!
; Eingang: X = Bufferdescriptor Offset
; Ausgang: X intakt
; A = Zeichen
; SEC, wenn Puffer leer war
getbuf:
sei
getbuf0:
sec
lda full,x
ora full+1,x
beq getbuf4 ; Test, ob Puffer leer ist
lda (out,x) ; Zeichen aus Puffer lesen
pha
inc out,x
bne getbuf1
inc out+1,x ; Lesezeiger erhoehen
lda out+1,x
cmp end,x
bne getbuf1
lda beg,x
sta out+1,x ; Ringpuffer, Zeiger wieder auf Pufferanfang
getbuf1:
dec wait_flg ; Warten, bis Update vorbei
inc free,x
bne getbuf2
inc free+1,x ; Freien Platz vergroessern
getbuf2:
lda full,x
bne getbuf3
dec full+1,x
getbuf3:
dec full,x ; Belegten Platz verringern
inc wait_flg ; Update vorbei
pla
clc
getbuf4: ; A enthaelt 00, wenn Puffer leer war
rts
;****************************************************************
;
; => Drucker-Spooler
;
;------------------------------------------------------------------
;
; Zeichen aus Druckerspooler an Drucker senden
;
spochc:
lda prackn
bmi chcend ; Printer ready ?
ldx #pbuf ; Printer Buffer
jsr getbuf0 ; Ohne SEI
bcs chcend ; Nichts auszugeben, fertig
sta prport ; Zeichen ausgeben
jmp spochc ; Bis nichts mehr moeglich ist
chcend:
rts
;--------------------------------------------------------------------
;
; Zeichen in Druckerpuffer schreiben
bufin:
ldx #pbuf ; Zeichen geht verloren, wenn Puffer voll
jmp putbuf0 ; Zeichen in Puffer schreiben
;****************************************************************
;
; => Ausgabe Spooler fuer serielle Schnittstelle
;
;-----------------------------------------------------------------
;
; Zeichen aus dem Transmitbuffer senden
;
;spsero:
; LDA serial_stat
; AND #10 ; Transmit Data Register empty ?
; BEQ schend ; serielles Interface nicht bereit
spserok: ; Einsprung fuer Transmitinterrupt
LDA SerFlg ; Ausgabe Stop ?
BMI dis_tx ; Ja -> nichts ausgeben
ldx #tbuf ; Transmitbuffer
jsr getbuf ; Zeichen aus Puffer lesen
bcs dis_tx ; Transmitter disabled, wenn Puffer leer
sta SER_DAT ; Zeichen ausgeben
schend:
rts
dis_tx:
lda ser_com
and #$F3
ora #$08 ; Transmit Interrupt aus
sta ser_com
rts
;---------------------------------------------------------------------
;
; Zeichen in den Transmitbuffer schreiben
sbufin:
ldx #tbuf ; Zeichen in Transmitbuffer schreiben
jsr putbuf ; Zeichen geht verloren, wenn Puffer voll
cli ; Wird nicht in Interruptrotinen aufgerufen
lda ser_com
and #$F3
cmp #$04 ; War Transmitinterrupt enabled ?
beq sbufin1
ora #$04 ; Enable Transmit Interrupt
sta ser_com
sbufin1:
rts
;****************************************************************
;
; Eingabe Spooler fuer serielle Schnittstelle
;
;-----------------------------------------------------------------
;
; Zeichen in A in den Receivebuffer schreiben
rxser:
bit A_FLG ; Ausgabeflusskontrolle
bpl rxser3 ; XON/XOFF interpretieren ?
cmp #XON
bne rxser4
lda #$7F
and SerFlg ; Transmitter starten
sta SerFlg ; Bit 7 := 0
lda ser_com
and #$F3
ora #$04
sta ser_com
rts
rxser4:
cmp #XOFF
bne rxser3 ; war weder XON noch XOFF
lda #80
ora SerFlg ; Transmit-IRQ schaltet sich selbst aus
sta SerFlg ; Bit 7 := 1
rts
rxser3:
ldx #rbuf
jsr putbuf ; Zeichen geht verloren, wenn Puffer voll
bcs rx_rts
lda free+1+rbuf
bne rx_rts ; Noch genug Platz
lda free+rbuf
cmp #10
bne rx_rts ; Mehr als 16 Zeichen frei
; Flusskontrolle durchfuehren
bit E_FLG ; Eingabeflusskontrolle
bpl rxser1
; XOFF senden
lda #XOFF
jsr DSerOut
rxser1:
bit E_FLG
bvc rx_rts
; DTR low legen
lda ser_com
and #$FE
sta ser_com
rx_rts: rts
;--------------------------------------------------------------------
;
; Zeichen aus Receivepuffer lesen an 64180 senden
;
rxout:
lda INTPAR1
bne rxout_rts ; Letzer Interrupt noch nicht quittiert
bit bus_locked
bmi rxout_rts ; 64180 darf nicht auf den Bus
bit IFLG ; "stop" - Zustand
bmi rxout_rts ; Kein Inputinterrupt
ldx #rbuf
jsr getbuf ; Zeichen lesen
bcs rxout_rts ; Puffer ist leer
ldx #5 ; Kanal 5: serielle Schnittstelle
ldy err5_bits ; Fehlerbits (passen nicht zum Zeichen)
jsr TO180 ; Zeichen im Akku
ldy #0
sty err5_bits ; loeschen
lda full+1+rbuf
bne rxout_rts ; Noch zuviel im Puffer
lda full+rbuf
cmp #10
bne rxout_rts ; Noch mehr als 16 Zeichen im Puffer
bit E_FLG
bpl rxout2
lda #XON ; XON senden
jsr DSerOut
rxout2:
bit E_FLG
bvc rxout_rts
; DTR high legen
lda ser_com
ora #01
sta ser_com
rxout_rts:
rts
;-------------------------------------------------------------------
;
; Direkte Ausgabe auf der seriellen Schnittstelle
;
DSerOut:
pha
lda ser_com
and #$F3
ora #08 ; Transmitter on, Tx_IRQ off
sta ser_com
Wai_empty:
LDA serial_stat
AND #10 ; Transmit Data Register empty ?
BEQ Wai_empty ; warten bis Transmitter empty ->
pla
STA SER_DAT
lda ser_com
and #$F3
ora #$04
sta ser_com ; Transmitter on, TX_IRQ on
RTS
;************************************************************************
;
; => Interrupt: Tastatur/V24
;
;-------------------------------------------------------------------------
;
; Interrupt-Handler
;
IRQ:
sta ASave
stx XSave
sty YSave
bit keyboard ; Taste gedrueckt ?
bpl irq_1
jsr keyIRQ
irq_1:
lda serial_stat
bpl irqret
pha
and #08 ; Receive Data Register full ?
beq irq_2
pla
pha
jsr receive_irq
irq_2:
pla
pha
and #10 ; Transmit Data Register empty ?
beq irq_3
jsr spserok ; Zeichen aus Transmitbuffer senden
irq_3:
pla
pha
and #18
bne irq_4
; External Status Change IRQ
pla
pha
jsr status_irq
irq_4:
pla
IRQret:
ldy YSave
ldx XSave
lda ASave
rti ; Pull Old Status and Return
;-------------------------------------------------------------------
;
; Status Change - Interrupt
;
; Eingang: A = serial_stat
;
status_irq:
bit A_FLG ; Ausgabe Flusskontrolle (DSR beachten)
bvc status1
and #40 ; DSR beobachten
beq status2 ; -DSR low, Transmitter starten
lda #$7F ; Bit 7 := 0
and SerFlg
sta SerFlg
lda ser_com
and #$F3
ora #$04 ; Transmitter on, Tx_IRQ on
sta ser_com
status1:
rts
status2: ; -DSR high, Transmitter stoppen
lda #80
ora SerFlg ; Transmitter stoppt sich selbst
sta SerFlg
rts
;-------------------------------------------------------------------
;
; Receiver - Interrupt
; Eingang: Y = ser_dat
; A = serial_stat
;
receive_irq:
and #7 ; Fehlerbits ausmaskieren
ldy ser_dat ; Zeichen einlesen
bit SerFlg ; Letztes Zeichen war Break
bvc receive1
pha
lda #2 ; Break
ora err5_bits
sta err5_bits ; Break empfangen
lda #$BF
and SerFlg ; Break Bit 6 := 0
sta SerFlg
pla
cpy #2 ; SV-Call
beq sv_call
cpy #'W' ; BREAK - W = control ('weiter') simulieren
beq weiter ; WEITER
cpy #'R' ; BREAK - R = RESET
beq reset_sys ; RESET
cpy #'S' ; BREAK - S = Shutup
bne receive1 ; SHUTUP
pha
ldx #'S' ; Shutup-Kennzeichen
tay
jsr TO180 ; Shutup - Interrupt
pla
receive1:
cmp #2 ; Framing Error ?
bne receive2
cpy #0 ; und Zeichen 00 = Break
bne receive2
lda #$40
ora SerFlg ; Break vermerken
sta SerFlg
rts
sv_call:
jsr weiter
ldy #0
ldx #5
lda #2 ; CTRL-B
jmp TO180
weiter:
lda #0
sta INTPAR1 ; Interrupt als quittiert ansehen
lda #7F
and IFLG
sta IFLG
rts
receive2:
tax
lda errbit_tab,x ; ACIA-Fehlerbits --> EUMEL Fehlerbits
ora err5_bits
sta err5_bits ; Fehler vermerken
tya ; Zeichen war in Y
jsr rxser ; Zeichen in Receivepuffer schreiben
jmp rxout ; Versuchen an 64180 zu senden
;-------------------------------------------------------------------------
;
; Fehlerbits
;
errbit_tab:
db 0, 4, 4, 4, 1, 5, 5, 5
; EUMEL: Bit 0= Overrun, Bit 1= Break, Bit 2= Parity/Framing
;*******************************************************************
;
; Remote - Reset
;
reset_sys:
sei
ldx #rescodelen-1
resetsysa:
lda rescode,x
sta 0,x
dex
bpl resetsysa
ldx SLOT180
lda stop180,x
nop
lda start180,x
nop
lda stop180,x
jmp resvec
rescode:
db $AF, $F3, $ED, $39, $00, $ED, $39, $00, $ED, $76
rescodelen equ $-rescode
; SYSEND:
; XOR A
; DI
; OUT0 (CNTLA0),A
; OUT0 (CNTLA0),A
; SLP
;------------------------------------------------------------------
;
; Keyboard - Interrupt
;
keyIRQ:
lda KeyBoard
asl a
tax ; X = 6543 210O
lda KeyExt
asl a ; Carry = Bit 7
txa
ror a
sta KeyStr ; Strobe loeschen
bit bus_locked
bmi readkey0 ; Nur SHUTUP/RESET erlaubt
cmp #$C2 ; F2 = SV-CALL
bne readkey0a
jsr readkey0b
lda #$C2
ldx #1
jmp TO180
readkey0a:
cmp #$BC ; SHIFT CTRL F12 = HCOPY-KEY
bne readkey0c
jmp HCOPY
readkey0c:
cmp #$BD ; SHIFT CTRL F13 = WEITER-KEY
bne readkey0
readkey0b:
lda #0
sta INTPAR1 ; Interrupt als quittiert ansehen
lda #$BF ; Bit 6 loeschen
and IFLG
sta IFLG
rts
readkey0:
cmp #$BE ; SHIFT CTRL F14 = SHUTUP-KEY
bne readkey1
ldx #'S' ; Kennzeichen fuer Shutup
jmp TO180 ; Shutup-Interrupt
readkey1:
cmp #$BF ; SHIFT CTRL F15 = RESET-KEY
bne readkey2
jmp reset_sys ; Keine Rueckkehr
readkey2:
ldx KeyIn
inx
cpx KeyOut
bne readkey3
; Tastaturpuffer Overflow
lda err1_bits ; Kanal 1 Fehlerbits
ora #1
sta err1_bits ; Overrun-Error
ldx #$0A ; Kurzer Beep: Buffer full
ldy #$10
jmp beep1
readkey3:
dex
sta KeyBuf,x
inc KeyIn
; Versuchen an 64180 zu senden
;----------------------------------------------------------------
;
; Zeichen aus Keyboard-Buffer holen
;
getkey:
ldx INTPAR1 ; letzter Interrupt quittiert ?
bne Getret
bit bus_locked
bmi Getret
bit IFLG ; "stop" - Zustand ?
bvs Getret ; Kein Inputinterrupt
sei
ldx KeyOut
cpx KeyIn
beq GetRet ; Puffer leer
lda KeyBuf,x
inc KeyOut
ldx #1 ; Kanal 1, Zeichen muss da sein
ldy err1_bits ; Overrun Bit
jsr TO180 ; 64180 Interrupt
ldy #0
sty err1_bits
GetRet:
rts
;****************************************************************
;
; Texthardcopy auf Basis-Parallel
; (Interrupt muessen disabled sein)
; (Nur moeglich, wenn Druckerspooler leer, 64180 wird gestoppt)
;
HCOPY:
lda pbuf+full
ora pbuf+full+1
bne getret ; Kein Hardcopy, da Spooler nicht leer ist.
jsr lock_bus ; 64180 vom Dienst suspendieren
lda #$0D
jsr bufin ; CR an Drucker
ldx #0
hcopy2:
ldy #0 ; 1. Spalte
hcopy1:
txa
pha
tya
pha
jsr bascalc ; Zeichen an der Position lesen
and #$7F ; Inversbit ausblenden
jsr bufin ; Zeichen an Drucker
pla
tay
pla
tax
iny
cpy #$50 ; 80. Spalte ?
bne hcopy1
txa
pha
lda #$0D ; CRLF an Drucker
jsr bufin
lda #$0A
jsr bufin
jsr spochc ; Spooler erstmal leeren
pla
tax
inx
cpx #$18 ; 24. Zeile ?
bne hcopy2
jmp unlock_bus ; 64180 darf wieder arbeiten
;------------------------------------------------------------------------
;
; Berechnet Adresse der Bildschirmposition (A,X) nach basl/bash
; Holt Zeichen --> A
; Static/Dynamic - Switch ggf. veraendert
;
bascalc:
lsr a
tay ; Y DIV 2
sta VIDBNK ; default even Y
bcc bascalc1
sta VIDBNK+1 ; odd Y
bascalc1:
txa
lsr a
and #3
ora #4 ; Page 0400..0BFF
sta bash ; High
txa
and #$18
bcc bascalc2
ora #$80
bascalc2:
sta basl ; Low
asl a
asl a
ora basl
sta basl
lda (basl),y
rts
;****************************************************************
;
; Interrupts zum 64180 (Inputinterrupts)
; moeglich von Tastatur (Kanal 1) und seriellem Interface (Kanal 5)
; Shutup-Interrupt mit X = 'S'
; Ausgang: X veraendert
;
TO180:
php
sei
STA intpar2 ; Zeichen
STY intpar3 ; Fehlerbits
STX intpar1 ; Kanalnr.
LDX SLOT180
LDA INT180,X ; 64180 Interrupt erzeugen
LDA intpar2
plp ; Interrupt Flag
RTS
;****************************************************************
;
; Drucker Spooler loeschen
;
init_pbuf:
ldx #initab_len
ploop: lda pbuf_ini,x
sta pbuf,x
dex
bpl ploop
rts
pbuf_ini:
DW (DBUFEND - DBUFBEG) * 100H, 0
DW DBUFBEG * 100H, DBUFBEG * 100H
DB DBUFBEG, DBUFEND
initab_len EQU *-pbuf_ini-1 ; Alle gleich Lang
;****************************************************************
;
; Puffer pollen
;
polling:
jsr spochc ; Zeichen aus Printer Spooler ?
; lda full+tbuf
; ora full+tbuf+1
; beq polling2
; jsr spsero ; Zeichen aus Transmitbuffer senden
; cli
;polling2:
lda INTPAR1 ; letzter Interrupt quittiert ?
bne polling1 ; Puffer garnicht erst testen
; Polling: Interrupts an 64180
jsr getkey ; Zeichen aus Tastatur-Buffer
cli
lda full+rbuf
ora full+rbuf+1
beq polling1
jsr rxout ; Zeichen aus Receive-Buffer
cli
polling1:
rts
;****************************************************************
;
; Hauptschleife des 6502: wartet auf Tasks
;
; Task 1 : Disk R/W
; 2 : Bell
; 3 : Char zum Drucker(spooler)
; 4 : Char zum seriell Spooler
; 5 : Direktausgabe auf serieller Schnittstelle
; 6 : Analog I/O
; 7 : Grafik
;
task_end:
; 8 : Druckerspooler loeschen
lda #0
sta task
sta bus_locked ; Nicht mehr gesperrt
task_loop:
cli
jsr polling ; Puffer pollen
lda task
beq task_loop
cmp #1
bne task_lp1
jsr DISKRW ; Disk I/O
jmp task_end
task_lp1:
cmp #2
bne task_lp2
jsr Beep
jmp task_end
task_lp2:
cmp #3
bne task_lp3
lda param
jsr bufin ; in Spooler-Buffer
jmp task_end
task_lp3:
cmp #4
bne task_lp4
lda param
jsr sbufin ; Output to serial Interface
jmp task_end
task_lp4:
cmp #5
bne task_lp5
lda param
jsr DSerOut ; direkte Ausgabe auf ser. Schnittstelle
jmp task_end
task_lp5:
cmp #6
bne task_lp6
jsr ANAL65 ; Analog I/O
jmp task_end
task_lp6:
cmp #7
bne task_lp7
JSR GRAFIK ; Grafik I/O
jmp task_end
task_lp7:
cmp #8
bne task_end
jsr init_pbuf ; Drucker Spooler loeschen
jmp task_end
defm 'Ende vom SHard'
LEN65 EQU $-start
IF $ GE 2000
.printx '6502-Modul in Grafikseite 1!'
ENDIF
end
|