diff --git a/components/modules/Kconfig b/components/modules/Kconfig index 628c8a7b..2bf6a166 100644 --- a/components/modules/Kconfig +++ b/components/modules/Kconfig @@ -47,6 +47,12 @@ depends on LUA_BUILTIN_DEBUG endmenu +config LUA_MODULE_BIT + bool "Bit module" + default "n" + help + Includes the bit module. This module provide bit manipulation functions + on Lua numbers. config LUA_MODULE_BTHCI bool "BlueTooth HCI interface module" diff --git a/components/modules/bit.c b/components/modules/bit.c new file mode 100644 index 00000000..67c0f2a3 --- /dev/null +++ b/components/modules/bit.c @@ -0,0 +1,138 @@ +/* Bitwise operations library */ +/* (c) Reuben Thomas 2000-2008 */ +/* See README for license */ + +// Modified by BogdanM for eLua + + +#include "module.h" +#include + +#include "lauxlib.h" + +/* FIXME: Assume size_t is an unsigned lua_Integer */ +typedef size_t lua_UInteger; +#define LUA_UINTEGER_MAX SIZE_MAX + +/* Define TOBIT to get a bit value */ +#define TOBIT(L, n) \ + (luaL_checkinteger((L), (n))) + +/* Operations + + The macros MONADIC and VARIADIC only deal with bitwise operations. + + LOGICAL_SHIFT truncates its left-hand operand before shifting so + that any extra bits at the most-significant end are not shifted + into the result. + + ARITHMETIC_SHIFT does not truncate its left-hand operand, so that + the sign bits are not removed and right shift work properly. + */ + +#define MONADIC(name, op) \ + static int bit_ ## name(lua_State *L) { \ + lua_pushinteger(L, op TOBIT(L, 1)); \ + return 1; \ + } + +#define VARIADIC(name, op) \ + static int bit_ ## name(lua_State *L) { \ + int n = lua_gettop(L), i; \ + lua_Integer w = TOBIT(L, 1); \ + for (i = 2; i <= n; i++) \ + w op TOBIT(L, i); \ + lua_pushinteger(L, w); \ + return 1; \ + } + +#define LOGICAL_SHIFT(name, op) \ + static int bit_ ## name(lua_State *L) { \ + lua_pushinteger(L, (lua_UInteger)TOBIT(L, 1) op \ + (unsigned)luaL_checknumber(L, 2)); \ + return 1; \ + } + +#define ARITHMETIC_SHIFT(name, op) \ + static int bit_ ## name(lua_State *L) { \ + lua_pushinteger(L, (lua_Integer)TOBIT(L, 1) op \ + (unsigned)luaL_checknumber(L, 2)); \ + return 1; \ + } + +MONADIC(bnot, ~) +VARIADIC(band, &=) +VARIADIC(bor, |=) +VARIADIC(bxor, ^=) +ARITHMETIC_SHIFT(lshift, <<) +LOGICAL_SHIFT(rshift, >>) +ARITHMETIC_SHIFT(arshift, >>) + +// Lua: res = bit( position ) +static int bit_bit( lua_State* L ) +{ + lua_pushinteger( L, ( lua_Integer )( 1 << luaL_checkinteger( L, 1 ) ) ); + return 1; +} + +// Lua: res = isset( value, position ) +static int bit_isset( lua_State* L ) +{ + lua_UInteger val = ( lua_UInteger )luaL_checkinteger( L, 1 ); + unsigned pos = ( unsigned )luaL_checkinteger( L, 2 ); + + lua_pushboolean( L, val & ( 1 << pos ) ? 1 : 0 ); + return 1; +} + +// Lua: res = isclear( value, position ) +static int bit_isclear( lua_State* L ) +{ + lua_UInteger val = ( lua_UInteger )luaL_checkinteger( L, 1 ); + unsigned pos = ( unsigned )luaL_checkinteger( L, 2 ); + + lua_pushboolean( L, val & ( 1 << pos ) ? 0 : 1 ); + return 1; +} + +// Lua: res = set( value, pos1, pos2, ... ) +static int bit_set( lua_State* L ) +{ + lua_UInteger val = ( lua_UInteger )luaL_checkinteger( L, 1 ); + unsigned total = lua_gettop( L ), i; + + for( i = 2; i <= total; i ++ ) + val |= 1 << ( unsigned )luaL_checkinteger( L, i ); + lua_pushinteger( L, ( lua_Integer )val ); + return 1; +} + +// Lua: res = clear( value, pos1, pos2, ... ) +static int bit_clear( lua_State* L ) +{ + lua_UInteger val = ( lua_UInteger )luaL_checkinteger( L, 1 ); + unsigned total = lua_gettop( L ), i; + + for( i = 2; i <= total; i ++ ) + val &= ~( 1 << ( unsigned )luaL_checkinteger( L, i ) ); + lua_pushinteger( L, ( lua_Integer )val ); + return 1; +} + +static const LUA_REG_TYPE bit_map[] = { + { LSTRKEY( "bnot" ), LFUNCVAL( bit_bnot ) }, + { LSTRKEY( "band" ), LFUNCVAL( bit_band ) }, + { LSTRKEY( "bor" ), LFUNCVAL( bit_bor ) }, + { LSTRKEY( "bxor" ), LFUNCVAL( bit_bxor ) }, + { LSTRKEY( "lshift" ), LFUNCVAL( bit_lshift ) }, + { LSTRKEY( "rshift" ), LFUNCVAL( bit_rshift ) }, + { LSTRKEY( "arshift" ), LFUNCVAL( bit_arshift ) }, + { LSTRKEY( "bit" ), LFUNCVAL( bit_bit ) }, + { LSTRKEY( "set" ), LFUNCVAL( bit_set ) }, + { LSTRKEY( "clear" ), LFUNCVAL( bit_clear ) }, + { LSTRKEY( "isset" ), LFUNCVAL( bit_isset ) }, + { LSTRKEY( "isclear" ), LFUNCVAL( bit_isclear ) }, + { LNILKEY, LNILVAL} +}; + +NODEMCU_MODULE(BIT, "bit", bit_map, NULL); diff --git a/docs/en/modules/bit.md b/docs/en/modules/bit.md new file mode 100644 index 00000000..b6dc1af4 --- /dev/null +++ b/docs/en/modules/bit.md @@ -0,0 +1,174 @@ +# bit Module +| Since | Origin / Contributor | Maintainer | Source | +| :----- | :-------------------- | :---------- | :------ | +| 2014-12-24 | [https://github.com/LuaDist/bitlib](https://github.com/LuaDist/bitlib), [Zeroday](https://github.com/funshine) | [Zeroday](https://github.com/funshine) | [bit.c](../../../app/modules/bit.c)| + + +Bit manipulation support, on 32bit integers. + +## bit.arshift() +Arithmetic right shift a number equivalent to `value >> shift` in C. + +####Syntax +`bit.arshift(value, shift)` + +####Parameters +- `value` the value to shift +- `shift` positions to shift + +####Returns +the number shifted right (arithmetically) + +## bit.band() + +Bitwise AND, equivalent to `val1 & val2 & ... & valn` in C. + +####Syntax +`bit.band(val1, val2 [, ... valn])` + +####Parameters + - `val1` first AND argument + - `val2` second AND argument + - `...valn` ...nth AND argument + +####Returns +the bitwise AND of all the arguments (number) + +## bit.bit() + +Generate a number with a 1 bit (used for mask generation). Equivalent to `1 << position` in C. + +####Syntax +`bit.bit(position)` + +####Parameters +`position` position of the bit that will be set to 1 + +####Returns +a number with only one 1 bit at position (the rest are set to 0) + +## bit.bnot() + +Bitwise negation, equivalent to `~value in C. + +####Syntax +`bit.bnot(value)` + +####Parameters +`value` the number to negate + +####Returns +the bitwise negated value of the number + +## bit.bor() +Bitwise OR, equivalent to `val1 | val2 | ... | valn` in C. + +####Syntax +`bit.bor(val1, val2 [, ... valn])` + +####Parameters +- `val1` first OR argument. +- `val2` second OR argument. +- `...valn` ...nth OR argument + +####Returns +the bitwise OR of all the arguments (number) + +## bit.bxor() + +Bitwise XOR, equivalent to `val1 ^ val2 ^ ... ^ valn` in C. + +####Syntax +`bit.bxor(val1, val2 [, ... valn])` + +####Parameters +- `val1` first XOR argument +- `val2` second XOR argument +- `...valn` ...nth XOR argument + +####Returns +the bitwise XOR of all the arguments (number) + +## bit.clear() +Clear bits in a number. + +####Syntax +`bit.clear(value, pos1 [, ... posn])` + +####Parameters +- `value` the base number +- `pos1` position of the first bit to clear +- `...posn` position of thet nth bit to clear + +####Returns +the number with the bit(s) cleared in the given position(s) + +## bit.isclear() + +Test if a given bit is cleared. + +####Syntax +`bit.isclear(value, position)` + +####Parameters +- `value` the value to test +- `position` bit position to test + +####Returns +true if the bit at the given position is 0, false othewise + +## bit.isset() + +Test if a given bit is set. + +####Syntax +`bit.isset(value, position)` + +####Parameters +- `value` the value to test +- `position` bit position to test + +####Returns +true if the bit at the given position is 1, false otherwise + +## bit.lshift() +Left-shift a number, equivalent to `value << shift` in C. + +####Syntax +`bit.lshift(value, shift)` + +####Parameters +- `value` the value to shift +- `shift` positions to shift + +####Returns +the number shifted left + +## bit.rshift() + +Logical right shift a number, equivalent to `( unsigned )value >> shift` in C. + +####Syntax +`bit.rshift(value, shift)` + +####Parameters +- `value` the value to shift. +- `shift` positions to shift. + +####Returns +the number shifted right (logically) + +## bit.set() + +Set bits in a number. + +####Syntax +`bit.set(value, pos1 [, ... posn ])` + +####Parameters +- `value` the base number. +- `pos1` position of the first bit to set. +- `...posn` position of the nth bit to set. + +####Returns +the number with the bit(s) set in the given position(s) diff --git a/mkdocs.yml b/mkdocs.yml index f3bdea0d..7a5760f2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -30,6 +30,10 @@ pages: - Extension Developer FAQ: 'en/extn-developer-faq.md' - Support: 'en/support.md' - Modules: - - 'file': 'en/modules/file.md' - - 'node': 'en/modules/node.md' - - 'uart': 'en/modules/uart.md' + - 'bit': 'en/modules/bit.md' + - 'bthci': 'en/modules/bthci.md' + - 'file': 'en/modules/file.md' + - 'node': 'en/modules/node.md' + - 'struct': 'en/modules/struct.md' + - 'uart': 'en/modules/uart.md' +