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,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