Mercurial > repos > blastem
comparison lc8951.c @ 2130:28b6453cf7e3
Emulate CDC sync detection and sync insertion rather than relying on external knowledge about sector offset
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 15 Mar 2022 08:58:04 -0700 |
parents | bb478feccca2 |
children | d90d92ce5cab |
comparison
equal
deleted
inserted
replaced
2129:4c9e447aa25b | 2130:28b6453cf7e3 |
---|---|
52 #define BIT_STBSY 0x04 | 52 #define BIT_STBSY 0x04 |
53 #define BIT_DTEN 0x02 | 53 #define BIT_DTEN 0x02 |
54 #define BIT_STEN 0x01 | 54 #define BIT_STEN 0x01 |
55 | 55 |
56 //CTRL0 | 56 //CTRL0 |
57 #define BIT_DECEN 0x80 | 57 #define BIT_DECEN 0x80 |
58 #define BIT_WRRQ 0x04 | 58 #define BIT_WRRQ 0x04 |
59 | |
60 //CTRL1 | |
61 #define BIT_SYIEN 0x80 | |
62 #define BIT_SYDEN 0x40 | |
59 | 63 |
60 //STAT0 | 64 //STAT0 |
61 #define BIT_CRCOK 0x80 | 65 #define BIT_CRCOK 0x80 |
66 #define BIT_ILSYNC 0x40 | |
67 #define BIT_NOSYNC 0x20 | |
68 #define BIT_LBLK 0x10 | |
69 #define BIT_SBLK 0x04 | |
70 | |
62 | 71 |
63 //STAT3 | 72 //STAT3 |
64 #define BIT_VALST 0x80 | 73 #define BIT_VALST 0x80 |
65 | 74 |
66 //datasheet timing info | 75 //datasheet timing info |
263 | 272 |
264 void lc8951_write_byte(lc8951 *context, uint32_t cycle, int sector_offset, uint8_t byte) | 273 void lc8951_write_byte(lc8951 *context, uint32_t cycle, int sector_offset, uint8_t byte) |
265 { | 274 { |
266 lc8951_run(context, cycle); | 275 lc8951_run(context, cycle); |
267 uint16_t current_write_addr = context->regs[WAL] | (context->regs[WAH] << 8); | 276 uint16_t current_write_addr = context->regs[WAL] | (context->regs[WAH] << 8); |
268 if (sector_offset == 12) { | 277 |
278 context->sector_counter++; | |
279 uint8_t sync_detected = 0, sync_ignored = 0; | |
280 if (byte == 0) { | |
281 if (context->sync_counter == 11 && ((sector_offset & 3) == 3)) { | |
282 if (context->ctrl1 & BIT_SYDEN) { | |
283 sync_detected = 1; | |
284 } else { | |
285 sync_ignored = 1; | |
286 } | |
287 context->sync_counter = 0; | |
288 } else { | |
289 context->sync_counter = 1; | |
290 } | |
291 } else if (byte == 0xFF && context->sync_counter) { | |
292 context->sync_counter++; | |
293 } else { | |
294 context->sync_counter = 0; | |
295 } | |
296 | |
297 uint8_t sync_inserted = 0; | |
298 if (context->ctrl1 & BIT_SYIEN && context->sector_counter == 2352) { | |
299 sync_inserted = 1; | |
300 } | |
301 | |
302 if (sync_detected || sync_inserted) { | |
269 //we've recevied the sync pattern for the next block | 303 //we've recevied the sync pattern for the next block |
304 context->regs[STAT0] &= ~(BIT_ILSYNC | BIT_NOSYNC | BIT_LBLK | BIT_SBLK); | |
305 if (sync_inserted && !(sync_detected || sync_ignored)) { | |
306 context->regs[STAT0] |= BIT_NOSYNC; | |
307 } | |
308 if (sync_detected && context->sector_counter != 2352) { | |
309 context->regs[STAT0] |= BIT_ILSYNC; | |
310 } | |
311 context->sector_counter = 0; | |
270 | 312 |
271 //header/status regs no longer considered "valid" | 313 //header/status regs no longer considered "valid" |
272 context->regs[STAT3] |= BIT_VALST; | 314 context->regs[STAT3] |= BIT_VALST; |
273 //!DECI is set inactive at the same time as !VALST | 315 //!DECI is set inactive at the same time as !VALST |
274 context->regs[IFSTAT] |= BIT_DECI; | 316 context->regs[IFSTAT] |= BIT_DECI; |
275 if (context->ctrl0 & BIT_DECEN) { | 317 if (context->ctrl0 & BIT_DECEN) { |
276 if (context->ctrl0 & BIT_WRRQ) { | 318 if (context->ctrl0 & BIT_WRRQ) { |
277 uint16_t block_start = current_write_addr - 2352; | 319 uint16_t block_start = current_write_addr + 1 - 2352; |
278 context->regs[PTL] = block_start; | 320 context->regs[PTL] = block_start; |
279 context->regs[PTH] = block_start >> 8; | 321 context->regs[PTH] = block_start >> 8; |
280 } | 322 } |
281 printf("Decoding block starting at %X (WRRQ: %d)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ)); | 323 printf("Decoding block starting at %X (WRRQ: %d)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ)); |
282 //TODO: Datasheet has some hints about how long decoding takes in the form of how long DECI is asserted | 324 //TODO: Datasheet has some hints about how long decoding takes in the form of how long DECI is asserted |
283 context->decode_end = context->cycle + 2352 * context->clock_step * 4; | 325 context->decode_end = context->cycle + 2352 * context->clock_step * 4; |
284 } | 326 } |
285 } | 327 } else { |
286 if (sector_offset >= 12 && sector_offset < 16) { | 328 if (sync_ignored) { |
329 context->regs[STAT0] |= BIT_SBLK; | |
330 } | |
331 if (context->sector_counter == 2352) { | |
332 context->regs[STAT0] |= BIT_LBLK; | |
333 } | |
334 } | |
335 if (context->sector_counter < 4) { | |
287 //TODO: Handle SHDREN = 1 | 336 //TODO: Handle SHDREN = 1 |
288 if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN)) { | 337 if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN)) { |
289 //monitor only mode | 338 //monitor only mode |
290 context->regs[HEAD0 + sector_offset - 12] = byte; | 339 context->regs[HEAD0 + sector_offset - 12] = byte; |
291 } | 340 } |