u8x8_d_fbrle.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Note: This file is intended to be shared between esp8266 and esp32 platform
  2. #include "u8x8.h"
  3. #include "lauxlib.h"
  4. #include "u8x8_nodemcu_hal.h"
  5. #include <stdlib.h>
  6. static const u8x8_display_info_t u8x8_fbrle_display_info =
  7. {
  8. /* chip_enable_level = */ 0,
  9. /* chip_disable_level = */ 1,
  10. /* post_chip_enable_wait_ns = */ 0,
  11. /* pre_chip_disable_wait_ns = */ 0,
  12. /* reset_pulse_width_ms = */ 0,
  13. /* post_reset_wait_ms = */ 0,
  14. /* sda_setup_time_ns = */ 0,
  15. /* sck_pulse_width_ns = */ 0,
  16. /* sck_clock_hz = */ 0,
  17. /* spi_mode = */ 0,
  18. /* i2c_bus_clock_100kHz = */ 4,
  19. /* data_setup_time_ns = */ 0,
  20. /* write_pulse_width_ns = */ 0,
  21. /* tile_width = */ 16,
  22. /* tile_hight = */ 8,
  23. /* default_x_offset = */ 0,
  24. /* flipmode_x_offset = */ 0,
  25. /* pixel_width = */ 128,
  26. /* pixel_height = */ 64
  27. };
  28. static int bit_at( uint8_t *buf, int line, int x )
  29. {
  30. return buf[x] & (1 << line) ? 1 : 0;
  31. }
  32. struct fbrle_item
  33. {
  34. uint8_t start_x;
  35. uint8_t len;
  36. };
  37. struct fbrle_line
  38. {
  39. uint8_t num_valid;
  40. struct fbrle_item items[0];
  41. };
  42. static uint8_t u8x8_d_fbrle(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  43. {
  44. u8g2_nodemcu_t *ext_u8g2 = (u8g2_nodemcu_t *)u8x8;
  45. switch(msg)
  46. {
  47. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  48. // forward to template display driver
  49. return ext_u8g2->overlay.template_display_cb(u8x8, msg, arg_int, arg_ptr);
  50. case U8X8_MSG_DISPLAY_INIT:
  51. //u8x8_d_helper_display_init(u8x8);
  52. ext_u8g2->overlay.fb_update_ongoing = 0;
  53. break;
  54. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  55. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  56. break;
  57. #ifdef U8X8_WITH_SET_CONTRAST
  58. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  59. break;
  60. #endif
  61. case U8X8_MSG_DISPLAY_REFRESH:
  62. ext_u8g2->overlay.fb_update_ongoing = 0;
  63. break;
  64. case U8X8_MSG_DISPLAY_DRAW_TILE:
  65. if (ext_u8g2->overlay.fb_update_ongoing == 0) {
  66. // tell rfb callback that a new framebuffer starts
  67. if (ext_u8g2->overlay.rfb_cb_ref != LUA_NOREF) {
  68. // fire callback with nil argument
  69. lua_State *L = lua_getstate();
  70. lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref );
  71. lua_pushnil( L );
  72. luaL_pcallx( L, 1, 0 );
  73. }
  74. // and note ongoing framebuffer update
  75. ext_u8g2->overlay.fb_update_ongoing = 1;
  76. }
  77. {
  78. // TODO: transport tile_y, needs structural change!
  79. uint8_t tile_x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  80. tile_x *= 8;
  81. tile_x += u8x8->x_offset;
  82. uint8_t tile_w = ((u8x8_tile_t *)arg_ptr)->cnt * 8;
  83. size_t fbrle_line_size = sizeof( struct fbrle_line ) + sizeof( struct fbrle_item ) * (tile_w/2);
  84. int num_lines = 8; /*arg_val / (xwidth/8);*/
  85. uint8_t *buf = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  86. struct fbrle_line *fbrle_line;
  87. if (!(fbrle_line = (struct fbrle_line *)malloc( fbrle_line_size ))) {
  88. break;
  89. }
  90. for (int line = 0; line < num_lines; line++) {
  91. int start_run = -1;
  92. fbrle_line->num_valid = 0;
  93. for (int x = tile_x; x < tile_x+tile_w; x++) {
  94. if (bit_at( buf, line, x ) == 0) {
  95. if (start_run >= 0) {
  96. // inside run, end it and enter result
  97. fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
  98. fbrle_line->items[fbrle_line->num_valid++].len = x - start_run;
  99. //NODE_ERR( " line: %d x: %d len: %d\n", line, start_run, x - start_run );
  100. start_run = -1;
  101. }
  102. } else {
  103. if (start_run < 0) {
  104. // outside run, start it
  105. start_run = x;
  106. }
  107. }
  108. if (fbrle_line->num_valid >= tile_w/2) break;
  109. }
  110. // active run?
  111. if (start_run >= 0 && fbrle_line->num_valid < tile_w/2) {
  112. fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
  113. fbrle_line->items[fbrle_line->num_valid++].len = tile_w - start_run;
  114. }
  115. // line done, trigger callback
  116. if (ext_u8g2->overlay.rfb_cb_ref != LUA_NOREF) {
  117. lua_State *L = lua_getstate();
  118. lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref );
  119. lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size );
  120. luaL_pcallx( L, 1, 0 );
  121. }
  122. }
  123. free( fbrle_line );
  124. }
  125. break;
  126. default:
  127. return 0;
  128. break;
  129. }
  130. return 1;
  131. }
  132. uint8_t u8x8_d_overlay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  133. {
  134. uint8_t res = 1;
  135. u8g2_nodemcu_t *ext_u8g2 = (u8g2_nodemcu_t *)u8x8;
  136. switch(msg)
  137. {
  138. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  139. // only call for hardware display
  140. if (ext_u8g2->overlay.hardware_display_cb)
  141. return ext_u8g2->overlay.hardware_display_cb(u8x8, msg, arg_int, arg_ptr);
  142. break;
  143. default:
  144. // forward all messages first to hardware display and then to fbrle
  145. if (ext_u8g2->overlay.hardware_display_cb)
  146. res = ext_u8g2->overlay.hardware_display_cb(u8x8, msg, arg_int, arg_ptr);
  147. u8x8_d_fbrle(u8x8, msg, arg_int, arg_ptr);
  148. break;
  149. }
  150. return res;
  151. }