fix font; add separate counter for distance from power-on

This commit is contained in:
2026-09-13 22:47:07 +03:00
parent 2073575f54
commit 6586bcfa69
4 changed files with 93 additions and 30 deletions

93
main.c
View File

@@ -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