Merge pull request #11336 from s-hadinger/berry_mar_14

Berry upgrade
This commit is contained in:
s-hadinger 2021-03-13 23:23:56 +01:00 committed by GitHub
commit 2d758d32ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 2222 additions and 965 deletions

View File

@ -16,9 +16,7 @@ All notable changes to this project will be documented in this file.
- Crash protection in ext_vnsprintf_P (#11202) - Crash protection in ext_vnsprintf_P (#11202)
- Extent compile time SetOptions support (#11204) - Extent compile time SetOptions support (#11204)
- ESP32 Extent BLE (#11212) - ESP32 Extent BLE (#11212)
- ESP32 support for WS2812 hardware driver via RMT or I2S - ESP32 support for WS2812 hardware driver via RMT or I2S
- ESP32 support for secondary I2C controller - ESP32 support for secondary I2C controller

View File

@ -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_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_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_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_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_pop;
extern const bcstring be_const_str_int; 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_keys;
extern const bcstring be_const_str_setitem; extern const bcstring be_const_str_elif;
extern const bcstring be_const_str_def; extern const bcstring be_const_str_item;
extern const bcstring be_const_str_except; extern const bcstring be_const_str_push;
extern const bcstring be_const_str_classname; extern const bcstring be_const_str_concat;
extern const bcstring be_const_str_isinstance; extern const bcstring be_const_str_traceback;
extern const bcstring be_const_str_cosh; 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;

View File

@ -1,165 +1,172 @@
be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_asin); be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_false);
be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_list); be_define_const_str(false, "false", 184981848u, 62, 5, &be_const_str_raise);
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(raise, "raise", 1593437475u, 70, 5, NULL); 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(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_dot_p);
be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_item); be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_calldepth);
be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_reverse); be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, NULL);
be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin); be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str_break);
be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_super); be_define_const_str(break, "break", 3378807160u, 58, 5, NULL);
be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try); 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(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(return, "return", 2246981567u, 60, 6, NULL);
be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_false); be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_hex);
be_define_const_str(false, "false", 184981848u, 62, 5, NULL); be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_resize);
be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_as);
be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); be_define_const_str(as, "as", 1579491469u, 67, 2, NULL);
be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_true); be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_codedump);
be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_cosh);
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(cosh, "cosh", 4099687964u, 0, 4, NULL); 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[] = { 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, (const bstring *)&be_const_str_acos,
NULL, (const bstring *)&be_const_str_fromstring,
(const bstring *)&be_const_str_int,
NULL,
(const bstring *)&be_const_str_iter,
(const bstring *)&be_const_str_opt_eq, (const bstring *)&be_const_str_opt_eq,
(const bstring *)&be_const_str_floor,
(const bstring *)&be_const_str_find, (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, (const bstring *)&be_const_str_opt_add,
NULL, NULL,
(const bstring *)&be_const_str_classof, (const bstring *)&be_const_str_deg,
(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_allocated, (const bstring *)&be_const_str_allocated,
(const bstring *)&be_const_str_attrdump, (const bstring *)&be_const_str_reverse,
(const bstring *)&be_const_str_for, (const bstring *)&be_const_str_assert,
(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_imax, (const bstring *)&be_const_str_imax,
(const bstring *)&be_const_str_codedump, (const bstring *)&be_const_str_opt_neq,
(const bstring *)&be_const_str_def, (const bstring *)&be_const_str___upper__,
(const bstring *)&be_const_str_classname, (const bstring *)&be_const_str_abs,
(const bstring *)&be_const_str_cosh (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 = { static const struct bconststrtab m_const_string_table = {
.size = 45, .size = 47,
.count = 90, .count = 95,
.table = m_string_table .table = m_string_table
}; };

View File

@ -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
);

View File

@ -1,31 +1,32 @@
#include "be_constobj.h" #include "be_constobj.h"
static be_define_const_map_slots(be_class_list_map) { static be_define_const_map_slots(be_class_list_map) {
{ be_const_key(pop, -1), be_const_func(m_pop) }, { be_const_key(concat, -1), be_const_func(m_concat) },
{ be_const_key(reverse, -1), be_const_func(m_reverse) },
{ be_const_key(push, -1), be_const_func(m_push) }, { be_const_key(push, -1), be_const_func(m_push) },
{ be_const_key(init, -1), be_const_func(m_init) }, { be_const_key(insert, 1), be_const_func(m_insert) },
{ be_const_key(copy, 8), be_const_func(m_copy) }, { be_const_key(find, -1), be_const_func(m_find) },
{ be_const_key(opt_connect, 13), be_const_func(m_connect) }, { be_const_key(remove, 9), be_const_func(m_remove) },
{ 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(clear, -1), be_const_func(m_clear) }, { be_const_key(clear, -1), be_const_func(m_clear) },
{ be_const_key(opt_eq, 3), be_const_func(m_equal) }, { be_const_key(size, -1), be_const_func(m_size) },
{ be_const_key(insert, 12), be_const_func(m_insert) }, { be_const_key(resize, 13), be_const_func(m_resize) },
{ be_const_key(concat, 2), be_const_func(m_concat) }, { be_const_key(copy, -1), be_const_func(m_copy) },
{ be_const_key(dot_p, -1), be_const_int(0) }, { be_const_key(pop, -1), be_const_func(m_pop) },
{ be_const_key(iter, 18), be_const_func(m_iter) }, { 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( static be_define_const_map(
be_class_list_map, be_class_list_map,
20 21
); );
BE_EXPORT_VARIABLE be_define_const_class( BE_EXPORT_VARIABLE be_define_const_class(

View File

@ -1,37 +1,39 @@
#include "be_constobj.h" #include "be_constobj.h"
static be_define_const_map_slots(m_builtin_map) { static be_define_const_map_slots(m_builtin_map) {
{ be_const_key(map, 11), be_const_int(10) }, { be_const_key(print, 19), be_const_int(15) },
{ be_const_key(str, 14), be_const_int(18) }, { be_const_key(isinstance, -1), be_const_int(8) },
{ be_const_key(int, -1), be_const_int(6) }, { be_const_key(classname, -1), be_const_int(3) },
{ be_const_key(type, -1), be_const_int(20) }, { be_const_key(module, -1), be_const_int(12) },
{ be_const_key(assert, -1), be_const_int(1) }, { be_const_key(size, -1), be_const_int(18) },
{ be_const_key(issubclass, -1), be_const_int(8) }, { be_const_key(type, 9), be_const_int(21) },
{ be_const_key(number, 7), be_const_int(12) }, { be_const_key(compile, -1), be_const_int(5) },
{ be_const_key(compile, 8), be_const_int(4) }, { be_const_key(open, -1), be_const_int(14) },
{ be_const_key(module, 18), be_const_int(11) }, { be_const_key(real, -1), be_const_int(17) },
{ 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(__iterator__, -1), be_const_int(0) }, { be_const_key(__iterator__, -1), be_const_int(0) },
{ be_const_key(real, 10), be_const_int(16) }, { be_const_key(super, -1), be_const_int(20) },
{ be_const_key(list, 20), be_const_int(9) }, { be_const_key(issubclass, -1), be_const_int(9) },
{ be_const_key(isinstance, -1), be_const_int(7) }, { be_const_key(classof, -1), be_const_int(4) },
{ be_const_key(range, -1), be_const_int(15) }, { be_const_key(map, 8), be_const_int(11) },
{ be_const_key(size, -1), be_const_int(17) }, { be_const_key(int, 2), be_const_int(7) },
{ be_const_key(classname, -1), be_const_int(2) }, { be_const_key(input, 3), be_const_int(6) },
{ be_const_key(print, -1), be_const_int(14) }, { 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( static be_define_const_map(
m_builtin_map, m_builtin_map,
21 22
); );
static const bvalue __vlist_array[] = { static const bvalue __vlist_array[] = {
be_const_func(l_iterator), be_const_func(l_iterator),
be_const_func(l_assert), be_const_func(l_assert),
be_const_class(be_class_bytes),
be_const_func(l_classname), be_const_func(l_classname),
be_const_func(l_classof), be_const_func(l_classof),
be_const_func(l_compile), be_const_func(l_compile),
@ -56,5 +58,5 @@ static const bvalue __vlist_array[] = {
static be_define_const_vector( static be_define_const_vector(
m_builtin_vector, m_builtin_vector,
__vlist_array, __vlist_array,
21 22
); );

View File

@ -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"
);

View File

@ -313,6 +313,7 @@ void be_load_baselib(bvm *vm)
extern const bclass be_class_list; extern const bclass be_class_list;
extern const bclass be_class_map; extern const bclass be_class_map;
extern const bclass be_class_range; extern const bclass be_class_range;
extern const bclass be_class_bytes;
extern int be_nfunc_open(bvm *vm); extern int be_nfunc_open(bvm *vm);
/* @const_object_info_begin /* @const_object_info_begin
vartab m_builtin (scope: local) { vartab m_builtin (scope: local) {
@ -337,6 +338,7 @@ vartab m_builtin (scope: local) {
list, class(be_class_list) list, class(be_class_list)
map, class(be_class_map) map, class(be_class_map)
range, class(be_class_range) range, class(be_class_range)
bytes, class(be_class_bytes)
} }
@const_object_info_end */ @const_object_info_end */
#include "../generate/be_fixed_m_builtin.h" #include "../generate/be_fixed_m_builtin.h"

View File

@ -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 <string.h>
#include <ctype.h>
#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<len; i++) {
if (buf_get1(buf1, i) != buf_get1(buf2, i)) { return bfalse; }
}
return btrue;
}
static uint8_t asc2byte(char chr) {
uint8_t rVal = 0;
if (isdigit(chr)) { rVal = chr - '0'; }
else if (chr >= '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

View File

@ -13,6 +13,9 @@ extern void be_load_maplib(bvm *vm);
extern void be_load_rangelib(bvm *vm); extern void be_load_rangelib(bvm *vm);
extern void be_load_filelib(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) void be_loadlibs(bvm *vm)
{ {
be_load_baselib(vm); be_load_baselib(vm);
@ -21,5 +24,8 @@ void be_loadlibs(bvm *vm)
be_load_maplib(vm); be_load_maplib(vm);
be_load_rangelib(vm); be_load_rangelib(vm);
be_load_filelib(vm); be_load_filelib(vm);
be_load_byteslib(vm);
#endif #endif
be_load_tasmota_ntvlib(vm);
be_load_wirelib(vm);
} }

View File

@ -207,6 +207,19 @@ static int m_item(bvm *vm)
be_return_nil(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) static int m_setitem(bvm *vm)
{ {
be_getmember(vm, 1, ".p"); be_getmember(vm, 1, ".p");
@ -291,13 +304,15 @@ static int m_merge(bvm *vm)
{ {
int argc = be_top(vm); int argc = be_top(vm);
if (argc >= 2) { if (argc >= 2) {
be_newobject(vm, "list"); /* stack contains instance and .p */
be_getmember(vm, 1, ".p"); be_getmember(vm, 1, ".p");
be_data_merge(vm, -2);
be_getmember(vm, 2, ".p"); be_getmember(vm, 2, ".p");
if (!be_islist(vm, -1)) { if (!be_islist(vm, -1)) {
be_raise(vm, "type_error", "operand must be a list"); be_raise(vm, "type_error", "operand must be a list");
} }
be_data_merge(vm, -2); be_data_merge(vm, -3);
be_pop(vm, argc + 1); be_pop(vm, 3);
} }
be_return(vm); /* return self */ be_return(vm); /* return self */
} }
@ -423,6 +438,7 @@ void be_load_listlib(bvm *vm)
{ "insert", m_insert }, { "insert", m_insert },
{ "remove", m_remove }, { "remove", m_remove },
{ "item", m_item }, { "item", m_item },
{ "find", m_find },
{ "setitem", m_setitem }, { "setitem", m_setitem },
{ "size", m_size }, { "size", m_size },
{ "resize", m_resize }, { "resize", m_resize },
@ -450,6 +466,7 @@ class be_class_list (scope: global, name: list) {
insert, func(m_insert) insert, func(m_insert)
remove, func(m_remove) remove, func(m_remove)
item, func(m_item) item, func(m_item)
find, func(m_find)
setitem, func(m_setitem) setitem, func(m_setitem)
size, func(m_size) size, func(m_size)
resize, func(m_resize) resize, func(m_resize)

View File

@ -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(bvm *vm);
BERRY_API void be_module_path_set(bvm *vm, const char *path); 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 */ /* registry operation */
BERRY_API int be_register(bvm *vm, int index); BERRY_API int be_register(bvm *vm, int index);
BERRY_API void be_unregister(bvm *vm, int id); BERRY_API void be_unregister(bvm *vm, int id);

View File

@ -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

View File

@ -20,8 +20,9 @@ be_extern_native_module(debug);
be_extern_native_module(gc); be_extern_native_module(gc);
/* Tasmota specific */ /* Tasmota specific */
be_extern_native_module(tasmota_ntv); // be_extern_native_module(tasmota_ntv);
be_extern_native_module(wire); be_extern_native_module(wire);
be_extern_native_module(energy);
/* user-defined modules declare start */ /* user-defined modules declare start */
@ -56,8 +57,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
#endif #endif
/* user-defined modules register start */ /* user-defined modules register start */
&be_native_module(tasmota_ntv), &be_native_module(energy),
&be_native_module(wire),
/* user-defined modules register end */ /* user-defined modules register end */
NULL /* do not remove */ NULL /* do not remove */

View File

@ -13,6 +13,7 @@ extern int l_millis(bvm *vm);
extern int l_timereached(bvm *vm); extern int l_timereached(bvm *vm);
extern int l_yield(bvm *vm); extern int l_yield(bvm *vm);
extern int l_delay(bvm *vm); extern int l_delay(bvm *vm);
extern int l_scaleuint(bvm *vm);
extern int l_respCmnd(bvm *vm); extern int l_respCmnd(bvm *vm);
extern int l_respCmndStr(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_resolveCmnd(bvm *vm);
extern int l_getlight(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 !BE_USE_PRECOMPILED_OBJECT
#if 1 // TODO we will do pre-compiled later #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) { { "respcmnd", l_respCmnd },
be_native_module_function("getfreeheap", l_getFreeHeap), { "respcmndstr", l_respCmndStr },
be_native_module_function("publish", l_publish), { "respcmnd_done", l_respCmndDone },
be_native_module_function("cmd", l_cmd), { "respcmnd_error", l_respCmndError },
be_native_module_function("getoption", l_getoption), { "respcmnd_failed", l_respCmndFailed },
be_native_module_function("millis", l_millis), { "resolvecmnd", l_resolveCmnd },
be_native_module_function("timereached", l_timereached),
be_native_module_function("yield", l_yield),
be_native_module_function("delay", l_delay),
be_native_module_function("respcmnd", l_respCmnd), { "getlight", l_getlight },
be_native_module_function("respcmndstr", l_respCmndStr), { "getpower", l_getpower },
be_native_module_function("respcmnd_done", l_respCmndDone), { "setlight", l_setlight },
be_native_module_function("respcmnd_error", l_respCmndError), { "setpower", l_setpower },
be_native_module_function("respcmnd_failed", l_respCmndFailed),
be_native_module_function("resolvecmnd", l_resolveCmnd),
be_native_module_function("getlight", l_getlight), { NULL, NULL }
};
be_regclass(vm, "Tasmota_ntv", members);
}
be_native_module_str("_operators", "=<>!|"),
};
be_define_native_module(tasmota_ntv, NULL);
#else #else
/* @const_object_info_begin /* @const_object_info_begin
module tasmota (scope: global, depend: 1) { module tasmota (scope: global, depend: 1) {

View File

@ -7,6 +7,8 @@
*******************************************************************/ *******************************************************************/
#include "be_object.h" #include "be_object.h"
extern int b_wire_init(bvm *vm);
extern int b_wire_begintransmission(bvm *vm); extern int b_wire_begintransmission(bvm *vm);
extern int b_wire_endtransmission(bvm *vm); extern int b_wire_endtransmission(bvm *vm);
extern int b_wire_requestfrom(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 !BE_USE_PRECOMPILED_OBJECT
#if 1 // TODO we will do pre-compiled later #if 1 // TODO we will do pre-compiled later
be_native_module_attr_table(wire) { void be_load_wirelib(bvm *vm)
be_native_module_function("_begintransmission", b_wire_begintransmission), {
be_native_module_function("_endtransmission", b_wire_endtransmission), static const bnfuncinfo members[] = {
be_native_module_function("_requestfrom", b_wire_requestfrom), { "_bus", NULL }, // bus number
be_native_module_function("_available", b_wire_available), { "init", b_wire_init },
be_native_module_function("_write", b_wire_write), { "_begintransmission", b_wire_begintransmission },
be_native_module_function("_read", b_wire_read), { "_endtransmission", b_wire_endtransmission },
be_native_module_function("scan", b_wire_scan), { "_requestfrom", b_wire_requestfrom },
be_native_module_function("write", b_wire_validwrite), { "_available", b_wire_available },
be_native_module_function("read", b_wire_validread), { "_write", b_wire_write },
}; { "_read", b_wire_read },
{ "scan", b_wire_scan },
{ "write", b_wire_validwrite },
{ "read", b_wire_validread },
be_define_native_module(wire, NULL); { NULL, NULL }
};
be_regclass(vm, "Wire", members);
}
#else #else
/* @const_object_info_begin /* @const_object_info_begin
module tasmota (scope: global, depend: 1) { module tasmota (scope: global, depend: 1) {

View File

@ -0,0 +1 @@
load('denky.be')

21
tasmota/berry/denky.be Normal file
View File

@ -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()

View File

@ -1812,27 +1812,37 @@ const uint8_t I2C_RETRY_COUNTER = 3;
uint32_t i2c_active[4] = { 0 }; uint32_t i2c_active[4] = { 0 };
uint32_t i2c_buffer = 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) bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size)
#endif
{ {
uint8_t retry = I2C_RETRY_COUNTER; uint8_t retry = I2C_RETRY_COUNTER;
bool status = false; bool status = false;
#ifdef ESP32
TwoWire & myWire = (bus == 0) ? Wire : Wire1;
#else
TwoWire & myWire = Wire;
#endif
i2c_buffer = 0; i2c_buffer = 0;
while (!status && retry) { while (!status && retry) {
Wire.beginTransmission(addr); // start transmission to device myWire.beginTransmission(addr); // start transmission to device
Wire.write(reg); // sends register address to read from myWire.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... if (0 == myWire.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 myWire.requestFrom((int)addr, (int)size); // send data n-bytes read
if (Wire.available() == size) { if (myWire.available() == size) {
for (uint32_t i = 0; i < size; i++) { 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; status = true;
} }
} }
retry--; retry--;
} }
if (!retry) Wire.endTransmission(); if (!retry) myWire.endTransmission();
return status; return status;
} }
@ -1916,19 +1926,30 @@ int32_t I2cRead24(uint8_t addr, uint8_t reg)
return i2c_buffer; 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) bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size)
#endif
{ {
uint8_t x = I2C_RETRY_COUNTER; uint8_t x = I2C_RETRY_COUNTER;
#ifdef ESP32
TwoWire & myWire = (bus == 0) ? Wire : Wire1;
#else
TwoWire & myWire = Wire;
#endif
do { do {
Wire.beginTransmission((uint8_t)addr); // start transmission to device myWire.beginTransmission((uint8_t)addr); // start transmission to device
Wire.write(reg); // sends register address to write to myWire.write(reg); // sends register address to write to
uint8_t bytes = size; uint8_t bytes = size;
while (bytes--) { while (bytes--) {
Wire.write((val >> (8 * bytes)) & 0xFF); // write data myWire.write((val >> (8 * bytes)) & 0xFF); // write data
} }
x--; x--;
} while (Wire.endTransmission(true) != 0 && x != 0); // end transmission } while (myWire.endTransmission(true) != 0 && x != 0); // end transmission
return (x); return (x);
} }

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#include <berry.h>
#include <Wire.h>
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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#include <berry.h>
/*********************************************************************************************\
* 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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#include <berry.h>
#include <Wire.h>
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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#include <berry.h>
#include <Wire.h>
/*********************************************************************************************\
* 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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#include <berry.h>
#include <Wire.h>
// 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

View File

@ -32,60 +32,33 @@ const char berry_prog[] =
//"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end " //"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end "
//"log(\"foobar\") " //"log(\"foobar\") "
// create a 'ntv' module to allow functions to be registered in a safe namespace
"ntv = module('ntv') "
// auto-import modules // auto-import modules
// // import alias // // import alias
"import wire " "import energy "
// Phase 1 // Phase 1
// Prepare the super class that will be eventually in Flash "class Tasmota: Tasmota_ntv "
"class Tasmota_ntv " // for now the variables are built, need to find a way to push in Flash
"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 "
"def init() " "def init() "
"self._op = [ " "self._op = ['==', '!==', '=', '!=', '>=', '<=', '>', '<'] "
"['==', /s1,s2-> str(s1) == str(s2)]," "self._opf = [ "
"['!==',/s1,s2-> str(s1) != str(s2)]," "/s1,s2-> str(s1) == str(s2),"
"['=', /f1,f2-> real(f1) == real(f2)]," "/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),"
"['>', /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._rules = {} "
"self._timers = [] " "self._timers = [] "
"self._cmd = {} " "self._cmd = {} "
"self.init_ntv() "
"end " "end "
"end "
"class Tasmota: Tasmota_ntv "
// add `charsinstring(s:string,c:string) -> int`` // add `charsinstring(s:string,c:string) -> int``
// looks for any char in c, and return the position of the first chat // looks for any char in c, and return the position of the first chat
// or -1 if not found // or -1 if not found
@ -125,10 +98,11 @@ const char berry_prog[] =
"var op_left = op_split[0] " "var op_left = op_split[0] "
"var op_rest = op_split[1] " "var op_rest = op_split[1] "
// # iterate through operators // # iterate through operators
"for op: self._op " "for i: 0..size(self._op)-1 "
"if string.find(op_rest,op[0]) == 0 " "var op = self._op[i] "
"var op_func = op[1] " "if string.find(op_rest,op) == 0 "
"var op_right = string.split(op_rest,size(op[0]))[1] " "var op_func = self._opf[i] "
"var op_right = string.split(op_rest,size(op))[1] "
"return [op_left,op_func,op_right] " "return [op_left,op_func,op_right] "
"end " "end "
"end " "end "
@ -137,7 +111,6 @@ const char berry_prog[] =
"end " "end "
// Rules trigger if match. return true if match, false if not // Rules trigger if match. return true if match, false if not
// Note: condition is not yet managed
"def try_rule(ev, rule, f) " "def try_rule(ev, rule, f) "
"import string " "import string "
"var rl_list = self.find_op(rule) " "var rl_list = self.find_op(rule) "
@ -229,6 +202,8 @@ const char berry_prog[] =
// Instantiate tasmota object // Instantiate tasmota object
"tasmota = Tasmota() " "tasmota = Tasmota() "
"wire = Wire(0) "
"wire1 = Wire(1) "
// Not sure how to run call methods from C // Not sure how to run call methods from C
"def _exec_rules(e) return tasmota.exec_rules(e) end " "def _exec_rules(e) return tasmota.exec_rules(e) end "
@ -253,19 +228,30 @@ const char berry_prog[] =
"var c = compile(f,'file') " "var c = compile(f,'file') "
// save the compiled bytecode // save the compiled bytecode
"if !native " "if !native "
"try "
"save(f+'c', c) " "save(f+'c', c) "
"except .. as e "
"log(string.format('BRY: could not save compiled file %s (%s)',f+'c',e)) "
"end "
"end " "end "
// call the compiled code // call the compiled code
"c() " "c() "
"log(string.format(\"BRY: sucessfully loaded '%s'\",f)) "
"except .. as e " "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 "
"end " "end "
// try to load "/autoexec.be" // try to load "/autoexec.be"
// "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end " // "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 #endif // USE_BERRY

View File

@ -36,8 +36,7 @@ class BerrySupport {
public: public:
bvm *vm = nullptr; // berry vm bvm *vm = nullptr; // berry vm
bool rules_busy = false; // are we already processing rules, avoid infinite loop bool rules_busy = false; // are we already processing rules, avoid infinite loop
const char *fname = nullptr; // name of berry function to call bool autoexec_done = false; // do we still need to load 'autoexec.be'
int32_t fret = 0;
}; };
BerrySupport berry; BerrySupport berry;
@ -59,10 +58,6 @@ void checkBeTop(void) {
* *
\*********************************************************************************************/ \*********************************************************************************************/
// // call a function (if exists) of type void -> 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) { bool callBerryRule(void) {
if (berry.rules_busy) { return false; } if (berry.rules_busy) { return false; }
@ -244,7 +239,7 @@ void BrReset(void) {
ret_code2 = be_pcall(berry.vm, 0); ret_code2 = be_pcall(berry.vm, 0);
if (ret_code1 != 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)); 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; break;
} }
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm)); // 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 * Tasmota Commands
\*********************************************************************************************/ \*********************************************************************************************/
@ -304,11 +325,11 @@ void CmndBrRun(void) {
// AddLog(LOG_LEVEL_INFO, "run: type(2)=%s", be_typename(berry.vm, 2)); // 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 // 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); ret_val = be_tostring(berry.vm, 1);
} else { // } else {
ret_val = be_tostring(berry.vm, 2); // 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 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); be_pop(berry.vm, 1);
} else { } else {
@ -340,6 +361,12 @@ bool Xdrv52(uint8_t function)
case FUNC_INIT: case FUNC_INIT:
BrReset(); BrReset();
break; break;
case FUNC_LOOP:
if (!berry.autoexec_done) {
BrAutoexec();
berry.autoexec_done = true;
}
break;
case FUNC_EVERY_50_MSECOND: case FUNC_EVERY_50_MSECOND:
callBerryFunctionVoid(PSTR("_run_deferred")); callBerryFunctionVoid(PSTR("_run_deferred"));
break; break;
@ -383,8 +410,6 @@ bool Xdrv52(uint8_t function)
case FUNC_BUTTON_PRESSED: case FUNC_BUTTON_PRESSED:
break; break;
case FUNC_LOOP:
break;
} }
return result; return result;