Berry support for neopixel (WS2812, SK6812)

This commit is contained in:
Stephan Hadinger 2021-11-18 20:30:16 +01:00
parent dbec7712ad
commit 3f140b4b10
13 changed files with 1795 additions and 4 deletions

View File

@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file.
- Autoconfiguration for ESP32 and variants
- ESP32 fix leftover GPIO configuration after restart
- ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) (#13447)
- Preliminary support for Tasmota Apps (.tapp extesions)
- Berry support for neopixel (WS2812, SK6812)
### Changed
- ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623)

View File

@ -0,0 +1,316 @@
/********************************************************************
* Berry class `Leds_animator`
*
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_WS2812
/********************************************************************
** Solidified function: set_bri
********************************************************************/
be_local_closure(set_bri, /* name */
be_nested_proto(
2, /* nstack */
2, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("bri", 2112284244, 3),
}),
(be_nested_const_str("set_bri", -1505848517, 7)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 2]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x80000000, // 0001 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: clear
********************************************************************/
be_local_closure(clear, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_string("stop", -883741979, 4),
/* K1 */ be_nested_string("strip", -48555823, 5),
/* K2 */ be_nested_string("clear", 1550717474, 5),
}),
(be_nested_const_str("clear", 1550717474, 5)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x7C040200, // 0001 CALL R1 1
0x88040101, // 0002 GETMBR R1 R0 K1
0x8C040302, // 0003 GETMET R1 R1 K2
0x7C040200, // 0004 CALL R1 1
0x80000000, // 0005 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: get_bri
********************************************************************/
be_local_closure(get_bri, /* name */
be_nested_proto(
3, /* nstack */
2, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("bri", 2112284244, 3),
}),
(be_nested_const_str("get_bri", 2041809895, 7)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 2]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x80040400, // 0001 RET 1 R2
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: every_50ms
********************************************************************/
be_local_closure(every_50ms, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("running", 343848780, 7),
/* K1 */ be_nested_string("animate", -409180496, 7),
}),
(be_nested_const_str("every_50ms", -1911083288, 10)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 5]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060001, // 0001 JMPF R1 #0004
0x8C040101, // 0002 GETMET R1 R0 K1
0x7C040200, // 0003 CALL R1 1
0x80000000, // 0004 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: stop
********************************************************************/
be_local_closure(stop, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("running", 343848780, 7),
}),
(be_nested_const_str("stop", -883741979, 4)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 3]) { /* code */
0x50040000, // 0000 LDBOOL R1 0 0
0x90020001, // 0001 SETMBR R0 K0 R1
0x80000000, // 0002 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: remove
********************************************************************/
be_local_closure(remove, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("tasmota", 424643812, 7),
/* K1 */ be_nested_string("remove_driver", 1030243768, 13),
}),
(be_nested_const_str("remove", -611183107, 6)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 5]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
0x5C0C0000, // 0002 MOVE R3 R0
0x7C040400, // 0003 CALL R1 2
0x80000000, // 0004 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: start
********************************************************************/
be_local_closure(start, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("running", 343848780, 7),
}),
(be_nested_const_str("start", 1697318111, 5)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 3]) { /* code */
0x50040200, // 0000 LDBOOL R1 1 0
0x90020001, // 0001 SETMBR R0 K0 R1
0x80000000, // 0002 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(init, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
/* K0 */ be_nested_string("strip", -48555823, 5),
/* K1 */ be_nested_string("bri", 2112284244, 3),
/* K2 */ be_nested_string("running", 343848780, 7),
/* K3 */ be_nested_string("pixel_count", -1855836553, 11),
/* K4 */ be_nested_string("clear", 1550717474, 5),
/* K5 */ be_nested_string("tasmota", 424643812, 7),
/* K6 */ be_nested_string("add_driver", 1654458371, 10),
}),
(be_nested_const_str("init", 380752755, 4)),
((bstring*) &be_const_str_input),
( &(const binstruction[15]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x540A0031, // 0001 LDINT R2 50
0x90020202, // 0002 SETMBR R0 K1 R2
0x50080000, // 0003 LDBOOL R2 0 0
0x90020402, // 0004 SETMBR R0 K2 R2
0x8C080303, // 0005 GETMET R2 R1 K3
0x7C080200, // 0006 CALL R2 1
0x90020602, // 0007 SETMBR R0 K3 R2
0x8C080104, // 0008 GETMET R2 R0 K4
0x7C080200, // 0009 CALL R2 1
0xB80A0A00, // 000A GETNGBL R2 K5
0x8C080506, // 000B GETMET R2 R2 K6
0x5C100000, // 000C MOVE R4 R0
0x7C080400, // 000D CALL R2 2
0x80000000, // 000E RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: animate
********************************************************************/
be_local_closure(animate, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
(be_nested_const_str("animate", -409180496, 7)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: Leds_animator
********************************************************************/
be_local_class(Leds_animator,
4,
NULL,
be_nested_map(13,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_nested_key("set_bri", -1505848517, 7, 9), be_const_closure(set_bri_closure) },
{ be_nested_key("clear", 1550717474, 5, -1), be_const_closure(clear_closure) },
{ be_nested_key("running", 343848780, 7, -1), be_const_var(3) },
{ be_nested_key("get_bri", 2041809895, 7, -1), be_const_closure(get_bri_closure) },
{ be_nested_key("every_50ms", -1911083288, 10, -1), be_const_closure(every_50ms_closure) },
{ be_nested_key("bri", 2112284244, 3, 0), be_const_var(2) },
{ be_nested_key("stop", -883741979, 4, 11), be_const_closure(stop_closure) },
{ be_nested_key("remove", -611183107, 6, 1), be_const_closure(remove_closure) },
{ be_nested_key("start", 1697318111, 5, 3), be_const_closure(start_closure) },
{ be_nested_key("strip", -48555823, 5, -1), be_const_var(0) },
{ be_nested_key("pixel_count", -1855836553, 11, -1), be_const_var(1) },
{ be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) },
{ be_nested_key("animate", -409180496, 7, 4), be_const_closure(animate_closure) },
})),
(be_nested_const_str("Leds_animator", 142168673, 13))
);
/*******************************************************************/
void be_load_Leds_animator_class(bvm *vm) {
be_pushntvclass(vm, &be_class_Leds_animator);
be_setglobal(vm, "Leds_animator");
be_pop(vm, 1);
}
#endif // USE_WS2812

View File

@ -0,0 +1,618 @@
/********************************************************************
* Berry class `Leds`
*
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_WS2812
/********************************************************************
** Solidified function: get_pixel_color
********************************************************************/
be_local_closure(get_pixel_color, /* name */
be_nested_proto(
6, /* nstack */
2, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
}),
(be_nested_const_str("get_pixel_color", 337490048, 15)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 5]) { /* code */
0x8C080100, // 0000 GETMET R2 R0 K0
0x5412000A, // 0001 LDINT R4 11
0x5C140200, // 0002 MOVE R5 R1
0x7C080600, // 0003 CALL R2 3
0x80040400, // 0004 RET 1 R2
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: pixels_buffer
********************************************************************/
be_local_closure(pixels_buffer, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
}),
(be_nested_const_str("pixels_buffer", 1229555807, 13)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0005, // 0001 LDINT R3 6
0x7C040400, // 0002 CALL R1 2
0x80040200, // 0003 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: clear
********************************************************************/
be_local_closure(clear, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_string("clear_to", -766965166, 8),
/* K1 */ be_const_int(0),
/* K2 */ be_nested_string("show", -1454906820, 4),
}),
(be_nested_const_str("clear", 1550717474, 5)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
0x7C040400, // 0002 CALL R1 2
0x8C040102, // 0003 GETMET R1 R0 K2
0x7C040200, // 0004 CALL R1 1
0x80000000, // 0005 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(init, /* name */
be_nested_proto(
9, /* nstack */
4, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[11]) { /* constants */
/* K0 */ be_nested_string("gamma", -802614262, 5),
/* K1 */ be_nested_string("pin", 1866532500, 3),
/* K2 */ be_nested_string("WS2812", -755226078, 6),
/* K3 */ be_const_int(0),
/* K4 */ be_nested_string("valuer_error", -1727020191, 12),
/* K5 */ be_nested_string("no GPIO specified for neopixelbus", 42078528, 33),
/* K6 */ be_nested_string("ctor", 375399343, 4),
/* K7 */ be_nested_string("_p", 1594591802, 2),
/* K8 */ be_nested_string("internal_error", -1775809127, 14),
/* K9 */ be_nested_string("couldn't not initialize noepixelbus", -1758476484, 35),
/* K10 */ be_nested_string("begin", 1748273790, 5),
}),
(be_nested_const_str("init", 380752755, 4)),
((bstring*) &be_const_str_input),
( &(const binstruction[31]) { /* code */
0x50100200, // 0000 LDBOOL R4 1 0
0x90020004, // 0001 SETMBR R0 K0 R4
0x4C100000, // 0002 LDNIL R4
0x1C100404, // 0003 EQ R4 R2 R4
0x78120008, // 0004 JMPF R4 #000E
0x8C100501, // 0005 GETMET R4 R2 K1
0x88180502, // 0006 GETMBR R6 R2 K2
0x7C100400, // 0007 CALL R4 2
0x28100903, // 0008 GE R4 R4 K3
0x78120003, // 0009 JMPF R4 #000E
0x8C100501, // 000A GETMET R4 R2 K1
0x88180502, // 000B GETMBR R6 R2 K2
0x7C100400, // 000C CALL R4 2
0x5C080800, // 000D MOVE R2 R4
0x4C100000, // 000E LDNIL R4
0x1C100404, // 000F EQ R4 R2 R4
0x78120000, // 0010 JMPF R4 #0012
0xB0060905, // 0011 RAISE 1 K4 K5
0x8C100106, // 0012 GETMET R4 R0 K6
0x5C180200, // 0013 MOVE R6 R1
0x5C1C0400, // 0014 MOVE R7 R2
0x5C200600, // 0015 MOVE R8 R3
0x7C100800, // 0016 CALL R4 4
0x88100107, // 0017 GETMBR R4 R0 K7
0x4C140000, // 0018 LDNIL R5
0x1C100805, // 0019 EQ R4 R4 R5
0x78120000, // 001A JMPF R4 #001C
0xB0061109, // 001B RAISE 1 K8 K9
0x8C10010A, // 001C GETMET R4 R0 K10
0x7C100200, // 001D CALL R4 1
0x80000000, // 001E RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: set_pixel_color
********************************************************************/
be_local_closure(set_pixel_color, /* name */
be_nested_proto(
12, /* nstack */
4, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
/* K1 */ be_nested_string("to_gamma", 1597139862, 8),
}),
(be_nested_const_str("set_pixel_color", 1275248356, 15)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 9]) { /* code */
0x8C100100, // 0000 GETMET R4 R0 K0
0x541A0009, // 0001 LDINT R6 10
0x5C1C0200, // 0002 MOVE R7 R1
0x8C200101, // 0003 GETMET R8 R0 K1
0x5C280400, // 0004 MOVE R10 R2
0x5C2C0600, // 0005 MOVE R11 R3
0x7C200600, // 0006 CALL R8 3
0x7C100800, // 0007 CALL R4 4
0x80000000, // 0008 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: begin
********************************************************************/
be_local_closure(begin, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
/* K1 */ be_const_int(1),
}),
(be_nested_const_str("begin", 1748273790, 5)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
0x7C040400, // 0002 CALL R1 2
0x80000000, // 0003 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: to_gamma
********************************************************************/
be_local_closure(to_gamma, /* name */
be_nested_proto(
12, /* nstack */
3, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
/* K0 */ be_nested_string("tasmota", 424643812, 7),
/* K1 */ be_nested_string("scale_uint", -1204156202, 10),
/* K2 */ be_const_int(0),
/* K3 */ be_const_int(16711680),
/* K4 */ be_nested_string("gamma", -802614262, 5),
/* K5 */ be_nested_string("light", -493019601, 5),
/* K6 */ be_nested_string("gamma8", -492123466, 6),
}),
(be_nested_const_str("to_gamma", 1597139862, 8)),
((bstring*) &be_const_str_input),
( &(const binstruction[67]) { /* code */
0x4C0C0000, // 0000 LDNIL R3
0x200C0403, // 0001 NE R3 R2 R3
0x780E0001, // 0002 JMPF R3 #0005
0x5C0C0400, // 0003 MOVE R3 R2
0x70020000, // 0004 JMP #0006
0x540E0063, // 0005 LDINT R3 100
0x5C080600, // 0006 MOVE R2 R3
0xB80E0000, // 0007 GETNGBL R3 K0
0x8C0C0701, // 0008 GETMET R3 R3 K1
0x5C140400, // 0009 MOVE R5 R2
0x58180002, // 000A LDCONST R6 K2
0x541E0063, // 000B LDINT R7 100
0x58200002, // 000C LDCONST R8 K2
0x2C240303, // 000D AND R9 R1 K3
0x542A000F, // 000E LDINT R10 16
0x3C24120A, // 000F SHR R9 R9 R10
0x7C0C0C00, // 0010 CALL R3 6
0xB8120000, // 0011 GETNGBL R4 K0
0x8C100901, // 0012 GETMET R4 R4 K1
0x5C180400, // 0013 MOVE R6 R2
0x581C0002, // 0014 LDCONST R7 K2
0x54220063, // 0015 LDINT R8 100
0x58240002, // 0016 LDCONST R9 K2
0x542AFEFF, // 0017 LDINT R10 65280
0x2C28020A, // 0018 AND R10 R1 R10
0x542E0007, // 0019 LDINT R11 8
0x3C28140B, // 001A SHR R10 R10 R11
0x7C100C00, // 001B CALL R4 6
0xB8160000, // 001C GETNGBL R5 K0
0x8C140B01, // 001D GETMET R5 R5 K1
0x5C1C0400, // 001E MOVE R7 R2
0x58200002, // 001F LDCONST R8 K2
0x54260063, // 0020 LDINT R9 100
0x58280002, // 0021 LDCONST R10 K2
0x542E00FE, // 0022 LDINT R11 255
0x2C2C020B, // 0023 AND R11 R1 R11
0x7C140C00, // 0024 CALL R5 6
0x88180104, // 0025 GETMBR R6 R0 K4
0x781A0013, // 0026 JMPF R6 #003B
0xB81A0A00, // 0027 GETNGBL R6 K5
0x8C180D06, // 0028 GETMET R6 R6 K6
0x5C200600, // 0029 MOVE R8 R3
0x7C180400, // 002A CALL R6 2
0x541E000F, // 002B LDINT R7 16
0x38180C07, // 002C SHL R6 R6 R7
0xB81E0A00, // 002D GETNGBL R7 K5
0x8C1C0F06, // 002E GETMET R7 R7 K6
0x5C240800, // 002F MOVE R9 R4
0x7C1C0400, // 0030 CALL R7 2
0x54220007, // 0031 LDINT R8 8
0x381C0E08, // 0032 SHL R7 R7 R8
0x30180C07, // 0033 OR R6 R6 R7
0xB81E0A00, // 0034 GETNGBL R7 K5
0x8C1C0F06, // 0035 GETMET R7 R7 K6
0x5C240A00, // 0036 MOVE R9 R5
0x7C1C0400, // 0037 CALL R7 2
0x30180C07, // 0038 OR R6 R6 R7
0x80040C00, // 0039 RET 1 R6
0x70020006, // 003A JMP #0042
0x541A000F, // 003B LDINT R6 16
0x38180606, // 003C SHL R6 R3 R6
0x541E0007, // 003D LDINT R7 8
0x381C0807, // 003E SHL R7 R4 R7
0x30180C07, // 003F OR R6 R6 R7
0x30180C05, // 0040 OR R6 R6 R5
0x80040C00, // 0041 RET 1 R6
0x80000000, // 0042 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: pixel_count
********************************************************************/
be_local_closure(pixel_count, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
}),
(be_nested_const_str("pixel_count", -1855836553, 11)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0007, // 0001 LDINT R3 8
0x7C040400, // 0002 CALL R1 2
0x80040200, // 0003 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: can_show
********************************************************************/
be_local_closure(can_show, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
/* K1 */ be_const_int(3),
}),
(be_nested_const_str("can_show", 960091187, 8)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
0x7C040400, // 0002 CALL R1 2
0x80040200, // 0003 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: pixel_size
********************************************************************/
be_local_closure(pixel_size, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
}),
(be_nested_const_str("pixel_size", -2085831511, 10)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0006, // 0001 LDINT R3 7
0x7C040400, // 0002 CALL R1 2
0x80040200, // 0003 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: dirty
********************************************************************/
be_local_closure(dirty, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
}),
(be_nested_const_str("dirty", -1627386213, 5)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0004, // 0001 LDINT R3 5
0x7C040400, // 0002 CALL R1 2
0x80000000, // 0003 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: show
********************************************************************/
be_local_closure(show, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
/* K1 */ be_const_int(2),
}),
(be_nested_const_str("show", -1454906820, 4)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
0x7C040400, // 0002 CALL R1 2
0x80000000, // 0003 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: clear_to
********************************************************************/
be_local_closure(clear_to, /* name */
be_nested_proto(
10, /* nstack */
3, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
/* K1 */ be_nested_string("to_gamma", 1597139862, 8),
}),
(be_nested_const_str("clear_to", -766965166, 8)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 8]) { /* code */
0x8C0C0100, // 0000 GETMET R3 R0 K0
0x54160008, // 0001 LDINT R5 9
0x8C180101, // 0002 GETMET R6 R0 K1
0x5C200200, // 0003 MOVE R8 R1
0x5C240400, // 0004 MOVE R9 R2
0x7C180600, // 0005 CALL R6 3
0x7C0C0600, // 0006 CALL R3 3
0x80000000, // 0007 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: is_dirty
********************************************************************/
be_local_closure(is_dirty, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
}),
(be_nested_const_str("is_dirty", 418034110, 8)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 4]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x540E0003, // 0001 LDINT R3 4
0x7C040400, // 0002 CALL R1 2
0x80040200, // 0003 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: ctor
********************************************************************/
be_local_closure(ctor, /* name */
be_nested_proto(
10, /* nstack */
4, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("call_native", 1389147405, 11),
/* K1 */ be_const_int(0),
}),
(be_nested_const_str("ctor", 375399343, 4)),
((bstring*) &be_const_str_input),
( &(const binstruction[16]) { /* code */
0x4C100000, // 0000 LDNIL R4
0x1C100604, // 0001 EQ R4 R3 R4
0x78120005, // 0002 JMPF R4 #0009
0x8C100100, // 0003 GETMET R4 R0 K0
0x58180001, // 0004 LDCONST R6 K1
0x5C1C0200, // 0005 MOVE R7 R1
0x5C200400, // 0006 MOVE R8 R2
0x7C100800, // 0007 CALL R4 4
0x70020005, // 0008 JMP #000F
0x8C100100, // 0009 GETMET R4 R0 K0
0x58180001, // 000A LDCONST R6 K1
0x5C1C0200, // 000B MOVE R7 R1
0x5C200400, // 000C MOVE R8 R2
0x5C240600, // 000D MOVE R9 R3
0x7C100A00, // 000E CALL R4 5
0x80000000, // 000F RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: Leds
********************************************************************/
extern const bclass be_class_Leds_ntv;
be_local_class(Leds,
1,
&be_class_Leds_ntv,
be_nested_map(16,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(get_pixel_color_closure) },
{ be_nested_key("pixels_buffer", 1229555807, 13, -1), be_const_closure(pixels_buffer_closure) },
{ be_nested_key("clear", 1550717474, 5, 13), be_const_closure(clear_closure) },
{ be_nested_key("init", 380752755, 4, 8), be_const_closure(init_closure) },
{ be_nested_key("set_pixel_color", 1275248356, 15, -1), be_const_closure(set_pixel_color_closure) },
{ be_nested_key("begin", 1748273790, 5, -1), be_const_closure(begin_closure) },
{ be_nested_key("to_gamma", 1597139862, 8, -1), be_const_closure(to_gamma_closure) },
{ be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(pixel_count_closure) },
{ be_nested_key("can_show", 960091187, 8, -1), be_const_closure(can_show_closure) },
{ be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(pixel_size_closure) },
{ be_nested_key("gamma", -802614262, 5, -1), be_const_var(0) },
{ be_nested_key("dirty", -1627386213, 5, -1), be_const_closure(dirty_closure) },
{ be_nested_key("show", -1454906820, 4, -1), be_const_closure(show_closure) },
{ be_nested_key("clear_to", -766965166, 8, -1), be_const_closure(clear_to_closure) },
{ be_nested_key("is_dirty", 418034110, 8, 5), be_const_closure(is_dirty_closure) },
{ be_nested_key("ctor", 375399343, 4, 1), be_const_closure(ctor_closure) },
})),
(be_nested_const_str("Leds", -1585722021, 4))
);
/*******************************************************************/
void be_load_Leds_class(bvm *vm) {
be_pushntvclass(vm, &be_class_Leds);
be_setglobal(vm, "Leds");
be_pop(vm, 1);
}
#endif // USE_WS2812

View File

@ -0,0 +1,106 @@
/********************************************************************
* Berry class `Leds_matrix`
*
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_WS2812
/********************************************************************
** Solidified function: set_matrix_pixel_color
********************************************************************/
be_local_closure(set_matrix_pixel_color, /* name */
be_nested_proto(
10, /* nstack */
5, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_string("set_pixel_color", 1275248356, 15),
/* K1 */ be_nested_string("w", -234078410, 1),
}),
(be_nested_const_str("set_matrix_pixel_color", 1197149462, 22)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 8]) { /* code */
0x8C140100, // 0000 GETMET R5 R0 K0
0x881C0101, // 0001 GETMBR R7 R0 K1
0x081C0207, // 0002 MUL R7 R1 R7
0x001C0E02, // 0003 ADD R7 R7 R2
0x5C200600, // 0004 MOVE R8 R3
0x5C240800, // 0005 MOVE R9 R4
0x7C140800, // 0006 CALL R5 4
0x80000000, // 0007 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(init, /* name */
be_nested_proto(
10, /* nstack */
5, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_string("w", -234078410, 1),
/* K1 */ be_nested_string("h", -317966505, 1),
/* K2 */ be_nested_string("init", 380752755, 4),
}),
(be_nested_const_str("init", 380752755, 4)),
((bstring*) &be_const_str_input),
( &(const binstruction[11]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x90020202, // 0001 SETMBR R0 K1 R2
0x60140003, // 0002 GETGBL R5 G3
0x5C180000, // 0003 MOVE R6 R0
0x7C140200, // 0004 CALL R5 1
0x8C140B02, // 0005 GETMET R5 R5 K2
0x081C0202, // 0006 MUL R7 R1 R2
0x5C200600, // 0007 MOVE R8 R3
0x5C240800, // 0008 MOVE R9 R4
0x7C140800, // 0009 CALL R5 4
0x80000000, // 000A RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: Leds_matrix
********************************************************************/
extern const bclass be_class_Leds;
be_local_class(Leds_matrix,
2,
&be_class_Leds,
be_nested_map(4,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_nested_key("h", -317966505, 1, -1), be_const_var(0) },
{ be_nested_key("w", -234078410, 1, -1), be_const_var(1) },
{ be_nested_key("set_matrix_pixel_color", 1197149462, 22, 1), be_const_closure(set_matrix_pixel_color_closure) },
{ be_nested_key("init", 380752755, 4, 0), be_const_closure(init_closure) },
})),
(be_nested_const_str("Leds_matrix", -1450073227, 11))
);
/*******************************************************************/
void be_load_Leds_matrix_class(bvm *vm) {
be_pushntvclass(vm, &be_class_Leds_matrix);
be_setglobal(vm, "Leds_matrix");
be_pop(vm, 1);
}
#endif // USE_WS2812

View File

@ -0,0 +1,77 @@
/********************************************************************
* Berry class `neopixelbus_ntv`
*
*******************************************************************/
/*
class Leds_ntv
var _p # pointer to internal object of type `NeoPixelBus<FEATURE, METHOD>(uint16_t countPixels, uint8_t pin)`
var _t # type of led strip
static WS2812_GRB = 1
static WS2812_GRBW = 2
static SK6812_GRB = 3
static SK6812_GRBW = 4
# skeleton for native call
def call_native() end
end
*/
#include "be_constobj.h"
#ifdef USE_WS2812
extern int be_neopixelbus_call_native(bvm *vm);
/********************************************************************
** Solidified function: call_native
********************************************************************/
be_local_closure(call_native, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
(be_nested_const_str("call_native", 1389147405, 11)),
((bstring*) &be_const_str_input),
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: Leds_ntv
********************************************************************/
be_local_class(Leds_ntv,
2,
NULL,
be_nested_map(7,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_nested_key("WS2812_GRB", 1736405692, 10, 3), be_const_int(1) },
{ be_nested_key("WS2812_GRBW", -660477967, 11, -1), be_const_int(2) },
{ be_nested_key("call_native", 1389147405, 11, 1), be_const_func(be_neopixelbus_call_native) },
{ be_nested_key("_t", 1527481326, 2, -1), be_const_var(1) },
{ be_nested_key("SK6812_GRBW", 81157857, 11, -1), be_const_int(4) },
{ be_nested_key("SK6812_GRB", 1159411308, 10, -1), be_const_int(3) },
{ be_nested_key("_p", 1594591802, 2, 5), be_const_var(0) },
})),
(be_nested_const_str("Leds_ntv", -292677248, 8))
);
/*******************************************************************/
void be_load_Leds_ntv_class(bvm *vm) {
be_pushntvclass(vm, &be_class_Leds_ntv);
be_setglobal(vm, "Leds_ntv");
be_pop(vm, 1);
}
// be_const_func(be_neopixelbus_call_native)
#endif // USE_WS2812

View File

@ -132,6 +132,10 @@ extern void be_load_AXP192_class(bvm *vm);
extern void be_load_md5_lib(bvm *vm);
extern void be_load_webclient_lib(bvm *vm);
extern void be_load_crypto_lib(bvm *vm);
extern void be_load_Leds_ntv_class(bvm *vm);
extern void be_load_Leds_class(bvm *vm);
extern void be_load_Leds_matrix_class(bvm *vm);
extern void be_load_Leds_animator_class(bvm *vm);
extern void be_load_ctypes_lib(bvm *vm);
extern void be_load_ctypes_energy_definitions_lib(bvm *vm);
@ -186,6 +190,12 @@ BERRY_API void be_load_custom_libs(bvm *vm)
#if defined(USE_ONEWIRE) || defined(USE_DS18x20)
be_load_onewirelib(vm);
#endif
#ifdef USE_WS2812
be_load_Leds_ntv_class(vm);
be_load_Leds_class(vm);
be_load_Leds_matrix_class(vm);
be_load_Leds_animator_class(vm);
#endif // USE_WS2812
#ifdef USE_I2S_AUDIO_BERRY
be_load_driver_audio_lib(vm);
#endif

View File

@ -0,0 +1,141 @@
# class Leds
#
# for adressable leds like NoePixel
# Native commands
# 00 : ctor (leds:int, gpio:int) -> void
# 01 : begin void -> void
# 02 : show void -> void
# 03 : CanShow void -> bool
# 04 : IsDirty void -> bool
# 05 : Dirty void -> void
# 06 : Pixels void -> bytes() (mapped to the buffer)
# 07 : PixelSize void -> int
# 08 : PixelCount void -> int
# 09 : ClearTo (color:??) -> void
# 10 : SetPixelColor (idx:int, color:??) -> void
# 11 : GetPixelColor (idx:int) -> color:??
# 20 : RotateLeft (rot:int [, first:int, last:int]) -> void
# 21 : RotateRight (rot:int [, first:int, last:int]) -> void
# 22 : ShiftLeft (rot:int [, first:int, last:int]) -> void
# 23 : ShiftRight (rot:int [, first:int, last:int]) -> void
class Leds : Leds_ntv
var gamma # if true, apply gamma (true is default)
# leds:int = number of leds of the strip
# gpio:int (optional) = GPIO for NeoPixel. If not specified, takes the WS2812 gpio
# type:int (optional) = Type of LED, defaults to WS2812 RGB
# rmt:int (optional) = RMT hardware channel to use, leave default unless you have a good reason
def init(leds, gpio, type, rmt) # rmt is optional
self.gamma = true # gamma is enabled by default, it should be disabled explicitly if needed
if gpio == nil && gpio.pin(gpio.WS2812) >= 0
gpio = gpio.pin(gpio.WS2812)
end
# if no GPIO, abort
if gpio == nil
raise "valuer_error", "no GPIO specified for neopixelbus"
end
# initialize the structure
self.ctor(leds, gpio, type, rmt)
if self._p == nil raise "internal_error", "couldn't not initialize noepixelbus" end
# call begin
self.begin()
end
def clear()
self.clear_to(0x000000)
self.show()
end
def ctor(leds, gpio, rmt)
if rmt == nil
self.call_native(0, leds, gpio)
else
self.call_native(0, leds, gpio, rmt)
end
end
def begin()
self.call_native(1)
end
def show()
self.call_native(2)
end
def can_show()
return self.call_native(3)
end
def is_dirty()
return self.call_native(4)
end
def dirty()
self.call_native(5)
end
def pixels_buffer()
return self.call_native(6)
end
def pixel_size()
return self.call_native(7)
end
def pixel_count()
return self.call_native(8)
end
def clear_to(col, bri)
self.call_native(9, self.to_gamma(col, bri))
end
def set_pixel_color(idx, col, bri)
self.call_native(10, idx, self.to_gamma(col, bri))
end
def get_pixel_color(idx)
return self.call_native(11, idx)
end
# def rotate_left(rot, first, last)
# self.call_native(20, rot, first, last)
# end
# def rotate_right(rot, first, last)
# self.call_native(21, rot, first, last)
# end
# def shift_left(rot, first, last)
# self.call_native(22, rot, first, last)
# end
# def shift_right(rot, first, last)
# self.call_native(22, rot, first, last)
# end
# apply gamma and bri
def to_gamma(rgbw, bri)
bri = (bri != nil) ? bri : 100
var r = tasmota.scale_uint(bri, 0, 100, 0, (rgbw & 0xFF0000) >> 16)
var g = tasmota.scale_uint(bri, 0, 100, 0, (rgbw & 0x00FF00) >> 8)
var b = tasmota.scale_uint(bri, 0, 100, 0, (rgbw & 0x0000FF))
if self.gamma
return light.gamma8(r) << 16 |
light.gamma8(g) << 8 |
light.gamma8(b)
else
return r << 16 |
g << 8 |
b
end
end
end
class Leds_matrix : Leds
var h, w
def init(w, h, gpio, rmt)
self.w = w
self.h = h
super(self).init(w * h, gpio, rmt)
end
def set_matrix_pixel_color(x, y, col, bri)
self.set_pixel_color(x * self.w + y, col, bri)
end
end

View File

@ -0,0 +1,51 @@
# class Leds_animator
class Leds_animator
var strip # neopixelbus object
var pixel_count # number of pixels in the strip
var bri # brightness of the animation, 0..100, default 50
var running # is the animation running
def init(strip)
self.strip = strip
self.bri = 50 # percentage of brightness 0..100
self.running = false
self.pixel_count = strip.pixel_count()
#
self.clear() # clear all leds first
#
tasmota.add_driver(self)
end
def clear()
self.stop()
self.strip.clear()
end
def start()
self.running = true
end
def stop()
self.running = false
end
def set_bri(bri)
self.bri = bri
end
def get_bri(bri)
return self.bri
end
def every_50ms()
if self.running
self.animate()
end
end
def animate()
# placeholder - do nothing by default
end
def remove()
tasmota.remove_driver(self)
end
end

View File

@ -0,0 +1,159 @@
# simple Rainbow animator
#-
# Ex: if WS2812 configured to WS2812 - channel 2
var strip = neopixelbus(25, gpio.pin(gpio.WS2812, 1))
rainbow = Rainbow(strip)
rainbow.start()
-#
# https://stackoverflow.com/questions/34187171/fast-integer-square-root-approximation
def fast_sqrt_int(val)
var a, b
if val < 2 return val end
a = 1255 # starting point is relatively unimportant
b = val / a; a = (a+b) /2;
b = val / a; a = (a+b) /2;
b = val / a; a = (a+b) /2;
b = val / a; a = (a+b) /2;
b = val / a; a = (a+b) /2;
b = val / a; a = (a+b) /2;
if (val < 20000)
b = val / a; a = (a+b) /2;
b = val / a; a = (a+b) /2;
end
return a
end
class Rainbow : Leds_animator
var cur_offset # current offset in the palette
static palette = [ 0xFF0000, #- red -#
0xFFA500, #- orange -#
0xFFFF00, #- yellow -#
0x008800, #- green -#
0x0000FF, #- blue -#
0x4B0082, #- indigo -#
0xEE82EE, #- violet -#
]
def init(strip)
super(self).init(strip)
self.cur_offset = 0
end
def animate()
var i = 0
# move instance variables to registers to avoid GETMBR inside the loop
var cur_offset = self.cur_offset
var modulus = size(self.palette)
var palette = self.palette
var strip = self.strip
var bri = self.bri
var set_pixel_color = strip.set_pixel_color
while i < self.pixel_count # doing a loop rather than a `for` prevents from allocating a new object
var col = palette[(cur_offset + i) % modulus]
set_pixel_color(strip, i, col, bri) # simulate the method call without GETMET
i += 1
end
strip.show()
# advance to next color
self.cur_offset = (self.cur_offset + 1) % modulus
end
end
class Rainbow_Matrix : Leds_animator
var cur_offset # current offset in the palette
static palette = [ 0xFF0000, #- red -#
0xFFA500, #- orange -#
0xFFFF00, #- yellow -#
0x008800, #- green -#
0x0000FF, #- blue -#
0x4B0082, #- indigo -#
0xEE82EE, #- violet -#
]
def init(strip)
super(self).init(strip)
self.cur_offset = 0
end
def animate()
# move instance variables to registers to avoid GETMBR inside the loop
var cur_offset = self.cur_offset
var modulus = size(self.palette)
var palette = self.palette
var strip = self.strip
var bri = self.bri
var set_matrix_pixel_color = strip.set_matrix_pixel_color
var h = self.strip.h
var w = self.strip.w
var y = 0
while y < h
var x = 0
while x < w
var col = palette[(cur_offset + y) % modulus]
set_matrix_pixel_color(strip, x, y, col, bri) # simulate the method call without GETMET
x += 1
end
y += 1
end
strip.show()
# advance to next color
self.cur_offset = (self.cur_offset + 1) % modulus
end
end
class Round : Leds_animator
var cur_val
var min_val, max_val
var incr_val
def init(strip)
super(self).init(strip)
self.cur_val = 5 << 8
self.min_val = 2 << 8
self.max_val = 6 << 8
self.incr_val = 50
end
def animate()
# move instance variables to registers to avoid GETMBR inside the loop
var strip = self.strip
var bri = self.bri
var set_matrix_pixel_color = strip.set_matrix_pixel_color
var h = self.strip.h
var w = self.strip.w
var ch = h / 2
var cw = w / 2
var y = 0
while y < h
var x = 0
while x < w
var col = 0xFF0000 # red
var dist = fast_sqrt_int( ((y - ch)*(y - ch) + (x - cw)*(x - cw)) << 16)
var rel_bri = tasmota.scale_uint(dist, 0, self.cur_val, bri, 0)
set_matrix_pixel_color(strip, x, y, col, rel_bri) # simulate the method call without GETMET
x += 1
end
y += 1
end
strip.show()
#
self.cur_val += self.incr_val
if self.cur_val > self.max_val self.cur_val = self.max_val self.incr_val = -self.incr_val end
if self.cur_val < self.min_val self.cur_val = self.min_val self.incr_val = -self.incr_val end
end
end

View File

@ -83,10 +83,22 @@ const uint16_t VL53L0X_MAX_SENSORS = 8; // Max number of VL53L0X sensors
const uint8_t MAX_I2C = 2; // Max number of I2C controllers (ESP32 = 2)
const uint8_t MAX_SPI = 2; // Max number of Hardware SPI controllers (ESP32 = 2)
const uint8_t MAX_I2S = 2; // Max number of Hardware I2S controllers (ESP32 = 2)
#if CONFIG_IDF_TARGET_ESP32
const uint8_t MAX_RMT = 8; // Max number or RMT channels (ESP32 only)
#elif CONFIG_IDF_TARGET_ESP32S2
const uint8_t MAX_RMT = 4; // Max number or RMT channels (ESP32S2 only)
#elif CONFIG_IDF_TARGET_ESP32C3
const uint8_t MAX_RMT = 2; // Max number or RMT channels (ESP32C3 only)
#else
const uint8_t MAX_RMT = 0; // Max number or RMT channels (0 if unknown)
#endif
#else
const uint8_t MAX_I2C = 0; // Max number of I2C controllers (ESP8266 = 0, no choice)
const uint8_t MAX_SPI = 0; // Max number of Hardware SPI controllers (ESP8266 = 0, no choice)
const uint8_t MAX_I2S = 0; // Max number of Hardware I2S controllers (ESP8266 = 0, no choice)
const uint8_t MAX_RMT = 0; // No RMT channel on ESP8266
#endif
// Changes to the following MAX_ defines need to be in line with enum SettingsTextIndex

View File

@ -569,7 +569,7 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_P9813_CLK), // P9813 CLOCK
AGPIO(GPIO_P9813_DAT), // P9813 DATA
#else
AGPIO(GPIO_WS2812), // WS2812 Led string
AGPIO(GPIO_WS2812) + MAX_RMT,// WS2812 Led string, using RMT on ESP32
#endif // NEO_HW_P9813
#endif
#ifdef USE_ARILUX_RF

View File

@ -0,0 +1,299 @@
/*
xdrv_52_3_berry_leds.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>
#ifdef USE_WS2812
#include <NeoPixelBus.h>
enum {
ws2812_grb = 1,
ws2812_grbw = 2,
sk6812_grb = 3,
sk6812_grbw = 4,
neopixel_type_end
};
typedef NeoPixelBus<NeoGrbFeature, NeoEsp32RmtN800KbpsMethod> neopixel_ws2812_grb_t;
typedef NeoPixelBus<NeoGrbwFeature, NeoEsp32RmtN800KbpsMethod> neopixel_ws2812_grbw_t;
typedef NeoPixelBus<NeoGrbFeature, NeoEsp32RmtNSk6812Method> neopixel_sk6812_grb_t;
typedef NeoPixelBus<NeoGrbwFeature, NeoEsp32RmtNSk6812Method> neopixel_sk6812_grbw_t;
/*********************************************************************************************\
* Native functions mapped to Berry functions
*
* import unishox
*
*
\*********************************************************************************************/
extern "C" {
// # Native commands
// # 00 : ctor
// # 01 : begin void -> void
// # 02 : show void -> void
// # 03 : CanShow void -> bool
// # 04 : IsDirty void -> bool
// # 05 : Dirty void -> void
// # 06 : Pixels void -> bytes() (mapped to the buffer)
// # 07 : PixelSize void -> int
// # 08 : PixelCount void -> int
// # 09 : ClearTo (color:??) -> void
// # 10 : SetPixelColor (idx:int, color:??) -> void
// # 11 : GetPixelColor (idx:int) -> color:??
// # 20 : RotateLeft (rot:int [, first:int, last:int]) -> void
// # 21 : RotateRight (rot:int [, first:int, last:int]) -> void
// # 22 : ShiftLeft (rot:int [, first:int, last:int]) -> void
// # 23 : ShiftRight (rot:int [, first:int, last:int]) -> void
void * be_get_neopixelbus(bvm *vm) {
be_getmember(vm, 1, "_p");
void * strip = (void*) be_tocomptr(vm, -1);
be_pop(vm, 1);
if (strip == nullptr) {
be_raise(vm, "internal_error", "neopixelbus object not initialized");
}
return strip;
}
int32_t be_get_leds_type(bvm *vm) {
be_getmember(vm, 1, "_t");
int32_t type = be_toint(vm, -1);
be_pop(vm, 1);
if (type <= 0 || type >= neopixel_type_end) {
be_raise(vm, "internal_error", "invalid leds type");
}
return type;
}
int be_neopixelbus_call_native(bvm *vm);
int be_neopixelbus_call_native(bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 2 && be_isint(vm, 2)) {
int32_t cmd = be_toint(vm, 2);
if (0 == cmd) { // 00 : ctor (leds:int, gpio:int) -> void
if (!(argc >= 4 && be_isint(vm, 3) && be_isint(vm, 4))) {
be_raise(vm, "value_error", "bad arguments for neopixelbus:ctor");
}
int32_t leds = be_toint(vm, 3);
int32_t gpio = be_toint(vm, 4);
int32_t rmt = 0;
int32_t neopixel_type = ws2812_grb;
if (argc >= 5 && !(be_isnil(vm, 5))) {
neopixel_type = be_toint(vm, 5);
}
if (neopixel_type < 1) { neopixel_type = 1; }
if (neopixel_type >= neopixel_type_end) { neopixel_type = neopixel_type_end - 1; }
// store type in attribute `_t`
be_pushint(vm, neopixel_type);
be_setmember(vm, 1, "_t");
be_pop(vm, 1);
if (PinUsed(GPIO_WS2812)) {
rmt = 1; // if WS2812 is already configured by Tasmota UI, we switch to RMT1
}
if (argc >= 6 && !(be_isnil(vm, 6))) {
rmt = be_toint(vm, 6); // if arg5, then RMT channel is specified
}
if (rmt < 0) { rmt = 0; }
if (rmt >= MAX_RMT) { rmt = MAX_RMT - 1; }
void * strip = nullptr;
switch (neopixel_type) {
case ws2812_grb: strip = new neopixel_ws2812_grb_t(leds, gpio, (NeoBusChannel) rmt);
break;
case ws2812_grbw: strip = new neopixel_ws2812_grbw_t(leds, gpio, (NeoBusChannel) rmt);
break;
case sk6812_grb: strip = new neopixel_sk6812_grb_t(leds, gpio, (NeoBusChannel) rmt);
break;
case sk6812_grbw: strip = new neopixel_sk6812_grbw_t(leds, gpio, (NeoBusChannel) rmt);
break;
}
be_pushcomptr(vm, (void*) strip);
be_setmember(vm, 1, "_p");
be_pop(vm, 1);
be_pushnil(vm);
} else {
// all other commands need a valid neopixelbus pointer
int32_t leds_type = be_get_leds_type(vm);
const void * s = be_get_neopixelbus(vm); // raises an exception if pointer is invalid
// initialize all possible variants
neopixel_ws2812_grb_t * s_ws2812_grb = (leds_type == ws2812_grb) ? (neopixel_ws2812_grb_t*) s : nullptr;
neopixel_ws2812_grbw_t * s_ws2812_grbw = (leds_type == ws2812_grbw) ? (neopixel_ws2812_grbw_t*) s : nullptr;
neopixel_sk6812_grb_t * s_sk6812_grb = (leds_type == sk6812_grb) ? (neopixel_sk6812_grb_t*) s : nullptr;
neopixel_sk6812_grbw_t * s_sk6812_grbw = (leds_type == sk6812_grbw) ? (neopixel_sk6812_grbw_t*) s : nullptr;
be_pushnil(vm); // push a default `nil` return value
switch (cmd) {
case 1: // # 01 : begin void -> void
if (s_ws2812_grb) s_ws2812_grb->Begin();
if (s_ws2812_grbw) s_ws2812_grbw->Begin();
if (s_sk6812_grb) s_sk6812_grb->Begin();
if (s_sk6812_grbw) s_sk6812_grbw->Begin();
break;
case 2: // # 02 : show void -> void
if (s_ws2812_grb) s_ws2812_grb->Show();
if (s_ws2812_grbw) s_ws2812_grbw->Show();
if (s_sk6812_grb) s_sk6812_grb->Show();
if (s_sk6812_grbw) s_sk6812_grbw->Show();
break;
case 3: // # 03 : CanShow void -> bool
if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->CanShow());
if (s_ws2812_grbw) be_pushbool(vm, s_ws2812_grbw->CanShow());
if (s_sk6812_grb) be_pushbool(vm, s_sk6812_grb->CanShow());
if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->CanShow());
break;
case 4: // # 04 : IsDirty void -> bool
if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->IsDirty());
if (s_ws2812_grbw) be_pushbool(vm, s_ws2812_grbw->IsDirty());
if (s_sk6812_grb) be_pushbool(vm, s_sk6812_grb->IsDirty());
if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->IsDirty());
break;
case 5: // # 05 : Dirty void -> void
if (s_ws2812_grb) s_ws2812_grb->Dirty();
if (s_ws2812_grbw) s_ws2812_grbw->Dirty();
if (s_sk6812_grb) s_sk6812_grb->Dirty();
if (s_sk6812_grbw) s_sk6812_grbw->Dirty();
break;
case 6: // # 06 : Pixels void -> bytes() (mapped to the buffer)
{
size_t pixels_bytes;
if (s_ws2812_grb) pixels_bytes = s_ws2812_grb->PixelsSize();
if (s_ws2812_grbw) pixels_bytes = s_ws2812_grbw->PixelsSize();
if (s_sk6812_grb) pixels_bytes = s_sk6812_grb->PixelsSize();
if (s_sk6812_grbw) pixels_bytes = s_sk6812_grbw->PixelsSize();
uint8_t * pixels;
if (s_ws2812_grb) pixels = s_ws2812_grb->Pixels();
if (s_ws2812_grbw) pixels = s_ws2812_grbw->Pixels();
if (s_sk6812_grb) pixels = s_sk6812_grb->Pixels();
if (s_sk6812_grbw) pixels = s_sk6812_grbw->Pixels();
be_getbuiltin(vm, "bytes");
be_pushcomptr(vm, pixels);
be_pushint(vm, pixels_bytes);
be_call(vm, 2);
be_pop(vm, 2);
}
break;
case 7: // # 07 : PixelSize void -> int
if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelSize());
if (s_ws2812_grbw) be_pushint(vm, s_ws2812_grbw->PixelSize());
if (s_sk6812_grb) be_pushint(vm, s_sk6812_grb->PixelSize());
if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelSize());
break;
case 8: // # 08 : PixelCount void -> int
if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelCount());
if (s_ws2812_grbw) be_pushint(vm, s_ws2812_grbw->PixelCount());
if (s_sk6812_grb) be_pushint(vm, s_sk6812_grb->PixelCount());
if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelCount());
break;
case 9: // # 09 : ClearTo (color:??) -> void
{
uint32_t rgbw = be_toint(vm, 3);
uint8_t w = (rgbw & 0xFF000000) >> 24;
uint8_t r = (rgbw & 0xFF0000) >> 16;
uint8_t g = (rgbw & 0xFF00) >> 8;
uint8_t b = (rgbw & 0xFF);
if (s_ws2812_grb) s_ws2812_grb->ClearTo(RgbColor(r, g, b));
if (s_ws2812_grbw) s_ws2812_grbw->ClearTo(RgbwColor(r, g, b, 0));
if (s_sk6812_grb) s_sk6812_grb->ClearTo(RgbColor(r, g, b));
if (s_sk6812_grbw) s_sk6812_grbw->ClearTo(RgbwColor(r, g, b, 0));
}
break;
case 10: // # 10 : SetPixelColor (idx:int, color:??) -> void
{
int32_t idx = be_toint(vm, 3);
uint32_t rgbw = be_toint(vm, 4);
uint8_t w = (rgbw & 0xFF000000) >> 24;
uint8_t r = (rgbw & 0xFF0000) >> 16;
uint8_t g = (rgbw & 0xFF00) >> 8;
uint8_t b = (rgbw & 0xFF);
if (s_ws2812_grb) s_ws2812_grb->SetPixelColor(idx, RgbColor(r, g, b));
if (s_ws2812_grbw) s_ws2812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, 0));
if (s_sk6812_grb) s_sk6812_grb->SetPixelColor(idx, RgbColor(r, g, b));
if (s_sk6812_grbw) s_sk6812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, 0));
}
break;
case 11: // # 11 : GetPixelColor (idx:int) -> color:??
{
int32_t idx = be_toint(vm, 3);
RgbColor rgb;
if (s_ws2812_grb) {
RgbColor rgb = s_ws2812_grb->GetPixelColor(idx);
be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B);
}
if (s_ws2812_grbw) {
RgbwColor rgbw = s_ws2812_grbw->GetPixelColor(idx);
be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B);
}
if (s_sk6812_grb) {
RgbColor rgb = s_sk6812_grb->GetPixelColor(idx);
be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B);
}
if (s_sk6812_grbw) {
RgbwColor rgbw = s_sk6812_grbw->GetPixelColor(idx);
be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B);
}
}
break;
// case 20: // # 20 : RotateLeft (rot:int [, first:int, last:int]) -> void
// case 21: // # 21 : RotateRight (rot:int [, first:int, last:int]) -> void
// case 22: // # 22 : ShiftLeft (rot:int [, first:int, last:int]) -> void
// case 23: // # 23 : ShiftRight (rot:int [, first:int, last:int]) -> void
// {
// int32_t rot = be_toint(vm, 3);
// int32_t first = -1;
// int32_t last = -1;
// if (argc >= 5) {
// first = be_toint(vm, 4);
// last = be_toint(vm, 5);
// }
// if (20 == cmd) {
// if (first >= 0) { strip->RotateLeft(rot, first, last); } else { strip->RotateLeft(rot); };
// } else if (21 == cmd) {
// if (first >= 0) { strip->RotateRight(rot, first, last); } else { strip->RotateRight(rot); };
// } else if (22 == cmd) {
// if (first >= 0) { strip->ShiftLeft(rot, first, last); } else { strip->ShiftLeft(rot); };
// } else if (23 == cmd) {
// if (first >= 0) { strip->ShiftRight(rot, first, last); } else { strip->ShiftRight(rot); };
// }
// }
// break;
default:
break;
}
}
be_return(vm);
}
be_raise(vm, kTypeError, nullptr);
}
}
#endif // USE_WS2812
#endif // USE_BERRY

View File

@ -780,9 +780,6 @@ bool Xdrv52(uint8_t function)
case FUNC_MQTT_DATA:
result = callBerryEventDispatcher(PSTR("mqtt_data"), XdrvMailbox.topic, 0, XdrvMailbox.data, XdrvMailbox.data_len);
break;
case FUNC_EVERY_50_MSECOND:
callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr);
break;
case FUNC_COMMAND:
result = DecodeCommand(kBrCommands, BerryCommand);
if (!result) {
@ -791,6 +788,9 @@ bool Xdrv52(uint8_t function)
break;
// Module specific events
case FUNC_EVERY_50_MSECOND:
callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr);
break;
case FUNC_EVERY_100_MSECOND:
callBerryEventDispatcher(PSTR("every_100ms"), nullptr, 0, nullptr);
break;