From c44dcf52b97087e1c612de2ebb9f0e648cf01ae5 Mon Sep 17 00:00:00 2001 From: daniel steuer Date: Sat, 15 Mar 2014 05:47:41 +0100 Subject: [PATCH] Simon the game --- Makefile | 6 +- rgbyteclock.c | 419 +++++++++++++++++++++++++++++++++++++++++++++----- util.c | 104 +++++++++++++ util.h | 22 +++ 4 files changed, 507 insertions(+), 44 deletions(-) create mode 100644 util.c create mode 100644 util.h diff --git a/Makefile b/Makefile index 2f914a0..236a6d4 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ PRG = rgbyteclock -OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o spi.o ringbuffer.o crc.o ledcontroller.o +OBJ = rgbyteclock.o timer.o lcd.o main.o rtc.o spi.o ringbuffer.o crc.o ledcontroller.o util.o MCU_TARGET = atmega164a OPTIMIZE = -Os @@ -25,8 +25,8 @@ $(PRG).elf: $(OBJ) @echo # dependency: -rgbyteclock.o: timer.o lcd.o rgbyteclock.h rtc.o spi.o ledcontroller.o -main.o: rgbyteclock.o lcd.o spi.o ledcontroller.o rtc.o timer.o +rgbyteclock.o: timer.o lcd.o rgbyteclock.h rtc.o spi.o ledcontroller.o util.o +main.o: rgbyteclock.o lcd.o spi.o ledcontroller.o rtc.o timer.o timer.o: timer.h lcd.o: lcd.h timer.o rtc.o: rtc.h diff --git a/rgbyteclock.c b/rgbyteclock.c index 960742c..610fdd6 100644 --- a/rgbyteclock.c +++ b/rgbyteclock.c @@ -1,4 +1,3 @@ - /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): @@ -13,53 +12,391 @@ #include "rgbyteclock.h" #include "timer.h" -#include "lcd.h" #include "ledcontroller.h" +#include "util.h" + +#define SEED_RNG 0 +#define INIT 1 +#define INTRO 2 +#define INTRODUCE_COLORS 3 +#define SHOW_SEQUENCE 4 +#define GET_USER_SEQUENCE 5 +#define USER_GUESS_OK 6 +#define USER_GUESS_NOK 7 +#define EXTEND_SEQUENCE 8 +#define WIN 9 + +int8_t show_intro( uint32_t now, uint32_t animation_start ); +int8_t show_introduce_colors( uint32_t now, uint32_t animation_start ); +void show_anim_wait_seed( uint32_t now, uint32_t animation_start ); +int8_t show_anim_ok( uint32_t now, uint32_t animation_start ); +int8_t show_anim_nok( uint32_t now, uint32_t animation_start ); +int8_t get_sequence( uint32_t now, uint32_t animation_start ); +int8_t show_anim_win( uint32_t now, uint32_t animation_start ); -void rgbyteclock(void) -{ +static uint8_t sequence[12]; +static uint8_t sequence_index; +static uint8_t input_sequence_index; +static uint8_t colorScheme[2]; - ledcontroller_turn_all_on(); +void rgbyteclock(void) { + uint32_t now, t1; + uint16_t r,g,b; // colors + int8_t end; + uint8_t button = BUTTON_NONE; - while (1) { - //PORTC ^= (1< 2000 || (get_button())) { + // hide sequence + for( int i=0; i<12; i++ ) { + get_color( &r, &g, &b, COLOR_BLACK ); + led_set( i, r, g, b); + } + + gameState = GET_USER_SEQUENCE; + t1 = now; + } + break; + + case GET_USER_SEQUENCE: + end = get_sequence( now, t1 ); + + if( end == 1 ) { + gameState = USER_GUESS_NOK; + t1 = now; + } + + if( end == 2 ) { + gameState = USER_GUESS_OK; + t1 = now; + } + break; + + case USER_GUESS_OK: + end = show_anim_ok( now, t1 ); + if( end ) { + gameState = EXTEND_SEQUENCE; + t1 = now; + } + break; + + case USER_GUESS_NOK: + end = show_anim_nok( now, t1 ); + if( end ) { + gameState = INIT; + t1 = now; + } + break; + + case EXTEND_SEQUENCE: + + if(sequence_index >= 12) { + gameState = WIN; + continue; + } + else { + gameState = SHOW_SEQUENCE; + } + + if( random()&1 ) { + sequence[sequence_index] = colorScheme[0]; + } + else { + sequence[sequence_index] = colorScheme[1]; + } + + sequence_index++; + break; + + case WIN: + end = show_anim_win( now, t1 ); + + if( end ) { + gameState = INIT; + t1 = now; + } + break; + } + + led_flush( ); + } +} + + + +int8_t get_sequence( uint32_t now, uint32_t animation_start ) { + uint16_t r,g,b; + uint8_t button; + uint8_t color; + uint8_t guessOK; + + button = get_button( ); + color = sequence[input_sequence_index]; + guessOK = 0; + + + if( button == BUTTON_RO ) { + if( color == colorScheme[0] ) { + guessOK = 1; + } + } + else if( button == BUTTON_LO ) { + if( color == colorScheme[1] ) { + guessOK = 1; + } + + } + else { + return 0; + } + + if( guessOK ) { + // draw what user entered until now + get_color( &r, &g, &b, color ); + led_set( input_sequence_index, r, g, b ); + + input_sequence_index++; + + if( input_sequence_index >= sequence_index) { + input_sequence_index = 0; + return 2; // entire sequence right + } + + return 0; // right but not finished + } + + return 1; // user guessed wrong +} + + + + +/* + ############## + # ANIMATIONS # + ############## +*/ + +int8_t show_introduce_colors( uint32_t now, uint32_t animation_start ) { + uint32_t t_diff = now - animation_start; + uint16_t r,g,b; + + // all ring LEDs off + for( int i=0; i<12; i++ ) { + led_set( i, 0,0,0 ); + } + + if( t_diff%100 < 50 ) { + // put gamecolors on the buttons + get_color( &r, &g, &b, colorScheme[0] ); + led_set( 12, r, g, b); // RO + get_color( &r, &g, &b, colorScheme[1] ); + led_set( 13, r, g, b); // LO + } + else { + for( int i=12; i<14; i++ ) { + get_color( &r, &g, &b, COLOR_BLACK ); + led_set( i, r,g,b ); + } + } + + if( t_diff > 1000 ) { + return 1; + } + return 0; +} + + + +void show_anim_wait_seed( uint32_t now, uint32_t animation_start ) { + uint32_t t_diff = (now - animation_start)%1000; + uint16_t w; + + if( t_diff < 500 ) { + // fade up + w = (MAX_BRIGHTNESS/500) * t_diff; + for( int i=0; i<12; i++ ) { + led_set( i, w, w, w); + } + } + else { + // fade down + w = MAX_BRIGHTNESS - (MAX_BRIGHTNESS/500) * (t_diff-500); + for( int i=0; i<12; i++ ) { + led_set( i, w, w, w); + } + } } + + + + +int8_t show_intro( uint32_t now, uint32_t animation_start ) { + // Animation: rotate a single LED once across the circle + uint32_t t_diff = now - animation_start; + uint16_t r,g,b; + uint8_t index; + + index = (t_diff%1200)/100; + if( !(t_diff % 100) ) { + // every 100ms + get_color( &r, &g, &b, (random()%6)+1 ); + led_set( index, r, g, b ); + } + + // next LED in line is dark to mark the update spot better + index++; + led_set( index%12, 0,0,0 ); + + if( now - animation_start > 2400 ) { + return 1; + } + return 0; +} + + + +int8_t show_anim_ok( uint32_t now, uint32_t animation_start ) { + uint32_t t_diff = now - animation_start; + uint16_t g; + + if( t_diff < 500 ) { + g = (MAX_BRIGHTNESS/500) * t_diff; + for( int i=0; i<12; i++ ) { + led_set( i, 0x00, g, 0x00); + } + } + else { + g = MAX_BRIGHTNESS - (MAX_BRIGHTNESS/500) * (t_diff-500); + for( int i=0; i<12; i++ ) { + led_set( i, 0x00, g, 0x00); + } + } + + if( t_diff > 1000 ) { + return 1; + } + return 0; +} + + + +int8_t show_anim_nok( uint32_t now, uint32_t animation_start ) { + uint32_t t_diff = now - animation_start; + uint16_t r,g,b; + + if( t_diff%100 < 50 ) { + for( int i=0; i<12; i++ ) { + get_color( &r, &g, &b, COLOR_RED ); + led_set( i, r,g,b ); + } + } + else { + for( int i=0; i<12; i++ ) { + get_color( &r, &g, &b, COLOR_BLACK ); + led_set( i, r,g,b ); + } + } + + if( t_diff > 1000 ) { + return 1; + } + return 0; +} + + + +int8_t show_anim_win( uint32_t now, uint32_t animation_start ) { + uint32_t t_diff = now - animation_start; + uint16_t b; + + if( t_diff < 1000 ) { + b = (MAX_BRIGHTNESS/1000) * t_diff; + for( int i=0; i<12; i++ ) { + led_set( i, 0x00, 0x00, b); + } + } + else { + b = MAX_BRIGHTNESS - (MAX_BRIGHTNESS/1000) * (t_diff-1000); + for( int i=0; i<12; i++ ) { + led_set( i, 0x00, 0x00, b); + } + + } + + if( t_diff > 2000 ) { + return 1; + } + return 0; +} diff --git a/util.c b/util.c new file mode 100644 index 0000000..f545550 --- /dev/null +++ b/util.c @@ -0,0 +1,104 @@ +#include +#include +#include "util.h" + + + +static volatile uint16_t s_lfsr=0xACE1u; + + + +void init_random( uint16_t lfsr ) { + s_lfsr = lfsr; +} + + + +uint16_t random( void ) { + uint8_t bit; + + bit = ((s_lfsr >> 0) ^ (s_lfsr >> 2) ^ (s_lfsr >> 3) ^ (s_lfsr >> 5) ) & 1; + s_lfsr = (s_lfsr >> 1) | (bit << 15); + return s_lfsr; +} + + + +void get_color( uint16_t *r, uint16_t *g, uint16_t *b, uint8_t colorIndex ) { + switch( colorIndex ) { + case COLOR_RED: + *r = MAX_BRIGHTNESS; + *g = 0x00; + *b = 0x00; + break; + + case COLOR_GREEN: + *r = 0x00; + *g = MAX_BRIGHTNESS; + *b = 0x00; + break; + + case COLOR_YELLOW: + *r = MAX_BRIGHTNESS; + *g = MAX_BRIGHTNESS; + *b = 0x00; + break; + + case COLOR_BLUE: + *r = 0x00; + *g = 0x00; + *b = MAX_BRIGHTNESS; + break; + + case COLOR_MAGENTA: + *r = MAX_BRIGHTNESS; + *g = 0x00; + *b = MAX_BRIGHTNESS; + break; + + case COLOR_CYAN: + *r = 0x00; + *g = MAX_BRIGHTNESS; + *b = MAX_BRIGHTNESS; + break; + + case COLOR_WHITE: + *r = MAX_BRIGHTNESS; + *g = MAX_BRIGHTNESS; + *b = MAX_BRIGHTNESS; + break; + + default: // black + *r = 0x00; + *g = 0x00; + *b = 0x00; + break; + } +} + + + +uint8_t get_button( void ) { + static uint8_t last_button = BUTTON_NONE; + uint8_t button = BUTTON_NONE; + + if( !(PIND&(1<