Mercurial > repos > blastem
comparison lc8951.c @ 2066:a61a8a87410c segacd
Fix a bunch of CDC/CDD related mcd-verificator failures
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 30 Jan 2022 00:21:58 -0800 |
parents | 02a9846668d1 |
children | f22e04b69272 |
comparison
equal
deleted
inserted
replaced
2065:02a9846668d1 | 2066:a61a8a87410c |
---|---|
58 #define BIT_WRRQ 0x04 | 58 #define BIT_WRRQ 0x04 |
59 | 59 |
60 //STAT3 | 60 //STAT3 |
61 #define BIT_VALST 0x80 | 61 #define BIT_VALST 0x80 |
62 | 62 |
63 #define DECI_AUTO_CLEAR 575 | |
64 | |
63 //datasheet timing info | 65 //datasheet timing info |
64 //3 cycles for memory operation | 66 //3 cycles for memory operation |
65 //6 cycles min for DMA-mode host transfer | 67 //6 cycles min for DMA-mode host transfer |
66 | 68 |
67 void lc8951_init(lc8951 *context, lcd8951_byte_recv_fun byte_handler, void *handler_data) | 69 void lc8951_init(lc8951 *context, lcd8951_byte_recv_fun byte_handler, void *handler_data) |
73 context->clock_step = (2 + 2) * 6; // external divider, internal divider + DMA period | 75 context->clock_step = (2 + 2) * 6; // external divider, internal divider + DMA period |
74 context->byte_handler = byte_handler; | 76 context->byte_handler = byte_handler; |
75 context->handler_data = handler_data; | 77 context->handler_data = handler_data; |
76 context->decode_end = CYCLE_NEVER; | 78 context->decode_end = CYCLE_NEVER; |
77 context->transfer_end = CYCLE_NEVER; | 79 context->transfer_end = CYCLE_NEVER; |
80 context->deci_clear = CYCLE_NEVER; | |
78 } | 81 } |
79 | 82 |
80 void lc8951_reg_write(lc8951 *context, uint8_t value) | 83 void lc8951_reg_write(lc8951 *context, uint8_t value) |
81 { | 84 { |
82 printf("CDC write %X: %X\n", context->ar, value); | |
83 switch (context->ar) | 85 switch (context->ar) |
84 { | 86 { |
85 case SBOUT: | 87 case SBOUT: |
86 context->regs[context->ar] = value; | 88 context->regs[context->ar] = value; |
87 if (context->ifctrl & BIT_SOUTEN) { | 89 if (context->ifctrl & BIT_SOUTEN) { |
92 context->ifctrl = value; | 94 context->ifctrl = value; |
93 if (!(value & BIT_SOUTEN)) { | 95 if (!(value & BIT_SOUTEN)) { |
94 context->regs[IFSTAT] |= BIT_STBSY; | 96 context->regs[IFSTAT] |= BIT_STBSY; |
95 } | 97 } |
96 if (!(value & BIT_DOUTEN)) { | 98 if (!(value & BIT_DOUTEN)) { |
97 context->regs[IFSTAT] |= BIT_DTBSY; | 99 context->regs[IFSTAT] |= BIT_DTBSY|BIT_DTEI; |
98 context->transfer_end = CYCLE_NEVER; | 100 context->transfer_end = CYCLE_NEVER; |
99 } | 101 } |
100 break; | 102 break; |
101 case DBCL: | 103 case DBCL: |
102 context->regs[context->ar] = value; | 104 context->regs[context->ar] = value; |
171 } | 173 } |
172 return value; | 174 return value; |
173 } | 175 } |
174 if (context->ar == STAT3) { | 176 if (context->ar == STAT3) { |
175 context->regs[IFSTAT] |= BIT_DECI; | 177 context->regs[IFSTAT] |= BIT_DECI; |
178 context->deci_clear = CYCLE_NEVER; | |
176 } | 179 } |
177 if (context->ar >= sizeof(context->regs)) { | 180 if (context->ar >= sizeof(context->regs)) { |
178 value = 0xFF; | 181 value = 0xFF; |
179 } else { | 182 } else { |
180 value = context->regs[context->ar]; | 183 value = context->regs[context->ar]; |
201 for(; context->cycle < cycle; context->cycle += context->clock_step) | 204 for(; context->cycle < cycle; context->cycle += context->clock_step) |
202 { | 205 { |
203 if (context->cycle >= context->decode_end) { | 206 if (context->cycle >= context->decode_end) { |
204 context->decode_end = CYCLE_NEVER; | 207 context->decode_end = CYCLE_NEVER; |
205 context->regs[IFSTAT] &= ~BIT_DECI; | 208 context->regs[IFSTAT] &= ~BIT_DECI; |
209 context->deci_clear = context->cycle + DECI_AUTO_CLEAR; | |
206 context->regs[STAT3] &= ~BIT_VALST; | 210 context->regs[STAT3] &= ~BIT_VALST; |
207 uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1); | 211 uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1); |
208 for (int reg = HEAD0; reg < PTL; reg++) | 212 for (int reg = HEAD0; reg < PTL; reg++) |
209 { | 213 { |
210 printf("Setting HEAD%d to buffer[%X]\n", reg - HEAD0, block_start); | 214 printf("Setting HEAD%d to buffer[%X]\n", reg - HEAD0, block_start); |
231 } else { | 235 } else { |
232 // pause transfer | 236 // pause transfer |
233 context->transfer_end = CYCLE_NEVER; | 237 context->transfer_end = CYCLE_NEVER; |
234 } | 238 } |
235 } | 239 } |
236 } | 240 if (context->cycle >= context->deci_clear) { |
237 } | 241 context->regs[IFSTAT] |= BIT_DECI; |
238 | 242 context->deci_clear = CYCLE_NEVER; |
239 void lc8951_resume_transfer(lc8951 *context) | 243 } |
244 } | |
245 } | |
246 | |
247 void lc8951_resume_transfer(lc8951 *context, uint32_t cycle) | |
240 { | 248 { |
241 if (context->transfer_end == CYCLE_NEVER && (context->ifctrl & BIT_DOUTEN)) { | 249 if (context->transfer_end == CYCLE_NEVER && (context->ifctrl & BIT_DOUTEN)) { |
242 uint16_t transfer_size = context->regs[DBCL] | (context->regs[DBCH] << 8); | 250 uint16_t transfer_size = context->regs[DBCL] | (context->regs[DBCH] << 8); |
243 if (transfer_size) { | 251 if (transfer_size != 0xFFFF) { |
252 //HACK!!! Work around Sub CPU running longer than we would like and dragging other components with it | |
253 uint32_t step_diff = (context->cycle - cycle) / context->clock_step; | |
254 if (step_diff) { | |
255 context->cycle -= step_diff * context->clock_step; | |
256 } | |
244 context->transfer_end = context->cycle + transfer_size * context->clock_step; | 257 context->transfer_end = context->cycle + transfer_size * context->clock_step; |
245 printf("RESUME: size %u, cycle %u, end %u\n", transfer_size, context->cycle, context->transfer_end); | 258 printf("RESUME: size %u, cycle %u, end %u\n", transfer_size, context->cycle, context->transfer_end); |
259 if (step_diff) { | |
260 lc8951_run(context, cycle); | |
261 } | |
246 } | 262 } |
247 } | 263 } |
248 } | 264 } |
249 | 265 |
250 void lc8951_write_byte(lc8951 *context, uint32_t cycle, int sector_offset, uint8_t byte) | 266 void lc8951_write_byte(lc8951 *context, uint32_t cycle, int sector_offset, uint8_t byte) |
295 if (context->ifctrl & BIT_DTEI) { | 311 if (context->ifctrl & BIT_DTEI) { |
296 dtei_cycle = context->transfer_end; | 312 dtei_cycle = context->transfer_end; |
297 } | 313 } |
298 return deci_cycle < dtei_cycle ? deci_cycle : dtei_cycle; | 314 return deci_cycle < dtei_cycle ? deci_cycle : dtei_cycle; |
299 } | 315 } |
316 | |
317 void lc8951_adjust_cycles(lc8951 *context, uint32_t deduction) | |
318 { | |
319 if (context->decode_end != CYCLE_NEVER) { | |
320 context->decode_end -= deduction; | |
321 } | |
322 if (context->transfer_end != CYCLE_NEVER) { | |
323 context->transfer_end -= deduction; | |
324 } | |
325 if (context->deci_clear != CYCLE_NEVER) { | |
326 context->transfer_end -= deduction; | |
327 } | |
328 } |