diff --git a/display.c b/display.c index 81f50f6..178f45a 100644 --- a/display.c +++ b/display.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "pinout.h" #include "display.h" @@ -25,11 +27,40 @@ void display_show(uint8_t dig0, uint8_t dig1) pin_up(PIN_DISP_STR); } -void display_show_number(uint8_t num) { - uint8_t tens = num/10; - uint8_t ones = num - tens*10; +void display_show_number(uint8_t num) +{ + uint8_t tens = num / 10; + uint8_t ones = num - tens * 10; uint8_t dig0 = tens ? disp_digits[tens] : 0; uint8_t dig1 = disp_digits[ones]; dig1 |= SEG_H; display_show(dig0, dig1); } + +// --- LED display brightness control --- + +/** + * PWM for LED display dimming + */ +void setup_pwm(void) +{ + OCR2B = disp_brightness = 0xFF; + TCCR2A |= _BV(WGM20) | _BV(WGM21) | _BV(COM2B1); + TIMSK2 |= _BV(TOIE2); // enable ISR + TCCR2B |= _BV(CS20); + + adc_start_conversion(LIGHT_ADC_CHANNEL); +} + +/** ISR that writes the PWM register - to avoid glitches */ +ISR(TIMER2_OVF_vect) +{ + // convert in background + if (adc_ready()) { + disp_brightness = 255 - adc_read_8bit(); // inverse + if (disp_brightness < 10) disp_brightness = 10; + adc_start_conversion(LIGHT_ADC_CHANNEL); + } + + OCR2B = disp_brightness; +} diff --git a/display.h b/display.h index 4f3b7cd..cb64c41 100644 --- a/display.h +++ b/display.h @@ -32,5 +32,6 @@ extern volatile uint8_t disp_brightness; // place to globally store display brig void display_show(uint8_t dig0, uint8_t dig1); void display_show_number(uint8_t num); +void setup_pwm(void); #endif //FIRMWARE_DISPLAY_H diff --git a/game.c b/game.c index 0991061..8050b8d 100644 --- a/game.c +++ b/game.c @@ -20,8 +20,8 @@ #define C_DARK rgb24(0,0,0) #define C_DIMWHITE rgb24(30,30,30) -#define C_OKGREEN rgb24(30,200,0) -#define C_CRIMSON rgb24(255,0,0) +#define C_OKGREEN rgb24(20,160,0) +#define C_CRIMSON rgb24(220,0,5) #define C_DIMRED rgb24(100,0,0) #define C_DIMGREEN rgb24(0,100,0) @@ -169,6 +169,7 @@ void suc_eff_callback(void *onOff) bool on = (bool) onOff; if (on) { + display_show_number(game_revealed_n-1); for (uint8_t i = 0; i < 4; i++) screen[i] = C_OKGREEN; schedule_task(suc_eff_callback, 0, SUC_EFF_TIME, false); } else { @@ -254,6 +255,8 @@ void prepare_sequence() repeat_count = 0; } +volatile uint16_t idle_cnt = 0; + /** Main function, called from MX-generated main.c */ void game_main(void) { @@ -262,16 +265,15 @@ void game_main(void) // we'll init the sequence when user first presses a button - the time is used as a seed enum GameState_enum last_state = STATE_NEW_GAME; - uint16_t cnt = 0; while (1) { if (GameState == last_state) { if (GameState == STATE_NEW_GAME) { - if (cnt == 20 && !holding_new_game_button) { + if (idle_cnt == 20 && !holding_new_game_button) { // clear after 2 secs display_show(SEG_G, SEG_G); } - if (cnt == 3000) { + if (idle_cnt == 3000) { // Shut down after 5 mins screen[0] = C_CRIMSON; screen[1] = C_CRIMSON; @@ -283,20 +285,20 @@ void game_main(void) while(1); // wait for shutdown } } else { - if (cnt > 120) {// 12 secs = stop game. + if (idle_cnt > 150) {// 15 secs = stop game. // reset state enter_state(STATE_NEW_GAME); show_screen(); display_show(SEG_G, SEG_G); - cnt = 0; + idle_cnt = 0; } } } else { last_state = GameState; - cnt = 0; + idle_cnt = 0; } - cnt++; + idle_cnt++; delay_ms(100); } } @@ -335,6 +337,9 @@ void game_button_handler(uint8_t button, bool press) } break; case STATE_USER_INPUT: + // Reset idle counter, so it doesn't cut off in the middle of input + idle_cnt = 0; + // user is entering a color memcpy(screen, dim, sizeof(screen)); @@ -351,7 +356,6 @@ void game_button_handler(uint8_t button, bool press) if (game_repeat_n == game_revealed_n) { // repeated all, good work! game_revealed_n++; - display_show_number(game_revealed_n-1); enter_state(STATE_SUCCESS_EFFECT); } } else { diff --git a/leds.c b/leds.c index fe69365..722456c 100644 --- a/leds.c +++ b/leds.c @@ -23,6 +23,7 @@ void leds_show(void) xrgb_t arr[4]; for (uint8_t i = 0; i < 4; i++) { float db = (float)disp_brightness / 255.0f; + if (db < 0.15) db = 0.15; arr[i].r = (uint8_t) ((float)rgb24_r(leds[i]) * db); arr[i].g = (uint8_t) ((float)rgb24_g(leds[i]) * db); arr[i].b = (uint8_t) ((float)rgb24_b(leds[i]) * db); diff --git a/main.c b/main.c index 87ecbb4..0d6c459 100644 --- a/main.c +++ b/main.c @@ -46,36 +46,6 @@ void setup_io(void) // PIN_LIGHT_SENSE is ADC exclusive, needs no config } -// --- LED display brightness control --- -// disp brightness defined in display.h -#define LIGHT_ADC_CHANNEL 6 - -/** - * PWM for LED display dimming - */ -void setup_pwm(void) -{ - OCR2B = disp_brightness = 0xFF; - TCCR2A |= _BV(WGM20) | _BV(WGM21) | _BV(COM2B1); - TIMSK2 |= _BV(TOIE2); // enable ISR - TCCR2B |= _BV(CS20); - - adc_start_conversion(LIGHT_ADC_CHANNEL); -} - -/** ISR that writes the PWM register - to avoid glitches */ -ISR(TIMER2_OVF_vect) -{ - // convert in background - if (adc_ready()) { - disp_brightness = 255 - adc_read_8bit(); // inverse - adc_start_conversion(LIGHT_ADC_CHANNEL); - } - - OCR2B = disp_brightness; -} - - // --- Debouncer slot allocation constants --- volatile bool booting = true; diff --git a/pinout.h b/pinout.h index 570b393..9c7bc6f 100644 --- a/pinout.h +++ b/pinout.h @@ -32,6 +32,6 @@ #define PIN_PWR_HOLD A5 // Hold the buck enabled. Set 0 for shutdown // Ambient light sensor (Vdd -> 10k -> * -> photo transistor -> GND) -#define PIN_LIGHT_SENSE A6 // ADC exclusive pin +#define LIGHT_ADC_CHANNEL 6 #endif //FIRMWARE_PINOUT_H