comparison cdd_mcu.c @ 2115:e93ced356a21

Hopefully more accurate relative timing of CDD status and data reaching the CDC
author Michael Pavone <pavone@retrodev.com>
date Sat, 05 Mar 2022 14:17:59 -0800
parents 539450d905b3
children cd057d6fe030
comparison
equal deleted inserted replaced
2114:2449c88cea36 2115:e93ced356a21
5 #define CD_BLOCK_CLKS 16934400 5 #define CD_BLOCK_CLKS 16934400
6 #define CDD_MCU_DIVIDER 8 6 #define CDD_MCU_DIVIDER 8
7 #define SECTOR_CLOCKS (CD_BLOCK_CLKS/75) 7 #define SECTOR_CLOCKS (CD_BLOCK_CLKS/75)
8 #define NIBBLE_CLOCKS (CDD_MCU_DIVIDER * 77) 8 #define NIBBLE_CLOCKS (CDD_MCU_DIVIDER * 77)
9 #define BYTE_CLOCKS (SECTOR_CLOCKS/2352) // 96 9 #define BYTE_CLOCKS (SECTOR_CLOCKS/2352) // 96
10 #define PROCESSING_DELAY 54000 //approximate, based on Wondermega M1 measurements
10 11
11 //lead in start max diameter 46 mm 12 //lead in start max diameter 46 mm
12 //program area start max diameter 50 mm 13 //program area start max diameter 50 mm
13 //difference 4 mm = 4000 um 14 //difference 4 mm = 4000 um
14 //radius difference 2 mm = 2000 um 15 //radius difference 2 mm = 2000 um
114 } 115 }
115 116
116 static void update_status(cdd_mcu *context, uint16_t *gate_array) 117 static void update_status(cdd_mcu *context, uint16_t *gate_array)
117 { 118 {
118 gate_array[GAO_CDD_CTRL] |= BIT_MUTE; 119 gate_array[GAO_CDD_CTRL] |= BIT_MUTE;
120 uint32_t prev_pba = context->head_pba;
119 switch (context->status) 121 switch (context->status)
120 { 122 {
121 case DS_PLAY: 123 case DS_PLAY:
122 handle_seek(context); 124 handle_seek(context);
123 if (!context->seeking) { 125 if (!context->seeking) {
181 } 183 }
182 if (context->first_cmd_received) { 184 if (context->first_cmd_received) {
183 switch (context->requested_format) 185 switch (context->requested_format)
184 { 186 {
185 case SF_ABSOLUTE: 187 case SF_ABSOLUTE:
186 if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) { 188 if (context->toc_valid && prev_pba >= LEADIN_SECTORS) {
187 lba_to_status(context, context->head_pba - LEADIN_SECTORS); 189 lba_to_status(context, prev_pba - LEADIN_SECTORS);
188 context->status_buffer.format = SF_ABSOLUTE; 190 context->status_buffer.format = SF_ABSOLUTE;
189 } else { 191 } else {
190 context->status_buffer.format = SF_NOTREADY; 192 context->status_buffer.format = SF_NOTREADY;
191 } 193 }
192 break; 194 break;
193 case SF_RELATIVE: 195 case SF_RELATIVE:
194 if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) { 196 if (context->toc_valid && prev_pba >= LEADIN_SECTORS) {
195 uint32_t lba =context->head_pba - LEADIN_SECTORS; 197 uint32_t lba =prev_pba - LEADIN_SECTORS;
196 for (uint32_t i = 0; i < context->media->num_tracks; i++) 198 for (uint32_t i = 0; i < context->media->num_tracks; i++)
197 { 199 {
198 if (lba < context->media->tracks[i].end_lba) { 200 if (lba < context->media->tracks[i].end_lba) {
199 if (context->media->tracks[i].fake_pregap) { 201 if (context->media->tracks[i].fake_pregap) {
200 if (lba > context->media->tracks[i].fake_pregap) { 202 if (lba > context->media->tracks[i].fake_pregap) {
221 } else { 223 } else {
222 context->status_buffer.format = SF_NOTREADY; 224 context->status_buffer.format = SF_NOTREADY;
223 } 225 }
224 break; 226 break;
225 case SF_TRACK: 227 case SF_TRACK:
226 if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) { 228 if (context->toc_valid && prev_pba >= LEADIN_SECTORS) {
227 uint32_t lba =context->head_pba - LEADIN_SECTORS; 229 uint32_t lba =prev_pba - LEADIN_SECTORS;
228 uint32_t i; 230 uint32_t i;
229 for (i = 0; i < context->media->num_tracks; i++) 231 for (i = 0; i < context->media->num_tracks; i++)
230 { 232 {
231 if (lba < context->media->tracks[i].end_lba) { 233 if (lba < context->media->tracks[i].end_lba) {
232 if (context->media->tracks[i].fake_pregap) { 234 if (context->media->tracks[i].fake_pregap) {
538 } 540 }
539 gate_array[GAO_CDD_CTRL] |= BIT_MUTE; 541 gate_array[GAO_CDD_CTRL] |= BIT_MUTE;
540 return; 542 return;
541 } 543 }
542 uint32_t next_subcode = context->last_subcode_cycle + SECTOR_CLOCKS; 544 uint32_t next_subcode = context->last_subcode_cycle + SECTOR_CLOCKS;
543 uint32_t next_nibble = context->current_status_nibble >= 0 ? context->last_nibble_cycle + NIBBLE_CLOCKS : CYCLE_NEVER; 545 uint32_t next_nibble;
546 if (context->current_status_nibble > 0) {
547 next_nibble = context->last_nibble_cycle + NIBBLE_CLOCKS;
548 } else if (!context->current_status_nibble) {
549 next_nibble = context->last_subcode_cycle + PROCESSING_DELAY;
550 } else {
551 next_nibble = CYCLE_NEVER;
552 }
544 uint32_t next_cmd_nibble = context->current_cmd_nibble >= 0 ? context->last_nibble_cycle + NIBBLE_CLOCKS : CYCLE_NEVER; 553 uint32_t next_cmd_nibble = context->current_cmd_nibble >= 0 ? context->last_nibble_cycle + NIBBLE_CLOCKS : CYCLE_NEVER;
545 554
546 for (; context->cycle < cd_cycle; context->cycle += CDD_MCU_DIVIDER) 555 for (; context->cycle < cd_cycle; context->cycle += CDD_MCU_DIVIDER)
547 { 556 {
548 if (context->cycle >= next_subcode) { 557 if (context->cycle >= next_subcode) {
549 context->last_subcode_cycle = context->cycle; 558 context->last_subcode_cycle = context->cycle;
550 next_subcode = context->cycle + SECTOR_CLOCKS; 559 next_subcode = context->cycle + SECTOR_CLOCKS;
551 update_status(context, gate_array); 560 update_status(context, gate_array);
552 next_nibble = context->cycle; 561 next_nibble = context->cycle + PROCESSING_DELAY;
553 context->current_status_nibble = 0; 562 context->current_status_nibble = 0;
554 gate_array[GAO_CDD_STATUS] |= BIT_DRS; 563 gate_array[GAO_CDD_STATUS] |= BIT_DRS;
555 if ((context->status == DS_PLAY || context->status == DS_PAUSE) && context->head_pba >= LEADIN_SECTORS) { 564 if ((context->status == DS_PLAY || context->status == DS_PAUSE) && context->head_pba >= LEADIN_SECTORS) {
556 context->current_sector_byte = 0; 565 context->current_sector_byte = 0;
557 } 566 }
633 } 642 }
634 643
635 void cdd_hock_enabled(cdd_mcu *context) 644 void cdd_hock_enabled(cdd_mcu *context)
636 { 645 {
637 context->last_subcode_cycle = context->cycle; 646 context->last_subcode_cycle = context->cycle;
638 context->next_int_cycle = cd_block_to_mclks(context->cycle + SECTOR_CLOCKS + 7 * NIBBLE_CLOCKS); 647 context->next_int_cycle = cd_block_to_mclks(context->cycle + SECTOR_CLOCKS + PROCESSING_DELAY + 7 * NIBBLE_CLOCKS);
639 } 648 }
640 649
641 void cdd_hock_disabled(cdd_mcu *context) 650 void cdd_hock_disabled(cdd_mcu *context)
642 { 651 {
643 context->last_subcode_cycle = CYCLE_NEVER; 652 context->last_subcode_cycle = CYCLE_NEVER;