ow.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Module for interfacing with the OneWire interface
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include <stdint.h>
  5. #include "platform.h"
  6. static int ow_bus_table_ref;
  7. // Lua: ow.setup( pin )
  8. static int ow_setup( lua_State *L )
  9. {
  10. int pin = luaL_checkint( L, 1 );
  11. luaL_argcheck( L, pin >= 0, 1, "invalid pin" );
  12. if (platform_onewire_init( pin ) != PLATFORM_OK)
  13. luaL_error( L, "failed" );
  14. return 0;
  15. }
  16. // Lua: r = ow.reset( pin )
  17. static int ow_reset( lua_State *L )
  18. {
  19. int pin = luaL_checkint( L, 1 );
  20. luaL_argcheck( L, pin >= 0, 1, "invalid pin" );
  21. uint8_t presence;
  22. if (platform_onewire_reset( pin, &presence ) != PLATFORM_OK)
  23. luaL_error( L, "failed" );
  24. lua_pushinteger( L, presence );
  25. return 1;
  26. }
  27. // Lua: ow.write( pin, v, power)
  28. static int ow_write( lua_State *L )
  29. {
  30. int stack = 0;
  31. int pin = luaL_checkint( L, ++stack );
  32. luaL_argcheck( L, pin >= 0, stack, "invalid pin" );
  33. int data = luaL_checkint( L, ++stack );
  34. luaL_argcheck( L, data >= 0 && data < 256, stack, "invalid data" );
  35. int power = luaL_optint( L, ++stack, 0 ) != 0 ? 1 : 0;
  36. uint8_t d = data;
  37. if (platform_onewire_write_bytes( pin, &d, 1, power ) != PLATFORM_OK)
  38. luaL_error( L, "failed" );
  39. return 0;
  40. }
  41. // Lua: ow.write_bytes( pin, buf, power)
  42. static int ow_write_bytes( lua_State *L )
  43. {
  44. int stack = 0;
  45. size_t datalen;
  46. int pin = luaL_checkint( L, ++stack );
  47. luaL_argcheck( L, pin >= 0, stack, "invalid pin" );
  48. const char *pdata = luaL_checklstring( L, ++stack, &datalen );
  49. int power = luaL_optint( L, ++stack, 0 ) != 0 ? 1 : 0;
  50. platform_onewire_write_bytes( pin, (uint8_t *)pdata, datalen, power);
  51. return 0;
  52. }
  53. // Lua: r = ow.read( pin )
  54. static int ow_read( lua_State *L )
  55. {
  56. int pin = luaL_checkint( L, 1 );
  57. luaL_argcheck( L, pin >= 0, 1, "invalid pin" );
  58. uint8_t data;
  59. if (platform_onewire_read_bytes( pin, &data, 1 ) != PLATFORM_OK)
  60. luaL_error( L, "failed" );
  61. lua_pushinteger( L, data );
  62. return 1;
  63. }
  64. // Lua: r = ow.read_bytes( pin, size )
  65. static int ow_read_bytes( lua_State *L )
  66. {
  67. int stack = 0;
  68. int pin = luaL_checkint( L, ++stack );
  69. luaL_argcheck( L, pin >= 0, stack, "invalid pin" );
  70. int size = luaL_checkint( L, ++stack );
  71. if (size == 0)
  72. return 0;
  73. luaL_argcheck( L, size <= LUAL_BUFFERSIZE, stack, "Attempt to read too many characters" );
  74. luaL_Buffer b;
  75. luaL_buffinit( L, &b );
  76. char *p = luaL_prepbuffer( &b );
  77. if (platform_onewire_read_bytes( pin, (uint8_t *)p, size ) != PLATFORM_OK)
  78. luaL_error( L, "failed" );
  79. luaL_addsize( &b, size );
  80. luaL_pushresult( &b );
  81. return 1;
  82. }
  83. // Lua: ow.select( pin, buf[8] )
  84. static int ow_select( lua_State *L )
  85. {
  86. int stack = 0;
  87. uint8_t rom[1+8];
  88. size_t datalen;
  89. int numdata, i;
  90. const char *pdata;
  91. int pin = luaL_checkint( L, ++stack );
  92. luaL_argcheck( L, pin >= 0, stack, "invalid pin" );
  93. if( lua_istable( L, ++stack ) )
  94. {
  95. datalen = lua_objlen( L, stack );
  96. luaL_argcheck( L, datalen == 8, stack, "wrong arg range" );
  97. for (i = 0; i < datalen; i ++) {
  98. lua_rawgeti( L, stack, i + 1 );
  99. numdata = ( int )luaL_checkinteger( L, -1 );
  100. lua_pop( L, 1 );
  101. if (numdata > 255)
  102. return luaL_error( L, "wrong arg range" );
  103. rom[1+i] = (uint8_t)numdata;
  104. }
  105. } else {
  106. pdata = luaL_checklstring( L, stack, &datalen );
  107. luaL_argcheck( L, datalen == 8, stack, "wrong arg range" );
  108. for (i = 0; i < datalen; i++) {
  109. rom[1+i] = pdata[i];
  110. }
  111. }
  112. rom[0] = 0x55; // select command
  113. if (platform_onewire_write_bytes( pin, rom, 1+8, 0 ) != PLATFORM_OK)
  114. luaL_error( L, "write failed" );
  115. return 0;
  116. }
  117. // Lua: ow.skip( pin )
  118. static int ow_skip( lua_State *L )
  119. {
  120. int pin = luaL_checkint( L, 1 );
  121. luaL_argcheck( L, pin >= 0, 1, "invalid pin" );
  122. const uint8_t cmd = 0xCC; // skip command
  123. if (platform_onewire_write_bytes( pin, &cmd, 1, 0 ) != PLATFORM_OK)
  124. luaL_error( L, "write failed" );
  125. return 0;
  126. }
  127. // Lua: ow.depower( pin )
  128. static int ow_depower( lua_State *L )
  129. {
  130. int pin = luaL_checkint( L, 1 );
  131. luaL_argcheck( L, pin >= 0, 1, "invalid pin" );
  132. platform_onewire_depower( pin );
  133. return 0;
  134. }
  135. // Clear the search state so that if will start from the beginning again.
  136. // Lua: ow.reset_search( pin )
  137. static int ow_reset_search( lua_State *L )
  138. {
  139. int pin = luaL_checkint( L, 1 );
  140. luaL_argcheck( L, pin >= 0, 1, "invalid pin" );
  141. // set up new userdata for this pin
  142. lua_rawgeti( L, LUA_REGISTRYINDEX, ow_bus_table_ref );
  143. platform_onewire_bus_t *bus = (platform_onewire_bus_t *)lua_newuserdata( L, sizeof( platform_onewire_bus_t ));
  144. lua_rawseti( L, -2, pin );
  145. // remove table from stack
  146. lua_pop( L, 1 );
  147. platform_onewire_reset_search( bus );
  148. return 0;
  149. }
  150. // Setup the search to find the device type 'family_code' on the next call
  151. // to search(*newAddr) if it is present.
  152. // Lua: ow.target_search( pin, family_code )
  153. static int ow_target_search( lua_State *L )
  154. {
  155. int stack = 0;
  156. int pin = luaL_checkint( L, ++stack );
  157. luaL_argcheck( L, pin >= 0, stack, "invalid pin" );
  158. int code = (int)luaL_checkinteger( L, ++stack );
  159. luaL_argcheck( L, code >= 0 && code < 256, stack, "wrong arg range" );
  160. // set up new userdata for this pin
  161. lua_rawgeti( L, LUA_REGISTRYINDEX, ow_bus_table_ref );
  162. platform_onewire_bus_t *bus = (platform_onewire_bus_t *)lua_newuserdata( L, sizeof( platform_onewire_bus_t ));
  163. lua_rawseti( L, -2, pin );
  164. // remove table from stack
  165. lua_pop( L, 1 );
  166. platform_onewire_target_search( (uint8_t)code, bus );
  167. return 0;
  168. }
  169. // Look for the next device. Returns 1 if a new address has been
  170. // returned. A zero might mean that the bus is shorted, there are
  171. // no devices, or you have already retrieved all of them. It
  172. // might be a good idea to check the CRC to make sure you didn't
  173. // get garbage. The order is deterministic. You will always get
  174. // the same devices in the same order.
  175. // Lua: r = ow.search( pin )
  176. static int ow_search( lua_State *L )
  177. {
  178. int pin = luaL_checkint( L, 1 );
  179. luaL_argcheck( L, pin >= 0, 1, "invalid pin" );
  180. // look-up bus userdata for this pin
  181. lua_rawgeti( L, LUA_REGISTRYINDEX, ow_bus_table_ref );
  182. lua_rawgeti( L, -1, pin );
  183. platform_onewire_bus_t *bus = (platform_onewire_bus_t *)lua_touserdata( L, -1 );
  184. if (!bus)
  185. return luaL_error( L, "search not initialized" );
  186. // removed temps from stack
  187. lua_pop( L, 2 );
  188. luaL_Buffer b;
  189. luaL_buffinit( L, &b );
  190. char *p = luaL_prepbuffer( &b );
  191. if (platform_onewire_search( pin, (uint8_t *)p, bus )){
  192. luaL_addsize( &b, 8 );
  193. luaL_pushresult( &b );
  194. } else {
  195. luaL_pushresult( &b ); /* close buffer */
  196. lua_pop( L, 1 );
  197. // remove bus userdata from table
  198. lua_rawgeti( L, LUA_REGISTRYINDEX, ow_bus_table_ref );
  199. lua_pushnil( L );
  200. lua_rawseti( L, -2, pin );
  201. // remove table from stack
  202. lua_pop( L, 1 );
  203. lua_pushnil( L );
  204. }
  205. return 1;
  206. }
  207. // uint8_t onewire_crc8(const uint8_t *addr, uint8_t len);
  208. // Lua: r = ow.crc8( buf )
  209. static int ow_crc8( lua_State *L )
  210. {
  211. size_t datalen;
  212. const char *pdata = luaL_checklstring( L, 1, &datalen );
  213. if(datalen > 255)
  214. return luaL_error( L, "wrong arg range" );
  215. lua_pushinteger( L, platform_onewire_crc8((uint8_t *)pdata, datalen) );
  216. return 1;
  217. }
  218. // bool onewire_check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc);
  219. // Lua: b = ow.check_crc16( buf, inverted_crc0, inverted_crc1, crc )
  220. static int ow_check_crc16( lua_State *L )
  221. {
  222. size_t datalen;
  223. uint8_t inverted_crc[2];
  224. const char *pdata = luaL_checklstring( L, 1, &datalen );
  225. if(datalen > 65535)
  226. return luaL_error( L, "wrong arg range" );
  227. int crc = 0;
  228. crc = luaL_checkinteger( L, 2 );
  229. if(datalen > 255)
  230. return luaL_error( L, "wrong arg range" );
  231. inverted_crc[0] = (uint8_t)crc;
  232. crc = luaL_checkinteger( L, 3 );
  233. if(datalen > 255)
  234. return luaL_error( L, "wrong arg range" );
  235. inverted_crc[1] = (uint8_t)crc;
  236. crc = 0;
  237. if(lua_isnumber(L, 4))
  238. crc = lua_tointeger(L, 4);
  239. if(crc > 65535)
  240. return luaL_error( L, "wrong arg range" );
  241. lua_pushboolean( L, platform_onewire_check_crc16((uint8_t *)pdata, datalen, inverted_crc, crc) );
  242. return 1;
  243. }
  244. // uint16_t onewire_crc16(const uint8_t* input, uint16_t len, uint16_t crc);
  245. // Lua: r = ow.crc16( buf, crc )
  246. static int ow_crc16( lua_State *L )
  247. {
  248. int stack = 0;
  249. size_t datalen;
  250. const char *pdata = luaL_checklstring( L, ++stack, &datalen );
  251. luaL_argcheck( L, datalen <= 65535, stack, "wrong arg range" );
  252. int crc = 0;
  253. if(lua_isnumber(L, ++stack))
  254. crc = lua_tointeger(L, stack);
  255. luaL_argcheck( L, crc >= 0 && crc <= 65535, stack, "wrong arg range" );
  256. lua_pushinteger( L, platform_onewire_crc16((uint8_t *)pdata, datalen, crc) );
  257. return 1;
  258. }
  259. static const LUA_REG_TYPE ow_map[] = {
  260. { LSTRKEY( "setup" ), LFUNCVAL( ow_setup ) },
  261. { LSTRKEY( "reset" ), LFUNCVAL( ow_reset ) },
  262. { LSTRKEY( "skip" ), LFUNCVAL( ow_skip ) },
  263. { LSTRKEY( "select" ), LFUNCVAL( ow_select ) },
  264. { LSTRKEY( "write" ), LFUNCVAL( ow_write ) },
  265. { LSTRKEY( "write_bytes" ), LFUNCVAL( ow_write_bytes ) },
  266. { LSTRKEY( "read" ), LFUNCVAL( ow_read ) },
  267. { LSTRKEY( "read_bytes" ), LFUNCVAL( ow_read_bytes ) },
  268. { LSTRKEY( "depower" ), LFUNCVAL( ow_depower ) },
  269. { LSTRKEY( "reset_search" ), LFUNCVAL( ow_reset_search ) },
  270. { LSTRKEY( "target_search" ), LFUNCVAL( ow_target_search ) },
  271. { LSTRKEY( "search" ), LFUNCVAL( ow_search ) },
  272. { LSTRKEY( "crc8" ), LFUNCVAL( ow_crc8 ) },
  273. { LSTRKEY( "check_crc16" ), LFUNCVAL( ow_check_crc16 ) },
  274. { LSTRKEY( "crc16" ), LFUNCVAL( ow_crc16 ) },
  275. { LNILKEY, LNILVAL }
  276. };
  277. int luaopen_ow( lua_State *L )
  278. {
  279. // create the table to store bus userdata for search operations
  280. lua_newtable( L );
  281. ow_bus_table_ref = luaL_ref( L, LUA_REGISTRYINDEX );
  282. return 0;
  283. }
  284. NODEMCU_MODULE(OW, "ow", ow_map, luaopen_ow);