#include #include #include #include #include #include #include static tabby_printer_packet header = { .type = 0, .compression = 0, .size = 0 }; static tabby_printer_response response; static uint8_t body[TABBY_PRINTER_MAX_PACKET_SIZE]; static uint16_t sum = 0x0000; /* * So like, we're abusing pins here. So badly, it's beyond. So here's * what's going down: We want to retain the same physical I/O connections * between both the sending and receiving flavors of the whole Game Boy * Printer endeavor, and that mean/s that we must absolutely bit bang MOSI * and MISO opposite from their ordinary roles. The reason being: There is * no notion of MISO or MOSI from the Game Boy's (nor its peripherals') * point of view. The SI and SO pins over a link cable are crossed over, so * SI on one end always connects to SO on the other, and vice-versa. The SI * and SO pins do not switch roles based on role, unlike on AVR SPI * implementations. */ static void spi_init() { SC_OUTPUT(); SO_OUTPUT(); SI_INPUT(); SI_PULLUP(); SC_HIGH(); SO_LOW(); } static uint8_t spi_send_byte(uint8_t value) { uint8_t i, ret = 0; for (i=0; i<8; i++) { SC_LOW(); if (value & 0x80) { SO_HIGH(); } else { SO_LOW(); } _delay_us(SPI_PULSE_USEC); ret <<= 1; value <<= 1; if (SI_IS_HIGH()) { ret |= 1; } SC_HIGH(); _delay_us(SPI_PULSE_USEC); } return ret; } static void spi_send_packet() { int i; for (i=0; i> 8); response.device = spi_send_byte(0); response.status = spi_send_byte(0); } int main() { uint16_t i = 0, b = 0; uint8_t c; uart_init(); spi_init(); sei(); while (1) { uart_putchar('O', NULL); c = uart_getchar(NULL); if (c == 'K') { break; } } while (1) { c = uart_getchar(NULL); switch (i) { case 0: { if (c == TABBY_PRINTER_SYNC_1) { header.data[0] = c; i++; b = 0; } break; } case 1: { if (c == TABBY_PRINTER_SYNC_2) { header.data[1] = c; i++; } else { i = 0; } break; } case 2: { switch (c) { case TABBY_PRINTER_PACKET_INIT: case TABBY_PRINTER_PACKET_JOB: case TABBY_PRINTER_PACKET_DATA: case TABBY_PRINTER_PACKET_CANCEL: case TABBY_PRINTER_PACKET_INQUIRY: { header.type = c; i++; break; } default: { i = 0; break; } } break; } case 3: { header.compression = c; i++; break; } case 4: { header.size = c; i++; break; } case 5: { header.size |= c << 8; i++; break; } default: { if (b < header.size) { body[b++] = c; } else if (b == header.size) { sum = c; b++; } else if (b == header.size + 1) { sum |= c << 8; i = 0; b = 0; spi_send_packet(); uart_putchar(response.device, NULL); uart_putchar(response.status, NULL); } } } } return 0; }