esphome 2024.12.3__py3-none-any.whl → 2025.2.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. esphome/__main__.py +16 -3
  2. esphome/components/adc/__init__.py +17 -11
  3. esphome/components/adc/adc_sensor.h +17 -0
  4. esphome/components/adc/adc_sensor_common.cpp +55 -0
  5. esphome/components/adc/adc_sensor_esp32.cpp +8 -5
  6. esphome/components/adc/adc_sensor_esp8266.cpp +10 -6
  7. esphome/components/adc/adc_sensor_libretiny.cpp +11 -6
  8. esphome/components/adc/adc_sensor_rp2040.cpp +13 -10
  9. esphome/components/adc/sensor.py +9 -3
  10. esphome/components/ads1115/ads1115.cpp +56 -7
  11. esphome/components/ads1115/ads1115.h +13 -1
  12. esphome/components/ads1115/sensor/__init__.py +16 -0
  13. esphome/components/ads1115/sensor/ads1115_sensor.cpp +2 -1
  14. esphome/components/ads1115/sensor/ads1115_sensor.h +2 -0
  15. esphome/components/animation/__init__.py +23 -261
  16. esphome/components/animation/animation.cpp +2 -2
  17. esphome/components/animation/animation.h +2 -1
  18. esphome/components/api/api_pb2.cpp +14 -0
  19. esphome/components/api/api_pb2.h +1 -0
  20. esphome/components/audio/__init__.py +112 -0
  21. esphome/components/audio/audio.cpp +67 -0
  22. esphome/components/audio/audio.h +125 -7
  23. esphome/components/audio/audio_decoder.cpp +361 -0
  24. esphome/components/audio/audio_decoder.h +135 -0
  25. esphome/components/audio/audio_reader.cpp +308 -0
  26. esphome/components/audio/audio_reader.h +85 -0
  27. esphome/components/audio/audio_resampler.cpp +159 -0
  28. esphome/components/audio/audio_resampler.h +101 -0
  29. esphome/components/audio/audio_transfer_buffer.cpp +165 -0
  30. esphome/components/audio/audio_transfer_buffer.h +139 -0
  31. esphome/components/audio_adc/__init__.py +41 -0
  32. esphome/components/audio_adc/audio_adc.h +17 -0
  33. esphome/components/audio_adc/automation.h +23 -0
  34. esphome/components/bk72xx/__init__.py +1 -0
  35. esphome/components/ble_client/ble_client.cpp +1 -2
  36. esphome/components/ble_client/sensor/__init__.py +1 -1
  37. esphome/components/ble_client/text_sensor/__init__.py +1 -1
  38. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -0
  39. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -0
  40. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
  41. esphome/components/ch422g/ch422g.h +2 -0
  42. esphome/components/climate/__init__.py +1 -1
  43. esphome/components/climate_ir/climate_ir.cpp +2 -1
  44. esphome/components/coolix/coolix.cpp +2 -1
  45. esphome/components/custom/__init__.py +0 -3
  46. esphome/components/custom/binary_sensor/__init__.py +2 -28
  47. esphome/components/custom/climate/__init__.py +2 -27
  48. esphome/components/custom/cover/__init__.py +2 -27
  49. esphome/components/custom/light/__init__.py +2 -27
  50. esphome/components/custom/output/__init__.py +2 -58
  51. esphome/components/custom/sensor/__init__.py +2 -24
  52. esphome/components/custom/switch/__init__.py +2 -24
  53. esphome/components/custom/text_sensor/__init__.py +2 -29
  54. esphome/components/custom_component/__init__.py +3 -27
  55. esphome/components/daly_bms/daly_bms.cpp +6 -0
  56. esphome/components/daly_bms/daly_bms.h +2 -0
  57. esphome/components/daly_bms/sensor.py +6 -0
  58. esphome/components/debug/debug_component.cpp +4 -0
  59. esphome/components/debug/debug_component.h +14 -0
  60. esphome/components/debug/debug_esp32.cpp +154 -74
  61. esphome/components/dfplayer/dfplayer.cpp +15 -2
  62. esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +2 -1
  63. esphome/components/dht/dht.cpp +2 -1
  64. esphome/components/display/__init__.py +18 -5
  65. esphome/components/display/display.cpp +2 -1
  66. esphome/components/display/rect.cpp +2 -1
  67. esphome/components/es7210/__init__.py +0 -0
  68. esphome/components/es7210/audio_adc.py +51 -0
  69. esphome/components/es7210/es7210.cpp +228 -0
  70. esphome/components/es7210/es7210.h +62 -0
  71. esphome/components/es7210/es7210_const.h +129 -0
  72. esphome/components/es7243e/__init__.py +0 -0
  73. esphome/components/es7243e/audio_adc.py +34 -0
  74. esphome/components/es7243e/es7243e.cpp +125 -0
  75. esphome/components/es7243e/es7243e.h +37 -0
  76. esphome/components/es7243e/es7243e_const.h +54 -0
  77. esphome/components/es8156/__init__.py +0 -0
  78. esphome/components/es8156/audio_dac.py +27 -0
  79. esphome/components/es8156/es8156.cpp +87 -0
  80. esphome/components/es8156/es8156.h +51 -0
  81. esphome/components/es8156/es8156_const.h +68 -0
  82. esphome/components/es8311/audio_dac.py +1 -2
  83. esphome/components/esp32/__init__.py +1 -0
  84. esphome/components/esp32/core.cpp +5 -1
  85. esphome/components/esp32/gpio.h +2 -0
  86. esphome/components/esp32_ble/__init__.py +39 -0
  87. esphome/components/esp32_ble/queue.h +4 -4
  88. esphome/components/esp32_ble_client/ble_client_base.cpp +46 -0
  89. esphome/components/esp32_ble_client/ble_client_base.h +2 -0
  90. esphome/components/esp32_ble_server/__init__.py +582 -12
  91. esphome/components/esp32_ble_server/ble_characteristic.cpp +48 -60
  92. esphome/components/esp32_ble_server/ble_characteristic.h +24 -17
  93. esphome/components/esp32_ble_server/ble_descriptor.cpp +21 -9
  94. esphome/components/esp32_ble_server/ble_descriptor.h +17 -6
  95. esphome/components/esp32_ble_server/ble_server.cpp +62 -67
  96. esphome/components/esp32_ble_server/ble_server.h +28 -32
  97. esphome/components/esp32_ble_server/ble_server_automations.cpp +77 -0
  98. esphome/components/esp32_ble_server/ble_server_automations.h +115 -0
  99. esphome/components/esp32_ble_server/ble_service.cpp +17 -15
  100. esphome/components/esp32_ble_server/ble_service.h +10 -14
  101. esphome/components/esp32_ble_tracker/__init__.py +6 -39
  102. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +33 -10
  103. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +8 -4
  104. esphome/components/esp32_improv/__init__.py +2 -8
  105. esphome/components/esp32_improv/esp32_improv_component.cpp +21 -20
  106. esphome/components/esp32_improv/esp32_improv_component.h +3 -4
  107. esphome/components/esp32_rmt/__init__.py +28 -3
  108. esphome/components/esp32_rmt_led_strip/led_strip.cpp +73 -6
  109. esphome/components/esp32_rmt_led_strip/led_strip.h +21 -3
  110. esphome/components/esp32_rmt_led_strip/light.py +72 -7
  111. esphome/components/esp32_touch/esp32_touch.cpp +5 -0
  112. esphome/components/esp8266/__init__.py +1 -0
  113. esphome/components/esp8266/gpio.h +1 -0
  114. esphome/components/ethernet/__init__.py +10 -10
  115. esphome/components/event/event.cpp +4 -2
  116. esphome/components/event/event.h +2 -0
  117. esphome/components/event_emitter/__init__.py +5 -0
  118. esphome/components/event_emitter/event_emitter.cpp +14 -0
  119. esphome/components/event_emitter/event_emitter.h +63 -0
  120. esphome/components/gcja5/gcja5.cpp +2 -1
  121. esphome/components/haier/haier_base.cpp +2 -1
  122. esphome/components/haier/hon_climate.cpp +2 -1
  123. esphome/components/heatpumpir/heatpumpir.cpp +2 -1
  124. esphome/components/host/__init__.py +1 -0
  125. esphome/components/host/gpio.h +1 -0
  126. esphome/components/http_request/http_request.h +2 -2
  127. esphome/components/http_request/http_request_arduino.cpp +1 -1
  128. esphome/components/http_request/http_request_idf.cpp +1 -1
  129. esphome/components/i2c/i2c_bus_esp_idf.cpp +4 -0
  130. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +7 -5
  131. esphome/components/i2s_audio/speaker/__init__.py +53 -6
  132. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +92 -46
  133. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -0
  134. esphome/components/ili9xxx/display.py +29 -11
  135. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -5
  136. esphome/components/ili9xxx/ili9xxx_display.h +2 -1
  137. esphome/components/image/__init__.py +443 -255
  138. esphome/components/image/image.cpp +115 -61
  139. esphome/components/image/image.h +15 -24
  140. esphome/components/json/json_util.cpp +8 -34
  141. esphome/components/libretiny/__init__.py +1 -0
  142. esphome/components/libretiny/gpio_arduino.h +1 -0
  143. esphome/components/light/light_color_values.h +1 -1
  144. esphome/components/logger/__init__.py +43 -7
  145. esphome/components/logger/logger.cpp +16 -11
  146. esphome/components/logger/logger.h +11 -7
  147. esphome/components/logger/select/__init__.py +29 -0
  148. esphome/components/logger/select/logger_level_select.cpp +27 -0
  149. esphome/components/logger/select/logger_level_select.h +15 -0
  150. esphome/components/lvgl/__init__.py +96 -73
  151. esphome/components/lvgl/automation.py +39 -7
  152. esphome/components/lvgl/defines.py +8 -2
  153. esphome/components/lvgl/lvgl_esphome.cpp +8 -15
  154. esphome/components/lvgl/lvgl_esphome.h +20 -5
  155. esphome/components/lvgl/schemas.py +25 -14
  156. esphome/components/lvgl/trigger.py +27 -3
  157. esphome/components/lvgl/widgets/dropdown.py +1 -1
  158. esphome/components/lvgl/widgets/keyboard.py +8 -1
  159. esphome/components/lvgl/widgets/meter.py +2 -1
  160. esphome/components/lvgl/widgets/msgbox.py +1 -1
  161. esphome/components/lvgl/widgets/obj.py +1 -12
  162. esphome/components/lvgl/widgets/page.py +37 -2
  163. esphome/components/lvgl/widgets/tabview.py +1 -1
  164. esphome/components/max6956/max6956.h +2 -0
  165. esphome/components/mcp23016/mcp23016.h +2 -0
  166. esphome/components/mcp23xxx_base/mcp23xxx_base.h +2 -0
  167. esphome/components/mdns/__init__.py +1 -1
  168. esphome/components/media_player/__init__.py +37 -8
  169. esphome/components/media_player/automation.h +11 -2
  170. esphome/components/media_player/media_player.cpp +8 -0
  171. esphome/components/media_player/media_player.h +8 -4
  172. esphome/components/micronova/switch/micronova_switch.cpp +4 -2
  173. esphome/components/midea/ac_automations.h +3 -1
  174. esphome/components/midea/air_conditioner.cpp +7 -5
  175. esphome/components/midea/air_conditioner.h +1 -1
  176. esphome/components/midea/climate.py +4 -2
  177. esphome/components/midea/ir_transmitter.h +36 -5
  178. esphome/components/mixer/__init__.py +0 -0
  179. esphome/components/mixer/speaker/__init__.py +172 -0
  180. esphome/components/mixer/speaker/automation.h +19 -0
  181. esphome/components/mixer/speaker/mixer_speaker.cpp +624 -0
  182. esphome/components/mixer/speaker/mixer_speaker.h +207 -0
  183. esphome/components/mpr121/mpr121.h +2 -0
  184. esphome/components/mqtt/__init__.py +1 -1
  185. esphome/components/mqtt/mqtt_client.cpp +7 -1
  186. esphome/components/mqtt/mqtt_client.h +1 -1
  187. esphome/components/mqtt/mqtt_climate.cpp +2 -2
  188. esphome/components/network/ip_address.h +2 -0
  189. esphome/components/nextion/automation.h +17 -0
  190. esphome/components/nextion/display.py +42 -17
  191. esphome/components/nextion/nextion.cpp +4 -10
  192. esphome/components/nextion/nextion.h +89 -82
  193. esphome/components/nextion/nextion_commands.cpp +10 -10
  194. esphome/components/ntc/sensor.py +2 -4
  195. esphome/components/online_image/__init__.py +98 -46
  196. esphome/components/online_image/bmp_image.cpp +101 -0
  197. esphome/components/online_image/bmp_image.h +40 -0
  198. esphome/components/online_image/image_decoder.cpp +28 -2
  199. esphome/components/online_image/image_decoder.h +24 -15
  200. esphome/components/online_image/jpeg_image.cpp +90 -0
  201. esphome/components/online_image/jpeg_image.h +34 -0
  202. esphome/components/online_image/online_image.cpp +112 -53
  203. esphome/components/online_image/online_image.h +24 -7
  204. esphome/components/online_image/png_image.cpp +7 -3
  205. esphome/components/online_image/png_image.h +2 -1
  206. esphome/components/opentherm/__init__.py +73 -7
  207. esphome/components/opentherm/automation.h +25 -0
  208. esphome/components/opentherm/const.py +1 -0
  209. esphome/components/opentherm/generate.py +39 -6
  210. esphome/components/opentherm/hub.cpp +117 -79
  211. esphome/components/opentherm/hub.h +31 -15
  212. esphome/components/opentherm/opentherm.cpp +47 -23
  213. esphome/components/opentherm/opentherm.h +27 -6
  214. esphome/components/opentherm/opentherm_macros.h +11 -0
  215. esphome/components/opentherm/schema.py +78 -1
  216. esphome/components/opentherm/validate.py +7 -2
  217. esphome/components/pca6416a/pca6416a.h +2 -0
  218. esphome/components/pca9554/pca9554.h +2 -0
  219. esphome/components/pcf8574/pcf8574.h +2 -0
  220. esphome/components/preferences/__init__.py +2 -4
  221. esphome/components/preferences/syncer.h +10 -3
  222. esphome/components/prometheus/prometheus_handler.cpp +313 -0
  223. esphome/components/prometheus/prometheus_handler.h +48 -7
  224. esphome/components/psram/psram.cpp +8 -1
  225. esphome/components/pulse_counter/pulse_counter_sensor.cpp +14 -9
  226. esphome/components/pulse_counter/pulse_counter_sensor.h +4 -4
  227. esphome/components/pulse_meter/pulse_meter_sensor.cpp +2 -0
  228. esphome/components/qspi_dbi/__init__.py +3 -0
  229. esphome/components/qspi_dbi/display.py +74 -47
  230. esphome/components/qspi_dbi/models.py +245 -2
  231. esphome/components/qspi_dbi/qspi_dbi.cpp +9 -16
  232. esphome/components/qspi_dbi/qspi_dbi.h +2 -2
  233. esphome/components/remote_base/__init__.py +77 -25
  234. esphome/components/remote_base/remote_base.cpp +1 -1
  235. esphome/components/remote_base/remote_base.h +20 -2
  236. esphome/components/remote_base/toto_protocol.cpp +100 -0
  237. esphome/components/remote_base/toto_protocol.h +45 -0
  238. esphome/components/remote_receiver/__init__.py +55 -10
  239. esphome/components/remote_receiver/remote_receiver.h +36 -3
  240. esphome/components/remote_receiver/remote_receiver_esp32.cpp +145 -6
  241. esphome/components/remote_transmitter/__init__.py +62 -4
  242. esphome/components/remote_transmitter/remote_transmitter.h +21 -2
  243. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +140 -4
  244. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +3 -3
  245. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +3 -3
  246. esphome/components/resampler/__init__.py +0 -0
  247. esphome/components/resampler/speaker/__init__.py +103 -0
  248. esphome/components/resampler/speaker/resampler_speaker.cpp +318 -0
  249. esphome/components/resampler/speaker/resampler_speaker.h +107 -0
  250. esphome/components/resistance/resistance_sensor.h +2 -3
  251. esphome/components/resistance/sensor.py +2 -9
  252. esphome/components/rotary_encoder/rotary_encoder.cpp +8 -4
  253. esphome/components/rp2040/__init__.py +1 -0
  254. esphome/components/rp2040/gpio.h +1 -0
  255. esphome/components/rtl87xx/__init__.py +2 -0
  256. esphome/components/sdl/binary_sensor.py +270 -0
  257. esphome/components/sdl/sdl_esphome.cpp +16 -0
  258. esphome/components/sdl/sdl_esphome.h +9 -0
  259. esphome/components/seeed_mr60bha2/binary_sensor.py +25 -0
  260. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +26 -2
  261. esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +9 -20
  262. esphome/components/seeed_mr60bha2/sensor.py +9 -1
  263. esphome/components/sn74hc165/sn74hc165.h +3 -0
  264. esphome/components/sn74hc595/sn74hc595.h +3 -0
  265. esphome/components/speaker/__init__.py +5 -4
  266. esphome/components/speaker/media_player/__init__.py +458 -0
  267. esphome/components/speaker/media_player/audio_pipeline.cpp +568 -0
  268. esphome/components/speaker/media_player/audio_pipeline.h +159 -0
  269. esphome/components/speaker/media_player/automation.h +26 -0
  270. esphome/components/speaker/media_player/speaker_media_player.cpp +577 -0
  271. esphome/components/speaker/media_player/speaker_media_player.h +160 -0
  272. esphome/components/speaker/speaker.h +20 -0
  273. esphome/components/spi/__init__.py +1 -5
  274. esphome/components/spi/spi.cpp +7 -1
  275. esphome/components/spi/spi.h +21 -2
  276. esphome/components/spi_led_strip/light.py +3 -5
  277. esphome/components/spi_led_strip/spi_led_strip.cpp +67 -0
  278. esphome/components/spi_led_strip/spi_led_strip.h +8 -60
  279. esphome/components/sprinkler/sprinkler.cpp +3 -1
  280. esphome/components/sx1509/sx1509_gpio_pin.h +2 -0
  281. esphome/components/tca9555/tca9555.h +2 -0
  282. esphome/components/toshiba/toshiba.cpp +2 -1
  283. esphome/components/tuya/light/tuya_light.cpp +4 -2
  284. esphome/components/uart/uart_component_esp32_arduino.cpp +2 -2
  285. esphome/components/uart/uart_component_esp_idf.cpp +2 -2
  286. esphome/components/udp/__init__.py +8 -2
  287. esphome/components/udp/udp_component.cpp +25 -56
  288. esphome/components/udp/udp_component.h +3 -0
  289. esphome/components/uponor_smatrix/sensor/__init__.py +14 -4
  290. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +5 -0
  291. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.h +1 -0
  292. esphome/components/uptime/text_sensor/__init__.py +19 -0
  293. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +63 -0
  294. esphome/components/uptime/text_sensor/uptime_text_sensor.h +25 -0
  295. esphome/components/voice_assistant/voice_assistant.cpp +24 -14
  296. esphome/components/voice_assistant/voice_assistant.h +8 -0
  297. esphome/components/waveshare_epaper/display.py +22 -1
  298. esphome/components/waveshare_epaper/waveshare_213v3.cpp +9 -3
  299. esphome/components/waveshare_epaper/waveshare_epaper.cpp +1155 -44
  300. esphome/components/waveshare_epaper/waveshare_epaper.h +208 -7
  301. esphome/components/web_server/web_server.cpp +28 -6
  302. esphome/components/weikai/weikai.h +2 -0
  303. esphome/components/wifi/__init__.py +6 -6
  304. esphome/components/wifi/wifi_component.cpp +1 -1
  305. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -1
  306. esphome/components/wireguard/__init__.py +2 -2
  307. esphome/components/xl9535/xl9535.h +2 -0
  308. esphome/components/xxtea/__init__.py +3 -0
  309. esphome/components/xxtea/xxtea.cpp +46 -0
  310. esphome/components/xxtea/xxtea.h +26 -0
  311. esphome/components/yashima/yashima.cpp +2 -1
  312. esphome/config.py +9 -5
  313. esphome/config_validation.py +55 -17
  314. esphome/const.py +7 -10
  315. esphome/core/__init__.py +6 -13
  316. esphome/core/base_automation.h +1 -0
  317. esphome/core/config.py +57 -72
  318. esphome/core/defines.h +9 -1
  319. esphome/core/gpio.h +7 -0
  320. esphome/core/helpers.cpp +19 -15
  321. esphome/core/helpers.h +57 -8
  322. esphome/core/log.h +9 -7
  323. esphome/cpp_generator.py +2 -2
  324. esphome/espota2.py +3 -2
  325. esphome/loader.py +12 -4
  326. esphome/log.py +5 -7
  327. esphome/yaml_util.py +2 -2
  328. {esphome-2024.12.3.dist-info → esphome-2025.2.0b1.dist-info}/METADATA +12 -7
  329. {esphome-2024.12.3.dist-info → esphome-2025.2.0b1.dist-info}/RECORD +338 -289
  330. esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +0 -16
  331. esphome/components/custom/binary_sensor/custom_binary_sensor.h +0 -26
  332. esphome/components/custom/climate/custom_climate.h +0 -22
  333. esphome/components/custom/cover/custom_cover.h +0 -21
  334. esphome/components/custom/light/custom_light_output.h +0 -24
  335. esphome/components/custom/output/custom_output.h +0 -37
  336. esphome/components/custom/sensor/custom_sensor.cpp +0 -16
  337. esphome/components/custom/sensor/custom_sensor.h +0 -24
  338. esphome/components/custom/switch/custom_switch.cpp +0 -16
  339. esphome/components/custom/switch/custom_switch.h +0 -24
  340. esphome/components/custom/text_sensor/custom_text_sensor.cpp +0 -16
  341. esphome/components/custom/text_sensor/custom_text_sensor.h +0 -26
  342. esphome/components/custom_component/custom_component.h +0 -28
  343. esphome/components/esp32_ble_server/ble_2901.cpp +0 -18
  344. esphome/components/esp32_ble_server/ble_2901.h +0 -19
  345. esphome/components/resistance_sampler/__init__.py +0 -6
  346. esphome/components/resistance_sampler/resistance_sampler.h +0 -10
  347. esphome/components/uptime/{sensor.py → sensor/__init__.py} +3 -3
  348. /esphome/components/uptime/{uptime_seconds_sensor.cpp → sensor/uptime_seconds_sensor.cpp} +0 -0
  349. /esphome/components/uptime/{uptime_seconds_sensor.h → sensor/uptime_seconds_sensor.h} +0 -0
  350. /esphome/components/uptime/{uptime_timestamp_sensor.cpp → sensor/uptime_timestamp_sensor.cpp} +0 -0
  351. /esphome/components/uptime/{uptime_timestamp_sensor.h → sensor/uptime_timestamp_sensor.h} +0 -0
  352. {esphome-2024.12.3.dist-info → esphome-2025.2.0b1.dist-info}/LICENSE +0 -0
  353. {esphome-2024.12.3.dist-info → esphome-2025.2.0b1.dist-info}/WHEEL +0 -0
  354. {esphome-2024.12.3.dist-info → esphome-2025.2.0b1.dist-info}/entry_points.txt +0 -0
  355. {esphome-2024.12.3.dist-info → esphome-2025.2.0b1.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@
3
3
  #include "esphome/core/application.h"
4
4
  #include "esphome/core/helpers.h"
5
5
  #include <cinttypes>
6
+ #include <bitset>
6
7
 
7
8
  namespace esphome {
8
9
  namespace waveshare_epaper {
@@ -110,8 +111,14 @@ static const uint8_t PARTIAL_UPD_2IN9_LUT[PARTIAL_UPD_2IN9_LUT_SIZE] =
110
111
  };
111
112
  // clang-format on
112
113
 
113
- void WaveshareEPaperBase::setup_pins_() {
114
+ void WaveshareEPaperBase::setup() {
114
115
  this->init_internal_(this->get_buffer_length_());
116
+ this->setup_pins_();
117
+ this->spi_setup();
118
+ this->reset_();
119
+ this->initialize();
120
+ }
121
+ void WaveshareEPaperBase::setup_pins_() {
115
122
  this->dc_pin_->setup(); // OUTPUT
116
123
  this->dc_pin_->digital_write(false);
117
124
  if (this->reset_pin_ != nullptr) {
@@ -121,9 +128,6 @@ void WaveshareEPaperBase::setup_pins_() {
121
128
  if (this->busy_pin_ != nullptr) {
122
129
  this->busy_pin_->setup(); // INPUT
123
130
  }
124
- this->spi_setup();
125
-
126
- this->reset_();
127
131
  }
128
132
  float WaveshareEPaperBase::get_setup_priority() const { return setup_priority::PROCESSOR; }
129
133
  void WaveshareEPaperBase::command(uint8_t value) {
@@ -173,6 +177,87 @@ void WaveshareEPaper::fill(Color color) {
173
177
  for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
174
178
  this->buffer_[i] = fill;
175
179
  }
180
+ void WaveshareEPaper7C::setup() {
181
+ this->init_internal_7c_(this->get_buffer_length_());
182
+ this->setup_pins_();
183
+ this->spi_setup();
184
+ this->reset_();
185
+ this->initialize();
186
+ }
187
+ void WaveshareEPaper7C::init_internal_7c_(uint32_t buffer_length) {
188
+ ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
189
+ uint32_t small_buffer_length = buffer_length / NUM_BUFFERS;
190
+
191
+ for (int i = 0; i < NUM_BUFFERS; i++) {
192
+ this->buffers_[i] = allocator.allocate(small_buffer_length);
193
+ if (this->buffers_[i] == nullptr) {
194
+ ESP_LOGE(TAG, "Could not allocate buffer %d for display!", i);
195
+ for (auto &buffer : this->buffers_) {
196
+ allocator.deallocate(buffer, small_buffer_length);
197
+ buffer = nullptr;
198
+ }
199
+ return;
200
+ }
201
+ }
202
+ this->clear();
203
+ }
204
+ uint8_t WaveshareEPaper7C::color_to_hex(Color color) {
205
+ uint8_t hex_code;
206
+ if (color.red > 127) {
207
+ if (color.green > 170) {
208
+ if (color.blue > 127) {
209
+ hex_code = 0x1; // White
210
+ } else {
211
+ hex_code = 0x5; // Yellow
212
+ }
213
+ } else if (color.green > 85) {
214
+ hex_code = 0x6; // Orange
215
+ } else {
216
+ hex_code = 0x4; // Red (or Magenta)
217
+ }
218
+ } else {
219
+ if (color.green > 127) {
220
+ if (color.blue > 127) {
221
+ hex_code = 0x3; // Cyan -> Blue
222
+ } else {
223
+ hex_code = 0x2; // Green
224
+ }
225
+ } else {
226
+ if (color.blue > 127) {
227
+ hex_code = 0x3; // Blue
228
+ } else {
229
+ hex_code = 0x0; // Black
230
+ }
231
+ }
232
+ }
233
+
234
+ return hex_code;
235
+ }
236
+ void WaveshareEPaper7C::fill(Color color) {
237
+ uint8_t pixel_color;
238
+ if (color.is_on()) {
239
+ pixel_color = this->color_to_hex(color);
240
+ } else {
241
+ pixel_color = 0x1;
242
+ }
243
+
244
+ if (this->buffers_[0] == nullptr) {
245
+ ESP_LOGE(TAG, "Buffer unavailable!");
246
+ } else {
247
+ uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
248
+ for (auto &buffer : this->buffers_) {
249
+ for (uint32_t buffer_pos = 0; buffer_pos < small_buffer_length; buffer_pos += 3) {
250
+ // We store 8 bitset<3> in 3 bytes
251
+ // | byte 1 | byte 2 | byte 3 |
252
+ // |aaabbbaa|abbbaaab|bbaaabbb|
253
+ buffer[buffer_pos + 0] = pixel_color << 5 | pixel_color << 2 | pixel_color >> 1;
254
+ buffer[buffer_pos + 1] = pixel_color << 7 | pixel_color << 4 | pixel_color << 1 | pixel_color >> 2;
255
+ buffer[buffer_pos + 2] = pixel_color << 6 | pixel_color << 3 | pixel_color << 0;
256
+ }
257
+ App.feed_wdt();
258
+ }
259
+ }
260
+ }
176
261
  void HOT WaveshareEPaper::draw_absolute_pixel_internal(int x, int y, Color color) {
177
262
  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
178
263
  return;
@@ -193,6 +278,9 @@ uint32_t WaveshareEPaper::get_buffer_length_() {
193
278
  uint32_t WaveshareEPaperBWR::get_buffer_length_() {
194
279
  return this->get_width_controller() * this->get_height_internal() / 4u;
195
280
  } // black and red buffer
281
+ uint32_t WaveshareEPaper7C::get_buffer_length_() {
282
+ return this->get_width_controller() * this->get_height_internal() / 8u * 3u;
283
+ } // 7 colors buffer, 1 pixel = 3 bits, we will store 8 pixels in 24 bits = 3 bytes
196
284
 
197
285
  void WaveshareEPaperBWR::fill(Color color) {
198
286
  this->filled_rectangle(0, 0, this->get_width(), this->get_height(), color);
@@ -219,7 +307,33 @@ void HOT WaveshareEPaperBWR::draw_absolute_pixel_internal(int x, int y, Color co
219
307
  this->buffer_[pos + buf_half_len] &= ~(0x80 >> subpos);
220
308
  }
221
309
  }
310
+ void HOT WaveshareEPaper7C::draw_absolute_pixel_internal(int x, int y, Color color) {
311
+ if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
312
+ return;
313
+
314
+ uint8_t pixel_bits = this->color_to_hex(color);
315
+ uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
316
+ uint32_t pixel_position = x + y * this->get_width_controller();
317
+ uint32_t first_bit_position = pixel_position * 3;
318
+ uint32_t byte_position = first_bit_position / 8u;
319
+ uint32_t byte_subposition = first_bit_position % 8u;
320
+ uint32_t buffer_position = byte_position / small_buffer_length;
321
+ uint32_t buffer_subposition = byte_position % small_buffer_length;
322
+
323
+ if (byte_subposition <= 5) {
324
+ this->buffers_[buffer_position][buffer_subposition] =
325
+ (this->buffers_[buffer_position][buffer_subposition] & (0xFF ^ (0b111 << (5 - byte_subposition)))) |
326
+ (pixel_bits << (5 - byte_subposition));
327
+ } else {
328
+ this->buffers_[buffer_position][buffer_subposition + 0] =
329
+ (this->buffers_[buffer_position][buffer_subposition + 0] & (0xFF ^ (0b111 >> (byte_subposition - 5)))) |
330
+ (pixel_bits >> (byte_subposition - 5));
222
331
 
332
+ this->buffers_[buffer_position][buffer_subposition + 1] = (this->buffers_[buffer_position][buffer_subposition + 1] &
333
+ (0xFF ^ (0xFF & (0b111 << (13 - byte_subposition))))) |
334
+ (pixel_bits << (13 - byte_subposition));
335
+ }
336
+ }
223
337
  void WaveshareEPaperBase::start_command_() {
224
338
  this->dc_pin_->digital_write(false);
225
339
  this->enable();
@@ -1211,6 +1325,93 @@ void WaveshareEPaper2P9InB::dump_config() {
1211
1325
  LOG_UPDATE_INTERVAL(this);
1212
1326
  }
1213
1327
 
1328
+ // ========================================================
1329
+ // Waveshare 2.9-inch E-Paper (Type D)
1330
+ // Waveshare WIKI: https://www.waveshare.com/wiki/Pico-ePaper-2.9-D
1331
+ // Datasheet: https://www.waveshare.com/w/upload/b/b5/2.9inch_e-Paper_(D)_Specification.pdf
1332
+ // ========================================================
1333
+
1334
+ void WaveshareEPaper2P9InD::initialize() {
1335
+ // EPD hardware init start
1336
+ this->reset_();
1337
+
1338
+ // Booster Soft Start
1339
+ this->command(0x06); // Command: BTST
1340
+ this->data(0x17); // Soft start configuration Phase A
1341
+ this->data(0x17); // Soft start configuration Phase B
1342
+ this->data(0x17); // Soft start configuration Phase C
1343
+
1344
+ // Power Setting
1345
+ this->command(0x01); // Command: PWR
1346
+ this->data(0x03); // Intern DC/DC for VDH/VDL and VGH/VGL
1347
+ this->data(0x00); // Default configuration VCOM_HV and VGHL_LV
1348
+ this->data(0x2b); // VDH = 10.8 V
1349
+ this->data(0x2b); // VDL = -10.8 V
1350
+
1351
+ // Power ON
1352
+ this->command(0x04); // Command: PON
1353
+ this->wait_until_idle_();
1354
+
1355
+ // Panel settings
1356
+ this->command(0x00); // Command: PSR
1357
+ this->data(0x1F); // LUT from OTP, black and white mode, default scan
1358
+
1359
+ // PLL Control
1360
+ this->command(0x30); // Command: PLL
1361
+ this->data(0x3A); // Default PLL frequency
1362
+
1363
+ // Resolution settings
1364
+ this->command(0x61); // Command: TRES
1365
+ this->data(0x80); // Width: 128
1366
+ this->data(0x01); // Height MSB: 296
1367
+ this->data(0x28); // Height LSB: 296
1368
+
1369
+ // VCOM and data interval settings
1370
+ this->command(0x50); // Command: CDI
1371
+ this->data(0x77);
1372
+
1373
+ // VCOM_DC settings
1374
+ this->command(0x82); // Command: VDCS
1375
+ this->data(0x12); // Dafault VCOM_DC
1376
+ }
1377
+
1378
+ void WaveshareEPaper2P9InD::display() {
1379
+ // Start transmitting old data (clearing buffer)
1380
+ this->command(0x10); // Command: DTM1 (OLD frame data)
1381
+ this->start_data_();
1382
+ this->write_array(this->buffer_, this->get_buffer_length_());
1383
+ this->end_data_();
1384
+
1385
+ // Start transmitting new data (updated content)
1386
+ this->command(0x13); // Command: DTM2 (NEW frame data)
1387
+ this->start_data_();
1388
+ this->write_array(this->buffer_, this->get_buffer_length_());
1389
+ this->end_data_();
1390
+
1391
+ // Refresh Display
1392
+ this->command(0x12); // Command: DRF
1393
+ this->wait_until_idle_();
1394
+
1395
+ // Enter Power Off
1396
+ this->command(0x02); // Command: POF
1397
+ this->wait_until_idle_();
1398
+
1399
+ // Enter Deep Sleep
1400
+ this->command(0x07); // Command: DSLP
1401
+ this->data(0xA5);
1402
+ }
1403
+
1404
+ int WaveshareEPaper2P9InD::get_width_internal() { return 128; }
1405
+ int WaveshareEPaper2P9InD::get_height_internal() { return 296; }
1406
+ void WaveshareEPaper2P9InD::dump_config() {
1407
+ LOG_DISPLAY("", "Waveshare E-Paper", this);
1408
+ ESP_LOGCONFIG(TAG, " Model: 2.9in (D)");
1409
+ LOG_PIN(" Reset Pin: ", this->reset_pin_);
1410
+ LOG_PIN(" DC Pin: ", this->dc_pin_);
1411
+ LOG_PIN(" Busy Pin: ", this->busy_pin_);
1412
+ LOG_UPDATE_INTERVAL(this);
1413
+ }
1414
+
1214
1415
  // DKE 2.9
1215
1416
  // https://www.badge.team/docs/badges/sha2017/hardware/#e-ink-display-the-dke-group-depg0290b1
1216
1417
  // https://www.badge.team/docs/badges/sha2017/hardware/DEPG0290B01V3.0.pdf
@@ -1590,21 +1791,187 @@ int WaveshareEPaper2P9InV2R2::get_width_controller() { return this->get_width_in
1590
1791
  void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every) {
1591
1792
  this->full_update_every_ = full_update_every;
1592
1793
  }
1794
+ // ========================================================
1795
+ // Good Display 2.9in black/white
1796
+ // Datasheet:
1797
+ // - https://files.seeedstudio.com/wiki/Other_Display/29-epaper/GDEY029T94.pdf
1798
+ // -
1799
+ // https://github.com/Allen-Kuang/e-ink_Demo/blob/main/2.9%20inch%20E-paper%20-%20monocolor%20128x296/example/Display_EPD_W21.cpp
1800
+ // ========================================================
1801
+
1802
+ void GDEY029T94::initialize() {
1803
+ // EPD hardware init start
1804
+ this->reset_();
1805
+
1806
+ this->wait_until_idle_();
1807
+ this->command(0x12); // SWRESET
1808
+ this->wait_until_idle_();
1809
+
1810
+ this->command(0x01); // Driver output control
1811
+ this->data((this->get_height_internal() - 1) % 256);
1812
+ this->data((this->get_height_internal() - 1) / 256);
1813
+ this->data(0x00);
1814
+
1815
+ this->command(0x11); // data entry mode
1816
+ this->data(0x03);
1817
+
1818
+ this->command(0x44); // set Ram-X address start/end position
1819
+ this->data(0x00);
1820
+ this->data(this->get_width_internal() / 8 - 1);
1821
+
1822
+ this->command(0x45); // set Ram-Y address start/end position
1823
+ this->data(0x00);
1824
+ this->data(0x00);
1825
+ this->data((this->get_height_internal() - 1) % 256);
1826
+ this->data((this->get_height_internal() - 1) / 256);
1827
+
1828
+ this->command(0x3C); // BorderWavefrom
1829
+ this->data(0x05);
1830
+
1831
+ this->command(0x21); // Display update control
1832
+ this->data(0x00);
1833
+ this->data(0x80);
1834
+
1835
+ this->command(0x18); // Read built-in temperature sensor
1836
+ this->data(0x80);
1837
+
1838
+ this->command(0x4E); // set RAM x address count to 0;
1839
+ this->data(0x00);
1840
+ this->command(0x4F); // set RAM y address count to 0X199;
1841
+ this->command(0x00);
1842
+ this->command(0x00);
1843
+ this->wait_until_idle_();
1844
+ }
1845
+ void HOT GDEY029T94::display() {
1846
+ this->command(0x24); // write RAM for black(0)/white (1)
1847
+ this->start_data_();
1848
+ for (uint32_t i = 0; i < this->get_buffer_length_(); i++) {
1849
+ this->write_byte(this->buffer_[i]);
1850
+ }
1851
+ this->end_data_();
1852
+ this->command(0x22); // Display Update Control
1853
+ this->data(0xF7);
1854
+ this->command(0x20); // Activate Display Update Sequence
1855
+ this->wait_until_idle_();
1856
+ }
1857
+ int GDEY029T94::get_width_internal() { return 128; }
1858
+ int GDEY029T94::get_height_internal() { return 296; }
1859
+ void GDEY029T94::dump_config() {
1860
+ LOG_DISPLAY("", "E-Paper (Good Display)", this);
1861
+ ESP_LOGCONFIG(TAG, " Model: 2.9in GDEY029T94");
1862
+ LOG_PIN(" Reset Pin: ", this->reset_pin_);
1863
+ LOG_PIN(" DC Pin: ", this->dc_pin_);
1864
+ LOG_PIN(" Busy Pin: ", this->busy_pin_);
1865
+ LOG_UPDATE_INTERVAL(this);
1866
+ }
1593
1867
 
1594
1868
  // ========================================================
1595
- // Good Display 2.9in black/white/grey
1869
+ // Good Display 2.9in black/white
1596
1870
  // Datasheet:
1597
1871
  // - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1680.pdf
1598
1872
  // - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h
1873
+ // - https://github.com/ZinggJM/GxEPD2/blob/master/src/epd/GxEPD2_290_T5.cpp
1874
+ // - http://www.e-paper-display.com/GDEW029T5%20V3.1%20Specification5c22.pdf?
1599
1875
  // ========================================================
1600
1876
 
1601
- void GDEW029T5::initialize() {
1602
- // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
1603
- // EPD hardware init start
1604
- this->reset_();
1877
+ // full screen update LUT
1878
+ static const uint8_t LUT_20_VCOMDC_29_5[] = {
1879
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x60, 0x28, 0x28, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00,
1880
+ 0x00, 0x00, 0x01, 0x00, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1881
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1882
+ };
1883
+
1884
+ static const uint8_t LUT_21_WW_29_5[] = {
1885
+ 0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14,
1886
+ 0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1887
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1888
+ };
1889
+
1890
+ static const uint8_t LUT_22_BW_29_5[] = {
1891
+ 0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14,
1892
+ 0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1893
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1894
+ };
1895
+
1896
+ static const uint8_t LUT_23_WB_29_5[] = {
1897
+ 0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14,
1898
+ 0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1899
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1900
+ };
1901
+
1902
+ static const uint8_t LUT_24_BB_29_5[] = {
1903
+ 0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14,
1904
+ 0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1905
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1906
+ };
1907
+
1908
+ // partial screen update LUT
1909
+ static const uint8_t LUT_20_VCOMDC_PARTIAL_29_5[] = {
1910
+ 0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1911
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1912
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1913
+ };
1914
+
1915
+ static const uint8_t LUT_21_WW_PARTIAL_29_5[] = {
1916
+ 0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1917
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1918
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1919
+ };
1920
+
1921
+ static const uint8_t LUT_22_BW_PARTIAL_29_5[] = {
1922
+ 0x80, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1923
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1924
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1925
+ };
1926
+
1927
+ static const uint8_t LUT_23_WB_PARTIAL_29_5[] = {
1928
+ 0x40, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1929
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1931
+ };
1932
+
1933
+ static const uint8_t LUT_24_BB_PARTIAL_29_5[] = {
1934
+ 0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1935
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1936
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1937
+ };
1938
+
1939
+ void GDEW029T5::power_on_() {
1940
+ if (!this->power_is_on_) {
1941
+ this->command(0x04);
1942
+ this->wait_until_idle_();
1943
+ }
1944
+ this->power_is_on_ = true;
1945
+ }
1946
+
1947
+ void GDEW029T5::power_off_() {
1948
+ this->command(0x02);
1949
+ this->wait_until_idle_();
1950
+ this->power_is_on_ = false;
1951
+ }
1952
+
1953
+ void GDEW029T5::deep_sleep() {
1954
+ this->power_off_();
1955
+ if (this->deep_sleep_between_updates_) {
1956
+ this->command(0x07); // deep sleep
1957
+ this->data(0xA5); // check code
1958
+ ESP_LOGD(TAG, "go to deep sleep");
1959
+ this->is_deep_sleep_ = true;
1960
+ }
1961
+ }
1962
+
1963
+ void GDEW029T5::init_display_() {
1964
+ // from https://github.com/ZinggJM/GxEPD2/blob/master/src/epd/GxEPD2_290_T5.cpp
1965
+
1966
+ // Hardware Initialization
1967
+ if (this->deep_sleep_between_updates_ && this->is_deep_sleep_) {
1968
+ ESP_LOGI(TAG, "wake up from deep sleep");
1969
+ this->reset_();
1970
+ this->is_deep_sleep_ = false;
1971
+ }
1605
1972
 
1606
1973
  // COMMAND POWER SETTINGS
1607
- this->command(0x00);
1974
+ this->command(0x01);
1608
1975
  this->data(0x03);
1609
1976
  this->data(0x00);
1610
1977
  this->data(0x2b);
@@ -1617,40 +1984,122 @@ void GDEW029T5::initialize() {
1617
1984
  this->data(0x17);
1618
1985
  this->data(0x17);
1619
1986
 
1620
- // COMMAND POWER ON
1621
- this->command(0x04);
1622
- this->wait_until_idle_();
1623
-
1624
- // Not sure what this does but it's in the Adafruit EPD library
1625
- this->command(0xFF);
1626
- this->wait_until_idle_();
1987
+ this->power_on_();
1627
1988
 
1628
1989
  // COMMAND PANEL SETTING
1629
1990
  this->command(0x00);
1630
1991
  // 128x296 resolution: 10
1631
- // LUT from OTP: 0
1992
+ // LUT from register: 1
1632
1993
  // B/W mode (doesn't work): 1
1633
1994
  // scan-up: 1
1634
1995
  // shift-right: 1
1635
1996
  // booster ON: 1
1636
1997
  // no soft reset: 1
1637
- this->data(0b10011111);
1998
+ this->data(0b10111111);
1999
+ this->data(0x0d); // VCOM to 0V fast
2000
+ this->command(0x30); // PLL setting
2001
+ this->data(0x3a); // 3a 100HZ 29 150Hz 39 200HZ 31 171HZ
2002
+ this->command(0x61); // resolution setting
2003
+ this->data(this->get_width_internal());
2004
+ this->data(this->get_height_internal() >> 8);
2005
+ this->data(this->get_height_internal() & 0xFF);
1638
2006
 
1639
- // COMMAND RESOLUTION SETTING
1640
- // set to 128x296 by COMMAND PANEL SETTING
2007
+ ESP_LOGD(TAG, "panel setting done");
2008
+ }
1641
2009
 
1642
- // COMMAND VCOM AND DATA INTERVAL SETTING
1643
- // use defaults for white border and ESPHome image polarity
2010
+ void GDEW029T5::initialize() {
2011
+ // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
2012
+ if (this->reset_pin_ != nullptr)
2013
+ this->deep_sleep_between_updates_ = true;
1644
2014
 
1645
- // EPD hardware init end
2015
+ // old buffer for partial update
2016
+ ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
2017
+ this->old_buffer_ = allocator.allocate(this->get_buffer_length_());
2018
+ if (this->old_buffer_ == nullptr) {
2019
+ ESP_LOGE(TAG, "Could not allocate old buffer for display!");
2020
+ return;
2021
+ }
2022
+ for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2023
+ this->old_buffer_[i] = 0xFF;
2024
+ }
2025
+ }
2026
+
2027
+ // initialize for full(normal) update
2028
+ void GDEW029T5::init_full_() {
2029
+ this->init_display_();
2030
+ this->command(0x82); // vcom_DC setting
2031
+ this->data(0x08);
2032
+ this->command(0X50); // VCOM AND DATA INTERVAL SETTING
2033
+ this->data(0x97); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
2034
+ this->command(0x20);
2035
+ this->write_lut_(LUT_20_VCOMDC_29_5, sizeof(LUT_20_VCOMDC_29_5));
2036
+ this->command(0x21);
2037
+ this->write_lut_(LUT_21_WW_29_5, sizeof(LUT_21_WW_29_5));
2038
+ this->command(0x22);
2039
+ this->write_lut_(LUT_22_BW_29_5, sizeof(LUT_22_BW_29_5));
2040
+ this->command(0x23);
2041
+ this->write_lut_(LUT_23_WB_29_5, sizeof(LUT_23_WB_29_5));
2042
+ this->command(0x24);
2043
+ this->write_lut_(LUT_24_BB_29_5, sizeof(LUT_24_BB_29_5));
2044
+ ESP_LOGD(TAG, "initialized full update");
2045
+ }
2046
+
2047
+ // initialzie for partial update
2048
+ void GDEW029T5::init_partial_() {
2049
+ this->init_display_();
2050
+ this->command(0x82); // vcom_DC setting
2051
+ this->data(0x08);
2052
+ this->command(0X50); // VCOM AND DATA INTERVAL SETTING
2053
+ this->data(0x17); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
2054
+ this->command(0x20);
2055
+ this->write_lut_(LUT_20_VCOMDC_PARTIAL_29_5, sizeof(LUT_20_VCOMDC_PARTIAL_29_5));
2056
+ this->command(0x21);
2057
+ this->write_lut_(LUT_21_WW_PARTIAL_29_5, sizeof(LUT_21_WW_PARTIAL_29_5));
2058
+ this->command(0x22);
2059
+ this->write_lut_(LUT_22_BW_PARTIAL_29_5, sizeof(LUT_22_BW_PARTIAL_29_5));
2060
+ this->command(0x23);
2061
+ this->write_lut_(LUT_23_WB_PARTIAL_29_5, sizeof(LUT_23_WB_PARTIAL_29_5));
2062
+ this->command(0x24);
2063
+ this->write_lut_(LUT_24_BB_PARTIAL_29_5, sizeof(LUT_24_BB_PARTIAL_29_5));
2064
+ ESP_LOGD(TAG, "initialized partial update");
1646
2065
  }
2066
+
1647
2067
  void HOT GDEW029T5::display() {
2068
+ bool full_update = this->at_update_ == 0;
2069
+ if (full_update) {
2070
+ this->init_full_();
2071
+ } else {
2072
+ this->init_partial_();
2073
+ this->command(0x91); // partial in
2074
+ // set partial window
2075
+ this->command(0x90);
2076
+ // this->data(0);
2077
+ this->data(0);
2078
+ // this->data(0);
2079
+ this->data((this->get_width_internal() - 1) % 256);
2080
+ this->data(0);
2081
+ this->data(0);
2082
+ this->data(((this->get_height_internal() - 1)) / 256);
2083
+ this->data(((this->get_height_internal() - 1)) % 256);
2084
+ this->data(0x01);
2085
+ }
2086
+ // input old buffer data
2087
+ this->command(0x10);
2088
+ delay(2);
2089
+ this->start_data_();
2090
+ for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2091
+ this->write_byte(this->old_buffer_[i]);
2092
+ }
2093
+ this->end_data_();
2094
+ delay(2);
2095
+
1648
2096
  // COMMAND DATA START TRANSMISSION 2 (B/W only)
1649
2097
  this->command(0x13);
1650
2098
  delay(2);
1651
2099
  this->start_data_();
1652
2100
  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1653
2101
  this->write_byte(this->buffer_[i]);
2102
+ this->old_buffer_[i] = this->buffer_[i];
1654
2103
  }
1655
2104
  this->end_data_();
1656
2105
  delay(2);
@@ -1660,10 +2109,28 @@ void HOT GDEW029T5::display() {
1660
2109
  delay(2);
1661
2110
  this->wait_until_idle_();
1662
2111
 
1663
- // COMMAND POWER OFF
1664
- // NOTE: power off < deep sleep
1665
- this->command(0x02);
2112
+ if (full_update) {
2113
+ ESP_LOGD(TAG, "full update done");
2114
+ } else {
2115
+ this->command(0x92); // partial out
2116
+ ESP_LOGD(TAG, "partial update done");
2117
+ }
2118
+
2119
+ this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
2120
+ // COMMAND deep sleep
2121
+ this->deep_sleep();
1666
2122
  }
2123
+
2124
+ void GDEW029T5::write_lut_(const uint8_t *lut, const uint8_t size) {
2125
+ // COMMAND WRITE LUT REGISTER
2126
+ this->start_data_();
2127
+ for (uint8_t i = 0; i < size; i++)
2128
+ this->write_byte(lut[i]);
2129
+ this->end_data_();
2130
+ }
2131
+
2132
+ void GDEW029T5::set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; }
2133
+
1667
2134
  int GDEW029T5::get_width_internal() { return 128; }
1668
2135
  int GDEW029T5::get_height_internal() { return 296; }
1669
2136
  void GDEW029T5::dump_config() {
@@ -1672,6 +2139,7 @@ void GDEW029T5::dump_config() {
1672
2139
  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1673
2140
  LOG_PIN(" DC Pin: ", this->dc_pin_);
1674
2141
  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2142
+ ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
1675
2143
  LOG_UPDATE_INTERVAL(this);
1676
2144
  }
1677
2145
 
@@ -1815,6 +2283,206 @@ void GDEW0154M09::dump_config() {
1815
2283
  LOG_UPDATE_INTERVAL(this);
1816
2284
  }
1817
2285
 
2286
+ // ========================================================
2287
+ // Good Display 4.2in black/white GDEY042T81 (SSD1683)
2288
+ // Product page:
2289
+ // - https://www.good-display.com/product/386.html
2290
+ // Datasheet:
2291
+ // - https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf
2292
+ // - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF
2293
+ // Reference code from GoodDisplay:
2294
+ // - https://www.good-display.com/companyfile/1572.html (2024-08-01 15:40:41)
2295
+ // Other reference code:
2296
+ // - https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp
2297
+ // ========================================================
2298
+
2299
+ void GDEY042T81::initialize() {
2300
+ this->init_display_();
2301
+ ESP_LOGD(TAG, "Initialization complete, set the display to deep sleep");
2302
+ this->deep_sleep();
2303
+ }
2304
+
2305
+ // conflicting documentation / examples regarding reset timings
2306
+ // https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF -> 10ms
2307
+ // GD sample code (Display_EPD_W21.cpp, see above) -> 10 ms
2308
+ // https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf (section 14.2) -> 0.2ms (200us)
2309
+ // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L351
2310
+ // -> 10ms
2311
+ // 10 ms seems to work, so we use this
2312
+ GDEY042T81::GDEY042T81() { this->reset_duration_ = 10; }
2313
+
2314
+ void GDEY042T81::reset_() {
2315
+ if (this->reset_pin_ != nullptr) {
2316
+ this->reset_pin_->digital_write(false);
2317
+ delay(reset_duration_); // NOLINT
2318
+ this->reset_pin_->digital_write(true);
2319
+ delay(reset_duration_); // NOLINT
2320
+ }
2321
+ }
2322
+
2323
+ void GDEY042T81::init_display_() {
2324
+ this->reset_();
2325
+
2326
+ this->wait_until_idle_();
2327
+ this->command(0x12); // SWRESET
2328
+ this->wait_until_idle_();
2329
+
2330
+ // Specify number of lines for the driver: 300 (MUX 300)
2331
+ // https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF (section 8.1)
2332
+ // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L354
2333
+ this->command(0x01); // driver output control
2334
+ this->data(0x2B); // (height - 1) % 256
2335
+ this->data(0x01); // (height - 1) / 256
2336
+ this->data(0x00);
2337
+
2338
+ // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L360
2339
+ this->command(0x3C); // BorderWaveform
2340
+ this->data(0x01);
2341
+ this->command(0x18); // Read built-in temperature sensor
2342
+ this->data(0x80);
2343
+
2344
+ // GD sample code (Display_EPD_W21.cpp@90ff)
2345
+ this->command(0x11); // data entry mode
2346
+ this->data(0x03);
2347
+ // set windows (0,0,400,300)
2348
+ this->command(0x44); // set Ram-X address start/end position
2349
+ this->data(0);
2350
+ this->data(0x31); // (width / 8 -1)
2351
+
2352
+ this->command(0x45); // set Ram-y address start/end position
2353
+ this->data(0);
2354
+ this->data(0);
2355
+ this->data(0x2B); // (height - 1) % 256
2356
+ this->data(0x01); // (height - 1) / 256
2357
+
2358
+ // set cursor (0,0)
2359
+ this->command(0x4E); // set RAM x address count to 0;
2360
+ this->data(0);
2361
+ this->command(0x4F); // set RAM y address count to 0;
2362
+ this->data(0);
2363
+ this->data(0);
2364
+
2365
+ this->wait_until_idle_();
2366
+ }
2367
+
2368
+ // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L366
2369
+ void GDEY042T81::update_full_() {
2370
+ this->command(0x21); // display update control
2371
+ this->data(0x40); // bypass RED as 0
2372
+ this->data(0x00); // single chip application
2373
+
2374
+ // only ever do a fast update because slow updates are only relevant
2375
+ // for lower operating temperatures
2376
+ // see
2377
+ // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_290_GDEY029T94.h#L30
2378
+ //
2379
+ // Should slow/fast updates be made configurable similar to how GxEPD2 does it? No idea if anyone would need it...
2380
+ this->command(0x1A); // Write to temperature register
2381
+ this->data(0x6E);
2382
+ this->command(0x22);
2383
+ this->data(0xd7);
2384
+
2385
+ this->command(0x20);
2386
+ this->wait_until_idle_();
2387
+ }
2388
+
2389
+ // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L389
2390
+ void GDEY042T81::update_part_() {
2391
+ this->command(0x21); // display update control
2392
+ this->data(0x00); // RED normal
2393
+ this->data(0x00); // single chip application
2394
+
2395
+ this->command(0x22);
2396
+ this->data(0xfc);
2397
+
2398
+ this->command(0x20);
2399
+ this->wait_until_idle_();
2400
+ }
2401
+
2402
+ void HOT GDEY042T81::display() {
2403
+ ESP_LOGD(TAG, "Wake up the display");
2404
+ this->init_display_();
2405
+
2406
+ if (!this->wait_until_idle_()) {
2407
+ this->status_set_warning();
2408
+ ESP_LOGE(TAG, "Failed to perform update, display is busy");
2409
+ return;
2410
+ }
2411
+
2412
+ // basic code structure copied from WaveshareEPaper2P9InV2R2
2413
+ if (this->full_update_every_ == 1) {
2414
+ ESP_LOGD(TAG, "Full update");
2415
+ // do single full update
2416
+ this->command(0x24);
2417
+ this->start_data_();
2418
+ this->write_array(this->buffer_, this->get_buffer_length_());
2419
+ this->end_data_();
2420
+
2421
+ // TurnOnDisplay
2422
+ this->update_full_();
2423
+ return;
2424
+ }
2425
+
2426
+ // if (this->full_update_every_ == 1 ||
2427
+ if (this->at_update_ == 0) {
2428
+ ESP_LOGD(TAG, "Update");
2429
+ // do base update
2430
+ this->command(0x24);
2431
+ this->start_data_();
2432
+ this->write_array(this->buffer_, this->get_buffer_length_());
2433
+ this->end_data_();
2434
+
2435
+ this->command(0x26);
2436
+ this->start_data_();
2437
+ this->write_array(this->buffer_, this->get_buffer_length_());
2438
+ this->end_data_();
2439
+
2440
+ // TurnOnDisplay;
2441
+ this->update_full_();
2442
+ } else {
2443
+ // do partial update (full screen)
2444
+ // no need to load a LUT for GoodDisplays as they seem to have the LUT onboard
2445
+ // GD example code (Display_EPD_W21.cpp@283ff)
2446
+ //
2447
+ // not setting the BorderWaveform here again (contrary to the GD example) because according to
2448
+ // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L358
2449
+ // it seems to be enough to set it during display initialization
2450
+ ESP_LOGD(TAG, "Partial update");
2451
+ this->reset_();
2452
+ if (!this->wait_until_idle_()) {
2453
+ this->status_set_warning();
2454
+ ESP_LOGE(TAG, "Failed to perform partial update, display is busy");
2455
+ return;
2456
+ }
2457
+
2458
+ this->command(0x24);
2459
+ this->start_data_();
2460
+ this->write_array(this->buffer_, this->get_buffer_length_());
2461
+ this->end_data_();
2462
+
2463
+ // TurnOnDisplay
2464
+ this->update_part_();
2465
+ }
2466
+
2467
+ this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
2468
+ this->wait_until_idle_();
2469
+ ESP_LOGD(TAG, "Set the display back to deep sleep");
2470
+ this->deep_sleep();
2471
+ }
2472
+ void GDEY042T81::set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; }
2473
+ int GDEY042T81::get_width_internal() { return 400; }
2474
+ int GDEY042T81::get_height_internal() { return 300; }
2475
+ uint32_t GDEY042T81::idle_timeout_() { return 5000; }
2476
+ void GDEY042T81::dump_config() {
2477
+ LOG_DISPLAY("", "GoodDisplay E-Paper", this);
2478
+ ESP_LOGCONFIG(TAG, " Model: 4.2in B/W GDEY042T81");
2479
+ ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
2480
+ LOG_PIN(" Reset Pin: ", this->reset_pin_);
2481
+ LOG_PIN(" DC Pin: ", this->dc_pin_);
2482
+ LOG_PIN(" Busy Pin: ", this->busy_pin_);
2483
+ LOG_UPDATE_INTERVAL(this);
2484
+ }
2485
+
1818
2486
  static const uint8_t LUT_VCOM_DC_4_2[] = {
1819
2487
  0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
1820
2488
  0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1993,6 +2661,64 @@ void WaveshareEPaper4P2InBV2::dump_config() {
1993
2661
  LOG_UPDATE_INTERVAL(this);
1994
2662
  }
1995
2663
 
2664
+ // ========================================================
2665
+ // 4.20in Type B With Red colour support (LUT from OTP)
2666
+ // Datasheet:
2667
+ // - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
2668
+ // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
2669
+ // The implementation is an adaptation of WaveshareEPaper4P2InBV2 class
2670
+ // ========================================================
2671
+ void WaveshareEPaper4P2InBV2BWR::initialize() {
2672
+ // these exact timings are required for a proper reset/init
2673
+ this->reset_pin_->digital_write(false);
2674
+ delay(2);
2675
+ this->reset_pin_->digital_write(true);
2676
+ delay(200); // NOLINT
2677
+
2678
+ // COMMAND POWER ON
2679
+ this->command(0x04);
2680
+ this->wait_until_idle_();
2681
+
2682
+ // COMMAND PANEL SETTING
2683
+ this->command(0x00);
2684
+ this->data(0x0f); // LUT from OTP
2685
+ }
2686
+
2687
+ void HOT WaveshareEPaper4P2InBV2BWR::display() {
2688
+ const uint32_t buf_len = this->get_buffer_length_() / 2u;
2689
+
2690
+ this->command(0x10); // Send BW data Transmission
2691
+ delay(2); // Delay to prevent Watchdog error
2692
+ for (uint32_t i = 0; i < buf_len; ++i) {
2693
+ this->data(this->buffer_[i]);
2694
+ }
2695
+
2696
+ this->command(0x13); // Send red data Transmission
2697
+ delay(2); // Delay to prevent Watchdog error
2698
+ for (uint32_t i = 0; i < buf_len; ++i) {
2699
+ // Red color need to flip bit from the buffer. Otherwise, red will conqure the screen!
2700
+ this->data(~this->buffer_[buf_len + i]);
2701
+ }
2702
+
2703
+ // COMMAND DISPLAY REFRESH
2704
+ this->command(0x12);
2705
+ this->wait_until_idle_();
2706
+
2707
+ // COMMAND POWER OFF
2708
+ // NOTE: power off < deep sleep
2709
+ this->command(0x02);
2710
+ }
2711
+ int WaveshareEPaper4P2InBV2BWR::get_width_internal() { return 400; }
2712
+ int WaveshareEPaper4P2InBV2BWR::get_height_internal() { return 300; }
2713
+ void WaveshareEPaper4P2InBV2BWR::dump_config() {
2714
+ LOG_DISPLAY("", "Waveshare E-Paper", this);
2715
+ ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2) BWR-Mode");
2716
+ LOG_PIN(" Reset Pin: ", this->reset_pin_);
2717
+ LOG_PIN(" DC Pin: ", this->dc_pin_);
2718
+ LOG_PIN(" Busy Pin: ", this->busy_pin_);
2719
+ LOG_UPDATE_INTERVAL(this);
2720
+ }
2721
+
1996
2722
  void WaveshareEPaper5P8In::initialize() {
1997
2723
  // COMMAND POWER SETTING
1998
2724
  this->command(0x01);
@@ -2425,28 +3151,21 @@ void WaveshareEPaper7P5InBV3BWR::init_display_() {
2425
3151
  this->command(0x01);
2426
3152
 
2427
3153
  // 1-0=11: internal power
2428
- this->data(0x07);
2429
- this->data(0x17); // VGH&VGL
2430
- this->data(0x3F); // VSH
2431
- this->data(0x26); // VSL
2432
- this->data(0x11); // VSHR
3154
+ this->data(0x07); // VRS_EN=1, VS_EN=1, VG_EN=1
3155
+ this->data(0x17); // VGH&VGL ??? VCOM_SLEW=1 but this is fixed, VG_LVL[2:0]=111 => VGH=20V VGL=-20V, it could be 0x07
3156
+ this->data(0x3F); // VSH=15V?
3157
+ this->data(0x26); // VSL=-9.4V?
3158
+ this->data(0x11); // VSHR=5.8V?
2433
3159
 
2434
3160
  // VCOM DC Setting
2435
3161
  this->command(0x82);
2436
- this->data(0x24); // VCOM
2437
-
2438
- // Booster Setting
2439
- this->command(0x06);
2440
- this->data(0x27);
2441
- this->data(0x27);
2442
- this->data(0x2F);
2443
- this->data(0x17);
3162
+ this->data(0x24); // VCOM=-1.9V
2444
3163
 
2445
3164
  // POWER ON
2446
3165
  this->command(0x04);
2447
-
2448
3166
  delay(100); // NOLINT
2449
3167
  this->wait_until_idle_();
3168
+
2450
3169
  // COMMAND PANEL SETTING
2451
3170
  this->command(0x00);
2452
3171
  this->data(0x0F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
@@ -2457,16 +3176,16 @@ void WaveshareEPaper7P5InBV3BWR::init_display_() {
2457
3176
  this->data(0x20);
2458
3177
  this->data(0x01); // gate 480
2459
3178
  this->data(0xE0);
2460
- // COMMAND ...?
2461
- this->command(0x15);
2462
- this->data(0x00);
3179
+
2463
3180
  // COMMAND VCOM AND DATA INTERVAL SETTING
2464
3181
  this->command(0x50);
2465
3182
  this->data(0x20);
2466
3183
  this->data(0x00);
3184
+
2467
3185
  // COMMAND TCON SETTING
2468
3186
  this->command(0x60);
2469
3187
  this->data(0x22);
3188
+
2470
3189
  // Resolution setting
2471
3190
  this->command(0x65);
2472
3191
  this->data(0x00);
@@ -2588,6 +3307,195 @@ void WaveshareEPaper7P5In::dump_config() {
2588
3307
  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2589
3308
  LOG_UPDATE_INTERVAL(this);
2590
3309
  }
3310
+ void WaveshareEPaper7P3InF::initialize() {
3311
+ if (this->buffers_[0] == nullptr) {
3312
+ ESP_LOGE(TAG, "Buffer unavailable!");
3313
+ return;
3314
+ }
3315
+
3316
+ this->reset_();
3317
+ delay(20);
3318
+ this->wait_until_idle_();
3319
+
3320
+ // COMMAND CMDH
3321
+ this->command(0xAA);
3322
+ this->data(0x49);
3323
+ this->data(0x55);
3324
+ this->data(0x20);
3325
+ this->data(0x08);
3326
+ this->data(0x09);
3327
+ this->data(0x18);
3328
+
3329
+ this->command(0x01);
3330
+ this->data(0x3F);
3331
+ this->data(0x00);
3332
+ this->data(0x32);
3333
+ this->data(0x2A);
3334
+ this->data(0x0E);
3335
+ this->data(0x2A);
3336
+
3337
+ this->command(0x00);
3338
+ this->data(0x5F);
3339
+ this->data(0x69);
3340
+
3341
+ this->command(0x03);
3342
+ this->data(0x00);
3343
+ this->data(0x54);
3344
+ this->data(0x00);
3345
+ this->data(0x44);
3346
+
3347
+ this->command(0x05);
3348
+ this->data(0x40);
3349
+ this->data(0x1F);
3350
+ this->data(0x1F);
3351
+ this->data(0x2C);
3352
+
3353
+ this->command(0x06);
3354
+ this->data(0x6F);
3355
+ this->data(0x1F);
3356
+ this->data(0x1F);
3357
+ this->data(0x22);
3358
+
3359
+ this->command(0x08);
3360
+ this->data(0x6F);
3361
+ this->data(0x1F);
3362
+ this->data(0x1F);
3363
+ this->data(0x22);
3364
+
3365
+ // COMMAND IPC
3366
+ this->command(0x13);
3367
+ this->data(0x00);
3368
+ this->data(0x04);
3369
+
3370
+ this->command(0x30);
3371
+ this->data(0x3C);
3372
+
3373
+ // COMMAND TSE
3374
+ this->command(0x41);
3375
+ this->data(0x00);
3376
+
3377
+ this->command(0x50);
3378
+ this->data(0x3F);
3379
+
3380
+ this->command(0x60);
3381
+ this->data(0x02);
3382
+ this->data(0x00);
3383
+
3384
+ this->command(0x61);
3385
+ this->data(0x03);
3386
+ this->data(0x20);
3387
+ this->data(0x01);
3388
+ this->data(0xE0);
3389
+
3390
+ this->command(0x82);
3391
+ this->data(0x1E);
3392
+
3393
+ this->command(0x84);
3394
+ this->data(0x00);
3395
+
3396
+ // COMMAND AGID
3397
+ this->command(0x86);
3398
+ this->data(0x00);
3399
+
3400
+ this->command(0xE3);
3401
+ this->data(0x2F);
3402
+
3403
+ // COMMAND CCSET
3404
+ this->command(0xE0);
3405
+ this->data(0x00);
3406
+
3407
+ // COMMAND TSSET
3408
+ this->command(0xE6);
3409
+ this->data(0x00);
3410
+
3411
+ ESP_LOGI(TAG, "Display initialized successfully");
3412
+ }
3413
+ void HOT WaveshareEPaper7P3InF::display() {
3414
+ if (this->buffers_[0] == nullptr) {
3415
+ ESP_LOGE(TAG, "Buffer unavailable!");
3416
+ return;
3417
+ }
3418
+
3419
+ // INITIALIZATION
3420
+ ESP_LOGI(TAG, "Initialise the display");
3421
+ this->initialize();
3422
+
3423
+ // COMMAND DATA START TRANSMISSION
3424
+ ESP_LOGI(TAG, "Sending data to the display");
3425
+ this->command(0x10);
3426
+ uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
3427
+ uint8_t byte_to_send;
3428
+ for (auto &buffer : this->buffers_) {
3429
+ for (uint32_t buffer_pos = 0; buffer_pos < small_buffer_length; buffer_pos += 3) {
3430
+ std::bitset<24> triplet =
3431
+ buffer[buffer_pos + 0] << 16 | buffer[buffer_pos + 1] << 8 | buffer[buffer_pos + 2] << 0;
3432
+ // 8 bitset<3> are stored in 3 bytes
3433
+ // |aaabbbaa|abbbaaab|bbaaabbb|
3434
+ // | byte 1 | byte 2 | byte 3 |
3435
+ byte_to_send = ((triplet >> 17).to_ulong() & 0b01110000) | ((triplet >> 18).to_ulong() & 0b00000111);
3436
+ this->data(byte_to_send);
3437
+
3438
+ byte_to_send = ((triplet >> 11).to_ulong() & 0b01110000) | ((triplet >> 12).to_ulong() & 0b00000111);
3439
+ this->data(byte_to_send);
3440
+
3441
+ byte_to_send = ((triplet >> 5).to_ulong() & 0b01110000) | ((triplet >> 6).to_ulong() & 0b00000111);
3442
+ this->data(byte_to_send);
3443
+
3444
+ byte_to_send = ((triplet << 1).to_ulong() & 0b01110000) | ((triplet << 0).to_ulong() & 0b00000111);
3445
+ this->data(byte_to_send);
3446
+ }
3447
+ App.feed_wdt();
3448
+ }
3449
+
3450
+ // COMMAND POWER ON
3451
+ ESP_LOGI(TAG, "Power on the display");
3452
+ this->command(0x04);
3453
+ this->wait_until_idle_();
3454
+
3455
+ // COMMAND REFRESH SCREEN
3456
+ ESP_LOGI(TAG, "Refresh the display");
3457
+ this->command(0x12);
3458
+ this->data(0x00);
3459
+ this->wait_until_idle_();
3460
+
3461
+ // COMMAND POWER OFF
3462
+ ESP_LOGI(TAG, "Power off the display");
3463
+ this->command(0x02);
3464
+ this->data(0x00);
3465
+ this->wait_until_idle_();
3466
+
3467
+ ESP_LOGI(TAG, "Set the display to deep sleep");
3468
+ this->command(0x07);
3469
+ this->data(0xA5);
3470
+ }
3471
+ int WaveshareEPaper7P3InF::get_width_internal() { return 800; }
3472
+ int WaveshareEPaper7P3InF::get_height_internal() { return 480; }
3473
+ uint32_t WaveshareEPaper7P3InF::idle_timeout_() { return 35000; }
3474
+ void WaveshareEPaper7P3InF::dump_config() {
3475
+ LOG_DISPLAY("", "Waveshare E-Paper", this);
3476
+ ESP_LOGCONFIG(TAG, " Model: 7.3in-F");
3477
+ LOG_PIN(" Reset Pin: ", this->reset_pin_);
3478
+ LOG_PIN(" DC Pin: ", this->dc_pin_);
3479
+ LOG_PIN(" Busy Pin: ", this->busy_pin_);
3480
+ LOG_UPDATE_INTERVAL(this);
3481
+ }
3482
+
3483
+ bool WaveshareEPaper7P3InF::wait_until_idle_() {
3484
+ if (this->busy_pin_ == nullptr) {
3485
+ return true;
3486
+ }
3487
+ const uint32_t start = millis();
3488
+ while (this->busy_pin_->digital_read()) {
3489
+ if (millis() - start > this->idle_timeout_()) {
3490
+ ESP_LOGE(TAG, "Timeout while displaying image!");
3491
+ return false;
3492
+ }
3493
+ App.feed_wdt();
3494
+ delay(10);
3495
+ }
3496
+ delay(200); // NOLINT
3497
+ return true;
3498
+ }
2591
3499
  bool WaveshareEPaper7P5InV2::wait_until_idle_() {
2592
3500
  if (this->busy_pin_ == nullptr) {
2593
3501
  return true;
@@ -2826,6 +3734,209 @@ void WaveshareEPaper7P5InV2alt::dump_config() {
2826
3734
  LOG_UPDATE_INTERVAL(this);
2827
3735
  }
2828
3736
 
3737
+ /* 7.50inV2 with partial and fast refresh */
3738
+ bool WaveshareEPaper7P5InV2P::wait_until_idle_() {
3739
+ if (this->busy_pin_ == nullptr) {
3740
+ return true;
3741
+ }
3742
+
3743
+ const uint32_t start = millis();
3744
+ while (this->busy_pin_->digital_read()) {
3745
+ this->command(0x71);
3746
+ if (millis() - start > this->idle_timeout_()) {
3747
+ ESP_LOGE(TAG, "Timeout while displaying image!");
3748
+ return false;
3749
+ }
3750
+ App.feed_wdt();
3751
+ delay(10);
3752
+ }
3753
+ return true;
3754
+ }
3755
+
3756
+ void WaveshareEPaper7P5InV2P::reset_() {
3757
+ if (this->reset_pin_ != nullptr) {
3758
+ this->reset_pin_->digital_write(true);
3759
+ delay(20);
3760
+ this->reset_pin_->digital_write(false);
3761
+ delay(2);
3762
+ this->reset_pin_->digital_write(true);
3763
+ delay(20);
3764
+ }
3765
+ }
3766
+
3767
+ void WaveshareEPaper7P5InV2P::turn_on_display_() {
3768
+ this->command(0x12);
3769
+ delay(100); // NOLINT
3770
+ this->wait_until_idle_();
3771
+ }
3772
+
3773
+ void WaveshareEPaper7P5InV2P::initialize() {
3774
+ this->reset_();
3775
+
3776
+ // COMMAND POWER SETTING
3777
+ this->command(0x01);
3778
+ this->data(0x07);
3779
+ this->data(0x07);
3780
+ this->data(0x3f);
3781
+ this->data(0x3f);
3782
+
3783
+ // COMMAND BOOSTER SOFT START
3784
+ this->command(0x06);
3785
+ this->data(0x17);
3786
+ this->data(0x17);
3787
+ this->data(0x28);
3788
+ this->data(0x17);
3789
+
3790
+ // COMMAND POWER DRIVER HAT UP
3791
+ this->command(0x04);
3792
+ delay(100); // NOLINT
3793
+ this->wait_until_idle_();
3794
+
3795
+ // COMMAND PANEL SETTING
3796
+ this->command(0x00);
3797
+ this->data(0x1F);
3798
+
3799
+ // COMMAND RESOLUTION SETTING
3800
+ this->command(0x61);
3801
+ this->data(0x03);
3802
+ this->data(0x20);
3803
+ this->data(0x01);
3804
+ this->data(0xE0);
3805
+
3806
+ // COMMAND DUAL SPI MM_EN, DUSPI_EN
3807
+ this->command(0x15);
3808
+ this->data(0x00);
3809
+
3810
+ // COMMAND VCOM AND DATA INTERVAL SETTING
3811
+ this->command(0x50);
3812
+ this->data(0x10);
3813
+ this->data(0x07);
3814
+
3815
+ // COMMAND TCON SETTING
3816
+ this->command(0x60);
3817
+ this->data(0x22);
3818
+
3819
+ // COMMAND ENABLE FAST UPDATE
3820
+ this->command(0xE0);
3821
+ this->data(0x02);
3822
+ this->command(0xE5);
3823
+ this->data(0x5A);
3824
+
3825
+ // COMMAND POWER DRIVER HAT DOWN
3826
+ this->command(0x02);
3827
+ }
3828
+
3829
+ void HOT WaveshareEPaper7P5InV2P::display() {
3830
+ uint32_t buf_len = this->get_buffer_length_();
3831
+
3832
+ // COMMAND POWER ON
3833
+ ESP_LOGI(TAG, "Power on the display and hat");
3834
+
3835
+ this->command(0x04);
3836
+ delay(200); // NOLINT
3837
+ this->wait_until_idle_();
3838
+
3839
+ if (this->full_update_every_ == 1) {
3840
+ this->command(0x13);
3841
+ for (uint32_t i = 0; i < buf_len; i++) {
3842
+ this->data(~(this->buffer_[i]));
3843
+ }
3844
+
3845
+ this->turn_on_display_();
3846
+
3847
+ this->command(0x02);
3848
+ this->wait_until_idle_();
3849
+ return;
3850
+ }
3851
+
3852
+ this->command(0x50);
3853
+ this->data(0xA9);
3854
+ this->data(0x07);
3855
+
3856
+ if (this->at_update_ == 0) {
3857
+ // Enable fast refresh
3858
+ this->command(0xE5);
3859
+ this->data(0x5A);
3860
+
3861
+ this->command(0x92);
3862
+
3863
+ this->command(0x10);
3864
+ delay(2);
3865
+ for (uint32_t i = 0; i < buf_len; i++) {
3866
+ this->data(~(this->buffer_[i]));
3867
+ }
3868
+
3869
+ delay(100); // NOLINT
3870
+ this->wait_until_idle_();
3871
+
3872
+ this->command(0x13);
3873
+ delay(2);
3874
+ for (uint32_t i = 0; i < buf_len; i++) {
3875
+ this->data(this->buffer_[i]);
3876
+ }
3877
+
3878
+ delay(100); // NOLINT
3879
+ this->wait_until_idle_();
3880
+
3881
+ this->turn_on_display_();
3882
+
3883
+ } else {
3884
+ // Enable partial refresh
3885
+ this->command(0xE5);
3886
+ this->data(0x6E);
3887
+
3888
+ // Activate partial refresh and set window bounds
3889
+ this->command(0x91);
3890
+ this->command(0x90);
3891
+
3892
+ this->data(0x00);
3893
+ this->data(0x00);
3894
+ this->data((get_width_internal() - 1) >> 8 & 0xFF);
3895
+ this->data((get_width_internal() - 1) & 0xFF);
3896
+
3897
+ this->data(0x00);
3898
+ this->data(0x00);
3899
+ this->data((get_height_internal() - 1) >> 8 & 0xFF);
3900
+ this->data((get_height_internal() - 1) & 0xFF);
3901
+
3902
+ this->data(0x01);
3903
+
3904
+ this->command(0x13);
3905
+ delay(2);
3906
+ for (uint32_t i = 0; i < buf_len; i++) {
3907
+ this->data(this->buffer_[i]);
3908
+ }
3909
+
3910
+ delay(100); // NOLINT
3911
+ this->wait_until_idle_();
3912
+
3913
+ this->turn_on_display_();
3914
+ }
3915
+
3916
+ ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
3917
+ this->command(0x02);
3918
+ this->wait_until_idle_();
3919
+ ESP_LOGV(TAG, "After command(0x02) (>> power off)");
3920
+
3921
+ this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
3922
+ }
3923
+
3924
+ int WaveshareEPaper7P5InV2P::get_width_internal() { return 800; }
3925
+ int WaveshareEPaper7P5InV2P::get_height_internal() { return 480; }
3926
+ uint32_t WaveshareEPaper7P5InV2P::idle_timeout_() { return 10000; }
3927
+ void WaveshareEPaper7P5InV2P::dump_config() {
3928
+ LOG_DISPLAY("", "Waveshare E-Paper", this);
3929
+ ESP_LOGCONFIG(TAG, " Model: 7.50inv2p");
3930
+ ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
3931
+ LOG_PIN(" Reset Pin: ", this->reset_pin_);
3932
+ LOG_PIN(" DC Pin: ", this->dc_pin_);
3933
+ LOG_PIN(" Busy Pin: ", this->busy_pin_);
3934
+ LOG_UPDATE_INTERVAL(this);
3935
+ }
3936
+ void WaveshareEPaper7P5InV2P::set_full_update_every(uint32_t full_update_every) {
3937
+ this->full_update_every_ = full_update_every;
3938
+ }
3939
+
2829
3940
  /* 7.50in-bc */
2830
3941
  void WaveshareEPaper7P5InBC::initialize() {
2831
3942
  /* The command sequence is similar to the 7P5In display but differs in subtle ways