#include #include #include #include static volatile uint8_t bits = 0; static volatile uint8_t value_in = 0x00; /* Data coming in from Game Boy */ static volatile uint8_t value_out = 0x00; /* Data going out from host */ uint16_t timer_counter_intervals[4] = { 1953, 977, 61, 31 }; /* * Internal clock source interrupt vector */ ISR(TIM0_COMPB_vect) { /* * Strobe the SCK pin */ PORTB |= (1 << PORTB1); PORTB &= ~(1 << PORTB1); value_in >>= 1; if (PORTB & (1 << PORTB2)) { value_in |= 0x80; } if (value_out & 0x80) { PORTB |= (1 << PORTB3); } else { PORTB &= ~(1 << PORTB3); } value_out <<= 1; if (--bits == 0) { putchar(value_in); value_out = getchar(); bits = 8; } } static void clock_internal_setup(tabby_clock_speed speed) { /* * Configure MISO as output */ DDB3 |= (1 << PORTB3); /* * Configure MOSI as input */ DDB2 &= ~(1 << PORTB2); /* * Configure SCK pin as output */ DDB1 |= (1 << PORTB1); /* * Enable timer interrupt vector */ TIMSK = (1 << TOIE1); /* * Reset timer counter to zero */ TCNT1 = 0; /* * Set timer interval */ OCR1A = timer_counter_intervals[speed]; /* * Set timer clock divider to 1/1 */ TCCR1B = (1 << CS10); } static void clock_external_setup() { /* * Disable internal timer interrupts */ TCCR1B = 0; OCR1A = 0; TIMSK = 0; } static void snooze() { set_sleep_mode(mode); sleep_enable(); sleep_mode(); sleep_disable(); } int main() { /* * By default, the Game Boy link port is configured to monitor for external * clock pulses, so we'll go ahead and do that in this case. */ clock_external_setup(); /* * We do actually want to globally enable interrupts here, so here's that * one assembly instruction to do so. */ sei(); while (1) { snooze(); } return 0; }