diff --git a/CHANGELOG.md b/CHANGELOG.md index f39aea56c..a2e722eac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,7 @@ All notable changes to this project will be documented in this file. - Crash protection in ext_vnsprintf_P (#11202) - Extent compile time SetOptions support (#11204) - ESP32 Extent BLE (#11212) - - ESP32 support for WS2812 hardware driver via RMT or I2S - - ESP32 support for secondary I2C controller diff --git a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h index d3ad809d7..2d1b7e9e0 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h @@ -1,111 +1,116 @@ +extern const bcstring be_const_str_remove; +extern const bcstring be_const_str_false; +extern const bcstring be_const_str_raise; +extern const bcstring be_const_str_opt_connect; +extern const bcstring be_const_str_dot_p; +extern const bcstring be_const_str_calldepth; +extern const bcstring be_const_str_toupper; +extern const bcstring be_const_str_break; +extern const bcstring be_const_str_map; +extern const bcstring be_const_str_bytes; +extern const bcstring be_const_str_tanh; +extern const bcstring be_const_str_real; +extern const bcstring be_const_str_count; +extern const bcstring be_const_str_setitem; +extern const bcstring be_const_str_split; +extern const bcstring be_const_str_if; +extern const bcstring be_const_str_format; +extern const bcstring be_const_str_pow; +extern const bcstring be_const_str_tostring; +extern const bcstring be_const_str_load; +extern const bcstring be_const_str_setrange; +extern const bcstring be_const_str_char; extern const bcstring be_const_str_acos; +extern const bcstring be_const_str_deinit; +extern const bcstring be_const_str_dump; +extern const bcstring be_const_str_sqrt; +extern const bcstring be_const_str_fromstring; +extern const bcstring be_const_str_opt_eq; extern const bcstring be_const_str_asin; +extern const bcstring be_const_str_byte; +extern const bcstring be_const_str_copy; +extern const bcstring be_const_str_floor; +extern const bcstring be_const_str_find; +extern const bcstring be_const_str_var; +extern const bcstring be_const_str_opt_add; +extern const bcstring be_const_str___lower__; +extern const bcstring be_const_str_rand; +extern const bcstring be_const_str_sin; +extern const bcstring be_const_str_deg; +extern const bcstring be_const_str_imin; +extern const bcstring be_const_str_class; +extern const bcstring be_const_str_try; +extern const bcstring be_const_str_allocated; +extern const bcstring be_const_str_asstring; +extern const bcstring be_const_str_classname; +extern const bcstring be_const_str_reverse; +extern const bcstring be_const_str_assert; +extern const bcstring be_const_str_str; +extern const bcstring be_const_str_imax; +extern const bcstring be_const_str_init; +extern const bcstring be_const_str_except; +extern const bcstring be_const_str_return; +extern const bcstring be_const_str_opt_neq; +extern const bcstring be_const_str_hex; +extern const bcstring be_const_str_resize; +extern const bcstring be_const_str_as; +extern const bcstring be_const_str___upper__; +extern const bcstring be_const_str_codedump; +extern const bcstring be_const_str_cosh; +extern const bcstring be_const_str_abs; +extern const bcstring be_const_str_collect; +extern const bcstring be_const_str_atan; +extern const bcstring be_const_str_attrdump; +extern const bcstring be_const_str_input; +extern const bcstring be_const_str_; +extern const bcstring be_const_str_compile; +extern const bcstring be_const_str_iter; +extern const bcstring be_const_str_lower; +extern const bcstring be_const_str_number; +extern const bcstring be_const_str_print; +extern const bcstring be_const_str_exp; +extern const bcstring be_const_str_pi; +extern const bcstring be_const_str___iterator__; +extern const bcstring be_const_str_log; +extern const bcstring be_const_str_log10; +extern const bcstring be_const_str_ceil; +extern const bcstring be_const_str_get; +extern const bcstring be_const_str_tolower; +extern const bcstring be_const_str_while; +extern const bcstring be_const_str_import; +extern const bcstring be_const_str_size; extern const bcstring be_const_str_list; +extern const bcstring be_const_str_rad; +extern const bcstring be_const_str_tan; +extern const bcstring be_const_str_type; +extern const bcstring be_const_str_insert; extern const bcstring be_const_str_module; +extern const bcstring be_const_str_range; +extern const bcstring be_const_str_super; +extern const bcstring be_const_str_issubclass; +extern const bcstring be_const_str_def; +extern const bcstring be_const_str_classof; +extern const bcstring be_const_str_sinh; +extern const bcstring be_const_str_srand; +extern const bcstring be_const_str_end; +extern const bcstring be_const_str_clear; +extern const bcstring be_const_str_top; +extern const bcstring be_const_str_nil; +extern const bcstring be_const_str_open; +extern const bcstring be_const_str_do; +extern const bcstring be_const_str_add; +extern const bcstring be_const_str_isinstance; extern const bcstring be_const_str_pop; extern const bcstring be_const_str_int; -extern const bcstring be_const_str_push; -extern const bcstring be_const_str_setrange; -extern const bcstring be_const_str_sinh; -extern const bcstring be_const_str_elif; -extern const bcstring be_const_str_iter; -extern const bcstring be_const_str_load; -extern const bcstring be_const_str_class; -extern const bcstring be_const_str_if; -extern const bcstring be_const_str_opt_eq; -extern const bcstring be_const_str_ceil; -extern const bcstring be_const_str_floor; -extern const bcstring be_const_str_map; -extern const bcstring be_const_str_print; -extern const bcstring be_const_str_else; -extern const bcstring be_const_str_find; -extern const bcstring be_const_str_str; -extern const bcstring be_const_str___upper__; -extern const bcstring be_const_str_dump; -extern const bcstring be_const_str_atan; -extern const bcstring be_const_str_size; -extern const bcstring be_const_str_tolower; -extern const bcstring be_const_str_opt_add; -extern const bcstring be_const_str_abs; -extern const bcstring be_const_str_lower; -extern const bcstring be_const_str_end; -extern const bcstring be_const_str_import; -extern const bcstring be_const_str_classof; -extern const bcstring be_const_str_concat; -extern const bcstring be_const_str_byte; -extern const bcstring be_const_str_top; -extern const bcstring be_const_str_clear; -extern const bcstring be_const_str_opt_connect; -extern const bcstring be_const_str_collect; -extern const bcstring be_const_str_init; -extern const bcstring be_const_str_log10; -extern const bcstring be_const_str_nil; -extern const bcstring be_const_str_; -extern const bcstring be_const_str_real; -extern const bcstring be_const_str_calldepth; -extern const bcstring be_const_str_format; -extern const bcstring be_const_str_pi; -extern const bcstring be_const_str_do; -extern const bcstring be_const_str___iterator__; -extern const bcstring be_const_str_number; -extern const bcstring be_const_str_type; -extern const bcstring be_const_str_dot_p; -extern const bcstring be_const_str_traceback; -extern const bcstring be_const_str_as; -extern const bcstring be_const_str___lower__; -extern const bcstring be_const_str_exp; -extern const bcstring be_const_str_hex; -extern const bcstring be_const_str_char; -extern const bcstring be_const_str_split; -extern const bcstring be_const_str_toupper; -extern const bcstring be_const_str_deinit; -extern const bcstring be_const_str_tan; -extern const bcstring be_const_str_srand; -extern const bcstring be_const_str_imin; -extern const bcstring be_const_str_input; -extern const bcstring be_const_str_issubclass; -extern const bcstring be_const_str_tostring; -extern const bcstring be_const_str_break; -extern const bcstring be_const_str_insert; -extern const bcstring be_const_str_var; -extern const bcstring be_const_str_open; -extern const bcstring be_const_str_tanh; -extern const bcstring be_const_str_upper; -extern const bcstring be_const_str_allocated; -extern const bcstring be_const_str_rad; -extern const bcstring be_const_str_attrdump; -extern const bcstring be_const_str_copy; -extern const bcstring be_const_str_sqrt; -extern const bcstring be_const_str_for; -extern const bcstring be_const_str_raise; -extern const bcstring be_const_str_opt_neq; -extern const bcstring be_const_str_assert; -extern const bcstring be_const_str_item; -extern const bcstring be_const_str_reverse; -extern const bcstring be_const_str_sin; -extern const bcstring be_const_str_super; -extern const bcstring be_const_str_try; -extern const bcstring be_const_str_range; -extern const bcstring be_const_str_return; -extern const bcstring be_const_str_compile; -extern const bcstring be_const_str_false; -extern const bcstring be_const_str_resize; -extern const bcstring be_const_str_continue; -extern const bcstring be_const_str_log; -extern const bcstring be_const_str_true; -extern const bcstring be_const_str_while; -extern const bcstring be_const_str_pow; -extern const bcstring be_const_str_cos; -extern const bcstring be_const_str_count; -extern const bcstring be_const_str_remove; -extern const bcstring be_const_str_imax; -extern const bcstring be_const_str_rand; -extern const bcstring be_const_str_codedump; -extern const bcstring be_const_str_deg; extern const bcstring be_const_str_keys; -extern const bcstring be_const_str_setitem; -extern const bcstring be_const_str_def; -extern const bcstring be_const_str_except; -extern const bcstring be_const_str_classname; -extern const bcstring be_const_str_isinstance; -extern const bcstring be_const_str_cosh; +extern const bcstring be_const_str_elif; +extern const bcstring be_const_str_item; +extern const bcstring be_const_str_push; +extern const bcstring be_const_str_concat; +extern const bcstring be_const_str_traceback; +extern const bcstring be_const_str_upper; +extern const bcstring be_const_str_true; +extern const bcstring be_const_str_continue; +extern const bcstring be_const_str_else; +extern const bcstring be_const_str_cos; +extern const bcstring be_const_str_for; diff --git a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h index b967bc818..bce08392c 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h @@ -1,165 +1,172 @@ -be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_asin); -be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_list); -be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_module); -be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_pop); -be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); -be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_push); -be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_setrange); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_sinh); -be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_elif); -be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_load); -be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_class); -be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_if); -be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_ceil); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, NULL); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_map); -be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_print); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_else); -be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); -be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_str); -be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_dump); -be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); -be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_size); -be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_tolower); -be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); -be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_abs); -be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_lower); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_end); -be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_import); -be_define_const_str(import, "import", 288002260u, 66, 6, NULL); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_concat); -be_define_const_str(concat, "concat", 4124019837u, 0, 6, NULL); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_top); -be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL); -be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_collect); -be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_init); -be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_log10); -be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_nil); -be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_real); -be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_format); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pi); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_do); -be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_number); -be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_type); -be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); -be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_traceback); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_as); -be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_exp); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_hex); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL); -be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_split); -be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_toupper); -be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_tan); -be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); -be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); -be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_input); -be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_issubclass); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL); -be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, &be_const_str_break); -be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_var); -be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); -be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_tanh); -be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_upper); -be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); -be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_rad); -be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_copy); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_sqrt); -be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); -be_define_const_str(for, "for", 2901640080u, 54, 3, &be_const_str_raise); +be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_false); +be_define_const_str(false, "false", 184981848u, 62, 5, &be_const_str_raise); be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); -be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_assert); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_item); -be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_reverse); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin); -be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_super); -be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try); +be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_dot_p); +be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_calldepth); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, NULL); +be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str_break); +be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); +be_define_const_str(map, "map", 3751997361u, 0, 3, NULL); +be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_tanh); +be_define_const_str(tanh, "tanh", 153638352u, 0, 4, NULL); +be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); +be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_setitem); +be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, &be_const_str_split); +be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_if); +be_define_const_str(if, "if", 959999494u, 50, 2, NULL); +be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pow); +be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_tostring); +be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); +be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_setrange); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); +be_define_const_str(char, "char", 2823553821u, 0, 4, NULL); +be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_deinit); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_dump); +be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_sqrt); +be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); +be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, NULL); +be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_asin); +be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_byte); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_copy); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_floor); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, NULL); +be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_var); +be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); +be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str___lower__); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_rand); +be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_sin); +be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_imin); +be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_class); +be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_try); be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); -be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_return); +be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_asstring); +be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_classname); +be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_str); +be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_init); +be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_except); +be_define_const_str(except, "except", 950914032u, 69, 6, &be_const_str_return); be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); -be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_false); -be_define_const_str(false, "false", 184981848u, 62, 5, NULL); -be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); -be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); -be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_true); -be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); -be_define_const_str(while, "while", 231090382u, 53, 5, NULL); -be_define_const_str(pow, "pow", 1479764693u, 0, 3, NULL); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_count); -be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_remove); -be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_rand); -be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL); -be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_deg); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_keys); -be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_setitem); -be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); -be_define_const_str(def, "def", 3310976652u, 55, 3, &be_const_str_except); -be_define_const_str(except, "except", 950914032u, 69, 6, NULL); -be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_isinstance); -be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); +be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_hex); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_resize); +be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_as); +be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_codedump); +be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_cosh); be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL); +be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_collect); +be_define_const_str(collect, "collect", 2399039025u, 0, 7, NULL); +be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_attrdump); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_input); +be_define_const_str(input, "input", 4191711099u, 0, 5, NULL); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_compile); +be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_iter); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_lower); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_number); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_print); +be_define_const_str(print, "print", 372738696u, 0, 5, NULL); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_pi); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_log); +be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_log10); +be_define_const_str(log10, "log10", 2346846000u, 0, 5, NULL); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_get); +be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_tolower); +be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, &be_const_str_while); +be_define_const_str(while, "while", 231090382u, 53, 5, NULL); +be_define_const_str(import, "import", 288002260u, 66, 6, NULL); +be_define_const_str(size, "size", 597743964u, 0, 4, NULL); +be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_rad); +be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_tan); +be_define_const_str(tan, "tan", 2633446552u, 0, 3, &be_const_str_type); +be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_module); +be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_range); +be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_super); +be_define_const_str(super, "super", 4152230356u, 0, 5, NULL); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_def); +be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_sinh); +be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_srand); +be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); +be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_top); +be_define_const_str(top, "top", 2802900028u, 0, 3, &be_const_str_nil); +be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); +be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_do); +be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); +be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_isinstance); +be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_pop); +be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); +be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_keys); +be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_elif); +be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); +be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_push); +be_define_const_str(push, "push", 2272264157u, 0, 4, NULL); +be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_traceback); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_upper); +be_define_const_str(upper, "upper", 176974407u, 0, 5, &be_const_str_true); +be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); +be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); +be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_for); +be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); static const bstring* const m_string_table[] = { + (const bstring *)&be_const_str_remove, + (const bstring *)&be_const_str_opt_connect, + (const bstring *)&be_const_str_toupper, + NULL, + (const bstring *)&be_const_str_map, + (const bstring *)&be_const_str_bytes, + (const bstring *)&be_const_str_real, + (const bstring *)&be_const_str_count, + (const bstring *)&be_const_str_format, + (const bstring *)&be_const_str_load, + (const bstring *)&be_const_str_char, (const bstring *)&be_const_str_acos, - NULL, - (const bstring *)&be_const_str_int, - NULL, - (const bstring *)&be_const_str_iter, + (const bstring *)&be_const_str_fromstring, (const bstring *)&be_const_str_opt_eq, - (const bstring *)&be_const_str_floor, (const bstring *)&be_const_str_find, - (const bstring *)&be_const_str___upper__, - (const bstring *)&be_const_str_atan, (const bstring *)&be_const_str_opt_add, NULL, - (const bstring *)&be_const_str_classof, - (const bstring *)&be_const_str_byte, - (const bstring *)&be_const_str_clear, - (const bstring *)&be_const_str_opt_connect, - (const bstring *)&be_const_str_, - (const bstring *)&be_const_str_calldepth, - (const bstring *)&be_const_str___iterator__, - (const bstring *)&be_const_str_dot_p, - (const bstring *)&be_const_str___lower__, - (const bstring *)&be_const_str_char, - (const bstring *)&be_const_str_deinit, - (const bstring *)&be_const_str_srand, - (const bstring *)&be_const_str_imin, - (const bstring *)&be_const_str_tostring, - (const bstring *)&be_const_str_insert, - (const bstring *)&be_const_str_open, + (const bstring *)&be_const_str_deg, (const bstring *)&be_const_str_allocated, - (const bstring *)&be_const_str_attrdump, - (const bstring *)&be_const_str_for, - (const bstring *)&be_const_str_opt_neq, - (const bstring *)&be_const_str_range, - (const bstring *)&be_const_str_compile, - (const bstring *)&be_const_str_resize, - (const bstring *)&be_const_str_continue, - (const bstring *)&be_const_str_log, - (const bstring *)&be_const_str_while, - (const bstring *)&be_const_str_pow, - (const bstring *)&be_const_str_cos, + (const bstring *)&be_const_str_reverse, + (const bstring *)&be_const_str_assert, (const bstring *)&be_const_str_imax, - (const bstring *)&be_const_str_codedump, - (const bstring *)&be_const_str_def, - (const bstring *)&be_const_str_classname, - (const bstring *)&be_const_str_cosh + (const bstring *)&be_const_str_opt_neq, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str_abs, + (const bstring *)&be_const_str_atan, + (const bstring *)&be_const_str_, + NULL, + (const bstring *)&be_const_str_exp, + (const bstring *)&be_const_str___iterator__, + (const bstring *)&be_const_str_ceil, + (const bstring *)&be_const_str_import, + (const bstring *)&be_const_str_size, + (const bstring *)&be_const_str_list, + (const bstring *)&be_const_str_insert, + (const bstring *)&be_const_str_issubclass, + (const bstring *)&be_const_str_classof, + (const bstring *)&be_const_str_end, + (const bstring *)&be_const_str_clear, + (const bstring *)&be_const_str_open, + (const bstring *)&be_const_str_add, + (const bstring *)&be_const_str_int, + (const bstring *)&be_const_str_item, + (const bstring *)&be_const_str_concat, + (const bstring *)&be_const_str_continue, + (const bstring *)&be_const_str_else, + (const bstring *)&be_const_str_cos }; static const struct bconststrtab m_const_string_table = { - .size = 45, - .count = 90, + .size = 47, + .count = 95, .table = m_string_table }; diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_be_class_bytes.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_be_class_bytes.h new file mode 100644 index 000000000..44f8eff3e --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_be_class_bytes.h @@ -0,0 +1,33 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_bytes_map) { + { be_const_key(copy, -1), be_const_func(m_copy) }, + { be_const_key(setitem, -1), be_const_func(m_setitem) }, + { be_const_key(tostring, -1), be_const_func(m_tostring) }, + { be_const_key(item, -1), be_const_func(m_item) }, + { be_const_key(init, 8), be_const_func(m_init) }, + { be_const_key(size, 6), be_const_func(m_size) }, + { be_const_key(opt_connect, 7), be_const_func(m_connect) }, + { be_const_key(opt_add, -1), be_const_func(m_merge) }, + { be_const_key(fromstring, -1), be_const_func(m_fromstring) }, + { be_const_key(opt_eq, 14), be_const_func(m_equal) }, + { be_const_key(get, 1), be_const_func(m_get) }, + { be_const_key(asstring, 5), be_const_func(m_asstring) }, + { be_const_key(add, -1), be_const_func(m_add) }, + { be_const_key(dot_p, -1), be_const_int(0) }, + { be_const_key(clear, -1), be_const_func(m_clear) }, + { be_const_key(opt_neq, 4), be_const_func(m_nequal) }, + { be_const_key(resize, 9), be_const_func(m_resize) }, +}; + +static be_define_const_map( + be_class_bytes_map, + 17 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_bytes, + 1, + NULL, + bytes +); diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_be_class_list.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_be_class_list.h index 64eaac2ac..98a52b494 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_fixed_be_class_list.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_be_class_list.h @@ -1,31 +1,32 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_list_map) { - { be_const_key(pop, -1), be_const_func(m_pop) }, - { be_const_key(reverse, -1), be_const_func(m_reverse) }, + { be_const_key(concat, -1), be_const_func(m_concat) }, { be_const_key(push, -1), be_const_func(m_push) }, - { be_const_key(init, -1), be_const_func(m_init) }, - { be_const_key(copy, 8), be_const_func(m_copy) }, - { be_const_key(opt_connect, 13), be_const_func(m_connect) }, - { be_const_key(item, -1), be_const_func(m_item) }, - { be_const_key(remove, -1), be_const_func(m_remove) }, - { be_const_key(size, -1), be_const_func(m_size) }, - { be_const_key(resize, 7), be_const_func(m_resize) }, - { be_const_key(opt_add, -1), be_const_func(m_merge) }, - { be_const_key(opt_neq, -1), be_const_func(m_nequal) }, - { be_const_key(setitem, -1), be_const_func(m_setitem) }, - { be_const_key(tostring, -1), be_const_func(m_tostring) }, + { be_const_key(insert, 1), be_const_func(m_insert) }, + { be_const_key(find, -1), be_const_func(m_find) }, + { be_const_key(remove, 9), be_const_func(m_remove) }, { be_const_key(clear, -1), be_const_func(m_clear) }, - { be_const_key(opt_eq, 3), be_const_func(m_equal) }, - { be_const_key(insert, 12), be_const_func(m_insert) }, - { be_const_key(concat, 2), be_const_func(m_concat) }, - { be_const_key(dot_p, -1), be_const_int(0) }, - { be_const_key(iter, 18), be_const_func(m_iter) }, + { be_const_key(size, -1), be_const_func(m_size) }, + { be_const_key(resize, 13), be_const_func(m_resize) }, + { be_const_key(copy, -1), be_const_func(m_copy) }, + { be_const_key(pop, -1), be_const_func(m_pop) }, + { be_const_key(tostring, 3), be_const_func(m_tostring) }, + { be_const_key(opt_eq, -1), be_const_func(m_equal) }, + { be_const_key(init, -1), be_const_func(m_init) }, + { be_const_key(dot_p, 17), be_const_int(0) }, + { be_const_key(setitem, -1), be_const_func(m_setitem) }, + { be_const_key(opt_connect, 4), be_const_func(m_connect) }, + { be_const_key(opt_neq, -1), be_const_func(m_nequal) }, + { be_const_key(opt_add, 18), be_const_func(m_merge) }, + { be_const_key(iter, 20), be_const_func(m_iter) }, + { be_const_key(item, -1), be_const_func(m_item) }, + { be_const_key(reverse, -1), be_const_func(m_reverse) }, }; static be_define_const_map( be_class_list_map, - 20 + 21 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_m_builtin.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_m_builtin.h index 4b6d13344..423be6100 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_fixed_m_builtin.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_m_builtin.h @@ -1,37 +1,39 @@ #include "be_constobj.h" static be_define_const_map_slots(m_builtin_map) { - { be_const_key(map, 11), be_const_int(10) }, - { be_const_key(str, 14), be_const_int(18) }, - { be_const_key(int, -1), be_const_int(6) }, - { be_const_key(type, -1), be_const_int(20) }, - { be_const_key(assert, -1), be_const_int(1) }, - { be_const_key(issubclass, -1), be_const_int(8) }, - { be_const_key(number, 7), be_const_int(12) }, - { be_const_key(compile, 8), be_const_int(4) }, - { be_const_key(module, 18), be_const_int(11) }, - { be_const_key(input, 5), be_const_int(5) }, - { be_const_key(super, -1), be_const_int(19) }, - { be_const_key(classof, -1), be_const_int(3) }, - { be_const_key(open, 13), be_const_int(13) }, + { be_const_key(print, 19), be_const_int(15) }, + { be_const_key(isinstance, -1), be_const_int(8) }, + { be_const_key(classname, -1), be_const_int(3) }, + { be_const_key(module, -1), be_const_int(12) }, + { be_const_key(size, -1), be_const_int(18) }, + { be_const_key(type, 9), be_const_int(21) }, + { be_const_key(compile, -1), be_const_int(5) }, + { be_const_key(open, -1), be_const_int(14) }, + { be_const_key(real, -1), be_const_int(17) }, { be_const_key(__iterator__, -1), be_const_int(0) }, - { be_const_key(real, 10), be_const_int(16) }, - { be_const_key(list, 20), be_const_int(9) }, - { be_const_key(isinstance, -1), be_const_int(7) }, - { be_const_key(range, -1), be_const_int(15) }, - { be_const_key(size, -1), be_const_int(17) }, - { be_const_key(classname, -1), be_const_int(2) }, - { be_const_key(print, -1), be_const_int(14) }, + { be_const_key(super, -1), be_const_int(20) }, + { be_const_key(issubclass, -1), be_const_int(9) }, + { be_const_key(classof, -1), be_const_int(4) }, + { be_const_key(map, 8), be_const_int(11) }, + { be_const_key(int, 2), be_const_int(7) }, + { be_const_key(input, 3), be_const_int(6) }, + { be_const_key(number, -1), be_const_int(13) }, + { be_const_key(list, 7), be_const_int(10) }, + { be_const_key(str, 1), be_const_int(19) }, + { be_const_key(range, -1), be_const_int(16) }, + { be_const_key(bytes, -1), be_const_int(2) }, + { be_const_key(assert, -1), be_const_int(1) }, }; static be_define_const_map( m_builtin_map, - 21 + 22 ); static const bvalue __vlist_array[] = { be_const_func(l_iterator), be_const_func(l_assert), + be_const_class(be_class_bytes), be_const_func(l_classname), be_const_func(l_classof), be_const_func(l_compile), @@ -56,5 +58,5 @@ static const bvalue __vlist_array[] = { static be_define_const_vector( m_builtin_vector, __vlist_array, - 21 + 22 ); diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_os_path.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_os_path.h deleted file mode 100644 index fc4f5edbc..000000000 --- a/lib/libesp32/Berry-0.1.10/generate/be_fixed_os_path.h +++ /dev/null @@ -1,20 +0,0 @@ -#include "be_constobj.h" - -static be_define_const_map_slots(m_libpath_map) { - { be_const_key(isdir, -1), be_const_func(m_path_isdir) }, - { be_const_key(join, 2), be_const_func(m_path_join) }, - { be_const_key(exists, -1), be_const_func(m_path_exists) }, - { be_const_key(split, -1), be_const_func(m_path_split) }, - { be_const_key(splitext, -1), be_const_func(m_path_splitext) }, - { be_const_key(isfile, -1), be_const_func(m_path_isfile) }, -}; - -static be_define_const_map( - m_libpath_map, - 6 -); - -static be_define_const_module( - m_libpath, - "path" -); diff --git a/lib/libesp32/Berry-0.1.10/src/be_baselib.c b/lib/libesp32/Berry-0.1.10/src/be_baselib.c index f0d7e0147..d1bfd83b1 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_baselib.c +++ b/lib/libesp32/Berry-0.1.10/src/be_baselib.c @@ -313,6 +313,7 @@ void be_load_baselib(bvm *vm) extern const bclass be_class_list; extern const bclass be_class_map; extern const bclass be_class_range; +extern const bclass be_class_bytes; extern int be_nfunc_open(bvm *vm); /* @const_object_info_begin vartab m_builtin (scope: local) { @@ -337,6 +338,7 @@ vartab m_builtin (scope: local) { list, class(be_class_list) map, class(be_class_map) range, class(be_class_range) + bytes, class(be_class_bytes) } @const_object_info_end */ #include "../generate/be_fixed_m_builtin.h" diff --git a/lib/libesp32/Berry-0.1.10/src/be_byteslib.c b/lib/libesp32/Berry-0.1.10/src/be_byteslib.c new file mode 100644 index 000000000..7217c7d75 --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/src/be_byteslib.c @@ -0,0 +1,668 @@ +/******************************************************************** +** Copyright (c) 2018-2020 Guan Wenliang - Stephan Hadinger +** This file is part of the Berry default interpreter. +** skiars@qq.com, https://github.com/Skiars/berry +** See Copyright Notice in the LICENSE file or at +** https://github.com/Skiars/berry/blob/master/LICENSE +********************************************************************/ +#include "be_object.h" +#include "be_string.h" +#include "be_strlib.h" +#include "be_list.h" +#include "be_func.h" +#include "be_exec.h" +#include "be_vm.h" +#include "be_mem.h" +#include +#include + +#define BYTES_DEFAULT_SIZE 28 // default pre-reserved size for buffer (keep 4 bytes for len/size) +#define BYTES_MAX_SIZE (32*1024) // max 32Kb +#define BYTES_OVERHEAD 4 // bytes overhead to be added when allocating (used to store len and size) +#define BYTES_HEADROOM 8 // keep a natural headroom of 8 bytes when resizing + +typedef struct buf_impl { + uint16_t size; // size in bytes of the buffer + uint16_t len; // current size of the data in buffer. Invariant: len <= size + uint8_t buf[]; // the actual data +} buf_impl; + +/******************************************************************** +** Buffer low-level implementation +** +** Extracted from Tasmota SBuffer lib +********************************************************************/ +static inline uint8_t* buf_get_buf(buf_impl* buf) { + return &buf->buf[0]; +} + +// shrink or increase. If increase, fill with zeores. Cannot go beyond `size` +static void buf_set_len(buf_impl* buf, const size_t len) { + uint16_t old_len = buf->len; + buf->len = (len <= buf->size) ? len : buf->size; + if (old_len < buf->len) { + memset((void*) &buf->buf[old_len], 0, buf->len - old_len); + } +} + + +static void buf_set1(buf_impl* buf, const size_t offset, const uint8_t data) { + if (offset < buf->len) { + buf->buf[offset] = data; + } +} +static size_t buf_add1(buf_impl* buf, const uint8_t data) { // append 8 bits value + if (buf->len < buf->size) { // do we have room for 1 byte + buf->buf[buf->len++] = data; + } + return buf->len; +} +static size_t buf_add2_le(buf_impl* buf, const uint16_t data) { // append 16 bits value + if (buf->len < buf->size - 1) { // do we have room for 2 bytes + buf->buf[buf->len++] = data; + buf->buf[buf->len++] = data >> 8; + } + return buf->len; +} +static size_t buf_add2_be(buf_impl* buf, const uint16_t data) { // append 16 bits value + if (buf->len < buf->size - 1) { // do we have room for 2 bytes + buf->buf[buf->len++] = data >> 8; + buf->buf[buf->len++] = data; + } + return buf->len; +} +static size_t buf_add4_le(buf_impl* buf, const uint32_t data) { // append 32 bits value + if (buf->len < buf->size - 3) { // do we have room for 4 bytes + buf->buf[buf->len++] = data; + buf->buf[buf->len++] = data >> 8; + buf->buf[buf->len++] = data >> 16; + buf->buf[buf->len++] = data >> 24; + } + return buf->len; +} +size_t buf_add4_be(buf_impl* buf, const uint32_t data) { // append 32 bits value + if (buf->len < buf->size - 3) { // do we have room for 4 bytes + buf->buf[buf->len++] = data >> 24; + buf->buf[buf->len++] = data >> 16; + buf->buf[buf->len++] = data >> 8; + buf->buf[buf->len++] = data; + } + return buf->len; +} + +static size_t buf_add_buf(buf_impl* buf, buf_impl* buf2) { + if (buf->len + buf2->len <= buf->size) { + for (uint32_t i = 0; i < buf2->len; i++) { + buf->buf[buf->len++] = buf2->buf[i]; + } + } + return buf->len; +} + +static uint8_t buf_get1(buf_impl* buf, int offset) { + if ((offset >= 0) && (offset < buf->len)) { + return buf->buf[offset]; + } + return 0; +} +static uint16_t buf_get2_le(buf_impl* buf, int offset) { + if ((offset >= 0) && (offset < buf->len - 1)) { + return buf->buf[offset] | (buf->buf[offset+1] << 8); + } + return 0; +} +static uint16_t buf_get2_be(buf_impl* buf, int offset) { + if (offset < buf->len - 1) { + return buf->buf[offset+1] | (buf->buf[offset] << 8); + } + return 0; +} +static uint32_t buf_get4_le(buf_impl* buf, int offset) { + if ((offset >= 0) && (offset < buf->len - 3)) { + return buf->buf[offset] | (buf->buf[offset+1] << 8) | + (buf->buf[offset+2] << 16) | (buf->buf[offset+3] << 24); + } + return 0; +} +static uint32_t buf_get4_be(buf_impl* buf, int offset) { + if (offset < buf->len - 3) { + return buf->buf[offset+3] | (buf->buf[offset+2] << 8) | + (buf->buf[offset+1] << 16) | (buf->buf[offset] << 24); + } + return 0; +} + +// nullptr accepted +static bbool buf_equals(buf_impl* buf1, buf_impl* buf2) { + if (buf1 == buf2) { return btrue; } + if (!buf1 || !buf2) { return bfalse; } // at least one buf is not empty + // we know that both buf1 and buf2 are non-null + if (buf1->len != buf2->len) { return bfalse; } + size_t len = buf1->len; + for (uint32_t i=0; i= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } + else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; } + return rVal; +} +// does not check if there is enough room before hand, truncated if buffer too small +static void buf_add_hex(buf_impl* buf, const char *hex, size_t len) { + uint8_t val; + for (; len > 1; len -= 2) { + val = asc2byte(*hex++) << 4; + val |= asc2byte(*hex++); + buf_add1(buf, val); + } +} + +/******************************************************************** +** Wrapping into lib +********************************************************************/ +// typedef int (*bntvfunc)(bvm*); /* native function pointer */ +int free_bytes_buf(bvm* vm) { + int argc = be_top(vm); + if (argc > 0) { + buf_impl * buf = (buf_impl*) be_tocomptr(vm, 1); + if (buf != NULL) { + be_os_free(buf); + } + } + be_return_nil(vm); +} + +buf_impl * bytes_alloc(int32_t size) +{ + if (size < 4) { size = 4; } + if (size > BYTES_MAX_SIZE) { size = BYTES_MAX_SIZE; } + buf_impl * next = (buf_impl*) be_os_malloc(size + BYTES_OVERHEAD); + next->size = size; + next->len = 0; + return next; +} + +/* allocate a new `bytes` object with pre-allocated size */ +static void bytes_new_object(bvm *vm, size_t size) +{ + be_getglobal(vm, "bytes"); /* eventually change with be_getbuiltin */ + be_call(vm, 0); /* stack has only instance */ + be_getmember(vm, -1, "init"); + be_pushvalue(vm, -2); + be_pushint(vm, size); /* stack: instance, init func, instance, size */ + be_call(vm, 2); /* stack: instance, ret, instance, size */ + be_pop(vm, 3); /* remove ret, instance, size */ +} + +static int m_init(bvm *vm) +{ + int argc = be_top(vm); + int size = BYTES_DEFAULT_SIZE; + const char * hex_in = NULL; + if (argc > 1 && be_isint(vm, 2)) { + int new_size = be_toint(vm, 2) + BYTES_HEADROOM; + if (new_size > size) { + size = new_size; + } + } else if (argc > 1 && be_isstring(vm, 2)) { + hex_in = be_tostring(vm, 2); + if (hex_in) { + size = strlen(hex_in) / 2 + BYTES_HEADROOM; // allocate headroom + } + } + buf_impl * buf = bytes_alloc(size); + if (!buf) { + be_throw(vm, BE_MALLOC_FAIL); + } + + if (hex_in) { + buf_add_hex(buf, hex_in, strlen(hex_in)); + } + be_newcomobj(vm, buf, &free_bytes_buf); + be_setmember(vm, 1, ".p"); + be_return_nil(vm); +} + +/* grow or shrink to the exact value */ +/* stack item 1 must contain the instance */ +static buf_impl * _bytes_resize(bvm *vm, buf_impl * buf, size_t new_size) { + buf_impl * new_buf = bytes_alloc(new_size); + if (!new_buf) { + be_throw(vm, BE_MALLOC_FAIL); + } + memmove(buf_get_buf(new_buf), buf_get_buf(buf), buf->len); + new_buf->len = buf->len; + /* replace the .p attribute */ + be_newcomobj(vm, new_buf, &free_bytes_buf); + be_setmember(vm, 1, ".p"); + be_pop(vm, 1); /* remove comobj from stack */ + /* the old buffer will be garbage collected later */ + return new_buf; +} + +/* grow if needed but don't shrink */ +/* if grow, then add some headroom */ +/* stack item 1 must contain the instance */ +static buf_impl * bytes_resize(bvm *vm, buf_impl * buf, size_t new_size) { + if (buf->size >= new_size) { return buf; } /* no resize needed */ + return _bytes_resize(vm, buf, new_size + BYTES_HEADROOM); +} + +static buf_impl * bytes_check_data(bvm *vm, size_t add_size) { + be_getmember(vm, 1, ".p"); + buf_impl * buf = be_tocomptr(vm, -1); + be_pop(vm, 1); /* remove member from stack */ + /* check if the `size` is big enough */ + if (buf->len + add_size > buf->size) { + /* it does not fit so we need to realocate the buffer */ + buf = bytes_resize(vm, buf, buf->len + add_size); + } + return buf; +} + +static size_t tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) { + static const char * hex = "0123456789ABCDEF"; + const uint8_t * pin = in; + char * pout = out; + for (; pin < in + insz; pout += 2, pin++) { + pout[0] = hex[((*pin)>>4) & 0xF]; + pout[1] = hex[ (*pin) & 0xF]; + if (pout + 3 > out + outsz) { break; } /* check overflow */ + } + pout[0] = 0; /* terminating Nul char */ + return pout - out; +} + +static int m_tostring(bvm *vm) +{ + buf_impl * buf = bytes_check_data(vm, 0); + size_t len = buf->len; + size_t hex_len = len * 2 + 5 + 2 + 2 + 1; /* reserve size for `bytes("")\0` - 9 chars */ + + char * hex_out = be_pushbuffer(vm, hex_len); + size_t l = strlcpy(hex_out, "bytes('", hex_len); + l += tohex(&hex_out[l], hex_len - l, buf_get_buf(buf), buf->len); + l += strlcpy(&hex_out[l], "')", hex_len - l); + + be_pushnstring(vm, hex_out, l); /* make escape string from buffer */ + be_remove(vm, -2); /* remove buffer */ + be_return(vm); +} + +/* + * Copy the buffer into a string without any changes + */ +static int m_asstring(bvm *vm) +{ + buf_impl * buf = bytes_check_data(vm, 0); + be_pushnstring(vm, (const char*) buf_get_buf(buf), buf->len); + be_return(vm); +} +static int m_fromstring(bvm *vm) +{ + int argc = be_top(vm); + if (argc >= 2 && be_isstring(vm, 2)) { + const char *s = be_tostring(vm, 2); + size_t len = strlen(s); + buf_impl * buf = bytes_check_data(vm, 0); + buf = bytes_resize(vm, buf, len); /* resize if needed */ + if (len > buf->size) { len = buf->size; } /* avoid overflow */ + memmove(buf_get_buf(buf), s, len); + buf->len = len; + be_pop(vm, 1); /* remove arg to leave instance */ + be_return(vm); + } + be_raise(vm, "type_error", "operand must be a string"); + be_return_nil(vm); +} + +/* + * Add an int made of 1, 2 or 4 bytes, in little or big endian + * `add(value:int[, size:int = 1]) -> instance` + * + * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian) + * obvisouly -1 is idntical to 1 + * size==0 does nothing + */ +static int m_add(bvm *vm) +{ + int argc = be_top(vm); + buf_impl * buf = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */ + if (argc >= 2 && be_isint(vm, 2)) { + int32_t v = be_toint(vm, 2); + int vsize = 1; + if (argc >= 3 && be_isint(vm, 3)) { + vsize = be_toint(vm, 3); + } + switch (vsize) { + case 0: break; + case -1: /* fallback below */ + case 1: buf_add1(buf, v); break; + case 2: buf_add2_le(buf, v); break; + case 4: buf_add4_le(buf, v); break; + case -2: buf_add2_be(buf, v); break; + case -4: buf_add4_be(buf, v); break; + default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4."); + } + be_pop(vm, argc - 1); + be_return(vm); + } + be_return_nil(vm); +} + +/* + * Get an int made of 1, 2 or 4 bytes, in little or big endian + * `get(index:int[, size:int = 1]) -> instance` + * + * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian) + * obvisouly -1 is idntical to 1 + * 0 returns nil + */ +static int m_get(bvm *vm) +{ + int argc = be_top(vm); + buf_impl * buf = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ + if (argc >=2 && be_isint(vm, 2)) { + int32_t idx = be_toint(vm, 2); + int vsize = 1; + if (argc >= 3 && be_isint(vm, 3)) { + vsize = be_toint(vm, 3); + } + int ret = 0; + switch (vsize) { + case 0: break; + case -1: /* fallback below */ + case 1: ret = buf_get1(buf, idx); break; + case 2: ret = buf_get2_le(buf, idx); break; + case 4: ret = buf_get4_le(buf, idx); break; + case -2: ret = buf_get2_be(buf, idx); break; + case -4: ret = buf_get4_be(buf, idx); break; + default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4."); + } + be_pop(vm, argc - 1); + if (vsize != 0) { + be_pushint(vm, ret); + } else { + be_pushnil(vm); + } + be_return(vm); + } + be_return_nil(vm); +} + + +static int m_setitem(bvm *vm) +{ + int argc = be_top(vm); + buf_impl * buf = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ + if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) { + int index = be_toint(vm, 2); + int val = be_toint(vm, 3); + if (index >= 0 && index < buf->len) { + buf_set1(buf, index, val); + be_return_nil(vm); + } + } + be_raise(vm, "index_error", "bytes index out of range or value non int"); + be_return_nil(vm); +} + +static int m_item(bvm *vm) +{ + int argc = be_top(vm); + buf_impl * buf = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ + if (argc >=2 && be_isint(vm, 2)) { + int index = be_toint(vm,2); + if (index >= 0 && index < buf->len) { + be_pushint(vm, buf_get1(buf, index)); + be_return(vm); + } + } + if (argc >= 2 && be_isinstance(vm, 2)) { + const char *cname = be_classname(vm, 2); + if (!strcmp(cname, "range")) { + bint lower, upper; + bint size = buf->len; + /* get index range */ + be_getmember(vm, 2, "__lower__"); + lower = be_toint(vm, -1); + be_pop(vm, 1); + be_getmember(vm, 2, "__upper__"); + upper = be_toint(vm, -1); + be_pop(vm, 1); + /* protection scope */ + upper = upper < size ? upper : size - 1; + lower = lower < 0 ? 0 : lower; + /* construction result list instance */ + bytes_new_object(vm, upper > lower ? upper-lower : 0); + be_getmember(vm, -1, ".p"); + buf_impl * buf2 = be_tocomptr(vm, -1); + be_pop(vm, 1); /* remove .p and leave bytes instance */ + for (; lower <= upper; ++lower) { + buf_add1(buf2, buf->buf[lower]); + } + be_return(vm); + } + } + be_raise(vm, "index_error", "bytes index out of range"); + be_return_nil(vm); +} + +static int m_size(bvm *vm) +{ + buf_impl * buf = bytes_check_data(vm, 0); + be_pushint(vm, buf->len); + be_return(vm); +} + +static int m_resize(bvm *vm) +{ + int argc = be_top(vm); + be_getmember(vm, 1, ".p"); + buf_impl * buf = be_tocomptr(vm, -1); + be_pop(vm, 1); + + if (argc <= 1 || !be_isint(vm, 2)) { + be_raise(vm, "type_error", "size must be of type 'int'"); + } + int new_len = be_toint(vm, 2); + if (new_len < 0) { + new_len = 0; + } + + buf = bytes_resize(vm, buf, new_len); + buf_set_len(buf, new_len); + be_pop(vm, 1); + be_return(vm); +} + +static int m_clear(bvm *vm) +{ + buf_impl * buf = bytes_check_data(vm, 0); + buf->len = 0; + be_return_nil(vm); +} + +static int m_merge(bvm *vm) +{ + int argc = be_top(vm); + buf_impl * buf1 = bytes_check_data(vm, 0); /* no resize yet */ + if (argc >= 2 && be_isinstance(vm, 2)) { + be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */ + if (be_isderived(vm, 2)) { + be_getmember(vm, 2, ".p"); + buf_impl * buf2 = be_tocomptr(vm, -1); + be_pop(vm, 4); /* remove class, member, and 2 operands */ + + /* allocate new object */ + bytes_new_object(vm, buf1->len + buf2->len); + be_getmember(vm, -1, ".p"); + /* .p is on top of stack, then instance */ + buf_impl * buf3 = be_tocomptr(vm, -1); + be_pop(vm, 1); + buf_add_buf(buf3, buf1); + buf_add_buf(buf3, buf2); + + be_return(vm); /* return self */ + } + } + be_raise(vm, "type_error", "operand must be bytes"); + be_return_nil(vm); /* return self */ +} + +static int m_copy(bvm *vm) +{ + buf_impl * buf1 = bytes_check_data(vm, 0); /* no resize */ + bytes_new_object(vm, buf1->len); + be_getmember(vm, -1, ".p"); + buf_impl * buf2 = be_tocomptr(vm, -1); + be_pop(vm, 1); + buf_add_buf(buf2, buf1); + be_return(vm); /* return self */ +} + +/* accept bytes or int as operand */ +static int m_connect(bvm *vm) +{ + int argc = be_top(vm); + buf_impl * buf1 = bytes_check_data(vm, 0); /* don't resize yet */ + if (argc >= 2 && (be_isinstance(vm, 2) || be_isint(vm, 2))) { + if (be_isint(vm, 2)) { + buf1 = bytes_resize(vm, buf1, buf1->len + 1); /* resize */ + buf_add1(buf1, be_toint(vm, 2)); + be_pop(vm, 1); /* remove operand */ + be_return(vm); /* return self */ + } else { + be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */ + if (be_isderived(vm, 2)) { + be_getmember(vm, 2, ".p"); + buf_impl * buf2 = be_tocomptr(vm, -1); + buf1 = bytes_resize(vm, buf1, buf1->len + buf2->len); /* resize buf1 for total size */ + buf_add_buf(buf1, buf2); + be_pop(vm, 3); /* remove class, member, and last operand */ + be_return(vm); /* return self */ + } + } + } + be_raise(vm, "type_error", "operand must be bytes or int"); + be_return_nil(vm); /* return self */ +} + +static int bytes_equal(bvm *vm, bbool iseq) +{ + be_getmember(vm, 1, ".p"); + buf_impl * buf1 = be_tocomptr(vm, -1); + be_pop(vm, 1); + + be_getmember(vm, 2, ".p"); + buf_impl * buf2 = be_tocomptr(vm, -1); + be_pop(vm, 1); + + bbool ret; + if (buf_equals(buf1, buf2)) { + ret = iseq; + } else { + ret = !iseq; + } + be_pushbool(vm, ret); + be_return(vm); +} + +static int m_equal(bvm *vm) +{ + return bytes_equal(vm, btrue); +} + +static int m_nequal(bvm *vm) +{ + return bytes_equal(vm, bfalse); +} + +/* + * External API + */ +BERRY_API void be_pushbytes(bvm *vm, const void * bytes, size_t len) +{ + bytes_new_object(vm, len); + be_getmember(vm, -1, ".p"); + buf_impl * buf = be_tocomptr(vm, -1); + be_pop(vm, 1); /* remove .p1 and leave instance */ + if (len > buf->size) { len = buf->size; } /* double check if the buffer allocated was smaller */ + memmove((void*)buf_get_buf(buf), bytes, len); + buf->len = len; + /* bytes instance is on top of stack */ +} + +BERRY_API const void *be_tobytes(bvm *vm, int rel_index, size_t *len) +{ + int index = be_absindex(vm, rel_index); + if (be_isinstance(vm, index)) { + be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */ + if (be_isderived(vm, index)) { + be_getmember(vm, index, ".p"); + buf_impl * buf = be_tocomptr(vm, -1); + be_pop(vm, 2); /* class and .p */ + if (len) { *len = buf->len; } + return (void*) buf_get_buf(buf); + } else { + be_pop(vm, 1); /* remove class */ + } + } + if (len) { *len = 0; } + return NULL; +} + +#if !BE_USE_PRECOMPILED_OBJECT +void be_load_byteslib(bvm *vm) +{ + static const bnfuncinfo members[] = { + { ".p", NULL }, + { "init", m_init }, + { "tostring", m_tostring }, + { "asstring", m_asstring }, + { "fromstring", m_fromstring }, + { "add", m_add }, + { "get", m_get }, + { "item", m_item }, + { "setitem", m_setitem }, + { "size", m_size }, + { "resize", m_resize }, + { "clear", m_clear }, + { "copy", m_copy }, + { "+", m_merge }, + { "..", m_connect }, + { "==", m_equal }, + { "!=", m_nequal }, + { NULL, NULL } + }; + be_regclass(vm, "bytes", members); +} +#else +/* @const_object_info_begin +class be_class_bytes (scope: global, name: bytes) { + .p, var + init, func(m_init) + tostring, func(m_tostring) + asstring, func(m_asstring) + fromstring, func(m_fromstring) + add, func(m_add) + get, func(m_get) + item, func(m_item) + setitem, func(m_setitem) + size, func(m_size) + resize, func(m_resize) + clear, func(m_clear) + copy, func(m_copy) + +, func(m_merge) + .., func(m_connect) + ==, func(m_equal) + !=, func(m_nequal) +} +@const_object_info_end */ +#include "../generate/be_fixed_be_class_bytes.h" +#endif diff --git a/lib/libesp32/Berry-0.1.10/src/be_libs.c b/lib/libesp32/Berry-0.1.10/src/be_libs.c index bf95f5dad..5dc77ea85 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_libs.c +++ b/lib/libesp32/Berry-0.1.10/src/be_libs.c @@ -13,6 +13,9 @@ extern void be_load_maplib(bvm *vm); extern void be_load_rangelib(bvm *vm); extern void be_load_filelib(bvm *vm); +extern void be_load_tasmota_ntvlib(bvm *vm); +extern void be_load_wirelib(bvm *vm); + void be_loadlibs(bvm *vm) { be_load_baselib(vm); @@ -21,5 +24,8 @@ void be_loadlibs(bvm *vm) be_load_maplib(vm); be_load_rangelib(vm); be_load_filelib(vm); + be_load_byteslib(vm); #endif + be_load_tasmota_ntvlib(vm); + be_load_wirelib(vm); } diff --git a/lib/libesp32/Berry-0.1.10/src/be_listlib.c b/lib/libesp32/Berry-0.1.10/src/be_listlib.c index a46c89e21..3733c78c0 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_listlib.c +++ b/lib/libesp32/Berry-0.1.10/src/be_listlib.c @@ -207,6 +207,19 @@ static int m_item(bvm *vm) be_return_nil(vm); } +static int m_find(bvm *vm) +{ + be_getmember(vm, 1, ".p"); + list_check_data(vm, 2); + if (be_isint(vm, 2)) { + be_pushvalue(vm, 2); + if (be_getindex(vm, -2)) { + be_return(vm); + } + } + be_return_nil(vm); +} + static int m_setitem(bvm *vm) { be_getmember(vm, 1, ".p"); @@ -291,13 +304,15 @@ static int m_merge(bvm *vm) { int argc = be_top(vm); if (argc >= 2) { + be_newobject(vm, "list"); /* stack contains instance and .p */ be_getmember(vm, 1, ".p"); + be_data_merge(vm, -2); be_getmember(vm, 2, ".p"); if (!be_islist(vm, -1)) { be_raise(vm, "type_error", "operand must be a list"); } - be_data_merge(vm, -2); - be_pop(vm, argc + 1); + be_data_merge(vm, -3); + be_pop(vm, 3); } be_return(vm); /* return self */ } @@ -423,6 +438,7 @@ void be_load_listlib(bvm *vm) { "insert", m_insert }, { "remove", m_remove }, { "item", m_item }, + { "find", m_find }, { "setitem", m_setitem }, { "size", m_size }, { "resize", m_resize }, @@ -450,6 +466,7 @@ class be_class_list (scope: global, name: list) { insert, func(m_insert) remove, func(m_remove) item, func(m_item) + find, func(m_find) setitem, func(m_setitem) size, func(m_size) resize, func(m_resize) diff --git a/lib/libesp32/Berry-0.1.10/src/be_vm.c b/lib/libesp32/Berry-0.1.10/src/be_vm.c index fd45cabfb..ec786aa09 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_vm.c +++ b/lib/libesp32/Berry-0.1.10/src/be_vm.c @@ -1060,4 +1060,4 @@ BERRY_API void be_set_obs_hook(bvm *vm, beobshook hook) #if BE_USE_OBSERVABILITY_HOOK vm->obshook = hook; #endif -} \ No newline at end of file +} diff --git a/lib/libesp32/Berry-0.1.10/src/berry.h b/lib/libesp32/Berry-0.1.10/src/berry.h index 91bc652a4..6bcdbc556 100644 --- a/lib/libesp32/Berry-0.1.10/src/berry.h +++ b/lib/libesp32/Berry-0.1.10/src/berry.h @@ -429,6 +429,10 @@ BERRY_API int be_savecode(bvm *vm, const char *name); BERRY_API void be_module_path(bvm *vm); BERRY_API void be_module_path_set(bvm *vm, const char *path); +/* bytes operations */ +BERRY_API void be_pushbytes(bvm *vm, const void *buf, size_t len); +BERRY_API const void *be_tobytes(bvm *vm, int index, size_t *len); + /* registry operation */ BERRY_API int be_register(bvm *vm, int index); BERRY_API void be_unregister(bvm *vm, int id); diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_energylib.c b/lib/libesp32/Berry-0.1.10/src/port/be_energylib.c new file mode 100644 index 000000000..444133852 --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/src/port/be_energylib.c @@ -0,0 +1,26 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `import power` + * + * read power values + *******************************************************************/ +#include "be_object.h" + +extern int b_nrg_read(bvm *vm); + +// #if !BE_USE_PRECOMPILED_OBJECT +#if 1 // TODO we will do pre-compiled later +be_native_module_attr_table(energy) { + be_native_module_function("read", b_nrg_read), +}; + +be_define_native_module(energy, NULL); +#else +/* @const_object_info_begin +module tasmota (scope: global, depend: 1) { + getfreeheap, func(l_getFreeHeap) +} +@const_object_info_end */ +#include "../generate/be_fixed_tasmota.h" +#endif diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c b/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c index b3e763fec..fa3f09479 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c @@ -20,8 +20,9 @@ be_extern_native_module(debug); be_extern_native_module(gc); /* Tasmota specific */ -be_extern_native_module(tasmota_ntv); +// be_extern_native_module(tasmota_ntv); be_extern_native_module(wire); +be_extern_native_module(energy); /* user-defined modules declare start */ @@ -56,8 +57,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #endif /* user-defined modules register start */ - &be_native_module(tasmota_ntv), - &be_native_module(wire), + &be_native_module(energy), /* user-defined modules register end */ NULL /* do not remove */ diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c index bd484a9da..17b09a219 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c @@ -13,6 +13,7 @@ extern int l_millis(bvm *vm); extern int l_timereached(bvm *vm); extern int l_yield(bvm *vm); extern int l_delay(bvm *vm); +extern int l_scaleuint(bvm *vm); extern int l_respCmnd(bvm *vm); extern int l_respCmndStr(bvm *vm); @@ -22,33 +23,49 @@ extern int l_respCmndFailed(bvm *vm); extern int l_resolveCmnd(bvm *vm); extern int l_getlight(bvm *vm); +extern int l_getpower(bvm *vm); +extern int l_setlight(bvm *vm); +extern int l_setpower(bvm *vm); // #if !BE_USE_PRECOMPILED_OBJECT #if 1 // TODO we will do pre-compiled later +// Class definition +void be_load_tasmota_ntvlib(bvm *vm) +{ + static const bnfuncinfo members[] = { + { "_op", NULL }, + { "_opf", NULL }, + { "_operators", NULL }, + { "_rules", NULL }, + { "_timers", NULL }, + { "_cmd", NULL }, + { "getfreeheap", l_getFreeHeap }, + { "publish", l_publish }, + { "cmd", l_cmd }, + { "getoption", l_getoption }, + { "millis", l_millis }, + { "timereached", l_timereached }, + { "yield", l_yield }, + { "delay", l_delay }, + { "scaleuint", l_scaleuint }, -be_native_module_attr_table(tasmota_ntv) { - be_native_module_function("getfreeheap", l_getFreeHeap), - be_native_module_function("publish", l_publish), - be_native_module_function("cmd", l_cmd), - be_native_module_function("getoption", l_getoption), - be_native_module_function("millis", l_millis), - be_native_module_function("timereached", l_timereached), - be_native_module_function("yield", l_yield), - be_native_module_function("delay", l_delay), + { "respcmnd", l_respCmnd }, + { "respcmndstr", l_respCmndStr }, + { "respcmnd_done", l_respCmndDone }, + { "respcmnd_error", l_respCmndError }, + { "respcmnd_failed", l_respCmndFailed }, + { "resolvecmnd", l_resolveCmnd }, - be_native_module_function("respcmnd", l_respCmnd), - be_native_module_function("respcmndstr", l_respCmndStr), - be_native_module_function("respcmnd_done", l_respCmndDone), - be_native_module_function("respcmnd_error", l_respCmndError), - be_native_module_function("respcmnd_failed", l_respCmndFailed), - be_native_module_function("resolvecmnd", l_resolveCmnd), + { "getlight", l_getlight }, + { "getpower", l_getpower }, + { "setlight", l_setlight }, + { "setpower", l_setpower }, + + { NULL, NULL } + }; + be_regclass(vm, "Tasmota_ntv", members); +} - be_native_module_function("getlight", l_getlight), - - be_native_module_str("_operators", "=<>!|"), -}; - -be_define_native_module(tasmota_ntv, NULL); #else /* @const_object_info_begin module tasmota (scope: global, depend: 1) { diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c b/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c index 948ccddef..07581b2a4 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c @@ -7,6 +7,8 @@ *******************************************************************/ #include "be_object.h" +extern int b_wire_init(bvm *vm); + extern int b_wire_begintransmission(bvm *vm); extern int b_wire_endtransmission(bvm *vm); extern int b_wire_requestfrom(bvm *vm); @@ -21,19 +23,25 @@ extern int b_wire_validread(bvm *vm); // #if !BE_USE_PRECOMPILED_OBJECT #if 1 // TODO we will do pre-compiled later -be_native_module_attr_table(wire) { - be_native_module_function("_begintransmission", b_wire_begintransmission), - be_native_module_function("_endtransmission", b_wire_endtransmission), - be_native_module_function("_requestfrom", b_wire_requestfrom), - be_native_module_function("_available", b_wire_available), - be_native_module_function("_write", b_wire_write), - be_native_module_function("_read", b_wire_read), - be_native_module_function("scan", b_wire_scan), - be_native_module_function("write", b_wire_validwrite), - be_native_module_function("read", b_wire_validread), -}; - -be_define_native_module(wire, NULL); +void be_load_wirelib(bvm *vm) +{ + static const bnfuncinfo members[] = { + { "_bus", NULL }, // bus number + { "init", b_wire_init }, + { "_begintransmission", b_wire_begintransmission }, + { "_endtransmission", b_wire_endtransmission }, + { "_requestfrom", b_wire_requestfrom }, + { "_available", b_wire_available }, + { "_write", b_wire_write }, + { "_read", b_wire_read }, + { "scan", b_wire_scan }, + { "write", b_wire_validwrite }, + { "read", b_wire_validread }, + + { NULL, NULL } + }; + be_regclass(vm, "Wire", members); +} #else /* @const_object_info_begin module tasmota (scope: global, depend: 1) { diff --git a/tasmota/berry/autoexec.be b/tasmota/berry/autoexec.be new file mode 100644 index 000000000..60f18e5fc --- /dev/null +++ b/tasmota/berry/autoexec.be @@ -0,0 +1 @@ +load('denky.be') diff --git a/tasmota/berry/denky.be b/tasmota/berry/denky.be new file mode 100644 index 000000000..bcec51407 --- /dev/null +++ b/tasmota/berry/denky.be @@ -0,0 +1,21 @@ +#- +# example of using Berry script to change the led color +# accordingly to power consumption +# using Denky (French Teleinfo reader) +-# + +#- define the global symbol for reference -# +runcolor = nil + +def runcolor() + var pwr = energy.read().find('activepower',0) + print(pwr) + var red = tasmota.scaleuint(int(pwr), 0, 2500, 0, 255) + var green = 255 - red + var channels = [red, green, 0] + tasmota.setlight({"channels":channels, "bri":64, "power":true}) + tasmota.settimer(2000, runcolor) +end + +#- run animation -# +runcolor() diff --git a/tasmota/support.ino b/tasmota/support.ino index 85e1a7341..f4d030def 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1812,27 +1812,37 @@ const uint8_t I2C_RETRY_COUNTER = 3; uint32_t i2c_active[4] = { 0 }; uint32_t i2c_buffer = 0; +#ifdef ESP32 +bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size, uint32_t bus = 0); +bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size, uint32_t bus) +#else bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size) +#endif { uint8_t retry = I2C_RETRY_COUNTER; bool status = false; +#ifdef ESP32 + TwoWire & myWire = (bus == 0) ? Wire : Wire1; +#else + TwoWire & myWire = Wire; +#endif i2c_buffer = 0; while (!status && retry) { - Wire.beginTransmission(addr); // start transmission to device - Wire.write(reg); // sends register address to read from - if (0 == Wire.endTransmission(false)) { // Try to become I2C Master, send data and collect bytes, keep master status for next request... - Wire.requestFrom((int)addr, (int)size); // send data n-bytes read - if (Wire.available() == size) { + myWire.beginTransmission(addr); // start transmission to device + myWire.write(reg); // sends register address to read from + if (0 == myWire.endTransmission(false)) { // Try to become I2C Master, send data and collect bytes, keep master status for next request... + myWire.requestFrom((int)addr, (int)size); // send data n-bytes read + if (myWire.available() == size) { for (uint32_t i = 0; i < size; i++) { - i2c_buffer = i2c_buffer << 8 | Wire.read(); // receive DATA + i2c_buffer = i2c_buffer << 8 | myWire.read(); // receive DATA } status = true; } } retry--; } - if (!retry) Wire.endTransmission(); + if (!retry) myWire.endTransmission(); return status; } @@ -1916,19 +1926,30 @@ int32_t I2cRead24(uint8_t addr, uint8_t reg) return i2c_buffer; } +#ifdef ESP32 +bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size, uint32_t bus = 0); +bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size, uint32_t bus) +#else bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size) +#endif { uint8_t x = I2C_RETRY_COUNTER; +#ifdef ESP32 + TwoWire & myWire = (bus == 0) ? Wire : Wire1; +#else + TwoWire & myWire = Wire; +#endif + do { - Wire.beginTransmission((uint8_t)addr); // start transmission to device - Wire.write(reg); // sends register address to write to + myWire.beginTransmission((uint8_t)addr); // start transmission to device + myWire.write(reg); // sends register address to write to uint8_t bytes = size; while (bytes--) { - Wire.write((val >> (8 * bytes)) & 0xFF); // write data + myWire.write((val >> (8 * bytes)) & 0xFF); // write data } x--; - } while (Wire.endTransmission(true) != 0 && x != 0); // end transmission + } while (myWire.endTransmission(true) != 0 && x != 0); // end transmission return (x); } diff --git a/tasmota/xdrv_52_2_berry_native.ino b/tasmota/xdrv_52_2_berry_native.ino new file mode 100644 index 000000000..58a4f8ec3 --- /dev/null +++ b/tasmota/xdrv_52_2_berry_native.ino @@ -0,0 +1,119 @@ +/* + xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include +#include + +const char kTypeError[] PROGMEM = "type_error"; + +extern "C" { + void be_dumpstack(bvm *vm) { + int32_t top = be_top(vm); + AddLog(LOG_LEVEL_INFO, "BRY: top=%d", top); + for (uint32_t i = 1; i <= top; i++) { + const char * tname = be_typename(vm, i); + const char * cname = be_classname(vm, i); + AddLog(LOG_LEVEL_INFO, "BRY: stack[%d] = type='%s' (%s)", i, (tname != nullptr) ? tname : "", (cname != nullptr) ? cname : ""); + } + } + + // convert to unsigned 8 bits + static uint8_t to_u8(int32_t v) { + if (v < 0) { return 0; } + if (v > 0xFF) { return 0xFF; } + return v; + } + static void map_insert_int(bvm *vm, const char *key, int value) + { + be_pushstring(vm, key); + be_pushint(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } + static void map_insert_bool(bvm *vm, const char *key, bool value) + { + be_pushstring(vm, key); + be_pushbool(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } + // if value == NAN, ignore + static void map_insert_float(bvm *vm, const char *key, float value) + { + if (!isnan(value)) { + be_pushstring(vm, key); + be_pushreal(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } + } + static void map_insert_str(bvm *vm, const char *key, const char *value) + { + be_pushstring(vm, key); + be_pushstring(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } + static void map_insert_list_uint8(bvm *vm, const char *key, const uint8_t *value, size_t size) + { + be_pushstring(vm, key); + + be_newobject(vm, "list"); + for (uint32_t i=0; i < size; i++) { + be_pushint(vm, value[i]); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); // now list is on top + + be_data_insert(vm, -3); // insert into map, key/value + be_pop(vm, 2); // pop both key and value + } + static bool map_find(bvm *vm, const char *key) + { + be_getmethod(vm, -1, "find"); // look for "find" method of "Map" instance + be_pushvalue(vm, -2); // put back instance as first argument (implicit instance) + be_pushstring(vm, key); // push string as second argument + be_call(vm, 2); // call wirn 2 parameters (implicit instance and key) + be_pop(vm, 2); // pop 2 arguments, the function is replaced by result + return !be_isnil(vm, -1); // true if not 'nil' + } + static int32_t get_list_size(bvm *vm) { + be_getmethod(vm, -1, "size"); // look for "size" method of "list" instance + be_pushvalue(vm, -2); // put back instance as first argument (implicit instance) + be_call(vm, 1); // call wirn 2 parameters (implicit instance and key) + int32_t ret = be_toint(vm, -2); + be_pop(vm, 2); // pop 1 argument and return value + return ret; + } + // get item number `index` from list, index must be valid or raises an exception + static void get_list_item(bvm *vm, int32_t index) { + be_getmethod(vm, -1, "item"); // look for "size" method of "list" instance + be_pushvalue(vm, -2); // put back instance as first argument (implicit instance) + be_pushint(vm, index); + // be_dumpstack(vm); + be_call(vm, 2); // call wirn 2 parameters (implicit instance and key) + be_pop(vm, 2); // pop 2 arguments and return value + } +} + +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_energy.ino b/tasmota/xdrv_52_3_berry_energy.ino new file mode 100644 index 000000000..75ae27245 --- /dev/null +++ b/tasmota/xdrv_52_3_berry_energy.ino @@ -0,0 +1,70 @@ +/* + xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include + + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * import power + * + * power.read() -> map + * +\*********************************************************************************************/ +extern "C" { +#ifdef USE_ENERGY_SENSOR + // Berry: `begintransmission(address:int) -> nil` + int32_t b_nrg_read(struct bvm *vm); + int32_t b_nrg_read(struct bvm *vm) { + be_newobject(vm, "map"); + map_insert_float(vm, "total", Energy.total); + // Energy.phase_count + map_insert_float(vm, "power", Energy.active_power[0]); + map_insert_float(vm, "yesterday", (float)Settings.energy_kWhyesterday / 100000); + map_insert_float(vm, "today", Energy.daily); + map_insert_float(vm, "activepower", Energy.active_power[0]); + map_insert_float(vm, "apparentpower", Energy.active_power[0]); + map_insert_float(vm, "reactivepower", Energy.reactive_power[0]); + // map_insert_float(vm, "powerfactor", ); + map_insert_float(vm, "frequency", Energy.frequency[0]); + map_insert_float(vm, "voltage", Energy.voltage[0]); + map_insert_float(vm, "current", Energy.current[0]); + + be_pop(vm, 1); + be_return(vm); // Return + } +#else // USE_ENERGY_SENSOR + // + int32_t b_wire_energymissing(struct bvm *vm); + int32_t b_wire_energymissing(struct bvm *vm) { + be_raise(vm, "feature_error", "Energy sensor is not enabled, use '#define USE_ENERGY_SENSOR'"); + } + + // define weak aliases + int32_t b_nrg_read(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_energymissing"))); +#endif // USE_ENERGY_SENSOR +} + + + +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_native.ino b/tasmota/xdrv_52_3_berry_native.ino deleted file mode 100644 index 46b869544..000000000 --- a/tasmota/xdrv_52_3_berry_native.ino +++ /dev/null @@ -1,534 +0,0 @@ -/* - xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions - - Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#ifdef USE_BERRY - -#include -#include - -const char kTypeError[] PROGMEM = "type_error"; -/*********************************************************************************************\ - * Native functions mapped to Berry functions - * - * log(msg:string [,log_level:int]) ->nil - * - * import tasmota - * - * tasmota.getfreeheap() -> int - * tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil - * tasmota.cmd(command:string) -> string - * tasmota.getoption(index:int) -> int - * tasmota.millis([delay:int]) -> int - * tasmota.timereached(timer:int) -> bool - * tasmota.yield() -> nil - * -\*********************************************************************************************/ -extern "C" { - // Berry: `tasmota.publish(topic, payload [,retain]) -> nil`` - // - int32_t l_publish(struct bvm *vm); - int32_t l_publish(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { // 2 mandatory string arguments - if (top == 2 || (top == 3 && be_isbool(vm, 3))) { // 3rd optional argument must be bool - const char * topic = be_tostring(vm, 1); - const char * payload = be_tostring(vm, 2); - bool retain = false; - if (top == 3) { - retain = be_tobool(vm, 3); - } - strlcpy(TasmotaGlobal.mqtt_data, payload, sizeof(TasmotaGlobal.mqtt_data)); - MqttPublish(topic, retain); - be_return(vm); // Return - } - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `tasmota.cmd(command:string) -> string` - // - int32_t l_cmd(struct bvm *vm); - int32_t l_cmd(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted - const char * command = be_tostring(vm, 1); - ExecuteCommand(command, SRC_BERRY); - be_pushstring(vm, TasmotaGlobal.mqtt_data); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: tasmota.millis([delay:int]) -> int - // - int32_t l_millis(struct bvm *vm); - int32_t l_millis(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 0 || (top == 1 && be_isint(vm, 1))) { // only 1 argument of type string accepted - uint32_t delay = 0; - if (top == 1) { - delay = be_toint(vm, 1); - } - uint32_t ret_millis = millis() + delay; - be_pushint(vm, ret_millis); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: tasmota.getoption(index:int) -> int - // - int32_t l_getoption(struct bvm *vm); - int32_t l_getoption(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isint(vm, 1)) { - uint32_t opt = GetOption(be_toint(vm, 1)); - be_pushint(vm, opt); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: tasmota.timereached(timer:int) -> bool - // - int32_t l_timereached(struct bvm *vm); - int32_t l_timereached(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted - uint32_t timer = be_toint(vm, 1); - bool reached = TimeReached(timer); - be_pushbool(vm, reached); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: tasmota.delay(timer:int) -> nil - // - int32_t l_delay(struct bvm *vm); - int32_t l_delay(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted - uint32_t timer = be_toint(vm, 1); - delay(timer); - be_return_nil(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `yield() -> nil` - // ESP object - int32_t l_yield(bvm *vm); - int32_t l_yield(bvm *vm) { - optimistic_yield(10); - be_return(vm); - } - - // Berry: `save(file:string, f:closure) -> bool` - int32_t l_save(struct bvm *vm); - int32_t l_save(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top ==2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted - const char *fname = be_tostring(vm, 1); - int32_t ret = be_savecode(vm, fname); - be_pushint(vm, ret); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - int32_t l_respCmnd(bvm *vm); - int32_t l_respCmnd(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { - const char *msg = be_tostring(vm, 1); - Response_P("%s", msg); - be_return_nil(vm); // Return nil when something goes wrong - } - be_raise(vm, kTypeError, nullptr); - } - - int32_t l_respCmndStr(bvm *vm); - int32_t l_respCmndStr(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { - const char *msg = be_tostring(vm, 1); - ResponseCmndChar(msg); - be_return_nil(vm); // Return nil when something goes wrong - } - be_raise(vm, kTypeError, nullptr); - } - - int32_t l_respCmndDone(bvm *vm); - int32_t l_respCmndDone(bvm *vm) { - ResponseCmndDone(); - be_return_nil(vm); - } - - int32_t l_respCmndError(bvm *vm); - int32_t l_respCmndError(bvm *vm) { - ResponseCmndError(); - be_return_nil(vm); - } - - int32_t l_respCmndFailed(bvm *vm); - int32_t l_respCmndFailed(bvm *vm) { - ResponseCmndFailed(); - be_return_nil(vm); - } - - // update XdrvMailbox.command with actual command - int32_t l_resolveCmnd(bvm *vm); - int32_t l_resolveCmnd(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isstring(vm, 1)) { - const char *msg = be_tostring(vm, 1); - strlcpy(XdrvMailbox.command, msg, CMDSZ); - be_return_nil(vm); // Return nil when something goes wrong - } - be_raise(vm, kTypeError, nullptr); - } - - - static void map_insert_int(bvm *vm, const char *key, int value) - { - be_pushstring(vm, key); - be_pushint(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); - } - static void map_insert_bool(bvm *vm, const char *key, bool value) - { - be_pushstring(vm, key); - be_pushbool(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); - } - static void map_insert_str(bvm *vm, const char *key, const char *value) - { - be_pushstring(vm, key); - be_pushstring(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); - } - - // get light - int32_t l_getlight(bvm *vm); - int32_t l_getlight(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 0 || (top == 1 && be_isint(vm, 1))) { - int32_t light_num = 0; - if (top > 0) { - light_num = be_toint(vm, 1); - } - bool data_present = false; // do we have relevant data - be_newobject(vm, "map"); - // check if the light exist - // TasmotaGlobal.devices_present - // Light.device - // Light.subtype - // Light.pwm_multi_channels - // light_controller.isCTRGBLinked() - - if (Light.device > 0) { - // we have a light - - uint8_t channels[LST_MAX]; - uint8_t channelsb[LST_MAX]; - char rgbcw[12] = {0}; - char rgbcwb[12] = {0}; - light_state.getChannelsRaw(channels); - light_state.getChannels(channelsb); - - // map_insert_int(vm, "_devices_present", TasmotaGlobal.devices_present); - // map_insert_int(vm, "_light_device", Light.device); - // map_insert_int(vm, "_light_subtype", Light.subtype); - // map_insert_int(vm, "_light_multi", Light.pwm_multi_channels); - // map_insert_int(vm, "_light_linked", light_controller.isCTRGBLinked()); - - if (!Light.pwm_multi_channels) { - uint32_t subtype = Light.subtype; // virtual sub-type, for SO37 128 - uint32_t chanidx = 0; // channel offset, for SO37 128 - - - if (light_controller.isCTRGBLinked() && (light_num == 0)) { - data_present = true; // valid combination - } - if (!light_controller.isCTRGBLinked()) { - if (light_num == 0) { - data_present = true; // valid combination - if (subtype > LST_RGB) { subtype = LST_RGB; } // limit to RGB - } - if ((light_num == 1) && subtype > LST_RGB) { - data_present = true; // valid combination - subtype = subtype - LST_RGB; - chanidx = 3; // skip first 3 channels - } - } - - if (data_present) { - // see ResponseLightState() - map_insert_bool(vm, "power", (bool)(Light.power & 1)); - map_insert_int(vm, "bri", light_state.getBri()); - - - if (subtype >= LST_RGB) { - uint16_t hue; - uint8_t sat, bri; - light_state.getHSB(&hue, &sat, &bri); - map_insert_int(vm, "hue", hue); - map_insert_int(vm, "sat", sat); - } - if ((LST_COLDWARM == subtype) || (LST_RGBW <= subtype)) { - map_insert_int(vm, "ct", light_state.getCT()); - } - if (subtype > LST_NONE) { - for (uint32_t i=0; i < subtype; i++) { - snprintf_P(rgbcw, sizeof(rgbcw), PSTR("%s%02X"), rgbcw, channels[i+chanidx]); - snprintf_P(rgbcwb, sizeof(rgbcwb), PSTR("%s%02X"), rgbcwb, channelsb[i+chanidx]); - } - map_insert_str(vm, "channels", rgbcw); - map_insert_str(vm, "channelsb", rgbcwb); - // map_insert_bool(vm, "gamma", Settings.light_correction); - } - } - } else { // Light.pwm_multi_channels - if ((light_num >= 0) && (light_num < LST_MAX)) { - data_present = true; - map_insert_bool(vm, "power", Light.power & (1 << light_num)); - map_insert_int(vm, "bri", Light.current_color[light_num]); - snprintf_P(rgbcw, sizeof(rgbcw), PSTR("%02X"), channels[light_num]); - snprintf_P(rgbcwb, sizeof(rgbcwb), PSTR("%02X"), channelsb[light_num]); - map_insert_str(vm, "channels", rgbcw); - map_insert_str(vm, "channelsb", rgbcwb); - } - } - - be_pop(vm, 1); - if (data_present) { - be_return(vm); // Return - } else { - be_return_nil(vm); // no data, return nil instead of empty map - } - } else { - be_return_nil(vm); - } - } - be_raise(vm, kTypeError, nullptr); - } - -} - -/*********************************************************************************************\ - * Native functions mapped to Berry functions - * - * import wire - * - * wire.getfreeheap() -> int - * -\*********************************************************************************************/ -extern "C" { - // Berry: `begintransmission(address:int) -> nil` - int32_t b_wire_begintransmission(struct bvm *vm); - int32_t b_wire_begintransmission(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted - int32_t address = be_toint(vm, 1); - Wire.beginTransmission(address); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `endtransmission([stop:bool]) -> nil` - int32_t b_wire_endtransmission(struct bvm *vm); - int32_t b_wire_endtransmission(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 0 || (top == 1 && be_isbool(vm, 1))) { // only 1 argument of type string accepted - bool stop = true; - if (top == 1) { - stop = be_tobool(vm, 1); - } - uint32_t ret = Wire.endTransmission(stop); - be_pushint(vm, ret); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `requestfrom(address:int, quantity:int [stop:bool = true]) -> nil` - int32_t b_wire_requestfrom(struct bvm *vm); - int32_t b_wire_requestfrom(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if ( (top == 2 || (top == 3 && be_isbool(vm, 3))) - && be_isint(vm, 1) && be_isint(vm, 2) ) { - int32_t address = be_toint(vm, 1); - int32_t quantity = be_toint(vm, 2); - bool stop = true; - if (top == 3) { - stop = be_tobool(vm, 3); - } - Wire.requestFrom((uint16_t)address, (uint8_t)quantity, stop); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `available() -> bool` - int32_t b_wire_available(struct bvm *vm); - int32_t b_wire_available(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 0) { - size_t available = Wire.available(); - be_pushint(vm, available); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `write(value:int | s:string) -> nil` - int32_t b_wire_write(struct bvm *vm); - int32_t b_wire_write(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && (be_isint(vm, 1) || be_isstring(vm, 1))) { - if (be_isint(vm, 1)) { - int32_t value = be_toint(vm, 1); - Wire.write(value); - } else if (be_isstring(vm, 1)) { - const char * s = be_tostring(vm, 1); - Wire.write(s); - } else { - be_return_nil(vm); - } - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `read() -> int` - int32_t b_wire_read(struct bvm *vm); - int32_t b_wire_read(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 0) { - int32_t value = Wire.read(); - be_pushint(vm, value); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - int32_t b_wire_scan(struct bvm *vm); - int32_t b_wire_scan(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 0) { - be_newobject(vm, "list"); - for (uint8_t address = 1; address <= 127; address++) { - Wire.beginTransmission(address); - int32_t error = Wire.endTransmission(); - if (0 == error) { - be_pushint(vm, address); - be_data_push(vm, -2); - be_pop(vm, 1); - } - } - be_pop(vm, 1); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `validwrite(address:int, reg:int, val:int, size:int) -> bool or nil` - int32_t b_wire_validwrite(struct bvm *vm); - int32_t b_wire_validwrite(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 4 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4)) { - uint8_t addr = be_toint(vm, 1); - uint8_t reg = be_toint(vm, 2); - uint8_t val = be_toint(vm, 3); - uint8_t size = be_toint(vm, 4); - bool ok = I2cWrite(addr, reg, val, size); - be_pushbool(vm, ok); - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } - - // Berry: `validread(address:int, reg:int, size:int) -> int or nil` - int32_t b_wire_validread(struct bvm *vm); - int32_t b_wire_validread(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 3 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) { - uint8_t addr = be_toint(vm, 1); - uint8_t reg = be_toint(vm, 2); - uint8_t size = be_toint(vm, 3); - bool ok = I2cValidRead(addr, reg, size); - if (ok) { - be_pushint(vm, i2c_buffer); - } else { - be_pushnil(vm); - } - be_return(vm); // Return - } - be_raise(vm, kTypeError, nullptr); - } -} - -/*********************************************************************************************\ - * Native functions mapped to Berry functions - * - * log(msg:string [,log_level:int]) ->nil - * -\*********************************************************************************************/ -extern "C" { - // Berry: `log(msg:string [,log_level:int]) ->nil` - // Logs the string at LOG_LEVEL_INFO (loglevel=2) - int32_t l_logInfo(struct bvm *vm); - int32_t l_logInfo(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted - const char * msg = be_tostring(vm, 1); - uint32_t log_level = LOG_LEVEL_INFO; - if (top >= 2 && be_isint(vm, 2)) { - log_level = be_toint(vm, 2); - if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; } - } - AddLog(log_level, PSTR("%s"), msg); - be_return(vm); // Return - } - be_return_nil(vm); // Return nil when something goes wrong - } - - // Berry: `getFreeHeap() -> int` - // ESP object - int32_t l_getFreeHeap(bvm *vm); - int32_t l_getFreeHeap(bvm *vm) { - be_pushint(vm, ESP.getFreeHeap()); - be_return(vm); - } -} - -// called as a replacement to Berry `print()` -void berry_log(const char * berry_buf); -void berry_log(const char * berry_buf) { - AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf); -} - - -#endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino new file mode 100644 index 000000000..f39f3cc1c --- /dev/null +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -0,0 +1,529 @@ +/* + xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include +#include + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * log(msg:string [,log_level:int]) ->nil + * + * import tasmota + * + * tasmota.getfreeheap() -> int + * tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil + * tasmota.cmd(command:string) -> string + * tasmota.getoption(index:int) -> int + * tasmota.millis([delay:int]) -> int + * tasmota.timereached(timer:int) -> bool + * tasmota.yield() -> nil + * + * tasmota.getlight([index:int = 0]) -> map + * tasmota.getpower([index:int = 0]) -> bool + * tasmota.setpower(idx:int, power:bool) -> bool or nil + * tasmota.setlight(idx:int, values:map) -> map + * +\*********************************************************************************************/ +extern "C" { + // Berry: `tasmota.publish(topic, payload [,retain]) -> nil`` + // + int32_t l_publish(struct bvm *vm); + int32_t l_publish(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 3 && be_isstring(vm, 2) && be_isstring(vm, 3)) { // 2 mandatory string arguments + if (top == 3 || (top == 4 && be_isbool(vm, 4))) { // 3rd optional argument must be bool + const char * topic = be_tostring(vm, 2); + const char * payload = be_tostring(vm, 3); + bool retain = false; + if (top == 4) { + retain = be_tobool(vm, 4); + } + strlcpy(TasmotaGlobal.mqtt_data, payload, sizeof(TasmotaGlobal.mqtt_data)); + MqttPublish(topic, retain); + be_return(vm); // Return + } + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `tasmota.cmd(command:string) -> string` + // + int32_t l_cmd(struct bvm *vm); + int32_t l_cmd(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isstring(vm, 2)) { // only 1 argument of type string accepted + const char * command = be_tostring(vm, 2); + ExecuteCommand(command, SRC_BERRY); + be_pushstring(vm, TasmotaGlobal.mqtt_data); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: tasmota.millis([delay:int]) -> int + // + int32_t l_millis(struct bvm *vm); + int32_t l_millis(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 || (top == 2 && be_isint(vm, 2))) { // only 1 argument of type string accepted + uint32_t delay = 0; + if (top == 2) { + delay = be_toint(vm, 2); + } + uint32_t ret_millis = millis() + delay; + be_pushint(vm, ret_millis); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: tasmota.getoption(index:int) -> int + // + int32_t l_getoption(struct bvm *vm); + int32_t l_getoption(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isint(vm, 2)) { + uint32_t opt = GetOption(be_toint(vm, 2)); + be_pushint(vm, opt); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: tasmota.timereached(timer:int) -> bool + // + int32_t l_timereached(struct bvm *vm); + int32_t l_timereached(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isint(vm, 2)) { // only 1 argument of type string accepted + uint32_t timer = be_toint(vm, 2); + bool reached = TimeReached(timer); + be_pushbool(vm, reached); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: tasmota.delay(timer:int) -> nil + // + int32_t l_delay(struct bvm *vm); + int32_t l_delay(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isint(vm, 2)) { // only 1 argument of type string accepted + uint32_t timer = be_toint(vm, 2); + delay(timer); + be_return_nil(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `yield() -> nil` + // ESP object + int32_t l_yield(bvm *vm); + int32_t l_yield(bvm *vm) { + optimistic_yield(10); + be_return_nil(vm); + } + + // Berry: tasmota.scaleuint(int * 5) -> int + // + int32_t l_scaleuint(struct bvm *vm); + int32_t l_scaleuint(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 6 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5) && be_isint(vm, 6)) { // only 1 argument of type string accepted + int32_t v = be_toint(vm, 2); + int32_t from1 = be_toint(vm, 3); + int32_t from2 = be_toint(vm, 4); + int32_t to1 = be_toint(vm, 5); + int32_t to2 = be_toint(vm, 6); + + int32_t ret = changeUIntScale(v, from1, from2, to1, to2); + be_pushint(vm, ret); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + int32_t l_respCmnd(bvm *vm); + int32_t l_respCmnd(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2) { + const char *msg = be_tostring(vm, 2); + Response_P("%s", msg); + be_return_nil(vm); // Return nil when something goes wrong + } + be_raise(vm, kTypeError, nullptr); + } + + int32_t l_respCmndStr(bvm *vm); + int32_t l_respCmndStr(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2) { + const char *msg = be_tostring(vm, 2); + ResponseCmndChar(msg); + be_return_nil(vm); // Return nil when something goes wrong + } + be_raise(vm, kTypeError, nullptr); + } + + int32_t l_respCmndDone(bvm *vm); + int32_t l_respCmndDone(bvm *vm) { + ResponseCmndDone(); + be_return_nil(vm); + } + + int32_t l_respCmndError(bvm *vm); + int32_t l_respCmndError(bvm *vm) { + ResponseCmndError(); + be_return_nil(vm); + } + + int32_t l_respCmndFailed(bvm *vm); + int32_t l_respCmndFailed(bvm *vm) { + ResponseCmndFailed(); + be_return_nil(vm); + } + + // update XdrvMailbox.command with actual command + int32_t l_resolveCmnd(bvm *vm); + int32_t l_resolveCmnd(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isstring(vm, 2)) { + const char *msg = be_tostring(vm, 2); + strlcpy(XdrvMailbox.command, msg, CMDSZ); + be_return_nil(vm); // Return nil when something goes wrong + } + be_raise(vm, kTypeError, nullptr); + } + + // push the light status object on the vm stack + void push_getlight(bvm *vm, uint32_t light_num) { + bool data_present = false; // do we have relevant data + be_newobject(vm, "map"); + // check if the light exist + // TasmotaGlobal.devices_present + // Light.device + // Light.subtype + // Light.pwm_multi_channels + // light_controller.isCTRGBLinked() + + if (Light.device > 0) { + // we have a light + + uint8_t channels[LST_MAX]; + char s_rgb[8] = {0}; // RGB raw levels + light_controller.calcLevels(channels); + uint8_t bri = light_state.getBri(); + + // map_insert_int(vm, "_devices_present", TasmotaGlobal.devices_present); + // map_insert_int(vm, "_light_device", Light.device); + // map_insert_int(vm, "_light_subtype", Light.subtype); + // map_insert_int(vm, "_light_multi", Light.pwm_multi_channels); + // map_insert_int(vm, "_light_linked", light_controller.isCTRGBLinked()); + + if (!Light.pwm_multi_channels) { + uint32_t subtype = Light.subtype; // virtual sub-type, for SO37 128 + uint32_t chanidx = 0; // channel offset, for SO37 128 + + + if (light_controller.isCTRGBLinked() && (light_num == 0)) { + data_present = true; // valid combination + if (subtype >= LST_RGBW) { + map_insert_str(vm, "colormode", (light_state.getColorMode() & LCM_RGB ? "rgb" : "ct")); + } + } + if (!light_controller.isCTRGBLinked()) { + if (light_num == 0) { + data_present = true; // valid combination + if (subtype > LST_RGB) { subtype = LST_RGB; } // limit to RGB + bri = light_state.getBriRGB(); + } + if ((light_num == 1) && subtype > LST_RGB) { + data_present = true; // valid combination + subtype = subtype - LST_RGB; + chanidx = 3; // skip first 3 channels + bri = light_state.getBriCT(); + } + } + + if (data_present) { + // see ResponseLightState() + map_insert_bool(vm, "power", bitRead(TasmotaGlobal.power, light_num)); + map_insert_int(vm, "bri", bri); + + if (subtype >= LST_RGB) { + uint16_t hue; + uint8_t sat, bri; + light_state.getHSB(&hue, &sat, &bri); + map_insert_int(vm, "hue", hue); + map_insert_int(vm, "sat", sat); + } + if ((LST_COLDWARM == subtype) || (LST_RGBW <= subtype)) { + map_insert_int(vm, "ct", light_state.getCT()); + } + if (subtype >= LST_RGB) { + snprintf(s_rgb, sizeof(s_rgb), PSTR("%02X%02X%02X"), channels[0], channels[1], channels[2]); + map_insert_str(vm, "rgb", s_rgb); + } + if (subtype > LST_NONE) { + map_insert_list_uint8(vm, "channels", &channels[chanidx], subtype); + } + } + } else { // Light.pwm_multi_channels + if ((light_num >= 0) && (light_num < LST_MAX)) { + data_present = true; + map_insert_bool(vm, "power", Light.power & (1 << light_num)); + map_insert_int(vm, "bri", Light.current_color[light_num]); + map_insert_list_uint8(vm, "channels", &channels[light_num], 1); + } + } + + be_pop(vm, 1); + if (!data_present) { + be_pop(vm, 1); + be_pushnil(vm); + } + } else { + be_pop(vm, 1); + be_pushnil(vm); + } + } + + // get light + int32_t l_getlight(bvm *vm); + int32_t l_getlight(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 || (top == 2 && be_isint(vm, 2))) { + int32_t light_num = 0; + if (top > 0) { + light_num = be_toint(vm, 2); + } + push_getlight(vm, light_num); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // set light + int32_t l_setlight(bvm *vm); + int32_t l_setlight(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 2 && be_isinstance(vm, 2) && (top != 3 || be_isint(vm, 3))) { + int32_t idx = 0; + if (top >= 3) { + idx = be_toint(vm, 3); + be_pop(vm, 1); // remove last argument to have the map at the top of stack + } + + // power + if (map_find(vm, "power")) { + bool power = be_tobool(vm, -1); + bool current_power = bitRead(TasmotaGlobal.power, idx); + if (power != current_power) { // only send command if needed + ExecuteCommandPower(Light.device + idx, (power) ? POWER_ON : POWER_OFF, SRC_BERRY); + } + } + be_pop(vm, 1); + + // ct + if (map_find(vm, "ct")) { + int32_t ct = be_toint(vm, -1); + light_controller.changeCTB(ct, light_state.getBriCT()); + } + be_pop(vm, 1); + + // hue + if (map_find(vm, "hue")) { + int32_t hue = be_toint(vm, -1); + uint8_t sat; + uint8_t bri; + light_state.getHSB(nullptr, &sat, &bri); + light_controller.changeHSB(hue, sat, bri); + } + be_pop(vm, 1); + + // sat + if (map_find(vm, "sat")) { + int32_t sat = be_toint(vm, -1); + uint16_t hue; + uint8_t bri; + light_state.getHSB(&hue, nullptr, &bri); + light_controller.changeHSB(hue, sat, bri); + } + be_pop(vm, 1); + + // rgb + if (map_find(vm, "rgb")) { + const char * rgb_s = be_tostring(vm, -1); + SBuffer buf = SBuffer::SBufferFromHex(rgb_s, strlen(rgb_s)); + uint8_t channels[LST_MAX] = {}; + memcpy(channels, buf.buf(), buf.len() > LST_MAX ? LST_MAX : buf.len()); + bool on = false; // if all are zero, then only set power off + for (uint32_t i = 0; i < LST_MAX; i++) { + if (channels[i] != 0) { on = true; } + } + if (on) { + light_controller.changeChannels(channels); + } else { + ExecuteCommandPower(idx + 1, POWER_OFF, SRC_BERRY); + } + } + be_pop(vm, 1); + + // channels + if (map_find(vm, "channels")) { + if (be_isinstance(vm, -1)) { + be_getbuiltin(vm, "list"); // add "list" class + if (be_isderived(vm, -2)) { + be_pop(vm, 1); // remove "list" class from top + int32_t list_size = get_list_size(vm); + // AddLog(LOG_LEVEL_INFO, "Instance is list size = %d", list_size); + + uint8_t channels[LST_MAX] = {}; // initialized with all zeroes + if (list_size > LST_MAX) { list_size = LST_MAX; } // no more than 5 channels, no need to test for positive, any negative will be discarded by loop + for (uint32_t i = 0; i < list_size; i++) { + // be_dumpstack(vm); + get_list_item(vm, i); + // be_dumpstack(vm); + int32_t val = be_toint(vm, -1); + be_pop(vm, 1); // remove result from stack + channels[i] = to_u8(val); + + bool on = false; // if all are zero, then only set power off + for (uint32_t i = 0; i < LST_MAX; i++) { + if (channels[i] != 0) { on = true; } + } + if (on) { + light_controller.changeChannels(channels); + } else { + ExecuteCommandPower(idx + 1, POWER_OFF, SRC_BERRY); + } + } + } else { + be_pop(vm, 1); // remove "list" class from top + } + } + } + be_pop(vm, 1); + + // bri is done after channels and rgb + // bri + if (map_find(vm, "bri")) { + int32_t bri = be_toint(vm, -1); + light_controller.changeBri(bri); + } + be_pop(vm, 1); + + push_getlight(vm, idx); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } // TODO + + // get power + int32_t l_getpower(bvm *vm); + int32_t l_getpower(bvm *vm) { + be_newobject(vm, "list"); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + be_pushbool(vm, bitRead(TasmotaGlobal.power, i)); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); + be_return(vm); // Return + } + + int32_t l_setpower(bvm *vm); + int32_t l_setpower(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 3 && be_isint(vm, 2) && be_isbool(vm, 3)) { + int32_t idx = be_toint(vm, 2); + bool power = be_tobool(vm, 3); + if ((idx >= 0) && (idx < TasmotaGlobal.devices_present)) { + ExecuteCommandPower(idx + 1, (power) ? POWER_ON : POWER_OFF, SRC_BERRY); + be_pushbool(vm, power); + be_return(vm); // Return + } else { + be_return_nil(vm); + } + } + be_raise(vm, kTypeError, nullptr); + } + +} + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * log(msg:string [,log_level:int]) ->nil + * +\*********************************************************************************************/ +extern "C" { + // Berry: `log(msg:string [,log_level:int]) ->nil` + // Logs the string at LOG_LEVEL_INFO (loglevel=2) + int32_t l_logInfo(struct bvm *vm); + int32_t l_logInfo(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted + const char * msg = be_tostring(vm, 1); + uint32_t log_level = LOG_LEVEL_INFO; + if (top >= 2 && be_isint(vm, 2)) { + log_level = be_toint(vm, 2); + if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; } + } + AddLog(log_level, PSTR("%s"), msg); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `getFreeHeap() -> int` + // ESP object + int32_t l_getFreeHeap(bvm *vm); + int32_t l_getFreeHeap(bvm *vm) { + be_pushint(vm, ESP.getFreeHeap()); + be_return(vm); + } + + // Berry: `save(file:string, f:closure) -> bool` + int32_t l_save(struct bvm *vm); + int32_t l_save(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted + const char *fname = be_tostring(vm, 1); + int32_t ret = be_savecode(vm, fname); + be_pushint(vm, ret); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } +} + +// called as a replacement to Berry `print()` +void berry_log(const char * berry_buf); +void berry_log(const char * berry_buf) { + AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf); +} + + +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_3_berry_wire.ino b/tasmota/xdrv_52_3_berry_wire.ino new file mode 100644 index 000000000..a5fccb44e --- /dev/null +++ b/tasmota/xdrv_52_3_berry_wire.ino @@ -0,0 +1,245 @@ +/* + xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include +#include + +// read the `_bus` attribute and return `Wire` or `Wire1` +TwoWire & getWire(bvm *vm); +TwoWire & getWire(bvm *vm) { + be_getmember(vm, 1, "_bus"); + int32_t bus = be_toint(vm, -1); + be_pop(vm, 1); + if (0 == bus) { + return Wire; + } else { + return Wire1; + } +} +int32_t getBus(bvm *vm); +int32_t getBus(bvm *vm) { + be_getmember(vm, 1, "_bus"); + int32_t bus = be_toint(vm, -1); + be_pop(vm, 1); + return bus; +} + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * import wire + * + * wire.getfreeheap() -> int + * +\*********************************************************************************************/ +extern "C" { +#ifdef USE_I2C + // Berry: `init([bus:int = 0]) -> nil + int32_t b_wire_init(struct bvm *vm); + int32_t b_wire_init(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + int32_t bus = 0; + if (top > 1 && be_isint(vm, 2)) { + bus = be_toint(vm, 2); + if (bus < 0) { bus = 0; } + if (bus > 1) { bus = 1; } + } + // store bus in instance + be_pushint(vm, bus); + be_setmember(vm, 1, "_bus"); + be_return_nil(vm); + } + + // Berry: `begintransmission(address:int) -> nil` + int32_t b_wire_begintransmission(struct bvm *vm); + int32_t b_wire_begintransmission(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + TwoWire & myWire = getWire(vm); + if (top == 2 && be_isint(vm, 2)) { // only 1 argument of type string accepted + int32_t address = be_toint(vm, 2); + myWire.beginTransmission(address); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `endtransmission([stop:bool]) -> nil` + int32_t b_wire_endtransmission(struct bvm *vm); + int32_t b_wire_endtransmission(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + TwoWire & myWire = getWire(vm); + if (top == 1 || (top == 2 && be_isbool(vm, 2))) { // only 1 argument of type string accepted + bool stop = true; + if (top == 1) { + stop = be_tobool(vm, 2); + } + uint32_t ret = myWire.endTransmission(stop); + be_pushint(vm, ret); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `requestfrom(address:int, quantity:int [stop:bool = true]) -> nil` + int32_t b_wire_requestfrom(struct bvm *vm); + int32_t b_wire_requestfrom(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + TwoWire & myWire = getWire(vm); + if ( (top == 3 || (top == 4 && be_isbool(vm, 4))) + && be_isint(vm, 2) && be_isint(vm, 3) ) { + int32_t address = be_toint(vm, 2); + int32_t quantity = be_toint(vm, 3); + bool stop = true; + if (top == 4) { + stop = be_tobool(vm, 4); + } + myWire.requestFrom((uint16_t)address, (uint8_t)quantity, stop); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `available() -> bool` + int32_t b_wire_available(struct bvm *vm); + int32_t b_wire_available(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + TwoWire & myWire = getWire(vm); + if (top == 1) { + size_t available = myWire.available(); + be_pushint(vm, available); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `write(value:int | s:string) -> nil` + int32_t b_wire_write(struct bvm *vm); + int32_t b_wire_write(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + TwoWire & myWire = getWire(vm); + if (top == 2 && (be_isint(vm, 2) || be_isstring(vm, 2))) { + if (be_isint(vm, 2)) { + int32_t value = be_toint(vm, 2); + myWire.write(value); + } else if (be_isstring(vm, 2)) { + const char * s = be_tostring(vm, 1); + myWire.write(s); + } else { + be_return_nil(vm); + } + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `read() -> int` + int32_t b_wire_read(struct bvm *vm); + int32_t b_wire_read(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + TwoWire & myWire = getWire(vm); + if (top == 1) { + int32_t value = myWire.read(); + be_pushint(vm, value); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + int32_t b_wire_scan(struct bvm *vm); + int32_t b_wire_scan(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + TwoWire & myWire = getWire(vm); + if (top == 1) { + be_newobject(vm, "list"); + for (uint8_t address = 1; address <= 127; address++) { + myWire.beginTransmission(address); + int32_t error = myWire.endTransmission(); + if (0 == error) { + be_pushint(vm, address); + be_data_push(vm, -2); + be_pop(vm, 1); + } + } + be_pop(vm, 1); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `validwrite(address:int, reg:int, val:int, size:int) -> bool or nil` + int32_t b_wire_validwrite(struct bvm *vm); + int32_t b_wire_validwrite(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + int32_t bus = getBus(vm); + if (top == 5 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5)) { + uint8_t addr = be_toint(vm, 2); + uint8_t reg = be_toint(vm, 3); + uint8_t val = be_toint(vm, 4); + uint8_t size = be_toint(vm, 5); + bool ok = I2cWrite(addr, reg, val, size, bus); + be_pushbool(vm, ok); + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `validread(address:int, reg:int, size:int) -> int or nil` + int32_t b_wire_validread(struct bvm *vm); + int32_t b_wire_validread(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + int32_t bus = getBus(vm); + if (top == 4 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4)) { + uint8_t addr = be_toint(vm, 2); + uint8_t reg = be_toint(vm, 3); + uint8_t size = be_toint(vm, 4); + bool ok = I2cValidRead(addr, reg, size); // TODO + if (ok) { + be_pushint(vm, i2c_buffer); + } else { + be_pushnil(vm); + } + be_return(vm); // Return + } + be_raise(vm, kTypeError, nullptr); + } +#else // USE_I2C + // + int32_t b_wire_i2cmissing(struct bvm *vm); + int32_t b_wire_i2cmissing(struct bvm *vm) { + be_raise(vm, "feature_error", "I2C is not enabled, use '#define USE_I2C'"); + } + + // define weak aliases + int32_t b_wire_init(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_begintransmission(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_endtransmission(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_requestfrom(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_available(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_write(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_read(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_scan(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_validwrite(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); + int32_t b_wire_validread(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing"))); +#endif // USE_I2C +} + +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino index b9575da81..83a3895e7 100644 --- a/tasmota/xdrv_52_7_berry_embedded.ino +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -32,60 +32,33 @@ const char berry_prog[] = //"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end " //"log(\"foobar\") " + // create a 'ntv' module to allow functions to be registered in a safe namespace + "ntv = module('ntv') " + // auto-import modules // // import alias - "import wire " + "import energy " // Phase 1 - // Prepare the super class that will be eventually in Flash - "class Tasmota_ntv " - "var _op, _operators, _rules, _timers, _cmd " - - // Map all native functions to methods - // Again, this will be eventually pre-compiled - "var getfreeheap, publish, cmd, getoption, millis, timereached, yield " - "var respcmnd, respcmndstr, respcmnd_done, respcmnd_error, respcmnd_failed, resolvecmnd " - "var getlight " - "def init_ntv() " - "import tasmota_ntv " - "self.getfreeheap = tasmota_ntv.getfreeheap " - "self.publish = tasmota_ntv.publish " - "self.cmd = tasmota_ntv.cmd " - "self.getoption = tasmota_ntv.getoption " - "self.millis = tasmota_ntv.millis " - "self.timereached = tasmota_ntv.timereached " - "self.yield = tasmota_ntv.yield " - "self._operators = tasmota_ntv._operators " - - "self.respcmnd = tasmota_ntv.respcmnd " - "self.respcmndstr = tasmota_ntv.respcmndstr " - "self.respcmnd_done = tasmota_ntv.respcmnd_done " - "self.respcmnd_error = tasmota_ntv.respcmnd_error " - "self.respcmnd_failed = tasmota_ntv.respcmnd_failed " - "self.resolvecmnd = tasmota_ntv.resolvecmnd " - - "self.getlight = tasmota_ntv.getlight " - "end " - + "class Tasmota: Tasmota_ntv " + // for now the variables are built, need to find a way to push in Flash "def init() " - "self._op = [ " - "['==', /s1,s2-> str(s1) == str(s2)]," - "['!==',/s1,s2-> str(s1) != str(s2)]," - "['=', /f1,f2-> real(f1) == real(f2)]," - "['!=', /f1,f2-> real(f1) != real(f2)]," - "['>=', /f1,f2-> real(f1) >= real(f2)]," - "['<=', /f1,f2-> real(f1) <= real(f2)]," - "['>', /f1,f2-> real(f1) > real(f2)]," - "['<', /f1,f2-> real(f1) < real(f2)]," + "self._op = ['==', '!==', '=', '!=', '>=', '<=', '>', '<'] " + "self._opf = [ " + "/s1,s2-> str(s1) == str(s2)," + "/s1,s2-> str(s1) != str(s2)," + "/f1,f2-> real(f1) == real(f2)," + "/f1,f2-> real(f1) != real(f2)," + "/f1,f2-> real(f1) >= real(f2)," + "/f1,f2-> real(f1) <= real(f2)," + "/f1,f2-> real(f1) > real(f2)," + "/f1,f2-> real(f1) < real(f2)," "] " + "self._operators = \"=<>!|\" " "self._rules = {} " "self._timers = [] " "self._cmd = {} " - "self.init_ntv() " "end " - "end " - - "class Tasmota: Tasmota_ntv " // add `charsinstring(s:string,c:string) -> int`` // looks for any char in c, and return the position of the first chat // or -1 if not found @@ -125,10 +98,11 @@ const char berry_prog[] = "var op_left = op_split[0] " "var op_rest = op_split[1] " // # iterate through operators - "for op: self._op " - "if string.find(op_rest,op[0]) == 0 " - "var op_func = op[1] " - "var op_right = string.split(op_rest,size(op[0]))[1] " + "for i: 0..size(self._op)-1 " + "var op = self._op[i] " + "if string.find(op_rest,op) == 0 " + "var op_func = self._opf[i] " + "var op_right = string.split(op_rest,size(op))[1] " "return [op_left,op_func,op_right] " "end " "end " @@ -137,7 +111,6 @@ const char berry_prog[] = "end " // Rules trigger if match. return true if match, false if not - // Note: condition is not yet managed "def try_rule(ev, rule, f) " "import string " "var rl_list = self.find_op(rule) " @@ -229,6 +202,8 @@ const char berry_prog[] = // Instantiate tasmota object "tasmota = Tasmota() " + "wire = Wire(0) " + "wire1 = Wire(1) " // Not sure how to run call methods from C "def _exec_rules(e) return tasmota.exec_rules(e) end " @@ -253,19 +228,30 @@ const char berry_prog[] = "var c = compile(f,'file') " // save the compiled bytecode "if !native " - "save(f+'c', c) " + "try " + "save(f+'c', c) " + "except .. as e " + "log(string.format('BRY: could not save compiled file %s (%s)',f+'c',e)) " + "end " "end " // call the compiled code "c() " + "log(string.format(\"BRY: sucessfully loaded '%s'\",f)) " "except .. as e " - "log(string.format(\"BRY: could not load file '%s' - %s\",f,e)) " + "raise \"io_error\",string.format(\"Could not load file '%s'\",f) " "end " "end " // try to load "/autoexec.be" // "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end " - - // Wire ; +const char berry_autoexec[] = + // load "autoexec.be" using import, which loads either .be or .bec file + "try " + "load('autoexec.be') " + "except .. " + "log(\"BRY: No 'autoexec.be' file\") " + "end " + ; #endif // USE_BERRY diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index fbbda679e..976e9e601 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -36,8 +36,7 @@ class BerrySupport { public: bvm *vm = nullptr; // berry vm bool rules_busy = false; // are we already processing rules, avoid infinite loop - const char *fname = nullptr; // name of berry function to call - int32_t fret = 0; + bool autoexec_done = false; // do we still need to load 'autoexec.be' }; BerrySupport berry; @@ -59,10 +58,6 @@ void checkBeTop(void) { * \*********************************************************************************************/ // // call a function (if exists) of type void -> void -// void callBerryFunctionVoid_berry(const char * fname) { -// berry.fret = 0; -// callBerryFunctionVoid(berry.fname); -// } bool callBerryRule(void) { if (berry.rules_busy) { return false; } @@ -244,7 +239,7 @@ void BrReset(void) { ret_code2 = be_pcall(berry.vm, 0); if (ret_code1 != 0) { AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); - be_pop(berry.vm, 2); + be_pop(berry.vm, 1); break; } // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm)); @@ -268,6 +263,32 @@ void BrReset(void) { } } + +void BrAutoexec(void) { + if (berry.vm == nullptr) { return; } + + int32_t ret_code1, ret_code2; + bool berry_init_ok = false; + + // load 'autoexec.be' or 'autoexec.bec' + ret_code1 = be_loadstring(berry.vm, berry_autoexec); + // be_dumpstack(berry.vm); + if (ret_code1 != 0) { + be_pop(berry.vm, 2); + return; + } + ret_code2 = be_pcall(berry.vm, 0); + // be_dumpstack(berry.vm); + if (ret_code1 != 0) { + // AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); + be_pop(berry.vm, 1); + return; + } + // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm)); + be_pop(berry.vm, 1); + // be_dumpstack(berry.vm); +} + /*********************************************************************************************\ * Tasmota Commands \*********************************************************************************************/ @@ -304,11 +325,11 @@ void CmndBrRun(void) { // AddLog(LOG_LEVEL_INFO, "run: type(2)=%s", be_typename(berry.vm, 2)); // code taken from REPL, look first at top, and if nil, look at return value - if (!be_isnil(berry.vm, 1)) { + // if (!be_isnil(berry.vm, 1)) { ret_val = be_tostring(berry.vm, 1); - } else { - ret_val = be_tostring(berry.vm, 2); - } + // } else { + // ret_val = be_tostring(berry.vm, 2); + // } Response_P("{\"" D_PRFX_BR "\":\"%s\"}", EscapeJSONString(ret_val).c_str()); // can't use XdrvMailbox.command as it may have been overwritten by subcommand be_pop(berry.vm, 1); } else { @@ -340,6 +361,12 @@ bool Xdrv52(uint8_t function) case FUNC_INIT: BrReset(); break; + case FUNC_LOOP: + if (!berry.autoexec_done) { + BrAutoexec(); + berry.autoexec_done = true; + } + break; case FUNC_EVERY_50_MSECOND: callBerryFunctionVoid(PSTR("_run_deferred")); break; @@ -383,8 +410,6 @@ bool Xdrv52(uint8_t function) case FUNC_BUTTON_PRESSED: break; - case FUNC_LOOP: - break; } return result;