#[derive(PartialEq, Copy, Clone)] enum PomState { STOPPED, RUNNING, PAUSED } const POM_DURATION : u16 = 1500; const POM_CURRENT_INDEX : u32 = 68; const POM_LIGHT_COUNT : u32 = 9; const POM_COMPLETE_INDEX : u32 = POM_CURRENT_INDEX + POM_LIGHT_COUNT + 1; static mut current_pom_state : PomState = PomState::STOPPED; static mut pom_visible : bool = false; static mut poms_completed : u32 = 0; static mut pom_current_secs : u16 = 0; static mut pom_second_start : u32 = 0; static mut blink_on : bool = false; static mut last_pos : u32 = 0; extern "C" { pub static complete_hsv : [u32; 3usize]; pub static current_hsv : [u32; 3usize]; pub static hidden_hsv : [u32; 3usize]; pub static blank_hsv : [u32; 3usize]; fn timer_read32() -> u32; fn timer_elapsed32(prev : u32) -> u32; fn hsv_matrix_set_color(i : u32, color : *const [u32; 3usize]); } #[no_mangle] pub unsafe extern "C" fn new_pom() { let previous_pom_state = current_pom_state; match previous_pom_state { PomState::RUNNING => { current_pom_state = PomState::PAUSED; }, PomState::PAUSED => { current_pom_state = PomState::RUNNING; }, PomState::STOPPED => { current_pom_state = PomState::RUNNING; pom_current_secs = 0; pom_second_start = 0; } } } #[no_mangle] pub unsafe extern "C" fn cancel_pom() { current_pom_state = PomState::STOPPED; pom_current_secs = 0; pom_second_start = 0; } #[no_mangle] pub unsafe extern "C" fn delete_pom() { cancel_pom(); poms_completed = 0; } #[no_mangle] pub unsafe extern "C" fn show_pom() { pom_visible = !pom_visible; } #[no_mangle] pub unsafe extern "C" fn tick_pom() { if current_pom_state == PomState::RUNNING { count_pom(); } if current_pom_state != PomState::STOPPED || poms_completed > 0 { draw_pom(); } } unsafe fn count_pom() { if pom_second_start == 0 { pom_second_start = timer_read32(); } if timer_elapsed32(pom_second_start) > 1000 { pom_second_start = 0; pom_current_secs += 1; } if pom_current_secs >= POM_DURATION { poms_completed += 1; current_pom_state = PomState::STOPPED; pom_current_secs = 0; pom_second_start = 0; } } unsafe fn draw_pom() { let current_pos = POM_CURRENT_INDEX + ((pom_current_secs as f32 / POM_DURATION as f32) * POM_LIGHT_COUNT as f32) as u32; let completed_pos = POM_COMPLETE_INDEX + poms_completed - 1; // Clear row if pom_visible { if current_pom_state != PomState::STOPPED { let mut i = POM_CURRENT_INDEX; while i < POM_CURRENT_INDEX + POM_LIGHT_COUNT { hsv_matrix_set_color(i, &blank_hsv); i += 1; } } let mut i = POM_COMPLETE_INDEX; while i < POM_COMPLETE_INDEX + 3 { hsv_matrix_set_color(i, &blank_hsv); i += 1; } } // Draw completed if pom_visible { let mut i = POM_COMPLETE_INDEX; while i < POM_COMPLETE_INDEX + poms_completed { hsv_matrix_set_color(i, &complete_hsv); i += 1; } } else if poms_completed > 0 && poms_completed <= 3 { hsv_matrix_set_color(completed_pos, &hidden_hsv); } if current_pom_state == PomState::STOPPED { return; } if last_pos != current_pos { last_pos = current_pos; blink_on = true; } else if pom_second_start == 0 { blink_on = !blink_on; } // Current solid if pom_visible { let mut i = POM_CURRENT_INDEX; while i < current_pos { hsv_matrix_set_color(i, ¤t_hsv); i += 1; } } // Current blinking if blink_on { if pom_visible { hsv_matrix_set_color(current_pos, ¤t_hsv); } else { hsv_matrix_set_color(current_pos, &hidden_hsv); } } }