fix font; add separate counter for distance from power-on
This commit is contained in:
@@ -326,9 +326,9 @@ const char GLYPH_CYRILLIC_SMALL_LETTER_CHE[] = {224, 224, 0, 0, 0, 0, 0, 0,
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_SHA[] = {224, 224, 0, 0, 0, 0, 0, 0, 224, 224, 0, 0, 0, 0, 0, 224,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 255,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_SHCHA[] = {224, 224, 0, 0, 0, 0, 0, 0, 224, 224, 0, 0, 0, 0, 0, 224,
|
||||
255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 255,
|
||||
7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 7};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_SHCHA[] = {
|
||||
224, 224, 0, 0, 0, 0, 0, 0, 224, 224, 0, 0, 0, 0, 0, 224, 224, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255,
|
||||
0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 6, 7, 7, 126, 126, 0};
|
||||
const char GLYPH_CYRILLIC_SMALL_LETTER_HARD_SIGN[] = {96, 96, 96, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 255, 255, 12, 12, 12, 12, 12, 12, 28, 24, 248, 240,
|
||||
0, 0, 0, 7, 7, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1};
|
||||
@@ -351,7 +351,7 @@ const char GLYPH_WIDTH[143] = {
|
||||
13, 9, 16, 17, 14, 13, 15, 12, 11, 13, 14, 2, 11, 14, 12, 16, 15, 16, 13, 16, 14, 12, 14, 14, 16, 17, 14, 14, 13,
|
||||
6, 11, 6, 13, 13, 5, 11, 12, 10, 12, 13, 8, 12, 11, 2, 4, 12, 4, 16, 11, 13, 12, 12, 8, 10, 8, 11, 12, 18,
|
||||
13, 12, 10, 7, 2, 7, 14, 12, 11, 18, 12, 17, 13, 15, 15, 14, 16, 14, 14, 17, 16, 12, 16, 16, 17, 16, 12, 13, 16,
|
||||
14, 13, 10, 9, 15, 13, 18, 11, 12, 12, 12, 14, 15, 11, 11, 10, 16, 12, 10, 16, 16, 15, 16, 10, 10, 16, 11};
|
||||
14, 13, 10, 9, 15, 13, 18, 11, 12, 12, 12, 14, 15, 11, 11, 10, 16, 12, 10, 16, 20, 15, 16, 10, 10, 16, 11};
|
||||
|
||||
const char *GLYPH_ADDR[143] = {
|
||||
GLYPH_EXCLAMATION_MARK,
|
||||
|
||||
@@ -111,8 +111,8 @@ void lcd_draw_vertical_xsmall_digit_segment(uint16_t x, uint16_t y, uint16_t col
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t DIGIT_MASKS[10] = {0b1110111, 0b0100100, 0b1011101, 0b1101101, 0b0101110,
|
||||
0b1101011, 0b1111011, 0b0100101, 0b1111111, 0b1101111};
|
||||
static const uint8_t DIGIT_MASKS[10] = {0b1110111, 0b0100100, 0b1011101, 0b1101101, 0b0101110,
|
||||
0b1101011, 0b1111011, 0b0100101, 0b1111111, 0b1101111};
|
||||
|
||||
void lcd_draw_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
||||
const uint16_t SEGMENT_OFFSETS[7][2] = {{9, 0}, {0, 9}, {49, 9}, {9, 49}, {0, 58}, {49, 58}, {9, 99}};
|
||||
@@ -199,7 +199,7 @@ void lcd_write_string(const char *string, uint16_t x, uint16_t y, uint16_t color
|
||||
st7789_write(glyphPixels, 24 * (glyphWidth + LETTER_SPACING) * sizeof(uint16_t));
|
||||
x += glyphWidth + LETTER_SPACING;
|
||||
} else {
|
||||
lcd_fill_rectangle(x, y, 12, 24, bgColor);
|
||||
_fill_rectangle(x, y, 12, 24, bgColor);
|
||||
x += 12;
|
||||
}
|
||||
}
|
||||
@@ -215,7 +215,7 @@ int lcd_string_width(const char *string) {
|
||||
} else {
|
||||
int glyphIndex = glyph_index_for_code_point(character);
|
||||
if (glyphIndex != -1) {
|
||||
width += GLYPH_WIDTH[glyphIndex] + 1;
|
||||
width += GLYPH_WIDTH[glyphIndex] + LETTER_SPACING;
|
||||
} else {
|
||||
width += 12;
|
||||
}
|
||||
|
||||
14
graphics.h
14
graphics.h
@@ -29,6 +29,14 @@ static inline void _draw_v_strip(uint16_t x, uint16_t y, uint16_t len, uint16_t
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _fill_rectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
|
||||
st7789_caset(x, x + w - 1);
|
||||
st7789_raset(y, y + h - 1);
|
||||
for (uint16_t i = 0; i < w * h; ++i) {
|
||||
st7789_put(color);
|
||||
}
|
||||
}
|
||||
|
||||
inline void lcd_set_pixel(uint16_t x, uint16_t y, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
@@ -39,11 +47,7 @@ inline void lcd_set_pixel(uint16_t x, uint16_t y, uint16_t color) {
|
||||
inline void lcd_fill_rectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
|
||||
x += LCD_OFFSET_X;
|
||||
y += LCD_OFFSET_Y;
|
||||
st7789_caset(x, x + w - 1);
|
||||
st7789_raset(y, y + h - 1);
|
||||
for (uint16_t i = 0; i < w * h; ++i) {
|
||||
st7789_put(color);
|
||||
}
|
||||
_fill_rectangle(x, y, w, h, color);
|
||||
}
|
||||
|
||||
void lcd_draw_horizontal_digit_segment(uint16_t x, uint16_t y, uint16_t color);
|
||||
|
||||
93
main.c
93
main.c
@@ -37,7 +37,8 @@ enum GUIScreen {
|
||||
|
||||
enum DisplayMode {
|
||||
DISPLAY_MODE_SPEED,
|
||||
DISPLAY_MODE_DISTANCE,
|
||||
DISPLAY_MODE_DISTANCE_FROM_POWER_ON,
|
||||
DISPLAY_MODE_TOTAL_DISTANCE,
|
||||
};
|
||||
|
||||
struct GUIState {
|
||||
@@ -51,6 +52,9 @@ struct GUIState {
|
||||
//...
|
||||
} settingsScreen;
|
||||
} screenState;
|
||||
uint8_t drawnTimeHours;
|
||||
uint8_t drawnTimeMinutes;
|
||||
uint16_t drawnTimeTextWidth;
|
||||
};
|
||||
|
||||
void on_gpio_interrupt(uint pin, uint32_t eventMask);
|
||||
@@ -112,7 +116,9 @@ uint16_t ticksPerWindow = 0;
|
||||
// critical_section_t intervalWheelTicksCritSec;
|
||||
repeating_timer_t speedMeasureTimer;
|
||||
|
||||
uint totalTicks = 0;
|
||||
// odometer counters
|
||||
uint totalWheelTicks = 0;
|
||||
uint wheelTicksFromPowerOn = 0;
|
||||
|
||||
DateTime currentDatetime;
|
||||
|
||||
@@ -289,7 +295,8 @@ int64_t hall_sensor_debounce_callback(alarm_id_t alarmId, void *userData) {
|
||||
absolute_time_t now = get_absolute_time();
|
||||
lastWheelTickTime = now;
|
||||
++intervalWheelTicks[currentInterval];
|
||||
++totalTicks;
|
||||
++totalWheelTicks;
|
||||
++wheelTicksFromPowerOn;
|
||||
|
||||
gpio_put(25, !gpio_get(25));
|
||||
hallSensorPrevState = hallSensorLastState;
|
||||
@@ -338,7 +345,9 @@ void on_button_short_press(uint button) {
|
||||
if (button == 3 && guiState.screen == MAIN_SCREEN) {
|
||||
uint oldDispMode = guiState.screenState.mainScreen.displayMode;
|
||||
if (oldDispMode == DISPLAY_MODE_SPEED)
|
||||
guiState.screenState.mainScreen.displayMode = DISPLAY_MODE_DISTANCE;
|
||||
guiState.screenState.mainScreen.displayMode = DISPLAY_MODE_DISTANCE_FROM_POWER_ON;
|
||||
else if (oldDispMode == DISPLAY_MODE_DISTANCE_FROM_POWER_ON)
|
||||
guiState.screenState.mainScreen.displayMode = DISPLAY_MODE_TOTAL_DISTANCE;
|
||||
else
|
||||
guiState.screenState.mainScreen.displayMode = DISPLAY_MODE_SPEED;
|
||||
guiState.screenState.mainScreen.displayModeChanged = true;
|
||||
@@ -457,10 +466,46 @@ void draw_short_term_distance(uint value) {
|
||||
#undef DIGITS_START_Y
|
||||
#undef DIGIT_WIDTH
|
||||
#undef DIGIT_SPACING
|
||||
#undef XSMALL_DIGITS_Y_OFFSET
|
||||
}
|
||||
|
||||
// long term distance is in "4.2" decimal fixed-point, in kilometers
|
||||
void draw_long_term_distance(uint value) {
|
||||
#define DIGITS_START_X 15
|
||||
#define DIGITS_START_Y 50
|
||||
#define XSMALL_DIGITS_Y_OFFSET 32
|
||||
#define XSMALL_DIGIT_WIDTH 30
|
||||
#define XSMALL_DIGIT_SPACING 4
|
||||
|
||||
if (value > 999999)
|
||||
value = 999999;
|
||||
|
||||
lcd_draw_small_digit(value / 100000, DIGITS_START_X, DIGITS_START_Y, 0xffff, 0x528a);
|
||||
lcd_draw_small_digit((value / 10000) % 10, DIGITS_START_X + SMALL_DIGIT_WIDTH + SMALL_DIGIT_SPACING, DIGITS_START_Y,
|
||||
0xffff, 0x528a);
|
||||
lcd_draw_small_digit((value / 1000) % 10, DIGITS_START_X + SMALL_DIGIT_WIDTH * 2 + SMALL_DIGIT_SPACING * 2,
|
||||
DIGITS_START_Y, 0xffff, 0x528a);
|
||||
lcd_draw_small_digit((value / 100) % 10, DIGITS_START_X + SMALL_DIGIT_WIDTH * 3 + SMALL_DIGIT_SPACING * 3,
|
||||
DIGITS_START_Y, 0xffff, 0x528a);
|
||||
lcd_draw_decimal_point(DIGITS_START_X + SMALL_DIGIT_WIDTH * 4 + SMALL_DIGIT_SPACING * 4 - 6, DIGITS_START_Y + 76,
|
||||
0xffff);
|
||||
lcd_draw_xsmall_digit((value / 10) % 10, DIGITS_START_X + SMALL_DIGIT_WIDTH * 4 + SMALL_DIGIT_SPACING * 4 + 10,
|
||||
DIGITS_START_Y + XSMALL_DIGITS_Y_OFFSET, 0xffff, 0x528a);
|
||||
lcd_draw_xsmall_digit(value % 10,
|
||||
DIGITS_START_X + SMALL_DIGIT_WIDTH * 4 + SMALL_DIGIT_SPACING * 4 + XSMALL_DIGIT_WIDTH +
|
||||
XSMALL_DIGIT_SPACING + 10,
|
||||
DIGITS_START_Y + XSMALL_DIGITS_Y_OFFSET, 0xffff, 0x528a);
|
||||
|
||||
#undef DIGITS_START_X
|
||||
#undef DIGITS_START_Y
|
||||
#undef XSMALL_DIGITS_Y_OFFSET
|
||||
#undef XSMALL_DIGIT_WIDTH
|
||||
#undef XSMALL_DIGIT_SPACING
|
||||
}
|
||||
|
||||
void update_lcd() {
|
||||
if (guiState.screen == MAIN_SCREEN) {
|
||||
bool forceRedrawClock = guiState.screenState.mainScreen.displayModeChanged;
|
||||
if (guiState.screenState.mainScreen.displayModeChanged) {
|
||||
// lcd_fill_rectangle(49, 27, 213, 113, 0x0000);
|
||||
st7789_fill(0x0000);
|
||||
@@ -470,29 +515,43 @@ void update_lcd() {
|
||||
if (guiState.screenState.mainScreen.displayMode == DISPLAY_MODE_SPEED) {
|
||||
uint convertedSpeed = ticksPerWindow * cmphPerTpw / 10000;
|
||||
draw_speed(convertedSpeed);
|
||||
lcd_write_string("Скорость", 20, 0, 0xffff, 0x0000);
|
||||
lcd_write_string("Скорость", 10, 0, 0xffff, 0x0000);
|
||||
lcd_write_string("км/ч", 241, 126, 0xffff, 0x0000);
|
||||
} else if (guiState.screenState.mainScreen.displayMode == DISPLAY_MODE_DISTANCE) {
|
||||
uint convertedDistance = totalTicks * cmPerTick / 100;
|
||||
} else if (guiState.screenState.mainScreen.displayMode == DISPLAY_MODE_DISTANCE_FROM_POWER_ON) {
|
||||
uint convertedDistance = wheelTicksFromPowerOn * cmPerTick / 100;
|
||||
draw_short_term_distance(convertedDistance);
|
||||
lcd_write_string("Расстояние", 20, 0, 0xffff, 0x0000);
|
||||
lcd_write_string("Текущий путь", 10, 0, 0xffff, 0x0000);
|
||||
lcd_write_string("км", 280, 37, 0xffff, 0x0000);
|
||||
} else if (guiState.screenState.mainScreen.displayMode == DISPLAY_MODE_TOTAL_DISTANCE) {
|
||||
uint convertedDistance = totalWheelTicks * cmPerTick / 1000;
|
||||
draw_long_term_distance(convertedDistance);
|
||||
lcd_write_string("Общий путь", 10, 0, 0xffff, 0x0000);
|
||||
lcd_write_string("км", 280, 37, 0xffff, 0x0000);
|
||||
}
|
||||
|
||||
char timeDisplay[6];
|
||||
memset(timeDisplay, ' ', sizeof(timeDisplay));
|
||||
timeDisplay[5] = 0;
|
||||
sprintf(timeDisplay, "%i:%02i", currentDatetime.hour, currentDatetime.minute);
|
||||
lcd_write_string(timeDisplay, 320 - 20 - lcd_string_width(timeDisplay), 0, 0xffff, 0x0000);
|
||||
lcd_fill_rectangle(320 - 160, 0, 140 - lcd_string_width(timeDisplay), 24, 0x0000);
|
||||
if (forceRedrawClock || guiState.drawnTimeHours != currentDatetime.hour ||
|
||||
guiState.drawnTimeMinutes != currentDatetime.minute) {
|
||||
lcd_fill_rectangle(305 - guiState.drawnTimeTextWidth, 0, guiState.drawnTimeTextWidth, 24, 0x0000);
|
||||
guiState.drawnTimeHours = currentDatetime.hour;
|
||||
guiState.drawnTimeMinutes = currentDatetime.minute;
|
||||
char timeDisplay[6];
|
||||
memset(timeDisplay, ' ', sizeof(timeDisplay));
|
||||
timeDisplay[5] = 0;
|
||||
sprintf(timeDisplay, "%i:%02i", currentDatetime.hour, currentDatetime.minute);
|
||||
lcd_write_string(timeDisplay, 305 - lcd_string_width(timeDisplay), 0, 0xffff, 0x0000);
|
||||
guiState.drawnTimeTextWidth = lcd_string_width(timeDisplay);
|
||||
}
|
||||
} else if (guiState.screen == SETTINGS_SCREEN) {
|
||||
}
|
||||
}
|
||||
|
||||
void gui_init(struct GUIState *state) {
|
||||
state->screen = 0;
|
||||
state->screenState.mainScreen.displayMode = DISPLAY_MODE_DISTANCE;
|
||||
state->screenState.mainScreen.displayMode = DISPLAY_MODE_DISTANCE_FROM_POWER_ON;
|
||||
state->screenState.mainScreen.displayModeChanged = true;
|
||||
state->drawnTimeTextWidth = 0;
|
||||
state->drawnTimeHours = 24;
|
||||
state->drawnTimeMinutes = 60;
|
||||
}
|
||||
|
||||
void init_button_states() {
|
||||
@@ -516,7 +575,7 @@ void save_to_rtc() {
|
||||
static uint savedDistance;
|
||||
uint8_t buffer[31];
|
||||
memset(buffer, 0, 31);
|
||||
uint newDistance = totalTicks * cmPerTick / 10;
|
||||
uint newDistance = totalWheelTicks * cmPerTick / 10;
|
||||
if (savedBefore && newDistance == savedDistance) {
|
||||
printf("skipped saving\n");
|
||||
return;
|
||||
@@ -588,7 +647,7 @@ bool load_from_rtc() {
|
||||
}
|
||||
|
||||
uint savedDistance = *(uint *)(buffer + 0);
|
||||
totalTicks = savedDistance * 10 / cmPerTick;
|
||||
totalWheelTicks = savedDistance * 10 / cmPerTick;
|
||||
#ifdef LOGGING
|
||||
printf("successfully loaded data from RTC memory\n");
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user