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 }