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 }