denko 0.13.6 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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