adding save and battery voltage reading
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
idf_component_register(SRCS "bt_app.c" "system.c" "bubble.c" "keypad.c" "main.c"
|
idf_component_register(SRCS "battery.c" "bt_app.c" "system.c" "bubble.c" "keypad.c" "main.c"
|
||||||
"gui.c"
|
"gui.c"
|
||||||
"lsm6dsv.c"
|
"lsm6dsv.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
|
|||||||
204
main/battery.c
Normal file
204
main/battery.c
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
#include "battery.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_adc/adc_oneshot.h"
|
||||||
|
#include "esp_adc/adc_cali.h"
|
||||||
|
#include "esp_adc/adc_cali_scheme.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
static const char *TAG = "battery";
|
||||||
|
|
||||||
|
static adc_oneshot_unit_handle_t adc1_handle = NULL;
|
||||||
|
static adc_cali_handle_t adc1_cali_handle = NULL;
|
||||||
|
static bool adc_calibration_enabled = false;
|
||||||
|
|
||||||
|
// ADC Calibration initialization
|
||||||
|
static bool adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle)
|
||||||
|
{
|
||||||
|
adc_cali_handle_t handle = NULL;
|
||||||
|
esp_err_t ret = ESP_FAIL;
|
||||||
|
bool calibrated = false;
|
||||||
|
|
||||||
|
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
|
||||||
|
if (!calibrated) {
|
||||||
|
ESP_LOGI(TAG, "Calibration scheme: Curve Fitting");
|
||||||
|
adc_cali_curve_fitting_config_t cali_config = {
|
||||||
|
.unit_id = unit,
|
||||||
|
.chan = channel,
|
||||||
|
.atten = atten,
|
||||||
|
.bitwidth = BATTERY_ADC_WIDTH,
|
||||||
|
};
|
||||||
|
ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
calibrated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
|
||||||
|
if (!calibrated) {
|
||||||
|
ESP_LOGI(TAG, "Calibration scheme: Line Fitting");
|
||||||
|
adc_cali_line_fitting_config_t cali_config = {
|
||||||
|
.unit_id = unit,
|
||||||
|
.atten = atten,
|
||||||
|
.bitwidth = BATTERY_ADC_WIDTH,
|
||||||
|
};
|
||||||
|
ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
calibrated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*out_handle = handle;
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "ADC calibration successful");
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "ADC calibration failed: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
return calibrated;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t battery_init(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
|
||||||
|
// Configure ADC1 oneshot mode
|
||||||
|
adc_oneshot_unit_init_cfg_t init_config = {
|
||||||
|
.unit_id = ADC_UNIT_1,
|
||||||
|
};
|
||||||
|
ret = adc_oneshot_new_unit(&init_config, &adc1_handle);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize ADC unit: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure ADC channel
|
||||||
|
adc_oneshot_chan_cfg_t config = {
|
||||||
|
.bitwidth = BATTERY_ADC_WIDTH,
|
||||||
|
.atten = BATTERY_ADC_ATTEN,
|
||||||
|
};
|
||||||
|
ret = adc_oneshot_config_channel(adc1_handle, BATTERY_ADC_CHANNEL, &config);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to configure ADC channel: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize calibration
|
||||||
|
adc_calibration_enabled = adc_calibration_init(ADC_UNIT_1, BATTERY_ADC_CHANNEL,
|
||||||
|
BATTERY_ADC_ATTEN, &adc1_cali_handle);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Battery monitoring initialized on GPIO34 (ADC1_CH6)");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int battery_read_raw(void)
|
||||||
|
{
|
||||||
|
int adc_raw = 0;
|
||||||
|
esp_err_t ret = adc_oneshot_read(adc1_handle, BATTERY_ADC_CHANNEL, &adc_raw);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to read ADC: %s", esp_err_to_name(ret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return adc_raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
int battery_read_voltage_mv(void)
|
||||||
|
{
|
||||||
|
int voltage_mv = 0;
|
||||||
|
int adc_sum = 0;
|
||||||
|
int valid_samples = 0;
|
||||||
|
|
||||||
|
// Take multiple samples and average
|
||||||
|
for (int i = 0; i < BATTERY_SAMPLES; i++) {
|
||||||
|
int adc_raw = battery_read_raw();
|
||||||
|
if (adc_raw >= 0) {
|
||||||
|
adc_sum += adc_raw;
|
||||||
|
valid_samples++;
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1)); // Small delay between samples
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid_samples == 0) {
|
||||||
|
ESP_LOGE(TAG, "No valid ADC samples");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adc_avg = adc_sum / valid_samples;
|
||||||
|
|
||||||
|
// Convert to voltage using calibration if available
|
||||||
|
if (adc_calibration_enabled) {
|
||||||
|
esp_err_t ret = adc_cali_raw_to_voltage(adc1_cali_handle, adc_avg, &voltage_mv);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "Calibration conversion failed, using raw calculation");
|
||||||
|
adc_calibration_enabled = false; // Disable for future reads
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to manual calculation if calibration not available
|
||||||
|
if (!adc_calibration_enabled) {
|
||||||
|
// Simple linear conversion for 12-bit ADC with 12dB attenuation
|
||||||
|
// Approximate range: 0-3300mV for 0-4095 raw values
|
||||||
|
voltage_mv = (adc_avg * 3300) / 4095;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply voltage divider ratio to get actual battery voltage
|
||||||
|
voltage_mv = (int)(voltage_mv * BATTERY_VOLTAGE_DIVIDER_RATIO);
|
||||||
|
|
||||||
|
return voltage_mv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int battery_get_percentage(void)
|
||||||
|
{
|
||||||
|
int voltage_mv = battery_read_voltage_mv();
|
||||||
|
|
||||||
|
if (voltage_mv < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp to min/max range
|
||||||
|
if (voltage_mv >= BATTERY_VOLTAGE_MAX) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
if (voltage_mv <= BATTERY_VOLTAGE_MIN) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Linear interpolation between min and max
|
||||||
|
int percentage = ((voltage_mv - BATTERY_VOLTAGE_MIN) * 100) /
|
||||||
|
(BATTERY_VOLTAGE_MAX - BATTERY_VOLTAGE_MIN);
|
||||||
|
|
||||||
|
return percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Battery monitoring task
|
||||||
|
static void battery_monitoring_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Battery monitoring task started");
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int voltage_mv = battery_read_voltage_mv();
|
||||||
|
int percentage = battery_get_percentage();
|
||||||
|
|
||||||
|
if (voltage_mv >= 0 && percentage >= 0) {
|
||||||
|
// Update system state with battery info
|
||||||
|
system_setBatteryVoltage(voltage_mv);
|
||||||
|
system_setBatteryPercentage(percentage);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Battery: %d mV (%d%%)", voltage_mv, percentage);
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "Failed to read battery voltage");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read battery every 30 seconds
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(30000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void battery_start_monitoring_task(void)
|
||||||
|
{
|
||||||
|
xTaskCreate(battery_monitoring_task, "battery_task", 3072, NULL, 5, NULL);
|
||||||
|
ESP_LOGI(TAG, "Battery monitoring task created");
|
||||||
|
}
|
||||||
56
main/battery.h
Normal file
56
main/battery.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef BATTERY_H
|
||||||
|
#define BATTERY_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
// Battery monitoring configuration
|
||||||
|
#define BATTERY_ADC_CHANNEL ADC_CHANNEL_6 // GPIO34 (ADC1_CH6)
|
||||||
|
#define BATTERY_ADC_ATTEN ADC_ATTEN_DB_12 // Full range ~3.9V (0-3300mV with attenuation)
|
||||||
|
#define BATTERY_ADC_WIDTH ADC_WIDTH_BIT_12 // 12-bit resolution (0-4095)
|
||||||
|
|
||||||
|
// Battery voltage calculation constants
|
||||||
|
// Adjust these based on your voltage divider circuit
|
||||||
|
#define BATTERY_VOLTAGE_DIVIDER_RATIO 2.0f // Example: R1=R2, adjust for your circuit
|
||||||
|
#define BATTERY_SAMPLES 16 // Number of samples to average
|
||||||
|
|
||||||
|
// Battery percentage thresholds (in millivolts at battery)
|
||||||
|
#define BATTERY_VOLTAGE_MAX 4200 // Fully charged Li-Ion
|
||||||
|
#define BATTERY_VOLTAGE_MIN 3000 // Empty Li-Ion (cutoff)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize battery monitoring ADC
|
||||||
|
*
|
||||||
|
* @return esp_err_t ESP_OK on success
|
||||||
|
*/
|
||||||
|
esp_err_t battery_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read raw ADC value from battery pin
|
||||||
|
*
|
||||||
|
* @return int Raw ADC value (0-4095)
|
||||||
|
*/
|
||||||
|
int battery_read_raw(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read battery voltage in millivolts (averaged)
|
||||||
|
*
|
||||||
|
* @return int Battery voltage in mV
|
||||||
|
*/
|
||||||
|
int battery_read_voltage_mv(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get battery percentage (0-100)
|
||||||
|
*
|
||||||
|
* @return int Battery percentage
|
||||||
|
*/
|
||||||
|
int battery_get_percentage(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start battery monitoring task
|
||||||
|
*
|
||||||
|
* This task periodically reads battery voltage and updates system state
|
||||||
|
*/
|
||||||
|
void battery_start_monitoring_task(void);
|
||||||
|
|
||||||
|
#endif // BATTERY_H
|
||||||
26
main/gui.c
26
main/gui.c
@@ -1395,28 +1395,32 @@ static lv_obj_t* create_volume_page(void) {
|
|||||||
|
|
||||||
static void show_volume_control(void) {
|
static void show_volume_control(void) {
|
||||||
ESP_LOGI(TAG, "Showing volume control");
|
ESP_LOGI(TAG, "Showing volume control");
|
||||||
|
|
||||||
|
// Load saved volume from system
|
||||||
|
_current_volume = system_getVolume();
|
||||||
|
ESP_LOGI(TAG, "Loaded volume from system: %d", _current_volume);
|
||||||
|
|
||||||
lv_obj_t* menu = create_menu_container();
|
lv_obj_t* menu = create_menu_container();
|
||||||
if (!menu) {
|
if (!menu) {
|
||||||
ESP_LOGE(TAG, "Failed to create menu container for volume control");
|
ESP_LOGE(TAG, "Failed to create menu container for volume control");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_obj_t* volume_page = create_volume_page();
|
lv_obj_t* volume_page = create_volume_page();
|
||||||
if (!volume_page) {
|
if (!volume_page) {
|
||||||
ESP_LOGE(TAG, "Failed to create volume page");
|
ESP_LOGE(TAG, "Failed to create volume page");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_menu_set_page(menu, volume_page);
|
lv_menu_set_page(menu, volume_page);
|
||||||
_currentPage = volume_page;
|
_currentPage = volume_page;
|
||||||
_mode = GUI_MENU; // Keep in menu mode
|
_mode = GUI_MENU; // Keep in menu mode
|
||||||
|
|
||||||
menu_hide_headers(menu);
|
menu_hide_headers(menu);
|
||||||
|
|
||||||
lv_obj_remove_flag(menu, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_remove_flag(menu, LV_OBJ_FLAG_HIDDEN);
|
||||||
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Volume control displayed");
|
ESP_LOGI(TAG, "Volume control displayed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1452,6 +1456,17 @@ static bool menu_stack_is_empty(void) {
|
|||||||
static void menu_go_back(void) {
|
static void menu_go_back(void) {
|
||||||
ESP_LOGI(TAG, "Menu go back requested");
|
ESP_LOGI(TAG, "Menu go back requested");
|
||||||
|
|
||||||
|
// Save volume if exiting from volume page
|
||||||
|
if (_currentPage == _volume_page) {
|
||||||
|
system_setVolume(_current_volume);
|
||||||
|
esp_err_t ret = system_saveVolume();
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "Volume %d saved when exiting volume menu", _current_volume);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Failed to save volume: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (menu_stack_is_empty()) {
|
if (menu_stack_is_empty()) {
|
||||||
ESP_LOGI(TAG, "Menu stack empty, returning to bubble mode");
|
ESP_LOGI(TAG, "Menu stack empty, returning to bubble mode");
|
||||||
_mode = GUI_BUBBLE;
|
_mode = GUI_BUBBLE;
|
||||||
@@ -1497,6 +1512,7 @@ static void update_volume_display(int volume) {
|
|||||||
UNLOCK();
|
UNLOCK();
|
||||||
|
|
||||||
_current_volume = volume;
|
_current_volume = volume;
|
||||||
|
system_setVolume(volume); // Update system state in real-time
|
||||||
ESP_LOGI(TAG, "Volume display updated to %d%%", volume);
|
ESP_LOGI(TAG, "Volume display updated to %d%%", volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "keypad.h"
|
#include "keypad.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "battery.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -313,10 +314,15 @@ void app_main(void)
|
|||||||
bt_app_init();
|
bt_app_init();
|
||||||
print_heap_info("POST_BLUETOOTH");
|
print_heap_info("POST_BLUETOOTH");
|
||||||
|
|
||||||
|
// Initialize battery monitoring
|
||||||
|
ESP_ERROR_CHECK(battery_init());
|
||||||
|
battery_start_monitoring_task();
|
||||||
|
print_heap_info("POST_BATTERY");
|
||||||
|
|
||||||
gpio_set_level(PIN_NUM_LED_0, 1);
|
gpio_set_level(PIN_NUM_LED_0, 1);
|
||||||
gpio_set_level(PIN_NUM_LED_1, 1);
|
gpio_set_level(PIN_NUM_LED_1, 1);
|
||||||
gpio_set_level(PIN_NUM_LED_2, 1);
|
gpio_set_level(PIN_NUM_LED_2, 1);
|
||||||
|
|
||||||
gui_start();
|
gui_start();
|
||||||
print_heap_info("POST_GUI");
|
print_heap_info("POST_GUI");
|
||||||
gpio_set_level(PIN_NUM_LED_2, 1);
|
gpio_set_level(PIN_NUM_LED_2, 1);
|
||||||
|
|||||||
119
main/system.c
119
main/system.c
@@ -13,6 +13,8 @@ static EventManager_t _eventManager;
|
|||||||
static QueueHandle_t _nvsRequestQueue;
|
static QueueHandle_t _nvsRequestQueue;
|
||||||
static const char* NVS_NAMESPACE = "bt_devices";
|
static const char* NVS_NAMESPACE = "bt_devices";
|
||||||
static const char* NVS_KEY_COUNT = "count";
|
static const char* NVS_KEY_COUNT = "count";
|
||||||
|
static const char* NVS_NAMESPACE_SETTINGS = "settings";
|
||||||
|
static const char* NVS_KEY_VOLUME = "volume";
|
||||||
|
|
||||||
static esp_err_t nvs_load_devices_internal(paired_device_t *devices, size_t *count);
|
static esp_err_t nvs_load_devices_internal(paired_device_t *devices, size_t *count);
|
||||||
static esp_err_t nvs_save_devices_internal(const paired_device_t *devices, size_t count);
|
static esp_err_t nvs_save_devices_internal(const paired_device_t *devices, size_t count);
|
||||||
@@ -24,6 +26,9 @@ void system_init(void)
|
|||||||
_systemState.pairedDeviceCount = 0;
|
_systemState.pairedDeviceCount = 0;
|
||||||
_systemState.isCharging = false;
|
_systemState.isCharging = false;
|
||||||
_systemState.swapLR = false;
|
_systemState.swapLR = false;
|
||||||
|
_systemState.volume = 50; // Default volume
|
||||||
|
_systemState.batteryVoltage_mv = 0;
|
||||||
|
_systemState.batteryPercentage = 0;
|
||||||
|
|
||||||
_systemEvent = xEventGroupCreate();
|
_systemEvent = xEventGroupCreate();
|
||||||
|
|
||||||
@@ -31,6 +36,9 @@ void system_init(void)
|
|||||||
_eventManager.mutex = xSemaphoreCreateMutex();
|
_eventManager.mutex = xSemaphoreCreateMutex();
|
||||||
|
|
||||||
system_initNvsService();
|
system_initNvsService();
|
||||||
|
|
||||||
|
// Load saved volume from NVS
|
||||||
|
system_loadVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
int system_getPrimaryAxis(void)
|
int system_getPrimaryAxis(void)
|
||||||
@@ -75,6 +83,38 @@ bool system_getChargeStatus(void)
|
|||||||
return charging;
|
return charging;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void system_setBatteryVoltage(int voltage_mv)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||||
|
_systemState.batteryVoltage_mv = voltage_mv;
|
||||||
|
xSemaphoreGive(_eventManager.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int system_getBatteryVoltage(void)
|
||||||
|
{
|
||||||
|
int voltage;
|
||||||
|
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||||
|
voltage = _systemState.batteryVoltage_mv;
|
||||||
|
xSemaphoreGive(_eventManager.mutex);
|
||||||
|
return voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void system_setBatteryPercentage(int percentage)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||||
|
_systemState.batteryPercentage = percentage;
|
||||||
|
xSemaphoreGive(_eventManager.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int system_getBatteryPercentage(void)
|
||||||
|
{
|
||||||
|
int percentage;
|
||||||
|
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||||
|
percentage = _systemState.batteryPercentage;
|
||||||
|
xSemaphoreGive(_eventManager.mutex);
|
||||||
|
return percentage;
|
||||||
|
}
|
||||||
|
|
||||||
void system_setSwapLR(bool swap)
|
void system_setSwapLR(bool swap)
|
||||||
{
|
{
|
||||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||||
@@ -257,6 +297,85 @@ void system_requestVolumeDown(void) {
|
|||||||
system_notifyAll(EM_EVENT_VOLUME_DOWN);
|
system_notifyAll(EM_EVENT_VOLUME_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void system_setVolume(int volume) {
|
||||||
|
if (volume < 0) volume = 0;
|
||||||
|
if (volume > 100) volume = 100;
|
||||||
|
|
||||||
|
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||||
|
_systemState.volume = volume;
|
||||||
|
xSemaphoreGive(_eventManager.mutex);
|
||||||
|
|
||||||
|
ESP_LOGI("system", "Volume set to %d", volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
int system_getVolume(void) {
|
||||||
|
int volume;
|
||||||
|
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||||
|
volume = _systemState.volume;
|
||||||
|
xSemaphoreGive(_eventManager.mutex);
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t system_saveVolume(void) {
|
||||||
|
nvs_handle_t nvs_handle;
|
||||||
|
esp_err_t ret;
|
||||||
|
|
||||||
|
int volume = system_getVolume();
|
||||||
|
|
||||||
|
ret = nvs_open(NVS_NAMESPACE_SETTINGS, NVS_READWRITE, &nvs_handle);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE("system", "Failed to open NVS namespace for volume write: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nvs_set_i32(nvs_handle, NVS_KEY_VOLUME, volume);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE("system", "Failed to write volume to NVS: %s", esp_err_to_name(ret));
|
||||||
|
nvs_close(nvs_handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nvs_commit(nvs_handle);
|
||||||
|
nvs_close(nvs_handle);
|
||||||
|
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI("system", "Volume %d saved to NVS", volume);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE("system", "Failed to commit volume to NVS: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t system_loadVolume(void) {
|
||||||
|
nvs_handle_t nvs_handle;
|
||||||
|
esp_err_t ret;
|
||||||
|
int32_t volume = 50; // Default value
|
||||||
|
|
||||||
|
ret = nvs_open(NVS_NAMESPACE_SETTINGS, NVS_READONLY, &nvs_handle);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGI("system", "No saved volume found, using default: %d", volume);
|
||||||
|
system_setVolume(volume);
|
||||||
|
return ESP_OK; // Not an error, just means no saved value
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nvs_get_i32(nvs_handle, NVS_KEY_VOLUME, &volume);
|
||||||
|
nvs_close(nvs_handle);
|
||||||
|
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI("system", "Loaded volume from NVS: %d", volume);
|
||||||
|
system_setVolume(volume);
|
||||||
|
} else if (ret == ESP_ERR_NVS_NOT_FOUND) {
|
||||||
|
ESP_LOGI("system", "No saved volume found, using default: %d", volume);
|
||||||
|
system_setVolume(volume);
|
||||||
|
ret = ESP_OK; // Not an error
|
||||||
|
} else {
|
||||||
|
ESP_LOGE("system", "Failed to read volume from NVS: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void system_initNvsService(void) {
|
void system_initNvsService(void) {
|
||||||
_nvsRequestQueue = xQueueCreate(10, sizeof(nvs_request_t));
|
_nvsRequestQueue = xQueueCreate(10, sizeof(nvs_request_t));
|
||||||
if (_nvsRequestQueue == NULL) {
|
if (_nvsRequestQueue == NULL) {
|
||||||
|
|||||||
@@ -58,6 +58,13 @@ typedef struct SystemState_s
|
|||||||
// Swap L/R audio channels
|
// Swap L/R audio channels
|
||||||
bool swapLR;
|
bool swapLR;
|
||||||
|
|
||||||
|
// Volume setting (0-100)
|
||||||
|
int volume;
|
||||||
|
|
||||||
|
// Battery monitoring
|
||||||
|
int batteryVoltage_mv;
|
||||||
|
int batteryPercentage;
|
||||||
|
|
||||||
} SystemState_t;
|
} SystemState_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -93,6 +100,11 @@ float system_getAngle(void);
|
|||||||
void system_setChargeStatus(bool charging);
|
void system_setChargeStatus(bool charging);
|
||||||
bool system_getChargeStatus(void);
|
bool system_getChargeStatus(void);
|
||||||
|
|
||||||
|
void system_setBatteryVoltage(int voltage_mv);
|
||||||
|
int system_getBatteryVoltage(void);
|
||||||
|
void system_setBatteryPercentage(int percentage);
|
||||||
|
int system_getBatteryPercentage(void);
|
||||||
|
|
||||||
void system_setSwapLR(bool swap);
|
void system_setSwapLR(bool swap);
|
||||||
bool system_getSwapLR(void);
|
bool system_getSwapLR(void);
|
||||||
void system_toggleSwapLR(void);
|
void system_toggleSwapLR(void);
|
||||||
@@ -118,6 +130,10 @@ int system_getBtDeviceIndex(void);
|
|||||||
// Volume control functions
|
// Volume control functions
|
||||||
void system_requestVolumeUp(void);
|
void system_requestVolumeUp(void);
|
||||||
void system_requestVolumeDown(void);
|
void system_requestVolumeDown(void);
|
||||||
|
void system_setVolume(int volume);
|
||||||
|
int system_getVolume(void);
|
||||||
|
esp_err_t system_saveVolume(void);
|
||||||
|
esp_err_t system_loadVolume(void);
|
||||||
|
|
||||||
// NVS Service
|
// NVS Service
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
Reference in New Issue
Block a user