/* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. * (c) 2014 Stefan Rupp * ---------------------------------------------------------------------------- */ #include "rgbyteclock.h" #include "timer.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 ); static uint8_t sequence[12]; static uint8_t sequence_index; static uint8_t input_sequence_index; static uint8_t colorScheme[2]; void rgbyteclock(void) { uint32_t now, t1; uint16_t r,g,b; // colors int8_t end; uint8_t button = BUTTON_NONE; uint8_t gameState = SEED_RNG; ledcontroller_turn_all_on(); DDRC &= ~(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 ) { for( int i=0; i<12; i++ ) { led_set( i, 0x00, 0x00, 0x00); } 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 ) { for( int i=0; i<12; i++ ) { led_set( i, 0x00, 0x00, 0x00); } 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 ) { for( int i=0; i<12; i++ ) { led_set( i, 0x00, 0x00, 0x00); } return 1; } return 0; }