mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-06 03:27:01 +03:00
headphone, bass/treble, battery from LMS
This commit is contained in:
3
TODO
3
TODO
@@ -1,4 +1,5 @@
|
|||||||
- in squeezelite some buffers (stream, output, header, recv) are allocated
|
- in squeezelite some buffers (stream, output, header, recv) are allocated
|
||||||
although they are almost static (expect output). This creates a risk of
|
although they are almost static (expect output). This creates a risk of
|
||||||
memory fragmentation, especially because the large output is re-allocated for
|
memory fragmentation, especially because the large output is re-allocated for
|
||||||
AirPlay
|
AirPlay
|
||||||
|
- libflac in lpc.c can be unrolled - that gains 43k of code, at the expense of 4% CPU
|
||||||
@@ -33,15 +33,27 @@ static struct {
|
|||||||
int channel;
|
int channel;
|
||||||
float sum, avg, scale;
|
float sum, avg, scale;
|
||||||
int count;
|
int count;
|
||||||
|
int cells;
|
||||||
TimerHandle_t timer;
|
TimerHandle_t timer;
|
||||||
} battery;
|
} battery = {
|
||||||
|
.channel = CONFIG_BAT_CHANNEL,
|
||||||
|
.cells = 2,
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int battery_value_svc(void) {
|
int battery_value_svc(void) {
|
||||||
return battery.avg;
|
return battery.avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t battery_level_svc(void) {
|
||||||
|
// TODO: this is totally incorrect
|
||||||
|
return battery.avg ? (battery.avg - (3.0 * battery.cells)) / ((4.2 - 3.0) * battery.cells) * 100 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
*
|
*
|
||||||
@@ -59,29 +71,30 @@ static void battery_callback(TimerHandle_t xTimer) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void battery_svc_init(void) {
|
void battery_svc_init(void) {
|
||||||
battery.channel = CONFIG_BAT_CHANNEL;
|
|
||||||
#ifdef CONFIG_BAT_SCALE
|
#ifdef CONFIG_BAT_SCALE
|
||||||
battery.scale = atof(CONFIG_BAT_SCALE);
|
battery.scale = atof(CONFIG_BAT_SCALE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_BAT_LOCKED
|
|
||||||
char *nvs_item = config_alloc_get_default(NVS_TYPE_STR, "bat_config", "n", 0);
|
char *nvs_item = config_alloc_get_default(NVS_TYPE_STR, "bat_config", "n", 0);
|
||||||
if (nvs_item) {
|
if (nvs_item) {
|
||||||
char *p;
|
char *p;
|
||||||
|
#ifndef CONFIG_BAT_LOCKED
|
||||||
if ((p = strcasestr(nvs_item, "channel")) != NULL) battery.channel = atoi(strchr(p, '=') + 1);
|
if ((p = strcasestr(nvs_item, "channel")) != NULL) battery.channel = atoi(strchr(p, '=') + 1);
|
||||||
if ((p = strcasestr(nvs_item, "scale")) != NULL) battery.scale = atof(strchr(p, '=') + 1);
|
if ((p = strcasestr(nvs_item, "scale")) != NULL) battery.scale = atof(strchr(p, '=') + 1);
|
||||||
|
#endif
|
||||||
|
if ((p = strcasestr(nvs_item, "cells")) != NULL) battery.cells = atof(strchr(p, '=') + 1);
|
||||||
free(nvs_item);
|
free(nvs_item);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (battery.channel != -1) {
|
if (battery.channel != -1) {
|
||||||
ESP_LOGI(TAG, "Battery measure channel: %u, scale %f", battery.channel, battery.scale);
|
|
||||||
|
|
||||||
adc1_config_width(ADC_WIDTH_BIT_12);
|
adc1_config_width(ADC_WIDTH_BIT_12);
|
||||||
adc1_config_channel_atten(battery.channel, ADC_ATTEN_DB_0);
|
adc1_config_channel_atten(battery.channel, ADC_ATTEN_DB_0);
|
||||||
|
|
||||||
|
battery.avg = adc1_get_raw(battery.channel) * battery.scale / 4095.0;
|
||||||
battery.timer = xTimerCreate("battery", BATTERY_TIMER / portTICK_RATE_MS, pdTRUE, NULL, battery_callback);
|
battery.timer = xTimerCreate("battery", BATTERY_TIMER / portTICK_RATE_MS, pdTRUE, NULL, battery_callback);
|
||||||
xTimerStart(battery.timer, portMAX_DELAY);
|
xTimerStart(battery.timer, portMAX_DELAY);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Battery measure channel: %u, scale %f, cells %u, avg %.2fV", battery.channel, battery.scale, battery.cells, battery.avg);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "No battery");
|
ESP_LOGI(TAG, "No battery");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ extern void (*spkfault_handler_svc)(bool inserted);
|
|||||||
extern bool spkfault_svc(void);
|
extern bool spkfault_svc(void);
|
||||||
|
|
||||||
extern int battery_value_svc(void);
|
extern int battery_value_svc(void);
|
||||||
|
extern uint8_t battery_level_svc(void);
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
|
#include "monitor.h"
|
||||||
|
|
||||||
mutex_type slimp_mutex;
|
mutex_type slimp_mutex;
|
||||||
|
|
||||||
@@ -60,3 +61,11 @@ u16_t get_RSSI(void) {
|
|||||||
if (wifidata.primary != 0) return 100 + wifidata.rssi + 30;
|
if (wifidata.primary != 0) return 100 + wifidata.rssi + 30;
|
||||||
else return 0xffff;
|
else return 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16_t get_plugged(void) {
|
||||||
|
return jack_inserted_svc() ? PLUG_HEADPHONE : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8_t get_battery(void) {
|
||||||
|
return (battery_level_svc() * 16) / 100;
|
||||||
|
}
|
||||||
|
|||||||
@@ -66,8 +66,13 @@ extern mutex_type slimp_mutex;
|
|||||||
#define LOCK_P mutex_lock(slimp_mutex)
|
#define LOCK_P mutex_lock(slimp_mutex)
|
||||||
#define UNLOCK_P mutex_unlock(slimp_mutex)
|
#define UNLOCK_P mutex_unlock(slimp_mutex)
|
||||||
|
|
||||||
// must provide or define as 0xffff
|
// bitmap of plugs status
|
||||||
u16_t get_RSSI(void);
|
#define PLUG_LINE_IN 0x01
|
||||||
|
#define PLUG_LINE_OUT 0x02
|
||||||
|
#define PLUG_HEADPHONE 0x04
|
||||||
|
u16_t get_RSSI(void); // must provide or define as 0xffff
|
||||||
|
u16_t get_plugged(void); // must provide or define as 0x0
|
||||||
|
u8_t get_battery(void); // must provide 0..15 or define as 0x0
|
||||||
|
|
||||||
// to be defined to nothing if you don't want to support these
|
// to be defined to nothing if you don't want to support these
|
||||||
extern struct visu_export_s {
|
extern struct visu_export_s {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ sure that using rate_delay would fix that
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "squeezelite.h"
|
#include "squeezelite.h"
|
||||||
|
#include "slimproto.h"
|
||||||
#include "esp_pthread.h"
|
#include "esp_pthread.h"
|
||||||
#include "driver/i2s.h"
|
#include "driver/i2s.h"
|
||||||
#include "driver/i2c.h"
|
#include "driver/i2c.h"
|
||||||
@@ -82,6 +83,7 @@ const struct adac_s *adac = &dac_external;
|
|||||||
|
|
||||||
static log_level loglevel;
|
static log_level loglevel;
|
||||||
|
|
||||||
|
static bool (*slimp_handler_chain)(u8_t *data, int len);
|
||||||
static bool jack_mutes_amp;
|
static bool jack_mutes_amp;
|
||||||
static bool running, isI2SStarted;
|
static bool running, isI2SStarted;
|
||||||
static i2s_config_t i2s_config;
|
static i2s_config_t i2s_config;
|
||||||
@@ -108,6 +110,36 @@ static void (*jack_handler_chain)(bool inserted);
|
|||||||
|
|
||||||
#define I2C_PORT 0
|
#define I2C_PORT 0
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* AUDO packet handler
|
||||||
|
*/
|
||||||
|
static bool handler(u8_t *data, int len){
|
||||||
|
bool res = true;
|
||||||
|
|
||||||
|
if (!strncmp((char*) data, "audo", 4)) {
|
||||||
|
struct audo_packet *pkt = (struct audo_packet*) data;
|
||||||
|
// 0 = headphone (internal speakers off), 1 = sub out,
|
||||||
|
// 2 = always on (internal speakers on), 3 = always off
|
||||||
|
|
||||||
|
if (jack_mutes_amp != (pkt->config == 0)) {
|
||||||
|
jack_mutes_amp = pkt->config == 0;
|
||||||
|
config_set_value(NVS_TYPE_STR, "jack_mutes_amp", jack_mutes_amp ? "y" : "n");
|
||||||
|
|
||||||
|
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false);
|
||||||
|
else adac->speaker(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("got AUDO %02x", pkt->config);
|
||||||
|
} else {
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// chain protocol handlers (bitwise or is fine)
|
||||||
|
if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* jack insertion handler
|
* jack insertion handler
|
||||||
*/
|
*/
|
||||||
@@ -164,6 +196,10 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
|
|||||||
int silent_do = -1;
|
int silent_do = -1;
|
||||||
char *p;
|
char *p;
|
||||||
esp_err_t res;
|
esp_err_t res;
|
||||||
|
|
||||||
|
// chain SLIMP handlers
|
||||||
|
slimp_handler_chain = slimp_handler;
|
||||||
|
slimp_handler = handler;
|
||||||
|
|
||||||
p = config_alloc_get_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0);
|
p = config_alloc_get_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0);
|
||||||
jack_mutes_amp = (strcmp(p,"1") == 0 ||strcasecmp(p,"y") == 0);
|
jack_mutes_amp = (strcmp(p,"1") == 0 ||strcasecmp(p,"y") == 0);
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ static void sendSTAT(const char *event, u32_t server_timestamp) {
|
|||||||
packN(&pkt.bytes_received_L, (u64_t)status.stream_bytes & 0xffffffff);
|
packN(&pkt.bytes_received_L, (u64_t)status.stream_bytes & 0xffffffff);
|
||||||
#if EMBEDDED
|
#if EMBEDDED
|
||||||
packn(&pkt.signal_strength, get_RSSI());
|
packn(&pkt.signal_strength, get_RSSI());
|
||||||
|
packn(&pkt.voltage, (get_battery() << 4) | get_plugged());
|
||||||
#else
|
#else
|
||||||
pkt.signal_strength = 0xffff;
|
pkt.signal_strength = 0xffff;
|
||||||
#endif
|
#endif
|
||||||
@@ -197,7 +198,6 @@ static void sendSTAT(const char *event, u32_t server_timestamp) {
|
|||||||
packN(&pkt.output_buffer_size, status.output_size);
|
packN(&pkt.output_buffer_size, status.output_size);
|
||||||
packN(&pkt.output_buffer_fullness, status.output_full);
|
packN(&pkt.output_buffer_fullness, status.output_full);
|
||||||
packN(&pkt.elapsed_seconds, ms_played / 1000);
|
packN(&pkt.elapsed_seconds, ms_played / 1000);
|
||||||
// voltage;
|
|
||||||
packN(&pkt.elapsed_milliseconds, ms_played);
|
packN(&pkt.elapsed_milliseconds, ms_played);
|
||||||
pkt.server_timestamp = server_timestamp; // keep this is server format - don't unpack/pack
|
pkt.server_timestamp = server_timestamp; // keep this is server format - don't unpack/pack
|
||||||
// error_code;
|
// error_code;
|
||||||
|
|||||||
@@ -178,6 +178,12 @@ struct codc_packet {
|
|||||||
u8_t pcm_endianness;
|
u8_t pcm_endianness;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// initially Boom
|
||||||
|
struct audo_packet {
|
||||||
|
char opcode[4];
|
||||||
|
u8_t config;
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef SUN
|
#ifndef SUN
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -287,8 +287,6 @@ void register_default_nvs(){
|
|||||||
config_set_default(NVS_TYPE_STR, "a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS), 0);
|
config_set_default(NVS_TYPE_STR, "a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS), 0);
|
||||||
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "bt_sink_pin", STR(CONFIG_A2DP_CONTROL_DELAY_MS));
|
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "bt_sink_pin", STR(CONFIG_A2DP_CONTROL_DELAY_MS));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
config_set_default(NVS_TYPE_STR, "bt_sink_pin", STR(CONFIG_BT_SINK_PIN), 0);
|
config_set_default(NVS_TYPE_STR, "bt_sink_pin", STR(CONFIG_BT_SINK_PIN), 0);
|
||||||
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "release_url", SQUEEZELITE_ESP32_RELEASE_URL);
|
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "release_url", SQUEEZELITE_ESP32_RELEASE_URL);
|
||||||
config_set_default(NVS_TYPE_STR, "release_url", SQUEEZELITE_ESP32_RELEASE_URL, 0);
|
config_set_default(NVS_TYPE_STR, "release_url", SQUEEZELITE_ESP32_RELEASE_URL, 0);
|
||||||
@@ -361,6 +359,9 @@ void register_default_nvs(){
|
|||||||
ESP_LOGD(TAG,"Registering default value for key %s", "dac_controlset");
|
ESP_LOGD(TAG,"Registering default value for key %s", "dac_controlset");
|
||||||
config_set_default(NVS_TYPE_STR, "dac_controlset", "", 0);
|
config_set_default(NVS_TYPE_STR, "dac_controlset", "", 0);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG,"Registering default value for key %s", "jack_mutes_amp");
|
||||||
|
config_set_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0);
|
||||||
|
|
||||||
ESP_LOGD(TAG,"Registering default value for key %s", "bat_config");
|
ESP_LOGD(TAG,"Registering default value for key %s", "bat_config");
|
||||||
config_set_default(NVS_TYPE_STR, "bat_config", "", 0);
|
config_set_default(NVS_TYPE_STR, "bat_config", "", 0);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user