Compare commits

...

6 Commits

Author SHA1 Message Date
Philippe G
29a74b9ca8 tweak dac_controlset timing - release 2020-09-01 16:23:41 -07:00
Philippe G
d95d1cd3db green led fix + i2c timeout - release 2020-09-01 13:41:17 -07:00
Philippe G
8947f2fc75 shidt i2c_addr by one for consistency - release 2020-08-31 15:37:29 -07:00
philippe44
b6c296460c Update README.md 2020-08-31 11:34:04 -07:00
Philippe G
e25c18a070 no mutex needed for polling check - release 2020-08-30 12:29:40 -07:00
Philippe G
8e3fde6f6e faster & simpler solution for stream poll() - release 2020-08-30 11:23:05 -07:00
6 changed files with 28 additions and 40 deletions

View File

@@ -84,7 +84,7 @@ The parameter "dac_controlset" allows definition of simple commands to be sent o
poweron: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
poweroff: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ] }
```
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**
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**. You can use a validator like [this](https://jsonlint.com) to verify your syntax
NB: For well-known configuration, this is ignored
### SPDIF

View File

@@ -35,7 +35,7 @@ static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data,
bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int Speed ) {
I2CPortNumber = PortNumber;
I2CWait = pdMS_TO_TICKS( Speed ? Speed / 4000 : 100 );
I2CWait = pdMS_TO_TICKS( Speed ? (250 * 250000) / Speed : 250 );
if (SDA != -1 && SCL != -1) {
i2c_config_t Config = { 0 };

View File

@@ -128,12 +128,12 @@ static esp_err_t i2c_write_reg(uint8_t reg, uint8_t val) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, val, I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
@@ -153,15 +153,15 @@ static uint8_t i2c_read_reg(uint8_t reg) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_READ, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK);
i2c_master_read_byte(cmd, &data, I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(i2c_port, cmd, 100 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {

View File

@@ -46,27 +46,17 @@ struct buffer *streambuf = &buf;
#define UNLOCK mutex_unlock(streambuf->mutex)
/*
After a lot of hesitation, I've added that "poll mutex" to prevent
socket from being allocated while we are still in poll(). The issue
happens is we have a close quickly followed by an open, we might still
be in the poll() and simple OS fail as they re-allocate the same socket
on which a thread is still waiting.
Ideally, you want to set the lock in the disconnect() but that would mean
very often we'd have to always wait for the end of the poll(), i.e. up to
100ms for nothing most of the time where if it is in the open(), it is
less elegant as closing a socket on which there is a poll() is not good
but it's more efficient as it is very rare that you'd have an open() less
then 100ms after a close()
When LMS sends a close/open sequence very quickly, the stream thread might
still be waiting in the poll() on the closed socket. It is never recommended
to have a thread closing a socket used by another thread but it works, as
opposed to an infinite select().
In stream_sock() a new socket is created and full OS will allocate a different
one but on RTOS and simple IP stack, the same might be re-used and that causes
an exception as a thread is already waiting on a newly allocated socket
A simple variable that forces stream_sock() to wait until we are out of poll()
is enough and much faster than a mutex
*/
#if EMBEDDED
static mutex_type poll_mutex;
#define LOCK_L mutex_lock(poll_mutex)
#define UNLOCK_L mutex_unlock(poll_mutex)
#else
#define LOCK_L
#define UNLOCK_L
#endif
static bool polling;
static sockfd fd;
struct streamstate stream;
@@ -209,7 +199,6 @@ static void *stream_thread() {
} else {
LOCK_L;
pollinfo.fd = fd;
pollinfo.events = POLLIN;
if (stream.state == SEND_HEADERS) {
@@ -218,10 +207,12 @@ static void *stream_thread() {
}
UNLOCK;
// no mutex needed - we just want to know if we are inside poll()
polling = true;
if (_poll(ssl, &pollinfo, 100)) {
UNLOCK_L;
polling = false;
LOCK;
// check socket has not been closed while in poll
@@ -374,7 +365,7 @@ static void *stream_thread() {
UNLOCK;
} else {
UNLOCK_L;
polling = false;
LOG_SDEBUG("poll timeout");
}
}
@@ -427,9 +418,6 @@ void stream_init(log_level level, unsigned stream_buf_size) {
*stream.header = '\0';
fd = -1;
#if EMBEDDED
mutex_create_p(poll_mutex);
#endif
#if LINUX || FREEBSD
touch_memory(streambuf->buf, streambuf->size);
@@ -459,9 +447,6 @@ void stream_close(void) {
#endif
free(stream.header);
buf_destroy(streambuf);
#if EMBEDDED
mutex_destroy(poll_mutex);
#endif
}
void stream_file(const char *header, size_t header_len, unsigned threshold) {
@@ -503,9 +488,12 @@ void stream_file(const char *header, size_t header_len, unsigned threshold) {
void stream_sock(u32_t ip, u16_t port, const char *header, size_t header_len, unsigned threshold, bool cont_wait) {
struct sockaddr_in addr;
LOCK_L;
#if EMBEDDED
// wait till we are not polling anymore
while (polling && running) { usleep(10000); }
#endif
int sock = socket(AF_INET, SOCK_STREAM, 0);
UNLOCK_L;
if (sock < 0) {
LOG_ERROR("failed to create socket");

View File

@@ -44,7 +44,7 @@ menu "Squeezelite-ESP32"
string
default "model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0" if SQUEEZEAMP
default "model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32" if A1S
default "model=I2S,bck=26,ws=25,do=33,i2c=106,sda=21,scl=22" if TWATCH2020
default "model=I2S,bck=26,ws=25,do=33,i2c=53,sda=21,scl=22" if TWATCH2020
default ""
config SPDIF_CONFIG
string

View File

@@ -413,7 +413,7 @@ void app_main()
/* start the wifi manager */
ESP_LOGD(TAG,"Blinking led");
led_blink(LED_GREEN, 250, 250);
led_blink_pushed(LED_GREEN, 250, 250);
if(bypass_wifi_manager){
ESP_LOGW(TAG,"\n\nwifi manager is disabled. Please use wifi commands to connect to your wifi access point.\n\n");