u8g2.c 19 KB

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