Magic‐1 CF Card Communication Protocol - retrotruestory/M1DEV GitHub Wiki
Magic-1 CF Card Communication Protocol
Based on the source code, here's how the Magic-1 communicates with the CF card:
CF Card Interface Configuration
// CF Configuration Constants
#define CF_MODE 0xE0 // MASTER, LBA mode
#define FEATURE_8_BIT 0x01 // 8-bit mode
#define CF_MASTER 0x02 // CF as master device
// Base I/O Address
unsigned char* cf_base = (unsigned char*)0xFF98;
CF Register Map
// CF Card Registers
#define DATA_PORT 0 // Data register
#define ERROR_REG 1 // Error register
#define FEATURE_REG 1 // Feature register
#define NUM_SECTORS 2 // Number of sectors
#define LBA_0 3 // LBA bits 0-7
#define LBA_1 4 // LBA bits 8-15
#define LBA_2 5 // LBA bits 16-23
#define LBA_3 6 // LBA bits 24-27 and mode
#define COMMAND_REG 7 // Command register
#define STATUS_REG 7 // Status register
Command Set
// CF Command Set
#define CMD_SET_FEATURE 0xEF // Set feature command
#define CMD_RESET 0x04 // Reset device
#define CMD_DRIVE_ID 0xEC // Identify device
#define CMD_READ 0x20 // Read sectors
#define CMD_WRITE 0x30 // Write sectors
Communication Protocol
- Card Initialization:
void cf_init(int drive, int mode) {
// Reset CF card
cf_base[FEATURE_REG] = CMD_RESET;
cf_wait();
// Set 8-bit mode
cf_base[LBA_3] = mode;
cf_base[FEATURE_REG] = FEATURE_8_BIT;
cf_base[COMMAND_REG] = CMD_SET_FEATURE;
cf_wait();
}
- Reading a Sector:
void cf_read_sector(int sector, char* buf, int drive) {
// Setup LBA addressing
cf_sector_setup(sector);
// Issue read command
cf_cmd_ready();
cf_base[COMMAND_REG] = CMD_READ;
// Read 512 bytes
cf_read_512(buf);
}
- Writing a Sector:
void cf_write_sector(int sector, char* buf, int drive) {
// Setup LBA addressing
cf_sector_setup(sector);
// Issue write command
cf_cmd_ready();
cf_base[COMMAND_REG] = CMD_WRITE;
// Write 512 bytes
cf_write_512(buf);
}
Status Checking
// Status Register Bits
#define BUSY_FLAG 0x80 // Card is busy
#define DRQ3_FLAG 0x08 // Data request
#define DRVRDY6_FLAG 0x40 // Drive ready
// Wait for card to be ready
int cf_wait() {
for (i = 0; i < 30000; i++) {
if ((cf_base[STATUS_REG] & BUSY_FLAG) == 0) {
return 0;
}
}
return -1; // timeout
}
Data Transfer
void cf_read_512(char* buf) {
int i;
cf_data_ready();
// Read 512 bytes - note byte order swapping
for (i = 0; i < 512; i += 2) {
buf[i+1] = cf_base[DATA_PORT];
buf[i] = cf_base[DATA_PORT];
}
}
void cf_write_512(char* buf) {
int i;
cf_data_ready();
// Write 512 bytes - note byte order swapping
for (i = 0; i < 512; i += 2) {
cf_base[DATA_PORT] = buf[i+1];
cf_base[DATA_PORT] = buf[i];
}
}
The protocol implements:
- 8-bit data transfers
- LBA addressing mode
- Simple command/status protocol
- 512-byte sector transfers
- Hardware handshaking via status register
- Error detection and timeout handling