Fix screen stack popping and add a menu

This commit is contained in:
2019-06-26 09:07:34 -07:00
parent 5cfa22c650
commit e0b49ba109
9 changed files with 269 additions and 38 deletions

View File

@@ -206,7 +206,7 @@ void DisplayDriver::write_glyph_unaligned(uint32_t x_off, uint32_t y_off, const
byte_cols++;
}
for (size_t x = 0; x < g->cols; x++) {
for (size_t x = 0; x < g->cols && x < DISPLAY_WIDTH; x++) {
for (size_t y = 0; y < g->rows && y < DISPLAY_HEIGHT; y++) {
int byte_x = x / 8;
int byte_y = y;
@@ -268,7 +268,7 @@ void DisplayDriver::char_at(uint32_t *x_off, uint32_t y_off, char c, const struc
return;
}
if (*x_off + g->left + g->cols > DISPLAY_WIDTH) {
if (*x_off + g->left + g->cols >= DISPLAY_WIDTH) {
return;
}
@@ -301,15 +301,6 @@ void DisplayDriver::string_at(uint32_t *x_off, uint32_t y_off, const char *strin
}
}
// TODO: Implement this
// void DisplayDriver::rect_at(int x_off, int y_off,
// int width, int height,
// bool is_black,
// int line_width)
// {
// }
void DisplayDriver::refresh()
{
if (!m_is_dirty) {

View File

@@ -22,16 +22,13 @@
#include "DisplayTimeScreen.h"
#include "RtcDriver.h"
#include "SystemTime.h"
#include "SystemFonts.h"
#include "font-notomono-29.h"
#include "font-notomono-68.h"
using Common::ReturnCode;
using Common::Time;
using Common::Schedule::NextTime;
static const struct font &font = font_notomono_68;
DisplayTimeScreen::DisplayTimeScreen(BSP::DisplayDriver &driver,
ScreenManager &manager,
Screen &menu_screen)
@@ -52,12 +49,6 @@ static char get_char_for_digit(uint8_t bcd_digit)
ReturnCode DisplayTimeScreen::init()
{
SET_TO(GPIOA->MODER, GPIO_MODER_MODE0, 1u << GPIO_MODER_MODE1_Pos);
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1;
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD1;
GPIOA->PUPDR |= 2u << GPIO_PUPDR_PUPD1_Pos;
return ReturnCode::OK;
}
@@ -76,14 +67,12 @@ void DisplayTimeScreen::display_time()
{
Common::WallClockTime time;
BSP::RtcDriver::get_time(time);
// FIXME: Don't clear every redraw. Something is broken on screen
// switching. enable/disable not called?
m_driver.clear();
const struct font &font = large_font;
const uint32_t font_width = large_font_width;
const uint32_t y_space = (m_driver.get_height() - (2 * font.size)) / 3;
const uint32_t x_space = (m_driver.get_width() - (2 * font_width)) / 2;
uint32_t x = 0;
const uint32_t y_space = (m_driver.get_height() - (2 * font.size)) / 3;
const uint32_t x_space = (m_driver.get_width() - (2 * 54)) / 2;
if (m_last_time.get_hours_24() != time.get_hours_24()) {
x = x_space;

163
MenuScreen.h Normal file
View File

@@ -0,0 +1,163 @@
/*
* 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.
*/
#pragma once
#include "macros.h"
#include <initializer_list>
#include "SystemFonts.h"
#include "ScreenManager.h"
#include "Screen.h"
struct MenuScreenItem {
enum class Type{
NONE,
SCREEN,
BACK,
};
MenuScreenItem()
: m_text(nullptr)
, m_screen(nullptr)
, m_type(Type::NONE)
{}
MenuScreenItem(const char *item, Screen &m_screen)
: m_text(item)
, m_screen(&m_screen)
, m_type(Type::SCREEN)
{}
MenuScreenItem(const char *item)
: m_text(item)
, m_screen(nullptr)
, m_type(Type::BACK)
{}
const char *m_text;
Screen *m_screen;
Type m_type;
};
class MenuScreen : public Screen {
public:
static constexpr std::size_t MAX_ITEMS = 10;
MenuScreen(BSP::DisplayDriver &display,
ScreenManager &manager,
std::initializer_list<MenuScreenItem> items)
: m_driver(display)
, m_manager(manager)
, m_items()
, m_num_items{0}
, m_selected{0}
{
for (auto &item : items) {
m_items[m_num_items++] = item;
// Leave room for "back"
if (m_num_items == MAX_ITEMS - 1) {
break;
}
}
new (&m_items[m_num_items++]) MenuScreenItem("Back");
}
void render() {
const struct font &font = default_font;
// const uint32_t font_width = default_font_width;
m_driver.clear();
for (std::size_t i = 0; i < m_num_items; i++) {
uint32_t x = 0;
uint32_t y = 8 + (font.size + 8) * i;
const char *spacer = " ";
if (i == m_selected) {
spacer = ">";
}
m_driver.string_at(&x, y, spacer, &font);
m_driver.string_at(&x, y, m_items[i].m_text, &font);
}
m_driver.refresh();
}
Common::ReturnCode init() {
return Common::ReturnCode::OK;
}
Common::Schedule::NextTime execute() override {
return Common::Schedule::NextTime::never();
}
void enable() override {
m_selected = 0;
render();
}
void disable() override {
m_driver.clear();
}
void notify_up_button() override {
if (m_selected == 0) {
m_selected = m_num_items - 1;
} else {
m_selected--;
}
render();
}
void notify_middle_button() override {
MenuScreenItem &item = m_items[m_selected];
if (item.m_type == MenuScreenItem::Type::SCREEN) {
m_manager.push_screen(*item.m_screen);
} else if (item.m_type == MenuScreenItem::Type::BACK) {
m_manager.pop_screen();
}
}
void notify_down_button() override {
if (m_selected == m_num_items - 1) {
m_selected = 0;
} else {
m_selected++;
}
render();
}
private:
BSP::DisplayDriver &m_driver;
ScreenManager &m_manager;
MenuScreenItem m_items[MAX_ITEMS];
std::size_t m_num_items;
std::size_t m_selected;
};

View File

@@ -182,6 +182,8 @@ ReturnCode RtcDriver::set_time(const Common::WallClockTime &wall_time)
RTC->TR = time;
CLR(RTC->ISR, RTC_ISR_INIT);
while ((RTC->ISR & RTC_ISR_INITF)) {}
while (!(RTC->ISR & RTC_ISR_RSF)) {}
disable_rtc_write();

View File

@@ -22,16 +22,13 @@
#include "SetTimeScreen.h"
#include "SystemTime.h"
#include "SystemFonts.h"
#include "RtcDriver.h"
#include "font-notomono-29.h"
using Common::ReturnCode;
using Common::Time;
using Common::Schedule::NextTime;
static const font &font = font_notomono_29;
SetTimeScreen::SetTimeScreen(BSP::DisplayDriver &display,
ScreenManager &manager)
: m_display(display)
@@ -77,15 +74,20 @@ void SetTimeScreen::render_time()
{
uint32_t x = 0;
uint32_t y = 32;
const struct font &font = default_font;
display_number(&x, y,
m_time.get_hours_12_tens(), m_time.get_hours_12_ones(),
font);
m_display.string_at(&x, y, ":", &font);
display_number(&x, y,
m_time.get_minutes_tens(), m_time.get_minutes_ones(),
font);
m_display.string_at(&x, y, ":", &font);
display_number(&x, y,
m_time.get_seconds_tens(), m_time.get_seconds_ones(),
font);
@@ -103,15 +105,17 @@ void SetTimeScreen::draw_line(uint32_t x, uint32_t y, uint32_t width)
void SetTimeScreen::render_selection()
{
uint32_t font_width = default_font_width;
switch (m_state) {
case SetState::HOURS:
draw_line(0, 64, 24 * 2);
draw_line(0, 64, font_width * 2);
break;
case SetState::MINUTES:
draw_line(48, 64, 24 * 2);
draw_line(font_width * 2, 64, font_width * 2);
break;
case SetState::SECONDS:
draw_line(96, 64, 24 * 2);
draw_line(font_width * 4, 64, font_width * 2);
break;
case SetState::AM_PM:
break;
@@ -132,7 +136,6 @@ void SetTimeScreen::refresh()
void SetTimeScreen::enable()
{
BSP::RtcDriver::get_time(m_time);
m_state = SetState::HOURS;
m_is_acked = true;
@@ -189,7 +192,7 @@ void SetTimeScreen::notify_middle_button()
BSP::RtcDriver::set_time(m_time);
}
m_manager.pop_screen();
break;
return;
}
refresh();

View File

@@ -50,7 +50,7 @@ private:
void refresh();
void render_time();
void render_selection();
void display_number(uint32_t *x, uint32_t y, uint32_t tens, uint32_t ones, const font &f);
void display_number(uint32_t *x, uint32_t y, uint32_t tens, uint32_t ones, const struct font &f);
void draw_line(uint32_t x, uint32_t y, uint32_t width);
enum class SetState {
HOURS,

37
SystemFonts.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* 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.
*/
#pragma once
#include "fontem.h"
#include "font-robotoMono-24.h"
#include "font-robotoMono-68.h"
// All fonts are fixed-width, so we also defined the widths here. It
// lets us know the width without needing a specific glyph to look it
// up.
static const struct font &default_font = font_robotoMono_24;
static constexpr uint32_t default_font_width = 20;
static const struct font &large_font = font_robotoMono_68;
static constexpr uint32_t large_font_width = 54;

43
font-type.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* 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.
*/
#define ASCII_COUNT 128
struct glyph {
uint8_t width; // Width of bitmap in bits
uint8_t height; // Height of bitmap in bits
uint8_t left; // bitmap left offset
uint8_t top; // bitmap top offset
uint8_t *bitmap;
};
struct fixed_font {
const char *name;
uint32_t advance; // Width of a single (every) character in the font
uint32_t height; // Height of a single (every) character in the font
struct glyph *glyphs[ASCII_COUNT];
};

View File

@@ -28,6 +28,7 @@
#include "ScreenManager.h"
#include "DisplayTimeScreen.h"
#include "MenuScreen.h"
#include "SetTimeScreen.h"
#include "stm32l0xx.h"
@@ -44,7 +45,9 @@ static BSP::ButtonManager g_btn_manager(2, 1, 0, Time::millis(1));
static ScreenManager g_screen_manager(g_sched, g_display, g_btn_manager);
static SetTimeScreen g_set_time_screen(g_display, g_screen_manager);
static DisplayTimeScreen g_display_time_screen(g_display, g_screen_manager, g_set_time_screen);
static MenuScreen g_menu_screen(
g_display, g_screen_manager, std::initializer_list<MenuScreenItem>({MenuScreenItem("Time", g_set_time_screen)}));
static DisplayTimeScreen g_display_time_screen(g_display, g_screen_manager, g_menu_screen);
extern "C" void __cxa_pure_virtual() { while(1) {} }