Start hammering out the state machine somewhat
This commit is contained in:
		
							parent
							
								
									e4ab4045f6
								
							
						
					
					
						commit
						8d0dae5d69
					
				
					 3 changed files with 125 additions and 16 deletions
				
			
		
							
								
								
									
										131
									
								
								avr/main.c
									
										
									
									
									
								
							
							
						
						
									
										131
									
								
								avr/main.c
									
										
									
									
									
								
							|  | @ -4,26 +4,28 @@ | |||
| #include <avr/sleep.h> | ||||
| 
 | ||||
| #include <tabby/clock.h> | ||||
| #include <tabby/packet.h> | ||||
| 
 | ||||
| #include <tabby/avr/uart.h> | ||||
| #include <tabby/avr/buffer.h> | ||||
| 
 | ||||
| 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 */ | ||||
| static volatile uint8_t value_out = 0x00; /* Data going out to Game Boy */ | ||||
| 
 | ||||
| uint16_t timer_counter_intervals[4] = { | ||||
| static const uint16_t timer_counter_intervals[4] = { | ||||
|     1953, 977, 61, 31 | ||||
| }; | ||||
| 
 | ||||
| static volatile tabby_avr_buffer buffer = { | ||||
|     .len = 0, | ||||
|     .cur = 0 | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * 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)) { | ||||
|  | @ -41,13 +43,38 @@ ISR(TIM0_COMPB_vect) { | |||
|     if (--bits == 0) { | ||||
|         uart_putchar(value_in, NULL); | ||||
| 
 | ||||
|         value_out = uart_getchar(NULL); | ||||
|         if (buffer.cur < buffer.len) { | ||||
|             value_out = buffer.data[++buffer.cur]; | ||||
|         } else { | ||||
|             buffer.len = 0; | ||||
|             buffer.cur = 0; | ||||
|         } | ||||
| 
 | ||||
|         bits = 8; | ||||
|     } | ||||
| 
 | ||||
|     /*
 | ||||
|      * Strobe the SCK pin | ||||
|      */ | ||||
|     PORTB |=  (1 << PORTB1); | ||||
|     PORTB &= ~(1 << PORTB1); | ||||
| } | ||||
| 
 | ||||
| static void clock_internal_setup(tabby_clock_speed speed) { | ||||
| /*
 | ||||
|  * SPI byte receipt interrupt vector | ||||
|  */ | ||||
| ISR(SPI_STC_vect) { | ||||
|     uart_putchar(SPDR); | ||||
| 
 | ||||
|     if (buffer.cur < buffer.len) { | ||||
|         SPDR = buffer.data[++buffer.cur]; | ||||
|     } else { | ||||
|         buffer.len = 0; | ||||
|         buffer.cur = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void setup_clock_internal(tabby_clock_speed speed) { | ||||
|     /*
 | ||||
|      * Configure MISO as output | ||||
|      */ | ||||
|  | @ -84,13 +111,41 @@ static void clock_internal_setup(tabby_clock_speed speed) { | |||
|     TCCR1B = (1 << CS10); | ||||
| } | ||||
| 
 | ||||
| static void clock_external_setup() { | ||||
| static void setup_clock_external() { | ||||
|     /*
 | ||||
|      * Disable internal timer interrupts | ||||
|      */ | ||||
|     TCCR1B = 0; | ||||
|     OCR1A  = 0; | ||||
|     TIMSK  = 0; | ||||
| 
 | ||||
|     /*
 | ||||
|      * Configure MISO as output | ||||
|      */ | ||||
|     DDB3 |= (1 << PORTB3); | ||||
| 
 | ||||
|     /*
 | ||||
|      * Configure MOSI as input | ||||
|      */ | ||||
|     DDB2 &= ~(1 << PORTB2); | ||||
| 
 | ||||
|     /*
 | ||||
|      * Set SPI slave mode, and shift in/out most significant bit first | ||||
|      */ | ||||
|     SPCR &= ~((1 << MSTR) | (1 << DORD)); | ||||
| 
 | ||||
|     /*
 | ||||
|      * Enable SPI in Mode 3 with interrupts | ||||
|      */ | ||||
|     SPCR |= (1 << CPOL) | (1 << CPHA) | (1 << SPIE) | (1 << SPE); | ||||
| 
 | ||||
|     /*
 | ||||
|      * Initialize the SPI Data Register and serial buffer | ||||
|      */ | ||||
|     SPDR = 0; | ||||
| 
 | ||||
|     buf.len = 0; | ||||
|     buf.cur = 0; | ||||
| } | ||||
| 
 | ||||
| static void snooze() { | ||||
|  | @ -101,6 +156,12 @@ static void snooze() { | |||
| } | ||||
| 
 | ||||
| int main() { | ||||
|     tabby_command state = TABBY_COMMAND_NONE; | ||||
| 
 | ||||
|     uint8_t last = 0x00; | ||||
| 
 | ||||
|     int received = 0; | ||||
| 
 | ||||
|     /*
 | ||||
|      * Best turn on the serial UART! | ||||
|      */ | ||||
|  | @ -110,7 +171,7 @@ 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(); | ||||
|     setup_clock_external(); | ||||
| 
 | ||||
|     /*
 | ||||
|      * We do actually want to globally enable interrupts here, so here's that | ||||
|  | @ -119,7 +180,51 @@ int main() { | |||
|     sei(); | ||||
| 
 | ||||
|     while (1) { | ||||
|         snooze(); | ||||
|         uint8_t c = uart_getchar(NULL); | ||||
| 
 | ||||
|         received++; | ||||
| 
 | ||||
|         switch (state) { | ||||
|             case TABBY_COMMAND_NONE: { | ||||
|                 if (last == 0 && c == TABBY_PACKET_START) { | ||||
|                     continue; | ||||
|                 } else if (last == TABBY_PACKET_START) { | ||||
|                     state = c; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             case TABBY_COMMAND_SEND: { | ||||
|                 if (received == 3 || received == 4) { | ||||
|                     buffer.len = (buffer.len >> 8) | (c << 8); | ||||
|                 } else { | ||||
|                     buffer.data[buffer.cur++] = c; | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             case TABBY_COMMAND_CLOCK_SOURCE: | ||||
|             case TABBY_COMMAND_CLOCK_SPEED: | ||||
| 
 | ||||
|             default: | ||||
|                 goto error_invalid_packet; | ||||
|         } | ||||
| 
 | ||||
|         last = c; | ||||
| 
 | ||||
|         received++; | ||||
| 
 | ||||
|         continue; | ||||
| 
 | ||||
| error_invalid_packet: | ||||
|         state    = TABBY_COMMAND_NONE; | ||||
|         last     = 0; | ||||
|         received = 0; | ||||
| 
 | ||||
|         buffer.cur = 0; | ||||
|         buffer.len = 0; | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| #define _TABBY_COMMAND_H | ||||
| 
 | ||||
| typedef enum { | ||||
|     TABBY_COMMAND_NONE         = 0x00, | ||||
|     TABBY_COMMAND_SEND         = 0x01, | ||||
|     TABBY_COMMAND_CLOCK_SOURCE = 0x02, | ||||
|     TABBY_COMMAND_CLOCK_SPEED  = 0x03 | ||||
|  |  | |||
|  | @ -1,13 +1,16 @@ | |||
| #ifndef _TABBY_PACKET_H | ||||
| #define _TABBY_PACKET_H | ||||
| 
 | ||||
| #define TABBY_PACKET_MAX_LEN 65535 | ||||
| #define TABBY_PACKET_START   0xff | ||||
| #define TABBY_PACKET_MAX_LEN 1024 | ||||
| 
 | ||||
| #include <tabby/command.h> | ||||
| 
 | ||||
| typedef struct _tabby_packet { | ||||
|     uint16_t type, | ||||
|     uint8_t start, | ||||
|             command; | ||||
| 
 | ||||
|     uint16_t len; | ||||
| } tabby_packet; | ||||
| 
 | ||||
| #endif /* _TABBY_PACKET_H */ | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue