comparison lc8951.c @ 2144:10e4439d8f13

Fix speed of CDC to PCM RAM DMA
author Michael Pavone <pavone@retrodev.com>
date Sat, 26 Mar 2022 00:54:47 -0700
parents d9151d0894c7
children 4cd60eecb0b1
comparison
equal deleted inserted replaced
2143:67f20f9188b0 2144:10e4439d8f13
83 { 83 {
84 //This seems to vary somewhat between Sega CD models 84 //This seems to vary somewhat between Sega CD models
85 //unclear if the difference is in the lc8951 or gate array 85 //unclear if the difference is in the lc8951 or gate array
86 context->regs[IFSTAT] = 0xFF; 86 context->regs[IFSTAT] = 0xFF;
87 context->ar_mask = 0x1F; 87 context->ar_mask = 0x1F;
88 context->clock_step = (2 + 2) * 6; // external divider, internal divider + DMA period 88 context->clock_step = (2 + 2); // external divider, internal divider
89 context->cycles_per_byte = context->clock_step * 6;
89 context->byte_handler = byte_handler; 90 context->byte_handler = byte_handler;
90 context->handler_data = handler_data; 91 context->handler_data = handler_data;
91 context->decode_end = CYCLE_NEVER; 92 context->decode_end = CYCLE_NEVER;
92 context->transfer_end = CYCLE_NEVER; 93 context->transfer_end = CYCLE_NEVER;
94 context->next_byte_cycle = CYCLE_NEVER;
95 }
96
97 void lc8951_set_dma_multiple(lc8951 *context, uint32_t multiple)
98 {
99 context->cycles_per_byte = context->clock_step * multiple;
100 if (context->transfer_end != CYCLE_NEVER) {
101 uint16_t transfer_size = context->regs[DBCL] | (context->regs[DBCH] << 8);
102 context->transfer_end = context->next_byte_cycle + transfer_size * context->cycles_per_byte;
103 }
93 } 104 }
94 105
95 void lc8951_reg_write(lc8951 *context, uint8_t value) 106 void lc8951_reg_write(lc8951 *context, uint8_t value)
96 { 107 {
97 switch (context->ar) 108 switch (context->ar)
128 break; 139 break;
129 case DTTRG: 140 case DTTRG:
130 if (context->ifctrl & BIT_DOUTEN) { 141 if (context->ifctrl & BIT_DOUTEN) {
131 context->regs[IFSTAT] &= ~BIT_DTBSY; 142 context->regs[IFSTAT] &= ~BIT_DTBSY;
132 uint16_t transfer_size = context->regs[DBCL] | (context->regs[DBCH] << 8); 143 uint16_t transfer_size = context->regs[DBCL] | (context->regs[DBCH] << 8);
133 context->transfer_end = context->cycle + transfer_size * context->clock_step; 144 context->transfer_end = context->cycle + transfer_size * context->cycles_per_byte;
145 context->next_byte_cycle = context->cycle;
134 printf("DTTRG: size %u, cycle %u, end %u\n", transfer_size, context->cycle, context->transfer_end); 146 printf("DTTRG: size %u, cycle %u, end %u\n", transfer_size, context->cycle, context->transfer_end);
135 } 147 }
136 break; 148 break;
137 case DTACK: 149 case DTACK:
138 context->regs[IFSTAT] |= BIT_DTEI; 150 context->regs[IFSTAT] |= BIT_DTEI;
249 context->regs[STAT1] = 0xFF; 261 context->regs[STAT1] = 0xFF;
250 context->regs[STAT2] = 0xF2; 262 context->regs[STAT2] = 0xF2;
251 } 263 }
252 context->regs[STAT3] |= BIT_WLONG; 264 context->regs[STAT3] |= BIT_WLONG;
253 } 265 }
254 if (context->transfer_end != CYCLE_NEVER) { 266 if (context->cycle >= context->next_byte_cycle) {
255 if (context->byte_handler(context->handler_data, context->buffer[context->dac & (sizeof(context->buffer)-1)])) { 267 if (context->byte_handler(context->handler_data, context->buffer[context->dac & (sizeof(context->buffer)-1)])) {
268 context->next_byte_cycle += context->cycles_per_byte;
256 context->dac++; 269 context->dac++;
257 context->regs[DBCL]--; 270 context->regs[DBCL]--;
258 if (context->regs[DBCL] == 0xFF) { 271 if (context->regs[DBCL] == 0xFF) {
259 context->regs[DBCH]--; 272 context->regs[DBCH]--;
260 if (context->regs[DBCH] == 0xFF) { 273 if (context->regs[DBCH] == 0xFF) {
262 context->regs[IFSTAT] |= BIT_DTBSY; 275 context->regs[IFSTAT] |= BIT_DTBSY;
263 if (context->cycle != context->transfer_end) { 276 if (context->cycle != context->transfer_end) {
264 printf("Expected transfer end at %u but ended at %u\n", context->transfer_end, context->cycle); 277 printf("Expected transfer end at %u but ended at %u\n", context->transfer_end, context->cycle);
265 } 278 }
266 context->transfer_end = CYCLE_NEVER; 279 context->transfer_end = CYCLE_NEVER;
280 context->next_byte_cycle = CYCLE_NEVER;
267 } 281 }
268 } 282 }
269 } else { 283 } else {
270 // pause transfer 284 // pause transfer
285 context->next_byte_cycle = CYCLE_NEVER;
271 context->transfer_end = CYCLE_NEVER; 286 context->transfer_end = CYCLE_NEVER;
272 } 287 }
273 } 288 }
274 } 289 }
275 } 290 }
282 //HACK!!! Work around Sub CPU running longer than we would like and dragging other components with it 297 //HACK!!! Work around Sub CPU running longer than we would like and dragging other components with it
283 uint32_t step_diff = (context->cycle - cycle) / context->clock_step; 298 uint32_t step_diff = (context->cycle - cycle) / context->clock_step;
284 if (step_diff) { 299 if (step_diff) {
285 context->cycle -= step_diff * context->clock_step; 300 context->cycle -= step_diff * context->clock_step;
286 } 301 }
287 context->transfer_end = context->cycle + transfer_size * context->clock_step; 302 context->transfer_end = context->cycle + transfer_size * context->cycles_per_byte;
303 context->next_byte_cycle = context->cycle;
288 if (step_diff) { 304 if (step_diff) {
289 lc8951_run(context, cycle); 305 lc8951_run(context, cycle);
290 } 306 }
291 } 307 }
292 } 308 }