diff 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
line wrap: on
line diff
--- 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