mirror of https://github.com/arendst/Tasmota.git
Compare commits
7 Commits
cad766d14d
...
3948c36892
Author | SHA1 | Date |
---|---|---|
fb-pilot | 3948c36892 | |
s-hadinger | fd148a8d12 | |
Christian Baars | 5b5fdb0afe | |
legchenkov | ecf7d444c6 | |
Jason2866 | 852ce100db | |
Jason2866 | 27d2a0a2d5 | |
Christian Baars | b3c075c666 |
|
@ -26,6 +26,7 @@ All notable changes to this project will be documented in this file.
|
|||
- LVGL fix memory allocation of flush buffers
|
||||
- Berry `web_add_handler` called before `Webserver` is initialized
|
||||
- Put back wifi IPv6 workaround
|
||||
- Berry `math.inf`, `math.isinf()` and fixed json ouput for `inf` and `nan`
|
||||
|
||||
### Removed
|
||||
- LVGL disabled vector graphics
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "be_object.h"
|
||||
#include "be_mem.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#if BE_USE_JSON_MODULE
|
||||
|
||||
|
@ -515,6 +516,15 @@ static void value_dump(bvm *vm, int *indent, int idx, int fmt)
|
|||
} else if (be_isnil(vm, idx)) { /* convert to json null */
|
||||
be_stack_require(vm, 1 + BE_STACK_FREE_MIN);
|
||||
be_pushstring(vm, "null");
|
||||
} else if (be_isreal(vm, idx)) {
|
||||
be_stack_require(vm, 1 + BE_STACK_FREE_MIN);
|
||||
breal v = be_toreal(vm, idx);
|
||||
if (isnan(v) || isinf(v)) {
|
||||
be_pushstring(vm, "null");
|
||||
} else {
|
||||
be_tostring(vm, idx);
|
||||
be_pushvalue(vm, idx); /* push to top */
|
||||
};
|
||||
} else if (be_isnumber(vm, idx) || be_isbool(vm, idx)) { /* convert to json number and boolean */
|
||||
be_stack_require(vm, 1 + BE_STACK_FREE_MIN);
|
||||
be_tostring(vm, idx);
|
||||
|
|
|
@ -45,6 +45,17 @@ static int m_isnan(bvm *vm)
|
|||
be_return(vm);
|
||||
}
|
||||
|
||||
static int m_isinf(bvm *vm)
|
||||
{
|
||||
if (be_top(vm) >= 1 && be_isreal(vm, 1)) {
|
||||
breal x = be_toreal(vm, 1);
|
||||
be_pushbool(vm, isinf(x));
|
||||
} else {
|
||||
be_pushbool(vm, bfalse);
|
||||
}
|
||||
be_return(vm);
|
||||
}
|
||||
|
||||
static int m_abs(bvm *vm)
|
||||
{
|
||||
if (be_top(vm) >= 1 && be_isnumber(vm, 1)) {
|
||||
|
@ -284,6 +295,7 @@ static int m_rand(bvm *vm)
|
|||
#if !BE_USE_PRECOMPILED_OBJECT
|
||||
be_native_module_attr_table(math) {
|
||||
be_native_module_function("isnan", m_isnan),
|
||||
be_native_module_function("isinf", m_isinf),
|
||||
be_native_module_function("abs", m_abs),
|
||||
be_native_module_function("ceil", m_ceil),
|
||||
be_native_module_function("floor", m_floor),
|
||||
|
@ -308,6 +320,7 @@ be_native_module_attr_table(math) {
|
|||
be_native_module_function("rand", m_rand),
|
||||
be_native_module_real("pi", M_PI),
|
||||
be_native_module_real("nan", NAN),
|
||||
be_native_module_real("inf", INFINITY),
|
||||
be_native_module_int("imax", M_IMAX),
|
||||
be_native_module_int("imin", M_IMIN),
|
||||
};
|
||||
|
@ -317,6 +330,7 @@ be_define_native_module(math, NULL);
|
|||
/* @const_object_info_begin
|
||||
module math (scope: global, depend: BE_USE_MATH_MODULE) {
|
||||
isnan, func(m_isnan)
|
||||
isinf, func(m_isinf)
|
||||
abs, func(m_abs)
|
||||
ceil, func(m_ceil)
|
||||
floor, func(m_floor)
|
||||
|
@ -341,6 +355,7 @@ module math (scope: global, depend: BE_USE_MATH_MODULE) {
|
|||
rand, func(m_rand)
|
||||
pi, real(M_PI)
|
||||
nan, real(NAN)
|
||||
inf, real(INFINITY)
|
||||
imax, int(M_IMAX)
|
||||
imin, int(M_IMIN)
|
||||
}
|
||||
|
|
|
@ -10,5 +10,37 @@ assert(math.isnan(n*0))
|
|||
|
||||
assert(!math.isnan(0))
|
||||
assert(!math.isnan(1.5))
|
||||
assert(!math.isnan(math.inf))
|
||||
|
||||
assert(n != n) #- nan is never identical to itself -#
|
||||
|
||||
#- inf -#
|
||||
i = math.inf
|
||||
assert(str(i) == 'inf')
|
||||
assert(str(-i) == '-inf') # inf has a sign
|
||||
assert(math.isinf(i))
|
||||
assert(math.isinf(i+i))
|
||||
assert(math.isinf(i+1))
|
||||
# the following result in nan
|
||||
assert(math.isnan(i*0))
|
||||
assert(math.isnan(i-i))
|
||||
assert(math.isnan(i/i))
|
||||
|
||||
assert(!math.isinf(0))
|
||||
assert(!math.isinf(1.5))
|
||||
assert(!math.isinf(math.nan))
|
||||
|
||||
assert(i == i) #- equality works for inf -#
|
||||
assert(i == i+1)
|
||||
|
||||
#- nan and inf convert to null in json -#
|
||||
import json
|
||||
|
||||
m_nan = {"v": math.nan}
|
||||
assert(json.dump(m_nan) == '{"v":null}')
|
||||
m_inf1 = {"v": math.inf}
|
||||
assert(json.dump(m_inf1) == '{"v":null}')
|
||||
m_inf2 = {"v": -math.inf}
|
||||
assert(json.dump(m_inf2) == '{"v":null}')
|
||||
m_v = {"v": 3.5}
|
||||
assert(json.dump(m_v) == '{"v":3.5}')
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1366,4 +1366,17 @@ https://rya.nc/tasmota-fingerprint.html"
|
|||
#endif
|
||||
#endif // USE_LVGL && USE_LVGL_FREETYPE
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Post-process I2S
|
||||
\*********************************************************************************************/
|
||||
|
||||
#if defined(USE_I2S_ALL)
|
||||
#define USE_I2S
|
||||
#define USE_I2S_AUDIO
|
||||
#define USE_I2S_MIC
|
||||
#define USE_SHINE
|
||||
#define MP3_MIC_STREAM
|
||||
#define USE_I2S_AUDIO_BERRY
|
||||
#endif // USE_I2S_ALL
|
||||
|
||||
#endif // _MY_USER_CONFIG_H_
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -139,9 +139,9 @@ const char kI2SAudio_Commands[] PROGMEM = "I2S|"
|
|||
#if defined(USE_SHINE) && defined(MP3_MIC_STREAM)
|
||||
"|Stream"
|
||||
#endif // MP3_MIC_STREAM
|
||||
#ifdef I2S_BRIDGE
|
||||
#ifdef USE_I2S_BRIDGE
|
||||
"|Bridge"
|
||||
#endif // I2S_BRIDGE
|
||||
#endif // USE_I2S_BRIDGE
|
||||
;
|
||||
|
||||
void (* const I2SAudio_Command[])(void) PROGMEM = {
|
||||
|
@ -167,8 +167,8 @@ void (* const I2SAudio_Command[])(void) PROGMEM = {
|
|||
#if defined(USE_SHINE) && defined(MP3_MIC_STREAM)
|
||||
&CmndI2SMP3Stream,
|
||||
#endif // MP3_MIC_STREAM
|
||||
#ifdef I2S_BRIDGE
|
||||
&CmndI2SI2SBridge,
|
||||
#ifdef USE_I2S_BRIDGE
|
||||
&CmndI2SBridge,
|
||||
#endif // I2S_BRIDGE
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
|
||||
#ifdef ESP32
|
||||
#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) || defined(USE_I2S_MIC))
|
||||
#ifdef I2S_BRIDGE
|
||||
#if defined(USE_I2S_AUDIO) && ESP_IDF_VERSION_MAJOR >= 5
|
||||
#ifdef USE_I2S_BRIDGE
|
||||
|
||||
#ifndef I2S_BRIDGE_PORT
|
||||
#define I2S_BRIDGE_PORT 6970
|
||||
|
@ -35,15 +35,17 @@
|
|||
|
||||
void i2s_bridge_init(uint8_t mode) {
|
||||
|
||||
audio_i2s.bridge_mode.mode = mode;
|
||||
audio_i2s_mp3.bridge_mode.mode = mode;
|
||||
|
||||
if (I2S_BRIDGE_MODE_OFF == mode) {
|
||||
audio_i2s.i2s_bridge_udp.flush();
|
||||
audio_i2s.i2s_bridge_udp.stop();
|
||||
audio_i2s_mp3.i2s_bridge_udp.flush();
|
||||
audio_i2s_mp3.i2s_bridge_udp.stop();
|
||||
//SpeakerMic(MODE_SPK);
|
||||
AUDIO_PWR_OFF
|
||||
} else {
|
||||
i2s_set_clk(audio_i2s.mic_port, audio_i2s.mic_rate, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);
|
||||
// i2s_set_clk(audio_i2s.mic_port, audio_i2s.mic_rate, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("I2S_bridge: TODO - set bit rate and channels!!"));
|
||||
audio_i2s.in->startRx();
|
||||
|
||||
if ((mode & 3) == I2S_BRIDGE_MODE_WRITE) {
|
||||
//SpeakerMic(MODE_MIC);
|
||||
|
@ -53,13 +55,13 @@ void i2s_bridge_init(uint8_t mode) {
|
|||
//SpeakerMic(MODE_SPK);
|
||||
}
|
||||
|
||||
audio_i2s.i2s_bridge_udp.begin(I2S_BRIDGE_PORT);
|
||||
xTaskCreatePinnedToCore(i2s_bridge_task, "BRIDGE", 8192, NULL, 3, &audio_i2s.i2s_bridge_h, 1);
|
||||
if (!audio_i2s.bridge_mode.master) {
|
||||
audio_i2s_mp3.i2s_bridge_udp.begin(I2S_BRIDGE_PORT);
|
||||
xTaskCreatePinnedToCore(i2s_bridge_task, "BRIDGE", 8192, NULL, 3, &audio_i2s_mp3.i2s_bridge_h, 1);
|
||||
if (!audio_i2s_mp3.bridge_mode.master) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("I2S_bridge: slave started"));
|
||||
} else {
|
||||
char buffer[32];
|
||||
sprintf_P(buffer, PSTR("%u.%u.%u.%u"), audio_i2s.i2s_bridge_ip[0], audio_i2s.i2s_bridge_ip[1], audio_i2s.i2s_bridge_ip[2], audio_i2s.i2s_bridge_ip[3]);
|
||||
sprintf_P(buffer, PSTR("%u.%u.%u.%u"), audio_i2s_mp3.i2s_bridge_ip[0], audio_i2s_mp3.i2s_bridge_ip[1], audio_i2s_mp3.i2s_bridge_ip[2], audio_i2s_mp3.i2s_bridge_ip[3]);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("I2S_bridge: master started sending to ip: %s"), buffer);
|
||||
}
|
||||
AUDIO_PWR_ON
|
||||
|
@ -71,10 +73,10 @@ void make_mono(int16_t *packet_buffer, uint32_t size) {
|
|||
int16_t *wp = (int16_t*)packet_buffer;
|
||||
for (uint32_t cnt = 0; cnt < size / 2; cnt += 2) {
|
||||
int16_t val;
|
||||
if (audio_i2s.bridge_mode.swap_mic) {
|
||||
val = wp[cnt + 1] * audio_i2s.mic_gain;
|
||||
if (audio_i2s_mp3.bridge_mode.swap_mic) {
|
||||
val = wp[cnt + 1] * audio_i2s.in->getRxGain();
|
||||
} else {
|
||||
val = wp[cnt] * audio_i2s.mic_gain;
|
||||
val = wp[cnt] * audio_i2s.in->getRxGain();
|
||||
}
|
||||
wp[cnt] = val;
|
||||
wp[cnt + 1] = val;
|
||||
|
@ -85,39 +87,43 @@ void i2s_bridge_task(void *arg) {
|
|||
int16_t packet_buffer[I2S_BRIDGE_BUFFER_SIZE/2];
|
||||
uint16_t bytesize;
|
||||
|
||||
while (I2S_BRIDGE_MODE_OFF != audio_i2s.bridge_mode.mode) {
|
||||
if ((audio_i2s.bridge_mode.mode & 3) == 3) {
|
||||
while (I2S_BRIDGE_MODE_OFF != audio_i2s_mp3.bridge_mode.mode) {
|
||||
if ((audio_i2s_mp3.bridge_mode.mode & 3) == 3) {
|
||||
// loopback test mode
|
||||
uint32_t bytes_read;
|
||||
size_t bytes_read;
|
||||
bytesize = I2S_BRIDGE_BUFFER_SIZE;
|
||||
i2s_read(audio_i2s.mic_port, (char *)packet_buffer, bytesize, &bytes_read, (100 / portTICK_RATE_MS));
|
||||
// i2s_read(audio_i2s.mic_port, (char *)packet_buffer, bytesize, &bytes_read, (100 / portTICK_RATE_MS));
|
||||
i2s_channel_read(audio_i2s.in->getRxHandle(), (void*)packet_buffer, bytesize, &bytes_read, pdMS_TO_TICKS(100));
|
||||
make_mono(packet_buffer, bytes_read);
|
||||
uint32_t bytes_written;
|
||||
i2s_write(audio_i2s.i2s_port, (const uint8_t*)packet_buffer, bytes_read, &bytes_written, 0);
|
||||
size_t bytes_written;
|
||||
// i2s_write(audio_i2s_mp3.i2s_port, (const uint8_t*)packet_buffer, bytes_read, &bytes_written, 0);
|
||||
i2s_channel_write(audio_i2s.out->getTxHandle(), (void*)packet_buffer, bytes_written, &bytes_written, 0);
|
||||
} else {
|
||||
if (audio_i2s.bridge_mode.mode & I2S_BRIDGE_MODE_READ) {
|
||||
if (audio_i2s.i2s_bridge_udp.parsePacket()) {
|
||||
uint32_t bytes_written;
|
||||
uint32_t len = audio_i2s.i2s_bridge_udp.available();
|
||||
if (audio_i2s_mp3.bridge_mode.mode & I2S_BRIDGE_MODE_READ) {
|
||||
if (audio_i2s_mp3.i2s_bridge_udp.parsePacket()) {
|
||||
size_t bytes_written;
|
||||
size_t len = audio_i2s_mp3.i2s_bridge_udp.available();
|
||||
if (len > I2S_BRIDGE_BUFFER_SIZE) {
|
||||
len = I2S_BRIDGE_BUFFER_SIZE;
|
||||
}
|
||||
len = audio_i2s.i2s_bridge_udp.read((uint8_t *)packet_buffer, len);
|
||||
audio_i2s.i2s_bridge_udp.flush();
|
||||
i2s_write(audio_i2s.i2s_port, (const uint8_t*)packet_buffer, len, &bytes_written, 0);
|
||||
len = audio_i2s_mp3.i2s_bridge_udp.read((uint8_t *)packet_buffer, len);
|
||||
audio_i2s_mp3.i2s_bridge_udp.flush();
|
||||
// i2s_write(audio_i2s.i2s_port, (const uint8_t*)packet_buffer, len, &bytes_written, 0);
|
||||
i2s_channel_write(audio_i2s.out->getTxHandle(), (void*)packet_buffer, bytes_written, &bytes_written, 0);
|
||||
} else {
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (audio_i2s.bridge_mode.mode & I2S_BRIDGE_MODE_WRITE) {
|
||||
uint32_t bytes_read;
|
||||
if (audio_i2s_mp3.bridge_mode.mode & I2S_BRIDGE_MODE_WRITE) {
|
||||
size_t bytes_read;
|
||||
bytesize = I2S_BRIDGE_BUFFER_SIZE;
|
||||
i2s_read(audio_i2s.mic_port, (char *)packet_buffer, bytesize, &bytes_read, (100 / portTICK_RATE_MS));
|
||||
// i2s_read(audio_i2s.mic_port, (char *)packet_buffer, bytesize, &bytes_read, (100 / portTICK_RATE_MS));
|
||||
i2s_channel_read(audio_i2s.in->getRxHandle(), (void*)packet_buffer, bytesize, &bytes_read, pdMS_TO_TICKS(100));
|
||||
make_mono(packet_buffer, bytes_read);
|
||||
audio_i2s.i2s_bridge_udp.beginPacket(audio_i2s.i2s_bridge_ip, I2S_BRIDGE_PORT);
|
||||
audio_i2s.i2s_bridge_udp.write((const uint8_t*)packet_buffer, bytes_read);
|
||||
audio_i2s.i2s_bridge_udp.endPacket();
|
||||
audio_i2s_mp3.i2s_bridge_udp.beginPacket(audio_i2s_mp3.i2s_bridge_ip, I2S_BRIDGE_PORT);
|
||||
audio_i2s_mp3.i2s_bridge_udp.write((const uint8_t*)packet_buffer, bytes_read);
|
||||
audio_i2s_mp3.i2s_bridge_udp.endPacket();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,19 +131,19 @@ uint16_t bytesize;
|
|||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void Cmd_I2SBridge(void) {
|
||||
void CmndI2SBridge(void) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
char *cp = XdrvMailbox.data;
|
||||
if (strchr(cp, '.')) {
|
||||
// enter destination ip
|
||||
audio_i2s.i2s_bridge_ip.fromString(cp);
|
||||
audio_i2s_mp3.i2s_bridge_ip.fromString(cp);
|
||||
Response_P(PSTR("{\"I2S_bridge\":{\"IP\":\"%s\"}}"), cp);
|
||||
} else if (cp = strchr(cp, 'p')) {
|
||||
// enter push to talk pin
|
||||
cp++;
|
||||
audio_i2s.ptt_pin = atoi(cp);
|
||||
pinMode(audio_i2s.ptt_pin, INPUT_PULLUP);
|
||||
Response_P(PSTR("{\"I2S_bridge\":{\"PTT-PIN\":%d}}"), audio_i2s.ptt_pin);
|
||||
audio_i2s_mp3.ptt_pin = atoi(cp);
|
||||
pinMode(audio_i2s_mp3.ptt_pin, INPUT_PULLUP);
|
||||
Response_P(PSTR("{\"I2S_bridge\":{\"PTT-PIN\":%d}}"), audio_i2s_mp3.ptt_pin);
|
||||
} else {
|
||||
I2SBridgeCmd(XdrvMailbox.payload, 1);
|
||||
}
|
||||
|
@ -146,11 +152,11 @@ void Cmd_I2SBridge(void) {
|
|||
|
||||
void SendBridgeCmd(uint8_t mode) {
|
||||
char slavecmd[16];
|
||||
if (audio_i2s.bridge_mode.master) {
|
||||
if (audio_i2s_mp3.bridge_mode.master) {
|
||||
sprintf(slavecmd,"cmd:%d", mode);
|
||||
audio_i2s.i2s_bridgec_udp.beginPacket(audio_i2s.i2s_bridge_ip, I2S_BRIDGE_PORT + 1);
|
||||
audio_i2s.i2s_bridgec_udp.write((const uint8_t*)slavecmd,strlen(slavecmd));
|
||||
audio_i2s.i2s_bridgec_udp.endPacket();
|
||||
audio_i2s_mp3.i2s_bridgec_udp.beginPacket(audio_i2s_mp3.i2s_bridge_ip, I2S_BRIDGE_PORT + 1);
|
||||
audio_i2s_mp3.i2s_bridgec_udp.write((const uint8_t*)slavecmd,strlen(slavecmd));
|
||||
audio_i2s_mp3.i2s_bridgec_udp.endPacket();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,29 +165,29 @@ void I2SBridgeCmd(uint8_t val, uint8_t flg) {
|
|||
if (val > 3) {
|
||||
switch (val) {
|
||||
case 4:
|
||||
audio_i2s.bridge_mode.master = 1;
|
||||
audio_i2s_mp3.bridge_mode.master = 1;
|
||||
break;
|
||||
case 5:
|
||||
audio_i2s.bridge_mode.master = 0;
|
||||
audio_i2s_mp3.bridge_mode.master = 0;
|
||||
break;
|
||||
case 6:
|
||||
audio_i2s.bridge_mode.swap_mic = 1;
|
||||
audio_i2s_mp3.bridge_mode.swap_mic = 1;
|
||||
break;
|
||||
case 7:
|
||||
audio_i2s.bridge_mode.swap_mic = 0;
|
||||
audio_i2s_mp3.bridge_mode.swap_mic = 0;
|
||||
break;
|
||||
}
|
||||
Response_P(PSTR("{\"I2S_bridge\":{\"SWAP_MIC\":%d}}"), audio_i2s.bridge_mode.swap_mic);
|
||||
Response_P(PSTR("{\"I2S_bridge\":{\"SWAP_MIC\":%d}}"), audio_i2s_mp3.bridge_mode.swap_mic);
|
||||
} else {
|
||||
if (audio_i2s.bridge_mode.mode != val) {
|
||||
if ((val == I2S_BRIDGE_MODE_OFF) && (audio_i2s.bridge_mode.mode != I2S_BRIDGE_MODE_OFF)) {
|
||||
if (flg && (audio_i2s.bridge_mode.master)) {
|
||||
if (audio_i2s_mp3.bridge_mode.mode != val) {
|
||||
if ((val == I2S_BRIDGE_MODE_OFF) && (audio_i2s_mp3.bridge_mode.mode != I2S_BRIDGE_MODE_OFF)) {
|
||||
if (flg && (audio_i2s_mp3.bridge_mode.master)) {
|
||||
// shutdown slave
|
||||
SendBridgeCmd(I2S_BRIDGE_MODE_OFF);
|
||||
}
|
||||
i2s_bridge_init(I2S_BRIDGE_MODE_OFF);
|
||||
} else {
|
||||
if (audio_i2s.bridge_mode.mode == I2S_BRIDGE_MODE_OFF) {
|
||||
if (audio_i2s_mp3.bridge_mode.mode == I2S_BRIDGE_MODE_OFF) {
|
||||
// initial on
|
||||
i2s_bridge_init(val);
|
||||
} else {
|
||||
|
@ -195,14 +201,14 @@ void I2SBridgeCmd(uint8_t val, uint8_t flg) {
|
|||
}
|
||||
}
|
||||
|
||||
audio_i2s.bridge_mode.mode = val;
|
||||
audio_i2s_mp3.bridge_mode.mode = val;
|
||||
|
||||
if (flg) {
|
||||
if (audio_i2s.bridge_mode.master) {
|
||||
if (audio_i2s_mp3.bridge_mode.master) {
|
||||
// set slave to complementary mode
|
||||
if (audio_i2s.bridge_mode.mode && ((audio_i2s.bridge_mode.mode & 3) != 3)) {
|
||||
if (audio_i2s_mp3.bridge_mode.mode && ((audio_i2s_mp3.bridge_mode.mode & 3) != 3)) {
|
||||
uint8_t slavemode = I2S_BRIDGE_MODE_READ;
|
||||
if (audio_i2s.bridge_mode.mode & I2S_BRIDGE_MODE_READ) {
|
||||
if (audio_i2s_mp3.bridge_mode.mode & I2S_BRIDGE_MODE_READ) {
|
||||
slavemode = I2S_BRIDGE_MODE_WRITE;
|
||||
}
|
||||
SendBridgeCmd(slavemode);
|
||||
|
@ -210,7 +216,7 @@ void I2SBridgeCmd(uint8_t val, uint8_t flg) {
|
|||
}
|
||||
}
|
||||
}
|
||||
ResponseCmndNumber(audio_i2s.bridge_mode.mode);
|
||||
ResponseCmndNumber(audio_i2s_mp3.bridge_mode.mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,32 +228,32 @@ void i2s_bridge_loop(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (audio_i2s.ptt_pin >= 0) {
|
||||
if (audio_i2s.bridge_mode.mode != I2S_BRIDGE_MODE_OFF) {
|
||||
if (digitalRead(audio_i2s.ptt_pin) == 0) {
|
||||
if (audio_i2s_mp3.ptt_pin >= 0) {
|
||||
if (audio_i2s_mp3.bridge_mode.mode != I2S_BRIDGE_MODE_OFF) {
|
||||
if (digitalRead(audio_i2s_mp3.ptt_pin) == 0) {
|
||||
// push to talk
|
||||
if (audio_i2s.bridge_mode.mode != I2S_BRIDGE_MODE_WRITE) {
|
||||
if (audio_i2s_mp3.bridge_mode.mode != I2S_BRIDGE_MODE_WRITE) {
|
||||
I2SBridgeCmd(I2S_BRIDGE_MODE_WRITE, 1);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (audio_i2s.bridge_mode.mode != I2S_BRIDGE_MODE_READ) {
|
||||
if (audio_i2s_mp3.bridge_mode.mode != I2S_BRIDGE_MODE_READ) {
|
||||
I2SBridgeCmd(I2S_BRIDGE_MODE_READ, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (audio_i2s.i2s_bridgec_udp.parsePacket()) {
|
||||
if (audio_i2s_mp3.i2s_bridgec_udp.parsePacket()) {
|
||||
// received control command
|
||||
memset(packet_buffer,0,sizeof(packet_buffer));
|
||||
audio_i2s.i2s_bridgec_udp.read(packet_buffer, 63);
|
||||
audio_i2s_mp3.i2s_bridgec_udp.read(packet_buffer, 63);
|
||||
char *cp = (char*)packet_buffer;
|
||||
if (!strncmp(cp, "cmd:", 4)) {
|
||||
cp += 4;
|
||||
I2SBridgeCmd(atoi(cp), 0);
|
||||
audio_i2s.i2s_bridge_ip = audio_i2s.i2s_bridgec_udp.remoteIP();
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("I2S_bridge: remote cmd %d"), audio_i2s.bridge_mode.mode);
|
||||
audio_i2s_mp3.i2s_bridge_ip = audio_i2s_mp3.i2s_bridgec_udp.remoteIP();
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("I2S_bridge: remote cmd %d"), audio_i2s_mp3.bridge_mode.mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,13 +264,13 @@ void i2s_bridge_loop(void) {
|
|||
|
||||
void I2SBridgeInit(void) {
|
||||
// start udp control channel
|
||||
audio_i2s.i2s_bridgec_udp.begin(I2S_BRIDGE_PORT + 1);
|
||||
audio_i2s_mp3.i2s_bridgec_udp.begin(I2S_BRIDGE_PORT + 1);
|
||||
//audio_i2s.i2s_bridgec_udp.flush();
|
||||
//audio_i2s.i2s_bridgec_udp.stop();
|
||||
//I2SBridgeCmd(audio_i2s.bridge_mode.mode, 1);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("I2S_bridge: command server created on port: %d "), I2S_BRIDGE_PORT + 1);
|
||||
}
|
||||
|
||||
#endif // I2S_BRIDGE
|
||||
#endif // USE_I2S_BRIDGE
|
||||
#endif // USE_I2S_AUDIO
|
||||
#endif // ESP32
|
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#if defined(USE_AHT1x) || defined(USE_AHT2x)
|
||||
#if defined(USE_AHT1x) || defined(USE_AHT2x) || defined(USE_AHT3x)
|
||||
|
||||
/*********************************************************************************************\
|
||||
* AHT10/15/20 - Temperature and Humidity
|
||||
|
@ -40,7 +40,10 @@
|
|||
* and allows other I2C Devices on the bus but have only one I2C Address (0x38)
|
||||
* 14.09.2021 support AHT20 without enabling AHT1x
|
||||
*
|
||||
* 26.10.2023 support for AHT30 added.
|
||||
*
|
||||
* AHT20 I2C Address: 0x38
|
||||
* AHT30 I2C Address: 0x38
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_63 63
|
||||
|
@ -56,12 +59,15 @@
|
|||
#define AHT_TEMPERATURE_OFFSET 50
|
||||
#define KILOBYTE_CONST 1048576.0f
|
||||
|
||||
#define AHT1X_CMD_DELAY 40
|
||||
#define AHT1X_RST_DELAY 30
|
||||
#define AHT1X_CMD_DELAY 20
|
||||
#define AHT1X_RST_DELAY 10
|
||||
#define AHT1X_MEAS_DELAY 80 // over 75ms in datasheet
|
||||
|
||||
#ifdef USE_AHT2x
|
||||
#define AHTX_CMD 0xB1 // Cmd for AHT2x
|
||||
#ifdef USE_AHT3x
|
||||
#define AHTX_CMD 0xBE // Cmd for AHT3x
|
||||
const char ahtTypes[] PROGMEM = "AHT3X|AHT3X";
|
||||
#elif defined(USE_AHT2x)
|
||||
#define AHTX_CMD 0xBE // Cmd for AHT2x
|
||||
const char ahtTypes[] PROGMEM = "AHT2X|AHT2X";
|
||||
#else
|
||||
#define AHTX_CMD 0xE1 // Cmd for AHT1x
|
||||
|
@ -92,6 +98,7 @@ bool AHT1XWrite(uint8_t aht1x_idx) {
|
|||
Wire.write(AHTMeasureCmd, 3);
|
||||
if (Wire.endTransmission() != 0)
|
||||
return false;
|
||||
delay(AHT1X_MEAS_DELAY);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -198,7 +205,7 @@ bool Xsns63(uint32_t function)
|
|||
}
|
||||
else if (aht1x.count) {
|
||||
switch (function) {
|
||||
case FUNC_EVERY_100_MSECOND:
|
||||
case FUNC_EVERY_SECOND:
|
||||
AHT1XPoll();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
|
@ -215,4 +222,4 @@ bool Xsns63(uint32_t function)
|
|||
}
|
||||
|
||||
#endif // USE_AHT1X
|
||||
#endif // USE_I2C
|
||||
#endif // USE_I2C
|
||||
|
|
Loading…
Reference in New Issue