/* * Copyright (C) 2019 Max Regan * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "Application/Screens/StopwatchScreen.h" #include "Application/SystemFonts.h" #include "Bsp/SystemTime.h" using BSP::ReturnCode; using BSP::Time; using BSP::Schedule::NextTime; StopwatchScreen::StopwatchScreen(BSP::DisplayDriver &display, ScreenManager &manager) : m_display(display) , m_manager(manager) , m_is_running(false) , m_accumulated_time() , m_last_time() , m_font(default_font) {} ReturnCode StopwatchScreen::init() { return ReturnCode::OK; } NextTime StopwatchScreen::execute() { refresh(); if (m_is_running) { add_time(); } return NextTime::asap(); } static char get_char_for_digit(uint8_t bcd_digit) { return (bcd_digit % 10) + '0'; } void StopwatchScreen::display_number(uint32_t *x, uint32_t y, uint32_t tens, uint32_t ones) { char time_str[3] = { 0 }; time_str[0] = get_char_for_digit(tens); time_str[1] = get_char_for_digit(ones); time_str[2] = '\0'; m_display.string_at(x, y, time_str, &m_font); } void StopwatchScreen::display_number(uint32_t *x, uint32_t y, uint32_t hundreds, uint32_t tens, uint32_t ones) { char time_str[4] = { 0 }; time_str[0] = get_char_for_digit(hundreds); time_str[1] = get_char_for_digit(tens); time_str[2] = get_char_for_digit(ones); time_str[3] = '\0'; m_display.string_at(x, y, time_str, &m_font); } void StopwatchScreen::refresh() { m_display.clear(); //uint32_t width = m_display.get_width(); uint32_t x = (m_display.get_width() - m_font.width * 7) / 2; uint32_t y = (m_display.get_height() - m_font.height * 2) / 2; uint64_t total_millis = BSP::Time::to_millis(m_accumulated_time); uint32_t millis = total_millis % 1000; uint64_t total_seconds = total_millis / 1000; uint32_t seconds = total_seconds % 60; uint64_t total_minutes = total_seconds / 60; uint32_t minutes = total_minutes % 60; uint64_t hours = total_minutes / 60; display_number(&x, y, hours / 100, hours / 10, hours); m_display.string_at(&x, y, ":", &m_font); display_number(&x, y, minutes / 10, minutes % 10); m_display.string_at(&x, y, ":", &m_font); y += m_font.height; x = (m_display.get_width() - 6 * m_font.width) / 2 ; display_number(&x, y, seconds / 10, seconds); m_display.string_at(&x, y, ".", &m_font); display_number(&x, y, millis / 100, millis / 10, millis); m_display.refresh(); } void StopwatchScreen::add_time() { BSP::time_t time; BSP::SystemTimer::get_time(time); m_accumulated_time += time - m_last_time; m_last_time = time; } void StopwatchScreen::notify_up_button() { m_manager.pop_screen(); return; } void StopwatchScreen::notify_middle_button() { BSP::SystemTimer::get_time(m_last_time); m_accumulated_time = 0; } void StopwatchScreen::notify_down_button() { if (!m_is_running) { // Start BSP::SystemTimer::get_time(m_last_time); } else { // Stop add_time(); } m_is_running = !m_is_running; return; } void StopwatchScreen::enable() { } void StopwatchScreen::disable() { }