denko 0.13.6 → 0.14.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 (376) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/{build_avr.yml → build_atmega_avr.yml} +18 -18
  3. data/.github/workflows/{build_megaavr.yml → build_atmega_megaavr.yml} +18 -18
  4. data/.github/workflows/{build_sam3x.yml → build_atsam3x.yml} +17 -17
  5. data/.github/workflows/{build_samd.yml → build_atsamd21.yml} +18 -18
  6. data/.github/workflows/build_esp32.yml +17 -18
  7. data/.github/workflows/build_esp32c3.yml +57 -0
  8. data/.github/workflows/build_esp32c6.yml +57 -0
  9. data/.github/workflows/build_esp32h2.yml +56 -0
  10. data/.github/workflows/build_esp32s2.yml +57 -0
  11. data/.github/workflows/build_esp32s3.yml +57 -0
  12. data/.github/workflows/build_esp8266.yml +15 -15
  13. data/.github/workflows/build_ra4m1.yml +16 -16
  14. data/.github/workflows/build_rp2040.yml +17 -16
  15. data/.github/workflows/ruby.yml +20 -20
  16. data/CHANGELOG.md +195 -11
  17. data/DEPS_CLI.md +9 -9
  18. data/DEPS_IDE.md +17 -18
  19. data/HARDWARE.md +50 -51
  20. data/README.md +61 -53
  21. data/Rakefile +1 -1
  22. data/benchmarks/analog_listen.rb +49 -0
  23. data/benchmarks/digital_write.rb +28 -0
  24. data/benchmarks/i2c_ssd1306_refresh.rb +13 -6
  25. data/build +1 -1
  26. data/denko.gemspec +5 -2
  27. data/examples/advanced/{m5_env.rb → m5_env3.rb} +12 -14
  28. data/examples/advanced/rotary_encoder_mac_volume.rb +18 -13
  29. data/examples/advanced/ssd1306_time_temp_rh.rb +8 -13
  30. data/examples/analog_io/ads1100.rb +48 -0
  31. data/examples/analog_io/ads1115.rb +2 -2
  32. data/examples/analog_io/ads1118.rb +3 -11
  33. data/examples/analog_io/input.rb +17 -16
  34. data/examples/analog_io/input_smoothing.rb +27 -0
  35. data/examples/analog_io/potentiometer.rb +31 -0
  36. data/examples/connection/binary_echo.rb +34 -0
  37. data/examples/connection/tcp.rb +12 -27
  38. data/examples/digital_io/button.rb +7 -3
  39. data/examples/digital_io/relay.rb +17 -0
  40. data/examples/digital_io/rotary_encoder.rb +21 -11
  41. data/examples/display/hd44780.rb +13 -5
  42. data/examples/display/ssd1306.rb +20 -17
  43. data/examples/display/ssd1306_s2_pico.rb +2 -2
  44. data/examples/i2c/search.rb +10 -26
  45. data/examples/led/apa102_bounce.rb +3 -4
  46. data/examples/led/apa102_fade.rb +44 -0
  47. data/examples/led/builtin_blink.rb +3 -1
  48. data/examples/led/builtin_fade.rb +19 -0
  49. data/examples/led/rgb_led.rb +31 -0
  50. data/examples/led/seven_segment_char_echo.rb +4 -2
  51. data/examples/led/ws2812_bounce.rb +5 -7
  52. data/examples/led/ws2812_builtin_blink.rb +3 -2
  53. data/examples/led/ws2812_fade.rb +43 -0
  54. data/examples/motor/l298.rb +10 -8
  55. data/examples/motor/servo.rb +4 -3
  56. data/examples/motor/stepper.rb +13 -13
  57. data/examples/one_wire/search.rb +32 -0
  58. data/examples/pulse_io/buzzer.rb +8 -3
  59. data/examples/pulse_io/ir_output.rb +51 -0
  60. data/examples/pulse_io/pwm_output.rb +30 -0
  61. data/examples/rtc/ds3231.rb +18 -35
  62. data/examples/sensor/aht10.rb +4 -6
  63. data/examples/sensor/aht20.rb +4 -6
  64. data/examples/sensor/bme280.rb +4 -4
  65. data/examples/sensor/bmp180.rb +9 -5
  66. data/examples/sensor/dht.rb +20 -15
  67. data/examples/sensor/ds18b20.rb +20 -21
  68. data/examples/sensor/generic_pir.rb +4 -2
  69. data/examples/sensor/hcsr04.rb +5 -2
  70. data/examples/sensor/htu21d.rb +9 -20
  71. data/examples/sensor/htu31d.rb +7 -9
  72. data/examples/sensor/neat_tph_readings.rb +15 -9
  73. data/examples/sensor/qmp6988.rb +5 -7
  74. data/examples/sensor/rcwl9620.rb +3 -3
  75. data/examples/sensor/sht3x.rb +4 -6
  76. data/examples/spi/bitbang_loopback.rb +46 -0
  77. data/examples/spi/input_register.rb +9 -19
  78. data/examples/spi/output_register.rb +9 -17
  79. data/examples/spi/ssd_through_registers.rb +28 -0
  80. data/examples/spi/two_registers.rb +18 -24
  81. data/examples/uart/bit_bang_demo.rb +25 -0
  82. data/examples/uart/board_passthrough.rb +19 -13
  83. data/examples/uart/hardware_loopback.rb +1 -1
  84. data/lib/denko/analog_io/ads1100.rb +127 -0
  85. data/lib/denko/analog_io/ads1115.rb +8 -25
  86. data/lib/denko/analog_io/ads1118.rb +10 -25
  87. data/lib/denko/analog_io/ads111x.rb +25 -11
  88. data/lib/denko/analog_io/input.rb +29 -55
  89. data/lib/denko/analog_io/input_helper.rb +42 -0
  90. data/lib/denko/analog_io/output.rb +5 -5
  91. data/lib/denko/analog_io/potentiometer.rb +6 -8
  92. data/lib/denko/analog_io.rb +2 -1
  93. data/lib/denko/behaviors/board_proxy.rb +13 -1
  94. data/lib/denko/behaviors/bus_controller.rb +1 -0
  95. data/lib/denko/behaviors/bus_controller_addressed.rb +1 -0
  96. data/lib/denko/behaviors/bus_peripheral.rb +3 -4
  97. data/lib/denko/behaviors/bus_peripheral_addressed.rb +8 -6
  98. data/lib/denko/behaviors/callbacks.rb +9 -7
  99. data/lib/denko/behaviors/component.rb +16 -14
  100. data/lib/denko/behaviors/input_pin.rb +14 -15
  101. data/lib/denko/behaviors/lifecycle.rb +51 -0
  102. data/lib/denko/behaviors/multi_pin.rb +22 -18
  103. data/lib/denko/behaviors/output_pin.rb +9 -4
  104. data/lib/denko/behaviors/single_pin.rb +1 -0
  105. data/lib/denko/behaviors/state.rb +15 -9
  106. data/lib/denko/behaviors/subcomponents.rb +72 -12
  107. data/lib/denko/behaviors.rb +2 -1
  108. data/lib/denko/board/core.rb +36 -18
  109. data/lib/denko/board/i2c.rb +14 -14
  110. data/lib/denko/board/i2c_bit_bang.rb +49 -0
  111. data/lib/denko/board/infrared.rb +6 -6
  112. data/lib/denko/board/led_array.rb +6 -5
  113. data/lib/denko/board/spi.rb +15 -10
  114. data/lib/denko/board/spi_bit_bang.rb +9 -7
  115. data/lib/denko/board.rb +35 -33
  116. data/lib/denko/connection/binary_echo.rb +17 -0
  117. data/lib/denko/connection/flow_control.rb +11 -15
  118. data/lib/denko/connection/handshake.rb +2 -0
  119. data/lib/denko/digital_io/button.rb +4 -0
  120. data/lib/denko/digital_io/c_bit_bang.rb +15 -0
  121. data/lib/denko/digital_io/input.rb +4 -5
  122. data/lib/denko/digital_io/output.rb +7 -6
  123. data/lib/denko/digital_io/relay.rb +2 -0
  124. data/lib/denko/digital_io/rotary_encoder.rb +78 -60
  125. data/lib/denko/digital_io.rb +1 -0
  126. data/lib/denko/display/hd44780.rb +136 -93
  127. data/lib/denko/display/sh1106.rb +42 -0
  128. data/lib/denko/display/ssd1306.rb +105 -45
  129. data/lib/denko/display.rb +1 -0
  130. data/lib/denko/eeprom/built_in.rb +19 -16
  131. data/lib/denko/i2c/bit_bang.rb +31 -0
  132. data/lib/denko/i2c/bus.rb +8 -36
  133. data/lib/denko/i2c/bus_common.rb +45 -0
  134. data/lib/denko/i2c/peripheral.rb +28 -19
  135. data/lib/denko/i2c.rb +2 -0
  136. data/lib/denko/led/apa102.rb +43 -29
  137. data/lib/denko/led/base.rb +8 -2
  138. data/lib/denko/led/rgb.rb +5 -7
  139. data/lib/denko/led/seven_segment.rb +24 -9
  140. data/lib/denko/led/ws2812.rb +10 -7
  141. data/lib/denko/message.rb +5 -0
  142. data/lib/denko/motor/l298.rb +11 -10
  143. data/lib/denko/motor/servo.rb +22 -10
  144. data/lib/denko/motor/stepper.rb +11 -14
  145. data/lib/denko/mutex_stub.rb +7 -0
  146. data/lib/denko/one_wire/bus.rb +9 -5
  147. data/lib/denko/one_wire/peripheral.rb +0 -3
  148. data/lib/denko/pulse_io/buzzer.rb +9 -3
  149. data/lib/denko/pulse_io/{ir_transmitter.rb → ir_output.rb} +9 -4
  150. data/lib/denko/pulse_io/pwm_output.rb +69 -15
  151. data/lib/denko/pulse_io.rb +3 -3
  152. data/lib/denko/rtc/ds3231.rb +11 -13
  153. data/lib/denko/sensor/aht.rb +22 -21
  154. data/lib/denko/sensor/bme280.rb +60 -63
  155. data/lib/denko/sensor/bmp180.rb +41 -38
  156. data/lib/denko/sensor/dht.rb +22 -5
  157. data/lib/denko/sensor/ds18b20.rb +40 -34
  158. data/lib/denko/sensor/hcsr04.rb +7 -5
  159. data/lib/denko/sensor/helper.rb +37 -0
  160. data/lib/denko/sensor/htu21d.rb +44 -55
  161. data/lib/denko/sensor/htu31d.rb +32 -33
  162. data/lib/denko/sensor/qmp6988.rb +25 -23
  163. data/lib/denko/sensor/rcwl9620.rb +2 -5
  164. data/lib/denko/sensor/sht3x.rb +23 -21
  165. data/lib/denko/sensor.rb +1 -2
  166. data/lib/denko/spi/base_register.rb +22 -22
  167. data/lib/denko/spi/bit_bang.rb +17 -51
  168. data/lib/denko/spi/bus.rb +15 -29
  169. data/lib/denko/spi/bus_common.rb +36 -0
  170. data/lib/denko/spi/input_register.rb +36 -30
  171. data/lib/denko/spi/output_register.rb +25 -40
  172. data/lib/denko/spi/peripheral.rb +93 -24
  173. data/lib/denko/spi.rb +6 -1
  174. data/lib/denko/uart/bit_bang.rb +5 -3
  175. data/lib/denko/uart/hardware.rb +9 -8
  176. data/lib/denko/version.rb +1 -1
  177. data/lib/denko.rb +10 -0
  178. data/lib/denko_cli/generator.rb +2 -2
  179. data/lib/denko_cli/packages.rb +8 -10
  180. data/lib/denko_cli/targets.rb +8 -8
  181. data/lib/denko_cli/targets.txt +4 -4
  182. data/lib/denko_cli/usage.txt +1 -1
  183. data/src/denko_ethernet.ino +0 -14
  184. data/src/denko_serial.ino +0 -14
  185. data/src/denko_wifi.ino +6 -15
  186. data/src/lib/Denko.cpp +39 -3
  187. data/src/lib/Denko.h +42 -26
  188. data/src/lib/DenkoCoreIO.cpp +57 -102
  189. data/src/lib/DenkoDefines.h +36 -31
  190. data/src/lib/DenkoI2C.cpp +54 -45
  191. data/src/lib/DenkoI2CBB.cpp +238 -0
  192. data/src/lib/DenkoIROut.cpp +12 -7
  193. data/src/lib/DenkoLEDArray.cpp +36 -13
  194. data/src/lib/DenkoSPI.cpp +6 -5
  195. data/src/lib/DenkoSPIBB.cpp +7 -6
  196. data/target.yml +37 -2
  197. data/test/analog_io/potentiometer_test.rb +10 -10
  198. data/test/behaviors/board_proxy_test.rb +1 -1
  199. data/test/behaviors/callbacks_test.rb +11 -3
  200. data/test/behaviors/component_test.rb +17 -9
  201. data/test/behaviors/input_pin_test.rb +14 -9
  202. data/test/behaviors/multi_pin_test.rb +14 -4
  203. data/test/behaviors/output_pin_test.rb +11 -8
  204. data/test/behaviors/poller_test.rb +1 -0
  205. data/test/behaviors/reader_test.rb +3 -2
  206. data/test/behaviors/subcomponents_test.rb +22 -2
  207. data/test/board/core_test.rb +15 -11
  208. data/test/board/i2c_test.rb +39 -33
  209. data/test/board/infrared_test.rb +1 -1
  210. data/test/board/message_test.rb +17 -11
  211. data/test/board/spi_test.rb +21 -21
  212. data/test/digital_io/button_test.rb +15 -0
  213. data/test/digital_io/relay_test.rb +18 -0
  214. data/test/digital_io/rotary_encoder_test.rb +80 -60
  215. data/test/eeprom/built_in_test.rb +9 -9
  216. data/test/i2c/bus_test.rb +30 -14
  217. data/test/i2c/peripheral_test.rb +36 -17
  218. data/test/led/base_test.rb +2 -1
  219. data/test/led/rgb_test.rb +6 -6
  220. data/test/led/seven_segment_test.rb +7 -7
  221. data/test/motor/servo_test.rb +1 -1
  222. data/test/motor/stepper_test.rb +2 -2
  223. data/test/one_wire/bus_test.rb +1 -0
  224. data/test/pulse_io/buzzer_test.rb +7 -4
  225. data/test/pulse_io/{ir_transmitter_test.rb → ir_output_test.rb} +10 -10
  226. data/test/pulse_io/pwm_output_test.rb +74 -18
  227. data/test/rtc/ds3231_test.rb +11 -13
  228. data/test/sensor/dht_test.rb +1 -1
  229. data/test/sensor/ds18b20_test.rb +4 -8
  230. data/test/spi/bus_test.rb +7 -7
  231. data/test/spi/input_register_test.rb +15 -15
  232. data/test/spi/output_register_test.rb +10 -28
  233. data/test/spi/peripheral_multi_pin_test.rb +53 -0
  234. data/test/spi/peripheral_single_pin_test.rb +48 -0
  235. data/test/test_helper.rb +36 -33
  236. data/tutorial/02-button/button.rb +5 -4
  237. data/tutorial/03-potentiometer/potentiometer.rb +9 -5
  238. data/tutorial/04-pwm_led/pwm_led.rb +14 -16
  239. data/tutorial/05-rgb_led/rgb_led.rb +6 -6
  240. data/tutorial/05-rgb_led/rgb_mapping.rb +11 -11
  241. data/vendor/board-maps/BoardMap.h +416 -56
  242. data/vendor/board-maps/lib/header_parser.rb +12 -2
  243. data/vendor/board-maps/yaml/ADAFRUIT_CAMERA_ESP32S3.yml +2 -2
  244. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32C6.yml +15 -0
  245. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32_V2.yml +1 -1
  246. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_RP2040_ADALOGGER.yml +44 -0
  247. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32C3.yml +1 -0
  248. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S2.yml +1 -0
  249. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_N4R2.yml +1 -0
  250. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_NOPSRAM.yml +1 -0
  251. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32_PICO.yml +1 -0
  252. data/vendor/board-maps/yaml/AMKEN_BB.yml +48 -0
  253. data/vendor/board-maps/yaml/AMKEN_ES.yml +48 -0
  254. data/vendor/board-maps/yaml/AMKEN_REVELOP.yml +48 -0
  255. data/vendor/board-maps/yaml/AMKEN_REVELOP_PLUS.yml +48 -0
  256. data/vendor/board-maps/yaml/ASL_CAN_X2.yml +41 -0
  257. data/vendor/board-maps/yaml/BLING.yml +25 -0
  258. data/vendor/board-maps/yaml/BPI_LEAF_S3.yml +1 -0
  259. data/vendor/board-maps/yaml/BRIDGETEK_IDM2040_7A.yml +48 -0
  260. data/vendor/board-maps/yaml/Bee_Motion_Mini.yml +13 -1
  261. data/vendor/board-maps/yaml/Breadstick_Raspberry.yml +31 -0
  262. data/vendor/board-maps/yaml/DFROBOT_BEETLE_ESP32C6.yml +8 -0
  263. data/vendor/board-maps/yaml/DFROBOT_FIREBEETLE_2_ESP32C6.yml +20 -0
  264. data/vendor/board-maps/yaml/DFROBOT_FIREBEETLE_ESP32.yml +46 -0
  265. data/vendor/board-maps/yaml/DPTECHNICS_WALTER.yml +39 -0
  266. data/vendor/board-maps/yaml/ELECROW_CROWPANEL_7.yml +8 -0
  267. data/vendor/board-maps/yaml/ESP32C2_DEV.yml +12 -0
  268. data/vendor/board-maps/yaml/ESP32C3_DEVKIT_LIPO.yml +14 -0
  269. data/vendor/board-maps/yaml/ESP32C6_DEV.yml +15 -0
  270. data/vendor/board-maps/yaml/ESP32C6_EVB.yml +15 -0
  271. data/vendor/board-maps/yaml/ESP32C6_QWIIC_POCKET.yml +15 -0
  272. data/vendor/board-maps/yaml/ESP32C6_THING_PLUS.yml +15 -0
  273. data/vendor/board-maps/yaml/ESP32H2_DEV.yml +13 -0
  274. data/vendor/board-maps/yaml/ESP32H2_DEVKIT_LIPO.yml +13 -0
  275. data/vendor/board-maps/yaml/ESP32S2_DEV.yml +1 -0
  276. data/vendor/board-maps/yaml/{RMP.yml → ESP32S2_DEVKIT_LIPO.yml} +2 -1
  277. data/vendor/board-maps/yaml/ESP32S2_DEVKIT_LIPO_USB.yml +44 -0
  278. data/vendor/board-maps/yaml/ESP32S3_DEVKIT_LIPO.yml +42 -0
  279. data/vendor/board-maps/yaml/ESP32S3_POWERFEATHER.yml +22 -0
  280. data/vendor/board-maps/yaml/ESP32_SBC_FABGL.yml +35 -0
  281. data/vendor/board-maps/yaml/EVN_ALPHA.yml +48 -0
  282. data/vendor/board-maps/yaml/FEATHERS3NEO.yml +32 -0
  283. data/vendor/board-maps/yaml/GEEKBLE_ESP32C3.yml +14 -0
  284. data/vendor/board-maps/yaml/HELTEC_CAPSULE_SENSOR_V3.yml +43 -0
  285. data/vendor/board-maps/yaml/HELTEC_WIFI_LORA_32_V3.yml +42 -0
  286. data/vendor/board-maps/yaml/HELTEC_WIRELESS_BRIDGE.yml +8 -0
  287. data/vendor/board-maps/yaml/HELTEC_WIRELESS_MINI_SHELL.yml +13 -0
  288. data/vendor/board-maps/yaml/HELTEC_WIRELESS_PAPER.yml +42 -0
  289. data/vendor/board-maps/yaml/HELTEC_WIRELESS_SHELL_V3.yml +42 -0
  290. data/vendor/board-maps/yaml/HELTEC_WIRELESS_STICK_LITE_V3.yml +30 -0
  291. data/vendor/board-maps/yaml/HELTEC_WIRELESS_TRACKER.yml +41 -0
  292. data/vendor/board-maps/yaml/HT_DE01.yml +42 -0
  293. data/vendor/board-maps/yaml/IMBRIOS_LOGSENS_V1P1.yml +1 -1
  294. data/vendor/board-maps/yaml/LILYGO_T3S3_LR1121.yml +9 -0
  295. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1262.yml +9 -0
  296. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1276.yml +9 -0
  297. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1278.yml +9 -0
  298. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1280.yml +9 -0
  299. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1280PA.yml +8 -0
  300. data/vendor/board-maps/yaml/LILYGO_T_ETH_LITE.yml +21 -0
  301. data/vendor/board-maps/yaml/LOLIN_C3_PICO.yml +14 -0
  302. data/vendor/board-maps/yaml/LOLIN_S3.yml +1 -0
  303. data/vendor/board-maps/yaml/LOLIN_S3_MINI_PRO.yml +40 -0
  304. data/vendor/board-maps/yaml/Lion_Bit_Dev_Board.yml +0 -2
  305. data/vendor/board-maps/yaml/LoPy.yml +1 -0
  306. data/vendor/board-maps/yaml/LoPy4.yml +1 -0
  307. data/vendor/board-maps/yaml/M5STACK_CAPSULE.yml +8 -0
  308. data/vendor/board-maps/yaml/M5STACK_CARDPUTER.yml +8 -0
  309. data/vendor/board-maps/yaml/M5STACK_DIAL.yml +8 -0
  310. data/vendor/board-maps/yaml/M5STACK_FIRE.yml +0 -1
  311. data/vendor/board-maps/yaml/M5STACK_NANOC6.yml +17 -0
  312. data/vendor/board-maps/yaml/M5STACK_PAPER.yml +9 -0
  313. data/vendor/board-maps/yaml/M5STACK_POE_CAM.yml +5 -0
  314. data/vendor/board-maps/yaml/M5STACK_STAMP_C3.yml +13 -0
  315. data/vendor/board-maps/yaml/M5STACK_STAMP_S3.yml +4 -0
  316. data/vendor/board-maps/yaml/{M5Stick_C.yml → M5STACK_STICKC.yml} +0 -1
  317. data/vendor/board-maps/yaml/M5STACK_STICKC_PLUS.yml +9 -0
  318. data/vendor/board-maps/yaml/M5STACK_STICKC_PLUS2.yml +9 -0
  319. data/vendor/board-maps/yaml/M5STACK_TOUGH.yml +9 -0
  320. data/vendor/board-maps/yaml/M5STACK_UNIT_CAM.yml +10 -0
  321. data/vendor/board-maps/yaml/M5STACK_UNIT_CAMS3.yml +4 -0
  322. data/vendor/board-maps/yaml/M5Stack_ATOM.yml +0 -1
  323. data/vendor/board-maps/yaml/MAKERGO_C3_SUPERMINI.yml +14 -0
  324. data/vendor/board-maps/yaml/MARBLE_PICO.yml +48 -0
  325. data/vendor/board-maps/yaml/METEHOCA_AKANA_R1.yml +46 -0
  326. data/vendor/board-maps/yaml/NAMINO_BIANCO.yml +13 -0
  327. data/vendor/board-maps/yaml/NEBULAS3.yml +0 -1
  328. data/vendor/board-maps/yaml/NEWSAN_ARCHI.yml +48 -0
  329. data/vendor/board-maps/yaml/NOLOGO_ESP32C3_SUPER_MINI.yml +14 -0
  330. data/vendor/board-maps/yaml/NOLOGO_ESP32S3_PICO.yml +12 -0
  331. data/vendor/board-maps/yaml/OLIMEX_RP2040_PICO30_16MB.yml +48 -0
  332. data/vendor/board-maps/yaml/OLIMEX_RP2040_PICO30_2MB.yml +48 -0
  333. data/vendor/board-maps/yaml/OPTA_ANALOG.yml +7 -0
  334. data/vendor/board-maps/yaml/OPTA_DIGITAL.yml +5 -0
  335. data/vendor/board-maps/yaml/PINTRONIX_PINMAX.yml +42 -0
  336. data/vendor/board-maps/yaml/PYCOM_GPY.yml +1 -0
  337. data/vendor/board-maps/yaml/REDPILL_ESP32S3.yml +0 -1
  338. data/vendor/board-maps/yaml/SENSEBOX_MCU_ESP32S2.yml +12 -0
  339. data/vendor/board-maps/yaml/SPARKFUN_MICROMOD_RP2040.yml +48 -0
  340. data/vendor/board-maps/yaml/SPARKFUN_PRO_MICRO_ESP32C3.yml +24 -0
  341. data/vendor/board-maps/yaml/THINGPULSE_EPULSE_FEATHER.yml +31 -0
  342. data/vendor/board-maps/yaml/THINGPULSE_EPULSE_FEATHER_C6.yml +15 -0
  343. data/vendor/board-maps/yaml/TINYC6.yml +25 -0
  344. data/vendor/board-maps/yaml/UPESY_EDU_ESP32.yml +28 -0
  345. data/vendor/board-maps/yaml/UPESY_ESP32C3_BASIC.yml +13 -0
  346. data/vendor/board-maps/yaml/UPESY_ESP32C3_MINI.yml +12 -0
  347. data/vendor/board-maps/yaml/UPESY_ESP32S3_BASIC.yml +42 -0
  348. data/vendor/board-maps/yaml/VIRALINK_GATE32_01.yml +6 -0
  349. data/vendor/board-maps/yaml/VIRALINK_GATE32_11.yml +7 -0
  350. data/vendor/board-maps/yaml/WAVESHARE_ESP32S3_TOUCH_LCD_128.yml +8 -0
  351. data/vendor/board-maps/yaml/WAVESHARE_RP2040_MATRIX.yml +48 -0
  352. data/vendor/board-maps/yaml/WAVESHARE_RP2040_ONE.yml +1 -0
  353. data/vendor/board-maps/yaml/WAVESHARE_RP2040_PIZERO.yml +47 -0
  354. data/vendor/board-maps/yaml/WAVESHARE_RP2040_ZERO.yml +1 -0
  355. data/vendor/board-maps/yaml/WEACT_STUDIO_ESP32C3.yml +14 -0
  356. data/vendor/board-maps/yaml/WIPY3.yml +1 -0
  357. data/vendor/board-maps/yaml/WT32_SC01_PLUS.yml +7 -0
  358. data/vendor/board-maps/yaml/WiFiduinoV2.yml +1 -0
  359. data/vendor/board-maps/yaml/XIAO_ESP32C3.yml +0 -1
  360. data/vendor/board-maps/yaml/XIAO_ESP32C6.yml +22 -0
  361. data/vendor/board-maps/yaml/unphone9.yml +8 -0
  362. metadata +169 -30
  363. data/examples/led/apa102_breathe.rb +0 -45
  364. data/examples/pulse_io/ir_transmitter.rb +0 -55
  365. data/examples/spi/ssd_through_register.rb +0 -40
  366. data/examples/uart/bit_bang_read.rb +0 -16
  367. data/examples/uart/bit_bang_write.rb +0 -16
  368. data/lib/denko/analog_io/sensor.rb +0 -6
  369. data/lib/denko/sensor/virtual.rb +0 -42
  370. data/src/lib/DenkoIROutESP.cpp +0 -26
  371. data/vendor/board-maps/yaml/STAMP_S3.yml +0 -8
  372. /data/vendor/board-maps/yaml/{BRIDGETEK_IDM2040-7A.yml → BRIDGETEK_IDM2040_43A.yml} +0 -0
  373. /data/vendor/board-maps/yaml/{heltec_wifi_32_lora_V3.yml → HELTEC_WIRELESS_STICK_V3.yml} +0 -0
  374. /data/vendor/board-maps/yaml/{M5Stack_Core_ESP32.yml → M5STACK_CORE.yml} +0 -0
  375. /data/vendor/board-maps/yaml/{M5Stamp_Pico.yml → M5STACK_STAMP_PICO.yml} +0 -0
  376. /data/vendor/board-maps/yaml/{M5Stack-Timer-CAM.yml → M5STACK_TIMER_CAM.yml} +0 -0
@@ -3,103 +3,121 @@ module Denko
3
3
  class RotaryEncoder
4
4
  include Behaviors::MultiPin
5
5
  include Behaviors::Callbacks
6
+ include Behaviors::Lifecycle
7
+
8
+ before_initialize do
9
+ # Allow pins to be given as printed on common parts.
10
+ unless params[:pins][:a]
11
+ params[:pins][:a] = params[:pins][:clk] if params[:pins][:clk]
12
+ params[:pins][:a] = params[:pins][:clock] if params[:pins][:clock]
13
+ end
14
+ unless params[:pins][:b]
15
+ params[:pins][:b] = params[:pins][:dt] if params[:pins][:dt]
16
+ params[:pins][:b] = params[:pins][:data] if params[:pins][:data]
17
+ end
18
+
19
+ # But always refer to them as a and b internally.
20
+ [:clk, :clock, :dt, :data].each { |key| params[:pins].delete(key) }
21
+ end
22
+
23
+ def initialize_pins(params={})
24
+ proxy_pin :a, DigitalIO::Input
25
+ proxy_pin :b, DigitalIO::Input
26
+ end
27
+
28
+ after_initialize do
29
+ a.debounce_time = debounce_time
30
+ b.debounce_time = debounce_time
31
+ a.listen(divider)
32
+ b.listen(divider)
33
+
34
+ # Let initial state settle.
35
+ sleep 0.010
6
36
 
7
- def initialize_pins(options={})
8
- proxy_pin :clock, DigitalIO::Input
9
- proxy_pin :data, DigitalIO::Input
10
- end
11
-
12
- def after_initialize(options={})
13
- super(options)
14
- self.steps_per_revolution = options[:steps_per_revolution] || 30
15
- @reverse = false
16
-
17
- # Avoid repeated memory allocation.
18
- self.state = { steps: 0, angle: 0 }
19
- @reading = { steps: 0, angle: 0, change: 0}
20
-
21
- # DigitalInputs listen with default divider automatically. Override here.
22
- @divider = options[:divider] || 1
23
- clock.listen(@divider)
24
- data.listen(@divider)
25
-
26
37
  observe_pins
27
38
  reset
28
39
  end
29
-
30
- attr_reader :reversed
40
+
41
+ # PiBoard will use GPIO alerts, default to 1 microsecond debounce time.
42
+ def debounce_time
43
+ @debounce_time ||= params[:debounce_time] || 1
44
+ end
45
+
46
+ # Board will default to 1ms digital listeners.
47
+ def divider
48
+ @divider ||= params[:divider] || 1
49
+ end
50
+
51
+ def reversed
52
+ @reversed ||= false || params[:reversed] || params[:reverse]
53
+ end
31
54
 
32
55
  def reverse
33
56
  @reversed = !@reversed
34
57
  end
35
58
 
36
- def steps_per_revolution
37
- (360 / @degrees_per_step).to_i
59
+ def counts_per_revolution
60
+ @counts_per_revolution ||= params[:counts_per_revolution] || params[:cpr] || 60
61
+ end
62
+
63
+ def degrees_per_count
64
+ @degrees_per_count ||= (360 / counts_per_revolution.to_f)
38
65
  end
39
-
40
- def steps_per_revolution=(step_count)
41
- @degrees_per_step = 360.to_f / step_count
66
+
67
+ def state
68
+ state_mutex.synchronize { @state ||= { count: 0, angle: 0 } }
69
+ end
70
+
71
+ def reading
72
+ @reading ||= { count: 0, angle: 0, change: 0 }
42
73
  end
43
-
74
+
44
75
  def angle
45
76
  state[:angle]
46
77
  end
47
78
 
48
- def steps
49
- state[:steps]
79
+ def count
80
+ state[:count]
50
81
  end
51
-
82
+
52
83
  def reset
53
- self.state = {steps: 0, angle: 0}
84
+ self.state = {count: 0, angle: 0}
54
85
  end
55
-
86
+
56
87
  private
57
88
 
58
89
  def observe_pins
59
- #
60
- # This is a quirk of listeners reading in numerical order.
61
- # When observing the pins, attach a callback to the higher numbered pin (trailing),
62
- # then read state of the lower numbered (leading). If not, direction will be reversed.
63
- #
64
- if clock.pin > data.pin
65
- trailing = clock
66
- leading = data
67
- else
68
- trailing = data
69
- leading = clock
90
+ a.add_callback do |a_state|
91
+ self.update((a_state == b.state) ? 1 : -1)
70
92
  end
71
-
72
- trailing.add_callback do |trailing_state|
73
- change = (trailing_state == leading.state) ? 1 : -1
74
- change = -change if trailing == clock
75
- self.update(change)
93
+
94
+ b.add_callback do |b_state|
95
+ self.update((b_state == a.state) ? -1 : 1)
76
96
  end
77
97
  end
78
-
98
+
79
99
  #
80
100
  # Take data (+/- 1 step change) and calculate new state.
81
- # Return a hash with the new :steps and :angle. Pass through raw
101
+ # Return a hash with the new :count and :angle. Pass through raw
82
102
  # value in :change, so callbacks can use any of these.
83
103
  #
84
104
  def pre_callback_filter(step)
85
105
  step = -step if reversed
86
106
 
87
- @reading[:change] = step
88
- @state_mutex.synchronize do
89
- @reading[:steps] = @state[:steps] + step
90
- end
91
- @reading[:angle] = @reading[:steps] * @degrees_per_step % 360
92
-
93
- @reading
107
+ state_mutex.synchronize { reading[:count] = @state[:count] + step }
108
+ reading[:change] = step
109
+ reading[:angle] = reading[:count] * degrees_per_count % 360
110
+
111
+ reading
94
112
  end
95
113
 
96
114
  #
97
115
  # After callbacks, set state to the hash from before, except change.
98
116
  #
99
117
  def update_state(reading)
100
- @state_mutex.synchronize do
101
- @state[:steps] = reading[:steps]
102
- @state[:angle] = reading[:angle]
118
+ state_mutex.synchronize do
119
+ @state[:count] = reading[:count]
120
+ @state[:angle] = reading[:angle]
103
121
  end
104
122
  end
105
123
  end
@@ -5,5 +5,6 @@ module Denko
5
5
  autoload :Button, "#{__dir__}/digital_io/button"
6
6
  autoload :Relay, "#{__dir__}/digital_io/relay"
7
7
  autoload :RotaryEncoder, "#{__dir__}/digital_io/rotary_encoder"
8
+ autoload :CBitBang, "#{__dir__}/digital_io/c_bit_bang"
8
9
  end
9
10
  end
@@ -7,7 +7,8 @@ module Denko
7
7
  module Display
8
8
  class HD44780
9
9
  include Behaviors::MultiPin
10
-
10
+ include Behaviors::Lifecycle
11
+
11
12
  # Commands
12
13
  LCD_CLEARDISPLAY = 0x01
13
14
  LCD_RETURNHOME = 0x02
@@ -17,13 +18,13 @@ module Denko
17
18
  LCD_FUNCTIONSET = 0x20
18
19
  LCD_SETCGRAMADDR = 0x40
19
20
  LCD_SETDDRAMADDR = 0x80
20
-
21
+
21
22
  # Flags for display entry mode
22
23
  LCD_ENTRYRIGHT = 0x00
23
24
  LCD_ENTRYLEFT = 0x02
24
25
  LCD_ENTRYSHIFTINCREMENT = 0x01
25
26
  LCD_ENTRYSHIFTDECREMENT = 0x00
26
-
27
+
27
28
  # Flags for display on/off control
28
29
  LCD_DISPLAYON = 0x04
29
30
  LCD_DISPLAYOFF = 0x00
@@ -31,13 +32,13 @@ module Denko
31
32
  LCD_CURSOROFF = 0x00
32
33
  LCD_BLINKON = 0x01
33
34
  LCD_BLINKOFF = 0x00
34
-
35
+
35
36
  # Flags for display/cursor shift
36
37
  LCD_DISPLAYMOVE = 0x08
37
38
  LCD_CURSORMOVE = 0x00
38
39
  LCD_MOVERIGHT = 0x04
39
40
  LCD_MOVELEFT = 0x00
40
-
41
+
41
42
  # Flags for function set
42
43
  LCD_8BITMODE = 0x10
43
44
  LCD_4BITMODE = 0x00
@@ -46,88 +47,105 @@ module Denko
46
47
  LCD_5x10DOTS = 0x04
47
48
  LCD_5x8DOTS = 0x00
48
49
 
50
+ def bits
51
+ @bits ||= 4
52
+ end
53
+
54
+ # Default to 16x2 display if columns and rows given.
55
+ def columns
56
+ @columns ||= params[:columns] || 16
57
+ end
58
+
59
+ def rows
60
+ @rows ||= params[:rows] || 2
61
+ end
62
+
63
+ # Fuction set byte to set up the LCD. These OR'ed defaults == 0x00.
64
+ def function
65
+ @function ||= LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS
66
+ end
67
+
68
+ # Offset memory address when moving cursor.
69
+ # Row 2 always starts at memory address 0x40.
70
+ # For 4 line LCDs:
71
+ # Row 3 is immediately after row 1, +16 or 20 bytes, depending on columns.
72
+ # Row 4 is immediately after row 2, +16 or 20 bytes, depending on columns.
73
+ def row_offsets
74
+ @row_offsets ||= [0x00, 0x40, 0x00+columns, 0x40+columns]
75
+ end
76
+
77
+ # Start with cursor off and no cursor blink.
78
+ def control
79
+ @control ||= LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF
80
+ end
81
+
82
+ def entry_mode
83
+ @entry_mode ||= LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT
84
+ end
85
+
86
+ attr_writer :columns, :rows, :function, :bits, :row_offsets, :control, :entry_mode
87
+
49
88
  def initialize_pins(options={})
50
89
  # All the required pins.
51
90
  [:rs, :enable, :d4, :d5, :d6, :d7].each do |symbol|
52
91
  proxy_pin(symbol, DigitalIO::Output)
53
92
  end
54
-
93
+
55
94
  # If any of d0-d3 was given, make them all non-optional.
56
95
  lower_bits_optional = (self.pins.keys & [:d0, :d1, :d2, :d3]).empty?
57
96
  [:d0, :d1, :d2, :d3].each do |symbol|
58
97
  proxy_pin(symbol, DigitalIO::Output, optional: lower_bits_optional)
59
98
  end
60
-
99
+
61
100
  # RW pin is mostly hard-wired to ground, but can given.
62
101
  proxy_pin(:rw, DigitalIO::Output, optional: true)
63
102
  end
64
103
 
65
- def after_initialize(options={})
66
- super(options)
67
-
68
- # Default to 16x2 display if no options given.
69
- @columns = options[:columns] || 16
70
- @rows = options[:rows] || 2
71
-
72
- # Create a fuction set byte to set up the LCD. These defaults equal 0x00.
73
- @function = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS
74
-
75
- # Set 8-bit mode in the mask if d0-d3 are present.
104
+ after_initialize do
105
+ # Switch to 8-bit mode if d0-d3 are present.
76
106
  if (d0 && d1 && d2 && d3)
77
- @bits = 8
78
- @function |= LCD_8BITMODE
79
- else
80
- @bits = 4
107
+ self.bits = 8
108
+ self.function |= LCD_8BITMODE
81
109
  end
82
110
 
83
111
  # Set 2 line (row) mode if needed.
84
- @function |= LCD_2LINE if (@rows > 1)
112
+ self.function |= LCD_2LINE if (rows > 1)
85
113
 
86
114
  # Some 1 line displays can use a 5x10 font.
87
- @function |= LCD_5x10DOTS if options[:tall_font] && (@rows == 1)
88
-
89
- # Offset memory address when moving cursor.
90
- # Row 2 always starts at memory address 0x40.
91
- # For 4 line LCDs:
92
- # Row 3 is immediately after row 1, +16 or 20 bytes, depending on columns.
93
- # Row 4 is immediately after row 2, +16 or 20 bytes, depending on columns.
94
- @row_offsets = [0x00, 0x40, 0x00+@columns, 0x40+@columns]
95
-
115
+ self.function |= LCD_5x10DOTS if params[:tall_font] && (rows == 1)
116
+
96
117
  # Wait 50ms for power to be > 2.7V, then pull everything low.
97
118
  micro_delay(50000)
98
119
  enable.low; rs.low; rw.low if rw
99
120
 
100
121
  # Start in 4-bit mode.
101
- if @bits == 4
122
+ if bits == 4
102
123
  # Keep setting 8-bit mode until ready.
103
124
  command(0x03); micro_delay(4500)
104
125
  command(0x03); micro_delay(4500)
105
126
  command(0x03); micro_delay(150)
106
-
127
+
107
128
  # Set 4-bit mode.
108
129
  command(0x02)
109
-
130
+
110
131
  # Or start in 8 bit mode.
111
132
  else
112
- command(LCD_FUNCTIONSET | @function)
133
+ command(LCD_FUNCTIONSET | function)
113
134
  micro_delay(4500)
114
- command(LCD_FUNCTIONSET | @function)
135
+ command(LCD_FUNCTIONSET | function)
115
136
  micro_delay(150)
116
- command(LCD_FUNCTIONSET | @function)
137
+ command(LCD_FUNCTIONSET | function)
117
138
  end
118
-
139
+
119
140
  # Set functions (lines, font size, etc.).
120
- command(LCD_FUNCTIONSET | @function)
141
+ command(LCD_FUNCTIONSET | function)
121
142
 
122
- # Start with cursor off and no cursor blink.
123
- @control = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF
124
143
  display_on
125
144
  clear
126
-
127
- # Set entry mode defaults.
128
- @mode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT
129
- command(LCD_ENTRYMODESET | @mode)
130
-
145
+
146
+ # Write entry mode.
147
+ command(LCD_ENTRYMODESET | entry_mode)
148
+
131
149
  # Need this small delay to avoid garbage data on startup.
132
150
  sleep 0.05
133
151
  end
@@ -144,15 +162,15 @@ module Denko
144
162
 
145
163
  def set_cursor(col, row)
146
164
  # Limit to the highest row, 0 indexed.
147
- row = (@rows - 1) if row > (@rows - 1)
148
- command(LCD_SETDDRAMADDR | (col + @row_offsets[row]))
165
+ row = (rows - 1) if row > (rows - 1)
166
+ command(LCD_SETDDRAMADDR | (col + row_offsets[row]))
149
167
  end
150
168
  alias :move_to :set_cursor
151
-
169
+
152
170
  def print(text)
153
171
  text.each_byte { |b| write b }
154
172
  end
155
-
173
+
156
174
  #
157
175
  # Create a #key_on and #key_off method for each feature in this hash,
158
176
  # using the constant in the value to send a control signal.
@@ -166,52 +184,52 @@ module Denko
166
184
  }
167
185
  CONTROL_TOGGLES.each_key do |key|
168
186
  define_method (key.to_s << "_off").to_sym do
169
- command LCD_DISPLAYCONTROL | (@control &= ~CONTROL_TOGGLES[key])
187
+ command LCD_DISPLAYCONTROL | (self.control &= ~CONTROL_TOGGLES[key])
170
188
  end
171
189
  define_method (key.to_s << "_on") do
172
- command LCD_DISPLAYCONTROL | (@control |= CONTROL_TOGGLES[key])
190
+ command LCD_DISPLAYCONTROL | (self.control |= CONTROL_TOGGLES[key])
173
191
  end
174
192
  end
175
-
193
+
176
194
  def left_to_right
177
- @mode |= LCD_ENTRYLEFT
178
- command(LCD_ENTRYMODESET | @mode)
195
+ self.entry_mode |= LCD_ENTRYLEFT
196
+ command(LCD_ENTRYMODESET | entry_mode)
179
197
  end
180
-
198
+
181
199
  def right_to_left
182
- @mode &= ~LCD_ENTRYLEFT
183
- command(LCD_ENTRYMODESET | @mode)
200
+ self.entry_mode &= ~LCD_ENTRYLEFT
201
+ command(LCD_ENTRYMODESET | entry_mode)
184
202
  end
185
-
203
+
186
204
  def scroll_left
187
205
  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT)
188
206
  end
189
-
207
+
190
208
  def scroll_right
191
209
  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT)
192
210
  end
193
-
211
+
194
212
  def autoscroll_on
195
- @mode |= LCD_ENTRYSHIFTINCREMENT;
196
- command(LCD_ENTRYMODESET | @mode);
213
+ self.entry_mode |= LCD_ENTRYSHIFTINCREMENT;
214
+ command(LCD_ENTRYMODESET | entry_mode);
197
215
  end
198
-
216
+
199
217
  def autoscroll_off
200
- @mode &= ~LCD_ENTRYSHIFTINCREMENT;
201
- command(LCD_ENTRYMODESET | @mode);
218
+ self.entry_mode &= ~LCD_ENTRYSHIFTINCREMENT;
219
+ command(LCD_ENTRYMODESET | entry_mode);
202
220
  end
203
-
221
+
204
222
  # Define custom characters as bitmaps.
205
223
  def create_char(location, bitmap)
206
224
  location &= 0x7
207
225
  command(LCD_SETCGRAMADDR | (location << 3))
208
226
  bitmap.each { |byte| write byte }
209
227
  end
210
-
228
+
211
229
  def command(byte)
212
230
  send(byte, board.low)
213
231
  end
214
-
232
+
215
233
  def write(byte)
216
234
  send(byte, board.high)
217
235
  end
@@ -220,37 +238,62 @@ module Denko
220
238
  # RS pin goes low to send commands, high to send data.
221
239
  rs.write(rs_level) unless rs.state == rs_level
222
240
  rw.low if rw
223
-
241
+
224
242
  # Get the byte as a string of 0s and 1s, LSBFIRST.
225
243
  bits_from_byte = byte.to_s(2).rjust(8, "0").reverse
226
-
244
+
227
245
  # Write bits depending on connection.
228
- @bits == 8 ? write8(bits_from_byte) : write4(bits_from_byte)
246
+ bits == 8 ? write8(bits_from_byte) : write4(bits_from_byte)
229
247
  end
230
-
248
+
231
249
  def write4(bits)
232
- d4.write bits[4].to_i
233
- d5.write bits[5].to_i
234
- d6.write bits[6].to_i
235
- d7.write bits[7].to_i
236
- pulse_enable
237
- d4.write bits[0].to_i
238
- d5.write bits[1].to_i
239
- d6.write bits[2].to_i
240
- d7.write bits[3].to_i
241
- pulse_enable
250
+ if board_is_register?
251
+ board.bit_set(d4.pin, bits[4].to_i)
252
+ board.bit_set(d5.pin, bits[5].to_i)
253
+ board.bit_set(d6.pin, bits[6].to_i)
254
+ d7.write bits[7].to_i
255
+ pulse_enable
256
+ board.bit_set(d4.pin, bits[0].to_i)
257
+ board.bit_set(d5.pin, bits[1].to_i)
258
+ board.bit_set(d6.pin, bits[2].to_i)
259
+ d7.write bits[3].to_i
260
+ pulse_enable
261
+ else
262
+ d4.write bits[4].to_i
263
+ d5.write bits[5].to_i
264
+ d6.write bits[6].to_i
265
+ d7.write bits[7].to_i
266
+ pulse_enable
267
+ d4.write bits[0].to_i
268
+ d5.write bits[1].to_i
269
+ d6.write bits[2].to_i
270
+ d7.write bits[3].to_i
271
+ pulse_enable
272
+ end
242
273
  end
243
274
 
244
275
  def write8(bits)
245
- d0.write bits[0].to_i
246
- d1.write bits[1].to_i
247
- d2.write bits[2].to_i
248
- d3.write bits[3].to_i
249
- d4.write bits[4].to_i
250
- d5.write bits[5].to_i
251
- d6.write bits[6].to_i
252
- d7.write bits[7].to_i
253
- pulse_enable
276
+ if board_has_write_bit?
277
+ board.bit_set(d0.pin, bits[0].to_i)
278
+ board.bit_set(d1.pin, bits[1].to_i)
279
+ board.bit_set(d2.pin, bits[2].to_i)
280
+ board.bit_set(d3.pin, bits[3].to_i)
281
+ board.bit_set(d4.pin, bits[4].to_i)
282
+ board.bit_set(d5.pin, bits[5].to_i)
283
+ board.bit_set(d6.pin, bits[6].to_i)
284
+ d7.write bits[7].to_i
285
+ pulse_enable
286
+ else
287
+ d0.write bits[0].to_i
288
+ d1.write bits[1].to_i
289
+ d2.write bits[2].to_i
290
+ d3.write bits[3].to_i
291
+ d4.write bits[4].to_i
292
+ d5.write bits[5].to_i
293
+ d6.write bits[6].to_i
294
+ d7.write bits[7].to_i
295
+ pulse_enable
296
+ end
254
297
  end
255
298
 
256
299
  def pulse_enable
@@ -0,0 +1,42 @@
1
+ require_relative 'ssd1306'
2
+
3
+ module Denko
4
+ module Display
5
+ class SH1106 < SSD1306
6
+ #
7
+ # Unlike the SSD1306, SH1106 only supports page addressing mode.
8
+ # Can't send all data as sequential pages and let page index auto-increment,
9
+ # like with horizontal addressing on the SSD1306.
10
+ #
11
+ ADDRESSING_MODE_DEFAULT = 0x02
12
+
13
+ def draw(x_min=0, x_max=(@columns-1), y_min=0, y_max=(@rows-1))
14
+ # Convert y-coords to page coords.
15
+ p_min = y_min / 8
16
+ p_max = y_max / 8
17
+
18
+ # Offset x_min by 2, since SH1106 has RAM for 132 columns, but we only use 128, then convert to nibbles.
19
+ x = x_min + 2
20
+ x_lower = (x & 0b00001111)
21
+ x_upper = (x & 0b11110000) >> 4
22
+
23
+ (p_min..p_max).each do |page|
24
+ # Set the page and column to start writing at.
25
+ command [PAGE_START | page, COLUMN_START_LOWER | x_lower, COLUMN_START_UPPER | x_upper]
26
+
27
+ # Get needed bytes for this page only.
28
+ src_start = (@columns * page) + x_min
29
+ src_end = (@columns * page) + x_max
30
+ buffer = canvas.framebuffer[src_start..src_end]
31
+
32
+ # Send all bytes at once if within limit, or split into chunks.
33
+ if buffer.length < (bus.board.i2c_limit - 1)
34
+ data(buffer)
35
+ else
36
+ buffer.each_slice(bus.board.i2c_limit - 1) { |slice| data(slice) }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end