time setting
This commit is contained in:
@@ -24,6 +24,7 @@ add_executable(zavlaha
|
||||
src/screens/screen_home.c
|
||||
src/screens/screen_settings.c
|
||||
src/screens/screen_cyklus.c
|
||||
src/screens/screen_set_time.c
|
||||
src/app_io.c
|
||||
src/app_config.c)
|
||||
|
||||
|
||||
@@ -49,6 +49,16 @@ void LcdBuffer_IO_WriteCGRAM(uint8_t position, const uint8_t* data)
|
||||
lcd_glyph(position, data);
|
||||
}
|
||||
|
||||
void LcdBuffer_IO_SetCursorPos(lcdbuf_pos_t cursor_row, lcdbuf_pos_t cursor_col)
|
||||
{
|
||||
lcd_xy(cursor_col, cursor_row);
|
||||
}
|
||||
|
||||
void LcdBuffer_IO_SetCursorStyle(uint8_t cursor_style)
|
||||
{
|
||||
lcd_set_cursor(cursor_style & 0b11);
|
||||
}
|
||||
|
||||
// Internal prototypes
|
||||
void _lcd_mode_r();
|
||||
|
||||
@@ -128,18 +138,20 @@ void lcd_command(uint8_t bb);
|
||||
|
||||
|
||||
// 0 W, 1 R
|
||||
bool _lcd_mode;
|
||||
static bool lcd_mode;
|
||||
|
||||
struct {
|
||||
static struct {
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
} _pos;
|
||||
} lcd_pos;
|
||||
|
||||
enum {
|
||||
static enum {
|
||||
TEXT = 0,
|
||||
CG = 1
|
||||
} _addrtype;
|
||||
} lcd_addrtype;
|
||||
|
||||
static uint8_t lcd_old_cursor = CURSOR_NONE;
|
||||
static bool lcd_enabled = false;
|
||||
|
||||
/** Initialize the display */
|
||||
void lcd_init()
|
||||
@@ -148,7 +160,7 @@ void lcd_init()
|
||||
as_output(LCD_E);
|
||||
as_output(LCD_RW);
|
||||
as_output(LCD_RS);
|
||||
_lcd_mode = 1; // force data pins to output
|
||||
lcd_mode = 1; // force data pins to output
|
||||
_lcd_mode_w();
|
||||
|
||||
// Magic sequence to invoke Cthulhu (or enter 4-bit mode)
|
||||
@@ -173,9 +185,9 @@ void lcd_init()
|
||||
// mark as enabled
|
||||
lcd_enable();
|
||||
|
||||
_pos.x = 0;
|
||||
_pos.y = 0;
|
||||
_addrtype = TEXT;
|
||||
lcd_pos.x = 0;
|
||||
lcd_pos.y = 0;
|
||||
lcd_addrtype = TEXT;
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +204,7 @@ void _lcd_clk()
|
||||
/** Enter READ mode */
|
||||
void _lcd_mode_r()
|
||||
{
|
||||
if (_lcd_mode == 1) { return; } // already in R mode
|
||||
if (lcd_mode == 1) { return; } // already in R mode
|
||||
|
||||
pin_high(LCD_RW);
|
||||
|
||||
@@ -201,14 +213,14 @@ void _lcd_mode_r()
|
||||
as_input_pu(LCD_D5);
|
||||
as_input_pu(LCD_D4);
|
||||
|
||||
_lcd_mode = 1;
|
||||
lcd_mode = 1;
|
||||
}
|
||||
|
||||
|
||||
/** Enter WRITE mode */
|
||||
void _lcd_mode_w()
|
||||
{
|
||||
if (_lcd_mode == 0) { return; } // already in W mode
|
||||
if (lcd_mode == 0) { return; } // already in W mode
|
||||
|
||||
pin_low(LCD_RW);
|
||||
|
||||
@@ -217,7 +229,7 @@ void _lcd_mode_w()
|
||||
as_output(LCD_D5);
|
||||
as_output(LCD_D4);
|
||||
|
||||
_lcd_mode = 0;
|
||||
lcd_mode = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -250,22 +262,22 @@ void lcd_command(uint8_t bb)
|
||||
/** Write a data byte */
|
||||
void lcd_write(uint8_t bb)
|
||||
{
|
||||
if (_addrtype == TEXT) {
|
||||
if (lcd_addrtype == TEXT) {
|
||||
if (bb == '\r') {
|
||||
// CR
|
||||
_pos.x = 0;
|
||||
lcd_xy(_pos.x, _pos.y);
|
||||
lcd_pos.x = 0;
|
||||
lcd_xy(lcd_pos.x, lcd_pos.y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bb == '\n') {
|
||||
// LF
|
||||
_pos.y++;
|
||||
lcd_xy(_pos.x, _pos.y);
|
||||
lcd_pos.y++;
|
||||
lcd_xy(lcd_pos.x, lcd_pos.y);
|
||||
return;
|
||||
}
|
||||
|
||||
_pos.x++;
|
||||
lcd_pos.x++;
|
||||
}
|
||||
|
||||
_lcd_wait_bf();
|
||||
@@ -285,7 +297,7 @@ uint8_t lcd_read_bf_addr()
|
||||
/** Read CGRAM or DDRAM */
|
||||
uint8_t lcd_read()
|
||||
{
|
||||
if (_addrtype == TEXT) { _pos.x++; }
|
||||
if (lcd_addrtype == TEXT) { lcd_pos.x++; }
|
||||
|
||||
pin_high(LCD_RS);
|
||||
return _lcd_read_byte();
|
||||
@@ -341,21 +353,17 @@ void lcd_putc(const char c)
|
||||
/** Set cursor position */
|
||||
void lcd_xy(const uint8_t x, const uint8_t y)
|
||||
{
|
||||
_pos.x = x;
|
||||
_pos.y = y;
|
||||
lcd_pos.x = x;
|
||||
lcd_pos.y = y;
|
||||
lcd_addr(LCD_ROW_ADDR[y] + (x));
|
||||
}
|
||||
|
||||
|
||||
uint8_t _lcd_old_cursor = CURSOR_NONE;
|
||||
bool _lcd_enabled = false;
|
||||
|
||||
/** Set LCD cursor. If not enabled, only remember it. */
|
||||
void lcd_cursor(uint8_t type)
|
||||
void lcd_set_cursor(uint8_t type)
|
||||
{
|
||||
_lcd_old_cursor = (type & CURSOR_BOTH);
|
||||
lcd_old_cursor = (type & CURSOR_BOTH);
|
||||
|
||||
if (_lcd_enabled) { lcd_command(LCD_CURSOR_NONE | _lcd_old_cursor); }
|
||||
if (lcd_enabled) { lcd_command(LCD_CURSOR_NONE | lcd_old_cursor); }
|
||||
}
|
||||
|
||||
|
||||
@@ -363,15 +371,15 @@ void lcd_cursor(uint8_t type)
|
||||
void lcd_disable()
|
||||
{
|
||||
lcd_command(LCD_DISABLE);
|
||||
_lcd_enabled = false;
|
||||
lcd_enabled = false;
|
||||
}
|
||||
|
||||
|
||||
/** Enable display (restoring cursor) */
|
||||
void lcd_enable()
|
||||
{
|
||||
_lcd_enabled = true;
|
||||
lcd_cursor(_lcd_old_cursor);
|
||||
lcd_enabled = true;
|
||||
lcd_set_cursor(lcd_old_cursor);
|
||||
}
|
||||
|
||||
|
||||
@@ -379,9 +387,9 @@ void lcd_enable()
|
||||
void lcd_home()
|
||||
{
|
||||
lcd_command(LCD_HOME);
|
||||
_pos.x = 0;
|
||||
_pos.y = 0;
|
||||
_addrtype = TEXT;
|
||||
lcd_pos.x = 0;
|
||||
lcd_pos.y = 0;
|
||||
lcd_addrtype = TEXT;
|
||||
}
|
||||
|
||||
|
||||
@@ -389,9 +397,9 @@ void lcd_home()
|
||||
void lcd_clear()
|
||||
{
|
||||
lcd_command(LCD_CLEAR);
|
||||
_pos.x = 0;
|
||||
_pos.y = 0;
|
||||
_addrtype = TEXT;
|
||||
lcd_pos.x = 0;
|
||||
lcd_pos.y = 0;
|
||||
lcd_addrtype = TEXT;
|
||||
_delay_ms(1); // it tends to lose the first character otherwise!
|
||||
}
|
||||
|
||||
@@ -405,15 +413,15 @@ void lcd_glyph(const uint8_t index, const uint8_t *array)
|
||||
}
|
||||
|
||||
// restore previous position
|
||||
lcd_xy(_pos.x, _pos.y);
|
||||
_addrtype = TEXT;
|
||||
lcd_xy(lcd_pos.x, lcd_pos.y);
|
||||
lcd_addrtype = TEXT;
|
||||
}
|
||||
|
||||
|
||||
/** Set address in CGRAM */
|
||||
void lcd_addr_cg(const uint8_t acg)
|
||||
{
|
||||
_addrtype = CG;
|
||||
lcd_addrtype = CG;
|
||||
lcd_command(0b01000000 | ((acg) & 0b00111111));
|
||||
}
|
||||
|
||||
@@ -421,6 +429,6 @@ void lcd_addr_cg(const uint8_t acg)
|
||||
/** Set address in DDRAM */
|
||||
void lcd_addr(const uint8_t add)
|
||||
{
|
||||
_addrtype = TEXT;
|
||||
lcd_addrtype = TEXT;
|
||||
lcd_command(0b10000000 | ((add) & 0b01111111));
|
||||
}
|
||||
|
||||
+59
-1
@@ -36,8 +36,37 @@ void LcdBuffer_Clear(struct LcdBuffer *self)
|
||||
/** Write what needs to be written to the HW, clear all dirty marks */
|
||||
void LcdBuffer_Flush(struct LcdBuffer *self)
|
||||
{
|
||||
bool any_flush = self->full_repaint_required || self->cursor_dirty;
|
||||
uint8_t flush_cgram_mask = 0;
|
||||
|
||||
// Check if any flushing is required
|
||||
for (int i = 0; i < LCDBUF_CGRAM_CAPACITY; i++) {
|
||||
if (self->cgram[i].refcount > 0 && self->cgram[i].dirty) {
|
||||
any_flush = true;
|
||||
flush_cgram_mask |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_flush) {
|
||||
// check if we have dirty areas
|
||||
for (int e = 0; e < LCDBUF_DIRTY_LIST_LEN; e++) {
|
||||
struct LcdBuf_DirtyExtent *ext = &self->dirty_extents[e];
|
||||
if (ext->count) {
|
||||
any_flush = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_flush) {
|
||||
// really nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
LcdBuffer_IO_SetCursorStyle(0); // hide cursor for the time of this function
|
||||
|
||||
for (int i = 0; i < LCDBUF_CGRAM_CAPACITY; i++) {
|
||||
if (flush_cgram_mask & (1 << i)) {
|
||||
LcdBuffer_IO_WriteCGRAM(i, self->custom_symbols[self->cgram[i].symbol_index].data);
|
||||
self->cgram[i].dirty = false;
|
||||
}
|
||||
@@ -57,7 +86,7 @@ void LcdBuffer_Flush(struct LcdBuffer *self)
|
||||
|
||||
if (!any_nonspace) {
|
||||
LcdBuffer_IO_Clear();
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (int r = 0; r < LINE_NUM; r++) {
|
||||
@@ -74,11 +103,21 @@ void LcdBuffer_Flush(struct LcdBuffer *self)
|
||||
ext->count = 0; // mark the slot as free
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
// Restore the visible cursor
|
||||
if (self->cursor_style != 0) {
|
||||
LcdBuffer_IO_SetCursorPos(self->cursor_row, self->cursor_col);
|
||||
LcdBuffer_IO_SetCursorStyle(self->cursor_style); // hide cursor for the time of this function
|
||||
}
|
||||
self->cursor_dirty = false;
|
||||
}
|
||||
|
||||
/** Fully write everything to the display */
|
||||
void LcdBuffer_FlushAll(struct LcdBuffer *self)
|
||||
{
|
||||
LcdBuffer_IO_SetCursorStyle(0); // hide cursor for the time of this function
|
||||
|
||||
for (int i = 0; i < LCDBUF_CGRAM_CAPACITY; i++) {
|
||||
if (self->cgram[i].refcount > 0) {
|
||||
LcdBuffer_IO_WriteCGRAM(i, self->custom_symbols[self->cgram[i].symbol_index].data);
|
||||
@@ -92,6 +131,14 @@ void LcdBuffer_FlushAll(struct LcdBuffer *self)
|
||||
|
||||
memset(self->dirty_extents, 0, sizeof(self->dirty_extents));
|
||||
self->full_repaint_required = false;
|
||||
|
||||
// Restore the visible cursor
|
||||
if (self->cursor_style != 0) {
|
||||
LcdBuffer_IO_SetCursorPos(self->cursor_row, self->cursor_col);
|
||||
LcdBuffer_IO_SetCursorStyle(self->cursor_style); // hide cursor for the time of this function
|
||||
}
|
||||
|
||||
self->cursor_dirty = false;
|
||||
}
|
||||
|
||||
//static void show_dirty_slots(const struct LcdBuffer *self) {
|
||||
@@ -289,3 +336,14 @@ void LcdBuffer_Write(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col,
|
||||
col++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LcdBuffer_SetCursor(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, uint8_t cursor_style)
|
||||
{
|
||||
if ((self->cursor_style != cursor_style) || (self->cursor_row != row) || (self->cursor_col != col)) {
|
||||
self->cursor_style = cursor_style;
|
||||
self->cursor_row = row;
|
||||
self->cursor_col = col;
|
||||
self->cursor_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-1
@@ -71,6 +71,12 @@ struct LcdBuffer {
|
||||
/** If the dirty extents array was not sufficient to hold all changes, this flag is set,
|
||||
* indicating the dirty_extents array should be disregarded. */
|
||||
bool full_repaint_required;
|
||||
|
||||
/* Visible cursor - is restored after flushing */
|
||||
uint8_t cursor_style; // two bits - blink 0b01, bar 0b10
|
||||
lcdbuf_pos_t cursor_row;
|
||||
lcdbuf_pos_t cursor_col;
|
||||
bool cursor_dirty;
|
||||
};
|
||||
|
||||
/** Initialize the struct */
|
||||
@@ -91,6 +97,9 @@ void LcdBuffer_Set(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, s
|
||||
/** Write a UTF8 string at a position */
|
||||
void LcdBuffer_Write(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, char *utf_string);
|
||||
|
||||
/** Set visible cursor position and style. style is 2 bits: blink 0b01, bar 0b10 */
|
||||
void LcdBuffer_SetCursor(struct LcdBuffer *self, lcdbuf_pos_t row, lcdbuf_pos_t col, uint8_t cursor_style);
|
||||
|
||||
/* Callbacks - need to be implemented by the application! */
|
||||
|
||||
/** Clear the entire screen (CGRAM can be left unchanged, but they will be written anew if needed) */
|
||||
@@ -100,6 +109,10 @@ extern void LcdBuffer_IO_Clear();
|
||||
extern void LcdBuffer_IO_WriteAt(lcdbuf_pos_t row, lcdbuf_pos_t col, const uint8_t *buf, lcdbuf_count_t len);
|
||||
|
||||
/** Write CGRAM data. Data is always 8 bytes long. */
|
||||
extern void LcdBuffer_IO_WriteCGRAM(uint8_t position, const uint8_t* data);
|
||||
extern void LcdBuffer_IO_WriteCGRAM(uint8_t position, const uint8_t *data);
|
||||
|
||||
/** Set cursor pos & style */
|
||||
extern void LcdBuffer_IO_SetCursorPos(lcdbuf_pos_t cursor_row, lcdbuf_pos_t cursor_col);
|
||||
extern void LcdBuffer_IO_SetCursorStyle(uint8_t cursor_style);
|
||||
|
||||
#endif //HD44780UTF_LCDBUF_H
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string.h>
|
||||
#include "app_gui.h"
|
||||
#include "../lcd/lcdbuf.h"
|
||||
#include "lcd.h"
|
||||
|
||||
struct State s_app = {};
|
||||
|
||||
@@ -70,6 +71,7 @@ void switch_screen(screen_t pScreen, bool init) {
|
||||
s_app.screen = pScreen;
|
||||
|
||||
LcdBuffer_Clear(&lcd);
|
||||
LcdBuffer_SetCursor(&lcd, 0, 0, CURSOR_NONE); // always start with a hidden cursor. If the page wants a visible cursor, it should do that in PAINT
|
||||
request_paint();
|
||||
|
||||
if (init) {
|
||||
|
||||
@@ -50,6 +50,7 @@ void request_paint();
|
||||
void screen_home(GuiEvent event);
|
||||
void screen_cyklus(GuiEvent event);
|
||||
void screen_settings(GuiEvent event);
|
||||
void screen_set_time(GuiEvent event);
|
||||
// XXX other prototypes
|
||||
|
||||
struct State {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <stdio.h>
|
||||
#include "app_gui.h"
|
||||
#include "gui_event.h"
|
||||
#include "ds_rtc.h"
|
||||
#include "app_io.h"
|
||||
#include "lcd.h"
|
||||
|
||||
static struct rtc_time time;
|
||||
static int cursor;
|
||||
|
||||
void screen_set_time(GuiEvent event)
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
switch (event) {
|
||||
case GUI_EVENT_SCREEN_INIT:
|
||||
time.hour = 0;
|
||||
time.minute = 0;
|
||||
time.second = 0;
|
||||
cursor = 0;
|
||||
break;
|
||||
|
||||
case GUI_EVENT_PAINT:
|
||||
LcdBuffer_Write(&lcd, 0, 0, "Zadejte přesný čas");
|
||||
|
||||
LcdBuffer_SetCursor(&lcd, 1, cursor + (cursor >= 2), (cursor < 4) ? CURSOR_BOTH : CURSOR_NONE);
|
||||
|
||||
snprintf(buf, 100, "%02d:%02d", time.hour, time.minute);
|
||||
LcdBuffer_Write(&lcd, 1, 0, buf);
|
||||
|
||||
LcdBuffer_Write(&lcd, 3, 0, "🅰Uložit 🅳Zrušit");
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KEY_A: // Confirm
|
||||
rtc_set_time(&time);
|
||||
switch_screen(screen_settings, false);
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KEY_D: // CANCEL
|
||||
switch_screen(screen_settings, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (event >= '0' && event <= '9') {
|
||||
int digit = event - '0';
|
||||
if (cursor == 0) {
|
||||
if (digit <= 2) {
|
||||
time.hour += digit * 10;
|
||||
cursor++;
|
||||
request_paint();
|
||||
}
|
||||
} else if (cursor == 1) {
|
||||
if (time.hour < 20 || digit <= 3) {
|
||||
time.hour += digit;
|
||||
cursor++;
|
||||
request_paint();
|
||||
}
|
||||
} else if (cursor == 2) {
|
||||
if (digit <= 5) {
|
||||
time.minute += digit * 10;
|
||||
cursor++;
|
||||
request_paint();
|
||||
}
|
||||
} else if (cursor == 3) {
|
||||
time.minute += digit;
|
||||
cursor++; // cursor disappears
|
||||
request_paint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ void screen_settings(GuiEvent event)
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KEY_3: // Nastavit cas
|
||||
// TODO
|
||||
switch_screen(screen_set_time, true);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user