Compare commits

...

10 Commits

Author SHA1 Message Date
Adrian Scillato 5e6f6a0c0d
Merge 28745ce0b1 into 27d2a0a2d5 2024-04-27 17:11:58 -04:00
Jason2866 27d2a0a2d5
add target reset (#21292) 2024-04-27 21:52:39 +02:00
Christian Baars b3c075c666
I2S changes for Core 3 (#21291)
* i2s fixes and refactoring

* DMA setting added, more refactoring
2024-04-27 20:50:03 +02:00
s-hadinger 5cc5e5ef45
HASPmota demo of Renaissance Watch for 480x480 displays (#21290)
* HASPmota demo of Renaissance Watch for 480x480 displays

* Put arrow in front of date
2024-04-27 19:05:24 +02:00
Jason2866 71c8748def
Revert "Platform 2024.04.13 (#21264)" (#21288)
This reverts commit 492c6bbda2.
2024-04-27 18:56:11 +02:00
s-hadinger bf01e5bb70
Fix async HMDI CEC (#21287) 2024-04-27 18:22:50 +02:00
sfromis 311a9f18e6
Wrong feature bit for USE_SPL06_007 (#21286)
Obvious "typo" in setting the feature bit for this recently added sensor. Already mentioned in https://github.com/arendst/Tasmota/pull/21185#issuecomment-2071122611
2024-04-27 16:30:57 +02:00
Adrian Scillato 28745ce0b1
Updated tasmota.h with new key for WiFi Hostname 2024-04-21 01:43:59 -07:00
Adrian Scillato 0ab7c63d76
Added new key for Default WiFI Hostname 2024-04-21 01:42:44 -07:00
Adrian Scillato 3f29b0e47d
Allow changes from user_config.h 2024-04-21 01:40:32 -07:00
20 changed files with 254 additions and 55 deletions

View File

@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
- esp32_partition_app3904k_fs3392k partition scheme for 8MB ESP32S3
- TCP Tx En GPIO type
- Berry `webserver.content_close()`
- HASPmota demo of Renaissance Watch for 480x480 displays
### Breaking Changed
- ESP32-C3 OTA binary name from `tasmota32c3cdc.bin` to `tasmota32c3.bin` with USB HWCDC and fallback to serial (#21212)

View File

@ -335,6 +335,35 @@ def esp32_use_external_crashreport(*args, **kwargs):
)
print(Fore.YELLOW + output[0]+": \n"+output[1]+" in "+output[2])
def reset_target(*args, **kwargs):
esptoolpy = join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py")
upload_port = join(env.get("UPLOAD_PORT", "none"))
if "none" in upload_port:
env.AutodetectUploadPort()
upload_port = join(env.get("UPLOAD_PORT", "none"))
esptoolpy_flags = [
"--no-stub",
"--chip", mcu,
"--port", upload_port,
"flash_id"
]
esptoolpy_cmd = [env["PYTHONEXE"], esptoolpy] + esptoolpy_flags
print("Try to reset device")
subprocess.call(esptoolpy_cmd, shell=False)
env.AddCustomTarget(
name="reset_target",
dependencies=None,
actions=[
reset_target
],
title="Reset ESP32 target",
description="This command resets ESP32x target via esptoolpy",
)
env.AddCustomTarget(
name="downloadfs",
dependencies=None,

View File

@ -77,7 +77,7 @@ lib_ignore = ${esp32_defaults.lib_ignore}
ccronexpr
[core32]
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.04.13/platform-espressif32.zip
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.04.12/platform-espressif32.zip
platform_packages =
build_unflags = ${esp32_defaults.build_unflags}
build_flags = ${esp32_defaults.build_flags}

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

View File

@ -0,0 +1,73 @@
# This is a simple demo of displaying Renaissance Watch adapted for 480x480 displays
#
# Just install `haspmota_watch_480.tapp` in the filesystem
#
# Generate with
# rm haspmota_watch_480.tapp ; zip -j -0 haspmota_watch_480.tapp ../haspmota_src/haspmota_watch_480/*
# Test if display is at least 480x480
lv.start()
hres = lv.get_hor_res() # should be 320
vres = lv.get_ver_res() # should be 240
if lv.get_hor_res() < 480 || lv.get_ver_res() < 480
print("Renaissance Watch 480 demo requires a screen at least 480x480")
return
end
import haspmota
haspmota.start(false, tasmota.wd + "pages.jsonl")
var prev_day = -1
def set_watch()
import global
var now = tasmota.rtc()
var time_raw = now['local']
var time = tasmota.time_dump(time_raw)
# set second
if global.contains("p23b13")
global.p23b13.angle = 60 * time['sec']
end
# set minutes
global.p100b12.angle = 60 * time['min'] + (time['sec'] / 10) * 10
# set hours
global.p100b11.angle = 300 * (time['hour'] % 12) + time['min'] * 5
# set day
if time['day'] != prev_day
global.p100b15.text = str(time['day'])
prev_day = time['day']
end
end
def run_watch()
set_watch()
tasmota.set_timer(1000, run_watch)
end
run_watch()
def watch_in()
import global
global.p0b90.hidden = true
global.p0b101.bg_opa = 0
global.p0b101.border_opa = 0
global.p0b102.bg_opa = 0
global.p0b102.border_opa = 0
global.p0b102.text_opa = 0
global.p0b103.bg_opa = 0
global.p0b103.border_opa = 0
end
def watch_out()
import global
global.p0b90.hidden = false
global.p0b101.bg_opa = 255
global.p0b101.border_opa = 255
global.p0b102.bg_opa = 255
global.p0b102.border_opa = 255
global.p0b102.text_opa = 255
global.p0b103.bg_opa = 255
global.p0b103.border_opa = 255
end
tasmota.add_rule("hasp#p100=in", watch_in)
tasmota.add_rule("hasp#p100=out", watch_out)

View File

@ -0,0 +1,29 @@
{"page":0,"comment":"---------- Upper stat line ----------"}
{"id":0,"text_color":"#FFFF44"}
{"id":90,"obj":"flex","x":0,"y":0,"w%":100,"h":24,"bg_color":"#4f4f4f","bg_opa":255,"radius":0,"border_side":1,"border_width":1,"border_color":"#FFFF44","text_color":"#FFFF44"}
{"id":91,"obj":"label","parentid":90,"x":0,"y":0,"w":100,"h%":100,"long_mode":3,"text":"Tasmota","flex_grow":1}
{"id":92,"obj":"fixed","parentid":90,"w":102,"text_color":"#FFFF44"}
{"id":95,"parentid":92,"comment":"-- Clock --","obj":"lv_clock","x":0,"y":3,"w":55,"h":16,"radius":0,"border_side":0}
{"id":96,"parentid":92,"comment":"-- Battery indicator --","obj":"label","x":57,"y":0,"w":20,"h":20,"text":"\uE6A5","align":0,"text_font":"icons-18"}
{"id":97,"parentid":92,"comment":"-- Wifi indicator --","obj":"lv_wifi_arcs","x":73,"y":0,"w":29,"h":20,"radius":0,"border_side":0,"bg_color":"#000000","line_color":"#FFFF44"}
{"comment":"---------- Bottom buttons - prev/home/next ----------"}
{"id":100,"obj":"flex","x":0,"y%":84,"h%":16,"w%":100,"flex_main_place":3}
{"id":101,"obj":"btn","parentid":100,"w%":25,"h%":100,"action":"prev","bg_color":"#4f4f4f","text_color":"#FFFF44","radius":10,"text":"\uF053","text_font":"montserrat-20","border_width":3,"border_side":15,"border_color":"#FFFF44","border_opa":210}
{"id":102,"obj":"btn","parentid":100,"w%":25,"h%":100,"action":"back","bg_color":"#4f4f4f","text_color":"#FFFF44","radius":10,"text":"\uF015","text_font":"montserrat-20","border_width":3,"border_side":15,"border_color":"#FFFF44","border_opa":210}
{"id":103,"obj":"btn","parentid":100,"w%":25,"h%":100,"action":"next","bg_color":"#4f4f4f","text_color":"#FFFF44","radius":10,"text":"\uF054","text_font":"montserrat-20","border_width":3,"border_side":15,"border_color":"#FFFF44","border_opa":210}
{"page":1,"comment":"---------- Page 1 Obj ----------"}
{"id":0,"bg_color":"#000000","text_color":"#FFFFFF"}
{"id":10,"obj":"label","x":0,"y":30,"w%":100,"h":24,"text":"Demo of Renaissance watch 480x480","text_font":"montserrat-20"}
{"page":100,"comment":"---------- Page 100 Renaissance Watch ----------"}
{"id":0,"bg_color":"#000000","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#000000"}
{"id":10,"obj":"img","src":"A:haspmota_watch_480.tapp#/ren_back_480.png","x":0,"y":0,"w":480,"h":480}
{"id":15,"obj":"label","parentid":10,"x":367,"y":225,"w":36,"h":36,"text":"29","align":"right","text_font":"montserrat-28"}
{"id":11,"obj":"img","parentid":10,"src":"A:/haspmota_watch_480.tapp#ren_hour_480.png","x":218,"y":94,"angle":-550}
{"id":12,"obj":"img","parentid":10,"src":"A:/haspmota_watch_480.tapp#ren_min_480.png","angle":500}
{"id":13,"obj":"img","parentid":10,"src":"A:/haspmota_watch_480.tapp#ren_sec_480.png","x":220,"y":20,"angle":1400,"hidden":true}

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -146,7 +146,7 @@ const uint8_t MAX_ROTARIES = 2; // Max number of Rotary Encoders
const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x]
const char MQTT_TOKEN_TOPIC[] PROGMEM = "%topic%"; // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
const char WIFI_HOSTNAME[] = "%s-%04d"; // Expands to <MQTT_TOPIC>-<last 4 decimal chars of MAC address>
const char WIFI_HOSTNAME[] = DEFAULT_WIFI_HOSTNAME;
const uint8_t CONFIG_FILE_SIGN = 0xA5; // Configuration file signature
const uint8_t CONFIG_FILE_XOR = 0x5A; // Configuration file xor (0 = No Xor)

View File

@ -84,6 +84,7 @@
#define WIFI_SCAN_AT_RESTART false // [SetOption56] Scan Wi-Fi network at restart for configured AP's
#define WIFI_SCAN_REGULARLY true // [SetOption57] Scan Wi-Fi network every 44 minutes for configured AP's
#define WIFI_NO_SLEEP false // [SetOption127] Sets Wifi in no-sleep mode which improves responsiveness on some routers
#define DEFAULT_WIFI_HOSTNAME "%s-%04d" // Expands to <MQTT_TOPIC>-<last 4 decimal chars of MAC address>
// -- Syslog --------------------------------------
#define SYS_LOG_HOST "" // [LogHost] (Linux) syslog host

View File

@ -23,8 +23,8 @@
#endif // ESP32_STAGE
#include "include/tasmota_compat.h"
#include "include/tasmota_version.h" // Tasmota version information
#include "include/tasmota.h" // Enumeration used in my_user_config.h
#include "my_user_config.h" // Fixed user configurable options
#include "include/tasmota.h" // Enumeration used in my_user_config.h
#ifdef USE_TLS
#include <t_bearssl.h> // We need to include before "tasmota_globals.h" to take precedence over the BearSSL version in Arduino
#endif // USE_TLS

View File

@ -917,9 +917,8 @@ constexpr uint32_t feature[] = {
0x00000010 | // xdrv_73_9_lora.ino
#endif
#if defined(USE_I2C) && defined(USE_SPL06_007)
0x10000000 | // xsns_25_spl006-7_sensor.ino
0x00000020 | // xsns_25_spl006-7_sensor.ino
#endif
// 0x00000020 | //
// 0x00000040 | //
// 0x00000080 | //
// 0x00000100 | //

View File

@ -53,7 +53,7 @@ enum : int8_t {
};
#define I2S_SLOTS 2
#define AUDIO_SETTINGS_VERSION 1
#define AUDIO_SETTINGS_VERSION 2
typedef struct{
struct{
@ -75,7 +75,7 @@ typedef struct{
uint32_t sample_rate = 16000; // B00-03
uint8_t gain = 10; // B04 - was `volume`
uint8_t mode = I2S_MODE_STD; // B05 - I2S mode standard, PDM, TDM, DAC
uint8_t slot_mask = I2S_SLOT_NOCHANGE;// B06 - slot mask
uint8_t slot_mask = BIT(0) | BIT(1); // B06 - slot mask - both slots aka stereo by default
uint8_t slot_config = I2S_SLOT_MSB;// B07 - slot configuration MSB = 0, PCM = 1, PHILIPS = 2
uint8_t channels = 2; // B08 - mono/stereo - 1 is added for both
bool apll = 1; // B09 - will be ignored on unsupported SOC's
@ -83,11 +83,11 @@ typedef struct{
uint8_t spare[5]; // B0B-0F
} tx;
struct {
uint32_t sample_rate = 16000; // B00-03
uint32_t sample_rate = 32000; // B00-03 - 32000 is compatible with MP3 encoding
uint16_t gain = 30 * 16; // B04-05 - in Q12.4
uint8_t mode = I2S_MODE_PDM; // B06 - I2S mode standard, PDM, TDM, DAC
uint8_t slot_mask = I2S_SLOT_NOCHANGE;// B07 - slot mask
uint8_t slot_config = I2S_SLOT_MSB;// B08 - slot configuration MSB = 0, PCM = 1, PHILIPS = 2
uint8_t slot_mask = BIT(0); // B07 - slot mask = left/right/both depended on mode, so BIT(0) maybe left or right
uint8_t slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT; // B08 - auto equals data_bit_width - can differ from bits per sample e.g. INMP441
uint8_t channels = 1; // B09 - mono/stereo - 1 is added for both
// filters
uint16_t dc_filter_alpha = 0b0111111011111111; // B0A-B0B - DC_block filter = (1-2^(-7)) Q32:1.31, or `0` if disabled
@ -99,11 +99,19 @@ typedef struct{
// alpha = (b) 0.100010100110111 = 0x4537
uint16_t lowpass_alpha = 0b0100010100110111; // B0C-B0D - lowpass filter = 3000Hz for 16000Hz sample rate
bool apll = 1; // B0E - will be ignored on unsupported SOC's
uint8_t spare[1]; // B0F
uint8_t ws_width = 32; // B0F - WS signal width - can differ from bits per sample - default 32 bits for INMP441
bool ws_pol = false; // B10 - WS signal polarity
bool bit_shift = true; // B11 - enable bit shift in Philips mode
bool left_align = true; // B12 - left alignment
bool big_endian = false; // B13 - big endian
bool bit_order_lsb = false; // B14 - lsb first
uint16_t dma_frame_num = 512; // B015/16 - DMA buffer size in samples, 512 should be okay up to ~32000 bps
uint8_t dma_desc_num = 3; // B17 - number of DMA buffers, maybe increased with smaller buffers
uint8_t spare[3]; // B018-20 - padding
} rx;
} tI2SSettings;
static_assert(sizeof(tI2SSettings) == 48, "tI2SSettings Size is not correct");
static_assert(sizeof(tI2SSettings) == 60, "tI2SSettings Size is not correct");
typedef union {
uint8_t data;
@ -120,7 +128,7 @@ class TasmotaI2S;
struct AUDIO_I2S_t {
tI2SSettings *Settings;
i2s_chan_handle_t rx_handle = nullptr;
// i2s_chan_handle_t rx_handle = nullptr;
TasmotaI2S *out = nullptr; // instance used for I2S output, or `nullptr` if none
TasmotaI2S *in = nullptr; // instance used for I2S input, or `nullptr` if none (it can be the same as `out` in case of full duplex)
} audio_i2s;

View File

@ -103,11 +103,10 @@ public:
void setPinout(int32_t bclk, int32_t ws, int32_t dout, int32_t mclk, int32_t din,
bool mclk_inv = false, bool bclk_inv = false, bool ws_inv = false, bool apll = false);
void setSlotConfig(i2s_port_t i2s_port, uint8_t tx_slot_config, uint8_t rx_slot_config,
void setSlotConfig(i2s_port_t i2s_port, uint8_t tx_slot_config,
uint8_t tx_slot_mask, uint8_t rx_slot_mask) {
_i2s_port = i2s_port;
_tx_slot_config = tx_slot_config;
_rx_slot_config = rx_slot_config;
}
void setRxFreq(uint16_t freq) { _rx_freq = freq; }
@ -237,7 +236,7 @@ protected:
// TX
bool _tx_configured = false; // true = configured, false = not configured
uint8_t _tx_mode = I2S_MODE_STD; // I2S_MODE_STD / I2S_MODE_PDM / I2S_MODE_TDM / I2S_MODE_DAC
uint8_t _tx_slot_mask = I2S_SLOT_NOCHANGE;
uint8_t _tx_slot_mask = BIT(0)|BIT(1);// default stereo
bool _tx_running = false; // true = enabled, false = disabled
uint8_t _tx_channels = 2; // number of channels, 1 = mono, 2 = stereo -- `channels`
i2s_chan_handle_t _tx_handle = nullptr; // I2S channel handle, automatically computed
@ -247,12 +246,12 @@ protected:
// RX
bool _rx_configured = false; // true = configured, false = not configured
uint8_t _rx_mode = I2S_MODE_STD; // I2S_MODE_STD / I2S_MODE_PDM / I2S_MODE_TDM / I2S_MODE_DAC
uint8_t _rx_slot_mask = I2S_SLOT_NOCHANGE;
uint8_t _rx_slot_mask = BIT(0); // default mono: for PDM right, for standard left
bool _rx_running = false; // true = enabled, false = disabled
uint8_t _rx_channels = 2; // number of channels, 1 = mono, 2 = stereo
i2s_chan_handle_t _rx_handle = nullptr; // I2S channel handle, automatically computed
uint8_t _rx_slot_config = I2S_SLOT_MSB;// I2S slot configuration
uint16_t _rx_freq = 16000; // I2S Rx sampling frequency in Hz
// uint8_t _rx_slot_config; // I2S slot configuration
uint16_t _rx_freq = 32000; // I2S Rx sampling frequency in Hz - default 32 kHz to prevent problems with Shine Encoder
uint8_t _rx_bps = 16; // bits per sample, 16 or 8
uint16_t _rx_gain = 0x10; // Microphone gain in Q12.4 format (0x10 = 1.0)
@ -539,7 +538,7 @@ bool TasmotaI2S::startI2SChannel(bool tx, bool rx) {
} else if (_tx_slot_config == I2S_SLOT_PHILIPS) { // PHILIPS
tx_std_cfg.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(tx_data_bit_width, tx_slot_mode);
}
if (_tx_slot_mask != I2S_SLOT_NOCHANGE) { tx_std_cfg.slot_cfg.slot_mask = (i2s_std_slot_mask_t)_tx_slot_mask; }
tx_std_cfg.slot_cfg.slot_mask = (i2s_std_slot_mask_t)_tx_slot_mask;
#if SOC_I2S_SUPPORTS_APLL
if (_apll) { tx_std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_APLL; }
#endif // SOC_I2S_SUPPORTS_APLL
@ -590,9 +589,9 @@ bool TasmotaI2S::startI2SChannel(bool tx, bool rx) {
i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(_i2s_port, I2S_ROLE_MASTER);
i2s_data_bit_width_t rx_data_bit_width = (_rx_bps == 8) ? I2S_DATA_BIT_WIDTH_8BIT : I2S_DATA_BIT_WIDTH_16BIT;
// change to 3 buffers of 512 samples
rx_chan_cfg.dma_desc_num = 3;
rx_chan_cfg.dma_frame_num = 512;
// defaults to 3 buffers of 512 samples
rx_chan_cfg.dma_desc_num = audio_i2s.Settings->rx.dma_desc_num;
rx_chan_cfg.dma_frame_num = audio_i2s.Settings->rx.dma_frame_num;
AddLog(LOG_LEVEL_DEBUG, "I2S: rx_chan_cfg id:%i role:%i dma_desc_num:%i dma_frame_num:%i auto_clear:%i",
rx_chan_cfg.id, rx_chan_cfg.role, rx_chan_cfg.dma_desc_num, rx_chan_cfg.dma_frame_num, rx_chan_cfg.auto_clear);
@ -615,7 +614,7 @@ bool TasmotaI2S::startI2SChannel(bool tx, bool rx) {
},
},
};
if (_rx_slot_mask != I2S_SLOT_NOCHANGE) { rx_pdm_cfg.slot_cfg.slot_mask = (i2s_pdm_slot_mask_t)_rx_slot_mask; }
rx_pdm_cfg.slot_cfg.slot_mask = (i2s_pdm_slot_mask_t)_rx_slot_mask;
// AddLog(LOG_LEVEL_DEBUG, "I2S: rx_pdm_cfg clk_cfg sample_rate_hz:%i clk_src:%i mclk_multiple:%i dn_sample_mode:%i",
// rx_pdm_cfg.clk_cfg.sample_rate_hz, rx_pdm_cfg.clk_cfg.clk_src, rx_pdm_cfg.clk_cfg.mclk_multiple, rx_pdm_cfg.clk_cfg.dn_sample_mode);
@ -637,10 +636,26 @@ bool TasmotaI2S::startI2SChannel(bool tx, bool rx) {
break;
#endif // SOC_I2S_SUPPORTS_PDM_RX
case I2S_MODE_STD:
{
{
i2s_std_slot_config_t _slot_cfg = {
.data_bit_width = (i2s_data_bit_width_t)bps,
.slot_bit_width = (i2s_slot_bit_width_t)audio_i2s.Settings->rx.slot_bit_width,
.slot_mode = (i2s_slot_mode_t)channels,
.slot_mask = (i2s_std_slot_mask_t)audio_i2s.Settings->rx.slot_mask,
.ws_width = audio_i2s.Settings->rx.ws_width,
.ws_pol = audio_i2s.Settings->rx.ws_pol,
.bit_shift = audio_i2s.Settings->rx.bit_shift,
#if SOC_I2S_HW_VERSION_1 // For esp32/esp32-s2
.msb_right = audio_i2s.Settings->rx.bit_order_lsb, // Placeholder for now!!
#else
.left_align = audio_i2s.Settings->rx.left_align,
.big_endian = audio_i2s.Settings->rx.big_endian,
.bit_order_lsb = audio_i2s.Settings->rx.bit_order_lsb,
#endif
};
i2s_std_config_t rx_std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(_rx_freq),
.slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(rx_data_bit_width, rx_slot_mode),
.slot_cfg = _slot_cfg,
.gpio_cfg = {
.mclk = (gpio_num_t)Pin(GPIO_I2S_MCLK),
.bclk = (gpio_num_t)Pin(GPIO_I2S_BCLK),
@ -654,11 +669,10 @@ bool TasmotaI2S::startI2SChannel(bool tx, bool rx) {
},
},
};
if (_rx_slot_mask != I2S_SLOT_NOCHANGE) { rx_std_cfg.slot_cfg.slot_mask = (i2s_std_slot_mask_t)_rx_slot_mask; }
err = i2s_channel_init_std_mode(_rx_handle, &rx_std_cfg);
AddLog(LOG_LEVEL_DEBUG, "I2S: RX i2s_channel_init_std_mode err:%i", err);
AddLog(LOG_LEVEL_DEBUG, "I2S: RX channel in standard mode with 16 bit width on %i channel(s) initialized", rx_slot_mode);
AddLog(LOG_LEVEL_DEBUG, "I2S: RX i2s_channel_init_std_mode with err:%i", err);
AddLog(LOG_LEVEL_DEBUG, "I2S: RX channel in standard mode with %u bit width on %i channel(s) initialized", bps, rx_slot_mode);
if (err) {
_rx_handle = nullptr;
return false;

View File

@ -227,11 +227,19 @@ void CmndI2SConfig(void) {
// cfg->rx.gain = rx.getUInt(PSTR("Gain"), cfg->rx.gain);
cfg->rx.mode = rx.getUInt(PSTR("Mode"), cfg->rx.mode);
cfg->rx.slot_mask = rx.getUInt(PSTR("SlotMask"), cfg->rx.slot_mask);
cfg->rx.slot_config = rx.getUInt(PSTR("SlotConfig"), cfg->rx.slot_config);
cfg->rx.slot_bit_width = rx.getUInt(PSTR("SlotWidth"), cfg->rx.slot_bit_width);
cfg->rx.channels = rx.getUInt(PSTR("Channels"), cfg->rx.channels);
cfg->rx.dc_filter_alpha = rx.getUInt(PSTR("DCFilterAlpha"), cfg->rx.dc_filter_alpha);
cfg->rx.lowpass_alpha = rx.getUInt(PSTR("LowpassAlpha"), cfg->rx.lowpass_alpha);
cfg->rx.apll = rx.getUInt(PSTR("APLL"), cfg->rx.apll);
cfg->rx.ws_width = rx.getUInt(PSTR("WsWidth"), cfg->rx.ws_width);
cfg->rx.ws_pol = rx.getUInt(PSTR("WsPol"), cfg->rx.ws_pol);
cfg->rx.bit_shift = rx.getUInt(PSTR("BitShift"), cfg->rx.bit_shift);
cfg->rx.left_align = rx.getUInt(PSTR("LeftAlign"), cfg->rx.left_align);
cfg->rx.big_endian = rx.getUInt(PSTR("BigEndian"), cfg->rx.big_endian);
cfg->rx.bit_order_lsb = rx.getUInt(PSTR("LsbOrder"), cfg->rx.bit_order_lsb);
cfg->rx.dma_frame_num = rx.getUInt(PSTR("DMAFrame"), cfg->rx.dma_frame_num);
cfg->rx.dma_desc_num = rx.getUInt(PSTR("DMADesc"), cfg->rx.dma_desc_num);
}
I2SSettingsSave(AUDIO_CONFIG_FILENAME);
}
@ -268,11 +276,19 @@ void CmndI2SConfig(void) {
// "\"Gain\":%d,"
"\"Mode\":%d,"
"\"SlotMask\":%d,"
"\"SlotConfig\":%d,"
"\"SlotWidth\":%d,"
"\"Channels\":%d,"
"\"DCFilterAlpha\":%d,"
"\"LowpassAlpha\":%d,"
"\"APLL\":%d"
"\"APLL\":%d,"
"\"WsWidth\":%d,"
"\"WsPol\":%d,"
"\"BitShift\":%d,"
"\"LeftAlign\":%d,"
"\"BigEndian\":%d,"
"\"LsbOrder\":%d,"
"\"DMAFrame\":%d,"
"\"DMADesc\":%d"
"}}}",
cfg->sys.version,
cfg->sys.duplex,
@ -300,11 +316,19 @@ void CmndI2SConfig(void) {
// cfg->rx.gain,
cfg->rx.mode,
cfg->rx.slot_mask,
cfg->rx.slot_config,
cfg->rx.slot_bit_width,
cfg->rx.channels,
cfg->rx.dc_filter_alpha,
cfg->rx.lowpass_alpha,
cfg->rx.apll
cfg->rx.apll,
cfg->rx.ws_width,
cfg->rx.ws_pol,
cfg->rx.bit_shift,
cfg->rx.left_align,
cfg->rx.big_endian,
cfg->rx.bit_order_lsb,
cfg->rx.dma_frame_num,
cfg->rx.dma_desc_num
);
}
/*********************************************************************************************\
@ -325,6 +349,7 @@ void I2sMicTask(void *arg){
uint16_t bwritten;
uint32_t ctime;
uint32_t gain = audio_i2s.Settings->rx.gain;
uint32_t timeForOneRead;
if (!audio_i2s_mp3.use_stream) {
mp3_out = ufsp->open(audio_i2s_mp3.mic_path, "w");
@ -354,7 +379,7 @@ void I2sMicTask(void *arg){
} else {
config.mpeg.mode = STEREO;
}
config.mpeg.bitr = 128;
// config.mpeg.bitr = 128; - this is default anyway, but maybe we want to make it a variable in the future
config.wave.samplerate = audio_i2s.Settings->rx.sample_rate;
config.wave.channels = (channels)(audio_i2s.Settings->rx.channels);
@ -379,16 +404,25 @@ void I2sMicTask(void *arg){
}
ctime = TasmotaGlobal.uptime;
timeForOneRead = 1000 / ((audio_i2s.Settings->rx.sample_rate / samples_per_pass));
timeForOneRead -= 1; // be very in time
AddLog(LOG_LEVEL_DEBUG, PSTR("I2S: samples %u, bytesize %u, time: %u"),samples_per_pass, bytesize, timeForOneRead);
while (!audio_i2s_mp3.mic_stop) {
TickType_t xLastWakeTime = xTaskGetTickCount();
size_t bytes_read;
i2s_channel_read(audio_i2s.rx_handle, (void*)buffer, bytesize, &bytes_read, (100 / portTICK_PERIOD_MS));
// bytes_read = audio_i2s.in->readMic((uint8_t*)buffer, bytesize, true /*dc_block*/, false /*apply_gain*/, true /*lowpass*/, nullptr /*peak_ptr*/);
i2s_channel_read(audio_i2s.in->getRxHandle(), (void*)buffer, bytesize, &bytes_read, pdMS_TO_TICKS(3));
if(bytes_read < bytesize) AddLog(LOG_LEVEL_DEBUG, PSTR("!! %u, %u"), bytes_read, bytesize);
if (gain > 1) {
// set gain
// set gain the "old way"
int16_t _gain = gain / 16;
for (uint32_t cnt = 0; cnt < bytes_read / 2; cnt++) {
buffer[cnt] *= gain;
buffer[cnt] *= _gain;
}
}
ucp = shine_encode_buffer_interleaved(s, buffer, &written);
@ -406,6 +440,8 @@ void I2sMicTask(void *arg){
}
}
audio_i2s_mp3.recdur = TasmotaGlobal.uptime - ctime;
vTaskDelayUntil( &xLastWakeTime, pdMS_TO_TICKS(timeForOneRead));
}
ucp = shine_flush(s, &written);
@ -433,7 +469,7 @@ exit:
audio_i2s_mp3.client.stop();
}
audio_i2s.out->stopRx();
audio_i2s.in->stopRx();
audio_i2s_mp3.mic_stop = 0;
audio_i2s_mp3.mic_error = error;
AddLog(LOG_LEVEL_INFO, PSTR("mp3task result code: %d"), error);
@ -453,13 +489,10 @@ int32_t I2sRecordShine(char *path) {
strlcpy(audio_i2s_mp3.mic_path, path, sizeof(audio_i2s_mp3.mic_path));
audio_i2s_mp3.mic_stop = 0;
uint32_t stack = 4096;
uint32_t stack = 8000;
audio_i2s_mp3.use_stream = !strcmp(audio_i2s_mp3.mic_path, "stream.mp3");
if (audio_i2s_mp3.use_stream) {
stack = 8000;
}
audio_i2s.out->startRx();
audio_i2s.in->startRx();
err = xTaskCreatePinnedToCore(I2sMicTask, "MIC", stack, NULL, 3, &audio_i2s_mp3.mic_task_handle, 1);
@ -507,9 +540,9 @@ void I2SSettingsLoad(const char * config_filename, bool erase) {
else if (TfsLoadFile(config_filename, (uint8_t*)audio_i2s.Settings, sizeof(tI2SSettings))) {
AddLog(LOG_LEVEL_INFO, "I2S: config loaded from file '%s'", config_filename);
if ((audio_i2s.Settings->sys.version == 0) || (audio_i2s.Settings->sys.version > AUDIO_SETTINGS_VERSION)) {
AddLog(LOG_LEVEL_DEBUG, "I2S: unsupported configuration version %u, use defaults", audio_i2s.Settings->sys.version);
delete audio_i2s.Settings;
audio_i2s.Settings = new tI2SSettings();
AddLog(LOG_LEVEL_DEBUG, "I2S: unsuppoted configuration version, use defaults");
I2SSettingsSave(config_filename);
}
}
@ -671,7 +704,7 @@ void I2sInit(void) {
i2s->setPinout(bclk, ws, dout, mclk, din,
audio_i2s.Settings->sys.mclk_inv[0], audio_i2s.Settings->sys.bclk_inv[0],
audio_i2s.Settings->sys.ws_inv[0], audio_i2s.Settings->tx.apll);
i2s->setSlotConfig((i2s_port_t)port, audio_i2s.Settings->tx.slot_config, audio_i2s.Settings->rx.slot_config,
i2s->setSlotConfig((i2s_port_t)port, audio_i2s.Settings->tx.slot_config,
audio_i2s.Settings->tx.slot_mask, audio_i2s.Settings->rx.slot_mask);
if (tx) {
i2s->setTxMode(audio_i2s.Settings->tx.mode);
@ -1063,8 +1096,8 @@ bool Xdrv42(uint32_t function) {
break;
case FUNC_WEB_ADD_HANDLER:
#if defined(USE_SHINE) && defined(MP3_MIC_STREAM)
audio_i2s.Settings->tx.stream_enable = 1;
I2sMp3Init(1);
// audio_i2s.Settings->tx.stream_enable = 1;
// I2sMp3Init(1);
#endif
#if defined(I2S_BRIDGE)
I2SBridgeInit();

View File

@ -26,10 +26,6 @@
void Stream_mp3(void) {
if (!audio_i2s.Settings->tx.stream_enable) {
return;
}
if (audio_i2s_mp3.stream_active) {
return;
}
@ -37,7 +33,8 @@ void Stream_mp3(void) {
audio_i2s_mp3.stream_active = 1;
audio_i2s_mp3.client = audio_i2s_mp3.MP3Server->client();
AddLog(LOG_LEVEL_INFO, PSTR("I2S: Create client"));
i2s_record_shine((char*)"stream.mp3");
// i2s_record_shine((char*)"stream.mp3");
I2sRecordShine((char*)"stream.mp3");
}
void I2sMp3Loop(void) {
@ -60,6 +57,7 @@ void I2sMp3Init(uint32_t on) {
audio_i2s_mp3.MP3Server->stop();
delete audio_i2s_mp3.MP3Server;
audio_i2s_mp3.MP3Server = nullptr;
audio_i2s_mp3.mic_stop = 1;
AddLog(LOG_LEVEL_INFO, PSTR("MP3: server deleted"));
}
}

View File

@ -116,7 +116,14 @@ void CmndHDMISendRaw(void) {
if (buf.len() > 0 && buf.len() < 16) {
bool success = HDMI_CEC_device->transmitRaw(buf.buf(), buf.len());
if (success) {
HDMI_CEC_device->run();
bool transmitting = true;
while (transmitting) {
HDMI_CEC_device->run();
transmitting = HDMI_CEC_device->isTransmitting();
if (transmitting) {
delay(1); // wait until next ms
}
}
ResponseCmndDone();
} else {
ResponseCmndChar_P(PSTR("Sending failed"));
@ -166,7 +173,14 @@ void CmndHDMISend(void) {
if (buf.len() > 0 && buf.len() < 15) {
bool success = HDMI_CEC_device->transmitFrame(to, buf.buf(), buf.len());
if (success) {
HDMI_CEC_device->run();
bool transmitting = true;
while (transmitting) {
HDMI_CEC_device->run();
transmitting = HDMI_CEC_device->isTransmitting();
if (transmitting) {
delay(1); // wait until next ms
}
}
ResponseCmndDone();
} else {
ResponseCmndChar_P(PSTR("Sending failed"));