denko 0.14.0 → 0.15.0

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 (344) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_atmega_avr.yml +2 -1
  3. data/.github/workflows/build_atmega_megaavr.yml +2 -1
  4. data/.github/workflows/build_atsam3x.yml +1 -0
  5. data/.github/workflows/build_atsamd21.yml +2 -1
  6. data/.github/workflows/build_esp32.yml +4 -2
  7. data/.github/workflows/build_esp32c3.yml +4 -3
  8. data/.github/workflows/build_esp32c6.yml +4 -2
  9. data/.github/workflows/build_esp32h2.yml +4 -2
  10. data/.github/workflows/build_esp32s2.yml +4 -2
  11. data/.github/workflows/build_esp32s3.yml +4 -2
  12. data/.github/workflows/build_esp8266.yml +2 -1
  13. data/.github/workflows/build_ra4m1.yml +1 -0
  14. data/.github/workflows/build_rp2040.yml +4 -3
  15. data/.github/workflows/ruby.yml +1 -1
  16. data/CHANGELOG.md +203 -0
  17. data/DEPS_CLI.md +16 -16
  18. data/DEPS_IDE.md +31 -30
  19. data/MICROCONTROLLERS.md +103 -0
  20. data/PERIPHERALS.md +178 -0
  21. data/README.md +28 -21
  22. data/denko.gemspec +6 -1
  23. data/lib/denko/analog_io/ads1118.rb +5 -5
  24. data/lib/denko/analog_io/ads111x.rb +23 -19
  25. data/lib/denko/analog_io/joystick.rb +87 -0
  26. data/lib/denko/analog_io/potentiometer.rb +1 -5
  27. data/lib/denko/analog_io.rb +22 -8
  28. data/lib/denko/behaviors/bus_controller.rb +2 -1
  29. data/lib/denko/behaviors/bus_peripheral.rb +1 -1
  30. data/lib/denko/behaviors/callbacks.rb +18 -16
  31. data/lib/denko/behaviors/component.rb +0 -4
  32. data/lib/denko/behaviors/lifecycle.rb +1 -1
  33. data/lib/denko/behaviors/listener.rb +9 -3
  34. data/lib/denko/behaviors/multi_pin.rb +4 -6
  35. data/lib/denko/behaviors/poller.rb +11 -2
  36. data/lib/denko/behaviors/reader.rb +109 -21
  37. data/lib/denko/behaviors/single_pin.rb +2 -4
  38. data/lib/denko/behaviors/state.rb +18 -13
  39. data/lib/denko/behaviors/threaded.rb +19 -8
  40. data/lib/denko/behaviors.rb +36 -23
  41. data/lib/denko/board/eeprom.rb +1 -1
  42. data/lib/denko/board/i2c.rb +1 -1
  43. data/lib/denko/board/i2c_bit_bang.rb +9 -5
  44. data/lib/denko/board/map.rb +6 -2
  45. data/lib/denko/board/one_wire.rb +3 -3
  46. data/lib/denko/board/spi.rb +30 -30
  47. data/lib/denko/board/spi_bit_bang.rb +8 -11
  48. data/lib/denko/board.rb +6 -3
  49. data/lib/denko/connection/flow_control.rb +1 -1
  50. data/lib/denko/connection/serial.rb +5 -5
  51. data/lib/denko/digital_io/output.rb +12 -4
  52. data/lib/denko/digital_io/pcf8574.rb +114 -0
  53. data/lib/denko/digital_io/rotary_encoder.rb +10 -6
  54. data/lib/denko/digital_io.rb +24 -6
  55. data/lib/denko/display/canvas.rb +350 -157
  56. data/lib/denko/display/font/bmp_5x7.rb +142 -0
  57. data/lib/denko/display/font/bmp_6x8.rb +142 -0
  58. data/lib/denko/display/font/bmp_8x16.rb +141 -0
  59. data/lib/denko/display/font.rb +22 -0
  60. data/lib/denko/display/hd44780.rb +24 -20
  61. data/lib/denko/display/il0373.rb +186 -0
  62. data/lib/denko/display/mono_oled.rb +193 -0
  63. data/lib/denko/display/pcd8544.rb +154 -0
  64. data/lib/denko/display/pixel_common.rb +83 -0
  65. data/lib/denko/display/sh1106.rb +17 -21
  66. data/lib/denko/display/sh1107.rb +10 -0
  67. data/lib/denko/display/spi_common.rb +35 -0
  68. data/lib/denko/display/spi_epaper_common.rb +30 -0
  69. data/lib/denko/display/ssd1306.rb +6 -228
  70. data/lib/denko/display/ssd1680.rb +14 -0
  71. data/lib/denko/display/ssd1681.rb +8 -0
  72. data/lib/denko/display/ssd168x.rb +227 -0
  73. data/lib/denko/display/st7302.rb +207 -0
  74. data/lib/denko/display/st7565.rb +166 -0
  75. data/lib/denko/display.rb +40 -4
  76. data/lib/denko/eeprom/at24c.rb +67 -0
  77. data/lib/denko/eeprom/board.rb +69 -0
  78. data/lib/denko/eeprom.rb +15 -1
  79. data/lib/denko/helpers/engine_check.rb +13 -0
  80. data/lib/denko/{mutex_stub.rb → helpers/mutex_stub.rb} +6 -0
  81. data/lib/denko/helpers.rb +6 -0
  82. data/lib/denko/i2c/bit_bang.rb +1 -0
  83. data/lib/denko/i2c/bus_common.rb +9 -4
  84. data/lib/denko/i2c/peripheral.rb +5 -1
  85. data/lib/denko/i2c.rb +17 -4
  86. data/lib/denko/led/apa102.rb +1 -3
  87. data/lib/denko/led/base.rb +5 -0
  88. data/lib/denko/led/rgb.rb +16 -10
  89. data/lib/denko/led/seven_segment.rb +1 -1
  90. data/lib/denko/led.rb +17 -8
  91. data/lib/denko/motor/{stepper.rb → a3967.rb} +1 -1
  92. data/lib/denko/motor/servo.rb +16 -6
  93. data/lib/denko/motor.rb +16 -3
  94. data/lib/denko/one_wire/bus.rb +20 -16
  95. data/lib/denko/one_wire/bus_enumerator.rb +25 -14
  96. data/lib/denko/one_wire/helper.rb +4 -2
  97. data/lib/denko/one_wire.rb +18 -5
  98. data/lib/denko/pulse_io/buzzer.rb +2 -6
  99. data/lib/denko/pulse_io/ir_output.rb +1 -5
  100. data/lib/denko/pulse_io/pwm_output.rb +56 -31
  101. data/lib/denko/pulse_io.rb +17 -3
  102. data/lib/denko/rtc/ds3231.rb +4 -3
  103. data/lib/denko/rtc.rb +14 -1
  104. data/lib/denko/sensor/aht.rb +16 -20
  105. data/lib/denko/sensor/bme280.rb +23 -36
  106. data/lib/denko/sensor/bmp180.rb +8 -13
  107. data/lib/denko/sensor/dht.rb +17 -7
  108. data/lib/denko/sensor/ds18b20.rb +5 -4
  109. data/lib/denko/sensor/hdc1080.rb +174 -0
  110. data/lib/denko/sensor/htu21d.rb +17 -6
  111. data/lib/denko/sensor/htu31d.rb +6 -5
  112. data/lib/denko/sensor/jsnsr04t.rb +49 -0
  113. data/lib/denko/sensor/qmp6988.rb +14 -30
  114. data/lib/denko/sensor/rcwl9620.rb +1 -0
  115. data/lib/denko/sensor/sht3x.rb +6 -5
  116. data/lib/denko/sensor/sht4x.rb +125 -0
  117. data/lib/denko/sensor/vl53l0x.rb +58 -0
  118. data/lib/denko/sensor.rb +33 -15
  119. data/lib/denko/spi/base_register.rb +11 -7
  120. data/lib/denko/spi/bus_common.rb +12 -15
  121. data/lib/denko/spi/input_register.rb +6 -6
  122. data/lib/denko/spi/output_register.rb +13 -4
  123. data/lib/denko/spi/peripheral.rb +82 -84
  124. data/lib/denko/spi.rb +20 -10
  125. data/lib/denko/uart/bit_bang.rb +2 -27
  126. data/lib/denko/uart/common.rb +33 -0
  127. data/lib/denko/uart/hardware.rb +1 -26
  128. data/lib/denko/uart.rb +16 -2
  129. data/lib/denko/version.rb +1 -1
  130. data/lib/denko.rb +22 -25
  131. data/lib/denko_cli/targets.rb +7 -7
  132. data/lib/denko_cli/targets.txt +19 -20
  133. data/src/lib/Denko.cpp +26 -13
  134. data/src/lib/Denko.h +4 -4
  135. data/src/lib/DenkoDefines.h +7 -26
  136. data/src/lib/DenkoLEDArray.cpp +1 -8
  137. data/src/lib/DenkoSPI.cpp +31 -29
  138. data/src/lib/DenkoSPIBB.cpp +12 -14
  139. data/test/analog_io/input_test.rb +1 -1
  140. data/test/analog_io/potentiometer_test.rb +2 -2
  141. data/test/behaviors/bus_peripheral_test.rb +4 -4
  142. data/test/behaviors/callbacks_test.rb +20 -10
  143. data/test/behaviors/component_test.rb +18 -8
  144. data/test/board/board_test.rb +9 -9
  145. data/test/board/one_wire_test.rb +25 -14
  146. data/test/board/spi_test.rb +31 -15
  147. data/test/digital_io/input_test.rb +2 -2
  148. data/test/display/canvas_test.rb +306 -0
  149. data/test/display/hd44780_test.rb +34 -7
  150. data/test/eeprom/board_test.rb +45 -0
  151. data/test/helpers/mruby_minitest.rb +95 -0
  152. data/test/helpers/mruby_runner.rb +13 -0
  153. data/test/i2c/bus_test.rb +93 -30
  154. data/test/i2c/peripheral_test.rb +2 -2
  155. data/test/led/apa102_test.rb +24 -0
  156. data/test/led/rgb_test.rb +4 -4
  157. data/test/motor/{stepper_test.rb → a3967_test.rb} +2 -2
  158. data/test/one_wire/bus_enumerator_test.rb +1 -1
  159. data/test/one_wire/bus_test.rb +42 -35
  160. data/test/one_wire/peripheral_test.rb +5 -17
  161. data/test/pulse_io/ir_output_test.rb +5 -0
  162. data/test/pulse_io/pwm_output_test.rb +10 -10
  163. data/test/rtc/ds3231_test.rb +3 -2
  164. data/test/sensor/dht_test.rb +11 -11
  165. data/test/spi/bitbang_test.rb +27 -0
  166. data/test/spi/bus_test.rb +19 -29
  167. data/test/spi/input_register_test.rb +2 -2
  168. data/test/spi/{peripheral_multi_pin_test.rb → peripheral_test.rb} +25 -5
  169. data/test/test_helper.rb +44 -124
  170. data/vendor/board-maps/BoardMap.h +264 -0
  171. data/vendor/board-maps/yaml/ALFREDO_NOU3.yml +2 -0
  172. data/vendor/board-maps/yaml/ATD143_S3.yml +1 -0
  173. data/vendor/board-maps/yaml/BHARATPI_A7672S_4G.yml +14 -0
  174. data/vendor/board-maps/yaml/BHARATPI_LORA.yml +14 -0
  175. data/vendor/board-maps/yaml/BHARATPI_NODE_WIFI.yml +14 -0
  176. data/vendor/board-maps/yaml/BPI_LEAF_S3.yml +0 -1
  177. data/vendor/board-maps/yaml/CEZERIO_DEV_ESP32C6.yml +14 -0
  178. data/vendor/board-maps/yaml/CEZERIO_MINI_DEV_ESP32C6.yml +12 -0
  179. data/vendor/board-maps/yaml/CIRCUITART_ZERO_S3.yml +71 -0
  180. data/vendor/board-maps/yaml/CODECELLC3.yml +13 -0
  181. data/vendor/board-maps/yaml/CYOBOT_V2_ESP32S3.yml +7 -0
  182. data/vendor/board-maps/yaml/EDGES3D.yml +25 -0
  183. data/vendor/board-maps/yaml/ESP32C6_DEV.yml +3 -4
  184. data/vendor/board-maps/yaml/ESP32C6_THING_PLUS.yml +0 -1
  185. data/vendor/board-maps/yaml/ESP32H2_DEV.yml +0 -1
  186. data/vendor/board-maps/yaml/ESP32H2_DEVKIT_LIPO.yml +0 -1
  187. data/vendor/board-maps/yaml/ESP32P4_DEV.yml +35 -0
  188. data/vendor/board-maps/yaml/ESP32S2_DEV.yml +0 -1
  189. data/vendor/board-maps/yaml/ESP32S2_DEVKIT_LIPO.yml +0 -1
  190. data/vendor/board-maps/yaml/ESP32S2_DEVKIT_LIPO_USB.yml +0 -1
  191. data/vendor/board-maps/yaml/ESP32_2432S028R.yml +14 -0
  192. data/vendor/board-maps/yaml/FEATHERS3.yml +1 -1
  193. data/vendor/board-maps/yaml/FRI3D_2024_ESP32S3.yml +43 -0
  194. data/vendor/board-maps/yaml/GEEKBLE_ESP32C3.yml +0 -1
  195. data/vendor/board-maps/yaml/GEEKBLE_NANO_ESP32S3.yml +25 -0
  196. data/vendor/board-maps/yaml/HELTEC_VISION_MASTER_E290.yml +41 -0
  197. data/vendor/board-maps/yaml/HELTEC_VISION_MASTER_E_213.yml +41 -0
  198. data/vendor/board-maps/yaml/HELTEC_VISION_MASTER_T190.yml +41 -0
  199. data/vendor/board-maps/yaml/HUIDU_HD_WF2.yml +5 -0
  200. data/vendor/board-maps/yaml/HUIDU_HD_WF4.yml +1 -0
  201. data/vendor/board-maps/yaml/LILYGO_LORA_CC1101.yml +6 -0
  202. data/vendor/board-maps/yaml/LILYGO_LORA_LR1121.yml +6 -0
  203. data/vendor/board-maps/yaml/LILYGO_LORA_SI4432.yml +6 -0
  204. data/vendor/board-maps/yaml/LILYGO_LORA_SX1262.yml +6 -0
  205. data/vendor/board-maps/yaml/LILYGO_LORA_SX1280.yml +6 -0
  206. data/vendor/board-maps/yaml/LOLIN_C3_MINI.yml +0 -1
  207. data/vendor/board-maps/yaml/LOLIN_C3_PICO.yml +1 -2
  208. data/vendor/board-maps/yaml/LoPy.yml +0 -1
  209. data/vendor/board-maps/yaml/LoPy4.yml +0 -1
  210. data/vendor/board-maps/yaml/M5STACK_DINMETER.yml +8 -0
  211. data/vendor/board-maps/yaml/M5STACK_FIRE.yml +1 -1
  212. data/vendor/board-maps/yaml/OMGS3.yml +25 -0
  213. data/vendor/board-maps/yaml/PCBCUPID_GLYPHC3.yml +23 -0
  214. data/vendor/board-maps/yaml/PCBCUPID_GLYPHC6.yml +32 -0
  215. data/vendor/board-maps/yaml/PCBCUPID_GLYPHH2.yml +24 -0
  216. data/vendor/board-maps/yaml/PYCOM_GPY.yml +0 -1
  217. data/vendor/board-maps/yaml/SENSEBOX_MCU_ESP32S2.yml +1 -1
  218. data/vendor/board-maps/yaml/SPARKFUN_ESP32S3_THING_PLUS.yml +13 -0
  219. data/vendor/board-maps/yaml/SPARKLEMOTIONMINI_ESP32.yml +12 -0
  220. data/vendor/board-maps/yaml/SPARKLEMOTIONSTICK_ESP32.yml +11 -0
  221. data/vendor/board-maps/yaml/SPARKLEMOTION_ESP32.yml +12 -0
  222. data/vendor/board-maps/yaml/SQUIXL.yml +7 -0
  223. data/vendor/board-maps/yaml/THINGPULSE_EPULSE_FEATHER_C6.yml +0 -1
  224. data/vendor/board-maps/yaml/T_LORA_PAGER.yml +6 -0
  225. data/vendor/board-maps/yaml/T_WATCH_S3.yml +7 -0
  226. data/vendor/board-maps/yaml/T_WATCH_S3_ULTRA.yml +6 -0
  227. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_146.yml +41 -0
  228. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_147.yml +41 -0
  229. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_169.yml +38 -0
  230. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_185.yml +41 -0
  231. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_RELAY_6CH.yml +41 -0
  232. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_143.yml +7 -0
  233. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_164.yml +7 -0
  234. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_18.yml +38 -0
  235. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_191.yml +7 -0
  236. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_241.yml +7 -0
  237. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_146.yml +41 -0
  238. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_169.yml +38 -0
  239. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_185.yml +41 -0
  240. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_185_BOX.yml +41 -0
  241. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_21.yml +41 -0
  242. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_28.yml +41 -0
  243. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_4.yml +36 -0
  244. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_43.yml +38 -0
  245. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_43B.yml +38 -0
  246. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_5.yml +38 -0
  247. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_5B.yml +38 -0
  248. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_7.yml +38 -0
  249. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_ZERO.yml +36 -0
  250. data/vendor/board-maps/yaml/WIPY3.yml +0 -1
  251. data/vendor/board-maps/yaml/WS_ESP32_S3_MATRIX.yml +38 -0
  252. data/vendor/board-maps/yaml/XIAO_ESP32S3_PLUS.yml +46 -0
  253. data/vendor/board-maps/yaml/YB_ESP32S3_AMP_V2.yml +28 -0
  254. data/vendor/board-maps/yaml/YB_ESP32S3_AMP_V3.yml +28 -0
  255. data/vendor/board-maps/yaml/YB_ESP32S3_ETH.yml +40 -0
  256. data/vendor/board-maps/yaml/mercury.yml +20 -0
  257. metadata +116 -101
  258. data/.vscode/settings.json +0 -5
  259. data/.vscode/tasks.json +0 -20
  260. data/HARDWARE.md +0 -263
  261. data/benchmarks/analog_listen.rb +0 -49
  262. data/benchmarks/digital_write.rb +0 -28
  263. data/benchmarks/i2c_ssd1306_refresh.rb +0 -91
  264. data/examples/advanced/m5_env3.rb +0 -46
  265. data/examples/advanced/rotary_encoder_mac_volume.rb +0 -53
  266. data/examples/advanced/ssd1306_time_temp_rh.rb +0 -43
  267. data/examples/analog_io/ads1100.rb +0 -48
  268. data/examples/analog_io/ads1115.rb +0 -57
  269. data/examples/analog_io/ads1118.rb +0 -65
  270. data/examples/analog_io/dac_loopback.rb +0 -34
  271. data/examples/analog_io/input.rb +0 -56
  272. data/examples/analog_io/input_smoothing.rb +0 -27
  273. data/examples/analog_io/potentiometer.rb +0 -31
  274. data/examples/connection/binary_echo.rb +0 -34
  275. data/examples/connection/tcp.rb +0 -19
  276. data/examples/digital_io/button.rb +0 -17
  277. data/examples/digital_io/relay.rb +0 -17
  278. data/examples/digital_io/rotary_encoder.rb +0 -36
  279. data/examples/display/hd44780.png +0 -0
  280. data/examples/display/hd44780.rb +0 -47
  281. data/examples/display/ssd1306.rb +0 -43
  282. data/examples/display/ssd1306_s2_pico.rb +0 -29
  283. data/examples/eeprom/built_in.rb +0 -32
  284. data/examples/i2c/search.rb +0 -39
  285. data/examples/led/apa102_bounce.rb +0 -32
  286. data/examples/led/apa102_fade.rb +0 -44
  287. data/examples/led/builtin_blink.rb +0 -14
  288. data/examples/led/builtin_fade.rb +0 -19
  289. data/examples/led/rgb_led.rb +0 -31
  290. data/examples/led/seven_segment_char_echo.rb +0 -17
  291. data/examples/led/ws2812_bounce.rb +0 -30
  292. data/examples/led/ws2812_builtin_blink.rb +0 -22
  293. data/examples/led/ws2812_fade.rb +0 -43
  294. data/examples/motor/l298.rb +0 -45
  295. data/examples/motor/servo.rb +0 -17
  296. data/examples/motor/stepper.png +0 -0
  297. data/examples/motor/stepper.rb +0 -43
  298. data/examples/one_wire/search.rb +0 -32
  299. data/examples/pulse_io/buzzer.rb +0 -35
  300. data/examples/pulse_io/ir_output.rb +0 -51
  301. data/examples/pulse_io/pwm_output.rb +0 -30
  302. data/examples/rtc/ds3231.rb +0 -31
  303. data/examples/sensor/aht10.rb +0 -17
  304. data/examples/sensor/aht20.rb +0 -17
  305. data/examples/sensor/bme280.rb +0 -38
  306. data/examples/sensor/bmp180.rb +0 -26
  307. data/examples/sensor/dht.rb +0 -29
  308. data/examples/sensor/ds18b20.rb +0 -57
  309. data/examples/sensor/generic_pir.rb +0 -27
  310. data/examples/sensor/hcsr04.rb +0 -17
  311. data/examples/sensor/htu21d.rb +0 -43
  312. data/examples/sensor/htu31d.rb +0 -33
  313. data/examples/sensor/neat_tph_readings.rb +0 -32
  314. data/examples/sensor/qmp6988.rb +0 -51
  315. data/examples/sensor/rcwl9620.rb +0 -15
  316. data/examples/sensor/sht3x.rb +0 -32
  317. data/examples/spi/bitbang_loopback.rb +0 -46
  318. data/examples/spi/input_register.rb +0 -40
  319. data/examples/spi/output_register.rb +0 -41
  320. data/examples/spi/ssd_through_registers.rb +0 -28
  321. data/examples/spi/two_registers.rb +0 -40
  322. data/examples/uart/bit_bang_demo.rb +0 -25
  323. data/examples/uart/board_passthrough.rb +0 -40
  324. data/examples/uart/hardware_loopback.rb +0 -16
  325. data/lib/denko/eeprom/built_in.rb +0 -72
  326. data/lib/denko/fonts.rb +0 -106
  327. data/test/eeprom/built_in_test.rb +0 -61
  328. data/test/spi/peripheral_single_pin_test.rb +0 -48
  329. data/tutorial/01-led/led.fzz +0 -0
  330. data/tutorial/01-led/led.pdf +0 -0
  331. data/tutorial/01-led/led.rb +0 -73
  332. data/tutorial/02-button/button.fzz +0 -0
  333. data/tutorial/02-button/button.pdf +0 -0
  334. data/tutorial/02-button/button.rb +0 -65
  335. data/tutorial/03-potentiometer/potentiometer.fzz +0 -0
  336. data/tutorial/03-potentiometer/potentiometer.pdf +0 -0
  337. data/tutorial/03-potentiometer/potentiometer.rb +0 -66
  338. data/tutorial/04-pwm_led/pwm_led.fzz +0 -0
  339. data/tutorial/04-pwm_led/pwm_led.pdf +0 -0
  340. data/tutorial/04-pwm_led/pwm_led.rb +0 -64
  341. data/tutorial/05-rgb_led/rgb_led.fzz +0 -0
  342. data/tutorial/05-rgb_led/rgb_led.pdf +0 -0
  343. data/tutorial/05-rgb_led/rgb_led.rb +0 -58
  344. data/tutorial/05-rgb_led/rgb_mapping.rb +0 -76
@@ -0,0 +1,35 @@
1
+ module Denko
2
+ module Display
3
+ module SPICommon
4
+ include SPI::Peripheral
5
+ include PixelCommon
6
+
7
+ #
8
+ # SPI displays use a D/C pin to toggle whether bytes being sent are data or commands.
9
+ # Most also have a RESET pin which is pulsed low to initalize, then held high.
10
+ #
11
+ def initialize_pins(options={})
12
+ super(options)
13
+ proxy_pin :dc, DigitalIO::Output
14
+ proxy_pin :reset, DigitalIO::Output, optional: true
15
+ reset.high if reset
16
+ end
17
+
18
+ # Commands are SPI bytes written while DC pin is low.
19
+ def command(bytes)
20
+ dc.low
21
+ spi_write(bytes)
22
+ end
23
+
24
+ # Display data are SPI SPI bytes written while DC pin is high.
25
+ def data(bytes)
26
+ dc.high
27
+ spi_write(bytes)
28
+ end
29
+
30
+ def transfer_limit
31
+ @transfer_limit ||= bus.board.spi_limit
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ module Denko
2
+ module Display
3
+ module SPIEPaperCommon
4
+ include SPICommon
5
+
6
+ # Defaults. Override in subclasses as needed.
7
+ BUSY_WAIT_TIME = 0.005
8
+ RESET_TIME = 0.010
9
+
10
+ def initialize_pins(options={})
11
+ super(options)
12
+ proxy_pin :busy, DigitalIO::Input, board: bus.board
13
+ busy.stop
14
+ end
15
+
16
+ def busy_wait
17
+ # #read is more compatible than #listen
18
+ sleep self.class::BUSY_WAIT_TIME while busy.read == 1
19
+ end
20
+
21
+ def hw_reset
22
+ if reset
23
+ reset.low
24
+ sleep self.class::RESET_TIME
25
+ reset.high
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,238 +1,16 @@
1
- require_relative 'canvas'
2
-
3
1
  module Denko
4
2
  module Display
5
3
  class SSD1306
6
- include Behaviors::BusPeripheral
7
- include Behaviors::Lifecycle
8
-
9
- # I2C Defaults
10
- I2C_ADDRESS = 0x3C
11
- I2C_FREQUENCY = 400_000
12
-
13
- # Fundamental Commands
14
- # Single byte (no need to OR with anything)
15
- PIXELS_FROM_RAM = 0xA4
16
- PIXELS_ALL_ON = 0xA5
17
- INVERT_OFF = 0xA6
18
- INVERT_ON = 0xA7
19
- DISPLAY_OFF = 0xAE
20
- DISPLAY_ON = 0xAF
21
-
22
- # Double byte (following byte sets value)
23
- CONTRAST = 0x81
24
- # Values: 0x00 to 0xFF. Default is 0x7F
25
-
26
- # Scrolling commands ignored.
27
-
28
- # Address Setting Commands
29
- # Single byte. OR with value. These are for page addressing mode only.
30
- COLUMN_START_LOWER = 0x00 # lower 4 bytes of column
31
- COLUMN_START_UPPER = 0x10 # upper 4 bytes of column
32
- PAGE_START = 0xB0 # page 0-7
33
-
34
- # Double byte. Following byte sets value.
35
- ADDRESSING_MODE = 0x20
36
- # Values:
37
- # 0x00 = horizontal (Pages auto-increment. Used for SSD1306)
38
- # 0x01 = vertical
39
- # 0x02 = page (Default. Page and column must be set each time. Needed on SH1106)
40
- ADDRESSING_MODE_DEFAULT = 0x00
41
-
42
- # Triple byte. Following 2 bytes sets value. For H/V addressing modes only.
43
- COLUMN_ADDRESS_RANGE = 0x21
44
- PAGE_ADDRESS_RANGE = 0x22
45
- # For both: first value = min column/row, second value = max column/row
46
-
47
- # Hardware Configuration Commands
48
- # Single byte. OR with value.
49
- START_LINE = 0x40 # Value: lowest 6 bits set RAM start line (default 0b000000)
50
- SEGMENT_REMAP = 0xA0 # Value: 0x00 = default, 0x01 = column draw order reversed (horizontal reflection)
51
- COM_DIRECTION = 0xC0 # Value: 0x00 = default, 0x08 = row draw order reversed (vertical reflection)
52
-
53
- # Double-byte commands. Following byte sets value.
54
- CHARGE_PUMP = 0x8D # Value: 0x10 = disable/external, 0x14 = enable/internal
55
- MULTIPLEX_RATIO = 0xA8 # Value: rows of display - 1
56
- DISPLAY_OFFSET = 0xD3 # Value: lowest 5 bits. Vertically shifts COM by that amount.
57
- COM_PIN_CONFIG = 0xDA
58
- # 0x02 = sequential, left and right not swapped
59
- # 0x12 = alternative, left and right not swapped (default)
60
- # 0x22 = sequential, left and right sawpped
61
- # 0x32 = alternative, left and right swapped
62
-
63
- # Timing & Driving Commands
64
- # Double-byte commands. Following byte sets value.
65
- CLOCK = 0xD5 # Lowest 4 bits = divider. Upper 4 bits = oscillator frequency.
66
- PRECHARGE_PERIOD = 0xD9 # Lowest 4 bits = phase 1. Upper 4 bits = phase 2. 0xF1 for internal charge pump. 0x22 for external.
67
- VCOM_DESELECT_LEVEL = 0xDB # 0x00 = 0.65 x Vcc, 0x20 = x 0.77 * Vcc (default), 0x30 = 0.83 x Vcc
68
-
69
- # Valid widths and heights for displays
70
- WIDTHS = [64,96,128]
71
- HEIGHTS = [16,32,48,64]
72
-
73
- attr_accessor :canvas
74
-
75
- # Default to a 128x64 display.
76
- def columns
77
- @columns ||= params[:columns] || params[:width] || 128
78
- end
79
-
80
- def rows
81
- @rows ||= params[:rows] || params[:height] || 64
82
- end
83
-
84
- def rotated
85
- return @rotated unless @rotated.nil?
86
- @rotated = params[:rotated]
87
- @rotated = params[:rotate] if @rotated.nil?
88
- @rotated = false if @rotated.nil?
89
- @rotated
90
- end
91
-
92
- # Decide whether this instnace is I2C or SPI.
93
- before_initialize do
94
- bus = params[:bus] || params[:board]
95
-
96
- if bus.class.ancestors.include?(Denko::SPI::Bus) || bus.class.ancestors.include?(Denko::SPI::BitBang)
97
- mutate_spi
98
- elsif bus.class.ancestors.include?(Denko::I2C::Bus) || bus.class.ancestors.include?(Denko::I2C::BitBang)
99
- mutate_i2c
100
- else
101
- raise ArgumentError, "#{self.class} must be connected to either an I2C or SPI bus"
102
- end
103
- end
104
-
105
- after_initialize do
106
- # Validate known sizes.
107
- raise ArgumentError, "error in #{self.class} width: #{columns}. Must be in: #{WIDTHS.inspect}" unless WIDTHS.include?(columns)
108
- raise ArgumentError, "error in #{self.class} height: #{rows}. Must be in: #{HEIGHTS.inspect}" unless HEIGHTS.include?(rows)
109
-
110
- # Everything except 96x16 size uses clock 0x80.
111
- clock = 0x80
112
- clock = 0x60 if (columns == 96 && rows == 16)
113
-
114
- # 128x32 and 96x16 sizes use com pin config 0x02
115
- com_pin_config = 0x12
116
- com_pin_config = 0x02 if (columns == 96 && rows == 16) || (columns == 128 && rows == 32)
4
+ include MonoOLED
117
5
 
118
- # Reflecting horizontally and vertically to effectively rotate 180 degrees.
119
- seg_remap = rotated ? 0x01 : 0x00
120
- com_direction = rotated ? 0x08 : 0x00
6
+ def draw_partial(buffer, x_start, x_finish, p_start, p_finish, color=1)
7
+ partial_buffer = get_partial_buffer(buffer, x_start, x_finish, p_start, p_finish)
121
8
 
122
- # Startup sequence (SPI doesn't work properly if this isn't sent twice.)
123
- 2.times do
124
- command [
125
- MULTIPLEX_RATIO, rows - 1,
126
- DISPLAY_OFFSET, 0x00,
127
- START_LINE | 0x00,
128
- SEGMENT_REMAP | seg_remap,
129
- COM_DIRECTION | com_direction,
130
- COM_PIN_CONFIG, com_pin_config,
131
- PIXELS_FROM_RAM,
132
- INVERT_OFF,
133
- CLOCK, clock,
134
- VCOM_DESELECT_LEVEL, 0x20,
135
- PRECHARGE_PERIOD, 0xF1, # Charge period for internal charge pump
136
- CHARGE_PUMP, 0x14, # Internal charge pump
137
- ADDRESSING_MODE, self.class::ADDRESSING_MODE_DEFAULT,
138
- DISPLAY_ON
139
- ]
140
- end
141
-
142
- # Create a new blank canvas and draw it.
143
- self.canvas = Canvas.new(columns, rows)
144
- draw
145
- end
146
-
147
- def off
148
- command [DISPLAY_OFF]
149
- end
150
-
151
- def on
152
- command [DISPLAY_ON]
153
- end
154
-
155
- def contrast=(value)
156
- raise ArgumentError, "contrast must be in range 0..255" if (value < 0 || value > 255)
157
- command [CONTRAST, value]
158
- end
159
-
160
- def draw(x_min=0, x_max=(columns-1), y_min=0, y_max=(rows-1))
161
- # Convert y-coords to page coords.
162
- p_min = y_min / 8
163
- p_max = y_max / 8
164
-
165
- # If drawing the whole frame (default), bypass temp buffer to save time.
166
- if (x_min == 0) && (x_max == columns-1) && (p_min == 0) && (p_max == rows/8)
167
- draw_partial(canvas.framebuffer, x_min, x_max, p_min, p_max)
168
-
169
- # Copy bytes for the given rectangle into a temp buffer.
170
- else
171
- temp_buffer = []
172
- (p_min..p_max).each do |page|
173
- src_start = (columns * page) + x_min
174
- src_end = (columns * page) + x_max
175
- temp_buffer += canvas.framebuffer[src_start..src_end]
176
- end
177
-
178
- # And draw them.
179
- draw_partial(temp_buffer, x_min, x_max, p_min, p_max)
180
- end
181
- end
182
-
183
- def draw_partial(buffer, x_min, x_max, p_min, p_max)
184
9
  # Limit auto-incrementing GRAM address to the rectangle being drawn.
185
- command [ COLUMN_ADDRESS_RANGE, x_min, x_max, PAGE_ADDRESS_RANGE, p_min, p_max ]
186
-
187
- # Send all the bytes at once if within board I2C limit.
188
- if buffer.length < (bus.board.i2c_limit - 1)
189
- data(buffer)
190
-
191
- # Or split into chunks.
192
- else
193
- buffer.each_slice(bus.board.i2c_limit - 1) { |slice| data(slice) }
194
- end
195
- end
196
-
197
- def mutate_i2c
198
- singleton_class.class_eval do
199
- include I2C::Peripheral
200
-
201
- # Commands are I2C messages prefixed with 0x00.
202
- def command(bytes)
203
- i2c_write([0x00] + bytes)
204
- end
205
-
206
- # Data are I2C messages prefixed with 0x40.
207
- def data(bytes)
208
- i2c_write([0x40] + bytes)
209
- end
210
- end
211
- end
212
-
213
- def mutate_spi
214
- singleton_class.class_eval do
215
- include SPI::Peripheral::MultiPin
216
-
217
- def initialize_pins(options={})
218
- super(options)
219
- proxy_pin :dc, DigitalIO::Output, board: bus.board
220
- proxy_pin :reset, DigitalIO::Output, board: bus.board, optional: true
221
- reset.high if reset
222
- end
223
-
224
- # Commands are SPI bytes written while DC pin low.
225
- def command(bytes)
226
- dc.low
227
- spi_write(bytes)
228
- end
10
+ command [ COLUMN_ADDRESS_RANGE, x_start, x_finish, PAGE_ADDRESS_RANGE, p_start, p_finish ]
229
11
 
230
- # Data are SPI SPI bytes written while DC pin high.
231
- def data(bytes)
232
- dc.high
233
- spi_write(bytes)
234
- end
235
- end
12
+ # Send in chunks up to maximum transfer size.
13
+ partial_buffer.each_slice(transfer_limit) { |slice| data(slice) }
236
14
  end
237
15
  end
238
16
  end
@@ -0,0 +1,14 @@
1
+ module Denko
2
+ module Display
3
+ class SSD1680 < SSD168X
4
+ COLUMNS = 296
5
+ ROWS = 128
6
+
7
+ # SSD1680 needs an extra byte here to offset source start by 8 pixels.
8
+ def set_display_update_control
9
+ super
10
+ data [0b1000_0000]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ module Denko
2
+ module Display
3
+ class SSD1681 < SSD168X
4
+ COLUMNS = 200
5
+ ROWS = 200
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,227 @@
1
+ module Denko
2
+ module Display
3
+ class SSD168X
4
+ include Behaviors::Lifecycle
5
+ include SPIEPaperCommon
6
+
7
+ # Used by #hw_reset
8
+ RESET_TIME = 0.010
9
+
10
+ # Typical Commands
11
+ SW_RESET = 0x12
12
+ DRIVER_OUTPUT_CTL = 0x01 # +3 data
13
+ DATA_ENTRY_MODE_SET = 0x11 # +1 data
14
+ BORDER_WAVEFORM_CTL = 0x3C # +1 data
15
+ DISPLAY_UPDATE_CTL1 = 0x21 # +1 data
16
+ TEMP_SENSOR_SELECT = 0x18 # +1 data
17
+ RAM_X_RANGE_SET = 0x44 # +2 data. X address range to stay within.
18
+ RAM_Y_RANGE_SET = 0x45 # +4 data. Y address range to stay within.
19
+ RAM_X_ADDR_SET = 0x4E # +1 data. X start address
20
+ RAM_Y_ADDR_SET = 0x4F # +2 data. Y start address
21
+ RAM_WRITE_BW = 0x24 # write n pixel data bytes after
22
+ RAM_WRITE_RED = 0x26 # write n pixel data bytes after
23
+ MASTER_ACTIVATION = 0x20
24
+ DISPLAY_UPDATE_CTL2 = 0x22 # +1 data
25
+ DEEP_SLEEP = 0x10 # +1 data
26
+ BOOSTER_CTL = 0x0C # +4 data
27
+
28
+ #
29
+ # Other commands taken from data sheet.
30
+ # Not used yet. Maybe for enabling more features in future?
31
+ #
32
+ RAM_AUTO_INC_BW = 0x46 # +1 data. This sets the auto-increment amount?
33
+ RAM_AUTO_INC_RED = 0x47 # +1 data. This sets the auto-increment amount?
34
+ READ_RAM = 0x27 # read n pixel data bytes after
35
+ GATE_VOLTAGE_CTL = 0x03 # +1 data
36
+ SOURCE_VOLTAGE_CTL = 0x04 # +3 data
37
+ INITIAL_CODE_OTP = 0x08 # ???
38
+ INITIAL_CODE_REG_SET = 0x08 # +3 data
39
+ INITIAL_CODE_REG_GET = 0x0A # Read 3 bytes back? Datasheet not clear.
40
+ HV_READY_DETECTION = 0x14 # +1 data
41
+ VCI_DETECTION = 0x15 # +1 data
42
+ TEMP_SENSOR_REG_SET = 0x1A # +2 data
43
+ TEMP_SENSOR_REG_GET = 0x1B # +2 data READ
44
+ TEMP_SENSOR_CTL = 0x1C # +3 data
45
+ VCOM_SENSE = 0x28
46
+ VCOM_SENS_DURATION = 0x29 # +1 data
47
+ PROGRAM_VCOM_OTP = 0x2A # +1 data
48
+ VCOM_REG_CTL = 0x2B # +2 data
49
+ VCOM_REG_WRITE = 0x2C # +1 data
50
+ OTP_REG_GET = 0x2D # +11 data READ
51
+ USER_ID_GET = 0x2E # +10 data READ
52
+ STATUS_BIT_GET = 0x2F # +1 data READ
53
+ PROGRAM_WS_OTP = 0x30
54
+ LOAD_WS_OTP = 0x31
55
+ WRITE_LUT_REGISTER = 0x32 # +153 data
56
+ CRC_CALCULATION = 0x34
57
+ CRC_STATUS_GET = 0x35 # +2 data READ
58
+ PROGRAM_OTP_SELECTION = 0x36
59
+ DISPLAY_OPTION_REG_SET = 0x37 # +10 data
60
+ USER_ID_REG_SET = 0x38 # +10 data
61
+ OTP_PROGRAM_MODE = 0x39 # +1 data
62
+ END_OPTION = 0x3F # +1 data
63
+ READ_RAM_OPTION = 0x41 # +1 data
64
+ NOP = 0x7F
65
+
66
+ def set_driver_output_control(gate_lines=columns)
67
+ # First data byte is lowest 8 bits of MUX value.
68
+ # Second data byte is 9th bit.
69
+ mux = gate_lines - 1
70
+
71
+ # Third byte:
72
+ # Bit 2: toggles gate scan interleave order
73
+ # Bit 1: enables gate scan interleaving
74
+ # Bit 0: flips gate scan direction, mirroring display in 1 axis
75
+ third_byte = @reflect_x ? 0b000 : 0b001
76
+
77
+ command [DRIVER_OUTPUT_CTL]
78
+ data [mux & 0xFF, (mux >> 8) & 0b1, third_byte]
79
+ end
80
+
81
+ def reflect_x
82
+ @reflect_x = !@reflect_x
83
+ end
84
+
85
+ def set_data_entry_mode
86
+ # Bit 2 = 1 : update hardware Y (software X) address first (after each byte),
87
+ # then update hardware X (software P) on overflow. (0 would update hardware X / software P first)
88
+ # Bit 1 = 1 : increment hardware Y (0 would decrement)
89
+ # Bit 0 = 1 : increment hardware X (0 would decrement)
90
+ command [DATA_ENTRY_MODE_SET]
91
+ data [0b111]
92
+ end
93
+
94
+ # Treating hardware X axis as page (P) axis, and hardware Y axis as X axis to match framebuffer.
95
+ def set_range_x(start=x_min, finish=x_max)
96
+ command [RAM_Y_RANGE_SET]
97
+ data [start & 0xFF, (start >> 8) & 0b1, finish & 0xFF, (finish >> 8) & 0b1]
98
+ end
99
+
100
+ def set_range_p(start=p_min, finish=p_max)
101
+ command [RAM_X_RANGE_SET]
102
+ data [start, finish]
103
+ end
104
+
105
+ def set_address_x(addr=x_min)
106
+ command [RAM_Y_ADDR_SET]
107
+ data [addr & 0xFF, (addr >> 8) & 0b1]
108
+ end
109
+
110
+ def set_address_p(addr=p_min)
111
+ command [RAM_X_ADDR_SET]
112
+ data [addr]
113
+ end
114
+
115
+ def set_panel_border
116
+ # Default to GS Transition: Follow LUT and LUT1, and VBD fix level: VSS.
117
+ command [BORDER_WAVEFORM_CTL]
118
+ data [0b00_00_00_01]
119
+ end
120
+
121
+ def set_temperature_sensor
122
+ # Use internal temperature sensor
123
+ command [TEMP_SENSOR_SELECT]
124
+ data [0x80]
125
+ end
126
+
127
+ def set_display_update_control
128
+ # In hardware:
129
+ # 0b1000: display inverted
130
+ # 0b0100: bypass
131
+ # 0b0000: display normally
132
+ #
133
+ # For black only, hardware treats 1 as blank, 0 as filled. Opposite of Canvas.
134
+ black = @invert_black ? 0b0000 : 0b1000
135
+ red = (colors == 1) ? 0b0100 : 0b0000
136
+
137
+ command [DISPLAY_UPDATE_CTL1]
138
+ data [red << 4 | black]
139
+ end
140
+
141
+ def invert_black
142
+ @invert_black = !@invert_black
143
+ end
144
+
145
+ def set_display_update_sequence(value=0x80)
146
+ # 0x80 enables clock signal without loading pixels from RAM
147
+ # 0xF7 refreshes all pixels from RAM
148
+ command [DISPLAY_UPDATE_CTL2]
149
+ data [value]
150
+ end
151
+
152
+ def booster_soft_start
153
+ command [BOOSTER_CTL]
154
+ data [
155
+ 0b1010_0011, # phase 1
156
+ 0b1100_0111, # phase 2
157
+ 0b1100_0011, # phase 3
158
+ 0b0000_0001, # duration
159
+ ]
160
+ end
161
+
162
+ def master_activate
163
+ command [MASTER_ACTIVATION]
164
+ end
165
+
166
+ def deep_sleep(sleep_mode=0b11)
167
+ # 0b00 = Normal Mode
168
+ # 0b01 = Deep Sleep Mode 1
169
+ # 0b11 = Deep Sleep Mode 2
170
+ command [DEEP_SLEEP]
171
+ data [sleep_mode]
172
+ end
173
+
174
+ def wake
175
+ hw_reset
176
+ command [SW_RESET]
177
+ sleep 0.020
178
+
179
+ set_driver_output_control
180
+ set_data_entry_mode
181
+ set_temperature_sensor
182
+ set_panel_border
183
+
184
+ set_display_update_control
185
+ set_display_update_sequence
186
+ master_activate
187
+ busy_wait
188
+ end
189
+
190
+ after_initialize do
191
+ wake
192
+ end
193
+
194
+ def draw_partial(buffer, x_start, x_finish, p_start, p_finish, color=1)
195
+ partial_buffer = get_partial_buffer(buffer, x_start, x_finish, p_start, p_finish)
196
+
197
+ # These displays treat bit 7 of a byte as the top pixel, but canvas uses bit 0 as top.
198
+ # Bytes are sent reversed to fix this, essentially rotating the image by 180 degrees byte-wise.
199
+ # Transform framebuffer coordinates to rotated hardware coordinates before sending.
200
+ x1 = x_max - x_finish
201
+ x2 = x_max - x_start
202
+ p1 = p_max - p_finish
203
+ p2 = p_max - p_start
204
+
205
+ # Set hardware addresses
206
+ set_range_x x1, x2
207
+ set_range_p p1, p2
208
+ set_address_x x1
209
+ set_address_p p1
210
+
211
+ # Send as black by default, or red if specified
212
+ ram_select = (color == 2) ? RAM_WRITE_RED : RAM_WRITE_BW
213
+ command [ram_select]
214
+ partial_buffer.reverse.each_slice(transfer_limit) { |slice| data(slice) }
215
+ end
216
+
217
+ def refresh
218
+ booster_soft_start
219
+ set_driver_output_control
220
+ set_display_update_control
221
+ set_display_update_sequence(0xF7)
222
+ master_activate
223
+ busy_wait
224
+ end
225
+ end
226
+ end
227
+ end