mirror of https://github.com/arendst/Tasmota.git
Berry specific moved to berry_tasmota
This commit is contained in:
parent
bfdf34813f
commit
4406eb9f3b
|
@ -1,113 +0,0 @@
|
|||
/********************************************************************
|
||||
* Tasmota I2S audio classes
|
||||
*
|
||||
*
|
||||
*******************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
#ifdef USE_I2S
|
||||
#ifdef USE_I2S_AUDIO_BERRY
|
||||
|
||||
extern int i2s_output_i2s_init(bvm *vm);
|
||||
extern int i2s_output_i2s_deinit(bvm *vm);
|
||||
extern int i2s_output_i2s_stop(bvm *vm);
|
||||
|
||||
extern int i2s_generator_wav_init(bvm *vm);
|
||||
extern int i2s_generator_wav_deinit(bvm *vm);
|
||||
extern int i2s_generator_wav_begin(bvm *vm);
|
||||
extern int i2s_generator_wav_loop(bvm *vm);
|
||||
extern int i2s_generator_wav_stop(bvm *vm);
|
||||
extern int i2s_generator_wav_isrunning(bvm *vm);
|
||||
|
||||
extern int i2s_generator_mp3_init(bvm *vm);
|
||||
extern int i2s_generator_mp3_deinit(bvm *vm);
|
||||
extern int i2s_generator_mp3_begin(bvm *vm);
|
||||
extern int i2s_generator_mp3_loop(bvm *vm);
|
||||
extern int i2s_generator_mp3_stop(bvm *vm);
|
||||
extern int i2s_generator_mp3_isrunning(bvm *vm);
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
extern int i2s_file_source_fs_init(bvm *vm);
|
||||
extern int i2s_file_source_fs_deinit(bvm *vm);
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
|
||||
#include "../generate/be_fixed_be_class_audio_output.h"
|
||||
#include "../generate/be_fixed_be_class_audio_output_i2s.h"
|
||||
#include "../generate/be_fixed_be_class_audio_generator.h"
|
||||
#include "../generate/be_fixed_be_class_audio_generator_wav.h"
|
||||
#include "../generate/be_fixed_be_class_audio_generator_mp3.h"
|
||||
#include "../generate/be_fixed_be_class_audio_file_source.h"
|
||||
#include "../generate/be_fixed_be_class_audio_file_source_fs.h"
|
||||
|
||||
void be_load_driver_audio_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_audio_output);
|
||||
be_setglobal(vm, "AudioOutput");
|
||||
be_pop(vm, 1);
|
||||
|
||||
be_pushntvclass(vm, &be_class_audio_output_i2s);
|
||||
be_setglobal(vm, "AudioOutputI2S");
|
||||
be_pop(vm, 1);
|
||||
|
||||
be_pushntvclass(vm, &be_class_audio_generator_wav);
|
||||
be_setglobal(vm, "AudioGeneratorWAV");
|
||||
be_pop(vm, 1);
|
||||
|
||||
be_pushntvclass(vm, &be_class_audio_generator_mp3);
|
||||
be_setglobal(vm, "AudioGeneratorMP3");
|
||||
be_pop(vm, 1);
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
be_pushntvclass(vm, &be_class_audio_file_source_fs);
|
||||
be_setglobal(vm, "AudioFileSourceFS");
|
||||
be_pop(vm, 1);
|
||||
#endif // USE_UFILESYS
|
||||
}
|
||||
|
||||
/* @const_object_info_begin
|
||||
|
||||
class be_class_audio_output (scope: global, name: AudioOutput) {
|
||||
.p, var
|
||||
}
|
||||
|
||||
class be_class_audio_generator (scope: global, name: AudioGenerator) {
|
||||
.p, var
|
||||
}
|
||||
|
||||
class be_class_audio_file_source (scope: global, name: AudioFileSource) {
|
||||
.p, var
|
||||
}
|
||||
|
||||
class be_class_audio_output_i2s (scope: global, name: AudioOutputI2S, super: be_class_audio_output) {
|
||||
init, func(i2s_output_i2s_init)
|
||||
deinit, func(i2s_output_i2s_deinit)
|
||||
stop, func(i2s_output_i2s_stop)
|
||||
}
|
||||
|
||||
class be_class_audio_generator_wav (scope: global, name: AudioGeneratorWAV, super: be_class_audio_generator) {
|
||||
init, func(i2s_generator_wav_init)
|
||||
deinit, func(i2s_generator_wav_deinit)
|
||||
begin, func(i2s_generator_wav_begin)
|
||||
loop, func(i2s_generator_wav_loop)
|
||||
stop, func(i2s_generator_wav_stop)
|
||||
isrunning, func(i2s_generator_wav_isrunning)
|
||||
}
|
||||
|
||||
class be_class_audio_generator_mp3 (scope: global, name: AudioGeneratorMP3, super: be_class_audio_generator) {
|
||||
init, func(i2s_generator_mp3_init)
|
||||
deinit, func(i2s_generator_mp3_deinit)
|
||||
begin, func(i2s_generator_mp3_begin)
|
||||
loop, func(i2s_generator_mp3_loop)
|
||||
stop, func(i2s_generator_mp3_stop)
|
||||
isrunning, func(i2s_generator_mp3_isrunning)
|
||||
}
|
||||
|
||||
class be_class_audio_file_source_fs (scope: global, name: AudioFileSourceFS, super: be_class_audio_file_source) {
|
||||
init, func(i2s_file_source_fs_init)
|
||||
deinit, func(i2s_file_source_fs_deinit)
|
||||
}
|
||||
|
||||
@const_object_info_end */
|
||||
|
||||
#endif // USE_I2S_AUDIO_BERRY
|
||||
#endif // USE_I2S
|
|
@ -159,6 +159,7 @@ extern void be_load_ctypes_energy_definitions_lib(bvm *vm);
|
|||
|
||||
#ifdef USE_I2S_AUDIO_BERRY
|
||||
extern void be_load_driver_audio_lib(bvm *vm);
|
||||
extern void be_load_driver_audio_opus_decoder(bvm *vm);
|
||||
#endif
|
||||
|
||||
#ifdef USE_LVGL
|
||||
|
@ -214,6 +215,7 @@ BERRY_API void be_load_custom_libs(bvm *vm)
|
|||
#endif // USE_WS2812
|
||||
#ifdef USE_I2S_AUDIO_BERRY
|
||||
be_load_driver_audio_lib(vm);
|
||||
be_load_driver_audio_opus_decoder(vm);
|
||||
#endif
|
||||
#ifdef USE_LVGL
|
||||
// LVGL
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#!/bin/bash
|
||||
python3 tools/pycoc/main.py -o generate src default ../berry_mapping/src ../../libesp32_lvgl/lv_berry/src ../../libesp32_lvgl/lv_berry/generate -c default/berry_conf.h
|
||||
python3 tools/pycoc/main.py -o generate src default ../berry_tasmota/src ../berry_mapping/src ../../libesp32_lvgl/lv_berry/src ../../libesp32_lvgl/lv_berry/generate -c default/berry_conf.h
|
||||
|
|
|
@ -51,6 +51,7 @@ extern const bcstring be_const_str_MD5;
|
|||
extern const bcstring be_const_str_None;
|
||||
extern const bcstring be_const_str_OPTION_A;
|
||||
extern const bcstring be_const_str_OneWire;
|
||||
extern const bcstring be_const_str_OpusDecoder;
|
||||
extern const bcstring be_const_str_PART_MAIN;
|
||||
extern const bcstring be_const_str_POST;
|
||||
extern const bcstring be_const_str_Parameter_X20error;
|
||||
|
@ -281,6 +282,9 @@ extern const bcstring be_const_str_connect;
|
|||
extern const bcstring be_const_str_connected;
|
||||
extern const bcstring be_const_str_connection_error;
|
||||
extern const bcstring be_const_str_constructor_cb;
|
||||
extern const bcstring be_const_str_consume_mono;
|
||||
extern const bcstring be_const_str_consume_silence;
|
||||
extern const bcstring be_const_str_consume_stereo;
|
||||
extern const bcstring be_const_str_contains;
|
||||
extern const bcstring be_const_str_content_button;
|
||||
extern const bcstring be_const_str_content_flush;
|
||||
|
@ -305,6 +309,7 @@ extern const bcstring be_const_str_ctypes_bytes_dyn;
|
|||
extern const bcstring be_const_str_dac_voltage;
|
||||
extern const bcstring be_const_str_day;
|
||||
extern const bcstring be_const_str_debug;
|
||||
extern const bcstring be_const_str_decode;
|
||||
extern const bcstring be_const_str_decompress;
|
||||
extern const bcstring be_const_str_decrypt;
|
||||
extern const bcstring be_const_str_def;
|
||||
|
@ -628,11 +633,14 @@ extern const bcstring be_const_str_serial;
|
|||
extern const bcstring be_const_str_set;
|
||||
extern const bcstring be_const_str_set_alternate;
|
||||
extern const bcstring be_const_str_set_auth;
|
||||
extern const bcstring be_const_str_set_bits_per_sample;
|
||||
extern const bcstring be_const_str_set_bri;
|
||||
extern const bcstring be_const_str_set_channels;
|
||||
extern const bcstring be_const_str_set_chg_current;
|
||||
extern const bcstring be_const_str_set_dc_voltage;
|
||||
extern const bcstring be_const_str_set_dcdc_enable;
|
||||
extern const bcstring be_const_str_set_first_time;
|
||||
extern const bcstring be_const_str_set_gain;
|
||||
extern const bcstring be_const_str_set_height;
|
||||
extern const bcstring be_const_str_set_ldo_enable;
|
||||
extern const bcstring be_const_str_set_ldo_voltage;
|
||||
|
@ -641,6 +649,7 @@ extern const bcstring be_const_str_set_matrix_pixel_color;
|
|||
extern const bcstring be_const_str_set_percentage;
|
||||
extern const bcstring be_const_str_set_pixel_color;
|
||||
extern const bcstring be_const_str_set_power;
|
||||
extern const bcstring be_const_str_set_rate;
|
||||
extern const bcstring be_const_str_set_style_bg_color;
|
||||
extern const bcstring be_const_str_set_style_line_color;
|
||||
extern const bcstring be_const_str_set_style_pad_right;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,20 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(be_class_audio_opus_decoder_map) {
|
||||
{ be_const_key(deinit, -1), be_const_func(be_audio_opus_decoder_deinit) },
|
||||
{ be_const_key(decode, 2), be_const_func(be_audio_opus_decoder_decode) },
|
||||
{ be_const_key(_X2Ep, -1), be_const_var(0) },
|
||||
{ be_const_key(init, 1), be_const_func(be_audio_opus_decoder_init) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
be_class_audio_opus_decoder_map,
|
||||
4
|
||||
);
|
||||
|
||||
BE_EXPORT_VARIABLE be_define_const_class(
|
||||
be_class_audio_opus_decoder,
|
||||
1,
|
||||
NULL,
|
||||
OpusDecoder
|
||||
);
|
|
@ -1,12 +1,23 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(be_class_audio_output_map) {
|
||||
{ be_const_key(set_bits_per_sample, -1), be_const_func(be_audio_output_set_bits_per_sample) },
|
||||
{ be_const_key(flush, -1), be_const_func(be_audio_output_flush) },
|
||||
{ be_const_key(consume_stereo, -1), be_const_func(be_audio_output_consume_stereo) },
|
||||
{ be_const_key(init, -1), be_const_func(be_audio_output_init) },
|
||||
{ be_const_key(consume_mono, -1), be_const_func(be_audio_output_consume_mono) },
|
||||
{ be_const_key(stop, -1), be_const_func(be_audio_output_stop) },
|
||||
{ be_const_key(begin, -1), be_const_func(be_audio_output_begin) },
|
||||
{ be_const_key(_X2Ep, -1), be_const_var(0) },
|
||||
{ be_const_key(set_channels, -1), be_const_func(be_audio_output_set_channels) },
|
||||
{ be_const_key(consume_silence, 4), be_const_func(be_audio_output_consume_silence) },
|
||||
{ be_const_key(set_rate, 2), be_const_func(be_audio_output_set_rate) },
|
||||
{ be_const_key(set_gain, 0), be_const_func(be_audio_output_set_gain) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
be_class_audio_output_map,
|
||||
1
|
||||
12
|
||||
);
|
||||
|
||||
BE_EXPORT_VARIABLE be_define_const_class(
|
||||
|
|
|
@ -17,11 +17,13 @@
|
|||
"frameworks": "arduino",
|
||||
"platforms": "espressif32",
|
||||
"build": {
|
||||
"includeDir": "generate",
|
||||
"srcFilter": [
|
||||
"+<*.c>",
|
||||
"+<../default/*.c>",
|
||||
"+<../default/*.cpp>",
|
||||
"+<../default/*.hpp>",
|
||||
"+<../generate/*.h>",
|
||||
"+<*.cpp>",
|
||||
"+<*.h>"
|
||||
],
|
||||
|
|
|
@ -138,6 +138,7 @@ int be_find_global_or_module_member(bvm *vm, const char * name) {
|
|||
* 'i' be_int
|
||||
* 'b' be_bool
|
||||
* 's' be_str
|
||||
* '&' bytes() object, pointer to buffer returned, and size passed with an additional (size_t*) argument
|
||||
*
|
||||
* - arg_type: optionally check the types of input arguments, or throw an error
|
||||
* string of argument types, '[' indicates that the following parameters are optional
|
||||
|
@ -145,8 +146,10 @@ int be_find_global_or_module_member(bvm *vm, const char * name) {
|
|||
* 'i' be_int
|
||||
* 'b' be_bool
|
||||
* 's' be_string
|
||||
* 'f' be_real (float)
|
||||
* 'c' C callback
|
||||
* '-' ignore and don't send to C function
|
||||
* '-': skip argument and ignore
|
||||
* '~': send the length of the previous bytes() buffer (or raise an exception if no length known)
|
||||
* 'lv_obj' be_instance of type or subtype
|
||||
* '^lv_event_cb' callback of a named class - will call `_lvgl.gen_cb(arg_type, closure, self)` and expects a callback address in return
|
||||
*
|
||||
|
@ -276,12 +279,15 @@ intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, int *buf
|
|||
// - '.': any argument (no check)
|
||||
// - '-': skip argument and ignore
|
||||
// - '~': send the length of the previous bytes() buffer (or raise an exception if no length known)
|
||||
// - if return type is '&' (bytes), an implicit additional parameter is passed as (size_t*) to return the length in bytes
|
||||
//
|
||||
// - a class name surroungded by parenthesis
|
||||
// - '(lv_button)' -> lv_button class or derived
|
||||
// - '[lv_event_cb]' -> callback type, still prefixed with '^' to mark that it is cb
|
||||
//
|
||||
void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, intptr_t p[8]) {
|
||||
// Returns the number of parameters sent to the function
|
||||
//
|
||||
int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, intptr_t p[8]) {
|
||||
bbool arg_type_check = (arg_type != NULL); // is type checking activated
|
||||
int32_t arg_idx = 0; // position in arg_type string
|
||||
bbool arg_optional = bfalse; // are remaining types optional?
|
||||
|
@ -289,14 +295,17 @@ void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type,
|
|||
|
||||
uint32_t p_idx = 0; // index in p[], is incremented with each parameter except '-'
|
||||
int32_t buf_len = -1; // stores the length of a bytes() buffer to be used as '~' attribute
|
||||
|
||||
// special case when no parameters are passed but all are optional
|
||||
if (NULL != arg_type && arg_type[arg_idx] == '[') {
|
||||
arg_optional = btrue;
|
||||
arg_idx++;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < argc; i++) {
|
||||
type_short_name[0] = 0; // clear string
|
||||
// extract individual type
|
||||
if (NULL != arg_type) {
|
||||
if (arg_type[arg_idx] == '[' || arg_type[arg_idx] == ']') { // '[' is a marker that following parameters are optional and default to NULL
|
||||
arg_optional = btrue;
|
||||
arg_idx++;
|
||||
}
|
||||
switch (arg_type[arg_idx]) {
|
||||
case '-':
|
||||
arg_idx++;
|
||||
|
@ -333,6 +342,10 @@ void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type,
|
|||
arg_type = NULL; // stop iterations
|
||||
break;
|
||||
}
|
||||
if (arg_type[arg_idx] == '[' || arg_type[arg_idx] == ']') { // '[' is a marker that following parameters are optional and default to NULL
|
||||
arg_optional = btrue;
|
||||
arg_idx++;
|
||||
}
|
||||
}
|
||||
// AddLog(LOG_LEVEL_INFO, ">> be_call_c_func arg %i, type %s", i, arg_type_check ? type_short_name : "<null>");
|
||||
p[p_idx] = be_convert_single_elt(vm, i + arg_start, arg_type_check ? type_short_name : NULL, &buf_len);
|
||||
|
@ -353,6 +366,7 @@ void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type,
|
|||
if (!arg_optional && arg_type != NULL && arg_type[arg_idx] != 0) {
|
||||
be_raisef(vm, "value_error", "Missing arguments, remaining type '%s'", &arg_type[arg_idx]);
|
||||
}
|
||||
return p_idx;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -420,8 +434,12 @@ int be_call_c_func(bvm *vm, void * func, const char * return_type, const char *
|
|||
}
|
||||
}
|
||||
|
||||
fn_any_callable f = (fn_any_callable) func;
|
||||
be_check_arg_type(vm, arg_start, arg_count, arg_type, p);
|
||||
fn_any_callable f = (fn_any_callable) func; // when returning a bytes buffer, this holds the length of the buffer, while the return value of the function is `void*`
|
||||
size_t return_len = 0;
|
||||
int c_args = be_check_arg_type(vm, arg_start, arg_count, arg_type, p);
|
||||
if (return_type != NULL && return_type[0] == '&') {
|
||||
if (c_args < 8) { p[c_args] = (intptr_t) &return_len; }
|
||||
}
|
||||
intptr_t ret = 0;
|
||||
if (f) ret = (*f)(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
|
||||
// berry_log_C("be_call_c_func '%s' -> '%s': (%i,%i,%i,%i,%i,%i) -> %i", return_type, arg_type, p[0], p[1], p[2], p[3], p[4], p[5], ret);
|
||||
|
@ -438,7 +456,7 @@ int be_call_c_func(bvm *vm, void * func, const char * return_type, const char *
|
|||
case 'i': be_pushint(vm, ret); break;
|
||||
case 'b': be_pushbool(vm, ret); break;
|
||||
case 's': be_pushstring(vm, (const char*) ret); break;
|
||||
case 'c': be_pushint(vm, ret); break; // TODO missing 'c' general callback type
|
||||
case '&': be_pushbytes(vm, (void*) ret, return_len); break;
|
||||
default: be_raise(vm, "internal_error", "Unsupported return type"); break;
|
||||
}
|
||||
be_return(vm);
|
||||
|
|
|
@ -57,7 +57,7 @@ extern int be_find_global_or_module_member(bvm *vm, const char * cl_name);
|
|||
|
||||
extern bbool be_const_member(bvm *vm, const be_const_member_t * definitions, size_t def_len);
|
||||
extern intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, int *len);
|
||||
extern void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, intptr_t p[8]);;
|
||||
extern int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, intptr_t p[8]);
|
||||
extern int be_call_c_func(bvm *vm, void * func, const char * return_type, const char * arg_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "Berry Tasmota mapping",
|
||||
"version": "1.0",
|
||||
"description": "Mapping of Tasmota features to Berry",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/arendst/Tasmota",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32",
|
||||
"authors":
|
||||
{
|
||||
"name": "Stephan Hadinger",
|
||||
"maintainer": true
|
||||
},
|
||||
"build": {
|
||||
"flags": [ "-I$PROJECT_DIR/include", "-includetasmota_options.h" ]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/********************************************************************
|
||||
* Tasmota I2S audio classes
|
||||
*
|
||||
*
|
||||
*******************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
#ifdef USE_I2S
|
||||
#ifdef USE_I2S_AUDIO_BERRY
|
||||
|
||||
#include "libopus/opus.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
// Tasmota Logging
|
||||
extern void tasmota_log_C(uint32_t loglevel, const char * berry_buf, ...);
|
||||
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||
|
||||
// init(freq:int, channels:int)
|
||||
void *be_audio_opus_decoder_init_ntv(int freq, int channels) {
|
||||
if (freq <= 0) { freq = 16000; }
|
||||
if (channels <= 0) { channels = 1; }
|
||||
int opus_size = opus_decoder_get_size(channels); // get size for n channel
|
||||
tasmota_log_C(LOG_LEVEL_DEBUG, "AUD: allocated %i bytes for Opus decoder", opus_size);
|
||||
void * buf = BE_EXPLICIT_MALLOC(opus_size);
|
||||
if (!buf) { berry_log_C("OPUS: out of memory"); }
|
||||
|
||||
int err = opus_decoder_init((OpusDecoder*)buf, freq, channels);
|
||||
if (err) { berry_log_C("OPUS: opus_encoder_init error=%i", err); }
|
||||
|
||||
return buf;
|
||||
}
|
||||
int32_t be_audio_opus_decoder_init(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_opus_decoder_init_ntv, "+.p", "i[i]");
|
||||
}
|
||||
|
||||
// deinit()
|
||||
void *be_audio_opus_decoder_deinit_ntv(OpusDecoder* buf) {
|
||||
if (buf) BE_EXPLICIT_FREE(buf);
|
||||
return NULL;
|
||||
}
|
||||
int32_t be_audio_opus_decoder_deinit(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_opus_decoder_deinit_ntv, "", ".");
|
||||
}
|
||||
|
||||
|
||||
// decode(payload:bytes) -> pcm:bytes()
|
||||
int32_t be_audio_opus_decoder_decode(struct bvm *vm) {
|
||||
int32_t argc = be_top(vm);
|
||||
be_call_c_func(vm, NULL, NULL, ".(bytes)");
|
||||
|
||||
OpusDecoder* st = (OpusDecoder*) be_convert_single_elt(vm, 1, NULL, NULL); // get value of '.p'
|
||||
size_t frames_len;
|
||||
const uint8_t * opus_frame = be_tobytes(vm, 2, &frames_len);
|
||||
|
||||
int samples = opus_decoder_get_nb_samples(st, opus_frame, frames_len);
|
||||
// tasmota_log_C(LOG_LEVEL_DEBUG, "AUD: frame contains %i samples", samples);
|
||||
|
||||
// allocate a buffer for the content
|
||||
void * pcm = be_pushbytes(vm, NULL, samples * 2);
|
||||
|
||||
int ret = opus_decode(st, opus_frame, frames_len, pcm, samples, 0);
|
||||
if (ret != samples) { be_raisef(vm, "internal_error", "wrong number of frames %i (supposed to be %i", ret, samples); }
|
||||
|
||||
be_return(vm);
|
||||
}
|
||||
|
||||
#include "be_fixed_be_class_audio_opus_decoder.h"
|
||||
|
||||
void be_load_driver_audio_opus_decoder(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_audio_opus_decoder);
|
||||
be_setglobal(vm, "OpusDecoder");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
/* @const_object_info_begin
|
||||
|
||||
class be_class_audio_opus_decoder (scope: global, name: OpusDecoder) {
|
||||
.p, var
|
||||
init, func(be_audio_opus_decoder_init)
|
||||
deinit, func(be_audio_opus_decoder_deinit)
|
||||
|
||||
decode, func(be_audio_opus_decoder_decode)
|
||||
}
|
||||
|
||||
@const_object_info_end */
|
||||
|
||||
#endif // USE_I2S_AUDIO_BERRY
|
||||
#endif // USE_I2S
|
|
@ -17,8 +17,8 @@ extern int m_aes_gcm_tag(bvm *vm);
|
|||
extern int m_ec_c25519_pubkey(bvm *vm);
|
||||
extern int m_ec_c25519_sharedkey(bvm *vm);
|
||||
|
||||
#include "../generate/be_fixed_be_class_aes_gcm.h"
|
||||
#include "../generate/be_fixed_be_class_ec_c25519.h"
|
||||
#include "be_fixed_be_class_aes_gcm.h"
|
||||
#include "be_fixed_be_class_ec_c25519.h"
|
||||
|
||||
void be_load_crypto_lib(bvm *vm) {
|
||||
// insert the class GCM in module AES
|
|
@ -462,8 +462,8 @@ int be_ctypes_dyn_init(bvm *vm) {
|
|||
|
||||
BE_EXPORT_VARIABLE extern const bclass be_class_bytes;
|
||||
|
||||
#include "../generate/be_fixed_be_class_ctypes.h"
|
||||
#include "../generate/be_fixed_be_class_ctypes_dyn.h"
|
||||
#include "be_fixed_be_class_ctypes.h"
|
||||
#include "be_fixed_be_class_ctypes_dyn.h"
|
||||
|
||||
void be_load_ctypes_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_ctypes);
|
|
@ -18,4 +18,4 @@ module flash (scope: global) {
|
|||
erase, func(p_flash_erase)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_flash.h"
|
||||
#include "be_fixed_flash.h"
|
|
@ -31,4 +31,4 @@ module gpio (scope: global) {
|
|||
pin, func(gp_pin)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_gpio.h"
|
||||
#include "be_fixed_gpio.h"
|
|
@ -0,0 +1,245 @@
|
|||
/********************************************************************
|
||||
* Tasmota I2S audio classes
|
||||
*
|
||||
*
|
||||
*******************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
#ifdef USE_I2S
|
||||
#ifdef USE_I2S_AUDIO_BERRY
|
||||
|
||||
#include "be_mapping.h"
|
||||
#include "AudioOutput.h"
|
||||
|
||||
extern "C" void berry_log_C(const char * berry_buf, ...);
|
||||
|
||||
extern "C" {
|
||||
extern int i2s_output_i2s_init(bvm *vm);
|
||||
extern int i2s_output_i2s_deinit(bvm *vm);
|
||||
extern int i2s_output_i2s_stop(bvm *vm);
|
||||
|
||||
extern int i2s_generator_wav_init(bvm *vm);
|
||||
extern int i2s_generator_wav_deinit(bvm *vm);
|
||||
extern int i2s_generator_wav_begin(bvm *vm);
|
||||
extern int i2s_generator_wav_loop(bvm *vm);
|
||||
extern int i2s_generator_wav_stop(bvm *vm);
|
||||
extern int i2s_generator_wav_isrunning(bvm *vm);
|
||||
|
||||
extern int i2s_generator_mp3_init(bvm *vm);
|
||||
extern int i2s_generator_mp3_deinit(bvm *vm);
|
||||
extern int i2s_generator_mp3_begin(bvm *vm);
|
||||
extern int i2s_generator_mp3_loop(bvm *vm);
|
||||
extern int i2s_generator_mp3_stop(bvm *vm);
|
||||
extern int i2s_generator_mp3_isrunning(bvm *vm);
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
extern int i2s_file_source_fs_init(bvm *vm);
|
||||
extern int i2s_file_source_fs_deinit(bvm *vm);
|
||||
#endif // USE_UFILESYS
|
||||
}
|
||||
|
||||
// AudioOutput.set_rate(rate_hz:int) -> bool
|
||||
AudioOutput* be_audio_output_init_ntv(void) {
|
||||
return new AudioOutput();
|
||||
}
|
||||
int32_t be_audio_output_init(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_init_ntv, "+.p", "");
|
||||
}
|
||||
|
||||
// AudioOutput.set_rate(rate_hz:int) -> bool
|
||||
int be_audio_output_set_rate_ntv(AudioOutput* out, int hz) {
|
||||
return out->SetRate(hz);
|
||||
}
|
||||
int32_t be_audio_output_set_rate(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_set_rate_ntv, "b", ".i");
|
||||
}
|
||||
|
||||
// AudioOutput.set_bits_per_sample(bits_per_sample:int) -> bool
|
||||
int be_audio_output_set_bits_per_sample_ntv(AudioOutput* out, int bps) {
|
||||
return out->SetBitsPerSample(bps);
|
||||
}
|
||||
int32_t be_audio_output_set_bits_per_sample(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_set_bits_per_sample_ntv, "b", ".i");
|
||||
}
|
||||
|
||||
// AudioOutput.set_channels(channels:int) -> bool
|
||||
int be_audio_output_set_channels_ntv(AudioOutput* out, int channels) {
|
||||
return out->SetChannels(channels);
|
||||
}
|
||||
int32_t be_audio_output_set_channels(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_set_channels_ntv, "b", ".i");
|
||||
}
|
||||
|
||||
// AudioOutput.set_gain(gain:real) -> bool
|
||||
int be_audio_output_set_gain_ntv(AudioOutput* out, float gain) {
|
||||
return out->SetGain(gain);
|
||||
}
|
||||
int32_t be_audio_output_set_gain(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_set_gain_ntv, "b", ".f");
|
||||
}
|
||||
|
||||
// AudioOutput.begin() -> bool
|
||||
int be_audio_output_begin_ntv(AudioOutput* out) {
|
||||
return out->begin();
|
||||
}
|
||||
int32_t be_audio_output_begin(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_begin_ntv, "b", ".");
|
||||
}
|
||||
// AudioOutput.stop() -> bool
|
||||
int be_audio_output_stop_ntv(AudioOutput* out) {
|
||||
return out->stop();
|
||||
}
|
||||
int32_t be_audio_output_stop(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_stop_ntv, "b", ".");
|
||||
}
|
||||
// AudioOutput.flush() -> bool
|
||||
void be_audio_output_flush_ntv(AudioOutput* out) {
|
||||
out->flush();
|
||||
}
|
||||
int32_t be_audio_output_flush(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_flush_ntv, "", ".");
|
||||
}
|
||||
|
||||
// AudioOutput.consume_mono(bytes) -> int
|
||||
int be_audio_output_consume_mono_ntv(AudioOutput* out, uint16_t *pcm, int bytes_len, int index) {
|
||||
int pcm_len = bytes_len / 2;
|
||||
int n;
|
||||
// berry_log_C("be_audio_output_consume_mono_ntv out=%p pcm=%p bytes_len=%i index=%i", out, pcm, bytes_len, index);
|
||||
for (n = 0; index + n < pcm_len; n++) {
|
||||
int16_t ms[2];
|
||||
ms[AudioOutput::LEFTCHANNEL] = ms[AudioOutput::RIGHTCHANNEL] = pcm[index + n];
|
||||
if (!out->ConsumeSample(ms)) { break; }
|
||||
}
|
||||
return n;
|
||||
}
|
||||
int32_t be_audio_output_consume_mono(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_consume_mono_ntv, "i", ".(bytes)~i");
|
||||
}
|
||||
|
||||
// AudioOutput.consume_stereo(bytes) -> int
|
||||
int be_audio_output_consume_stereo_ntv(AudioOutput* out, uint16_t *pcm, int bytes_len, int index) {
|
||||
int pcm_len = bytes_len / 4; // 2 samples LEFT+RIGHT of 2 bytes each
|
||||
int n;
|
||||
// berry_log_C("be_audio_output_consume_stereo_ntv out=%p pcm=%p bytes_len=%i index=%i", out, pcm, bytes_len, index);
|
||||
for (n = 0; index + n < pcm_len; n++) {
|
||||
int16_t ms[2];
|
||||
ms[AudioOutput::LEFTCHANNEL] = pcm[index + n + n];
|
||||
ms[AudioOutput::RIGHTCHANNEL] = pcm[index + n + n + 1];
|
||||
if (!out->ConsumeSample(ms)) { break; }
|
||||
}
|
||||
return n;
|
||||
}
|
||||
int32_t be_audio_output_consume_stereo(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_consume_stereo_ntv, "i", ".(bytes)~i");
|
||||
}
|
||||
|
||||
// AudioOutput.consume_silence() -> int, push silence frames
|
||||
int be_audio_output_consume_silence_ntv(AudioOutput* out) {
|
||||
int n = 0;
|
||||
int16_t ms[2] = {0, 0};
|
||||
while (true) {
|
||||
if (!out->ConsumeSample(ms)) { break; }
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
int32_t be_audio_output_consume_silence(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_audio_output_consume_silence_ntv, "i", ".");
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "be_fixed_be_class_audio_output.h"
|
||||
#include "be_fixed_be_class_audio_output_i2s.h"
|
||||
#include "be_fixed_be_class_audio_generator.h"
|
||||
#include "be_fixed_be_class_audio_generator_wav.h"
|
||||
#include "be_fixed_be_class_audio_generator_mp3.h"
|
||||
#include "be_fixed_be_class_audio_file_source.h"
|
||||
#include "be_fixed_be_class_audio_file_source_fs.h"
|
||||
|
||||
void be_load_driver_audio_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_audio_output);
|
||||
be_setglobal(vm, "AudioOutput");
|
||||
be_pop(vm, 1);
|
||||
|
||||
be_pushntvclass(vm, &be_class_audio_output_i2s);
|
||||
be_setglobal(vm, "AudioOutputI2S");
|
||||
be_pop(vm, 1);
|
||||
|
||||
be_pushntvclass(vm, &be_class_audio_generator_wav);
|
||||
be_setglobal(vm, "AudioGeneratorWAV");
|
||||
be_pop(vm, 1);
|
||||
|
||||
be_pushntvclass(vm, &be_class_audio_generator_mp3);
|
||||
be_setglobal(vm, "AudioGeneratorMP3");
|
||||
be_pop(vm, 1);
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
be_pushntvclass(vm, &be_class_audio_file_source_fs);
|
||||
be_setglobal(vm, "AudioFileSourceFS");
|
||||
be_pop(vm, 1);
|
||||
#endif // USE_UFILESYS
|
||||
}
|
||||
}
|
||||
|
||||
/* @const_object_info_begin
|
||||
|
||||
class be_class_audio_output (scope: global, name: AudioOutput) {
|
||||
.p, var
|
||||
init, func(be_audio_output_init)
|
||||
|
||||
begin, func(be_audio_output_begin)
|
||||
stop, func(be_audio_output_stop)
|
||||
flush, func(be_audio_output_flush)
|
||||
|
||||
consume_mono, func(be_audio_output_consume_mono)
|
||||
consume_stereo, func(be_audio_output_consume_stereo)
|
||||
consume_silence, func(be_audio_output_consume_silence)
|
||||
|
||||
set_rate, func(be_audio_output_set_rate)
|
||||
set_bits_per_sample, func(be_audio_output_set_bits_per_sample)
|
||||
set_channels, func(be_audio_output_set_channels)
|
||||
set_gain, func(be_audio_output_set_gain)
|
||||
}
|
||||
|
||||
class be_class_audio_generator (scope: global, name: AudioGenerator) {
|
||||
.p, var
|
||||
}
|
||||
|
||||
class be_class_audio_file_source (scope: global, name: AudioFileSource) {
|
||||
.p, var
|
||||
}
|
||||
|
||||
class be_class_audio_output_i2s (scope: global, name: AudioOutputI2S, super: be_class_audio_output) {
|
||||
init, func(i2s_output_i2s_init)
|
||||
deinit, func(i2s_output_i2s_deinit)
|
||||
stop, func(i2s_output_i2s_stop)
|
||||
}
|
||||
|
||||
class be_class_audio_generator_wav (scope: global, name: AudioGeneratorWAV, super: be_class_audio_generator) {
|
||||
init, func(i2s_generator_wav_init)
|
||||
deinit, func(i2s_generator_wav_deinit)
|
||||
begin, func(i2s_generator_wav_begin)
|
||||
loop, func(i2s_generator_wav_loop)
|
||||
stop, func(i2s_generator_wav_stop)
|
||||
isrunning, func(i2s_generator_wav_isrunning)
|
||||
}
|
||||
|
||||
class be_class_audio_generator_mp3 (scope: global, name: AudioGeneratorMP3, super: be_class_audio_generator) {
|
||||
init, func(i2s_generator_mp3_init)
|
||||
deinit, func(i2s_generator_mp3_deinit)
|
||||
begin, func(i2s_generator_mp3_begin)
|
||||
loop, func(i2s_generator_mp3_loop)
|
||||
stop, func(i2s_generator_mp3_stop)
|
||||
isrunning, func(i2s_generator_mp3_isrunning)
|
||||
}
|
||||
|
||||
class be_class_audio_file_source_fs (scope: global, name: AudioFileSourceFS, super: be_class_audio_file_source) {
|
||||
init, func(i2s_file_source_fs_init)
|
||||
deinit, func(i2s_file_source_fs_deinit)
|
||||
}
|
||||
|
||||
@const_object_info_end */
|
||||
|
||||
#endif // USE_I2S_AUDIO_BERRY
|
||||
#endif // USE_I2S
|
|
@ -23,6 +23,6 @@ module light (scope: global) {
|
|||
reverse_gamma10, func(l_rev_gamma10)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_light.h"
|
||||
#include "be_fixed_light.h"
|
||||
|
||||
#endif // USE_LIGHT
|
|
@ -111,6 +111,6 @@ module lv_tasmota (scope: global) {
|
|||
load_freetype_font, func(lv0_load_freetype_font)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_lv_tasmota.h"
|
||||
#include "be_fixed_lv_tasmota.h"
|
||||
|
||||
#endif // USE_LVGL
|
|
@ -81,7 +81,7 @@ int32_t m_md5_finish(struct bvm *vm) {
|
|||
be_return(vm);
|
||||
}
|
||||
|
||||
#include "../generate/be_fixed_be_class_md5.h"
|
||||
#include "be_fixed_be_class_md5.h"
|
||||
|
||||
void be_load_md5_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_md5);
|
|
@ -0,0 +1,2 @@
|
|||
// TODO
|
||||
|
|
@ -24,7 +24,7 @@ extern int b_onewire_reset_search(bvm *vm);
|
|||
extern int b_onewire_target_search(bvm *vm);
|
||||
extern int b_onewire_search(bvm *vm);
|
||||
|
||||
#include "../generate/be_fixed_be_class_tasmota_onewire.h"
|
||||
#include "be_fixed_be_class_tasmota_onewire.h"
|
||||
|
||||
void be_load_onewirelib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_tasmota_onewire);
|
|
@ -67,4 +67,4 @@ module path (scope: global, file: tasmota_path) {
|
|||
remove, func(m_path_remove)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_tasmota_path.h"
|
||||
#include "be_fixed_tasmota_path.h"
|
|
@ -17,7 +17,7 @@ extern int b_serial_read(bvm *vm);
|
|||
extern int b_serial_available(bvm *vm);
|
||||
extern int b_serial_flush(bvm *vm);
|
||||
|
||||
#include "../generate/be_fixed_be_class_tasmota_serial.h"
|
||||
#include "be_fixed_be_class_tasmota_serial.h"
|
||||
|
||||
void be_load_serial_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_tasmota_serial);
|
|
@ -31,6 +31,7 @@ extern int l_delay(bvm *vm);
|
|||
extern int l_scaleuint(bvm *vm);
|
||||
extern int l_logInfo(bvm *vm);
|
||||
extern int l_save(bvm *vm);
|
||||
extern int t_random_byte(bvm *vm);
|
||||
|
||||
extern int l_read_sensors(bvm *vm);
|
||||
|
||||
|
@ -1973,7 +1974,7 @@ be_local_closure(Tasmota_get_light, /* name */
|
|||
);
|
||||
/*******************************************************************/
|
||||
|
||||
#include "../generate/be_fixed_be_class_tasmota.h"
|
||||
#include "be_fixed_be_class_tasmota.h"
|
||||
|
||||
|
||||
// Class definition
|
|
@ -20,7 +20,7 @@ extern int wc_tcp_write(bvm *vm);
|
|||
extern int wc_tcp_read(bvm *vm);
|
||||
extern int wc_tcp_readbytes(bvm *vm);
|
||||
|
||||
#include "../generate/be_fixed_be_class_tcpclient.h"
|
||||
#include "be_fixed_be_class_tcpclient.h"
|
||||
|
||||
void be_load_tcpclient_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_tcpclient);
|
|
@ -116,7 +116,7 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
#include "../generate/be_fixed_be_class_udp.h"
|
||||
#include "be_fixed_be_class_udp.h"
|
||||
|
||||
void be_load_udp_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_udp);
|
|
@ -24,7 +24,7 @@ extern int wc_getstring(bvm *vm);
|
|||
extern int wc_writefile(bvm *vm);
|
||||
extern int wc_getsize(bvm *vm);
|
||||
|
||||
#include "../generate/be_fixed_be_class_webclient.h"
|
||||
#include "be_fixed_be_class_webclient.h"
|
||||
|
||||
void be_load_webclient_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_webclient);
|
|
@ -50,6 +50,6 @@ module webserver (scope: global) {
|
|||
has_arg, func(w_webserver_has_arg)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_webserver.h"
|
||||
#include "be_fixed_webserver.h"
|
||||
|
||||
#endif // USE_WEBSERVER
|
|
@ -118,7 +118,7 @@ be_local_closure(read_bytes, /* name */
|
|||
/*******************************************************************/
|
||||
|
||||
|
||||
#include "../generate/be_fixed_be_class_tasmota_wire.h"
|
||||
#include "be_fixed_be_class_tasmota_wire.h"
|
||||
|
||||
void be_load_wirelib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_tasmota_wire);
|
|
@ -0,0 +1,8 @@
|
|||
// force include of module by including this file
|
||||
|
||||
#ifndef __BERRY_TASMOTA__
|
||||
#define __BERRY_TASMOTA__
|
||||
|
||||
|
||||
|
||||
#endif // __BERRY_TASMOTA__
|
|
@ -618,6 +618,16 @@ extern "C" {
|
|||
if (len+3 > LOGSZ) { strcat(log_data, "..."); } // Actual data is more
|
||||
berry_log(log_data);
|
||||
}
|
||||
|
||||
void tasmota_log_C(int32_t loglevel, const char * berry_buf, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, berry_buf);
|
||||
char* log_data = ext_vsnprintf_malloc_P(berry_buf, arg);
|
||||
va_end(arg);
|
||||
if (log_data == nullptr) { return; }
|
||||
AddLogData(loglevel, log_data);
|
||||
free(log_data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_BERRY
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define XDRV_52 52
|
||||
|
||||
#include <berry.h>
|
||||
#include "berry_tasmota.h"
|
||||
#include "be_vm.h"
|
||||
#include "ZipReadFS.h"
|
||||
|
||||
|
@ -727,6 +728,7 @@ bool Xdrv52(uint8_t function)
|
|||
BrLoad("autoexec.be"); // run autoexec.be at first tick, so we know all modules are initialized
|
||||
berry.autoexec_done = true;
|
||||
}
|
||||
callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr);
|
||||
break;
|
||||
|
||||
// Berry wide commands and events
|
||||
|
@ -737,7 +739,9 @@ bool Xdrv52(uint8_t function)
|
|||
result = callBerryRule(nullptr, true);
|
||||
break;
|
||||
case FUNC_MQTT_DATA:
|
||||
{int32_t now = millis();
|
||||
result = callBerryEventDispatcher(PSTR("mqtt_data"), XdrvMailbox.topic, 0, XdrvMailbox.data, XdrvMailbox.data_len);
|
||||
AddLog(LOG_LEVEL_INFO, ">>>: mqtt_data ms = %i", millis()-now);}
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kBrCommands, BerryCommand);
|
||||
|
|
Loading…
Reference in New Issue