comparison cdd_mcu.c @ 2141:793715149f16

More accurate seek emulation
author Michael Pavone <pavone@retrodev.com>
date Tue, 22 Mar 2022 20:20:25 -0700
parents 11a3d5b00a66
children d9151d0894c7
comparison
equal deleted inserted replaced
2140:6d0de02a068a 2141:793715149f16
2 #include "backend.h" 2 #include "backend.h"
3 3
4 #define SCD_MCLKS 50000000 4 #define SCD_MCLKS 50000000
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 SECTORS_PER_SECOND 75
8 #define SECTOR_CLOCKS (CD_BLOCK_CLKS/SECTORS_PER_SECOND)
8 #define NIBBLE_CLOCKS (CDD_MCU_DIVIDER * 77) 9 #define NIBBLE_CLOCKS (CDD_MCU_DIVIDER * 77)
9 #define BYTE_CLOCKS (SECTOR_CLOCKS/2352) // 96 10 #define BYTE_CLOCKS (SECTOR_CLOCKS/2352) // 96
10 #define SUBCODE_CLOCKS (SECTOR_CLOCKS/98) 11 #define SUBCODE_CLOCKS (SECTOR_CLOCKS/98)
11 #define PROCESSING_DELAY 54000 //approximate, based on Wondermega M1 measurements 12 #define PROCESSING_DELAY 54000 //approximate, based on Wondermega M1 measurements
12 13
74 { 75 {
75 sum += buffer[i]; 76 sum += buffer[i];
76 } 77 }
77 return (~sum) & 0xF; 78 return (~sum) & 0xF;
78 } 79 }
80
81 #define MIN_CIRCUMFERENCE 144.51f
82 #define MAX_CIRCUMFERENCE 364.42f
83 #define SECTOR_LENGTH 17.3333f
84 // max diameter for program area 116 mm
85 // circumference ~ 364.42 mm
86 // ~ 21 sectors per physical track at edge
87 // ~8 sectors per physical track at start of lead-in
79 #define COARSE_SEEK 2200 //made up numbers 88 #define COARSE_SEEK 2200 //made up numbers
80 #define FINE_SEEK 10 89 #define FINE_SEEK 10
81 static void handle_seek(cdd_mcu *context) 90 static void handle_seek(cdd_mcu *context)
82 { 91 {
83 //TODO: more realistic seeking behavior 92 //TODO: more realistic seeking behavior
85 if (context->seek_pba == context->head_pba) { 94 if (context->seek_pba == context->head_pba) {
86 context->seeking = 0; 95 context->seeking = 0;
87 if (context->status == DS_PAUSE) { 96 if (context->status == DS_PAUSE) {
88 context->pause_pba = context->head_pba; 97 context->pause_pba = context->head_pba;
89 } 98 }
90 } else if (context->seek_pba > context->head_pba) {
91 if (context->seek_pba - context->head_pba >= COARSE_SEEK || context->head_pba < LEADIN_SECTORS) {
92 context->head_pba += COARSE_SEEK;
93 } else if (context->seek_pba - context->head_pba >= FINE_SEEK) {
94 context->head_pba += FINE_SEEK;
95 } else {
96 context->head_pba++;
97 }
98 } else { 99 } else {
99 if (context->head_pba - context->seek_pba >= COARSE_SEEK) { 100 //TODO: better estimate of sectors per track at current head location
100 context->head_pba -= COARSE_SEEK; 101 float circumference = (MAX_CIRCUMFERENCE-MIN_CIRCUMFERENCE) * ((float)context->head_pba) / (74 * 60 * SECTORS_PER_SECOND) + MIN_CIRCUMFERENCE;
101 } else if (context->head_pba >= FINE_SEEK) { 102 float sectors_per_track = circumference / SECTOR_LENGTH;
102 context->head_pba -= FINE_SEEK; 103 uint32_t max_seek = sectors_per_track * 190;
103 } else { 104 uint32_t min_seek = sectors_per_track;
104 context->head_pba = 0; 105
106
107 if (context->seek_pba > context->head_pba) {
108 uint32_t seek_amount;
109 for (seek_amount = max_seek; seek_amount >= min_seek; seek_amount >>= 1)
110 {
111 if (context->seek_pba - context->head_pba >= seek_amount) {
112 break;
113 }
114 }
115 if (seek_amount >= min_seek) {
116 context->head_pba += seek_amount;
117 } else {
118 context->head_pba++;
119 }
120 } else {
121 uint32_t seek_amount;
122 for (seek_amount = max_seek; seek_amount >= min_seek; seek_amount >>= 1)
123 {
124 if (context->head_pba - context->seek_pba >= seek_amount) {
125 break;
126 }
127 }
128 if (seek_amount >= min_seek) {
129 context->head_pba -= seek_amount;
130 } else if (context->head_pba >= min_seek){
131 context->head_pba -= min_seek;
132 } else {
133 context->head_pba = 0;
134 }
105 } 135 }
106 } 136 }
107 } 137 }
108 } 138 }
109 139
404 ); 434 );
405 if (lba >= context->media->tracks[0].fake_pregap + context->media->tracks[context->media->num_tracks - 1].end_lba) { 435 if (lba >= context->media->tracks[0].fake_pregap + context->media->tracks[context->media->num_tracks - 1].end_lba) {
406 context->error_status = DS_CMD_ERROR; 436 context->error_status = DS_CMD_ERROR;
407 break; 437 break;
408 } 438 }
409 context->seek_pba = lba + LEADIN_SECTORS - 4; 439 context->seek_pba = lba + LEADIN_SECTORS - 3;
410 context->seeking = 1; 440 context->seeking = 1;
411 context->status = context->cmd_buffer.cmd_type == CMD_READ ? DS_PLAY : DS_PAUSE; 441 context->status = context->cmd_buffer.cmd_type == CMD_READ ? DS_PLAY : DS_PAUSE;
412 break; 442 break;
413 } 443 }
414 case CMD_REPORT_REQUEST: 444 case CMD_REPORT_REQUEST: