branches/alto2/src/emu/cpu/alto2/a2disk.c
| r26156 | r26157 | |
| 134 | 134 | s1 = (s1 & ~JKFF_Q) | JKFF_Q0; |
| 135 | 135 | else |
| 136 | 136 | s1 = (s1 | JKFF_Q) & ~JKFF_Q0; |
| 137 | | LOG((LOG_DISK,5,"%s J:0 K':1 flip-flop Q:%d\n", |
| 138 | | jkff_name, (s1 & JKFF_Q) ? 1 : 0)); |
| 137 | LOG((LOG_DISK,5,"%s J:0 K':1 flip-flop Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0)); |
| 139 | 138 | break; |
| 140 | 139 | case JKFF_K: |
| 141 | 140 | if ((s0 ^ s1) & JKFF_Q) { |
| 142 | | LOG((LOG_DISK,5,"%s J:0 K':1 keep Q:%d\n", |
| 143 | | jkff_name, (s1 & JKFF_Q) ? 1 : 0)); |
| 141 | LOG((LOG_DISK,5,"%s J:0 K':1 keep Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0)); |
| 144 | 142 | } |
| 145 | 143 | /* J is 0, and K' is 1: keep Q as is */ |
| 146 | 144 | if (s0 & JKFF_Q) |
| r26156 | r26157 | |
| 152 | 150 | /* both J and K' are 1: set Q to 1 */ |
| 153 | 151 | s1 = (s1 | JKFF_Q) & ~JKFF_Q0; |
| 154 | 152 | if (!(s0 & JKFF_Q)) { |
| 155 | | LOG((LOG_DISK,5,"%s J:1 K':1 → Q:1\n", |
| 156 | | jkff_name)); |
| 153 | LOG((LOG_DISK,5,"%s J:1 K':1 → Q:1\n", jkff_name)); |
| 157 | 154 | } |
| 158 | 155 | break; |
| 159 | 156 | } |
| r26156 | r26157 | |
| 1047 | 1044 | */ |
| 1048 | 1045 | void alto2_cpu_device::kwd_timing(int bitclk, int datin, int block) |
| 1049 | 1046 | { |
| 1050 | | static int wddone0; |
| 1051 | | int wddone1 = wddone0; |
| 1047 | int wddone = m_dsk.wddone; |
| 1052 | 1048 | int i; |
| 1053 | 1049 | UINT8 s0, s1; |
| 1054 | 1050 | |
| r26156 | r26157 | |
| 1078 | 1074 | */ |
| 1079 | 1075 | LOG((LOG_DISK,3," HIORDBIT:1 sets WFFO:1\n")); |
| 1080 | 1076 | PUT_KCOM_WFFO(m_dsk.kcom, 1); |
| 1077 | // TODO: show disk indicators |
| 1081 | 1078 | } |
| 1082 | 1079 | /* |
| 1083 | 1080 | * Falling edge of BITCLK, counting continues as it was preset |
| r26156 | r26157 | |
| 1103 | 1100 | LOG((LOG_DISK,3," WFFO:0 load bitcount:%2d\n", m_dsk.bitcount)); |
| 1104 | 1101 | } |
| 1105 | 1102 | } else if (!m_dsk.bitclk && bitclk) { |
| 1106 | | /* clock the shift register on the rising edge of bitclk */ |
| 1103 | // clock the shift register on the rising edge of bitclk |
| 1107 | 1104 | m_dsk.shiftin = (m_dsk.shiftin << 1) | datin; |
| 1108 | | /* and the output shift register, too */ |
| 1105 | // and the output shift register too |
| 1109 | 1106 | m_dsk.shiftout = m_dsk.shiftout << 1; |
| 1110 | 1107 | } |
| 1111 | 1108 | |
| 1112 | | if (wddone0 != wddone1) { |
| 1113 | | LOG((LOG_DISK,2," WDDONE':%d→%d\n", wddone0, wddone1)); |
| 1109 | if (m_dsk.wddone != wddone) { |
| 1110 | LOG((LOG_DISK,2," WDDONE':%d→%d\n", m_dsk.wddone, wddone)); |
| 1114 | 1111 | } |
| 1115 | 1112 | |
| 1116 | 1113 | if (m_dsk.carry) { |
| 1117 | 1114 | /* CARRY = 1 -> WDDONE' = 0 */ |
| 1118 | | wddone1 = 0; |
| 1119 | | if (wddone0 == 0) { |
| 1115 | wddone = 0; |
| 1116 | if (wddone == 0) { |
| 1120 | 1117 | /* |
| 1121 | 1118 | * Latch a new data word while WDDONE is 0 |
| 1122 | 1119 | * Note: The shifter outputs for bits 0 to 14 are connected |
| r26156 | r26157 | |
| 1131 | 1128 | } |
| 1132 | 1129 | } else { |
| 1133 | 1130 | /* CARRY = 0 -> WDDONE' = 1 */ |
| 1134 | | wddone1 = 1; |
| 1131 | wddone = 1; |
| 1135 | 1132 | } |
| 1136 | 1133 | |
| 1137 | 1134 | /* remember previous state of wddone */ |
| 1138 | | wddone0 = wddone1; |
| 1135 | m_dsk.wddone = wddone; |
| 1139 | 1136 | |
| 1140 | 1137 | /** |
| 1141 | 1138 | * JK flip-flop 43b (word task) |
| r26156 | r26157 | |
| 1150 | 1147 | */ |
| 1151 | 1148 | DEBUG_NAME("\t\t43b KWD "); |
| 1152 | 1149 | s0 = m_dsk.ff_43b; |
| 1153 | | s1 = wddone1 ? JKFF_CLK : 0; |
| 1150 | s1 = wddone ? JKFF_CLK : 0; |
| 1154 | 1151 | s1 |= JKFF_J; |
| 1155 | 1152 | s1 |= JKFF_K; |
| 1156 | 1153 | if (m_dsk.ok_to_run) |
| r26156 | r26157 | |
| 1159 | 1156 | s1 |= JKFF_C; |
| 1160 | 1157 | m_dsk.ff_43b = update_jkff(s0, s1); |
| 1161 | 1158 | |
| 1162 | | /* count for the 4 stages of sysclka and sysclkb transitions */ |
| 1159 | // loop over the 4 stages of sysclka and sysclkb transitions |
| 1163 | 1160 | for (i = 0; i < 4; i++) { |
| 1164 | 1161 | |
| 1165 | 1162 | if (m_sysclka0[i] != m_sysclka1[i]) { |
| r26156 | r26157 | |
| 1250 | 1247 | DEBUG_NAME("\t\t45a RDYLAT"); |
| 1251 | 1248 | s0 = m_dsk.ff_45a; |
| 1252 | 1249 | s1 = m_sysclka1[i] ? JKFF_CLK : JKFF_0; |
| 1253 | | if (0 == dhd->get_ready_0()) |
| 1250 | if (dhd->get_ready_0()) |
| 1254 | 1251 | s1 |= JKFF_J; |
| 1255 | 1252 | s1 |= JKFF_K; |
| 1256 | 1253 | s1 |= JKFF_S; |
| r26156 | r26157 | |
| 1341 | 1338 | s1 |= JKFF_J; |
| 1342 | 1339 | s1 |= JKFF_K; |
| 1343 | 1340 | s1 |= JKFF_S; |
| 1344 | | if (!(m_dsk.ff_22b & JKFF_Q)) |
| 1341 | if (m_dsk.ff_22b & JKFF_Q0) |
| 1345 | 1342 | s1 |= JKFF_C; |
| 1346 | 1343 | m_dsk.ff_21b = update_jkff(s0, s1); |
| 1347 | 1344 | } |
| 1348 | 1345 | |
| 1349 | | /* The 53b FF Q output is the WDINIT signal. */ |
| 1346 | // The 53b FF Q output is the WDINIT signal. |
| 1350 | 1347 | if (WDINIT != m_dsk.wdinit) { |
| 1351 | 1348 | m_dsk.wdinit0 = m_dsk.wdinit; |
| 1352 | | /* rising edge immediately */ |
| 1349 | // rising edge immediately |
| 1353 | 1350 | if ((m_dsk.wdinit = WDINIT) == 1) |
| 1354 | 1351 | m_dsk.wdinit0 = 1; |
| 1355 | 1352 | LOG((LOG_DISK,2," WDINIT:%d\n", m_dsk.wdinit)); |
| r26156 | r26157 | |
| 1377 | 1374 | } |
| 1378 | 1375 | |
| 1379 | 1376 | if (m_dsk.kfer) { |
| 1380 | | /* no fatal error: ready and not seqerr and seekok */ |
| 1377 | // no fatal error: ready AND not seqerr AND seekok |
| 1381 | 1378 | if (!RDYLAT && !SEQERR && SEEKOK) { |
| 1382 | 1379 | LOG((LOG_DISK,2," reset KFER\n")); |
| 1383 | 1380 | m_dsk.kfer = 0; |
| 1384 | 1381 | } |
| 1385 | 1382 | } else { |
| 1386 | | /* fatal error: not ready or seqerr or not seekok */ |
| 1383 | // fatal error: not ready OR seqerr OR not seekok |
| 1387 | 1384 | if (RDYLAT) { |
| 1388 | 1385 | LOG((LOG_DISK,2," RDYLAT sets KFER\n")); |
| 1389 | 1386 | m_dsk.kfer = 1; |
| 1390 | | } else if (SEQERR) { |
| 1387 | } |
| 1388 | if (SEQERR) { |
| 1391 | 1389 | LOG((LOG_DISK,2," SEQERR sets KFER\n")); |
| 1392 | 1390 | m_dsk.kfer = 1; |
| 1393 | | } else if (!SEEKOK) { |
| 1391 | } |
| 1392 | if (!SEEKOK) { |
| 1394 | 1393 | LOG((LOG_DISK,2," not SEEKOK sets KFER\n")); |
| 1395 | 1394 | m_dsk.kfer = 1; |
| 1396 | 1395 | } |
| 1397 | 1396 | } |
| 1398 | 1397 | |
| 1399 | 1398 | /* |
| 1400 | | * The FF 22b Q output is the STSKENA signal, |
| 1401 | | * the Q' is the WAKEKST' signal. |
| 1399 | * The FF 22b Q output is the STSKENA (sector task enable) |
| 1400 | * signal, the Q' is the WAKEKST' signal. |
| 1402 | 1401 | */ |
| 1403 | 1402 | if (m_dsk.ff_22b & JKFF_Q) { |
| 1404 | | if (!(m_task_wakeup & (1 << task_ksec))) { |
| 1403 | if (0 == (m_task_wakeup & (1 << task_ksec))) { |
| 1405 | 1404 | LOG((LOG_DISK,2," STSKENA:1; WAKEST':0 wake KSEC\n")); |
| 1406 | 1405 | m_task_wakeup |= 1 << task_kwd; |
| 1407 | 1406 | } |
| 1408 | 1407 | } else { |
| 1409 | | if (m_task_wakeup & (1 << task_ksec)) { |
| 1408 | if (0 != (m_task_wakeup & (1 << task_ksec))) { |
| 1410 | 1409 | LOG((LOG_DISK,2," STSKENA:0; WAKEST':1\n")); |
| 1411 | 1410 | m_task_wakeup &= ~(1 << task_kwd); |
| 1412 | 1411 | } |
| r26156 | r26157 | |
| 1425 | 1424 | */ |
| 1426 | 1425 | DEBUG_NAME("\t\t21a KSEC "); |
| 1427 | 1426 | s0 = m_dsk.ff_21a; |
| 1428 | | s1 = dhd->get_sector_mark_0() ? JKFF_0 : JKFF_CLK; |
| 1427 | s1 = 0 == dhd->get_sector_mark_0() ? JKFF_CLK : JKFF_0; |
| 1429 | 1428 | if (m_dsk.ff_22b & JKFF_Q0) |
| 1430 | 1429 | s1 |= JKFF_J; |
| 1431 | 1430 | s1 |= JKFF_K; |
| r26156 | r26157 | |
| 1440 | 1439 | * some time. |
| 1441 | 1440 | */ |
| 1442 | 1441 | if ((m_dsk.ff_21a_old & JKFF_Q0) && (m_dsk.ff_21a & JKFF_Q)) { |
| 1443 | | if (!m_dsk.seclate_timer) |
| 1444 | | m_dsk.seclate_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_seclate),this));; |
| 1445 | | m_dsk.seclate_timer->adjust(attotime::from_nsec(TW_SECLATE), 1, attotime::never); |
| 1442 | m_dsk.seclate_timer->adjust(attotime::from_nsec(TW_SECLATE), 1); |
| 1446 | 1443 | if (m_dsk.seclate) { |
| 1447 | 1444 | m_dsk.seclate = 0; |
| 1448 | 1445 | LOG((LOG_DISK,4," SECLATE -> 0 pulse until %lldns\n", ntime() + TW_SECLATE)); |
| r26156 | r26157 | |
| 1453 | 1450 | * check if write and erase gate, or read gate are changed |
| 1454 | 1451 | */ |
| 1455 | 1452 | if ((m_task_wakeup & (1 << task_ksec)) || GET_KCOM_XFEROFF(m_dsk.kcom) || m_dsk.kfer) { |
| 1453 | // sector task is active OR xferoff is set OR fatal error |
| 1456 | 1454 | dhd->set_egate(1); |
| 1457 | 1455 | dhd->set_wrgate(1); |
| 1458 | 1456 | dhd->set_rdgate(1); |
| 1459 | 1457 | } else { |
| 1460 | | /* enable either read or write gates depending on current record R/W */ |
| 1458 | // assert either read or write gates depending on current record R/W |
| 1461 | 1459 | if (m_dsk.krwc & RWC_WRITE) { |
| 1462 | | /* enable erase and write gates only if OKTORUN is high */ |
| 1460 | // assert erase and write gates only if OKTORUN is high |
| 1463 | 1461 | if (m_dsk.ok_to_run) { |
| 1464 | 1462 | dhd->set_egate(0); |
| 1465 | 1463 | dhd->set_wrgate(0); |
| 1466 | 1464 | } |
| 1467 | 1465 | } else { |
| 1468 | | /* enable read gate */ |
| 1466 | // assert read gate |
| 1469 | 1467 | dhd->set_rdgate(0); |
| 1470 | 1468 | } |
| 1471 | 1469 | } |