Browse Source

headphone, bass/treble, battery from LMS

Philippe G 4 years ago
parent
commit
86b64d0415

+ 2 - 1
TODO

@@ -1,4 +1,5 @@
 - in squeezelite some buffers (stream, output, header, recv) are allocated 
 although they are almost static (expect output). This creates a risk of 
 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

+ 22 - 9
components/services/battery.c

@@ -33,15 +33,27 @@ static struct {
 	int channel;
 	float sum, avg, scale;
 	int count;
+	int cells;
 	TimerHandle_t timer;
-} battery;
+} battery = {
+	.channel = CONFIG_BAT_CHANNEL,
+	.cells = 2,
+};	
 
 /****************************************************************************************
  * 
  */
 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) {
-	battery.channel = CONFIG_BAT_CHANNEL;
 #ifdef CONFIG_BAT_SCALE	
 	battery.scale = atof(CONFIG_BAT_SCALE);
 #endif	
 
-#ifndef CONFIG_BAT_LOCKED
 	char *nvs_item = config_alloc_get_default(NVS_TYPE_STR, "bat_config", "n", 0);
 	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, "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);
 	}	
-#endif	
 
 	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_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);
 		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 {
 		ESP_LOGI(TAG, "No battery");
 	}	

+ 1 - 0
components/services/monitor.h

@@ -17,4 +17,5 @@ extern void (*spkfault_handler_svc)(bool inserted);
 extern bool spkfault_svc(void);
 
 extern int battery_value_svc(void);
+extern uint8_t battery_level_svc(void);
 

+ 9 - 0
components/squeezelite/embedded.c

@@ -14,6 +14,7 @@
 #include "esp_system.h"
 #include "esp_timer.h"
 #include "esp_wifi.h"
+#include "monitor.h"
 
 mutex_type slimp_mutex;
 
@@ -60,3 +61,11 @@ u16_t get_RSSI(void) {
     if (wifidata.primary != 0) return 100 + wifidata.rssi + 30;
     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;
+}	 

+ 7 - 2
components/squeezelite/embedded.h

@@ -66,8 +66,13 @@ extern mutex_type slimp_mutex;
 #define LOCK_P   mutex_lock(slimp_mutex)
 #define UNLOCK_P mutex_unlock(slimp_mutex)
 
-// must provide or define as 0xffff
-u16_t		get_RSSI(void);
+// bitmap of plugs status
+#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
 extern struct visu_export_s {

+ 36 - 0
components/squeezelite/output_i2s.c

@@ -31,6 +31,7 @@ sure that using rate_delay would fix that
 */
 
 #include "squeezelite.h"
+#include "slimproto.h"
 #include "esp_pthread.h"
 #include "driver/i2s.h"
 #include "driver/i2c.h"
@@ -82,6 +83,7 @@ const struct adac_s *adac = &dac_external;
 
 static log_level loglevel;
 
+static bool (*slimp_handler_chain)(u8_t *data, int len);
 static bool jack_mutes_amp;
 static bool running, isI2SStarted;
 static i2s_config_t i2s_config;
@@ -108,6 +110,36 @@ static void (*jack_handler_chain)(bool inserted);
 
 #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
  */
@@ -164,6 +196,10 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
 	int silent_do = -1;
 	char *p;
 	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);
 	jack_mutes_amp = (strcmp(p,"1") == 0 ||strcasecmp(p,"y") == 0);

+ 1 - 1
components/squeezelite/slimproto.c

@@ -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);
 #if EMBEDDED
 	packn(&pkt.signal_strength, get_RSSI());
+	packn(&pkt.voltage, (get_battery() << 4) | get_plugged());
 #else 
 	pkt.signal_strength = 0xffff;
 #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_fullness, status.output_full);
 	packN(&pkt.elapsed_seconds, ms_played / 1000);
-	// voltage;
 	packN(&pkt.elapsed_milliseconds, ms_played);
 	pkt.server_timestamp = server_timestamp; // keep this is server format - don't unpack/pack
 	// error_code;

+ 6 - 0
components/squeezelite/slimproto.h

@@ -178,6 +178,12 @@ struct codc_packet {
 	u8_t  pcm_endianness;
 };
 
+// initially Boom 
+struct audo_packet {
+	char  opcode[4];
+	u8_t  config;
+};
+
 #ifndef SUN
 #pragma pack(pop)
 #else

+ 3 - 2
main/esp_app_main.c

@@ -287,8 +287,6 @@ void register_default_nvs(){
 	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));
 
-
-
 	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);
 	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");
 	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");
 	config_set_default(NVS_TYPE_STR, "bat_config", "", 0);