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
@@ -1,14 +1,16 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module BusPeripheralAddressed
4
- include Denko::Behaviors::BusPeripheral
4
+ include BusPeripheral
5
+ include Lifecycle
5
6
 
6
- def before_initialize(options={})
7
- # Allow @address override in options, even if peripheral sets a default.
8
- @address = options[:address] if options[:address]
7
+ def address
8
+ @address ||= params[:address]
9
+ end
9
10
 
10
- raise ArgumentError, "missing address for #{self}. Try Bus#search first" unless @address
11
- super(options)
11
+ # Validate address presence after initialization.
12
+ after_initialize do
13
+ raise ArgumentError, "no address set for for #{self}. Try Bus#search first" unless address
12
14
  end
13
15
  end
14
16
  end
@@ -2,20 +2,19 @@ module Denko
2
2
  module Behaviors
3
3
  module Callbacks
4
4
  include State
5
- attr_reader :callback_mutex
6
5
 
7
- def initialize(options={})
8
- @callback_mutex = Mutex.new
9
- remove_callbacks
10
- super(options)
6
+ def callback_mutex
7
+ @callback_mutex ||= Denko.cruby? ? Denko::MutexStub.new : Mutex.new
8
+ @callback_mutex
11
9
  end
12
10
 
13
11
  def callbacks
14
- callback_mutex.synchronize { @callbacks }
12
+ callback_mutex.synchronize { @callbacks ||= {} }
15
13
  end
16
14
 
17
15
  def add_callback(key=:persistent, &block)
18
16
  callback_mutex.synchronize do
17
+ @callbacks ||= {}
19
18
  @callbacks[key] ||= []
20
19
  @callbacks[key] << block
21
20
  end
@@ -23,7 +22,7 @@ module Denko
23
22
 
24
23
  def remove_callback(key=nil)
25
24
  callback_mutex.synchronize do
26
- key ? @callbacks.delete(key) : @callbacks = {}
25
+ (@callbacks && key) ? @callbacks.delete(key) : @callbacks = {}
27
26
  end
28
27
  end
29
28
 
@@ -46,6 +45,9 @@ module Denko
46
45
  end
47
46
 
48
47
  callback_mutex.synchronize do
48
+ break unless @callbacks
49
+ break if @callbacks.empty?
50
+
49
51
  @callbacks.each_value do |array|
50
52
  array.each do |callback|
51
53
  callback.call(filtered_data)
@@ -1,28 +1,34 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module Component
4
+ attr_reader :board, :params
4
5
  include State
5
- attr_reader :board
6
6
 
7
7
  def initialize(options={})
8
- super(options)
9
- before_initialize(options)
10
- initialize_board(options)
11
- convert_pins(options)
12
- initialize_pins(options)
8
+ @params = options
9
+ run_before_initialize_cbs
10
+
11
+ initialize_board
12
+ convert_pins(params)
13
+ initialize_pins(params)
13
14
  register
14
- after_initialize(options)
15
+
16
+ run_after_initialize_cbs
15
17
  end
16
18
 
17
19
  def micro_delay(duration)
18
20
  board.micro_delay(duration)
19
21
  end
20
22
 
23
+ def board_is_register?
24
+ @board_is_register ||= board.class.ancestors.include?(SPI::BaseRegister)
25
+ end
26
+
21
27
  protected
22
28
 
23
- def initialize_board(options={})
24
- raise ArgumentError, 'a board is required for a component' unless options[:board]
25
- @board = options[:board]
29
+ def initialize_board
30
+ raise ArgumentError, 'a board is required for a component' unless params[:board]
31
+ @board = params[:board]
26
32
  end
27
33
 
28
34
  def register
@@ -36,13 +42,9 @@ module Denko
36
42
  # Behaviors::Component only requires a board.
37
43
  # Include modules from Setup or override this to use pins.
38
44
  #
39
- def before_initialize(options={}); end
40
45
  def convert_pins(options={}); end
41
46
  def initialize_pins(options={}); end
42
47
  alias :initialize_pin :initialize_pins
43
-
44
- # Override in components. Call super when inheriting or mixing in.
45
- def after_initialize(options={}); end
46
48
  end
47
49
  end
48
50
  end
@@ -1,26 +1,25 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module InputPin
4
+ include Component
4
5
  include SinglePin
5
-
6
+ include Lifecycle
7
+
8
+ INPUT_MODES = [:input, :input_pulldown, :input_pullup]
9
+
10
+ before_initialize do
11
+ params[:mode] ||= :input
12
+ unless INPUT_MODES.include?(params[:mode])
13
+ raise "invalid input mode: #{params[:mode]} given. Should be one of #{INPUT_MODES.inspect}"
14
+ end
15
+ end
16
+
6
17
  def _stop_listener
7
18
  board.stop_listener(pin)
8
19
  end
9
20
 
10
- protected
11
-
12
- def initialize_pins(options={})
13
- super(options)
14
-
15
- # Assume input direction, and look for pull mode in options.
16
- initial_mode = :input
17
- initial_mode = :input_pullup if options[:pullup]
18
- initial_mode = :input_pulldown if options[:pulldown]
19
-
20
- # If user was explicit about mode, just use that.
21
- initial_mode = options[:mode] if options[:mode]
22
-
23
- self.mode = initial_mode
21
+ def debounce_time=(value)
22
+ board.set_pin_debounce(pin, value)
24
23
  end
25
24
  end
26
25
  end
@@ -0,0 +1,51 @@
1
+ module Denko
2
+ module Behaviors
3
+ module Lifecycle
4
+ #
5
+ # Callback hook DSL for setup work in including classes.
6
+ # include(Component) in final classes to get callbacks methods.
7
+ #
8
+ def self.included(base); base.extend ClassMethods; end
9
+ #
10
+ CALLBACK_METHODS = [:before_initialize, :after_initialize]
11
+
12
+ # Callback methods themselves.
13
+ module ClassMethods
14
+ CALLBACK_METHODS.each do |method_sym|
15
+ civar_sym = "@#{method_sym}_cbs".to_sym
16
+ define_method(method_sym) do |&block|
17
+ if self.instance_variable_defined?(civar_sym)
18
+ blocks = self.instance_variable_get(civar_sym)
19
+ else
20
+ blocks = []
21
+ end
22
+ blocks << block
23
+ self.instance_variable_set(civar_sym, blocks)
24
+ end
25
+ end
26
+ end
27
+
28
+ # Instance method runners.
29
+ CALLBACK_METHODS.each do |method_sym|
30
+ civar_sym = "@#{method_sym}_cbs".to_sym
31
+ runner_sym = "run_#{method_sym}_cbs".to_sym
32
+
33
+ define_method(runner_sym) do
34
+ # Need to check civars in ancestors too.
35
+ klasses = self.class.ancestors
36
+ # If running "after" reverse hierarchy so they run top-down.
37
+ klasses = klasses.reverse if method_sym.match? /after/
38
+
39
+ blocks = []
40
+ klasses.each do |klass|
41
+ if klass.instance_variable_defined?(civar_sym)
42
+ blocks << klass.instance_variable_get(civar_sym)
43
+ end
44
+ end
45
+ blocks = blocks.flatten
46
+ blocks.each { |b| instance_exec(&b) }
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -3,11 +3,17 @@ module Denko
3
3
  module MultiPin
4
4
  #
5
5
  # Model complex components, using multiple pins, by using proxy components
6
- # with one pin each.
6
+ # with one pin each.
7
7
  #
8
8
  include Component
9
+ include Lifecycle
10
+
9
11
  attr_reader :pin, :pins, :proxies
10
-
12
+
13
+ def proxies
14
+ @proxies ||= {}
15
+ end
16
+
11
17
  # Return a hash with the state of each proxy component.
12
18
  def proxy_states
13
19
  hash = {}
@@ -16,17 +22,10 @@ module Denko
16
22
  end
17
23
  hash
18
24
  end
19
-
20
- def before_initialize(options={})
21
- # Get given pins early. Avoids giving them again to require or proxy.
22
- self.pins = options[:pins]
23
- self.proxies = {}
24
- super(options)
25
- end
26
25
 
27
26
  def convert_pins(options={})
28
- super(options)
29
- self.pins.each { |key,pin| self.pins[key] = board.convert_pin(pin) }
27
+ self.pins = {}
28
+ params[:pins].each { |key,pin| self.pins[key] = board.convert_pin(pin) }
30
29
  pin_array = pins.values
31
30
  raise ArgumentError, "duplicate pins in: #{pins.inspect}" unless pin_array == pin_array.uniq
32
31
  end
@@ -34,15 +33,20 @@ module Denko
34
33
  #
35
34
  # Proxy a pin to a single-pin component. Set this up in the including
36
35
  # component's #initialize_pins method. Additional options for each proxy
37
- # (eg. pullup/pulldown) can be injected there.
38
- #
36
+ # (eg. mode: :input_pullup) can be injected there.
37
+ #
39
38
  def proxy_pin(name, klass, pin_options={})
40
39
  # Proxied pins are required by default.
41
40
  require_pin(name) unless pin_options[:optional]
42
-
41
+
43
42
  # Make the proxy, passing through options, and store it.
44
43
  if self.pins[name]
45
- proxy = klass.new pin_options.merge(board: self.board, pin: self.pins[name])
44
+ # Allow pin_options to override board or pin number.
45
+ proxy_options = pin_options
46
+ proxy_options[:board] ||= self.board
47
+ proxy_options[:pin] ||= self.pins[name]
48
+
49
+ proxy = klass.new(proxy_options)
46
50
  self.proxies[name] = proxy
47
51
  instance_variable_set("@#{name}", proxy)
48
52
  end
@@ -50,7 +54,7 @@ module Denko
50
54
  # Accessor for the proxy's instance var, or nil, if not given.
51
55
  singleton_class.class_eval { attr_reader name }
52
56
  end
53
-
57
+
54
58
  #
55
59
  # Require a single pin that may or may not be proxied. This is useful for
56
60
  # components using libraries running on the board, where we need to specify
@@ -63,9 +67,9 @@ module Denko
63
67
  def require_pins(*array)
64
68
  [array].flatten.each { |name| require_pin(name) }
65
69
  end
66
-
70
+
67
71
  private
68
-
72
+
69
73
  attr_writer :pins, :proxies
70
74
  end
71
75
  end
@@ -1,12 +1,17 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module OutputPin
4
+ include Component
4
5
  include SinglePin
5
- protected
6
+ include Lifecycle
6
7
 
7
- def initialize_pins(options={})
8
- super(options)
9
- self.mode = :output
8
+ OUTPUT_MODES = [:output, :output_pwm, :output_dac, :output_open_drain, :output_open_source]
9
+
10
+ before_initialize do
11
+ params[:mode] ||= :output
12
+ unless OUTPUT_MODES.include?(params[:mode])
13
+ raise "invalid input mode: #{params[:mode]} given. Should be one of #{OUTPUT_MODES.inspect}"
14
+ end
10
15
  end
11
16
  end
12
17
  end
@@ -18,6 +18,7 @@ module Denko
18
18
 
19
19
  def initialize_pins(options={})
20
20
  @pin = options[:pin]
21
+ self.mode = params[:mode] if params[:mode]
21
22
  end
22
23
  end
23
24
  end
@@ -1,22 +1,28 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module State
4
- def initialize(options={})
5
- # Component includes State, so no need to call super here.
6
- @state_mutex = Mutex.new
7
- @state = nil
4
+ include Lifecycle
5
+
6
+ # Force state initialization.
7
+ after_initialize do
8
+ state
9
+ end
10
+
11
+ def state_mutex
12
+ @state_mutex ||= Denko.cruby? ? Denko::MutexStub.new : Mutex.new
13
+ @state_mutex
8
14
  end
9
-
15
+
10
16
  def state
11
- @state_mutex.synchronize { @state }
17
+ state_mutex.synchronize { @state }
12
18
  end
13
-
19
+
14
20
  protected
15
21
 
16
22
  def state=(value)
17
- @state_mutex.synchronize { @state = value }
23
+ state_mutex.synchronize { @state = value }
18
24
  end
19
-
25
+
20
26
  def update_state(value)
21
27
  self.state = value if value
22
28
  end
@@ -1,15 +1,32 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module Subcomponents
4
- def components
5
- @components ||= []
4
+ #
5
+ # Main Methods
6
+ #
7
+ def add_component(component)
8
+ add_single_pin(component)
9
+ add_hw_i2c(component)
10
+ add_hw_spi(component)
11
+ components << component
6
12
  end
7
13
 
8
- def single_pin_components
9
- @single_pin_components ||= {}
14
+ def remove_component(component)
15
+ remove_single_pin(component)
16
+ remove_hw_i2c(component)
17
+ remove_hw_spi(component)
18
+ deleted = components.delete(component)
19
+ component.stop if deleted && component.respond_to?(:stop)
10
20
  end
11
21
 
12
- def add_component(component)
22
+ def components
23
+ @components ||= []
24
+ end
25
+
26
+ #
27
+ # Single Pin
28
+ #
29
+ def add_single_pin(component)
13
30
  if component.respond_to?(:pin) && component.pin.class == Integer
14
31
  unless single_pin_components[component.pin]
15
32
  single_pin_components[component.pin] = component
@@ -18,17 +35,60 @@ module Denko
18
35
  "already in use by: #{single_pin_components[component.pin]}"
19
36
  end
20
37
  end
21
-
22
- components << component
23
38
  end
24
39
 
25
- def remove_component(component)
40
+ def remove_single_pin(component)
26
41
  if component.respond_to?(:pin) && component.pin.class == Integer
27
- single_pin_components[component.pin] = nil
42
+ single_pin_components.delete(component.pin)
28
43
  end
29
-
30
- deleted = components.delete(component)
31
- component.stop if deleted && component.respond_to?(:stop)
44
+ end
45
+
46
+ def single_pin_components
47
+ @single_pin_components ||= {}
48
+ end
49
+
50
+ #
51
+ # I2C
52
+ #
53
+ def add_hw_i2c(component)
54
+ if component.respond_to?(:i2c_index)
55
+ unless hw_i2c_comps[component.i2c_index]
56
+ hw_i2c_comps[component.i2c_index] = component
57
+ else
58
+ raise StandardError, "Error adding #{component} to #{self}. I2C dev: #{component.i2c_index} " \
59
+ "already in use by: #{hw_i2c_comps[component.i2c_index]}"
60
+ end
61
+ end
62
+ end
63
+
64
+ def remove_hw_i2c(component)
65
+ hw_i2c_comps.delete(component.i2c_index) if component.respond_to?(:i2c_index)
66
+ end
67
+
68
+ def hw_i2c_comps
69
+ @hw_i2c_comps ||= {}
70
+ end
71
+
72
+ #
73
+ # SPI
74
+ #
75
+ def add_hw_spi(component)
76
+ if component.respond_to?(:spi_index)
77
+ unless hw_spi_comps[component.spi_index]
78
+ hw_spi_comps[component.spi_index] = component
79
+ else
80
+ raise StandardError, "Error adding #{component} to #{self}. SPI dev: #{component.spi_index} " \
81
+ "already in use by: #{hw_spi_comps[component.spi_index]}"
82
+ end
83
+ end
84
+ end
85
+
86
+ def remove_hw_spi(component)
87
+ hw_spi_comps.delete(component.spi_index) if component.respond_to?(:spi_index)
88
+ end
89
+
90
+ def hw_spi_comps
91
+ @hw_spi_comps ||= {}
32
92
  end
33
93
  end
34
94
  end
@@ -1,13 +1,14 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  # Pin and component setup stuff
4
+ autoload :Lifecycle, "#{__dir__}/behaviors/lifecycle"
4
5
  autoload :State, "#{__dir__}/behaviors/state"
5
6
  autoload :Component, "#{__dir__}/behaviors/component"
6
7
  autoload :SinglePin, "#{__dir__}/behaviors/single_pin"
7
8
  autoload :InputPin, "#{__dir__}/behaviors/input_pin"
8
9
  autoload :OutputPin, "#{__dir__}/behaviors/output_pin"
9
10
  autoload :MultiPin, "#{__dir__}/behaviors/multi_pin"
10
-
11
+
11
12
  # Subcomponent stuff
12
13
  autoload :Subcomponents, "#{__dir__}/behaviors/subcomponents"
13
14
  autoload :BusController, "#{__dir__}/behaviors/bus_controller"
@@ -3,29 +3,44 @@ module Denko
3
3
  DIVIDERS = [1, 2, 4, 8, 16, 32, 64, 128]
4
4
 
5
5
  PIN_MODES = {
6
- output: 0b000,
7
- output_pwm: 0b010,
8
- output_dac: 0b100,
9
- input: 0b001,
10
- input_pulldown: 0b011,
11
- input_pullup: 0b101,
12
- input_output: 0b111
6
+ output: 0b0000,
7
+ output_pwm: 0b0010,
8
+ output_dac: 0b0100,
9
+ output_open_drain: 0b0110,
10
+ output_open_source: 0b1000,
11
+ input: 0b0001,
12
+ input_pulldown: 0b0011,
13
+ input_pullup: 0b0101,
13
14
  }
14
15
 
15
16
  # CMD = 0
16
- def set_pin_mode(pin, mode=:input)
17
+ def set_pin_mode(pin, mode=:input, options={})
17
18
  unless PIN_MODES.keys.include? mode
18
19
  raise ArgumentError, "cannot set mode: #{mode}. Should be one of: #{PIN_MODES.keys.inspect}"
19
20
  end
21
+
22
+ # Set frequency and resolution for PWM if given.
23
+ aux = nil
24
+ if (mode == :output_pwm) && options
25
+ aux = [0, 0]
26
+ aux[0] = options[:frequency] if options[:frequency]
27
+ aux[1] = options[:resolution] if options[:resolution]
28
+ aux = pack :uint32, aux, min: 8, max: 8
29
+ end
30
+
20
31
  write Message.encode command: 0,
21
32
  pin: pin,
22
- value: PIN_MODES[mode]
33
+ value: PIN_MODES[mode],
34
+ aux_message: aux
35
+ end
36
+
37
+ def set_pin_debounce(pin, debounce_time)
23
38
  end
24
39
 
25
40
  # CMD = 1
26
41
  def digital_write(pin,value)
27
42
  unless (value == 1) || (value == 0)
28
- raise ArgumentError, "cannot write digital value: #{value}. Should be Integer either 0 or 1"
43
+ raise ArgumentError, "cannot write digital value: #{value}. Should be Integer either 0 or 1"
29
44
  end
30
45
  write Message.encode command: 1, pin: pin, value: value
31
46
  end
@@ -37,12 +52,10 @@ module Denko
37
52
 
38
53
  # CMD = 3
39
54
  def pwm_write(pin,value)
40
- if (value < 0) || (value > pwm_high)
41
- raise ArgumentError, "cannot write PWM value: #{value}. Should be Integer in range 0..#{pwm_high} "
42
- end
55
+ raise ArgumentError, "PWM value cannot be negative" if (value < 0)
43
56
  write Message.encode command: 3, pin: pin, value: value.round
44
57
  end
45
-
58
+
46
59
  # CMD = 4
47
60
  def dac_write(pin,value)
48
61
  if (value < 0) || (value > dac_high)
@@ -60,7 +73,7 @@ module Denko
60
73
  def set_listener(pin, state=:off, **options)
61
74
  # Default to digital listener and validate.
62
75
  options[:mode] ||= :digital
63
- unless (options[:mode] == :digital) || (options[:mode] == :analog)
76
+ unless (options[:mode] == :digital) || (options[:mode] == :analog)
64
77
  raise ArgumentError, "error in mode: #{options[:mode]}. Should be one of: [:digital, :analog]"
65
78
  end
66
79
  mode_byte = (options[:mode] == :digital) ? 0 : 1
@@ -71,7 +84,7 @@ module Denko
71
84
  else
72
85
  options[:divider] ||= 16
73
86
  end
74
-
87
+
75
88
  # Convert divider to exponent and validate.
76
89
  exponent = Math.log2(options[:divider]).round
77
90
  if (exponent < 0) || (exponent > 7)
@@ -79,7 +92,7 @@ module Denko
79
92
  end
80
93
 
81
94
  # Validate state.
82
- unless (state == :on) || (state == :off)
95
+ unless (state == :on) || (state == :off)
83
96
  raise ArgumentError, "error in state: #{options[:state]}. Should be one of: [:on, :off]"
84
97
  end
85
98
  state_byte = (state == :on) ? 1 : 0
@@ -131,7 +144,7 @@ module Denko
131
144
  end
132
145
  write Message.encode(command: 96, value: value)
133
146
  end
134
-
147
+
135
148
  # CMD = 97
136
149
  def set_analog_read_resolution(value)
137
150
  if (value < 0) || (value > 16)
@@ -140,6 +153,11 @@ module Denko
140
153
  write Message.encode(command: 97, value: value)
141
154
  end
142
155
 
156
+ # CMD = 98
157
+ def binary_echo(pin, data=[])
158
+ write Message.encode command: 98, pin: pin, value: data.length, aux_message: pack(:uint8, data)
159
+ end
160
+
143
161
  # CMD = 99
144
162
  def micro_delay(duration)
145
163
  if (duration < 0) || (duration > 0xFFFF)
@@ -14,38 +14,37 @@ module Denko
14
14
  freq = 100000 unless freq
15
15
 
16
16
  unless I2C_FREQUENCIES.include?(freq)
17
- raise ArgumentError, "I2C frequency must be in: #{I2C_FREQUENCIES.keys.inspect}"
17
+ raise ArgumentError, "I2C frequency must be in: #{I2C_FREQUENCIES.keys.inspect}"
18
18
  end
19
19
  I2C_FREQUENCIES[freq]
20
20
  end
21
21
 
22
22
  # CMD = 33
23
- def i2c_search
23
+ def i2c_search(i2c_index)
24
24
  write Message.encode command: 33
25
25
  end
26
26
 
27
27
  # CMD = 34
28
- def i2c_write(address, bytes, frequency=100000, repeated_start=false)
28
+ def i2c_write(i2c_index, address, bytes, frequency=100000, repeated_start=false)
29
29
  bytes = [bytes] unless bytes.class == Array
30
30
  raise ArgumentError, "I2C write must be 1..#{i2c_limit} bytes long" if (bytes.length > i2c_limit || bytes.length < 1)
31
-
31
+
32
32
  # Use top bit of address to select stop condition (1), or repated start (0).
33
33
  send_stop = repeated_start ? 0 : 1
34
- frequency = i2c_convert_frequency(frequency)
35
-
34
+
36
35
  write Message.encode command: 34,
37
- pin: address | (send_stop << 7),
38
- value: bytes.length,
39
- aux_message: pack(:uint8, frequency) + pack(:uint8, bytes)
36
+ aux_message: pack(:uint8, i2c_convert_frequency(frequency)) +
37
+ pack(:uint8, address | (send_stop << 7)) +
38
+ pack(:uint8, bytes.length) +
39
+ pack(:uint8, bytes)
40
40
  end
41
41
 
42
42
  # CMD = 35
43
- def i2c_read(address, register, read_length, frequency=100000, repeated_start=false)
43
+ def i2c_read(i2c_index, address, register, read_length, frequency=100000, repeated_start=false)
44
44
  raise ArgumentError, "I2C read must be 1..#{i2c_limit} bytes long" if (read_length > i2c_limit || read_length < 1)
45
45
 
46
46
  # Use top bit of address to select stop condition (1), or repated start (0).
47
47
  send_stop = repeated_start ? 0 : 1
48
- frequency = i2c_convert_frequency(frequency)
49
48
 
50
49
  # A register address starting register address can be given (up to 4 bytes)
51
50
  if register
@@ -57,9 +56,10 @@ module Denko
57
56
  end
58
57
 
59
58
  write Message.encode command: 35,
60
- pin: address | (send_stop << 7),
61
- value: read_length,
62
- aux_message: pack(:uint8, frequency) + register_packed
59
+ aux_message: pack(:uint8, i2c_convert_frequency(frequency)) +
60
+ pack(:uint8, address | (send_stop << 7)) +
61
+ pack(:uint8, read_length) +
62
+ register_packed
63
63
  end
64
64
  end
65
65
  end