trunk/src/mess/machine/victor9k_fdc.c
| r242252 | r242253 | |
| 35 | 35 | - communication error with SCP after loading boot sector |
| 36 | 36 | - bp ff1a8 |
| 37 | 37 | - patch ff1ab=c3 |
| 38 | | - sync counter errors |
| 39 | | - FF if sync byte counter loaded to 10 |
| 40 | | - 11 if sync byte counter loaded to 9 |
| 38 | - single/double sided jumper |
| 39 | - header sync length unknown (6 is too short) |
| 41 | 40 | - 8048 spindle speed control |
| 42 | | - write logic |
| 43 | 41 | |
| 44 | 42 | */ |
| 45 | 43 | |
| r242252 | r242253 | |
| 60 | 58 | #define M6522_5_TAG "1k" |
| 61 | 59 | #define M6522_6_TAG "1h" |
| 62 | 60 | |
| 63 | | // this is exactly the same decode as used in the Commodore 4040/8050 series drives |
| 61 | // this is exactly the same decode/encode as used in the Commodore 4040/8050 series drives |
| 64 | 62 | #define GCR_DECODE(_e, _i) \ |
| 65 | 63 | ((BIT(_e, 6) << 7) | (BIT(_i, 7) << 6) | (_e & 0x33) | (BIT(_e, 2) << 3) | (_i & 0x04)) |
| 66 | 64 | |
| 65 | // E7 E6 I7 E5 E4 E3 E2 I2 E1 E0 |
| 66 | #define GCR_ENCODE(_e, _i) \ |
| 67 | ((_e & 0xc0) << 2 | (_i & 0x80) | (_e & 0x3c) << 1 | (_i & 0x04) | (_e & 0x03)) |
| 68 | |
| 67 | 69 | // Tandon TM-100 spindle @ 300RPM, measured TACH 12VAC 256Hz |
| 68 | 70 | // TACH = RPM / 60 * SPINDLE RATIO * MOTOR POLES |
| 69 | 71 | // 256 = 300 / 60 * 6.4 * 8 |
| r242252 | r242253 | |
| 794 | 796 | |
| 795 | 797 | */ |
| 796 | 798 | |
| 799 | if (LOG_VIA) logerror("%s %s WD %02x\n", machine().time().as_string(), machine().describe_context(), data); |
| 800 | |
| 797 | 801 | if (m_wd != data) |
| 798 | 802 | { |
| 799 | 803 | live_sync(); |
| 800 | 804 | m_wd = cur_live.wd = data; |
| 801 | | if (LOG_VIA) logerror("%s %s WD %02x\n", machine().time().as_string(), machine().describe_context(), data); |
| 802 | 805 | checkpoint(); |
| 803 | 806 | live_run(); |
| 804 | 807 | } |
| r242252 | r242253 | |
| 931 | 934 | // door A sense |
| 932 | 935 | data |= (m_floppy0->exists() ? 0 : 1) << 4; |
| 933 | 936 | |
| 934 | | // single/double sided |
| 935 | | data |= (m_drive ? m_floppy1->twosid_r() : m_floppy0->twosid_r()) << 5; |
| 937 | // single/double sided jumper |
| 938 | //data |= 0x20; |
| 936 | 939 | |
| 937 | 940 | return data; |
| 938 | 941 | } |
| r242252 | r242253 | |
| 997 | 1000 | checkpoint(); |
| 998 | 1001 | if (LOG_VIA) logerror("%s %s DRW %u\n", machine().time().as_string(), machine().describe_context(), state); |
| 999 | 1002 | if (state) { |
| 1000 | | stop_writing(machine().time()); |
| 1003 | pll_stop_writing(get_floppy(), machine().time()); |
| 1001 | 1004 | } else { |
| 1002 | | start_writing(machine().time()); |
| 1005 | pll_start_writing(machine().time()); |
| 1003 | 1006 | } |
| 1004 | 1007 | live_run(); |
| 1005 | 1008 | } |
| r242252 | r242253 | |
| 1079 | 1082 | cur_pll.set_clock(clock); |
| 1080 | 1083 | } |
| 1081 | 1084 | |
| 1082 | | void victor_9000_fdc_t::pll_save_checkpoint() |
| 1085 | void victor_9000_fdc_t::pll_start_writing(const attotime &tm) |
| 1083 | 1086 | { |
| 1084 | | checkpoint_pll = cur_pll; |
| 1087 | cur_pll.start_writing(tm); |
| 1085 | 1088 | } |
| 1086 | 1089 | |
| 1087 | | void victor_9000_fdc_t::pll_retrieve_checkpoint() |
| 1090 | void victor_9000_fdc_t::pll_commit(floppy_image_device *floppy, const attotime &tm) |
| 1088 | 1091 | { |
| 1089 | | cur_pll = checkpoint_pll; |
| 1092 | cur_pll.commit(floppy, tm); |
| 1090 | 1093 | } |
| 1091 | 1094 | |
| 1092 | | void victor_9000_fdc_t::checkpoint() |
| 1095 | void victor_9000_fdc_t::pll_stop_writing(floppy_image_device *floppy, const attotime &tm) |
| 1093 | 1096 | { |
| 1094 | | checkpoint_live = cur_live; |
| 1095 | | pll_save_checkpoint(); |
| 1097 | cur_pll.stop_writing(floppy, tm); |
| 1096 | 1098 | } |
| 1097 | 1099 | |
| 1098 | | void victor_9000_fdc_t::rollback() |
| 1100 | void victor_9000_fdc_t::pll_save_checkpoint() |
| 1099 | 1101 | { |
| 1100 | | cur_live = checkpoint_live; |
| 1101 | | pll_retrieve_checkpoint(); |
| 1102 | checkpoint_pll = cur_pll; |
| 1102 | 1103 | } |
| 1103 | 1104 | |
| 1104 | | void victor_9000_fdc_t::start_writing(const attotime &tm) |
| 1105 | void victor_9000_fdc_t::pll_retrieve_checkpoint() |
| 1105 | 1106 | { |
| 1106 | | cur_live.write_start_time = tm; |
| 1107 | | cur_live.write_position = 0; |
| 1107 | cur_pll = checkpoint_pll; |
| 1108 | 1108 | } |
| 1109 | 1109 | |
| 1110 | | void victor_9000_fdc_t::stop_writing(const attotime &tm) |
| 1110 | int victor_9000_fdc_t::pll_get_next_bit(attotime &tm, floppy_image_device *floppy, const attotime &limit) |
| 1111 | 1111 | { |
| 1112 | | commit(tm); |
| 1113 | | cur_live.write_start_time = attotime::never; |
| 1112 | return cur_pll.get_next_bit(tm, floppy, limit); |
| 1114 | 1113 | } |
| 1115 | 1114 | |
| 1116 | | bool victor_9000_fdc_t::write_next_bit(bool bit, const attotime &limit) |
| 1115 | bool victor_9000_fdc_t::pll_write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit) |
| 1117 | 1116 | { |
| 1118 | | if(cur_live.write_start_time.is_never()) { |
| 1119 | | cur_live.write_start_time = cur_live.tm; |
| 1120 | | cur_live.write_position = 0; |
| 1121 | | } |
| 1122 | | |
| 1123 | | attotime etime = cur_live.tm + m_period; |
| 1124 | | if(etime > limit) |
| 1125 | | return true; |
| 1126 | | |
| 1127 | | if(bit && cur_live.write_position < ARRAY_LENGTH(cur_live.write_buffer)) |
| 1128 | | cur_live.write_buffer[cur_live.write_position++] = cur_live.tm; |
| 1129 | | |
| 1130 | | if (LOG) logerror("%s write bit %u (%u)\n", cur_live.tm.as_string(), cur_live.bit_counter, bit); |
| 1131 | | |
| 1132 | | return false; |
| 1117 | return cur_pll.write_next_bit(bit, tm, floppy, limit); |
| 1133 | 1118 | } |
| 1134 | 1119 | |
| 1135 | | void victor_9000_fdc_t::commit(const attotime &tm) |
| 1120 | void victor_9000_fdc_t::checkpoint() |
| 1136 | 1121 | { |
| 1137 | | if(cur_live.write_start_time.is_never() || tm == cur_live.write_start_time || !cur_live.write_position) |
| 1138 | | return; |
| 1122 | pll_commit(get_floppy(), cur_live.tm); |
| 1123 | checkpoint_live = cur_live; |
| 1124 | pll_save_checkpoint(); |
| 1125 | } |
| 1139 | 1126 | |
| 1140 | | if (LOG) logerror("%s committing %u transitions since %s\n", tm.as_string(), cur_live.write_position, cur_live.write_start_time.as_string()); |
| 1141 | | |
| 1142 | | if(get_floppy()) |
| 1143 | | get_floppy()->write_flux(cur_live.write_start_time, tm, cur_live.write_position, cur_live.write_buffer); |
| 1144 | | |
| 1145 | | cur_live.write_start_time = tm; |
| 1146 | | cur_live.write_position = 0; |
| 1127 | void victor_9000_fdc_t::rollback() |
| 1128 | { |
| 1129 | cur_live = checkpoint_live; |
| 1130 | pll_retrieve_checkpoint(); |
| 1147 | 1131 | } |
| 1148 | 1132 | |
| 1149 | 1133 | void victor_9000_fdc_t::live_delay(int state) |
| r242252 | r242253 | |
| 1161 | 1145 | if(cur_live.tm > machine().time()) { |
| 1162 | 1146 | rollback(); |
| 1163 | 1147 | live_run(machine().time()); |
| 1164 | | commit(cur_live.tm); |
| 1148 | pll_commit(get_floppy(), cur_live.tm); |
| 1165 | 1149 | } else { |
| 1166 | | commit(cur_live.tm); |
| 1150 | pll_commit(get_floppy(), cur_live.tm); |
| 1167 | 1151 | if(cur_live.next_state != -1) { |
| 1168 | 1152 | cur_live.state = cur_live.next_state; |
| 1169 | 1153 | cur_live.next_state = -1; |
| 1170 | 1154 | } |
| 1171 | 1155 | if(cur_live.state == IDLE) { |
| 1172 | | stop_writing(cur_live.tm); |
| 1156 | pll_stop_writing(get_floppy(), cur_live.tm); |
| 1173 | 1157 | cur_live.tm = attotime::never; |
| 1174 | 1158 | } |
| 1175 | 1159 | } |
| r242252 | r242253 | |
| 1185 | 1169 | live_run(machine().time()); |
| 1186 | 1170 | } |
| 1187 | 1171 | |
| 1188 | | stop_writing(cur_live.tm); |
| 1172 | pll_stop_writing(get_floppy(), cur_live.tm); |
| 1189 | 1173 | |
| 1190 | 1174 | cur_live.tm = attotime::never; |
| 1191 | 1175 | cur_live.state = IDLE; |
| r242252 | r242253 | |
| 1215 | 1199 | return; |
| 1216 | 1200 | |
| 1217 | 1201 | // read bit |
| 1218 | | int bit = get_next_bit(cur_live.tm, limit); |
| 1202 | int bit = pll_get_next_bit(cur_live.tm, get_floppy(), limit); |
| 1219 | 1203 | if(bit < 0) |
| 1220 | 1204 | return; |
| 1221 | 1205 | |
| r242252 | r242253 | |
| 1227 | 1211 | int sync = !(cur_live.shift_reg == 0x3ff); |
| 1228 | 1212 | |
| 1229 | 1213 | // bit counter |
| 1230 | | if (!sync) { |
| 1231 | | cur_live.bit_counter = 0; |
| 1232 | | } else if (cur_live.sync) { |
| 1214 | if (cur_live.drw) { |
| 1215 | if (!sync) { |
| 1216 | cur_live.bit_counter = 0; |
| 1217 | } else if (cur_live.sync) { |
| 1218 | cur_live.bit_counter++; |
| 1219 | if (cur_live.bit_counter == 10) { |
| 1220 | cur_live.bit_counter = 0; |
| 1221 | } |
| 1222 | } |
| 1223 | } else { |
| 1233 | 1224 | cur_live.bit_counter++; |
| 1234 | 1225 | if (cur_live.bit_counter == 10) { |
| 1235 | 1226 | cur_live.bit_counter = 0; |
| r242252 | r242253 | |
| 1239 | 1230 | // sync counter |
| 1240 | 1231 | if (sync) { |
| 1241 | 1232 | cur_live.sync_bit_counter = 0; |
| 1242 | | cur_live.sync_byte_counter = 9; |
| 1233 | cur_live.sync_byte_counter = 10; // TODO 9 in schematics |
| 1243 | 1234 | } else if (!cur_live.sync) { |
| 1244 | 1235 | cur_live.sync_bit_counter++; |
| 1245 | 1236 | if (cur_live.sync_bit_counter == 10) { |
| r242252 | r242253 | |
| 1256 | 1247 | |
| 1257 | 1248 | // GCR decoder |
| 1258 | 1249 | if (cur_live.drw) { |
| 1259 | | cur_live.i = cur_live.drw << 10 | cur_live.shift_reg; |
| 1250 | cur_live.i = cur_live.shift_reg; |
| 1260 | 1251 | } else { |
| 1261 | | cur_live.i = cur_live.drw << 10 | ((cur_live.wd & 0xf0) << 1) | cur_live.wrsync << 4 | (cur_live.wd & 0x0f); |
| 1252 | cur_live.i = 0x200 | ((cur_live.wd & 0xf0) << 1) | cur_live.wrsync << 4 | (cur_live.wd & 0x0f); |
| 1262 | 1253 | } |
| 1263 | 1254 | |
| 1264 | | cur_live.e = m_gcr_rom->base()[cur_live.i]; |
| 1255 | cur_live.e = m_gcr_rom->base()[cur_live.drw << 10 | cur_live.i]; |
| 1265 | 1256 | |
| 1266 | 1257 | attotime next = cur_live.tm + m_period; |
| 1267 | | if (LOG) logerror("%s:%s:%s bit %u sync %u bc %u sbc %u sBC %u syn %u i %03x e %02x\n",cur_live.tm.as_string(),next.as_string(),cur_live.edge.as_string(),bit,sync,cur_live.bit_counter,cur_live.sync_bit_counter,cur_live.sync_byte_counter,syn,cur_live.i,cur_live.e); |
| 1258 | if (LOG) logerror("%s:%s cyl %u bit %u sync %u bc %u sr %03x sbc %u sBC %u syn %u i %03x e %02x\n",cur_live.tm.as_string(),next.as_string(),get_floppy()->get_cyl(),bit,sync,cur_live.bit_counter,cur_live.shift_reg,cur_live.sync_bit_counter,cur_live.sync_byte_counter,syn,cur_live.i,cur_live.e); |
| 1268 | 1259 | |
| 1269 | 1260 | // byte ready |
| 1270 | 1261 | int brdy = !(cur_live.bit_counter == 9); |
| r242252 | r242253 | |
| 1272 | 1263 | // GCR error |
| 1273 | 1264 | int gcr_err = !(brdy || BIT(cur_live.e, 3)); |
| 1274 | 1265 | |
| 1266 | // write bit |
| 1267 | if (!cur_live.drw) { // TODO WPS |
| 1268 | int write_bit = BIT(cur_live.shift_reg_write, 9); |
| 1269 | if (LOG) logerror("%s writing bit %u sr %03x\n",cur_live.tm.as_string(),write_bit,cur_live.shift_reg_write); |
| 1270 | pll_write_next_bit(write_bit, cur_live.tm, get_floppy(), limit); |
| 1271 | } |
| 1272 | |
| 1273 | if (!brdy) { |
| 1274 | // load write shift register |
| 1275 | cur_live.shift_reg_write = GCR_ENCODE(cur_live.e, cur_live.i); |
| 1276 | |
| 1277 | if (LOG) logerror("%s load write shift register %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write); |
| 1278 | } else { |
| 1279 | // clock write shift register |
| 1280 | cur_live.shift_reg_write <<= 1; |
| 1281 | cur_live.shift_reg_write &= 0x3ff; |
| 1282 | } |
| 1283 | |
| 1275 | 1284 | if (brdy != cur_live.brdy) { |
| 1276 | 1285 | if (LOG) logerror("%s BRDY %u\n", cur_live.tm.as_string(),brdy); |
| 1277 | 1286 | if (!brdy) |
| r242252 | r242253 | |
| 1303 | 1312 | } |
| 1304 | 1313 | |
| 1305 | 1314 | if (syncpoint) { |
| 1306 | | commit(cur_live.tm); |
| 1307 | | |
| 1308 | | cur_live.tm += m_period; |
| 1309 | 1315 | live_delay(RUNNING_SYNCPOINT); |
| 1310 | 1316 | return; |
| 1311 | 1317 | } |
| 1312 | | |
| 1313 | | cur_live.tm += m_period; |
| 1314 | 1318 | break; |
| 1315 | 1319 | } |
| 1316 | 1320 | |
| r242252 | r242253 | |
| 1334 | 1338 | } |
| 1335 | 1339 | } |
| 1336 | 1340 | } |
| 1337 | | |
| 1338 | | int victor_9000_fdc_t::get_next_bit(attotime &tm, const attotime &limit) |
| 1339 | | { |
| 1340 | | return cur_pll.get_next_bit(tm, get_floppy(), limit); |
| 1341 | | } |