mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-28 05:06:32 +00:00
commit
e6d8afbe58
@ -268,8 +268,8 @@ int BM8563_RTC::SetAlarmIRQ(const RTC_TimeTypeDef &RTC_TimeStruct)
|
|||||||
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_buf[2] = 0x00;
|
//out_buf[2] = 0x00;
|
||||||
out_buf[3] = 0x00;
|
//out_buf[3] = 0x00;
|
||||||
|
|
||||||
uint8_t reg_value = ReadReg(0x01);
|
uint8_t reg_value = ReadReg(0x01);
|
||||||
|
|
||||||
|
@ -1251,7 +1251,7 @@ float Get_MFVal(uint8_t index, int16_t bind) {
|
|||||||
if (bind<0) {
|
if (bind<0) {
|
||||||
return maxind;
|
return maxind;
|
||||||
}
|
}
|
||||||
if (bind<1 || bind>maxind) bind = maxind;
|
if (bind < 1 || bind > maxind ) bind = 1;
|
||||||
return mflp->rbuff[bind - 1];
|
return mflp->rbuff[bind - 1];
|
||||||
}
|
}
|
||||||
mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float);
|
mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float);
|
||||||
@ -1266,11 +1266,13 @@ void Set_MFVal(uint8_t index, uint16_t bind, float val) {
|
|||||||
if (count==index) {
|
if (count==index) {
|
||||||
uint16_t maxind = mflp->numvals & AND_FILT_MASK;
|
uint16_t maxind = mflp->numvals & AND_FILT_MASK;
|
||||||
if (!bind) {
|
if (!bind) {
|
||||||
|
if (val < 0 || val >= maxind) val = 0;
|
||||||
mflp->index = val;
|
mflp->index = val;
|
||||||
} else {
|
} else {
|
||||||
if (bind<1 || bind>maxind) bind = maxind;
|
if (bind > 1 && bind <= maxind) {
|
||||||
mflp->rbuff[bind-1] = val;
|
mflp->rbuff[bind-1] = val;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float);
|
mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float);
|
||||||
@ -2407,6 +2409,10 @@ chknext:
|
|||||||
#endif
|
#endif
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
if (!strncmp(vname, "frnm", 4)) {
|
||||||
|
if (sp) strlcpy(sp, SettingsText(SET_FRIENDLYNAME1), glob_script_mem.max_ssize);
|
||||||
|
goto strexit;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
if (!strncmp(vname, "gtmp", 4)) {
|
if (!strncmp(vname, "gtmp", 4)) {
|
||||||
@ -2783,6 +2789,17 @@ chknext:
|
|||||||
len++;
|
len++;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
#if defined(ESP32) && (defined(USE_M5STACK_CORE2))
|
||||||
|
if (!strncmp(vname, "rec(", 4)) {
|
||||||
|
char str[SCRIPT_MAXSSIZE];
|
||||||
|
lp = GetStringArgument(lp + 4, OPER_EQU, str, 0);
|
||||||
|
SCRIPT_SKIP_SPACES
|
||||||
|
lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0);
|
||||||
|
fvar = i2s_record(str, fvar);
|
||||||
|
len++;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (!strncmp(vname, "secs", 4)) {
|
if (!strncmp(vname, "secs", 4)) {
|
||||||
@ -3800,8 +3817,9 @@ void esp32_beep(int32_t freq ,uint32_t len) {
|
|||||||
uint8_t pwmpin[5];
|
uint8_t pwmpin[5];
|
||||||
|
|
||||||
void esp_pwm(int32_t value, uint32 freq, uint32_t channel) {
|
void esp_pwm(int32_t value, uint32 freq, uint32_t channel) {
|
||||||
if (channel < 1 || channel > 3) channel = 1;
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
|
if (channel < 1 || channel > 8) channel = 1;
|
||||||
channel+=7;
|
channel+=7;
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
if (value <= -64) value = 0;
|
if (value <= -64) value = 0;
|
||||||
@ -3817,6 +3835,7 @@ void esp_pwm(int32_t value, uint32 freq, uint32_t channel) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// esp8266 default to range 0-1023
|
// esp8266 default to range 0-1023
|
||||||
|
if (channel < 1 || channel > 5) channel = 1;
|
||||||
channel-=1;
|
channel-=1;
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
if (value <= -64) value = 0;
|
if (value <= -64) value = 0;
|
||||||
@ -7174,7 +7193,8 @@ exgc:
|
|||||||
char *cp = &label[3];
|
char *cp = &label[3];
|
||||||
//todflg=atoi(&label[3]);
|
//todflg=atoi(&label[3]);
|
||||||
todflg = strtol(cp, &cp, 10);
|
todflg = strtol(cp, &cp, 10);
|
||||||
if (todflg>=entries) todflg = entries - 1;
|
if (todflg >= entries) todflg = entries - 1;
|
||||||
|
if (todflg < 0) todflg = 0;
|
||||||
if (*cp=='/') {
|
if (*cp=='/') {
|
||||||
cp++;
|
cp++;
|
||||||
divflg = strtol(cp, &cp, 10);
|
divflg = strtol(cp, &cp, 10);
|
||||||
@ -7676,6 +7696,7 @@ bool Xdrv10(uint8_t function)
|
|||||||
|
|
||||||
#endif // USE_SCRIPT_FATFS>=0
|
#endif // USE_SCRIPT_FATFS>=0
|
||||||
AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount OK!"));
|
AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount OK!"));
|
||||||
|
|
||||||
//fsp->dateTimeCallback(dateTime);
|
//fsp->dateTimeCallback(dateTime);
|
||||||
glob_script_mem.script_sd_found = 1;
|
glob_script_mem.script_sd_found = 1;
|
||||||
char *script;
|
char *script;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH))
|
#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
|
||||||
#include "AudioFileSourcePROGMEM.h"
|
#include "AudioFileSourcePROGMEM.h"
|
||||||
#include "AudioFileSourceID3.h"
|
#include "AudioFileSourceID3.h"
|
||||||
#include "AudioGeneratorMP3.h"
|
#include "AudioGeneratorMP3.h"
|
||||||
@ -31,18 +31,32 @@
|
|||||||
#include "AudioFileSourceBuffer.h"
|
#include "AudioFileSourceBuffer.h"
|
||||||
#include "AudioGeneratorAAC.h"
|
#include "AudioGeneratorAAC.h"
|
||||||
|
|
||||||
|
#undef AUDIO_PWR_ON
|
||||||
|
#undef AUDIO_PWR_OFF
|
||||||
|
#define AUDIO_PWR_ON
|
||||||
|
#define AUDIO_PWR_OFF
|
||||||
|
|
||||||
#ifdef USE_TTGO_WATCH
|
#ifdef USE_TTGO_WATCH
|
||||||
#undef TTGO_PWR_ON
|
#undef AUDIO_PWR_ON
|
||||||
#undef TTGO_PWR_OFF
|
#undef AUDIO_PWR_OFF
|
||||||
#define TTGO_PWR_ON TTGO_audio_power(true);
|
#define AUDIO_PWR_ON TTGO_audio_power(true);
|
||||||
#define TTGO_PWR_OFF TTGO_audio_power(false);
|
#define AUDIO_PWR_OFF TTGO_audio_power(false);
|
||||||
#else
|
|
||||||
#undef TTGO_PWR_ON
|
|
||||||
#undef TTGO_PWR_OFF
|
|
||||||
#define TTGO_PWR_ON
|
|
||||||
#define TTGO_PWR_OFF
|
|
||||||
#endif // USE_TTGO_WATCH
|
#endif // USE_TTGO_WATCH
|
||||||
|
|
||||||
|
#ifdef USE_M5STACK_CORE2
|
||||||
|
#undef AUDIO_PWR_ON
|
||||||
|
#undef AUDIO_PWR_OFF
|
||||||
|
#define AUDIO_PWR_ON CORE2_audio_power(true);
|
||||||
|
#define AUDIO_PWR_OFF CORE2_audio_power(false);
|
||||||
|
#undef DAC_IIS_BCK
|
||||||
|
#undef DAC_IIS_WS
|
||||||
|
#undef DAC_IIS_DOUT
|
||||||
|
#define DAC_IIS_BCK 12
|
||||||
|
#define DAC_IIS_WS 0
|
||||||
|
#define DAC_IIS_DOUT 2
|
||||||
|
#endif // USE_M5STACK_CORE2
|
||||||
|
|
||||||
|
|
||||||
#define EXTERNAL_DAC_PLAY 1
|
#define EXTERNAL_DAC_PLAY 1
|
||||||
|
|
||||||
#define XDRV_42 42
|
#define XDRV_42 42
|
||||||
@ -82,26 +96,36 @@ AudioGeneratorTalkie *talkie = nullptr;
|
|||||||
|
|
||||||
//! MAX98357A + INMP441 DOUBLE I2S BOARD
|
//! MAX98357A + INMP441 DOUBLE I2S BOARD
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#undef TWATCH_DAC_IIS_BCK
|
#undef DAC_IIS_BCK
|
||||||
#undef TWATCH_DAC_IIS_WS
|
#undef DAC_IIS_WS
|
||||||
#undef TWATCH_DAC_IIS_DOUT
|
#undef DAC_IIS_DOUT
|
||||||
#define TWATCH_DAC_IIS_BCK 15
|
#define DAC_IIS_BCK 15
|
||||||
#define TWATCH_DAC_IIS_WS 2
|
#define DAC_IIS_WS 2
|
||||||
#define TWATCH_DAC_IIS_DOUT 3
|
#define DAC_IIS_DOUT 3
|
||||||
#endif // ESP8266
|
#endif // ESP8266
|
||||||
|
|
||||||
|
// defaults to TTGO WATCH
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#ifndef TWATCH_DAC_IIS_BCK
|
#ifndef DAC_IIS_BCK
|
||||||
#undef TWATCH_DAC_IIS_BCK
|
#undef DAC_IIS_BCK
|
||||||
#define TWATCH_DAC_IIS_BCK 26
|
#define DAC_IIS_BCK 26
|
||||||
#endif
|
#endif
|
||||||
#ifndef TWATCH_DAC_IIS_WS
|
|
||||||
#undef TWATCH_DAC_IIS_WS
|
#ifndef DAC_IIS_WS
|
||||||
#define TWATCH_DAC_IIS_WS 25
|
#undef DAC_IIS_WS
|
||||||
|
#define DAC_IIS_WS 25
|
||||||
#endif
|
#endif
|
||||||
#ifndef TWATCH_DAC_IIS_DOUT
|
|
||||||
#undef TWATCH_DAC_IIS_DOUT
|
#ifndef DAC_IIS_DOUT
|
||||||
#define TWATCH_DAC_IIS_DOUT 33
|
#undef DAC_IIS_DOUT
|
||||||
|
#define DAC_IIS_DOUT 33
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DAC_IIS_DIN
|
||||||
|
#undef DAC_IIS_DIN
|
||||||
|
#define DAC_IIS_DIN 34
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
|
|
||||||
#ifdef SAY_TIME
|
#ifdef SAY_TIME
|
||||||
@ -147,7 +171,10 @@ uint8_t spPAUSE1[] PROGMEM = {0x00,0x00,0x00,0x00,0xFF,0x0F};
|
|||||||
void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) ;
|
void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) ;
|
||||||
|
|
||||||
void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) {
|
void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) {
|
||||||
TTGO_PWR_ON
|
|
||||||
|
if (!out) return;
|
||||||
|
|
||||||
|
AUDIO_PWR_ON
|
||||||
talkie = new AudioGeneratorTalkie();
|
talkie = new AudioGeneratorTalkie();
|
||||||
talkie->begin(nullptr, out);
|
talkie->begin(nullptr, out);
|
||||||
|
|
||||||
@ -198,7 +225,7 @@ void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) {
|
|||||||
}
|
}
|
||||||
delete talkie;
|
delete talkie;
|
||||||
out->stop();
|
out->stop();
|
||||||
TTGO_PWR_OFF
|
AUDIO_PWR_OFF
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -210,11 +237,11 @@ void I2S_Init(void) {
|
|||||||
#if EXTERNAL_DAC_PLAY
|
#if EXTERNAL_DAC_PLAY
|
||||||
out = new AudioOutputI2S();
|
out = new AudioOutputI2S();
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
out->SetPinout(TWATCH_DAC_IIS_BCK, TWATCH_DAC_IIS_WS, TWATCH_DAC_IIS_DOUT);
|
out->SetPinout(DAC_IIS_BCK, DAC_IIS_WS, DAC_IIS_DOUT);
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
#else
|
#else
|
||||||
out = new AudioOutputI2S(0, 1);
|
out = new AudioOutputI2S(0, 1);
|
||||||
#endif
|
#endif // EXTERNAL_DAC_PLAY
|
||||||
|
|
||||||
is2_volume=10;
|
is2_volume=10;
|
||||||
out->SetGain(((float)is2_volume/100.0)*4.0);
|
out->SetGain(((float)is2_volume/100.0)*4.0);
|
||||||
@ -241,6 +268,163 @@ void I2S_Init(void) {
|
|||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#define MODE_MIC 0
|
||||||
|
#define MODE_SPK 1
|
||||||
|
#define Speak_I2S_NUMBER I2S_NUM_0
|
||||||
|
//#define MICSRATE 44100
|
||||||
|
#define MICSRATE 16000
|
||||||
|
|
||||||
|
#include <driver/i2s.h>
|
||||||
|
|
||||||
|
uint32_t SpeakerMic(uint8_t spkr) {
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
if (out) {
|
||||||
|
out->stop();
|
||||||
|
delete out;
|
||||||
|
out = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2s_driver_uninstall(Speak_I2S_NUMBER);
|
||||||
|
if (spkr==MODE_SPK) {
|
||||||
|
out = new AudioOutputI2S();
|
||||||
|
out->SetPinout(DAC_IIS_BCK, DAC_IIS_WS, DAC_IIS_DOUT);
|
||||||
|
out->SetGain(((float)is2_volume/100.0)*4.0);
|
||||||
|
out->stop();
|
||||||
|
} else {
|
||||||
|
// config mic
|
||||||
|
i2s_config_t i2s_config = {
|
||||||
|
.mode = (i2s_mode_t)(I2S_MODE_MASTER),
|
||||||
|
.sample_rate = MICSRATE,
|
||||||
|
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||||
|
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
|
||||||
|
.communication_format = I2S_COMM_FORMAT_I2S,
|
||||||
|
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||||
|
.dma_buf_count = 2,
|
||||||
|
//.dma_buf_len = 128,
|
||||||
|
.dma_buf_len = 1024,
|
||||||
|
};
|
||||||
|
i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM);
|
||||||
|
err += i2s_driver_install(Speak_I2S_NUMBER, &i2s_config, 0, NULL);
|
||||||
|
|
||||||
|
i2s_pin_config_t tx_pin_config;
|
||||||
|
tx_pin_config.bck_io_num = DAC_IIS_BCK;
|
||||||
|
tx_pin_config.ws_io_num = DAC_IIS_WS;
|
||||||
|
tx_pin_config.data_out_num = DAC_IIS_DOUT;
|
||||||
|
tx_pin_config.data_in_num = DAC_IIS_DIN;
|
||||||
|
err += i2s_set_pin(Speak_I2S_NUMBER, &tx_pin_config);
|
||||||
|
|
||||||
|
err += i2s_set_clk(Speak_I2S_NUMBER, MICSRATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DATA_SIZE 1024
|
||||||
|
|
||||||
|
TaskHandle_t mic_task_h;
|
||||||
|
uint32_t mic_size;
|
||||||
|
uint8_t *mic_buff;
|
||||||
|
char mic_path[32];
|
||||||
|
|
||||||
|
void mic_task(void *arg){
|
||||||
|
uint32_t data_offset = 0;
|
||||||
|
while (1) {
|
||||||
|
uint32_t bytes_read;
|
||||||
|
i2s_read(Speak_I2S_NUMBER, (char *)(mic_buff + data_offset), DATA_SIZE, &bytes_read, (100 / portTICK_RATE_MS));
|
||||||
|
if (bytes_read != DATA_SIZE) break;
|
||||||
|
data_offset += DATA_SIZE;
|
||||||
|
if (data_offset >= mic_size-DATA_SIZE) break;
|
||||||
|
}
|
||||||
|
SpeakerMic(MODE_SPK);
|
||||||
|
SaveWav(mic_path, mic_buff, mic_size);
|
||||||
|
free(mic_buff);
|
||||||
|
vTaskDelete(mic_task_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i2s_record(char *path, uint32_t secs) {
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
if (decoder || mp3) return 0;
|
||||||
|
|
||||||
|
err = SpeakerMic(MODE_MIC);
|
||||||
|
if (err) {
|
||||||
|
SpeakerMic(MODE_SPK);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mic_size = secs * MICSRATE * 2;
|
||||||
|
|
||||||
|
mic_buff = (uint8_t*)heap_caps_malloc(mic_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
|
if (!mic_buff) return 2;
|
||||||
|
|
||||||
|
if (*path=='+') {
|
||||||
|
path++;
|
||||||
|
strlcpy(mic_path, path , sizeof(mic_path));
|
||||||
|
xTaskCreatePinnedToCore(mic_task, "MIC", 4096, NULL, 3, &mic_task_h, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t data_offset = 0;
|
||||||
|
uint32_t stime=millis();
|
||||||
|
while (1) {
|
||||||
|
uint32_t bytes_read;
|
||||||
|
i2s_read(Speak_I2S_NUMBER, (char *)(mic_buff + data_offset), DATA_SIZE, &bytes_read, (100 / portTICK_RATE_MS));
|
||||||
|
if (bytes_read != DATA_SIZE) break;
|
||||||
|
data_offset += DATA_SIZE;
|
||||||
|
if (data_offset >= mic_size-DATA_SIZE) break;
|
||||||
|
delay(0);
|
||||||
|
}
|
||||||
|
//AddLog_P(LOG_LEVEL_INFO, PSTR("rectime: %d ms"), millis()-stime);
|
||||||
|
SpeakerMic(MODE_SPK);
|
||||||
|
// save to path
|
||||||
|
SaveWav(mic_path, mic_buff, mic_size);
|
||||||
|
free(mic_buff);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t wavHTemplate[] PROGMEM = { // Hardcoded simple WAV header with 0xffffffff lengths all around
|
||||||
|
0x52, 0x49, 0x46, 0x46, 0xff, 0xff, 0xff, 0xff, 0x57, 0x41, 0x56, 0x45,
|
||||||
|
0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x22, 0x56, 0x00, 0x00, 0x88, 0x58, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00,
|
||||||
|
0x64, 0x61, 0x74, 0x61, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
|
bool SaveWav(char *path, uint8_t *buff, uint32_t size) {
|
||||||
|
File fwp = fsp->open(path, FILE_WRITE);
|
||||||
|
uint8_t wavHeader[sizeof(wavHTemplate)];
|
||||||
|
memcpy_P(wavHeader, wavHTemplate, sizeof(wavHTemplate));
|
||||||
|
|
||||||
|
uint8_t channels = 1;
|
||||||
|
uint32_t hertz = MICSRATE;
|
||||||
|
uint8_t bps = 16;
|
||||||
|
|
||||||
|
wavHeader[22] = channels & 0xff;
|
||||||
|
wavHeader[23] = 0;
|
||||||
|
wavHeader[24] = hertz & 0xff;
|
||||||
|
wavHeader[25] = (hertz >> 8) & 0xff;
|
||||||
|
wavHeader[26] = (hertz >> 16) & 0xff;
|
||||||
|
wavHeader[27] = (hertz >> 24) & 0xff;
|
||||||
|
int byteRate = hertz * bps * channels / 8;
|
||||||
|
wavHeader[28] = byteRate & 0xff;
|
||||||
|
wavHeader[29] = (byteRate >> 8) & 0xff;
|
||||||
|
wavHeader[30] = (byteRate >> 16) & 0xff;
|
||||||
|
wavHeader[31] = (byteRate >> 24) & 0xff;
|
||||||
|
wavHeader[32] = channels * bps / 8;
|
||||||
|
wavHeader[33] = 0;
|
||||||
|
wavHeader[34] = bps;
|
||||||
|
wavHeader[35] = 0;
|
||||||
|
|
||||||
|
fwp.write(wavHeader, sizeof(wavHeader));
|
||||||
|
|
||||||
|
fwp.write(buff, size);
|
||||||
|
fwp.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ESP32
|
||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
TaskHandle_t mp3_task_h;
|
TaskHandle_t mp3_task_h;
|
||||||
|
|
||||||
@ -286,7 +470,8 @@ void StatusCallback(void *cbData, int code, const char *string) {
|
|||||||
|
|
||||||
void Webradio(const char *url) {
|
void Webradio(const char *url) {
|
||||||
if (decoder || mp3) return;
|
if (decoder || mp3) return;
|
||||||
TTGO_PWR_ON
|
if (!out) return;
|
||||||
|
AUDIO_PWR_ON
|
||||||
ifile = new AudioFileSourceICYStream(url);
|
ifile = new AudioFileSourceICYStream(url);
|
||||||
ifile->RegisterMetadataCB(MDCallback, NULL);
|
ifile->RegisterMetadataCB(MDCallback, NULL);
|
||||||
buff = new AudioFileSourceBuffer(ifile, preallocateBuffer, preallocateBufferSize);
|
buff = new AudioFileSourceBuffer(ifile, preallocateBuffer, preallocateBufferSize);
|
||||||
@ -338,7 +523,7 @@ void StopPlaying() {
|
|||||||
delete ifile;
|
delete ifile;
|
||||||
ifile = NULL;
|
ifile = NULL;
|
||||||
}
|
}
|
||||||
TTGO_PWR_OFF
|
AUDIO_PWR_OFF
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cmd_WebRadio(void) {
|
void Cmd_WebRadio(void) {
|
||||||
@ -369,10 +554,11 @@ void I2S_WR_Show(void) {
|
|||||||
void Play_mp3(const char *path) {
|
void Play_mp3(const char *path) {
|
||||||
#if defined(USE_SCRIPT) && defined(USE_SCRIPT_FATFS)
|
#if defined(USE_SCRIPT) && defined(USE_SCRIPT_FATFS)
|
||||||
if (decoder || mp3) return;
|
if (decoder || mp3) return;
|
||||||
|
if (!out) return;
|
||||||
|
|
||||||
bool I2S_Task;
|
bool I2S_Task;
|
||||||
|
|
||||||
TTGO_PWR_ON
|
AUDIO_PWR_ON
|
||||||
if (*path=='+') {
|
if (*path=='+') {
|
||||||
I2S_Task = true;
|
I2S_Task = true;
|
||||||
path++;
|
path++;
|
||||||
@ -411,13 +597,15 @@ void mp3_delete(void) {
|
|||||||
delete id3;
|
delete id3;
|
||||||
delete mp3;
|
delete mp3;
|
||||||
mp3=nullptr;
|
mp3=nullptr;
|
||||||
TTGO_PWR_OFF
|
AUDIO_PWR_OFF
|
||||||
}
|
}
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
|
|
||||||
void Say(char *text) {
|
void Say(char *text) {
|
||||||
|
|
||||||
TTGO_PWR_ON
|
if (!out) return;
|
||||||
|
|
||||||
|
AUDIO_PWR_ON
|
||||||
|
|
||||||
out->begin();
|
out->begin();
|
||||||
ESP8266SAM *sam = new ESP8266SAM;
|
ESP8266SAM *sam = new ESP8266SAM;
|
||||||
@ -425,7 +613,7 @@ void Say(char *text) {
|
|||||||
delete sam;
|
delete sam;
|
||||||
out->stop();
|
out->stop();
|
||||||
|
|
||||||
TTGO_PWR_OFF
|
AUDIO_PWR_OFF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,14 +19,18 @@
|
|||||||
|
|
||||||
/* remaining work:
|
/* remaining work:
|
||||||
|
|
||||||
i2s microphone, at least as loudness sensor
|
i2s microphone as loudness sensor
|
||||||
rtc use after reboot, sync with internet on regular intervals.
|
rtc better sync
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#ifdef USE_M5STACK_CORE2
|
#ifdef USE_M5STACK_CORE2
|
||||||
|
|
||||||
|
#include <Esp.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <esp_system.h>
|
||||||
|
|
||||||
#include <AXP192.h>
|
#include <AXP192.h>
|
||||||
#include <MPU6886.h>
|
#include <MPU6886.h>
|
||||||
#include <BM8563_RTC.h>
|
#include <BM8563_RTC.h>
|
||||||
@ -41,9 +45,11 @@ struct CORE2_globs {
|
|||||||
BM8563_RTC Rtc;
|
BM8563_RTC Rtc;
|
||||||
bool ready;
|
bool ready;
|
||||||
bool tset;
|
bool tset;
|
||||||
uint32_t shutdownseconds;
|
int32_t shutdownseconds;
|
||||||
|
uint8_t wakeup_hour;
|
||||||
|
uint8_t wakeup_minute;
|
||||||
uint8_t shutdowndelay;
|
uint8_t shutdowndelay;
|
||||||
|
bool timesynced;
|
||||||
} core2_globs;
|
} core2_globs;
|
||||||
|
|
||||||
struct CORE2_ADC {
|
struct CORE2_ADC {
|
||||||
@ -79,6 +85,31 @@ void CORE2_Module_Init(void) {
|
|||||||
|
|
||||||
void CORE2_Init(void) {
|
void CORE2_Init(void) {
|
||||||
|
|
||||||
|
if (Rtc.utc_time < START_VALID_TIME) {
|
||||||
|
// set rtc from chip
|
||||||
|
Rtc.utc_time = Get_utc();
|
||||||
|
|
||||||
|
TIME_T tmpTime;
|
||||||
|
TasmotaGlobal.ntp_force_sync = true; //force to sync with ntp
|
||||||
|
// Rtc.utc_time = ReadFromDS3231(); //we read UTC TIME from DS3231
|
||||||
|
// from this line, we just copy the function from "void RtcSecond()" at the support.ino ,line 2143 and above
|
||||||
|
// We need it to set rules etc.
|
||||||
|
BreakTime(Rtc.utc_time, tmpTime);
|
||||||
|
if (Rtc.utc_time < START_VALID_TIME ) {
|
||||||
|
//ds3231ReadStatus = true; //if time in DS3231 is valid, do not update again
|
||||||
|
}
|
||||||
|
Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year);
|
||||||
|
Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year);
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR("Set time from BM8563 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"),
|
||||||
|
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
|
||||||
|
if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01
|
||||||
|
TasmotaGlobal.rules_flag.time_init = 1;
|
||||||
|
} else {
|
||||||
|
TasmotaGlobal.rules_flag.time_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CORE2_audio_power(bool power) {
|
void CORE2_audio_power(bool power) {
|
||||||
@ -100,6 +131,7 @@ const char HTTP_CORE2_MPU[] PROGMEM =
|
|||||||
|
|
||||||
|
|
||||||
void CORE2_loop(uint32_t flg) {
|
void CORE2_loop(uint32_t flg) {
|
||||||
|
Sync_RTOS_TIME();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CORE2_WebShow(uint32_t json) {
|
void CORE2_WebShow(uint32_t json) {
|
||||||
@ -135,24 +167,45 @@ void (* const CORE2_Command[])(void) PROGMEM = {
|
|||||||
|
|
||||||
|
|
||||||
void CORE2_Shutdown(void) {
|
void CORE2_Shutdown(void) {
|
||||||
|
char *mp = strchr(XdrvMailbox.data, ':');
|
||||||
|
if (mp) {
|
||||||
|
core2_globs.wakeup_hour = atoi(XdrvMailbox.data);
|
||||||
|
core2_globs.wakeup_minute = atoi(mp+1);
|
||||||
|
core2_globs.shutdownseconds = -1;
|
||||||
|
core2_globs.shutdowndelay = 10;
|
||||||
|
char tbuff[16];
|
||||||
|
sprintf(tbuff,"%02.2d:%02.2d", core2_globs.wakeup_hour, core2_globs.wakeup_minute );
|
||||||
|
ResponseCmndChar(tbuff);
|
||||||
|
} else {
|
||||||
if (XdrvMailbox.payload >= 30) {
|
if (XdrvMailbox.payload >= 30) {
|
||||||
core2_globs.shutdownseconds = XdrvMailbox.payload;
|
core2_globs.shutdownseconds = XdrvMailbox.payload;
|
||||||
core2_globs.shutdowndelay = 10;
|
core2_globs.shutdowndelay = 10;
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(XdrvMailbox.payload -2);
|
ResponseCmndNumber(XdrvMailbox.payload);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CORE2_DoShutdown(void) {
|
void CORE2_DoShutdown(void) {
|
||||||
SettingsSaveAll();
|
SettingsSaveAll();
|
||||||
RtcSettingsSave();
|
RtcSettingsSave();
|
||||||
core2_globs.Rtc.clearIRQ();
|
core2_globs.Rtc.clearIRQ();
|
||||||
|
if (core2_globs.shutdownseconds > 0) {
|
||||||
core2_globs.Rtc.SetAlarmIRQ(core2_globs.shutdownseconds);
|
core2_globs.Rtc.SetAlarmIRQ(core2_globs.shutdownseconds);
|
||||||
|
} else {
|
||||||
|
RTC_TimeTypeDef wut;
|
||||||
|
wut.Hours = core2_globs.wakeup_hour;
|
||||||
|
wut.Minutes = core2_globs.wakeup_minute;
|
||||||
|
core2_globs.Rtc.SetAlarmIRQ(wut);
|
||||||
|
}
|
||||||
delay(10);
|
delay(10);
|
||||||
core2_globs.Axp.PowerOff();
|
core2_globs.Axp.PowerOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern uint8_t tbstate[3];
|
extern uint8_t tbstate[3];
|
||||||
|
|
||||||
|
|
||||||
|
// c2ps(a b)
|
||||||
float core2_setaxppin(uint32_t sel, uint32_t val) {
|
float core2_setaxppin(uint32_t sel, uint32_t val) {
|
||||||
switch (sel) {
|
switch (sel) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -165,7 +218,25 @@ float core2_setaxppin(uint32_t sel, uint32_t val) {
|
|||||||
if (val<1 || val>3) val = 1;
|
if (val<1 || val>3) val = 1;
|
||||||
return tbstate[val - 1] & 1;
|
return tbstate[val - 1] & 1;
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
switch (val) {
|
||||||
|
case 0:
|
||||||
|
return core2_globs.Axp.isACIN();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return core2_globs.Axp.isCharging();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return core2_globs.Axp.isVBUS();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
return core2_globs.Axp.AXPInState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GetRtc();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -187,16 +258,107 @@ uint16_t voltage = 2200;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CORE2_EverySecond(void) {
|
/*
|
||||||
if (core2_globs.ready) {
|
void SetRtc(void) {
|
||||||
CORE2_GetADC();
|
|
||||||
|
|
||||||
if (RtcTime.year>2000 && core2_globs.tset==false) {
|
|
||||||
RTC_TimeTypeDef RTCtime;
|
RTC_TimeTypeDef RTCtime;
|
||||||
RTCtime.Hours = RtcTime.hour;
|
RTCtime.Hours = RtcTime.hour;
|
||||||
RTCtime.Minutes = RtcTime.minute;
|
RTCtime.Minutes = RtcTime.minute;
|
||||||
RTCtime.Seconds = RtcTime.second;
|
RTCtime.Seconds = RtcTime.second;
|
||||||
core2_globs.Rtc.SetTime(&RTCtime);
|
core2_globs.Rtc.SetTime(&RTCtime);
|
||||||
|
|
||||||
|
RTC_DateTypeDef RTCdate;
|
||||||
|
RTCdate.WeekDay = RtcTime.day_of_week;
|
||||||
|
RTCdate.Month = RtcTime.month;
|
||||||
|
RTCdate.Date = RtcTime.day_of_month;
|
||||||
|
RTCdate.Year = RtcTime.year;
|
||||||
|
core2_globs.Rtc.SetDate(&RTCdate);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// needed for sd card time
|
||||||
|
void Sync_RTOS_TIME(void) {
|
||||||
|
|
||||||
|
if (Rtc.local_time < START_VALID_TIME || core2_globs.timesynced) return;
|
||||||
|
|
||||||
|
core2_globs.timesynced = 1;
|
||||||
|
// Set freertos time for sd card
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
//tv.tv_sec = Rtc.utc_time;
|
||||||
|
tv.tv_sec = Rtc.local_time;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
//struct timezone tz;
|
||||||
|
//tz.tz_minuteswest = 0;
|
||||||
|
//tz.tz_dsttime = 0;
|
||||||
|
//settimeofday(&tv, &tz);
|
||||||
|
|
||||||
|
settimeofday(&tv, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetRtc(void) {
|
||||||
|
RTC_TimeTypeDef RTCtime;
|
||||||
|
core2_globs.Rtc.GetTime(&RTCtime);
|
||||||
|
RtcTime.hour = RTCtime.Hours;
|
||||||
|
RtcTime.minute = RTCtime.Minutes;
|
||||||
|
RtcTime.second = RTCtime.Seconds;
|
||||||
|
|
||||||
|
|
||||||
|
RTC_DateTypeDef RTCdate;
|
||||||
|
core2_globs.Rtc.GetDate(&RTCdate);
|
||||||
|
RtcTime.day_of_week = RTCdate.WeekDay;
|
||||||
|
RtcTime.month = RTCdate.Month;
|
||||||
|
RtcTime.day_of_month = RTCdate.Date;
|
||||||
|
RtcTime.year = RTCdate.Year;
|
||||||
|
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR("RTC: %02d:%02d:%02d"), RTCtime.Hours, RTCtime.Minutes, RTCtime.Seconds);
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR("RTC: %02d.%02d.%04d"), RTCdate.Date, RTCdate.Month, RTCdate.Year);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set_utc(uint32_t epoch_time) {
|
||||||
|
TIME_T tm;
|
||||||
|
BreakTime(epoch_time, tm);
|
||||||
|
RTC_TimeTypeDef RTCtime;
|
||||||
|
RTCtime.Hours = tm.hour;
|
||||||
|
RTCtime.Minutes = tm.minute;
|
||||||
|
RTCtime.Seconds = tm.second;
|
||||||
|
core2_globs.Rtc.SetTime(&RTCtime);
|
||||||
|
RTC_DateTypeDef RTCdate;
|
||||||
|
RTCdate.WeekDay = tm.day_of_week;
|
||||||
|
RTCdate.Month = tm.month;
|
||||||
|
RTCdate.Date = tm.day_of_month;
|
||||||
|
RTCdate.Year = tm.year + 1970;
|
||||||
|
core2_globs.Rtc.SetDate(&RTCdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Get_utc(void) {
|
||||||
|
RTC_TimeTypeDef RTCtime;
|
||||||
|
// 1. read has errors ???
|
||||||
|
core2_globs.Rtc.GetTime(&RTCtime);
|
||||||
|
core2_globs.Rtc.GetTime(&RTCtime);
|
||||||
|
RTC_DateTypeDef RTCdate;
|
||||||
|
core2_globs.Rtc.GetDate(&RTCdate);
|
||||||
|
TIME_T tm;
|
||||||
|
tm.second = RTCtime.Seconds;
|
||||||
|
tm.minute = RTCtime.Minutes;
|
||||||
|
tm.hour = RTCtime.Hours;
|
||||||
|
tm.day_of_week = RTCdate.WeekDay;
|
||||||
|
tm.day_of_month = RTCdate.Date;
|
||||||
|
tm.month = RTCdate.Month;
|
||||||
|
tm.year =RTCdate.Year - 1970;
|
||||||
|
return MakeTime(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CORE2_EverySecond(void) {
|
||||||
|
if (core2_globs.ready) {
|
||||||
|
CORE2_GetADC();
|
||||||
|
|
||||||
|
if (Rtc.utc_time > START_VALID_TIME && core2_globs.tset==false && abs(Rtc.utc_time - Get_utc()) > 3) {
|
||||||
|
Set_utc(Rtc.utc_time);
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR("Write Time TO BM8563 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"),
|
||||||
|
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
|
||||||
core2_globs.tset = true;
|
core2_globs.tset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user