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,7 +3,12 @@ require_relative 'canvas'
3
3
  module Denko
4
4
  module Display
5
5
  class SSD1306
6
- include I2C::Peripheral
6
+ include Behaviors::BusPeripheral
7
+ include Behaviors::Lifecycle
8
+
9
+ # I2C Defaults
10
+ I2C_ADDRESS = 0x3C
11
+ I2C_FREQUENCY = 400_000
7
12
 
8
13
  # Fundamental Commands
9
14
  # Single byte (no need to OR with anything)
@@ -27,9 +32,13 @@ module Denko
27
32
  PAGE_START = 0xB0 # page 0-7
28
33
 
29
34
  # Double byte. Following byte sets value.
30
- ADDRESSING_MODE = 0x20
31
- # Values: 0x00 = horizontal, 0x01 = vertical, 0x02 = page
32
-
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
+
33
42
  # Triple byte. Following 2 bytes sets value. For H/V addressing modes only.
34
43
  COLUMN_ADDRESS_RANGE = 0x21
35
44
  PAGE_ADDRESS_RANGE = 0x22
@@ -61,38 +70,59 @@ module Denko
61
70
  WIDTHS = [64,96,128]
62
71
  HEIGHTS = [16,32,48,64]
63
72
 
64
- def before_initialize(options={})
65
- @i2c_address = 0x3C
66
- @i2c_frequency = 400000
67
- super(options)
73
+ attr_accessor :canvas
74
+
75
+ # Default to a 128x64 display.
76
+ def columns
77
+ @columns ||= params[:columns] || params[:width] || 128
68
78
  end
69
79
 
70
- def after_initialize(options={})
71
- super(options)
80
+ def rows
81
+ @rows ||= params[:rows] || params[:height] || 64
82
+ end
72
83
 
73
- # Default to a 128x64 display.
74
- @columns = options[:columns] || options[:width] || 128
75
- @rows = options[:rows] || options[:height] || 64
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]
76
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
77
106
  # Validate known sizes.
78
- raise ArgumentError, "error in SSD1306 width: #{@columns}. Must be in: #{WIDTHS.inspect}" unless WIDTHS.include?(@columns)
79
- raise ArgumentError, "error in SSD1306 height: #{@rows}. Must be in: #{HEIGHTS.inspect}" unless HEIGHTS.include?(@rows)
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)
80
109
 
81
110
  # Everything except 96x16 size uses clock 0x80.
82
111
  clock = 0x80
83
- clock = 0x60 if (@columns == 96 && @rows == 16)
112
+ clock = 0x60 if (columns == 96 && rows == 16)
84
113
 
85
114
  # 128x32 and 96x16 sizes use com pin config 0x02
86
115
  com_pin_config = 0x12
87
- com_pin_config = 0x02 if (@columns == 96 && @rows == 16) || (@columns == 128 && @rows == 32)
116
+ com_pin_config = 0x02 if (columns == 96 && rows == 16) || (columns == 128 && rows == 32)
88
117
 
89
118
  # Reflecting horizontally and vertically to effectively rotate 180 degrees.
90
- seg_remap = options[:rotate] ? 0x01 : 0x00
91
- com_direction = options[:rotate] ? 0x08 : 0x00
119
+ seg_remap = rotated ? 0x01 : 0x00
120
+ com_direction = rotated ? 0x08 : 0x00
92
121
 
93
- # Startup sequence
122
+ # Startup sequence (SPI doesn't work properly if this isn't sent twice.)
123
+ 2.times do
94
124
  command [
95
- MULTIPLEX_RATIO, @rows - 1,
125
+ MULTIPLEX_RATIO, rows - 1,
96
126
  DISPLAY_OFFSET, 0x00,
97
127
  START_LINE | 0x00,
98
128
  SEGMENT_REMAP | seg_remap,
@@ -104,23 +134,22 @@ module Denko
104
134
  VCOM_DESELECT_LEVEL, 0x20,
105
135
  PRECHARGE_PERIOD, 0xF1, # Charge period for internal charge pump
106
136
  CHARGE_PUMP, 0x14, # Internal charge pump
107
- ADDRESSING_MODE, 0x00, # Horizontal addressing mode so pages auto increment
137
+ ADDRESSING_MODE, self.class::ADDRESSING_MODE_DEFAULT,
108
138
  DISPLAY_ON
109
139
  ]
110
-
140
+ end
141
+
111
142
  # Create a new blank canvas and draw it.
112
- self.canvas = Canvas.new(@columns, @rows)
143
+ self.canvas = Canvas.new(columns, rows)
113
144
  draw
114
145
  end
115
146
 
116
- attr_accessor :canvas
117
-
118
147
  def off
119
- command(DISPLAY_OFF)
148
+ command [DISPLAY_OFF]
120
149
  end
121
150
 
122
151
  def on
123
- command(DISPLAY_ON)
152
+ command [DISPLAY_ON]
124
153
  end
125
154
 
126
155
  def contrast=(value)
@@ -128,24 +157,24 @@ module Denko
128
157
  command [CONTRAST, value]
129
158
  end
130
159
 
131
- def draw(x_min=0, x_max=(@columns-1), y_min=0, y_max=(@rows-1))
160
+ def draw(x_min=0, x_max=(columns-1), y_min=0, y_max=(rows-1))
132
161
  # Convert y-coords to page coords.
133
162
  p_min = y_min / 8
134
163
  p_max = y_max / 8
135
-
164
+
136
165
  # If drawing the whole frame (default), bypass temp buffer to save time.
137
- if (x_min == 0) && (x_max == @columns-1) && (p_min == 0) && (p_max == @rows/8)
166
+ if (x_min == 0) && (x_max == columns-1) && (p_min == 0) && (p_max == rows/8)
138
167
  draw_partial(canvas.framebuffer, x_min, x_max, p_min, p_max)
139
-
140
- # Copy bytes for the given rectangle into a temp buffer.
168
+
169
+ # Copy bytes for the given rectangle into a temp buffer.
141
170
  else
142
171
  temp_buffer = []
143
172
  (p_min..p_max).each do |page|
144
- src_start = (@columns * page) + x_min
145
- src_end = (@columns * page) + x_max
173
+ src_start = (columns * page) + x_min
174
+ src_end = (columns * page) + x_max
146
175
  temp_buffer += canvas.framebuffer[src_start..src_end]
147
176
  end
148
-
177
+
149
178
  # And draw them.
150
179
  draw_partial(temp_buffer, x_min, x_max, p_min, p_max)
151
180
  end
@@ -154,25 +183,56 @@ module Denko
154
183
  def draw_partial(buffer, x_min, x_max, p_min, p_max)
155
184
  # Limit auto-incrementing GRAM address to the rectangle being drawn.
156
185
  command [ COLUMN_ADDRESS_RANGE, x_min, x_max, PAGE_ADDRESS_RANGE, p_min, p_max ]
157
-
186
+
158
187
  # Send all the bytes at once if within board I2C limit.
159
188
  if buffer.length < (bus.board.i2c_limit - 1)
160
189
  data(buffer)
161
-
190
+
162
191
  # Or split into chunks.
163
- else
192
+ else
164
193
  buffer.each_slice(bus.board.i2c_limit - 1) { |slice| data(slice) }
165
194
  end
166
195
  end
167
196
 
168
- # Commands are I2C messages prefixed with 0x00.
169
- def command(bytes)
170
- i2c_write([0x00] + bytes)
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
171
211
  end
172
212
 
173
- # Data are I2C messages prefixed with 0x40.
174
- def data(bytes)
175
- i2c_write([0x40] + bytes)
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
229
+
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
176
236
  end
177
237
  end
178
238
  end
data/lib/denko/display.rb CHANGED
@@ -3,5 +3,6 @@ module Denko
3
3
  autoload :Canvas, "#{__dir__}/display/canvas"
4
4
  autoload :HD44780, "#{__dir__}/display/hd44780"
5
5
  autoload :SSD1306, "#{__dir__}/display/ssd1306"
6
+ autoload :SH1106, "#{__dir__}/display/sh1106"
6
7
  end
7
8
  end
@@ -3,6 +3,7 @@ module Denko
3
3
  class BuiltIn
4
4
  include Behaviors::Component
5
5
  include Behaviors::Reader
6
+ include Behaviors::Lifecycle
6
7
 
7
8
  public :state=
8
9
 
@@ -10,12 +11,14 @@ module Denko
10
11
  254
11
12
  end
12
13
 
13
- def after_initialize(options={})
14
- super(options)
15
- self.state = Array.new(board.eeprom_length, nil)
14
+ after_initialize do
16
15
  load
17
16
  end
18
17
 
18
+ def state
19
+ state_mutex.synchronize { @state ||= Array.new(board.eeprom_length, nil) }
20
+ end
21
+
19
22
  def load
20
23
  state.each_slice(128).with_index do |slice, index|
21
24
  read_using -> { board.eeprom_read(index * 128, slice.length) }
@@ -23,36 +26,36 @@ module Denko
23
26
  end
24
27
 
25
28
  def save
26
- @state_mutex.synchronize do
29
+ state_mutex.synchronize do
27
30
  @state.each_slice(128).with_index do |slice, index|
28
31
  board.eeprom_write(index * 128, slice)
29
32
  end
30
33
  end
31
34
  load
32
35
  end
33
-
36
+
34
37
  #
35
38
  # Specific Array-like methods for convenience.
36
- #
39
+ #
37
40
  def length; board.eeprom_length; end
38
41
  alias :count :length
39
-
42
+
40
43
  def [](index)
41
- @state_mutex.synchronize { @state.send :[], index }
44
+ state_mutex.synchronize { @state.send :[], index }
42
45
  end
43
-
46
+
44
47
  def []=(index, value)
45
- @state_mutex.synchronize { @state.send :[]=, index, value }
48
+ state_mutex.synchronize { @state.send :[]=, index, value }
46
49
  end
47
-
50
+
48
51
  def each(&block)
49
- @state_mutex.synchronize { @state.send :each, &block }
52
+ state_mutex.synchronize { @state.send :each, &block }
50
53
  end
51
-
54
+
52
55
  def each_with_index(&block)
53
- @state_mutex.synchronize { @state.send :each_with_index, &block }
56
+ state_mutex.synchronize { @state.send :each_with_index, &block }
54
57
  end
55
-
58
+
56
59
  def pre_callback_filter(message)
57
60
  address = message.split("-", 2)[0].to_i
58
61
  bytes = message.split("-", 2)[1].split(",").map(&:to_i)
@@ -60,7 +63,7 @@ module Denko
60
63
  end
61
64
 
62
65
  def update_state(hash)
63
- @state_mutex.synchronize do
66
+ state_mutex.synchronize do
64
67
  @state[hash[:address], hash[:data].length] = hash[:data]
65
68
  end
66
69
  end
@@ -0,0 +1,31 @@
1
+ module Denko
2
+ module I2C
3
+ class BitBang
4
+ include Behaviors::MultiPin
5
+ include Behaviors::Lifecycle
6
+ include BusCommon
7
+
8
+ def initialize_pins(options={})
9
+ proxy_pin :scl, DigitalIO::CBitBang
10
+ proxy_pin :sda, DigitalIO::CBitBang
11
+ end
12
+
13
+ after_initialize do
14
+ # Data received for the SDA pin is really for the bus.
15
+ sda.add_callback(:bus_forwarder) { |data| self.update(data) }
16
+ end
17
+
18
+ def _search
19
+ board.i2c_bb_search(pins[:scl], pins[:sda])
20
+ end
21
+
22
+ def write(address, bytes, frequency=nil, repeated_start=false)
23
+ board.i2c_bb_write(pins[:scl], pins[:sda], address, bytes, repeated_start)
24
+ end
25
+
26
+ def _read(address, register, num_bytes, frequency=nil, repeated_start=false)
27
+ board.i2c_bb_read(pins[:scl], pins[:sda], address, register, num_bytes, repeated_start)
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/denko/i2c/bus.rb CHANGED
@@ -1,51 +1,23 @@
1
1
  module Denko
2
2
  module I2C
3
3
  class Bus
4
- include Behaviors::SinglePin
5
- include Behaviors::BusControllerAddressed
6
- include Behaviors::Reader
4
+ include Behaviors::Lifecycle
5
+ include BusCommon
7
6
 
8
- attr_reader :found_devices
9
-
10
- def after_initialize(options={})
11
- super(options)
12
- @found_devices = []
13
- bubble_callbacks
7
+ def i2c_index
8
+ @i2c_index ||= params[:i2c_index] || params[:index] || 0
14
9
  end
15
10
 
16
- def search
17
- addresses = read_using -> { board.i2c_search }
18
- @found_devices = addresses.split(":").map(&:to_i) if addresses
11
+ def _search
12
+ board.i2c_search(i2c_index)
19
13
  end
20
14
 
21
15
  def write(address, bytes, frequency=100000, repeated_start=false)
22
- board.i2c_write(address, bytes, frequency, repeated_start)
16
+ board.i2c_write(i2c_index, address, bytes, frequency, repeated_start)
23
17
  end
24
18
 
25
19
  def _read(address, register, num_bytes, frequency=100000, repeated_start=false)
26
- board.i2c_read(address, register, num_bytes, frequency, repeated_start)
27
- end
28
-
29
- def bubble_callbacks
30
- add_callback(:bus_controller) do |str|
31
- if str && str.match(/\A\d+-/)
32
- address, data = str.split("-", 2)
33
- address = address.to_i
34
-
35
- data = data.split(",").map(&:to_i)
36
- data = nil if data.empty?
37
-
38
- update_component(address, data)
39
- end
40
- end
41
- end
42
-
43
- def update_component(address, data)
44
- components.each do |component|
45
- if component.address == address
46
- component.update(data)
47
- end
48
- end
20
+ board.i2c_read(i2c_index, address, register, num_bytes, frequency, repeated_start)
49
21
  end
50
22
  end
51
23
  end
@@ -0,0 +1,45 @@
1
+ module Denko
2
+ module I2C
3
+ module BusCommon
4
+ include Behaviors::BusControllerAddressed
5
+ include Behaviors::Reader
6
+ include Behaviors::Lifecycle
7
+
8
+ after_initialize do
9
+ bubble_callbacks
10
+ end
11
+
12
+ def found_devices
13
+ @found_devices ||= []
14
+ end
15
+ attr_writer :found_devices
16
+
17
+ def search
18
+ addresses = read_using -> { _search }
19
+ @found_devices = addresses.split(":").map(&:to_i).reject{ |e| e==0 } if addresses
20
+ end
21
+
22
+ def bubble_callbacks
23
+ add_callback(:bus_controller) do |data|
24
+ bytes = nil
25
+
26
+ # Array data from PiBoard.
27
+ if data.class == Array
28
+ address = data.shift
29
+ bytes = data
30
+
31
+ # String data from microcontroller.
32
+ elsif (data.class == String) && (data.match /\A\d+-/)
33
+ address, bytes = data.split("-", 2)
34
+ address = address.to_i
35
+ bytes = bytes.split(",").map(&:to_i)
36
+ bytes = nil if bytes.empty?
37
+ end
38
+
39
+ # Update components.
40
+ components.each { |c| c.update(bytes) if c.address == address } if bytes
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -3,35 +3,44 @@ module Denko
3
3
  module Peripheral
4
4
  include Behaviors::BusPeripheralAddressed
5
5
  include Behaviors::Reader
6
+ include Behaviors::Lifecycle
6
7
 
7
- def before_initialize(options={})
8
- # Allow peripherals to set @i2c_address.
9
- @address ||= @i2c_address
8
+ # Set I2C defaults for including classes by defining these constants in them.
9
+ I2C_ADDRESS = nil
10
+ I2C_FREQUENCY = 100_000
11
+ I2C_REPEATED_START = false
10
12
 
11
- # I2C defaults if peripheral does not set.
12
- @i2c_frequency ||= 100000
13
- @i2c_repeated_start ||= false
13
+ def i2c_default(sym)
14
+ const_sym = "I2C_#{sym}".upcase.to_sym
15
+ self.class.const_get(const_sym) if self.class.const_defined?(const_sym)
16
+ end
14
17
 
15
- # Override defaults if given in options.
16
- @i2c_frequency = options[:i2c_frequency] if options[:i2c_frequency]
17
- @i2c_repeated_start = options[:i2c_repeated_start] if options[:i2c_frequency]
18
+ # Use @address instead of @i2c_address for default BusPeripheral behavior.
19
+ def address
20
+ @address ||= params[:i2c_address] || params[:address] || i2c_default(:address)
21
+ end
22
+ alias :i2c_address :address
18
23
 
19
- # Allow generic :address option to be given as :i2c_address before validation.
20
- # Superclass method will hande override.
21
- options[:address] ||= options[:i2c_address]
24
+ def i2c_frequency
25
+ @i2c_frequency ||= params[:i2c_frequency] || params[:frequency] || i2c_default(:frequency)
26
+ end
22
27
 
23
- super(options)
28
+ def i2c_repeated_start
29
+ return @i2c_repeated_start unless @i2c_repeated_start.nil?
30
+ @i2c_repeated_start = params[:i2c_repeated_start] if @i2c_repeated_start.nil?
31
+ @i2c_repeated_start = params[:repeated_start] if @i2c_repeated_start.nil?
32
+ @i2c_repeated_start = i2c_default(:repeated_start) if @i2c_repeated_start.nil?
33
+ @i2c_repeated_start
24
34
  end
25
-
26
- attr_accessor :i2c_repeated_start, :i2c_frequency
27
- alias :i2c_address :address
35
+
36
+ attr_writer :i2c_frequency, :i2c_repeated_start
28
37
 
29
38
  def i2c_write(bytes=[])
30
- bus.write(address, bytes, i2c_frequency, i2c_repeated_start)
39
+ bus.write(i2c_address, bytes, i2c_frequency, i2c_repeated_start)
31
40
  end
32
41
 
33
- def i2c_read(register, num_bytes)
34
- bus._read(address, register, num_bytes, i2c_frequency, i2c_repeated_start)
42
+ def i2c_read(num_bytes, register: nil)
43
+ bus._read(i2c_address, register, num_bytes, i2c_frequency, i2c_repeated_start)
35
44
  end
36
45
  end
37
46
  end
data/lib/denko/i2c.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  module Denko
2
2
  module I2C
3
+ autoload :BusCommon, "#{__dir__}/i2c/bus_common"
3
4
  autoload :Bus, "#{__dir__}/i2c/bus"
5
+ autoload :BitBang, "#{__dir__}/i2c/bit_bang"
4
6
  autoload :Peripheral, "#{__dir__}/i2c/peripheral"
5
7
  end
6
8
  end
@@ -1,39 +1,52 @@
1
1
  module Denko
2
2
  module LED
3
3
  class APA102
4
- include SPI::Peripheral
4
+ include Behaviors::BusPeripheral
5
+ include Behaviors::Lifecycle
5
6
 
6
- attr_reader :length, :bpp, :brightness
7
+ def pin; nil; end
7
8
 
8
- def before_initialize(options={})
9
- options[:pin] = 255
10
- super(options)
9
+ def length
10
+ @length ||= params[:length] || 1
11
11
  end
12
12
 
13
- def after_initialize(options={})
14
- super(options)
15
-
16
- raise ArgumentError, "no length given for APA102 array" unless options[:length]
17
- @length = options[:length]
13
+ # Start frame is always 32 0-bits (4 bytes).
14
+ def start_frame
15
+ @start_frame ||= Array.new(4) { 0 }
16
+ end
18
17
 
19
- # Start frame is always 32 0-bits (4 bytes).
20
- @start_frame = Array.new(4) { 0 }
18
+ def end_frame
19
+ return @end_frame if @end_frame
21
20
 
22
- # End frame must be at least @length/2 bits long, and 32 bits (4 bytes) minimum.
23
- end_frame_bytes = (@length / 16.0).ceil
21
+ # End frame must be at least length/2 bits long, and 32 bits (4 bytes) minimum.
22
+ end_frame_bytes = (length / 16.0).ceil
24
23
  end_frame_bytes = 4 if end_frame_bytes < 4
25
24
 
26
25
  # Use all 0's for end frame instead of 1's. Prevents extra pixel when using partial strip.
27
26
  @end_frame = Array.new(end_frame_bytes) { 0 }
27
+ end
28
28
 
29
- # This is BYTES per pixel, not bits per pixel.
30
- # 0th byte is per-pixel brightness (PWM applied to all 3 colors).
31
- @bpp = 4
32
- @buffer = Array.new(length * bpp) { 0 }
29
+ # This is BYTES per pixel, not bits per pixel.
30
+ # 0th byte is per-pixel brightness (PWM applied to all 3 colors).
31
+ def bpp
32
+ @bpp ||= 4
33
+ end
34
+
35
+ def buffer
36
+ @buffer ||= Array.new(length * bpp) { 0 }
37
+ end
33
38
 
39
+ attr_writer :buffer
40
+
41
+ before_initialize do
42
+ unless [Denko::SPI::Bus, Denko::SPI::BitBang].include? params[:bus].class
43
+ raise "APA102 must be connected to the output pin of a SPI bus"
44
+ end
45
+ end
46
+
47
+ after_initialize do
34
48
  # Default to max brightness.
35
49
  self.brightness = 31
36
-
37
50
  off
38
51
  end
39
52
 
@@ -47,26 +60,26 @@ module Denko
47
60
  @masked_brightness = 0b11100000 | @brightness
48
61
 
49
62
  # Set brightness for all pixels.
50
- (0..@length-1).each do |index|
51
- @buffer[index*bpp+0] = @masked_brightness
63
+ (0..length-1).each do |index|
64
+ buffer[index*bpp+0] = @masked_brightness
52
65
  end
53
66
  end
54
67
 
55
68
  def []=(index, array)
56
69
  # Per-pixel brightness control, as optional 3rd indexed element of array.
57
70
  if array[3]
58
- @buffer[index*bpp+0] = 0b11100000 | array[3]
71
+ buffer[index*bpp+0] = 0b11100000 | array[3]
59
72
  end
60
-
73
+
61
74
  # APA102 uses BGR ordering.
62
- @buffer[index*bpp+1] = array[2]
63
- @buffer[index*bpp+2] = array[1]
64
- @buffer[index*bpp+3] = array[0]
75
+ buffer[index*bpp+1] = array[2]
76
+ buffer[index*bpp+2] = array[1]
77
+ buffer[index*bpp+3] = array[0]
65
78
  end
66
79
 
67
80
  def all_on
68
81
  self.brightness = 31
69
- @buffer = @buffer.each_slice(bpp).map { [@masked_brightness,255,255,255] }.flatten
82
+ self.buffer = buffer.each_slice(bpp).map { [@masked_brightness,255,255,255] }.flatten
70
83
  show
71
84
  end
72
85
 
@@ -76,11 +89,12 @@ module Denko
76
89
  end
77
90
 
78
91
  def clear
79
- @buffer = @buffer.each_slice(bpp).map { [@masked_brightness,0,0,0] }.flatten
92
+ self.buffer = buffer.each_slice(bpp).map { [@masked_brightness,0,0,0] }.flatten
80
93
  end
81
94
 
82
95
  def show
83
- spi_write(@start_frame + @buffer + @end_frame)
96
+ data = start_frame + buffer + end_frame
97
+ bus.transfer(pin, write: data)
84
98
  end
85
99
  end
86
100
  end
@@ -2,11 +2,17 @@ module Denko
2
2
  module LED
3
3
  class Base < PulseIO::PWMOutput
4
4
  def blink(interval=0.5)
5
- threaded_loop do
5
+ self.blink_interval = interval
6
+ threaded_loop do
6
7
  toggle
7
- sleep interval
8
+ sleep @blink_interval
8
9
  end
9
10
  end
11
+
12
+ def blink_interval=(interval)
13
+ @blink_interval = interval
14
+ end
15
+ attr_reader :blink_interval
10
16
  end
11
17
  end
12
18
  end