Compare commits

...

5 Commits

Author SHA1 Message Date
Philippe G
f08bde8d48 headset, bass/treble, battery from LMS - release 2020-08-15 18:45:59 -07:00
philippe44
a6b57604d3 Update README.md 2020-08-15 16:05:16 -07:00
Philippe G
ca33ff4ba9 fix DAC defaults in KConfig 2020-08-14 10:56:39 -07:00
Philippe G
8b55fa3986 DAC I2S default were wrong - release 2020-08-14 09:23:53 -07:00
Philippe G
e04a631665 typo in config - release 2020-08-13 14:28:11 -07:00
14 changed files with 103 additions and 36 deletions

View File

@@ -86,6 +86,7 @@ The parameter "dac_controlset" allows definition of simple commands to be sent o
```
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. **Note that all values must be decimal**
NB: For well-known configuration, this is ignored
### SPDIF
The NVS parameter "spdif_config" sets the i2s's gpio needed for SPDIF.
@@ -97,6 +98,7 @@ Leave it blank to disable SPDIF usage, you can also define them at compile time
```
bck=<gpio>,ws=<gpio>,do=<gpio>
```
NB: For well-known configuration, this is ignored
### Display
The NVS parameter "display_config" sets the parameters for an optional display. Syntax is
```
@@ -156,12 +158,13 @@ Syntax is:
```
<gpio>=Vcc|GND|amp[:1|0]|ir|jack[:0|1]|green[:0|1]|red[:0|1]|spkfault[:0|1][,<repeated sequence for next GPIO>]
```
You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for SqueezeAMP where these are forced at runtime.
You can define the defaults for jack, spkfault leds at compile time but nvs parameter takes precedence except for well-known configurations where these are forced at runtime.
### LED
See §**set_GPIO** for how to set the green and red LEDs. In addition, their brightness can be controlled using the "led_brigthness" parameter. The syntax is
```
[green=0..100][,red=0..100]
```
NB: For well-known configuration, this is ignored
### Rotary Encoder
One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software.
@@ -278,9 +281,9 @@ There is no good or bad option, it's your choice. Use the NVS parameter "lms_ctr
### Battery / ADC
The NVS parameter "bat_config" sets the ADC1 channel used to measure battery/DC voltage. Scale is a float ratio applied to every sample of the 12 bits ADC. A measure is taken every 10s and an average is made every 5 minutes (not a sliding window). Syntax is
```
channel=0..7,scale=<scale>
channel=0..7,scale=<scale>,cells=<2|3>
```
NB: Set parameter to empty to disable battery reading
NB: Set parameter to empty to disable battery reading. For well-known configuration, this is ignored (except for SqueezeAMP where number of cells is required)
## Setting up ESP-IDF
### Docker
You can use docker to build squeezelite-esp32

View File

@@ -26,7 +26,7 @@ CONFIG_SPKFAULT_GPIO=-1
CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=-1
CONFIG_BAT_SCALE="0"
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_NUM=0
CONFIG_SPDIF_BCK_IO=27
CONFIG_SPDIF_WS_IO=26
CONFIG_SPDIF_DO_IO=-1
@@ -116,10 +116,6 @@ CONFIG_INCLUDE_VORBIS=y
CONFIG_INCLUDE_ALAC=y
CONFIG_A1S=y
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=-1
CONFIG_SPDIF_WS_IO=-1
CONFIG_SPDIF_DO_IO=-1
CONFIG_A2DP_SINK_NAME="SMSL BT4.2"
CONFIG_A2DP_DEV_NAME="Squeezelite"

View File

@@ -25,13 +25,13 @@ CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=-1
CONFIG_BAT_SCALE="0"
CONFIG_I2S_NUM=0
CONFIG_I2S_BCK_IO=33
CONFIG_I2S_WS_IO=25
CONFIG_I2S_DO_IO=32
CONFIG_I2S_BCK_IO=-1
CONFIG_I2S_WS_IO=-1
CONFIG_I2S_DO_IO=-1
CONFIG_I2S_DI_IO=-1
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=33
CONFIG_SPDIF_WS_IO=25
CONFIG_SPDIF_NUM=0
CONFIG_SPDIF_BCK_IO=-1
CONFIG_SPDIF_WS_IO=-1
CONFIG_SPDIF_DO_IO=-1
CONFIG_MUTE_GPIO=-1
CONFIG_MUTE_GPIO_LEVEL=-1
@@ -121,11 +121,6 @@ CONFIG_INCLUDE_ALAC=y
CONFIG_BASIC_I2C_BT=y
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_BCK_IO=-1
CONFIG_SPDIF_WS_IO=-1
CONFIG_SPDIF_DO_IO=-1
CONFIG_A2DP_SINK_NAME="SMSL BT4.2"
CONFIG_A2DP_DEV_NAME="Squeezelite"
CONFIG_A2DP_CONTROL_DELAY_MS=500

View File

@@ -29,7 +29,7 @@ CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=7
CONFIG_BAT_SCALE="20.24"
CONFIG_I2S_NUM=0
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_NUM=0
CONFIG_SPDIF_CONFIG="bck=33,ws=25,do=15"
CONFIG_DAC_CONFIG="model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0"
CONFIG_IDF_TARGET_ESP32=y

View File

@@ -29,7 +29,7 @@ CONFIG_SPKFAULT_GPIO_LEVEL=0
CONFIG_BAT_CHANNEL=7
CONFIG_BAT_SCALE="20.24"
CONFIG_I2S_NUM=0
CONFIG_SDIF_NUM=0
CONFIG_SPDIF_NUM=0
CONFIG_SPDIF_CONFIG="bck=33,ws=25,do=15"
CONFIG_DAC_CONFIG="model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14"
CONFIG_MUTE_GPIO_LEVEL=-1

View File

@@ -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");
}

View File

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

View File

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

View File

@@ -63,8 +63,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 {

View File

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

View File

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

View File

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

View File

@@ -97,17 +97,17 @@ menu "Squeezelite-ESP32"
I2S dma channel to use.
config I2S_BCK_IO
int "I2S Bit clock GPIO number. "
default 33
default -1
help
I2S Bit Clock gpio pin to use.
config I2S_WS_IO
int "I2S Word Select GPIO number. "
default 25
default -1
help
I2S Word Select gpio pin to use.
config I2S_DO_IO
int "I2S Data Output GPIO number. "
default 32
default -1
help
I2S data output gpio pin to use.
config I2S_DI_IO

View File

@@ -333,6 +333,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);