re-implement AOD
This commit is contained in:
@@ -46,6 +46,7 @@ add_executable(BattMITM_2.0
|
||||
battery.c
|
||||
button.c
|
||||
defused/gui.c
|
||||
defused/aod.c
|
||||
)
|
||||
|
||||
pico_set_program_name(BattMITM_2.0 "BattMITM_2.0")
|
||||
|
||||
@@ -24,17 +24,27 @@
|
||||
#include "battery.h"
|
||||
#include "config.h"
|
||||
#include "smbus.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
bool battery_stat_need_cache_update = false;
|
||||
|
||||
spin_lock_t* battery_stat_cache_lock;
|
||||
battery_stat_t* battery_stat_cache;
|
||||
size_t battery_stat_cache_size;
|
||||
|
||||
|
||||
void battery_stat_lock() {
|
||||
spin_lock_unsafe_blocking(battery_stat_cache_lock);
|
||||
}
|
||||
|
||||
void battery_stat_unlock() {
|
||||
spin_unlock_unsafe(battery_stat_cache_lock);
|
||||
}
|
||||
|
||||
bool battery_stat_is_error(battery_stat_t* batt_stat) {
|
||||
return !batt_stat->result_valid;
|
||||
}
|
||||
@@ -60,6 +70,9 @@ battery_stat_t* battery_get_stat(uint8_t cmd) {
|
||||
|
||||
void battery_update_cache() {
|
||||
if (!battery_stat_need_cache_update) return;
|
||||
|
||||
battery_stat_lock();
|
||||
|
||||
battery_stat_need_cache_update = false;
|
||||
|
||||
i2c_dev_t* bms = get_bms_dev();
|
||||
@@ -97,6 +110,8 @@ void battery_update_cache() {
|
||||
|
||||
batt_stat->last_updated = time_us_64();
|
||||
}
|
||||
|
||||
battery_stat_unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -163,4 +178,6 @@ void init_battery() {
|
||||
for (int i = 0; i < battery_stat_cache_size; i++) {
|
||||
battery_stat_cache[i] = battery_stat_cache_init[i];
|
||||
}
|
||||
|
||||
battery_stat_cache_lock = spin_lock_instance(spin_lock_claim_unused(true));
|
||||
}
|
||||
|
||||
@@ -96,7 +96,13 @@ struct battery_stat {
|
||||
|
||||
typedef struct battery_stat battery_stat_t;
|
||||
|
||||
// IMPORTANT:
|
||||
// - never call anything here in an interrupt handler (it uses unsafe locks)
|
||||
// - if calling from core 1 acquire a lock
|
||||
// - make it quick, long locks will delay comms between the laptop and battery and could cause problems
|
||||
|
||||
void battery_stat_lock();
|
||||
void battery_stat_unlock();
|
||||
bool battery_stat_is_error(battery_stat_t* batt_stat);
|
||||
bool battery_stat_is_expired(battery_stat_t* batt_stat);
|
||||
battery_stat_t* battery_get_stat(uint8_t cmd);
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Benjamin Wiegand
|
||||
|
||||
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 "aod.h"
|
||||
#include "display.h"
|
||||
#include "battery.h"
|
||||
|
||||
// this mechanism will be replaced
|
||||
#define SCREEN_DIM_TIMEOUT 5000000
|
||||
|
||||
uint64_t aod_last_input = 0;
|
||||
|
||||
bool defused_aod_on_button_event(button_func_t function, button_event_t event) {
|
||||
aod_last_input = time_us_64();
|
||||
defused_update_display_now();
|
||||
return true;
|
||||
}
|
||||
|
||||
void defused_aod_on_nav_up() {}
|
||||
void defused_aod_on_nav_down() {}
|
||||
void defused_aod_on_pre_select() {}
|
||||
void defused_aod_on_cancel_select() {}
|
||||
void defused_aod_on_select() {}
|
||||
bool defused_aod_on_select_held() { return false; }
|
||||
|
||||
|
||||
void defused_aod_update_display() {
|
||||
|
||||
display_burn_update(false);
|
||||
|
||||
display_clear();
|
||||
|
||||
if (aod_last_input + SCREEN_DIM_TIMEOUT < time_us_64()) {
|
||||
display_set_contrast(0); // dimmest setting
|
||||
} else {
|
||||
display_set_contrast(255);
|
||||
}
|
||||
|
||||
|
||||
battery_stat_lock();
|
||||
battery_stat_t* stat;
|
||||
|
||||
display_set_text_position(0, 36);
|
||||
display_set_text_scale(2);
|
||||
|
||||
stat = battery_get_stat(BATT_CMD_RELATIVE_STATE_OF_CHARGE);
|
||||
if (battery_stat_is_expired(stat)) {
|
||||
display_set_text_color(COLOR_GRAY);
|
||||
display_print("...");
|
||||
} else if (battery_stat_is_error(stat)) {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_print("error");
|
||||
} else {
|
||||
display_set_text_color(COLOR_WHITE);
|
||||
display_printf("%d%%", *((uint16_t*) stat->cached_result));
|
||||
}
|
||||
|
||||
display_set_text_position(0, 45);
|
||||
display_set_text_scale(1);
|
||||
display_print("\n");
|
||||
|
||||
stat = battery_get_stat(BATT_CMD_VOLTAGE);
|
||||
if (battery_stat_is_expired(stat)) {
|
||||
display_set_text_color(COLOR_GRAY);
|
||||
display_print("...");
|
||||
} else if (battery_stat_is_error(stat)) {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_print("error");
|
||||
} else {
|
||||
display_set_text_color(COLOR_GREEN);
|
||||
display_printf("%.2f V", (*((uint16_t*) stat->cached_result)) / 1000.0);
|
||||
}
|
||||
|
||||
display_print(" ");
|
||||
|
||||
stat = battery_get_stat(BATT_CMD_CURRENT);
|
||||
if (battery_stat_is_expired(stat)) {
|
||||
display_set_text_color(COLOR_GRAY);
|
||||
display_print("...");
|
||||
} else if (battery_stat_is_error(stat)) {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_print("error");
|
||||
} else {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_printf("%.2f A", (*((int16_t*) stat->cached_result)) / 1000.0);
|
||||
}
|
||||
|
||||
battery_stat_unlock();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void defused_aod_init() {
|
||||
display_set_contrast(0);
|
||||
}
|
||||
|
||||
|
||||
menu_binding_t defused_aod_menu_binding = {
|
||||
display_update_interval: 1000000,
|
||||
burn_margin_x: 5,
|
||||
burn_margin_y: 20,
|
||||
|
||||
on_button_event: &defused_aod_on_button_event,
|
||||
|
||||
on_nav_up: &defused_aod_on_nav_up,
|
||||
on_nav_down: &defused_aod_on_nav_down,
|
||||
on_pre_select: &defused_aod_on_pre_select,
|
||||
on_cancel_select: &defused_aod_on_cancel_select,
|
||||
on_select: &defused_aod_on_select,
|
||||
on_select_held: &defused_aod_on_select_held,
|
||||
|
||||
update_display: &defused_aod_update_display,
|
||||
|
||||
init: &defused_aod_init
|
||||
};
|
||||
|
||||
menu_binding_t* bind_aod() {
|
||||
return &defused_aod_menu_binding;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Benjamin Wiegand
|
||||
|
||||
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 "defused/gui.h"
|
||||
|
||||
menu_binding_t* bind_aod();
|
||||
|
||||
+31
-6
@@ -24,10 +24,18 @@
|
||||
// the gui is codename "defused" because I think it's funny
|
||||
#include "defused/gui.h"
|
||||
#include "display.h"
|
||||
#include "aod.h"
|
||||
|
||||
struct repeating_timer display_update_timer;
|
||||
|
||||
menu_binding_t* defused_current_binding = NULL;
|
||||
|
||||
uint64_t defused_last_display_update = 0;
|
||||
bool defused_force_display_update = false;
|
||||
|
||||
void button_callback(button_func_t function, button_event_t event) {
|
||||
bool handled = defused_current_binding->on_button_event(function, event);
|
||||
if (handled) return;
|
||||
|
||||
switch (event) {
|
||||
case BUTTON_UP:
|
||||
case BUTTON_DOWN:
|
||||
@@ -37,12 +45,26 @@ void button_callback(button_func_t function, button_event_t event) {
|
||||
}
|
||||
}
|
||||
|
||||
bool display_update_handler(struct repeating_timer* t) {
|
||||
|
||||
void defused_update_display_now() {
|
||||
defused_force_display_update = true;
|
||||
}
|
||||
|
||||
void defused_set_display_update_interval(uint64_t interval) {
|
||||
add_repeating_timer_us(interval, display_update_handler, NULL, &display_update_timer);
|
||||
void defused_bind(menu_binding_t* binding) {
|
||||
defused_current_binding = binding;
|
||||
display_set_burn_limits(binding->burn_margin_x, binding->burn_margin_y);
|
||||
defused_current_binding->init();
|
||||
}
|
||||
|
||||
|
||||
void defused_loop() {
|
||||
if (defused_current_binding == NULL) return;
|
||||
uint64_t timestamp = time_us_64();
|
||||
|
||||
if (defused_force_display_update || defused_last_display_update + defused_current_binding->display_update_interval < timestamp) {
|
||||
defused_force_display_update = false;
|
||||
defused_current_binding->update_display();
|
||||
defused_last_display_update = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
void init_gui() {
|
||||
@@ -59,5 +81,8 @@ void init_gui() {
|
||||
sleep_ms(2000);
|
||||
|
||||
display_clear();
|
||||
|
||||
|
||||
defused_bind(bind_aod());
|
||||
|
||||
while (true) defused_loop();
|
||||
}
|
||||
|
||||
+11
-2
@@ -22,9 +22,12 @@
|
||||
IN THE SOFTWARE.
|
||||
*/
|
||||
// the gui is codename "defused" because I think it's funny
|
||||
#include "button.h"
|
||||
|
||||
#ifndef MENU_BINDING_DEF
|
||||
#define MENU_BINDING_DEF
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include <stdbool.h>
|
||||
#include "button.h"
|
||||
|
||||
struct menu_binding {
|
||||
uint64_t display_update_interval;
|
||||
@@ -50,4 +53,10 @@ struct menu_binding {
|
||||
|
||||
typedef struct menu_binding menu_binding_t;
|
||||
|
||||
#endif
|
||||
|
||||
void defused_update_display_now();
|
||||
|
||||
void defused_bind(menu_binding_t* binding);
|
||||
|
||||
void init_gui();
|
||||
|
||||
@@ -28,77 +28,6 @@
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/multicore.h"
|
||||
#include <stdio.h>
|
||||
/*
|
||||
bool do_update = false;
|
||||
|
||||
bool trigger_display_update(struct repeating_timer* t) {
|
||||
do_update = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void update_display() {
|
||||
display_burn_update(false);
|
||||
|
||||
display_clear();
|
||||
|
||||
display_set_contrast(0); // dimmest setting
|
||||
display_set_text_position(0, 14);
|
||||
display_set_text_scale(2);
|
||||
|
||||
battery_stat_t* stat;
|
||||
stat = battery_get_stat(BATT_CMD_RELATIVE_STATE_OF_CHARGE);
|
||||
if (battery_stat_is_expired(stat)) {
|
||||
display_set_text_color(COLOR_GRAY);
|
||||
display_print("loading...");
|
||||
} else if (battery_stat_is_error(stat)) {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_print("error");
|
||||
} else {
|
||||
display_set_text_color(COLOR_WHITE);
|
||||
display_printf("%d%%", *((uint16_t*) stat->cached_result));
|
||||
}
|
||||
|
||||
display_set_text_scale(1);
|
||||
display_print("\n");
|
||||
|
||||
stat = battery_get_stat(BATT_CMD_VOLTAGE);
|
||||
if (battery_stat_is_expired(stat)) {
|
||||
display_set_text_color(COLOR_GRAY);
|
||||
display_print("loading...");
|
||||
} else if (battery_stat_is_error(stat)) {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_print("error");
|
||||
} else {
|
||||
display_set_text_color(COLOR_GREEN);
|
||||
display_printf("%.2f V", (*((uint16_t*) stat->cached_result)) / 1000.0);
|
||||
}
|
||||
|
||||
display_print(" ");
|
||||
|
||||
stat = battery_get_stat(BATT_CMD_CURRENT);
|
||||
if (battery_stat_is_expired(stat)) {
|
||||
display_set_text_color(COLOR_GRAY);
|
||||
display_print("loading...");
|
||||
} else if (battery_stat_is_error(stat)) {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_print("error");
|
||||
} else {
|
||||
display_set_text_color(COLOR_RED);
|
||||
display_printf("%.2f A", (*((int16_t*) stat->cached_result)) / 1000.0);
|
||||
}
|
||||
|
||||
display_print("\n");
|
||||
|
||||
display_set_text_color(COLOR_GRAY);
|
||||
display_print(button_get_state(BUTTON_NAV_UP) == BUTTON_DOWN ? " D " : " U ");
|
||||
display_print(button_get_state(BUTTON_SELECT) == BUTTON_DOWN ? " D " : " U ");
|
||||
display_print(button_get_state(BUTTON_NAV_DOWN) == BUTTON_DOWN ? " D " : " U ");
|
||||
display_print("\n");
|
||||
|
||||
display_printf("%03d %03d %03d\n", button_down_ctrs[0], button_down_ctrs[1], button_down_ctrs[2]);
|
||||
display_printf("%03d %03d %03d\n", button_up_ctrs[0], button_up_ctrs[1], button_up_ctrs[2]);
|
||||
|
||||
} */
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
Reference in New Issue
Block a user