#include <stdint.h>
#include <stdbool.h>
#define REG8(addr) *((volatile uint8_t *) addr)
#define REG16(addr) *((volatile uint16_t *) addr)
#define REG32(addr) *((volatile uint32_t *) addr)
#define JOY_DATA REG8(0x1F801040)
#define JOY_STAT REG16(0x1F801044)
#define JOY_MODE REG16(0x1F801048)
#define JOY_CTRL REG16(0x1F80104A)
#define JOY_BAUD REG16(0x1F80104E)
// Stores 0x2000 for second slot and 0x0000 for first slot
static uint16_t slotMask;
void card_delay(int time) {
// To be demangled
}
void card_init() {
JOY_CTRL = 0x0040; // Reset I/O unit
JOY_BAUD = 0x0043; // Clock speed: 505504.48KHz
JOY_MODE = 0x000D;
JOY_CTRL = slotMask | 0x0002;
card_delay(10);
JOY_CTRL = 0x0000;
card_delay(10000);
}
int card_transceive(uint8_t txData) {
JOY_DATA = txData; // Store output byte on TX buffer
JOY_CTRL = slotMask | 0x0003; // Begin transference
int retry = 100000;
while (JOY_STAT & 0x0002 == 0) { // Wait until a byte is received
if (retry-- == 0) { // If no data has been received when retry is zero, return -1
return -1;
}
}
JOY_CTRL = slotMask | 0x0002; // Clear RX mask
int rxData = JOY_DATA; // Read data
card_delay(5);
return rxData;
}
bool card_acknowledge() {
int retry = 100000;
while (JOY_STAT & 0x0080 != 0) { // Wait until /ACK goes low
if (retry-- == 0) { // If no acknowledgement has been issued when retry is zero, return false
return false;
}
}
JOY_CTRL |= 0x0010; // Clear ACK flag
return true;
}
bool card_check(bool secondSlot) {
if (secondSlot) {
slotMask = 0x2000;
} else {
slotMask = 0x0000;
}
card_init();
JOY_CTRL = slotMask | 0x0002;
card_delay(100);
card_transceive(0x21);
if (!card_acknowledge()) {
return false;
}
bool ok = card_transceive(0x53) & 0xF0 == 0;
JOY_CTRL = 0x0000;
card_init();
return ok;
}