#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. */ static void spi_init() { /* * Set SC to output */ DDRB |= (1 << DDB5); /* * Configure SO as output */ DDRB |= (1 << DDB4); /* * Configure SI as input with pullup */ DDRB &= ~(1 << DDB3); PORTB |= (1 << DDB3); /* * Set SO clear */ PORTB &= ~(1 << PORTB4); /* * Set SC high */ PORTB |= (1 << PORTB5); } static uint8_t spi_send_byte(uint8_t value) { uint8_t i, ret = 0; for (i=0; i<8; i++) { PORTB &= ~(1 << PORTB5); if (value & 0x80) { PORTB |= (1 << PORTB4); } else { PORTB &= ~(1 << PORTB4); } _delay_us(61); ret <<= 1; value <<= 1; if (PINB & (1 << PINB3)) { ret |= 1; } PORTB |= (1 << PORTB5); _delay_us(61); } 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); _delay_us(244); } int main() { uint16_t i = 0, b = 0, 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 == 0x88) { header.data[0] = c; i++; b = 0; } break; } case 1: { if (c == 0x33) { header.data[1] = c; i++; } else { i = 0; } break; } case 2: { switch (c) { case 0x01: case 0x02: case 0x04: case 0x08: case 0x0f: { 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; }