denko 0.13.6 → 0.15.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 (499) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/{build_avr.yml → build_atmega_avr.yml} +19 -18
  3. data/.github/workflows/{build_megaavr.yml → build_atmega_megaavr.yml} +19 -18
  4. data/.github/workflows/{build_sam3x.yml → build_atsam3x.yml} +18 -17
  5. data/.github/workflows/{build_samd.yml → build_atsamd21.yml} +19 -18
  6. data/.github/workflows/build_esp32.yml +19 -18
  7. data/.github/workflows/build_esp32c3.yml +58 -0
  8. data/.github/workflows/build_esp32c6.yml +59 -0
  9. data/.github/workflows/build_esp32h2.yml +58 -0
  10. data/.github/workflows/build_esp32s2.yml +59 -0
  11. data/.github/workflows/build_esp32s3.yml +59 -0
  12. data/.github/workflows/build_esp8266.yml +16 -15
  13. data/.github/workflows/build_ra4m1.yml +17 -16
  14. data/.github/workflows/build_rp2040.yml +19 -17
  15. data/.github/workflows/ruby.yml +20 -20
  16. data/CHANGELOG.md +398 -11
  17. data/DEPS_CLI.md +16 -16
  18. data/DEPS_IDE.md +39 -39
  19. data/MICROCONTROLLERS.md +103 -0
  20. data/PERIPHERALS.md +178 -0
  21. data/README.md +73 -58
  22. data/Rakefile +1 -1
  23. data/build +1 -1
  24. data/denko.gemspec +11 -3
  25. data/lib/denko/analog_io/ads1100.rb +127 -0
  26. data/lib/denko/analog_io/ads1115.rb +8 -25
  27. data/lib/denko/analog_io/ads1118.rb +12 -27
  28. data/lib/denko/analog_io/ads111x.rb +39 -21
  29. data/lib/denko/analog_io/input.rb +29 -55
  30. data/lib/denko/analog_io/input_helper.rb +42 -0
  31. data/lib/denko/analog_io/joystick.rb +87 -0
  32. data/lib/denko/analog_io/output.rb +5 -5
  33. data/lib/denko/analog_io/potentiometer.rb +3 -9
  34. data/lib/denko/analog_io.rb +22 -7
  35. data/lib/denko/behaviors/board_proxy.rb +13 -1
  36. data/lib/denko/behaviors/bus_controller.rb +3 -1
  37. data/lib/denko/behaviors/bus_controller_addressed.rb +1 -0
  38. data/lib/denko/behaviors/bus_peripheral.rb +3 -4
  39. data/lib/denko/behaviors/bus_peripheral_addressed.rb +8 -6
  40. data/lib/denko/behaviors/callbacks.rb +18 -14
  41. data/lib/denko/behaviors/component.rb +12 -14
  42. data/lib/denko/behaviors/input_pin.rb +14 -15
  43. data/lib/denko/behaviors/lifecycle.rb +51 -0
  44. data/lib/denko/behaviors/listener.rb +9 -3
  45. data/lib/denko/behaviors/multi_pin.rb +22 -20
  46. data/lib/denko/behaviors/output_pin.rb +9 -4
  47. data/lib/denko/behaviors/poller.rb +11 -2
  48. data/lib/denko/behaviors/reader.rb +109 -21
  49. data/lib/denko/behaviors/single_pin.rb +3 -4
  50. data/lib/denko/behaviors/state.rb +24 -13
  51. data/lib/denko/behaviors/subcomponents.rb +72 -12
  52. data/lib/denko/behaviors/threaded.rb +19 -8
  53. data/lib/denko/behaviors.rb +36 -22
  54. data/lib/denko/board/core.rb +36 -18
  55. data/lib/denko/board/eeprom.rb +1 -1
  56. data/lib/denko/board/i2c.rb +15 -15
  57. data/lib/denko/board/i2c_bit_bang.rb +53 -0
  58. data/lib/denko/board/infrared.rb +6 -6
  59. data/lib/denko/board/led_array.rb +6 -5
  60. data/lib/denko/board/map.rb +6 -2
  61. data/lib/denko/board/one_wire.rb +3 -3
  62. data/lib/denko/board/spi.rb +35 -30
  63. data/lib/denko/board/spi_bit_bang.rb +14 -15
  64. data/lib/denko/board.rb +41 -36
  65. data/lib/denko/connection/binary_echo.rb +17 -0
  66. data/lib/denko/connection/flow_control.rb +12 -16
  67. data/lib/denko/connection/handshake.rb +2 -0
  68. data/lib/denko/connection/serial.rb +5 -5
  69. data/lib/denko/digital_io/button.rb +4 -0
  70. data/lib/denko/digital_io/c_bit_bang.rb +15 -0
  71. data/lib/denko/digital_io/input.rb +4 -5
  72. data/lib/denko/digital_io/output.rb +19 -10
  73. data/lib/denko/digital_io/pcf8574.rb +114 -0
  74. data/lib/denko/digital_io/relay.rb +2 -0
  75. data/lib/denko/digital_io/rotary_encoder.rb +83 -61
  76. data/lib/denko/digital_io.rb +24 -5
  77. data/lib/denko/display/canvas.rb +350 -157
  78. data/lib/denko/display/font/bmp_5x7.rb +142 -0
  79. data/lib/denko/display/font/bmp_6x8.rb +142 -0
  80. data/lib/denko/display/font/bmp_8x16.rb +141 -0
  81. data/lib/denko/display/font.rb +22 -0
  82. data/lib/denko/display/hd44780.rb +152 -105
  83. data/lib/denko/display/il0373.rb +186 -0
  84. data/lib/denko/display/mono_oled.rb +193 -0
  85. data/lib/denko/display/pcd8544.rb +154 -0
  86. data/lib/denko/display/pixel_common.rb +83 -0
  87. data/lib/denko/display/sh1106.rb +38 -0
  88. data/lib/denko/display/sh1107.rb +10 -0
  89. data/lib/denko/display/spi_common.rb +35 -0
  90. data/lib/denko/display/spi_epaper_common.rb +30 -0
  91. data/lib/denko/display/ssd1306.rb +6 -168
  92. data/lib/denko/display/ssd1680.rb +14 -0
  93. data/lib/denko/display/ssd1681.rb +8 -0
  94. data/lib/denko/display/ssd168x.rb +227 -0
  95. data/lib/denko/display/st7302.rb +207 -0
  96. data/lib/denko/display/st7565.rb +166 -0
  97. data/lib/denko/display.rb +40 -3
  98. data/lib/denko/eeprom/at24c.rb +67 -0
  99. data/lib/denko/eeprom/board.rb +69 -0
  100. data/lib/denko/eeprom.rb +15 -1
  101. data/lib/denko/helpers/engine_check.rb +13 -0
  102. data/lib/denko/helpers/mutex_stub.rb +13 -0
  103. data/lib/denko/helpers.rb +6 -0
  104. data/lib/denko/i2c/bit_bang.rb +32 -0
  105. data/lib/denko/i2c/bus.rb +8 -36
  106. data/lib/denko/i2c/bus_common.rb +50 -0
  107. data/lib/denko/i2c/peripheral.rb +32 -19
  108. data/lib/denko/i2c.rb +17 -2
  109. data/lib/denko/led/apa102.rb +42 -30
  110. data/lib/denko/led/base.rb +13 -2
  111. data/lib/denko/led/rgb.rb +18 -14
  112. data/lib/denko/led/seven_segment.rb +24 -9
  113. data/lib/denko/led/ws2812.rb +10 -7
  114. data/lib/denko/led.rb +17 -8
  115. data/lib/denko/message.rb +5 -0
  116. data/lib/denko/motor/{stepper.rb → a3967.rb} +12 -15
  117. data/lib/denko/motor/l298.rb +11 -10
  118. data/lib/denko/motor/servo.rb +37 -15
  119. data/lib/denko/motor.rb +16 -3
  120. data/lib/denko/one_wire/bus.rb +31 -23
  121. data/lib/denko/one_wire/bus_enumerator.rb +25 -14
  122. data/lib/denko/one_wire/helper.rb +4 -2
  123. data/lib/denko/one_wire/peripheral.rb +0 -3
  124. data/lib/denko/one_wire.rb +18 -5
  125. data/lib/denko/pulse_io/buzzer.rb +11 -9
  126. data/lib/denko/pulse_io/{ir_transmitter.rb → ir_output.rb} +6 -5
  127. data/lib/denko/pulse_io/pwm_output.rb +94 -15
  128. data/lib/denko/pulse_io.rb +17 -3
  129. data/lib/denko/rtc/ds3231.rb +13 -14
  130. data/lib/denko/rtc.rb +14 -1
  131. data/lib/denko/sensor/aht.rb +35 -38
  132. data/lib/denko/sensor/bme280.rb +76 -92
  133. data/lib/denko/sensor/bmp180.rb +46 -48
  134. data/lib/denko/sensor/dht.rb +34 -7
  135. data/lib/denko/sensor/ds18b20.rb +41 -34
  136. data/lib/denko/sensor/hcsr04.rb +7 -5
  137. data/lib/denko/sensor/hdc1080.rb +174 -0
  138. data/lib/denko/sensor/helper.rb +37 -0
  139. data/lib/denko/sensor/htu21d.rb +57 -57
  140. data/lib/denko/sensor/htu31d.rb +36 -36
  141. data/lib/denko/sensor/jsnsr04t.rb +49 -0
  142. data/lib/denko/sensor/qmp6988.rb +34 -48
  143. data/lib/denko/sensor/rcwl9620.rb +3 -5
  144. data/lib/denko/sensor/sht3x.rb +27 -24
  145. data/lib/denko/sensor/sht4x.rb +125 -0
  146. data/lib/denko/sensor/vl53l0x.rb +58 -0
  147. data/lib/denko/sensor.rb +33 -16
  148. data/lib/denko/spi/base_register.rb +25 -21
  149. data/lib/denko/spi/bit_bang.rb +17 -51
  150. data/lib/denko/spi/bus.rb +15 -29
  151. data/lib/denko/spi/bus_common.rb +33 -0
  152. data/lib/denko/spi/input_register.rb +37 -31
  153. data/lib/denko/spi/output_register.rb +33 -39
  154. data/lib/denko/spi/peripheral.rb +81 -14
  155. data/lib/denko/spi.rb +21 -6
  156. data/lib/denko/uart/bit_bang.rb +7 -30
  157. data/lib/denko/uart/common.rb +33 -0
  158. data/lib/denko/uart/hardware.rb +10 -34
  159. data/lib/denko/uart.rb +16 -2
  160. data/lib/denko/version.rb +1 -1
  161. data/lib/denko.rb +23 -16
  162. data/lib/denko_cli/generator.rb +2 -2
  163. data/lib/denko_cli/packages.rb +8 -10
  164. data/lib/denko_cli/targets.rb +13 -13
  165. data/lib/denko_cli/targets.txt +23 -24
  166. data/lib/denko_cli/usage.txt +1 -1
  167. data/src/denko_ethernet.ino +0 -14
  168. data/src/denko_serial.ino +0 -14
  169. data/src/denko_wifi.ino +6 -15
  170. data/src/lib/Denko.cpp +65 -16
  171. data/src/lib/Denko.h +46 -30
  172. data/src/lib/DenkoCoreIO.cpp +57 -102
  173. data/src/lib/DenkoDefines.h +32 -46
  174. data/src/lib/DenkoI2C.cpp +54 -45
  175. data/src/lib/DenkoI2CBB.cpp +238 -0
  176. data/src/lib/DenkoIROut.cpp +12 -7
  177. data/src/lib/DenkoLEDArray.cpp +29 -13
  178. data/src/lib/DenkoSPI.cpp +36 -33
  179. data/src/lib/DenkoSPIBB.cpp +19 -20
  180. data/target.yml +37 -2
  181. data/test/analog_io/input_test.rb +1 -1
  182. data/test/analog_io/potentiometer_test.rb +12 -12
  183. data/test/behaviors/board_proxy_test.rb +1 -1
  184. data/test/behaviors/bus_peripheral_test.rb +4 -4
  185. data/test/behaviors/callbacks_test.rb +28 -10
  186. data/test/behaviors/component_test.rb +32 -14
  187. data/test/behaviors/input_pin_test.rb +14 -9
  188. data/test/behaviors/multi_pin_test.rb +14 -4
  189. data/test/behaviors/output_pin_test.rb +11 -8
  190. data/test/behaviors/poller_test.rb +1 -0
  191. data/test/behaviors/reader_test.rb +3 -2
  192. data/test/behaviors/subcomponents_test.rb +22 -2
  193. data/test/board/board_test.rb +9 -9
  194. data/test/board/core_test.rb +15 -11
  195. data/test/board/i2c_test.rb +39 -33
  196. data/test/board/infrared_test.rb +1 -1
  197. data/test/board/message_test.rb +17 -11
  198. data/test/board/one_wire_test.rb +25 -14
  199. data/test/board/spi_test.rb +45 -29
  200. data/test/digital_io/button_test.rb +15 -0
  201. data/test/digital_io/input_test.rb +2 -2
  202. data/test/digital_io/relay_test.rb +18 -0
  203. data/test/digital_io/rotary_encoder_test.rb +80 -60
  204. data/test/display/canvas_test.rb +306 -0
  205. data/test/display/hd44780_test.rb +34 -7
  206. data/test/eeprom/board_test.rb +45 -0
  207. data/test/helpers/mruby_minitest.rb +95 -0
  208. data/test/helpers/mruby_runner.rb +13 -0
  209. data/test/i2c/bus_test.rb +108 -29
  210. data/test/i2c/peripheral_test.rb +38 -19
  211. data/test/led/apa102_test.rb +24 -0
  212. data/test/led/base_test.rb +2 -1
  213. data/test/led/rgb_test.rb +9 -9
  214. data/test/led/seven_segment_test.rb +7 -7
  215. data/test/motor/{stepper_test.rb → a3967_test.rb} +4 -4
  216. data/test/motor/servo_test.rb +1 -1
  217. data/test/one_wire/bus_enumerator_test.rb +1 -1
  218. data/test/one_wire/bus_test.rb +43 -35
  219. data/test/one_wire/peripheral_test.rb +5 -17
  220. data/test/pulse_io/buzzer_test.rb +7 -4
  221. data/test/pulse_io/{ir_transmitter_test.rb → ir_output_test.rb} +15 -10
  222. data/test/pulse_io/pwm_output_test.rb +74 -18
  223. data/test/rtc/ds3231_test.rb +13 -14
  224. data/test/sensor/dht_test.rb +12 -12
  225. data/test/sensor/ds18b20_test.rb +4 -8
  226. data/test/spi/bitbang_test.rb +27 -0
  227. data/test/spi/bus_test.rb +24 -34
  228. data/test/spi/input_register_test.rb +17 -17
  229. data/test/spi/output_register_test.rb +10 -28
  230. data/test/spi/peripheral_test.rb +73 -0
  231. data/test/test_helper.rb +44 -121
  232. data/vendor/board-maps/BoardMap.h +678 -54
  233. data/vendor/board-maps/lib/header_parser.rb +12 -2
  234. data/vendor/board-maps/yaml/ADAFRUIT_CAMERA_ESP32S3.yml +2 -2
  235. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32C6.yml +15 -0
  236. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32_V2.yml +1 -1
  237. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_RP2040_ADALOGGER.yml +44 -0
  238. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32C3.yml +1 -0
  239. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S2.yml +1 -0
  240. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_N4R2.yml +1 -0
  241. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_NOPSRAM.yml +1 -0
  242. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32_PICO.yml +1 -0
  243. data/vendor/board-maps/yaml/ALFREDO_NOU3.yml +2 -0
  244. data/vendor/board-maps/yaml/AMKEN_BB.yml +48 -0
  245. data/vendor/board-maps/yaml/AMKEN_ES.yml +48 -0
  246. data/vendor/board-maps/yaml/AMKEN_REVELOP.yml +48 -0
  247. data/vendor/board-maps/yaml/AMKEN_REVELOP_PLUS.yml +48 -0
  248. data/vendor/board-maps/yaml/ASL_CAN_X2.yml +41 -0
  249. data/vendor/board-maps/yaml/ATD143_S3.yml +1 -0
  250. data/vendor/board-maps/yaml/BHARATPI_A7672S_4G.yml +14 -0
  251. data/vendor/board-maps/yaml/BHARATPI_LORA.yml +14 -0
  252. data/vendor/board-maps/yaml/BHARATPI_NODE_WIFI.yml +14 -0
  253. data/vendor/board-maps/yaml/BLING.yml +25 -0
  254. data/vendor/board-maps/yaml/BRIDGETEK_IDM2040_7A.yml +48 -0
  255. data/vendor/board-maps/yaml/Bee_Motion_Mini.yml +13 -1
  256. data/vendor/board-maps/yaml/Breadstick_Raspberry.yml +31 -0
  257. data/vendor/board-maps/yaml/CEZERIO_DEV_ESP32C6.yml +14 -0
  258. data/vendor/board-maps/yaml/CEZERIO_MINI_DEV_ESP32C6.yml +12 -0
  259. data/vendor/board-maps/yaml/CIRCUITART_ZERO_S3.yml +71 -0
  260. data/vendor/board-maps/yaml/CODECELLC3.yml +13 -0
  261. data/vendor/board-maps/yaml/CYOBOT_V2_ESP32S3.yml +7 -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/EDGES3D.yml +25 -0
  267. data/vendor/board-maps/yaml/ELECROW_CROWPANEL_7.yml +8 -0
  268. data/vendor/board-maps/yaml/ESP32C2_DEV.yml +12 -0
  269. data/vendor/board-maps/yaml/ESP32C3_DEVKIT_LIPO.yml +14 -0
  270. data/vendor/board-maps/yaml/ESP32C6_DEV.yml +14 -0
  271. data/vendor/board-maps/yaml/ESP32C6_EVB.yml +15 -0
  272. data/vendor/board-maps/yaml/ESP32C6_QWIIC_POCKET.yml +15 -0
  273. data/vendor/board-maps/yaml/ESP32C6_THING_PLUS.yml +14 -0
  274. data/vendor/board-maps/yaml/ESP32H2_DEV.yml +12 -0
  275. data/vendor/board-maps/yaml/ESP32H2_DEVKIT_LIPO.yml +12 -0
  276. data/vendor/board-maps/yaml/ESP32P4_DEV.yml +35 -0
  277. data/vendor/board-maps/yaml/{RMP.yml → ESP32S2_DEVKIT_LIPO.yml} +1 -1
  278. data/vendor/board-maps/yaml/ESP32S2_DEVKIT_LIPO_USB.yml +43 -0
  279. data/vendor/board-maps/yaml/ESP32S3_DEVKIT_LIPO.yml +42 -0
  280. data/vendor/board-maps/yaml/ESP32S3_POWERFEATHER.yml +22 -0
  281. data/vendor/board-maps/yaml/ESP32_2432S028R.yml +14 -0
  282. data/vendor/board-maps/yaml/ESP32_SBC_FABGL.yml +35 -0
  283. data/vendor/board-maps/yaml/EVN_ALPHA.yml +48 -0
  284. data/vendor/board-maps/yaml/FEATHERS3.yml +1 -1
  285. data/vendor/board-maps/yaml/FEATHERS3NEO.yml +32 -0
  286. data/vendor/board-maps/yaml/FRI3D_2024_ESP32S3.yml +43 -0
  287. data/vendor/board-maps/yaml/GEEKBLE_ESP32C3.yml +13 -0
  288. data/vendor/board-maps/yaml/GEEKBLE_NANO_ESP32S3.yml +25 -0
  289. data/vendor/board-maps/yaml/HELTEC_CAPSULE_SENSOR_V3.yml +43 -0
  290. data/vendor/board-maps/yaml/HELTEC_VISION_MASTER_E290.yml +41 -0
  291. data/vendor/board-maps/yaml/HELTEC_VISION_MASTER_E_213.yml +41 -0
  292. data/vendor/board-maps/yaml/HELTEC_VISION_MASTER_T190.yml +41 -0
  293. data/vendor/board-maps/yaml/HELTEC_WIFI_LORA_32_V3.yml +42 -0
  294. data/vendor/board-maps/yaml/HELTEC_WIRELESS_BRIDGE.yml +8 -0
  295. data/vendor/board-maps/yaml/HELTEC_WIRELESS_MINI_SHELL.yml +13 -0
  296. data/vendor/board-maps/yaml/HELTEC_WIRELESS_PAPER.yml +42 -0
  297. data/vendor/board-maps/yaml/HELTEC_WIRELESS_SHELL_V3.yml +42 -0
  298. data/vendor/board-maps/yaml/HELTEC_WIRELESS_STICK_LITE_V3.yml +30 -0
  299. data/vendor/board-maps/yaml/HELTEC_WIRELESS_TRACKER.yml +41 -0
  300. data/vendor/board-maps/yaml/HT_DE01.yml +42 -0
  301. data/vendor/board-maps/yaml/HUIDU_HD_WF2.yml +5 -0
  302. data/vendor/board-maps/yaml/HUIDU_HD_WF4.yml +1 -0
  303. data/vendor/board-maps/yaml/IMBRIOS_LOGSENS_V1P1.yml +1 -1
  304. data/vendor/board-maps/yaml/LILYGO_LORA_CC1101.yml +6 -0
  305. data/vendor/board-maps/yaml/LILYGO_LORA_LR1121.yml +6 -0
  306. data/vendor/board-maps/yaml/LILYGO_LORA_SI4432.yml +6 -0
  307. data/vendor/board-maps/yaml/LILYGO_LORA_SX1262.yml +6 -0
  308. data/vendor/board-maps/yaml/LILYGO_LORA_SX1280.yml +6 -0
  309. data/vendor/board-maps/yaml/LILYGO_T3S3_LR1121.yml +9 -0
  310. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1262.yml +9 -0
  311. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1276.yml +9 -0
  312. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1278.yml +9 -0
  313. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1280.yml +9 -0
  314. data/vendor/board-maps/yaml/LILYGO_T3S3_SX1280PA.yml +8 -0
  315. data/vendor/board-maps/yaml/LILYGO_T_ETH_LITE.yml +21 -0
  316. data/vendor/board-maps/yaml/LOLIN_C3_MINI.yml +0 -1
  317. data/vendor/board-maps/yaml/LOLIN_C3_PICO.yml +13 -0
  318. data/vendor/board-maps/yaml/LOLIN_S3.yml +1 -0
  319. data/vendor/board-maps/yaml/LOLIN_S3_MINI_PRO.yml +40 -0
  320. data/vendor/board-maps/yaml/Lion_Bit_Dev_Board.yml +0 -2
  321. data/vendor/board-maps/yaml/M5STACK_CAPSULE.yml +8 -0
  322. data/vendor/board-maps/yaml/M5STACK_CARDPUTER.yml +8 -0
  323. data/vendor/board-maps/yaml/M5STACK_DIAL.yml +8 -0
  324. data/vendor/board-maps/yaml/M5STACK_DINMETER.yml +8 -0
  325. data/vendor/board-maps/yaml/M5STACK_FIRE.yml +1 -2
  326. data/vendor/board-maps/yaml/M5STACK_NANOC6.yml +17 -0
  327. data/vendor/board-maps/yaml/M5STACK_PAPER.yml +9 -0
  328. data/vendor/board-maps/yaml/M5STACK_POE_CAM.yml +5 -0
  329. data/vendor/board-maps/yaml/M5STACK_STAMP_C3.yml +13 -0
  330. data/vendor/board-maps/yaml/M5STACK_STAMP_S3.yml +4 -0
  331. data/vendor/board-maps/yaml/{M5Stick_C.yml → M5STACK_STICKC.yml} +0 -1
  332. data/vendor/board-maps/yaml/M5STACK_STICKC_PLUS.yml +9 -0
  333. data/vendor/board-maps/yaml/M5STACK_STICKC_PLUS2.yml +9 -0
  334. data/vendor/board-maps/yaml/M5STACK_TOUGH.yml +9 -0
  335. data/vendor/board-maps/yaml/M5STACK_UNIT_CAM.yml +10 -0
  336. data/vendor/board-maps/yaml/M5STACK_UNIT_CAMS3.yml +4 -0
  337. data/vendor/board-maps/yaml/M5Stack_ATOM.yml +0 -1
  338. data/vendor/board-maps/yaml/MAKERGO_C3_SUPERMINI.yml +14 -0
  339. data/vendor/board-maps/yaml/MARBLE_PICO.yml +48 -0
  340. data/vendor/board-maps/yaml/METEHOCA_AKANA_R1.yml +46 -0
  341. data/vendor/board-maps/yaml/NAMINO_BIANCO.yml +13 -0
  342. data/vendor/board-maps/yaml/NEBULAS3.yml +0 -1
  343. data/vendor/board-maps/yaml/NEWSAN_ARCHI.yml +48 -0
  344. data/vendor/board-maps/yaml/NOLOGO_ESP32C3_SUPER_MINI.yml +14 -0
  345. data/vendor/board-maps/yaml/NOLOGO_ESP32S3_PICO.yml +12 -0
  346. data/vendor/board-maps/yaml/OLIMEX_RP2040_PICO30_16MB.yml +48 -0
  347. data/vendor/board-maps/yaml/OLIMEX_RP2040_PICO30_2MB.yml +48 -0
  348. data/vendor/board-maps/yaml/OMGS3.yml +25 -0
  349. data/vendor/board-maps/yaml/OPTA_ANALOG.yml +7 -0
  350. data/vendor/board-maps/yaml/OPTA_DIGITAL.yml +5 -0
  351. data/vendor/board-maps/yaml/PCBCUPID_GLYPHC3.yml +23 -0
  352. data/vendor/board-maps/yaml/PCBCUPID_GLYPHC6.yml +32 -0
  353. data/vendor/board-maps/yaml/PCBCUPID_GLYPHH2.yml +24 -0
  354. data/vendor/board-maps/yaml/PINTRONIX_PINMAX.yml +42 -0
  355. data/vendor/board-maps/yaml/REDPILL_ESP32S3.yml +0 -1
  356. data/vendor/board-maps/yaml/SENSEBOX_MCU_ESP32S2.yml +12 -0
  357. data/vendor/board-maps/yaml/SPARKFUN_ESP32S3_THING_PLUS.yml +13 -0
  358. data/vendor/board-maps/yaml/SPARKFUN_MICROMOD_RP2040.yml +48 -0
  359. data/vendor/board-maps/yaml/SPARKFUN_PRO_MICRO_ESP32C3.yml +24 -0
  360. data/vendor/board-maps/yaml/SPARKLEMOTIONMINI_ESP32.yml +12 -0
  361. data/vendor/board-maps/yaml/SPARKLEMOTIONSTICK_ESP32.yml +11 -0
  362. data/vendor/board-maps/yaml/SPARKLEMOTION_ESP32.yml +12 -0
  363. data/vendor/board-maps/yaml/SQUIXL.yml +7 -0
  364. data/vendor/board-maps/yaml/THINGPULSE_EPULSE_FEATHER.yml +31 -0
  365. data/vendor/board-maps/yaml/THINGPULSE_EPULSE_FEATHER_C6.yml +14 -0
  366. data/vendor/board-maps/yaml/TINYC6.yml +25 -0
  367. data/vendor/board-maps/yaml/T_LORA_PAGER.yml +6 -0
  368. data/vendor/board-maps/yaml/T_WATCH_S3.yml +7 -0
  369. data/vendor/board-maps/yaml/T_WATCH_S3_ULTRA.yml +6 -0
  370. data/vendor/board-maps/yaml/UPESY_EDU_ESP32.yml +28 -0
  371. data/vendor/board-maps/yaml/UPESY_ESP32C3_BASIC.yml +13 -0
  372. data/vendor/board-maps/yaml/UPESY_ESP32C3_MINI.yml +12 -0
  373. data/vendor/board-maps/yaml/UPESY_ESP32S3_BASIC.yml +42 -0
  374. data/vendor/board-maps/yaml/VIRALINK_GATE32_01.yml +6 -0
  375. data/vendor/board-maps/yaml/VIRALINK_GATE32_11.yml +7 -0
  376. data/vendor/board-maps/yaml/WAVESHARE_ESP32S3_TOUCH_LCD_128.yml +8 -0
  377. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_146.yml +41 -0
  378. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_147.yml +41 -0
  379. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_169.yml +38 -0
  380. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_LCD_185.yml +41 -0
  381. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_RELAY_6CH.yml +41 -0
  382. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_143.yml +7 -0
  383. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_164.yml +7 -0
  384. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_18.yml +38 -0
  385. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_191.yml +7 -0
  386. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_AMOLED_241.yml +7 -0
  387. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_146.yml +41 -0
  388. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_169.yml +38 -0
  389. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_185.yml +41 -0
  390. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_185_BOX.yml +41 -0
  391. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_21.yml +41 -0
  392. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_28.yml +41 -0
  393. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_4.yml +36 -0
  394. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_43.yml +38 -0
  395. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_43B.yml +38 -0
  396. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_5.yml +38 -0
  397. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_5B.yml +38 -0
  398. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_TOUCH_LCD_7.yml +38 -0
  399. data/vendor/board-maps/yaml/WAVESHARE_ESP32_S3_ZERO.yml +36 -0
  400. data/vendor/board-maps/yaml/WAVESHARE_RP2040_MATRIX.yml +48 -0
  401. data/vendor/board-maps/yaml/WAVESHARE_RP2040_ONE.yml +1 -0
  402. data/vendor/board-maps/yaml/WAVESHARE_RP2040_PIZERO.yml +47 -0
  403. data/vendor/board-maps/yaml/WAVESHARE_RP2040_ZERO.yml +1 -0
  404. data/vendor/board-maps/yaml/WEACT_STUDIO_ESP32C3.yml +14 -0
  405. data/vendor/board-maps/yaml/WS_ESP32_S3_MATRIX.yml +38 -0
  406. data/vendor/board-maps/yaml/WT32_SC01_PLUS.yml +7 -0
  407. data/vendor/board-maps/yaml/WiFiduinoV2.yml +1 -0
  408. data/vendor/board-maps/yaml/XIAO_ESP32C3.yml +0 -1
  409. data/vendor/board-maps/yaml/XIAO_ESP32C6.yml +22 -0
  410. data/vendor/board-maps/yaml/XIAO_ESP32S3_PLUS.yml +46 -0
  411. data/vendor/board-maps/yaml/YB_ESP32S3_AMP_V2.yml +28 -0
  412. data/vendor/board-maps/yaml/YB_ESP32S3_AMP_V3.yml +28 -0
  413. data/vendor/board-maps/yaml/YB_ESP32S3_ETH.yml +40 -0
  414. data/vendor/board-maps/yaml/mercury.yml +20 -0
  415. data/vendor/board-maps/yaml/unphone9.yml +8 -0
  416. metadata +259 -105
  417. data/.vscode/settings.json +0 -5
  418. data/.vscode/tasks.json +0 -20
  419. data/HARDWARE.md +0 -264
  420. data/benchmarks/i2c_ssd1306_refresh.rb +0 -84
  421. data/examples/advanced/m5_env.rb +0 -48
  422. data/examples/advanced/rotary_encoder_mac_volume.rb +0 -48
  423. data/examples/advanced/ssd1306_time_temp_rh.rb +0 -48
  424. data/examples/analog_io/ads1115.rb +0 -57
  425. data/examples/analog_io/ads1118.rb +0 -73
  426. data/examples/analog_io/dac_loopback.rb +0 -34
  427. data/examples/analog_io/input.rb +0 -55
  428. data/examples/connection/tcp.rb +0 -34
  429. data/examples/digital_io/button.rb +0 -13
  430. data/examples/digital_io/rotary_encoder.rb +0 -26
  431. data/examples/display/hd44780.png +0 -0
  432. data/examples/display/hd44780.rb +0 -39
  433. data/examples/display/ssd1306.rb +0 -40
  434. data/examples/display/ssd1306_s2_pico.rb +0 -29
  435. data/examples/eeprom/built_in.rb +0 -32
  436. data/examples/i2c/search.rb +0 -55
  437. data/examples/led/apa102_bounce.rb +0 -33
  438. data/examples/led/apa102_breathe.rb +0 -45
  439. data/examples/led/builtin_blink.rb +0 -12
  440. data/examples/led/seven_segment_char_echo.rb +0 -15
  441. data/examples/led/ws2812_bounce.rb +0 -32
  442. data/examples/led/ws2812_builtin_blink.rb +0 -21
  443. data/examples/motor/l298.rb +0 -43
  444. data/examples/motor/servo.rb +0 -16
  445. data/examples/motor/stepper.png +0 -0
  446. data/examples/motor/stepper.rb +0 -43
  447. data/examples/pulse_io/buzzer.rb +0 -30
  448. data/examples/pulse_io/ir_transmitter.rb +0 -55
  449. data/examples/rtc/ds3231.rb +0 -48
  450. data/examples/sensor/aht10.rb +0 -19
  451. data/examples/sensor/aht20.rb +0 -19
  452. data/examples/sensor/bme280.rb +0 -38
  453. data/examples/sensor/bmp180.rb +0 -22
  454. data/examples/sensor/dht.rb +0 -24
  455. data/examples/sensor/ds18b20.rb +0 -58
  456. data/examples/sensor/generic_pir.rb +0 -25
  457. data/examples/sensor/hcsr04.rb +0 -14
  458. data/examples/sensor/htu21d.rb +0 -54
  459. data/examples/sensor/htu31d.rb +0 -35
  460. data/examples/sensor/neat_tph_readings.rb +0 -26
  461. data/examples/sensor/qmp6988.rb +0 -53
  462. data/examples/sensor/rcwl9620.rb +0 -15
  463. data/examples/sensor/sht3x.rb +0 -34
  464. data/examples/spi/input_register.rb +0 -50
  465. data/examples/spi/output_register.rb +0 -49
  466. data/examples/spi/ssd_through_register.rb +0 -40
  467. data/examples/spi/two_registers.rb +0 -46
  468. data/examples/uart/bit_bang_read.rb +0 -16
  469. data/examples/uart/bit_bang_write.rb +0 -16
  470. data/examples/uart/board_passthrough.rb +0 -34
  471. data/examples/uart/hardware_loopback.rb +0 -16
  472. data/lib/denko/analog_io/sensor.rb +0 -6
  473. data/lib/denko/eeprom/built_in.rb +0 -69
  474. data/lib/denko/fonts.rb +0 -106
  475. data/lib/denko/sensor/virtual.rb +0 -42
  476. data/src/lib/DenkoIROutESP.cpp +0 -26
  477. data/test/eeprom/built_in_test.rb +0 -61
  478. data/tutorial/01-led/led.fzz +0 -0
  479. data/tutorial/01-led/led.pdf +0 -0
  480. data/tutorial/01-led/led.rb +0 -73
  481. data/tutorial/02-button/button.fzz +0 -0
  482. data/tutorial/02-button/button.pdf +0 -0
  483. data/tutorial/02-button/button.rb +0 -64
  484. data/tutorial/03-potentiometer/potentiometer.fzz +0 -0
  485. data/tutorial/03-potentiometer/potentiometer.pdf +0 -0
  486. data/tutorial/03-potentiometer/potentiometer.rb +0 -62
  487. data/tutorial/04-pwm_led/pwm_led.fzz +0 -0
  488. data/tutorial/04-pwm_led/pwm_led.pdf +0 -0
  489. data/tutorial/04-pwm_led/pwm_led.rb +0 -66
  490. data/tutorial/05-rgb_led/rgb_led.fzz +0 -0
  491. data/tutorial/05-rgb_led/rgb_led.pdf +0 -0
  492. data/tutorial/05-rgb_led/rgb_led.rb +0 -58
  493. data/tutorial/05-rgb_led/rgb_mapping.rb +0 -76
  494. data/vendor/board-maps/yaml/STAMP_S3.yml +0 -8
  495. /data/vendor/board-maps/yaml/{BRIDGETEK_IDM2040-7A.yml → BRIDGETEK_IDM2040_43A.yml} +0 -0
  496. /data/vendor/board-maps/yaml/{heltec_wifi_32_lora_V3.yml → HELTEC_WIRELESS_STICK_V3.yml} +0 -0
  497. /data/vendor/board-maps/yaml/{M5Stack_Core_ESP32.yml → M5STACK_CORE.yml} +0 -0
  498. /data/vendor/board-maps/yaml/{M5Stamp_Pico.yml → M5STACK_STAMP_PICO.yml} +0 -0
  499. /data/vendor/board-maps/yaml/{M5Stack-Timer-CAM.yml → M5STACK_TIMER_CAM.yml} +0 -0
@@ -1,11 +1,26 @@
1
+ # Represent files to be autoloaded in CRuby as an Array.
2
+ # This allows Mruby::Build to parse and preload them instead.
3
+ ANALOG_IO_FILES = [
4
+ [:InputHelper, "input_helper"],
5
+ [:Input, "input"],
6
+ [:Output, "output"],
7
+ [:Potentiometer, "potentiometer"],
8
+ [:Joystick, "joystick"],
9
+ [:ADS111X, "ads111x"],
10
+ [:ADS1100, "ads1100"],
11
+ [:ADS1115, "ads1115"],
12
+ [:ADS1118, "ads1118"],
13
+ ]
14
+
1
15
  module Denko
2
16
  module AnalogIO
3
- autoload :Input, "#{__dir__}/analog_io/input"
4
- autoload :Output, "#{__dir__}/analog_io/output"
5
- autoload :Potentiometer, "#{__dir__}/analog_io/potentiometer"
6
- autoload :Sensor, "#{__dir__}/analog_io/sensor"
7
- autoload :ADS111X, "#{__dir__}/analog_io/ads111x"
8
- autoload :ADS1115, "#{__dir__}/analog_io/ads1115"
9
- autoload :ADS1118, "#{__dir__}/analog_io/ads1118"
17
+ ANALOG_IO_FILES.each do |file|
18
+ file_path = "#{__dir__}/analog_io/#{file[1]}"
19
+ if file[0]
20
+ autoload file[0], file_path
21
+ else
22
+ require file_path
23
+ end
24
+ end
10
25
  end
11
26
  end
@@ -11,11 +11,23 @@ module Denko
11
11
  0
12
12
  end
13
13
 
14
+ def analog_read_high
15
+ nil
16
+ end
17
+
18
+ def analog_write_high
19
+ nil
20
+ end
21
+
22
+ alias :pwm_high :analog_write_high
23
+ alias :dac_high :analog_write_high
24
+ alias :adc_high :analog_read_high
25
+
14
26
  def convert_pin(pin)
15
27
  pin.to_i
16
28
  end
17
29
 
18
- def set_pin_mode(pin, mode, pull=nil); end
30
+ def set_pin_mode(pin, mode, options={}); end
19
31
 
20
32
  def start_read; end
21
33
  end
@@ -1,10 +1,12 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module BusController
4
+ include Component
4
5
  include Subcomponents
5
6
 
6
7
  def mutex
7
- @mutex ||= Mutex.new
8
+ # mruby doesn't have Thread or Mutex, so only stub there.
9
+ @mutex ||= Denko.mruby? ? Denko::MutexStub.new : Mutex.new
8
10
  end
9
11
  end
10
12
  end
@@ -8,6 +8,7 @@ module Denko
8
8
  if addresses.include? component.address
9
9
  raise ArgumentError, "duplicate peripheral address for #{component}"
10
10
  end
11
+
11
12
  super(component)
12
13
  end
13
14
  end
@@ -2,13 +2,12 @@ module Denko
2
2
  module Behaviors
3
3
  module BusPeripheral
4
4
  include Component
5
+ include Lifecycle
5
6
 
6
- attr_reader :address
7
7
  alias :bus :board
8
8
 
9
- def before_initialize(options={})
10
- options[:board] ||= options[:bus]
11
- super(options)
9
+ before_initialize do
10
+ params[:board] = params[:bus] if params[:bus]
12
11
  end
13
12
 
14
13
  def atomically(&block)
@@ -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
@@ -1,30 +1,32 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module Callbacks
4
+ include Lifecycle
4
5
  include State
5
- attr_reader :callback_mutex
6
6
 
7
- def initialize(options={})
8
- @callback_mutex = Mutex.new
9
- remove_callbacks
10
- super(options)
7
+ after_initialize do
8
+ @callback_mutex = Denko.gil? ? Denko::MutexStub.new : Mutex.new
9
+ callbacks
11
10
  end
12
11
 
13
12
  def callbacks
14
- callback_mutex.synchronize { @callbacks }
13
+ @callbacks ||= {}
15
14
  end
16
15
 
17
16
  def add_callback(key=:persistent, &block)
18
- callback_mutex.synchronize do
19
- @callbacks[key] ||= []
20
- @callbacks[key] << block
21
- end
17
+ @callback_mutex.lock
18
+ @callbacks ||= {}
19
+ @callbacks[key] ||= []
20
+ @callbacks[key] << block
21
+ @callback_mutex.unlock
22
+ @callbacks
22
23
  end
23
24
 
24
25
  def remove_callback(key=nil)
25
- callback_mutex.synchronize do
26
- key ? @callbacks.delete(key) : @callbacks = {}
27
- end
26
+ @callback_mutex.lock
27
+ (@callbacks && key) ? @callbacks.delete(key) : @callbacks = {}
28
+ @callback_mutex.unlock
29
+ @callbacks
28
30
  end
29
31
 
30
32
  alias :on_data :add_callback
@@ -45,7 +47,8 @@ module Denko
45
47
  return nil
46
48
  end
47
49
 
48
- callback_mutex.synchronize do
50
+ @callback_mutex.lock
51
+ if @callbacks && !@callbacks.empty?
49
52
  @callbacks.each_value do |array|
50
53
  array.each do |callback|
51
54
  callback.call(filtered_data)
@@ -54,6 +57,7 @@ module Denko
54
57
  # Remove one-time callbacks added by #read.
55
58
  @callbacks.delete(:read)
56
59
  end
60
+ @callback_mutex.unlock
57
61
 
58
62
  update_state(filtered_data)
59
63
  end
@@ -1,17 +1,19 @@
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)
@@ -20,9 +22,9 @@ module Denko
20
22
 
21
23
  protected
22
24
 
23
- def initialize_board(options={})
24
- raise ArgumentError, 'a board is required for a component' unless options[:board]
25
- @board = options[:board]
25
+ def initialize_board
26
+ raise ArgumentError, 'a board is required for a component' unless params[:board]
27
+ @board = params[:board]
26
28
  end
27
29
 
28
30
  def register
@@ -36,13 +38,9 @@ module Denko
36
38
  # Behaviors::Component only requires a board.
37
39
  # Include modules from Setup or override this to use pins.
38
40
  #
39
- def before_initialize(options={}); end
40
41
  def convert_pins(options={}); end
41
42
  def initialize_pins(options={}); end
42
43
  alias :initialize_pin :initialize_pins
43
-
44
- # Override in components. Call super when inheriting or mixing in.
45
- def after_initialize(options={}); end
46
44
  end
47
45
  end
48
46
  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.to_s.start_with? "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
@@ -2,20 +2,26 @@ module Denko
2
2
  module Behaviors
3
3
  module Listener
4
4
  include Callbacks
5
-
5
+
6
6
  attr_reader :divider
7
7
 
8
+ #
9
+ # These delegate to #_listen and #_stop_listener,
10
+ # which should be defined in the including class.
11
+ #
8
12
  def listen(divider=nil, &block)
9
- @divider = divider || @listener
13
+ @divider = divider
10
14
  stop
11
15
  add_callback(:listen, &block) if block_given?
12
16
  _listen(@divider)
17
+ @listening = true
13
18
  end
14
19
 
15
20
  def stop
16
- super if defined?(super)
21
+ begin; super; rescue NoMethodError; end
17
22
  _stop_listener
18
23
  remove_callbacks :listen
24
+ @listening = false
19
25
  end
20
26
  end
21
27
  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,12 @@ 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
+ @pins = {}
28
+ params[:pins].each do |key,pin|
29
+ self.pins[key] = pin ? board.convert_pin(pin) : nil
30
+ end
30
31
  pin_array = pins.values
31
32
  raise ArgumentError, "duplicate pins in: #{pins.inspect}" unless pin_array == pin_array.uniq
32
33
  end
@@ -34,15 +35,20 @@ module Denko
34
35
  #
35
36
  # Proxy a pin to a single-pin component. Set this up in the including
36
37
  # component's #initialize_pins method. Additional options for each proxy
37
- # (eg. pullup/pulldown) can be injected there.
38
- #
38
+ # (eg. mode: :input_pullup) can be injected there.
39
+ #
39
40
  def proxy_pin(name, klass, pin_options={})
40
41
  # Proxied pins are required by default.
41
42
  require_pin(name) unless pin_options[:optional]
42
-
43
+
43
44
  # Make the proxy, passing through options, and store it.
44
45
  if self.pins[name]
45
- proxy = klass.new pin_options.merge(board: self.board, pin: self.pins[name])
46
+ # Allow pin_options to override board or pin number.
47
+ proxy_options = pin_options
48
+ proxy_options[:board] ||= self.board
49
+ proxy_options[:pin] ||= self.pins[name]
50
+
51
+ proxy = klass.new(proxy_options)
46
52
  self.proxies[name] = proxy
47
53
  instance_variable_set("@#{name}", proxy)
48
54
  end
@@ -50,7 +56,7 @@ module Denko
50
56
  # Accessor for the proxy's instance var, or nil, if not given.
51
57
  singleton_class.class_eval { attr_reader name }
52
58
  end
53
-
59
+
54
60
  #
55
61
  # Require a single pin that may or may not be proxied. This is useful for
56
62
  # components using libraries running on the board, where we need to specify
@@ -63,10 +69,6 @@ module Denko
63
69
  def require_pins(*array)
64
70
  [array].flatten.each { |name| require_pin(name) }
65
71
  end
66
-
67
- private
68
-
69
- attr_writer :pins, :proxies
70
72
  end
71
73
  end
72
74
  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
@@ -3,8 +3,10 @@ module Denko
3
3
  module Poller
4
4
  include Reader
5
5
  include Threaded
6
-
6
+
7
7
  def poll_using(method, interval, *args, &block)
8
+ mruby_thread_check
9
+
8
10
  unless [Integer, Float].include? interval.class
9
11
  raise ArgumentError, "wrong interval given to #poll : #{interval.inspect}"
10
12
  end
@@ -13,7 +15,14 @@ module Denko
13
15
  add_callback(:poll, &block) if block_given?
14
16
 
15
17
  threaded_loop do
18
+ # Lock, THEN wait for other normal reads to finish.
19
+ @reader_mutex.lock
20
+ sleep 0.001 while read_busy?
21
+ @reading_normally = true
22
+
16
23
  method.call(*args)
24
+ @reader_mutex.unlock
25
+
17
26
  sleep interval
18
27
  end
19
28
  end
@@ -23,7 +32,7 @@ module Denko
23
32
  end
24
33
 
25
34
  def stop
26
- super if defined?(super)
35
+ begin; super; rescue NoMethodError; end
27
36
  remove_callbacks :poll
28
37
  end
29
38
  end
@@ -1,49 +1,137 @@
1
1
  module Denko
2
2
  module Behaviors
3
3
  module Reader
4
+ include Lifecycle
4
5
  include Callbacks
5
6
 
6
7
  #
7
- # Defalt behavior for #read is to delegate to #_read.
8
- # Define #_read in including classes.
8
+ # DO NOT REPLACE with MutexStub on CRuby!
9
+ # Even with GIL, misordered readings possible with multiple threads.
10
+ #
11
+ after_initialize do
12
+ # mruby doesn't have Thread or Mutex, so only stub there.
13
+ @reader_mutex = Denko.mruby? ? Denko::MutexStub.new : Mutex.new
14
+ end
15
+
16
+ READ_WAIT_TIME = 0.001
17
+ #
18
+ # Override #update to allow "raw reads" or "normal reads":
19
+ #
20
+ # - Normal reads perform normal #update behavior, passing through
21
+ # #pre_callback_filter, running all callbacks and returning filtered_data.
22
+ # Use normal for anything that updates the state of a component, and handle
23
+ # that in in #pre_callback_filter and #update_state.
24
+ # May or may not block calling thread, depending on platform.
25
+ #
26
+ # - Raw reads bypass #pre_callback_filter, callbacks, and return
27
+ # raw data. Use raw for reading things like sensor config/serial etc.
28
+ # DOES NOT take block callbacks from the use. ALWAYS handle the return value.
29
+ # ALWAYS blocks the calling thread.
30
+ #
31
+ def update(data)
32
+ if @reading_raw
33
+ @callback_mutex.lock
34
+ @callbacks[:read_raw].each { |c| c.call(data) }
35
+ @callbacks.delete(:read_raw)
36
+ @callback_mutex.unlock
37
+ @reading_raw = false
38
+ data
39
+ else
40
+ return_value = super(data)
41
+ @reading_normally = false
42
+ return_value
43
+ end
44
+ end
45
+
46
+ #
47
+ # Delegates to #_read. Data passes through #pre_callback_filter, runs all
48
+ # callbacks, and @state is set. BLOCKS calling thread.
9
49
  #
10
50
  def read(*args, **kwargs, &block)
11
51
  read_using(self.method(:_read), *args, **kwargs, &block)
12
52
  end
13
53
 
54
+ #
55
+ # Delegates to #_read. Data passes through #pre_callback_filter, runs all
56
+ # callbacks, and @state is set. DOES NOT BLOCK calling thread.
57
+ #
58
+ def read_nb(*args, **kwargs, &block)
59
+ @reader_mutex.lock
60
+ sleep READ_WAIT_TIME while read_busy?
61
+ @reading_normally = true
62
+ _read(*args, **kwargs, &block)
63
+ @reader_mutex.unlock
64
+ end
65
+
66
+ #
67
+ # NEVER call this directly. Use #read_nb instead.
68
+ #
69
+ # Define #_read in including class to get data which updates the
70
+ # peripheral state. See #read_using comments for more info.
71
+ #
72
+ def _read
73
+ raise NotImplementedError.new("#{self.class.name}#_read is not defined.")
74
+ end
75
+
14
76
  #
15
77
  # Take a proc/lambda/method as the first agrument and use it to read.
16
78
  # Arguments are passed through, allowing dynamic read methods to be defined.
17
79
  # Eg. send commands (in args) to a bus, then wait for data read back.
18
- #
19
- # Block given is added as a one-time callback in the :read key, and
20
- # the curent thread waits until data is received. Returns the result of
21
- # calling #pre_callback_filter with the data.
80
+ #
81
+ # Data is received when the board/bus calls #update on us. If a read was
82
+ # started by this method, the data will pass through #pre_callback_filter,
83
+ # trigger all callbacks, and set @state. Use this for reading the state
84
+ # of peripherals, like digital pin level, enviro sensor reading etc.
22
85
  #
23
86
  def read_using(reader, *args, **kwargs, &block)
24
- add_callback(:read, &block) if block_given?
87
+ # Lock, THEN wait for other normal reads to finish.
88
+ @reader_mutex.lock
89
+ sleep READ_WAIT_TIME while read_busy?
90
+ @reading_normally = true
25
91
 
92
+ # One-time callbacks.
26
93
  return_value = nil
27
- add_callback(:read) do |filtered_data|
28
- return_value = filtered_data
29
- end
30
-
94
+ add_callback(:read) { |filtered_data| return_value = filtered_data }
95
+ add_callback(:read, &block) if block_given?
96
+
31
97
  reader.call(*args, **kwargs)
32
- wait_for_read
98
+ @reader_mutex.unlock
33
99
 
100
+ # Wait for #update to remove the :read callbacks (return_value is set).
101
+ sleep READ_WAIT_TIME while callbacks[:read]
34
102
  return_value
35
103
  end
36
-
37
- def wait_for_read
38
- loop do
39
- break if !callbacks[:read]
40
- sleep 0.001
41
- end
104
+
105
+ #
106
+ # Similar to #read_using, but does not trigger #pre_callback_filter,
107
+ # or run any callbacks except :read_raw. BLOCKS calling thread.
108
+ # Use for things like sensor status, config etc.
109
+ #
110
+ def read_raw(reader, *args, **kwargs)
111
+ # Can't guarantee read order.
112
+ raise StandardError, "#read_raw unavailable while listening" if @listening
113
+
114
+ # Lock, THEN wait for any normal read to finish.
115
+ @reader_mutex.lock
116
+ sleep READ_WAIT_TIME while read_busy?
117
+ @reading_raw = true
118
+
119
+ # Special :read_raw one-time callback.
120
+ return_value = nil
121
+ add_callback(:read_raw) { |bytes| return_value = bytes }
122
+
123
+ # Call reader, but block and keep the lock until :read_raw callback gets run.
124
+ reader.call(*args, **kwargs)
125
+ sleep READ_WAIT_TIME while callbacks[:read_raw]
126
+ @reader_mutex.unlock
127
+
128
+ return_value
42
129
  end
43
130
 
44
- def _read
45
- raise NotImplementedError
46
- .new("#{self.class.name}#_read is not defined.")
131
+ def read_busy?
132
+ # mruby gets stuck waiting somewhere, but doesn't have threads
133
+ # so it can never really be busy.
134
+ !Denko.mruby? && (@reading_normally || @reading_raw)
47
135
  end
48
136
  end
49
137
  end