u8g2.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. // Module for binding the u8g2 library
  2. // Note: This file is intended to be shared between esp8266 and esp32 platform
  3. #include "module.h"
  4. #include "lauxlib.h"
  5. #define U8X8_USE_PINS
  6. #include "u8g2.h"
  7. #include "u8x8_nodemcu_hal.h"
  8. #include "u8g2_displays.h"
  9. #include "u8g2_fonts.h"
  10. #ifdef ESP_PLATFORM
  11. // ESP32
  12. #include "spi_common.h"
  13. #include "sdkconfig.h"
  14. #endif
  15. #ifndef CONFIG_LUA_MODULE_U8G2
  16. // ignore unused functions if u8g2 module will be skipped anyhow
  17. #pragma GCC diagnostic ignored "-Wunused-function"
  18. #endif
  19. typedef struct {
  20. int font_ref;
  21. int host_ref;
  22. u8g2_nodemcu_t u8g2;
  23. } u8g2_ud_t;
  24. #define GET_U8G2() \
  25. u8g2_ud_t *ud = (u8g2_ud_t *)luaL_checkudata( L, 1, "u8g2.display" ); \
  26. u8g2_t *u8g2 = (u8g2_t *)(&(ud->u8g2));
  27. static int lu8g2_clearBuffer( lua_State *L )
  28. {
  29. GET_U8G2();
  30. u8g2_ClearBuffer( u8g2 );
  31. return 0;
  32. }
  33. static int lu8g2_drawBox( lua_State *L )
  34. {
  35. GET_U8G2();
  36. int stack = 1;
  37. int x = luaL_checkint( L, ++stack );
  38. int y = luaL_checkint( L, ++stack );
  39. int w = luaL_checkint( L, ++stack );
  40. int h = luaL_checkint( L, ++stack );
  41. u8g2_DrawBox( u8g2, x, y, w, h );
  42. return 0;
  43. }
  44. static int lu8g2_drawCircle( lua_State *L )
  45. {
  46. GET_U8G2();
  47. int stack = 1;
  48. int x0 = luaL_checkint( L, ++stack );
  49. int y0 = luaL_checkint( L, ++stack );
  50. int rad = luaL_checkint( L, ++stack );
  51. int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
  52. u8g2_DrawCircle( u8g2, x0, y0, rad, opt );
  53. return 0;
  54. }
  55. static int lu8g2_drawDisc( lua_State *L )
  56. {
  57. GET_U8G2();
  58. int stack = 1;
  59. int x0 = luaL_checkint( L, ++stack );
  60. int y0 = luaL_checkint( L, ++stack );
  61. int rad = luaL_checkint( L, ++stack );
  62. int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
  63. u8g2_DrawDisc( u8g2, x0, y0, rad, opt );
  64. return 0;
  65. }
  66. static int lu8g2_drawEllipse( lua_State *L )
  67. {
  68. GET_U8G2();
  69. int stack = 1;
  70. int x0 = luaL_checkint( L, ++stack );
  71. int y0 = luaL_checkint( L, ++stack );
  72. int rx = luaL_checkint( L, ++stack );
  73. int ry = luaL_checkint( L, ++stack );
  74. int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
  75. u8g2_DrawEllipse( u8g2, x0, y0, rx, ry, opt );
  76. return 0;
  77. }
  78. static int lu8g2_drawFilledEllipse( lua_State *L )
  79. {
  80. GET_U8G2();
  81. int stack = 1;
  82. int x0 = luaL_checkint( L, ++stack );
  83. int y0 = luaL_checkint( L, ++stack );
  84. int rx = luaL_checkint( L, ++stack );
  85. int ry = luaL_checkint( L, ++stack );
  86. int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
  87. u8g2_DrawFilledEllipse( u8g2, x0, y0, rx, ry, opt );
  88. return 0;
  89. }
  90. static int lu8g2_drawFrame( lua_State *L )
  91. {
  92. GET_U8G2();
  93. int stack = 1;
  94. int x = luaL_checkint( L, ++stack );
  95. int y = luaL_checkint( L, ++stack );
  96. int w = luaL_checkint( L, ++stack );
  97. int h = luaL_checkint( L, ++stack );
  98. u8g2_DrawFrame( u8g2, x, y, w, h );
  99. return 0;
  100. }
  101. static int lu8g2_drawGlyph( lua_State *L )
  102. {
  103. GET_U8G2();
  104. int stack = 1;
  105. int x = luaL_checkint( L, ++stack );
  106. int y = luaL_checkint( L, ++stack );
  107. int enc = luaL_checkint( L, ++stack );
  108. u8g2_DrawGlyph( u8g2, x, y, enc );
  109. return 0;
  110. }
  111. static int lu8g2_drawHLine( lua_State *L )
  112. {
  113. GET_U8G2();
  114. int stack = 1;
  115. int x = luaL_checkint( L, ++stack );
  116. int y = luaL_checkint( L, ++stack );
  117. int w = luaL_checkint( L, ++stack );
  118. u8g2_DrawHLine( u8g2, x, y, w );
  119. return 0;
  120. }
  121. static int lu8g2_drawLine( lua_State *L )
  122. {
  123. GET_U8G2();
  124. int stack = 1;
  125. int x0 = luaL_checkint( L, ++stack );
  126. int y0 = luaL_checkint( L, ++stack );
  127. int x1 = luaL_checkint( L, ++stack );
  128. int y1 = luaL_checkint( L, ++stack );
  129. u8g2_DrawLine( u8g2, x0, y0, x1, y1 );
  130. return 0;
  131. }
  132. static int lu8g2_drawPixel( lua_State *L )
  133. {
  134. GET_U8G2();
  135. int stack = 1;
  136. int x = luaL_checkint( L, ++stack );
  137. int y = luaL_checkint( L, ++stack );
  138. u8g2_DrawPixel( u8g2, x, y );
  139. return 0;
  140. }
  141. static int lu8g2_drawRBox( lua_State *L )
  142. {
  143. GET_U8G2();
  144. int stack = 1;
  145. int x = luaL_checkint( L, ++stack );
  146. int y = luaL_checkint( L, ++stack );
  147. int w = luaL_checkint( L, ++stack );
  148. int h = luaL_checkint( L, ++stack );
  149. int r = luaL_checkint( L, ++stack );
  150. u8g2_DrawRBox( u8g2, x, y, w, h, r );
  151. return 0;
  152. }
  153. static int lu8g2_drawRFrame( lua_State *L )
  154. {
  155. GET_U8G2();
  156. int stack = 1;
  157. int x = luaL_checkint( L, ++stack );
  158. int y = luaL_checkint( L, ++stack );
  159. int w = luaL_checkint( L, ++stack );
  160. int h = luaL_checkint( L, ++stack );
  161. int r = luaL_checkint( L, ++stack );
  162. u8g2_DrawRFrame( u8g2, x, y, w, h, r );
  163. return 0;
  164. }
  165. static int lu8g2_drawStr( lua_State *L )
  166. {
  167. GET_U8G2();
  168. int stack = 1;
  169. int x = luaL_checkint( L, ++stack );
  170. int y = luaL_checkint( L, ++stack );
  171. const char *str = luaL_checkstring( L, ++stack );
  172. u8g2_DrawStr( u8g2, x, y, str );
  173. return 0;
  174. }
  175. static int lu8g2_drawTriangle( lua_State *L )
  176. {
  177. GET_U8G2();
  178. int stack = 1;
  179. int x0 = luaL_checkint( L, ++stack );
  180. int y0 = luaL_checkint( L, ++stack );
  181. int x1 = luaL_checkint( L, ++stack );
  182. int y1 = luaL_checkint( L, ++stack );
  183. int x2 = luaL_checkint( L, ++stack );
  184. int y2 = luaL_checkint( L, ++stack );
  185. u8g2_DrawTriangle( u8g2, x0, y0, x1, y1, x2, y2 );
  186. return 0;
  187. }
  188. static int lu8g2_drawUTF8( lua_State *L )
  189. {
  190. GET_U8G2();
  191. int stack = 1;
  192. int x = luaL_checkint( L, ++stack );
  193. int y = luaL_checkint( L, ++stack );
  194. const char *str = luaL_checkstring( L, ++stack );
  195. u8g2_DrawUTF8( u8g2, x, y, str );
  196. return 0;
  197. }
  198. static int lu8g2_drawVLine( lua_State *L )
  199. {
  200. GET_U8G2();
  201. int stack = 1;
  202. int x = luaL_checkint( L, ++stack );
  203. int y = luaL_checkint( L, ++stack );
  204. int h = luaL_checkint( L, ++stack );
  205. u8g2_DrawVLine( u8g2, x, y, h );
  206. return 0;
  207. }
  208. static int lu8g2_drawXBM( lua_State *L )
  209. {
  210. GET_U8G2();
  211. int stack = 1;
  212. int x = luaL_checkint( L, ++stack );
  213. int y = luaL_checkint( L, ++stack );
  214. int w = luaL_checkint( L, ++stack );
  215. int h = luaL_checkint( L, ++stack );
  216. size_t len;
  217. const char *bitmap = luaL_checklstring( L, ++stack, &len );
  218. u8g2_DrawXBM( u8g2, x, y, w, h, (uint8_t *)bitmap );
  219. return 0;
  220. }
  221. static int lu8g2_getAscent( lua_State *L )
  222. {
  223. GET_U8G2();
  224. lua_pushinteger( L, u8g2_GetAscent( u8g2 ) );
  225. return 1;
  226. }
  227. static int lu8g2_getDescent( lua_State *L )
  228. {
  229. GET_U8G2();
  230. lua_pushinteger( L, u8g2_GetDescent( u8g2 ) );
  231. return 1;
  232. }
  233. static int lu8g2_getStrWidth( lua_State *L )
  234. {
  235. GET_U8G2();
  236. int stack = 1;
  237. const char *s = luaL_checkstring( L, ++stack );
  238. lua_pushinteger( L, u8g2_GetStrWidth( u8g2, s ) );
  239. return 1;
  240. }
  241. static int lu8g2_getUTF8Width( lua_State *L )
  242. {
  243. GET_U8G2();
  244. int stack = 1;
  245. const char *s = luaL_checkstring( L, ++stack );
  246. lua_pushinteger( L, u8g2_GetUTF8Width( u8g2, s ) );
  247. return 1;
  248. }
  249. static int lu8g2_sendBuffer( lua_State *L )
  250. {
  251. GET_U8G2();
  252. u8g2_SendBuffer( u8g2 );
  253. return 0;
  254. }
  255. static int lu8g2_setBitmapMode( lua_State *L )
  256. {
  257. GET_U8G2();
  258. int stack = 1;
  259. int is_transparent = luaL_checkint( L, ++stack );
  260. u8g2_SetBitmapMode( u8g2, is_transparent );
  261. return 0;
  262. }
  263. static int lu8g2_setContrast( lua_State *L )
  264. {
  265. GET_U8G2();
  266. int stack = 1;
  267. int value = luaL_checkint( L, ++stack );
  268. u8g2_SetContrast( u8g2, value );
  269. return 0;
  270. }
  271. static int lu8g2_setDisplayRotation( lua_State *L )
  272. {
  273. GET_U8G2();
  274. int stack = 1;
  275. const u8g2_cb_t *u8g2_cb = (u8g2_cb_t *)lua_touserdata( L, ++stack );
  276. u8g2_SetDisplayRotation( u8g2, u8g2_cb );
  277. return 0;
  278. }
  279. static int lu8g2_setDrawColor( lua_State *L )
  280. {
  281. GET_U8G2();
  282. int stack = 1;
  283. int col = luaL_checkint( L, ++stack );
  284. u8g2_SetDrawColor( u8g2, col );
  285. return 0;
  286. }
  287. static int lu8g2_setFlipMode( lua_State *L )
  288. {
  289. GET_U8G2();
  290. int stack = 1;
  291. int is_enable = luaL_checkint( L, ++stack );
  292. u8g2_SetFlipMode( u8g2, is_enable );
  293. return 0;
  294. }
  295. static int lu8g2_setFont( lua_State *L )
  296. {
  297. GET_U8G2();
  298. int stack = 1;
  299. const uint8_t *font = NULL;
  300. luaL_unref( L, LUA_REGISTRYINDEX, ud->font_ref );
  301. ud->font_ref = LUA_NOREF;
  302. if (lua_islightuserdata( L, ++stack )) {
  303. font = (const uint8_t *)lua_touserdata( L, stack );
  304. } else if (lua_isstring( L, stack )) {
  305. // ref the font string to safe it in case the string variable gets gc'ed
  306. lua_pushvalue( L, stack );
  307. ud->font_ref = luaL_ref( L, LUA_REGISTRYINDEX );
  308. size_t len;
  309. font = (const uint8_t *)luaL_checklstring( L, stack, &len );
  310. }
  311. luaL_argcheck( L, font != NULL, stack, "invalid font" );
  312. u8g2_SetFont( u8g2, font );
  313. return 0;
  314. }
  315. static int lu8g2_setFontDirection( lua_State *L )
  316. {
  317. GET_U8G2();
  318. int stack = 1;
  319. int dir = luaL_checkint( L, ++stack );
  320. u8g2_SetFontDirection( u8g2, dir );
  321. return 0;
  322. }
  323. static int lu8g2_setFontMode( lua_State *L )
  324. {
  325. GET_U8G2();
  326. int stack = 1;
  327. int is_transparent = luaL_checkint( L, ++stack );
  328. u8g2_SetFontMode( u8g2, is_transparent );
  329. return 0;
  330. }
  331. static int lu8g2_setFontPosBaseline( lua_State *L )
  332. {
  333. GET_U8G2();
  334. u8g2_SetFontPosBaseline( u8g2 );
  335. return 0;
  336. }
  337. static int lu8g2_setFontPosBottom( lua_State *L )
  338. {
  339. GET_U8G2();
  340. u8g2_SetFontPosBottom( u8g2 );
  341. return 0;
  342. }
  343. static int lu8g2_setFontPosTop( lua_State *L )
  344. {
  345. GET_U8G2();
  346. u8g2_SetFontPosTop( u8g2 );
  347. return 0;
  348. }
  349. static int lu8g2_setFontPosCenter( lua_State *L )
  350. {
  351. GET_U8G2();
  352. u8g2_SetFontPosCenter( u8g2 );
  353. return 0;
  354. }
  355. static int lu8g2_setFontRefHeightAll( lua_State *L )
  356. {
  357. GET_U8G2();
  358. u8g2_SetFontRefHeightAll( u8g2 );
  359. return 0;
  360. }
  361. static int lu8g2_setFontRefHeightExtendedText( lua_State *L )
  362. {
  363. GET_U8G2();
  364. u8g2_SetFontRefHeightExtendedText( u8g2 );
  365. return 0;
  366. }
  367. static int lu8g2_setFontRefHeightText( lua_State *L )
  368. {
  369. GET_U8G2();
  370. u8g2_SetFontRefHeightText( u8g2 );
  371. return 0;
  372. }
  373. static int lu8g2_setPowerSave( lua_State *L )
  374. {
  375. GET_U8G2();
  376. int stack = 1;
  377. int is_enable = luaL_checkint( L, ++stack );
  378. u8g2_SetPowerSave( u8g2, is_enable );
  379. return 0;
  380. }
  381. static const LUA_REG_TYPE lu8g2_display_map[] = {
  382. { LSTRKEY( "clearBuffer" ), LFUNCVAL( lu8g2_clearBuffer ) },
  383. { LSTRKEY( "drawBox" ), LFUNCVAL( lu8g2_drawBox ) },
  384. { LSTRKEY( "drawCircle" ), LFUNCVAL( lu8g2_drawCircle ) },
  385. { LSTRKEY( "drawDisc" ), LFUNCVAL( lu8g2_drawDisc ) },
  386. { LSTRKEY( "drawEllipse" ), LFUNCVAL( lu8g2_drawEllipse ) },
  387. { LSTRKEY( "drawFilledEllipse" ), LFUNCVAL( lu8g2_drawFilledEllipse ) },
  388. { LSTRKEY( "drawFrame" ), LFUNCVAL( lu8g2_drawFrame ) },
  389. { LSTRKEY( "drawGlyph" ), LFUNCVAL( lu8g2_drawGlyph ) },
  390. { LSTRKEY( "drawHLine" ), LFUNCVAL( lu8g2_drawHLine ) },
  391. { LSTRKEY( "drawLine" ), LFUNCVAL( lu8g2_drawLine ) },
  392. { LSTRKEY( "drawPixel" ), LFUNCVAL( lu8g2_drawPixel ) },
  393. { LSTRKEY( "drawRBox" ), LFUNCVAL( lu8g2_drawRBox ) },
  394. { LSTRKEY( "drawRFrame" ), LFUNCVAL( lu8g2_drawRFrame ) },
  395. { LSTRKEY( "drawStr" ), LFUNCVAL( lu8g2_drawStr ) },
  396. { LSTRKEY( "drawTriangle" ), LFUNCVAL( lu8g2_drawTriangle ) },
  397. { LSTRKEY( "drawUTF8" ), LFUNCVAL( lu8g2_drawUTF8 ) },
  398. { LSTRKEY( "drawVLine" ), LFUNCVAL( lu8g2_drawVLine ) },
  399. { LSTRKEY( "drawXBM" ), LFUNCVAL( lu8g2_drawXBM ) },
  400. { LSTRKEY( "getAscent" ), LFUNCVAL( lu8g2_getAscent ) },
  401. { LSTRKEY( "getDescent" ), LFUNCVAL( lu8g2_getDescent ) },
  402. { LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g2_getStrWidth ) },
  403. { LSTRKEY( "getUTF8Width" ), LFUNCVAL( lu8g2_getUTF8Width ) },
  404. { LSTRKEY( "sendBuffer" ), LFUNCVAL( lu8g2_sendBuffer ) },
  405. { LSTRKEY( "setBitmapMode" ), LFUNCVAL( lu8g2_setBitmapMode ) },
  406. { LSTRKEY( "setContrast" ), LFUNCVAL( lu8g2_setContrast ) },
  407. { LSTRKEY( "setDisplayRotation" ), LFUNCVAL( lu8g2_setDisplayRotation ) },
  408. { LSTRKEY( "setDrawColor" ), LFUNCVAL( lu8g2_setDrawColor ) },
  409. { LSTRKEY( "setFlipMode" ), LFUNCVAL( lu8g2_setFlipMode ) },
  410. { LSTRKEY( "setFont" ), LFUNCVAL( lu8g2_setFont ) },
  411. { LSTRKEY( "setFontDirection" ), LFUNCVAL( lu8g2_setFontDirection ) },
  412. { LSTRKEY( "setFontMode" ), LFUNCVAL( lu8g2_setFontMode ) },
  413. { LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lu8g2_setFontPosBaseline ) },
  414. { LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lu8g2_setFontPosBottom ) },
  415. { LSTRKEY( "setFontPosTop" ), LFUNCVAL( lu8g2_setFontPosTop ) },
  416. { LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lu8g2_setFontPosCenter ) },
  417. { LSTRKEY( "setFontRefHeightAll" ), LFUNCVAL( lu8g2_setFontRefHeightAll ) },
  418. { LSTRKEY( "setFontRefHeightExtendedText" ), LFUNCVAL( lu8g2_setFontRefHeightExtendedText ) },
  419. { LSTRKEY( "setFontRefHeightText" ), LFUNCVAL( lu8g2_setFontRefHeightText ) },
  420. { LSTRKEY( "setPowerSave" ), LFUNCVAL( lu8g2_setPowerSave ) },
  421. //{ LSTRKEY( "__gc" ), LFUNCVAL( lu8g2_display_free ) },
  422. { LSTRKEY( "__index" ), LROVAL( lu8g2_display_map ) },
  423. {LNILKEY, LNILVAL}
  424. };
  425. uint8_t u8x8_d_overlay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
  426. typedef void (*display_setup_fn_t)(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
  427. // ***************************************************************************
  428. // Device constructors
  429. //
  430. // I2C based devices will use this function template to implement the Lua binding.
  431. //
  432. static int ldisplay_i2c( lua_State *L, display_setup_fn_t setup_fn )
  433. {
  434. int stack = 0;
  435. int id = -1;
  436. int i2c_addr = -1;
  437. int rfb_cb_ref = LUA_NOREF;
  438. if (lua_type( L, ++stack) == LUA_TNUMBER) {
  439. /* hardware display connected */
  440. id = luaL_checkint( L, stack );
  441. i2c_addr = luaL_checkint( L, ++stack );
  442. luaL_argcheck( L, i2c_addr >= 0 && i2c_addr <= 0x7f, stack, "invalid i2c address" );
  443. } else
  444. stack--;
  445. if (lua_isfunction( L, ++stack )) {
  446. lua_pushvalue( L, stack );
  447. rfb_cb_ref = luaL_ref( L, LUA_REGISTRYINDEX );
  448. }
  449. if (id < 0 && rfb_cb_ref == LUA_NOREF)
  450. return luaL_error( L, "wrong args" );
  451. u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) );
  452. u8g2_nodemcu_t *ext_u8g2 = &(ud->u8g2);
  453. ud->font_ref = LUA_NOREF;
  454. ud->host_ref = LUA_NOREF;
  455. /* the i2c driver id is forwarded in the hal member */
  456. ext_u8g2->hal = id >= 0 ? (void *)id : NULL;
  457. u8g2_t *u8g2 = (u8g2_t *)ext_u8g2;
  458. u8x8_t *u8x8 = (u8x8_t *)u8g2;
  459. setup_fn( u8g2, U8G2_R0, u8x8_byte_nodemcu_i2c, u8x8_gpio_and_delay_nodemcu );
  460. /* prepare overlay data */
  461. if (rfb_cb_ref != LUA_NOREF) {
  462. ext_u8g2->overlay.template_display_cb = u8x8->display_cb;
  463. ext_u8g2->overlay.hardware_display_cb = NULL;
  464. ext_u8g2->overlay.rfb_cb_ref = LUA_NOREF;
  465. u8x8->display_cb = u8x8_d_overlay;
  466. }
  467. if (id >= 0) {
  468. /* hardware device specific initialization */
  469. u8x8_SetI2CAddress( u8x8, i2c_addr );
  470. ext_u8g2->overlay.hardware_display_cb = ext_u8g2->overlay.template_display_cb;
  471. }
  472. u8g2_InitDisplay( (u8g2_t *)u8g2 );
  473. u8g2_ClearDisplay( (u8g2_t *)u8g2 );
  474. u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 );
  475. if (rfb_cb_ref != LUA_NOREF) {
  476. /* finally enable rfb display driver */
  477. ext_u8g2->overlay.rfb_cb_ref = rfb_cb_ref;
  478. }
  479. /* set its metatable */
  480. luaL_getmetatable(L, "u8g2.display");
  481. lua_setmetatable(L, -2);
  482. return 1;
  483. }
  484. //
  485. // SPI based devices will use this function template to implement the Lua binding.
  486. //
  487. static int ldisplay_spi( lua_State *L, display_setup_fn_t setup_fn )
  488. {
  489. int stack = 0;
  490. #ifndef ESP_PLATFORM
  491. // ESP8266
  492. typedef struct {
  493. int host;
  494. } lspi_host_t;
  495. lspi_host_t host_elem;
  496. lspi_host_t *host = &host_elem;
  497. #else
  498. // ESP32
  499. lspi_host_t *host = NULL;
  500. #endif
  501. int host_ref = LUA_NOREF;
  502. int cs = -1;
  503. int dc = -1;
  504. int res = -1;
  505. int rfb_cb_ref = LUA_NOREF;
  506. int get_spi_pins;
  507. if (lua_type( L, ++stack ) == LUA_TUSERDATA) {
  508. host = (lspi_host_t *)luaL_checkudata( L, stack, "spi.master" );
  509. /* reference host object to avoid automatic gc */
  510. lua_pushvalue( L, stack );
  511. host_ref = luaL_ref( L, LUA_REGISTRYINDEX );
  512. get_spi_pins = 1;
  513. } else if (lua_type( L, stack ) == LUA_TNUMBER) {
  514. host->host = luaL_checkint( L, stack );
  515. get_spi_pins = 1;
  516. } else {
  517. get_spi_pins = 0;
  518. stack--;
  519. }
  520. if (get_spi_pins) {
  521. cs = luaL_checkint( L, ++stack );
  522. dc = luaL_checkint( L, ++stack );
  523. res = luaL_optint( L, ++stack, -1 );
  524. }
  525. if (lua_isfunction( L, ++stack )) {
  526. lua_pushvalue( L, stack );
  527. rfb_cb_ref = luaL_ref( L, LUA_REGISTRYINDEX );
  528. }
  529. if (!host && rfb_cb_ref == LUA_NOREF)
  530. return luaL_error( L, "wrong args" );
  531. u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) );
  532. u8g2_nodemcu_t *ext_u8g2 = &(ud->u8g2);
  533. ud->font_ref = LUA_NOREF;
  534. ud->host_ref = host_ref;
  535. /* the spi host id is forwarded in the hal member */
  536. ext_u8g2->hal = host ? (void *)(host->host) : NULL;
  537. u8g2_t *u8g2 = (u8g2_t *)ext_u8g2;
  538. u8x8_t *u8x8 = (u8x8_t *)u8g2;
  539. setup_fn( u8g2, U8G2_R0, u8x8_byte_nodemcu_spi, u8x8_gpio_and_delay_nodemcu );
  540. /* prepare overlay data */
  541. if (rfb_cb_ref != LUA_NOREF) {
  542. ext_u8g2->overlay.template_display_cb = u8x8->display_cb;
  543. ext_u8g2->overlay.hardware_display_cb = NULL;
  544. ext_u8g2->overlay.rfb_cb_ref = LUA_NOREF;
  545. u8x8->display_cb = u8x8_d_overlay;
  546. }
  547. if (host) {
  548. /* hardware specific device initialization */
  549. u8x8_SetPin( u8x8, U8X8_PIN_CS, cs );
  550. u8x8_SetPin( u8x8, U8X8_PIN_DC, dc );
  551. if (res >= 0)
  552. u8x8_SetPin( u8x8, U8X8_PIN_RESET, res );
  553. ext_u8g2->overlay.hardware_display_cb = ext_u8g2->overlay.template_display_cb;
  554. }
  555. u8g2_InitDisplay( (u8g2_t *)u8g2 );
  556. u8g2_ClearDisplay( (u8g2_t *)u8g2 );
  557. u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 );
  558. if (rfb_cb_ref != LUA_NOREF) {
  559. /* finally enable rfb display driver */
  560. ext_u8g2->overlay.rfb_cb_ref = rfb_cb_ref;
  561. }
  562. /* set its metatable */
  563. luaL_getmetatable(L, "u8g2.display");
  564. lua_setmetatable(L, -2);
  565. return 1;
  566. }
  567. //
  568. //
  569. #undef U8G2_DISPLAY_TABLE_ENTRY
  570. #define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \
  571. static int l ## binding( lua_State *L ) \
  572. { \
  573. return ldisplay_i2c( L, function ); \
  574. }
  575. //
  576. // Unroll the display table and insert binding functions for I2C based displays.
  577. U8G2_DISPLAY_TABLE_I2C
  578. //
  579. //
  580. #undef U8G2_DISPLAY_TABLE_ENTRY
  581. #define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \
  582. static int l ## binding( lua_State *L ) \
  583. { \
  584. return ldisplay_spi( L, function ); \
  585. }
  586. //
  587. // Unroll the display table and insert binding functions for SPI based displays.
  588. U8G2_DISPLAY_TABLE_SPI
  589. //
  590. #undef U8G2_FONT_TABLE_ENTRY
  591. #undef U8G2_DISPLAY_TABLE_ENTRY
  592. #define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \
  593. { LSTRKEY( #binding ), LFUNCVAL( l ## binding ) },
  594. static const LUA_REG_TYPE lu8g2_map[] = {
  595. U8G2_DISPLAY_TABLE_I2C
  596. U8G2_DISPLAY_TABLE_SPI
  597. //
  598. // Register fonts
  599. #define U8G2_FONT_TABLE_ENTRY(font) \
  600. { LSTRKEY( #font ), LUDATA( (void *)(u8g2_ ## font) ) },
  601. U8G2_FONT_TABLE
  602. //
  603. { LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( U8G2_DRAW_UPPER_RIGHT ) },
  604. { LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( U8G2_DRAW_UPPER_LEFT ) },
  605. { LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( U8G2_DRAW_LOWER_RIGHT ) },
  606. { LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( U8G2_DRAW_LOWER_LEFT ) },
  607. { LSTRKEY( "DRAW_ALL" ), LNUMVAL( U8G2_DRAW_ALL ) },
  608. { LSTRKEY( "R0" ), LUDATA( (void *)U8G2_R0 ) },
  609. { LSTRKEY( "R1" ), LUDATA( (void *)U8G2_R1 ) },
  610. { LSTRKEY( "R2" ), LUDATA( (void *)U8G2_R2 ) },
  611. { LSTRKEY( "R3" ), LUDATA( (void *)U8G2_R3 ) },
  612. { LSTRKEY( "MIRROR" ), LUDATA( (void *)U8G2_MIRROR ) },
  613. {LNILKEY, LNILVAL}
  614. };
  615. int luaopen_u8g2( lua_State *L ) {
  616. luaL_rometatable(L, "u8g2.display", (void *)lu8g2_display_map);
  617. return 0;
  618. }
  619. NODEMCU_MODULE(U8G2, "u8g2", lu8g2_map, luaopen_u8g2);