/** * Dispay */ #include "user_interface.h" #include "twi.h" #include "ssd1306.h" #include "sevenseg.h" #include "global_state.h" #include "radiation.h" static bool ended_loading = false; static struct SevenSeg sseg = { .x0 = 0, .y0 = 0, .charwidth = 17, .thick = 3, .spacing = 4, }; void clear_screen() { ssd1306_clearScreen(); } void init_user_interface() { TWI_Init(); ssd1306_128x32_i2c_init(); ssd1306_clearScreen(); } void turn_off_display() { ssd1306_displayOff(); } void show_current_radiation() { static struct rad_results last_results = {}; static struct rad_results results; static uint8_t pending_dark_frames = 0; static bool is_invert = false; static bool was_dark = false; // 12 step counter is better suited for display flashing effect static uint8_t tick_counter_12 = 0; tick_counter_12 += 1; if (tick_counter_12 == 12) { tick_counter_12 = 0; } // this is called from main, so we can sleep if (!ended_loading) { int progress = rad_get_progress(); if (progress == 100) { show_loading_screen(100, false); ended_loading = true; // so user sees it _delay_ms(250); clear_screen(); // start showing values } else { if (progress < 10) { progress = 10; } show_loading_screen(progress, false); return; } } if (pending_dark_frames > 0) { pending_dark_frames -= 1; return; } rad_get_reading(&results); // Severe inverts display to make it super obvious that shit's bad if (results.danger_level >= RAD_LEVEL_4_SEVERE) { if (!is_invert) { ssd1306_invertMode(); is_invert = true; } } else { if (is_invert) { is_invert = false; ssd1306_normalMode(); } } // blinking, higher radiation = faster if (results.danger_level == RAD_LEVEL_1_ELEVATED) { if (tick_counter_12 == 0) { pending_dark_frames = 1; } } if (results.danger_level == RAD_LEVEL_2_DANGER) { if (tick_counter_12 == 0 || tick_counter_12 == 6) { pending_dark_frames = 1; } } if (results.danger_level >= RAD_LEVEL_3_HIGH_DANGER) { if (tick_counter_12 == 0 || tick_counter_12 == 4 || tick_counter_12 == 8) { pending_dark_frames = 1; } } if (pending_dark_frames) { clear_screen(); was_dark = true; return; } if (was_dark || results.cpm_x10 != last_results.cpm_x10 || results.usvh_decimals != last_results.usvh_decimals || results.danger_level != last_results.danger_level) { was_dark = false; if (results.usvh_decimals != last_results.usvh_decimals || results.danger_level != last_results.danger_level) { clear_screen(); } memcpy(&last_results, &results, sizeof(struct rad_results)); // This is an optimized function that draws black as well as white lines as rectangles, // so we don't need to redraw the whole screen sseg_number(&sseg, results.usvh_num, 5, results.usvh_decimals); ssd1306_setColor(0xFFFF); for (uint8_t lv = 1; lv <= results.danger_level; lv++) { uint8_t xx = 129 - lv * 3; ssd1306_fillRect( xx, 20, xx, 30 ); } } }