--- cwcbm/common.c 2004/01/07 16:53:58 1.1 +++ cwcbm/common.c 2004/01/10 14:05:59 1.2 @@ -8,23 +8,24 @@ #include "common.h" -/* 1541 crystal frequency (16 MHz) */ -#define CRYSTAL_FREQ 16000000 +/* Effective crystal frequencies */ +#define CRYSTAL_FREQ_1541 4000000 // 4 MHz +#define CRYSTAL_FREQ_8050 6000000 // 6 MHz -/* 1541 RPM */ +/* CBM drive RPM */ #define NOMINAL_RPM 300 /* Catweasel frequency (7 MHz) */ #define CW_FREQ 7080500.0 -/* Bit rate for each speed zone */ -const int bps[4] = { - CRYSTAL_FREQ / 16 / 4, CRYSTAL_FREQ / 15 / 4, - CRYSTAL_FREQ / 14 / 4, CRYSTAL_FREQ / 13 / 4 + +/* 1541 disk format */ +static const int bps_1541[4] = { + CRYSTAL_FREQ_1541 / 16, CRYSTAL_FREQ_1541 / 15, + CRYSTAL_FREQ_1541 / 14, CRYSTAL_FREQ_1541 / 13 }; -/* Standard speeds for tracks */ -const int std_speed[NUM_TRACKS + 1] = { +static const int std_speed_1541[36] = { 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, @@ -32,8 +33,7 @@ const int std_speed[NUM_TRACKS + 1] = { 0, 0, 0, 0, 0 }; -/* Number of sectors per track, for all tracks */ -const int num_sectors[NUM_TRACKS + 1] = { +static const int num_sectors_1541[36] = { 0, 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, 19,19,19,19,19,19,19, @@ -41,11 +41,86 @@ const int num_sectors[NUM_TRACKS + 1] = 17,17,17,17,17 }; +static const struct format_t format_1541 = { + 1, // sides + 35, // tracks_per_side + bps_1541, // bps + std_speed_1541, // std_speed + num_sectors_1541 // num_sectors +}; + +/* 8050 disk format */ +static const int bps_8050[4] = { + CRYSTAL_FREQ_8050 / 16, CRYSTAL_FREQ_8050 / 15, + CRYSTAL_FREQ_8050 / 14, CRYSTAL_FREQ_8050 / 13 +}; + +static const int std_speed_8050[78] = { + 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const int num_sectors_8050[78] = { + 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23 +}; + +static const struct format_t format_8050 = { + 1, // sides + 77, // tracks_per_side + bps_8050, // bps + std_speed_8050, // std_speed + num_sectors_8050 // num_sectors +}; + +/* 8250 disk format */ +static const int std_speed_8250[155] = { + 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const int num_sectors_8250[155] = { + 0, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23 +}; + +static const struct format_t format_8250 = { + 2, // sides + 77, // tracks_per_side + bps_8050, // bps + std_speed_8250, // std_speed + num_sectors_8250 // num_sectors +}; + +/* Selected format */ +const struct format_t *format = NULL; + /* Command line arguments */ int drive_num = 0; int drive_rpm = 360; int drive_40tracks = 0; +int steps_per_track = 1; const char *file_name; @@ -64,39 +139,6 @@ int thresh_table[3] = {0, 0, 0}; unsigned char track_buf[MAX_SECTORS * SECTOR_SIZE]; -/* Delay specified number of milliseconds */ -void msdelay(int ms) -{ - usleep(ms * 1000); -} - - -/* Set speed zone and tables */ -static void set_zone(int track) -{ - int zone = std_speed[track]; - clock_table[0] = 0; - clock_table[1] = CW_FREQ * NOMINAL_RPM * 1 / (bps[zone] * drive_rpm); - clock_table[2] = CW_FREQ * NOMINAL_RPM * 2 / (bps[zone] * drive_rpm); - clock_table[3] = CW_FREQ * NOMINAL_RPM * 3 / (bps[zone] * drive_rpm); - thresh_table[0] = (clock_table[0] + clock_table[1]) / 2; - thresh_table[1] = (clock_table[1] + clock_table[2]) / 2; - thresh_table[2] = (clock_table[2] + clock_table[3]) / 2; -} - - -/* Seek to given CBM track (1..35) and select correct side and speed zone */ -void seek_to(int drive, int track) -{ - // Set speed zone and tables - set_zone(track); - - // Seek to track - catweasel_seek(c.drives + drive, (track - 1) * (drive_40tracks ? 1 : 2)); - msdelay(20); -} - - /* Print usage information */ static void usage(const char *prgname) { @@ -107,6 +149,7 @@ static void usage(const char *prgname) " -h | --help this text\n" " -p | --port n Catweasel I/O port address (hex, required)\n" " -d | --drive n drive number (0 or 1)\n" + " -f | --format n disk format type (1541, 8050, or 8250)\n" " -4 | --40tracks assume 300RPM 40-track drive\n", prgname ); @@ -121,10 +164,13 @@ void parse_args(int argc, char **argv) {"help", 0, 0, 'h'}, {"port", 1, 0, 'p'}, {"drive", 1, 0, 'd'}, + {"format", 1, 0, 'f'}, {"40tracks", 0, 0, '4'}, {NULL, 0, 0, 0} }; + int format_type = 0; + // Init Catweasel struct memset(&c, 0, sizeof(c)); c.msdelay = msdelay; @@ -132,7 +178,7 @@ void parse_args(int argc, char **argv) // Parse arguments for (;;) { int ch; - if ((ch = getopt_long(argc, argv, "hp:d:4", long_opts, NULL)) == -1) + if ((ch = getopt_long(argc, argv, "hp:d:f:4", long_opts, NULL)) == -1) break; switch (ch) { @@ -146,6 +192,13 @@ void parse_args(int argc, char **argv) if (drive_num < 0 || drive_num > 1) usage(argv[0]); break; + case 'f': + format_type = atoi(optarg); + if (format_type == 1541 || format_type == 8050 || format_type == 8250) + select_format(format_type); + else + usage(argv[0]); + break; case '4': drive_rpm = 300; drive_40tracks = 1; @@ -165,6 +218,14 @@ void parse_args(int argc, char **argv) // Check for consistency if (c.iobase == 0) usage(argv[0]); + if (format_type == 0) + select_format(1541); + if (format->tracks_per_side >= 40 && drive_40tracks) { + fprintf(stderr, "Can't use 80 track disk format on 40 track drive\n"); + exit(1); + } + if (format->tracks_per_side < 40 && !drive_40tracks) + steps_per_track = 2; // double step // Set Catweasel type if (c.iobase < 0x1000) @@ -186,6 +247,63 @@ void ioport_access(void) } +/* Delay specified number of milliseconds */ +void msdelay(int ms) +{ + usleep(ms * 1000); +} + + +/* Select disk format */ +void select_format(int type) +{ + switch (type) { + case 1541: + format = &format_1541; + break; + case 8050: + format = &format_8050; + break; + case 8250: + format = &format_8250; + break; + default: + fprintf(stderr, "Invalid disk format type\n"); + exit(1); + } +} + + +/* Set speed zone and tables */ +static void set_zone(int track) +{ + int zone = format->std_speed[track]; + int bps = format->bps[zone]; + clock_table[0] = 0; + clock_table[1] = CW_FREQ * NOMINAL_RPM * 1 / (bps * drive_rpm); + clock_table[2] = CW_FREQ * NOMINAL_RPM * 2 / (bps * drive_rpm); + clock_table[3] = CW_FREQ * NOMINAL_RPM * 3 / (bps * drive_rpm); + thresh_table[0] = (clock_table[0] + clock_table[1]) / 2; + thresh_table[1] = (clock_table[1] + clock_table[2]) / 2; + thresh_table[2] = (clock_table[2] + clock_table[3]) / 2; +} + + +/* Seek to given CBM track (1..35) and select correct side and speed zone */ +void seek_to(int drive, int track) +{ + // Set speed zone and tables + set_zone(track); + + // Seek to track + int cw_track = ((track - 1) % format->tracks_per_side) * steps_per_track; +//cw_track -= 3; +//if (cw_track < 0) cw_track = 0; + catweasel_seek(c.drives + drive, cw_track); + msdelay(20); +} + + /* Start drive */ void start_drive(int drive) {