changeset 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 4c9e447aa25b
children d90d92ce5cab
files cdd_mcu.c lc8951.c lc8951.h
diffstat 3 files changed, 59 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/cdd_mcu.c	Sun Mar 13 11:49:07 2022 -0700
+++ b/cdd_mcu.c	Tue Mar 15 08:58:04 2022 -0700
@@ -543,6 +543,7 @@
 		for (; context->cycle < cd_cycle; context->cycle += CDD_MCU_DIVIDER) {
 			if (context->cycle >= context->next_byte_cycle) {
 				cdd_fader_data(fader, 0);
+				lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), 0, 0);
 				context->next_byte_cycle += BYTE_CLOCKS;
 			}
 		}
@@ -631,6 +632,7 @@
 				lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), context->current_sector_byte++, byte);
 				cdd_fader_data(fader, gate_array[GAO_CDD_CTRL] & BIT_MUTE ? 0 : byte);
 			} else {
+				lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), 0, 0);
 				cdd_fader_data(fader, 0);
 				if (context->current_sector_byte >= 0) {
 					next_subcode += BYTE_CLOCKS;
--- a/lc8951.c	Sun Mar 13 11:49:07 2022 -0700
+++ b/lc8951.c	Tue Mar 15 08:58:04 2022 -0700
@@ -54,11 +54,20 @@
 #define BIT_STEN   0x01
 
 //CTRL0
-#define BIT_DECEN 0x80
-#define BIT_WRRQ  0x04
+#define BIT_DECEN  0x80
+#define BIT_WRRQ   0x04
+
+//CTRL1
+#define BIT_SYIEN  0x80
+#define BIT_SYDEN  0x40
 
 //STAT0
-#define BIT_CRCOK 0x80
+#define BIT_CRCOK  0x80
+#define BIT_ILSYNC 0x40
+#define BIT_NOSYNC 0x20
+#define BIT_LBLK   0x10
+#define BIT_SBLK   0x04
+
 
 //STAT3
 #define BIT_VALST 0x80
@@ -265,8 +274,41 @@
 {
 	lc8951_run(context, cycle);
 	uint16_t current_write_addr = context->regs[WAL] | (context->regs[WAH] << 8);
-	if (sector_offset == 12) {
+
+	context->sector_counter++;
+	uint8_t sync_detected = 0, sync_ignored = 0;
+	if (byte == 0) {
+		if (context->sync_counter == 11 && ((sector_offset & 3) == 3)) {
+			if (context->ctrl1 & BIT_SYDEN) {
+				sync_detected = 1;
+			} else {
+				sync_ignored = 1;
+			}
+			context->sync_counter = 0;
+		} else {
+			context->sync_counter = 1;
+		}
+	} else if (byte == 0xFF && context->sync_counter) {
+		context->sync_counter++;
+	} else {
+		context->sync_counter = 0;
+	}
+
+	uint8_t sync_inserted = 0;
+	if (context->ctrl1 & BIT_SYIEN && context->sector_counter == 2352) {
+		sync_inserted = 1;
+	}
+
+	if (sync_detected || sync_inserted) {
 		//we've recevied the sync pattern for the next block
+		context->regs[STAT0] &= ~(BIT_ILSYNC | BIT_NOSYNC | BIT_LBLK | BIT_SBLK);
+		if (sync_inserted && !(sync_detected || sync_ignored)) {
+			context->regs[STAT0] |= BIT_NOSYNC;
+		}
+		if (sync_detected && context->sector_counter != 2352) {
+			context->regs[STAT0] |= BIT_ILSYNC;
+		}
+		context->sector_counter = 0;
 
 		//header/status regs no longer considered "valid"
 		context->regs[STAT3] |= BIT_VALST;
@@ -274,7 +316,7 @@
 		context->regs[IFSTAT] |= BIT_DECI;
 		if (context->ctrl0 & BIT_DECEN) {
 			if (context->ctrl0 & BIT_WRRQ) {
-				uint16_t block_start = current_write_addr - 2352;
+				uint16_t block_start = current_write_addr + 1 - 2352;
 				context->regs[PTL] = block_start;
 				context->regs[PTH] = block_start >> 8;
 			}
@@ -282,8 +324,15 @@
 			//TODO: Datasheet has some hints about how long decoding takes in the form of how long DECI is asserted
 			context->decode_end = context->cycle + 2352 * context->clock_step * 4;
 		}
+	} else {
+		if (sync_ignored) {
+			context->regs[STAT0] |= BIT_SBLK;
+		}
+		if (context->sector_counter == 2352) {
+			context->regs[STAT0] |= BIT_LBLK;
+		}
 	}
-	if (sector_offset >= 12 && sector_offset < 16) {
+	if (context->sector_counter < 4) {
 		//TODO: Handle SHDREN = 1
 		if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN)) {
 			//monitor only mode
--- a/lc8951.h	Sun Mar 13 11:49:07 2022 -0700
+++ b/lc8951.h	Tue Mar 15 08:58:04 2022 -0700
@@ -12,6 +12,7 @@
 	uint32_t clock_step;
 	uint32_t decode_end;
 	uint32_t transfer_end;
+	uint16_t sector_counter;
 
 	uint8_t  buffer[0x4000];
 
@@ -26,6 +27,7 @@
 	uint8_t  ctrl1;
 	uint8_t  ar;
 	uint8_t  ar_mask;
+	uint8_t  sync_counter;
 } lc8951;
 
 void lc8951_init(lc8951 *context, lcd8951_byte_recv_fun byte_handler, void *handler_data);