Mercurial > repos > blastem
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; |