comparison lc8951.c @ 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 c69e42444f96
comparison
equal deleted inserted replaced
2066:a61a8a87410c 2067:f22e04b69272
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 59
60 //STAT0
61 #define BIT_CRCOK 0x80
62
60 //STAT3 63 //STAT3
61 #define BIT_VALST 0x80 64 #define BIT_VALST 0x80
62
63 #define DECI_AUTO_CLEAR 575
64 65
65 //datasheet timing info 66 //datasheet timing info
66 //3 cycles for memory operation 67 //3 cycles for memory operation
67 //6 cycles min for DMA-mode host transfer 68 //6 cycles min for DMA-mode host transfer
68 69
75 context->clock_step = (2 + 2) * 6; // external divider, internal divider + DMA period 76 context->clock_step = (2 + 2) * 6; // external divider, internal divider + DMA period
76 context->byte_handler = byte_handler; 77 context->byte_handler = byte_handler;
77 context->handler_data = handler_data; 78 context->handler_data = handler_data;
78 context->decode_end = CYCLE_NEVER; 79 context->decode_end = CYCLE_NEVER;
79 context->transfer_end = CYCLE_NEVER; 80 context->transfer_end = CYCLE_NEVER;
80 context->deci_clear = CYCLE_NEVER;
81 } 81 }
82 82
83 void lc8951_reg_write(lc8951 *context, uint8_t value) 83 void lc8951_reg_write(lc8951 *context, uint8_t value)
84 { 84 {
85 switch (context->ar) 85 switch (context->ar)
140 case PTL_WRITE: 140 case PTL_WRITE:
141 context->regs[PTL] = value; 141 context->regs[PTL] = value;
142 break; 142 break;
143 case PTH_WRITE: 143 case PTH_WRITE:
144 context->regs[PTH] = value; 144 context->regs[PTH] = value;
145 context->ptl_internal = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer) - 1); 145 //TODO: Datasheet says any write to PT triggers a decode, but initial tests suggest that's not the case
146 context->decoding = 1; 146 //Need to do more tests with other CTRL0/CTRL1 settings
147 context->decode_end = context->cycle + 2352 * context->clock_step * 4; 147 //context->decode_end = context->cycle + 2352 * context->clock_step * 4;
148 break; 148 break;
149 case RESET: 149 case RESET:
150 context->comin_count = 0; 150 context->comin_count = 0;
151 context->regs[IFSTAT] = 0xFF; 151 context->regs[IFSTAT] = 0xFF;
152 break; 152 break;
173 } 173 }
174 return value; 174 return value;
175 } 175 }
176 if (context->ar == STAT3) { 176 if (context->ar == STAT3) {
177 context->regs[IFSTAT] |= BIT_DECI; 177 context->regs[IFSTAT] |= BIT_DECI;
178 context->deci_clear = CYCLE_NEVER;
179 } 178 }
180 if (context->ar >= sizeof(context->regs)) { 179 if (context->ar >= sizeof(context->regs)) {
181 value = 0xFF; 180 value = 0xFF;
182 } else { 181 } else {
183 value = context->regs[context->ar]; 182 value = context->regs[context->ar];
204 for(; context->cycle < cycle; context->cycle += context->clock_step) 203 for(; context->cycle < cycle; context->cycle += context->clock_step)
205 { 204 {
206 if (context->cycle >= context->decode_end) { 205 if (context->cycle >= context->decode_end) {
207 context->decode_end = CYCLE_NEVER; 206 context->decode_end = CYCLE_NEVER;
208 context->regs[IFSTAT] &= ~BIT_DECI; 207 context->regs[IFSTAT] &= ~BIT_DECI;
209 context->deci_clear = context->cycle + DECI_AUTO_CLEAR;
210 context->regs[STAT3] &= ~BIT_VALST; 208 context->regs[STAT3] &= ~BIT_VALST;
211 uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1); 209 if (context->ctrl0 & BIT_WRRQ) {
212 for (int reg = HEAD0; reg < PTL; reg++) 210 uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1);
213 { 211 for (int reg = HEAD0; reg < PTL; reg++)
214 printf("Setting HEAD%d to buffer[%X]\n", reg - HEAD0, block_start); 212 {
215 context->regs[reg] =context->buffer[block_start++]; 213 printf("Setting HEAD%d to buffer[%X]\n", reg - HEAD0, block_start);
216 block_start &= (sizeof(context->buffer)-1); 214 context->regs[reg] =context->buffer[block_start++];
215 block_start &= (sizeof(context->buffer)-1);
216 }
217 } 217 }
218 printf("Decode done %X:%X:%X mode %X\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2], context->regs[HEAD3]); 218 printf("Decode done %X:%X:%X mode %X\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2], context->regs[HEAD3]);
219 context->regs[STAT0] |= BIT_CRCOK;
219 } 220 }
220 if (context->transfer_end != CYCLE_NEVER) { 221 if (context->transfer_end != CYCLE_NEVER) {
221 if (context->byte_handler(context->handler_data, context->buffer[context->dac & (sizeof(context->buffer)-1)])) { 222 if (context->byte_handler(context->handler_data, context->buffer[context->dac & (sizeof(context->buffer)-1)])) {
222 context->dac++; 223 context->dac++;
223 context->regs[DBCL]--; 224 context->regs[DBCL]--;
235 } else { 236 } else {
236 // pause transfer 237 // pause transfer
237 context->transfer_end = CYCLE_NEVER; 238 context->transfer_end = CYCLE_NEVER;
238 } 239 }
239 } 240 }
240 if (context->cycle >= context->deci_clear) {
241 context->regs[IFSTAT] |= BIT_DECI;
242 context->deci_clear = CYCLE_NEVER;
243 }
244 } 241 }
245 } 242 }
246 243
247 void lc8951_resume_transfer(lc8951 *context, uint32_t cycle) 244 void lc8951_resume_transfer(lc8951 *context, uint32_t cycle)
248 { 245 {
270 if (sector_offset == 12) { 267 if (sector_offset == 12) {
271 //we've recevied the sync pattern for the next block 268 //we've recevied the sync pattern for the next block
272 269
273 //header/status regs no longer considered "valid" 270 //header/status regs no longer considered "valid"
274 context->regs[STAT3] |= BIT_VALST; 271 context->regs[STAT3] |= BIT_VALST;
275 if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN|BIT_WRRQ)) { 272 //!DECI is set inactive at the same time as !VALST
276 uint16_t block_start = current_write_addr - 2352; 273 context->regs[IFSTAT] |= BIT_DECI;
277 context->regs[PTL] = block_start; 274 if (context->ctrl0 & BIT_DECEN) {
278 context->regs[PTH] = block_start >> 8; 275 if (context->ctrl0 & BIT_WRRQ) {
279 printf("Decoding block starting at %X\n", block_start); 276 uint16_t block_start = current_write_addr - 2352;
280 context->ptl_internal = block_start & (sizeof(context->buffer)-1); 277 context->regs[PTL] = block_start;
278 context->regs[PTH] = block_start >> 8;
279 }
280 printf("Decoding block starting at %X\n", context->regs[PTL] | (context->regs[PTH] << 8));
281 //TODO: Datasheet has some hints about how long decoding takes in the form of how long DECI is asserted
281 context->decode_end = context->cycle + 2352 * context->clock_step * 4; 282 context->decode_end = context->cycle + 2352 * context->clock_step * 4;
282 } 283 }
283 } 284 }
284 if (sector_offset >= 12 && sector_offset < 16) { 285 if (sector_offset >= 12 && sector_offset < 16) {
285 //TODO: Handle SHDREN = 1 286 //TODO: Handle SHDREN = 1
320 context->decode_end -= deduction; 321 context->decode_end -= deduction;
321 } 322 }
322 if (context->transfer_end != CYCLE_NEVER) { 323 if (context->transfer_end != CYCLE_NEVER) {
323 context->transfer_end -= deduction; 324 context->transfer_end -= deduction;
324 } 325 }
325 if (context->deci_clear != CYCLE_NEVER) { 326 }
326 context->transfer_end -= deduction;
327 }
328 }