changeset 2067:f22e04b69272 segacd

More CDC/CDD improvements
author Michael Pavone <pavone@retrodev.com>
date Sun, 30 Jan 2022 11:58:17 -0800
parents a61a8a87410c
children f573f2c31bc9
files cdd_mcu.c lc8951.c lc8951.h
diffstat 3 files changed, 61 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/cdd_mcu.c	Sun Jan 30 00:21:58 2022 -0800
+++ b/cdd_mcu.c	Sun Jan 30 11:58:17 2022 -0800
@@ -61,26 +61,30 @@
 	}
 	return (~sum) & 0xF;
 }
-#define SEEK_SPEED 2200 //made up number
+#define COARSE_SEEK 2200 //made up numbers
+#define FINE_SEEK 10
 static void handle_seek(cdd_mcu *context)
 {
+	//TODO: more realistic seeking behavior
 	if (context->seeking) {
 		if (context->seek_pba == context->head_pba) {
 			context->seeking = 0;
 		} else if (context->seek_pba > context->head_pba) {
-			context->head_pba += SEEK_SPEED;
-			if (context->head_pba > context->seek_pba) {
-				context->head_pba = context->seek_pba;
+			if (context->seek_pba - context->head_pba >= COARSE_SEEK) {
+				context->head_pba += COARSE_SEEK;
+			} else if (context->seek_pba - context->head_pba >= FINE_SEEK) {
+				context->head_pba += FINE_SEEK;
+			} else {
+				context->head_pba++;
 			}
 		} else {
-			if (context->head_pba >= SEEK_SPEED) {
-				context->head_pba -= SEEK_SPEED;
+			if (context->head_pba - context->seek_pba >= COARSE_SEEK) {
+				context->head_pba -= COARSE_SEEK;
+			} else if (context->head_pba >= FINE_SEEK) {
+				context->head_pba -= FINE_SEEK;
 			} else {
 				context->head_pba = 0;
 			}
-			if (context->head_pba < context->seek_pba) {
-				context->head_pba = context->seek_pba;
-			}
 		}
 	}
 }
@@ -352,7 +356,8 @@
 		lba += context->cmd_buffer.b.time.sec_high * 10 + context->cmd_buffer.b.time.sec_low;
 		lba *= 75;
 		lba += context->cmd_buffer.b.time.frame_high * 10 + context->cmd_buffer.b.time.frame_low;
-		printf("READ/SEEK cmd for lba %d, MM:SS:FF %u%u:%u%u:%u%u\n", lba,
+		printf("CDD CMD: %s cmd for lba %d, MM:SS:FF %u%u:%u%u:%u%u\n",
+			context->cmd_buffer.cmd_type == CMD_READ ? "READ" : "SEEK", lba,
 			context->cmd_buffer.b.time.min_high, context->cmd_buffer.b.time.min_low,
 			context->cmd_buffer.b.time.sec_high, context->cmd_buffer.b.time.sec_low,
 			context->cmd_buffer.b.time.frame_high, context->cmd_buffer.b.time.frame_low
@@ -411,6 +416,27 @@
 		}
 		printf("CDD CMD: REPORT REQUEST(%d), format set to %d\n", context->cmd_buffer.b.format.status_type, context->requested_format);
 		break;
+	case CMD_PAUSE:
+		if (context->status == DS_DOOR_OPEN || context->status == DS_TRAY_MOVING || context->status == DS_DISC_LEADOUT || context->status == DS_DISC_LEADIN) {
+			context->error_status = DS_CMD_ERROR;
+			break;
+		}
+		if (context->requested_format == SF_TOCT || context->requested_format == SF_TOCN) {
+			context->requested_format = SF_ABSOLUTE;
+		}
+		if (!context->toc_valid) {
+			context->error_status = DS_CMD_ERROR;
+			break;
+		}
+		if (context->status == DS_STOP) {
+			context->seeking = 1;
+			context->seek_pba = LEADIN_SECTORS + context->media->tracks[0].fake_pregap + context->media->tracks[0].start_lba;
+			printf("CDD CMD: PAUSE, seeking to %u\n", context->seek_pba);
+		} else {
+			puts("CDD CMD: PAUSE");
+		}
+		context->status = DS_PAUSE;
+		break;
 	default:
 		printf("CDD CMD: Unimplemented(%d)\n", context->cmd_buffer.cmd_type);
 	}
--- a/lc8951.c	Sun Jan 30 00:21:58 2022 -0800
+++ b/lc8951.c	Sun Jan 30 11:58:17 2022 -0800
@@ -57,11 +57,12 @@
 #define BIT_DECEN 0x80
 #define BIT_WRRQ  0x04
 
+//STAT0
+#define BIT_CRCOK 0x80
+
 //STAT3
 #define BIT_VALST 0x80
 
-#define DECI_AUTO_CLEAR 575
-
 //datasheet timing info
 //3 cycles for memory operation
 //6 cycles min for DMA-mode host transfer
@@ -77,7 +78,6 @@
 	context->handler_data = handler_data;
 	context->decode_end = CYCLE_NEVER;
 	context->transfer_end = CYCLE_NEVER;
-	context->deci_clear = CYCLE_NEVER;
 }
 
 void lc8951_reg_write(lc8951 *context, uint8_t value)
@@ -142,9 +142,9 @@
 		break;
 	case PTH_WRITE:
 		context->regs[PTH] = value;
-		context->ptl_internal = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer) - 1);
-		context->decoding = 1;
-		context->decode_end = context->cycle + 2352 * context->clock_step * 4;
+		//TODO: Datasheet says any write to PT triggers a decode, but initial tests suggest that's not the case
+		//Need to do more tests with other CTRL0/CTRL1 settings
+		//context->decode_end = context->cycle + 2352 * context->clock_step * 4;
 		break;
 	case RESET:
 		context->comin_count = 0;
@@ -175,7 +175,6 @@
 	}
 	if (context->ar == STAT3) {
 		context->regs[IFSTAT] |= BIT_DECI;
-		context->deci_clear = CYCLE_NEVER;
 	}
 	if (context->ar >= sizeof(context->regs)) {
 		value = 0xFF;
@@ -206,16 +205,18 @@
 		if (context->cycle >= context->decode_end) {
 			context->decode_end = CYCLE_NEVER;
 			context->regs[IFSTAT] &= ~BIT_DECI;
-			context->deci_clear = context->cycle + DECI_AUTO_CLEAR;
 			context->regs[STAT3] &= ~BIT_VALST;
-			uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1);
-			for (int reg = HEAD0; reg < PTL; reg++)
-			{
-				printf("Setting HEAD%d to buffer[%X]\n", reg - HEAD0, block_start);
-				context->regs[reg] =context->buffer[block_start++];
-				block_start &= (sizeof(context->buffer)-1);
+			if (context->ctrl0 & BIT_WRRQ) {
+				uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1);
+				for (int reg = HEAD0; reg < PTL; reg++)
+				{
+					printf("Setting HEAD%d to buffer[%X]\n", reg - HEAD0, block_start);
+					context->regs[reg] =context->buffer[block_start++];
+					block_start &= (sizeof(context->buffer)-1);
+				}
 			}
 			printf("Decode done %X:%X:%X mode %X\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2], context->regs[HEAD3]);
+			context->regs[STAT0] |= BIT_CRCOK;
 		}
 		if (context->transfer_end != CYCLE_NEVER) {
 			if (context->byte_handler(context->handler_data, context->buffer[context->dac & (sizeof(context->buffer)-1)])) {
@@ -237,10 +238,6 @@
 				context->transfer_end = CYCLE_NEVER;
 			}
 		}
-		if (context->cycle >= context->deci_clear) {
-			context->regs[IFSTAT] |= BIT_DECI;
-			context->deci_clear = CYCLE_NEVER;
-		}
 	}
 }
 
@@ -272,12 +269,16 @@
 
 		//header/status regs no longer considered "valid"
 		context->regs[STAT3] |= BIT_VALST;
-		if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN|BIT_WRRQ)) {
-			uint16_t block_start = current_write_addr - 2352;
-			context->regs[PTL] = block_start;
-			context->regs[PTH] = block_start >> 8;
-			printf("Decoding block starting at %X\n", block_start);
-			context->ptl_internal = block_start & (sizeof(context->buffer)-1);
+		//!DECI is set inactive at the same time as !VALST
+		context->regs[IFSTAT] |= BIT_DECI;
+		if (context->ctrl0 & BIT_DECEN) {
+			if (context->ctrl0 & BIT_WRRQ) {
+				uint16_t block_start = current_write_addr - 2352;
+				context->regs[PTL] = block_start;
+				context->regs[PTH] = block_start >> 8;
+			}
+			printf("Decoding block starting at %X\n", context->regs[PTL] | (context->regs[PTH] << 8));
+			//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;
 		}
 	}
@@ -322,7 +323,4 @@
 	if (context->transfer_end != CYCLE_NEVER) {
 		context->transfer_end -= deduction;
 	}
-	if (context->deci_clear != CYCLE_NEVER) {
-		context->transfer_end -= deduction;
-	}
 }
--- a/lc8951.h	Sun Jan 30 00:21:58 2022 -0800
+++ b/lc8951.h	Sun Jan 30 11:58:17 2022 -0800
@@ -12,7 +12,6 @@
 	uint32_t clock_step;
 	uint32_t decode_end;
 	uint32_t transfer_end;
-	uint32_t deci_clear;
 
 	uint8_t  buffer[0x4000];
 
@@ -27,8 +26,6 @@
 	uint8_t  ctrl1;
 	uint8_t  ar;
 	uint8_t  ar_mask;
-	uint8_t  decoding;
-	uint16_t ptl_internal;
 } lc8951;
 
 void lc8951_init(lc8951 *context, lcd8951_byte_recv_fun byte_handler, void *handler_data);