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
data/lib/denko/spi/bus.rb CHANGED
@@ -1,43 +1,29 @@
1
1
  module Denko
2
2
  module SPI
3
3
  class Bus
4
- include Behaviors::Component
5
- include Behaviors::BusController
6
- include Behaviors::Reader
4
+ include BusCommon
7
5
 
8
6
  # Board expects all components to have #pin.
9
7
  attr_reader :pin
10
8
 
11
- # Forward some methods directly to the board.
12
- extend Forwardable
13
-
14
- # Forward SPI methods with prefixed names.
15
- def_delegator :board, :spi_transfer, :transfer
16
- def_delegator :board, :spi_listen, :listen
17
- def_delegator :board, :spi_stop, :stop
18
-
19
- # Forward pin control methods with same names for board proxying.
20
- def_delegator :board, :convert_pin
21
- def_delegator :board, :set_pin_mode
22
-
23
- # Add peripheral to self and the board. It gets callbacks directly from the board.
24
- def add_component(component)
25
- # Treat pin 255 as the component having no select pin. Mostly for APA102.
26
- return if component.pin == 255
9
+ def spi_index
10
+ @spi_index ||= params[:spi_index] || params[:index] || 0
11
+ end
27
12
 
28
- pins = components.map { |c| c.pin }
29
- if pins.include? component.pin
30
- raise ArgumentError, "duplicate select pin for #{component}"
31
- end
13
+ # Prepend spi_index to these and forward to the board.
14
+ def transfer(*args, **kwargs)
15
+ args.unshift(spi_index)
16
+ board.spi_transfer(*args, **kwargs)
17
+ end
32
18
 
33
- components << component
34
- board.add_component(component)
19
+ def listen(*args, **kwargs)
20
+ args.unshift(spi_index)
21
+ board.spi_listen(*args, **kwargs)
35
22
  end
36
23
 
37
- # Remove peripheral from self and the board.
38
- def remove_component(component)
39
- components.delete(component)
40
- board.remove_component(component)
24
+ # This is for WS2812 strips on PiBoard.
25
+ def show_ws2812(*args)
26
+ board.show_ws2812(*args, spi_index: spi_index)
41
27
  end
42
28
  end
43
29
  end
@@ -0,0 +1,33 @@
1
+ module Denko
2
+ module SPI
3
+ module BusCommon
4
+ include Behaviors::BusController
5
+ include Behaviors::Reader
6
+
7
+ # Add peripheral to self and the board. It gets callbacks directly from the board.
8
+ def add_component(component)
9
+ # Don't check for select pin uniqueness. Board handles that.
10
+ components << component
11
+ end
12
+
13
+ # Remove peripheral from self and the board.
14
+ def remove_component(component)
15
+ components.delete(component)
16
+ end
17
+
18
+ # Pass through to the real board for converting select/other pins.
19
+ def convert_pin(*args, **kwargs)
20
+ board.convert_pin(*args, **kwargs)
21
+ end
22
+
23
+ def set_pin_mode(*args, **kwargs)
24
+ board.set_pin_mode(*args, **kwargs)
25
+ end
26
+
27
+ # If a component calls #stop, that's just a call to Board#spi_stop giving its select pin.
28
+ def stop(*args, **kwargs)
29
+ board.spi_stop(*args, **kwargs)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,28 +1,30 @@
1
1
  module Denko
2
2
  module SPI
3
3
  class InputRegister < BaseRegister
4
+ include Behaviors::Lifecycle
4
5
 
5
- def before_initialize(options={})
6
- super(options)
7
- #
8
- # Keep track of whether anything is listening or reading a specific pin.
9
- # This might be separate from whether a component is attached or not.
10
- #
11
- @reading_pins = Array.new(@bytes*8) { false }
12
- @listening_pins = Array.new(@bytes*8) { false }
6
+ #
7
+ # Keep track of whether anything is listening or reading a specific pin.
8
+ # This might be separate from whether a component is attached or not.
9
+ #
10
+ def reading_pins
11
+ @reading_pins ||= Array.new(bytes*8) { false }
12
+ end
13
+
14
+ def listening_pins
15
+ @listening_pins ||= Array.new(bytes*8) { false }
13
16
  end
14
17
 
15
- def after_initialize(options={})
16
- super(options)
18
+ after_initialize do
17
19
  enable_proxy
18
20
  end
19
21
 
20
22
  def read
21
- spi_read(@bytes)
23
+ spi_read(bytes)
22
24
  end
23
25
 
24
26
  def listen
25
- spi_listen(@bytes)
27
+ spi_listen(bytes)
26
28
  end
27
29
 
28
30
  def stop
@@ -35,7 +37,7 @@ module Denko
35
37
  def digital_read(pin)
36
38
  # Remember what pin was read and force callbacks to run next update.
37
39
  add_callback(:force_update) { Proc.new{} }
38
- @reading_pins[pin] = true
40
+ reading_pins[pin] = true
39
41
 
40
42
  # Don't actually call #read if already listening.
41
43
  read unless any_listening
@@ -43,16 +45,16 @@ module Denko
43
45
 
44
46
  def digital_listen(pin, divider)
45
47
  listen unless any_listening
46
- @listening_pins[pin] = true
48
+ listening_pins[pin] = true
47
49
  end
48
50
 
49
51
  def stop_listener(pin)
50
- @listening_pins[pin] = false
52
+ listening_pins[pin] = false
51
53
  stop unless any_listening
52
54
  end
53
55
 
54
56
  def any_listening
55
- @listening_pins.each { |p| return true if p }
57
+ listening_pins.each { |p| return true if p }
56
58
  false
57
59
  end
58
60
 
@@ -67,7 +69,7 @@ module Denko
67
69
  components.each do |part|
68
70
  update_component(part, pin, value) if pin == part.pin
69
71
  end
70
- @reading_pins[pin] = false
72
+ reading_pins[pin] = false
71
73
  end
72
74
  end
73
75
  end
@@ -77,14 +79,15 @@ module Denko
77
79
  # within the main mutex lock.
78
80
  #
79
81
  def update(message)
80
- bits = byte_array_to_bit_array(message.split(","))
81
-
82
- @callback_mutex.synchronize {
83
- #
84
- # The Arduino code does not de-duplicate repeated state.
85
- # Do it here, but if a :force_update callback exists, run anyway.
86
- #
87
- if (bits != @state)|| @callbacks[:force_update]
82
+ # Since overriding update, make sure this is a byte array first.
83
+ byte_array = ensure_byte_array(message)
84
+
85
+ bits = byte_array_to_bit_array(byte_array)
86
+
87
+ @callback_mutex.lock
88
+ if @callbacks && !@callbacks.empty?
89
+ # Arduino doesn't de-duplicate state. Do it, but honor :force_update callbacks.
90
+ if (bits != state) || @callbacks[:force_update]
88
91
  @callbacks.each_value do |array|
89
92
  array.each { |callback| callback.call(bits) }
90
93
  end
@@ -93,16 +96,19 @@ module Denko
93
96
  # Remove both :read and :force update while inside the lock.
94
97
  @callbacks.delete(:read)
95
98
  @callbacks.delete(:force_update)
96
- }
97
- @state = bits
99
+ end
100
+ @callback_mutex.unlock
101
+
102
+ self.state = bits
98
103
  end
99
104
 
100
105
  def update_component(part, pin, value)
101
106
  # Update if component is listening and value has changed.
102
- if @listening_pins[pin] && (value != @state[pin])
107
+ if listening_pins[pin] && (value != state[pin])
103
108
  part.update(value)
104
109
  # Also update if the component forced a read.
105
- elsif @reading_pins[pin] && @callbacks[:force_update]
110
+ # Always called inside @callback_mutex, so @callbacks, not callbacks
111
+ elsif reading_pins[pin] && @callbacks[:force_update]
106
112
  part.update(value)
107
113
  end
108
114
  end
@@ -114,14 +120,14 @@ module Denko
114
120
  def byte_array_to_bit_array(byte_array)
115
121
  #
116
122
  # For each array element (1 byte):
117
- # decimal number as string -> integer -> padded string of binary digits
123
+ # decimal number as string -> integer -> padded string of binary digits
118
124
  # -> reverse digits from reading order to array indexing order
119
125
  # -> join digits of all bytes into one string
120
126
  #
121
127
  binary_string = byte_array.map do |byte|
122
128
  byte.to_i.to_s(2).rjust(8, "0").reverse
123
129
  end.join
124
-
130
+
125
131
  # Split the digits out of the string into individual integers.
126
132
  binary_string.split("").map { |bit| bit.to_i }
127
133
  end
@@ -1,66 +1,60 @@
1
1
  module Denko
2
2
  module SPI
3
3
  class OutputRegister < BaseRegister
4
+ include Behaviors::Lifecycle
4
5
 
5
- def before_initialize(options={})
6
- super(options)
7
- #
8
- # When used as a board proxy, only write sate if @write_delay seconds
9
- # have passed since this object last got input. Better for things like SSDs
10
- # where many bits change in sequence, but not at exactly the same time.
11
- #
12
- @buffer_writes = true
13
- @buffer_writes = false if options[:buffer_writes] == false
14
- @write_delay = options[:write_delay] || 0.001
15
- end
16
-
17
- def after_initialize(options={})
6
+ after_initialize do
7
+ state
18
8
  write
19
9
  end
20
10
 
21
11
  #
22
- # Overrides Peripheral#write to always write @state.
12
+ # Overrides Peripheral#write to always write state.
23
13
  # Convert bit state to array of 0-255 integers (bytes) first.
24
14
  #
25
15
  def write
26
16
  bytes = []
27
- @state.each_slice(8) do |slice|
28
- # Convert nils in the slice to zero.
29
- zeroed = slice.map { |bit| bit.to_i }
30
-
31
- # Each slice is 8 bits of a byte, with the lowest on the left.
32
- # Reverse to reading order (lowest right) then join into string, and convert to integer.
33
- byte = zeroed.reverse.join.to_i(2)
34
-
35
- # Pack bytes in reverse order.
36
- bytes.unshift byte
17
+ @state_mutex.lock
18
+ if @state != @previous_state
19
+ @state.each_slice(8) do |slice|
20
+ # Convert nils in the slice to zero.
21
+ zeroed = slice.map { |bit| bit.to_i }
22
+
23
+ # Each slice is 8 bits of a byte, with the lowest on the left.
24
+ # Reverse to reading order (lowest right) then join into string, and convert to integer.
25
+ byte = zeroed.reverse.join.to_i(2)
26
+
27
+ # Pack bytes in reverse order.
28
+ bytes.unshift byte
29
+ end
30
+ spi_write(bytes)
31
+ @previous_state = @state.dup
37
32
  end
38
- spi_write(bytes)
33
+ @state_mutex.unlock
34
+ @state
39
35
  end
40
36
 
41
37
  #
42
38
  # BoardProxy interface
43
39
  #
44
40
  def digital_write(pin, value)
45
- state[pin] = value # Might not be atomic?
46
- @buffer_writes ? write_buffered(state) : write
41
+ bit_set(pin, value)
42
+ write
43
+ end
44
+
45
+ def bit_set(pin, value)
46
+ @state_mutex.lock
47
+ @state[pin] = value
48
+ @state_mutex.unlock
49
+ value
47
50
  end
48
-
51
+
49
52
  def digital_read(pin)
50
53
  state[pin]
51
54
  end
52
55
 
53
- #
54
- # If acting as board, do writes in a separate thread and with small delay.
55
- # Lets us catch multiple changed bits, like when hosting an SSD.
56
- #
57
- include Behaviors::Threaded
58
- def write_buffered(old_state)
59
- threaded do
60
- sleep @write_delay
61
- # Keep delaying if state has changed.
62
- write if (old_state == state)
63
- end
56
+ def pin_is_pwm?(pin)
57
+ false
64
58
  end
65
59
  end
66
60
  end
@@ -1,42 +1,109 @@
1
1
  module Denko
2
2
  module SPI
3
- module Peripheral
4
- include Behaviors::OutputPin
3
+ class ChipSelect
4
+ include Behaviors::SinglePin
5
5
  include Behaviors::Callbacks
6
+ include Behaviors::Lifecycle
7
+
8
+ before_initialize do
9
+ # It actually functions as an output.
10
+ params[:mode] = :output
11
+
12
+ # But we can't claim it on Linux (the SPI hardware handles it), so don't.
13
+ if !Denko.mruby? && Object.const_defined?("Denko::PiBoard")
14
+ board = params[:board]
15
+ if board.class.ancestors.include?(Denko::PiBoard)
16
+ params[:mode] = nil
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module Peripheral
23
+ include Behaviors::MultiPin
6
24
  include Behaviors::BusPeripheral
25
+ include Behaviors::Callbacks
26
+ include Behaviors::Lifecycle
27
+
28
+ # We have the SPI bus set as our board, but the select pin,
29
+ # and any other pins, need to attach to the underlying board.
30
+ def proxy_pin(*args, **kwargs)
31
+ kwargs[:board] = bus.board
32
+ super(*args, **kwargs)
33
+ end
7
34
 
8
- attr_reader :spi_frequency, :spi_mode, :spi_bit_order
35
+ # If given just one value in pin:, treat that as the select pin.
36
+ before_initialize do
37
+ if (params[:pin].class != Hash) && (!params[:pins])
38
+ params[:pins] = { select: params[:pin] }
39
+ params[:pin] = nil
40
+ end
41
+ end
9
42
 
10
- def before_initialize(options={})
11
- super(options)
43
+ # Chip select pin is always treated as a subcomponent
44
+ def initialize_pins(params={})
45
+ super(params)
46
+ proxy_pin :select, ChipSelect, mode: :output
47
+ end
12
48
 
13
- # Save SPI settings.
14
- @spi_frequency = options[:spi_frequency]
15
- @spi_mode = options[:spi_mode]
16
- @spi_bit_order = options[:spi_bit_order]
49
+ # SelectPin is a separate component that receives updates from Board.
50
+ # Forward them to the Peripheral
51
+ after_initialize do
52
+ select.add_callback(:peripheral_forwarder) { |data| self.update(data) }
17
53
  end
18
54
 
55
+ def ensure_byte_array(message)
56
+ if message.class == Array
57
+ # Byte array coming from PiBoard.
58
+ return message
59
+ else
60
+ # Split up comma delimited bytes coming from a microcontroller.
61
+ return message.split(",").map { |b| b.to_i }
62
+ end
63
+ end
64
+
65
+ def update(message)
66
+ super(ensure_byte_array(message))
67
+ end
68
+
69
+ #
70
+ # SPI Properties
71
+ #
72
+ def spi_frequency
73
+ @spi_frequency ||= params[:spi_frequency] || 1_000_000
74
+ end
75
+
76
+ def spi_mode
77
+ @spi_mode ||= params[:spi_mode] || 0
78
+ end
79
+
80
+ def spi_bit_order
81
+ @spi_bit_order ||= params[:spi_bit_order] || :msbfirst
82
+ end
83
+
84
+ attr_writer :spi_frequency, :spi_mode, :spi_bit_order
85
+
19
86
  #
20
87
  # Delegate methods to the bus.
21
88
  #
22
89
  def spi_transfer(write: [], read: 0)
23
- bus.transfer(pin, write: write, read: read, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
90
+ bus.transfer(select.pin, write: write, read: read, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
24
91
  end
25
92
 
26
93
  def spi_write(byte_array)
27
- bus.transfer(pin, write: byte_array, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
94
+ bus.transfer(select.pin, write: byte_array, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
28
95
  end
29
96
 
30
97
  def spi_read(num_bytes)
31
- bus.transfer(pin, read: num_bytes, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
98
+ bus.transfer(select.pin, read: num_bytes, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
32
99
  end
33
100
 
34
101
  def spi_listen(num_bytes)
35
- bus.listen(pin, read: num_bytes, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
102
+ bus.listen(select.pin, read: num_bytes, frequency: spi_frequency, mode: spi_mode, bit_order: spi_bit_order)
36
103
  end
37
104
 
38
105
  def spi_stop
39
- bus.stop(pin)
106
+ bus.stop(select.pin)
40
107
  end
41
108
  end
42
109
  end
data/lib/denko/spi.rb CHANGED
@@ -1,10 +1,25 @@
1
+ # Represent files to be autoloaded in CRuby as an Array.
2
+ # This allows Mruby::Build to parse and preload them instead.
3
+ SPI_FILES = [
4
+ [:BusCommon, "bus_common"],
5
+ [:Bus, "bus"],
6
+ [:BitBang, "bit_bang"],
7
+ [:ChipSelect, "peripheral"],
8
+ [:Peripheral, "peripheral"],
9
+ [:BaseRegister, "base_register"],
10
+ [:InputRegister, "input_register"],
11
+ [:OutputRegister, "output_register"],
12
+ ]
13
+
1
14
  module Denko
2
15
  module SPI
3
- autoload :Bus, "#{__dir__}/spi/bus"
4
- autoload :BitBang, "#{__dir__}/spi/bit_bang"
5
- autoload :Peripheral, "#{__dir__}/spi/peripheral"
6
- autoload :BaseRegister, "#{__dir__}/spi/base_register"
7
- autoload :InputRegister, "#{__dir__}/spi/input_register"
8
- autoload :OutputRegister, "#{__dir__}/spi/output_register"
16
+ SPI_FILES.each do |file|
17
+ file_path = "#{__dir__}/spi/#{file[1]}"
18
+ if file[0]
19
+ autoload file[0], file_path
20
+ else
21
+ require file_path
22
+ end
23
+ end
9
24
  end
10
25
  end
@@ -3,12 +3,15 @@ module Denko
3
3
  class UARTRxPin
4
4
  include Behaviors::InputPin
5
5
  include Behaviors::Callbacks
6
+ include Behaviors::Lifecycle
6
7
  end
7
8
 
8
9
  class BitBang
9
10
  include Behaviors::MultiPin
10
11
  include Behaviors::Callbacks
11
-
12
+ include Behaviors::Lifecycle
13
+ include Common
14
+
12
15
  attr_reader :baud
13
16
 
14
17
  def initialize_pins(options={})
@@ -16,36 +19,10 @@ module Denko
16
19
  proxy_pin(:rx, UARTRxPin)
17
20
  end
18
21
 
19
- def after_initialize(options={})
22
+ after_initialize do
20
23
  hook_rx_callback
21
24
  initialize_buffer
22
- start(options[:baud] || 9600)
23
- end
24
-
25
- def initialize_buffer
26
- @buffer = ""
27
- @buffer_mutex = Mutex.new
28
- self.add_callback(:buffer) do |data|
29
- @buffer_mutex.synchronize do
30
- @buffer = "#{@buffer}#{data}"
31
- end
32
- end
33
- end
34
-
35
- def gets
36
- @buffer_mutex.synchronize do
37
- newline = @buffer.index("\n")
38
- return nil unless newline
39
- line = @buffer[0..newline-1]
40
- @buffer = @buffer[newline+1..-1]
41
- return line
42
- end
43
- end
44
-
45
- def flush
46
- @buffer_mutex.synchronize do
47
- @buffer = ""
48
- end
25
+ start(params[:baud] || 9600)
49
26
  end
50
27
 
51
28
  def start(baud)
@@ -62,7 +39,7 @@ module Denko
62
39
  end
63
40
 
64
41
  def hook_rx_callback
65
- rx.add_callback {|data| self.update(data)}
42
+ rx.add_callback { |data| self.update(data) }
66
43
  end
67
44
  end
68
45
  end
@@ -0,0 +1,33 @@
1
+ module Denko
2
+ module UART
3
+ module Common
4
+ def initialize_buffer
5
+ @buffer = String.new
6
+ @buffer_mutex = Denko.gil? ? Denko::MutexStub.new : Mutex.new
7
+ self.add_callback(:buffer) do |data|
8
+ @buffer_mutex.lock
9
+ @buffer = "#{@buffer}#{data}"
10
+ @buffer_mutex.unlock
11
+ end
12
+ end
13
+
14
+ def gets
15
+ line = nil
16
+ @buffer_mutex.lock
17
+ newline = @buffer.index("\n")
18
+ if newline
19
+ line = @buffer[0..newline-1]
20
+ @buffer = @buffer[newline+1..-1]
21
+ end
22
+ @buffer_mutex.unlock
23
+ line
24
+ end
25
+
26
+ def flush
27
+ @buffer_mutex.lock
28
+ @buffer = ""
29
+ @buffer_mutex.unlock
30
+ end
31
+ end
32
+ end
33
+ end
@@ -3,49 +3,25 @@ module Denko
3
3
  class Hardware
4
4
  include Behaviors::SinglePin
5
5
  include Behaviors::Callbacks
6
+ include Behaviors::Lifecycle
7
+ include Common
6
8
 
7
9
  attr_reader :index, :baud
8
-
9
- def before_initialize(options={})
10
- if options[:index] && (options[:index] > 0) && (options[:index] < 4)
11
- @index = options[:index]
10
+
11
+ before_initialize do
12
+ if params[:index] && (params[:index] > 0) && (params[:index] < 4)
13
+ @index = params[:index]
12
14
  else
13
- raise ArgumentError, "UART index (#{options[:index]}) not given or out of range (1..3)"
15
+ raise ArgumentError, "UART index (#{params[:index]}) not given or out of range (1..3)"
14
16
  end
15
17
 
16
18
  # Set pin to a "virtual pin" in 251 - 253 that will match the board.
17
- options[:pin] = 250 + options[:index]
19
+ params[:pin] = 250 + params[:index]
18
20
  end
19
21
 
20
- def after_initialize(options={})
22
+ after_initialize do
21
23
  initialize_buffer
22
- start(options[:baud] ||= 9600)
23
- end
24
-
25
- def initialize_buffer
26
- @buffer = ""
27
- @buffer_mutex = Mutex.new
28
- self.add_callback(:buffer) do |data|
29
- @buffer_mutex.synchronize do
30
- @buffer = "#{@buffer}#{data}"
31
- end
32
- end
33
- end
34
-
35
- def gets
36
- @buffer_mutex.synchronize do
37
- newline = @buffer.index("\n")
38
- return nil unless newline
39
- line = @buffer[0..newline-1]
40
- @buffer = @buffer[newline+1..-1]
41
- return line
42
- end
43
- end
44
-
45
- def flush
46
- @buffer_mutex.synchronize do
47
- @buffer = ""
48
- end
24
+ start(params[:baud] ||= 9600)
49
25
  end
50
26
 
51
27
  def start(baud)
data/lib/denko/uart.rb CHANGED
@@ -1,6 +1,20 @@
1
+ # Represent files to be autoloaded in CRuby as an Array.
2
+ # This allows Mruby::Build to parse and preload them instead.
3
+ UART_FILES = [
4
+ [nil, "common"],
5
+ [:Hardware, "hardware"],
6
+ [:BitBang, "bit_bang"],
7
+ ]
8
+
1
9
  module Denko
2
10
  module UART
3
- autoload :Hardware, "#{__dir__}/uart/hardware"
4
- autoload :BitBang, "#{__dir__}/uart/bit_bang"
11
+ UART_FILES.each do |file|
12
+ file_path = "#{__dir__}/uart/#{file[1]}"
13
+ if file[0]
14
+ autoload file[0], file_path
15
+ else
16
+ require file_path
17
+ end
18
+ end
5
19
  end
6
20
  end
data/lib/denko/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Denko
2
- VERSION = "0.13.6"
2
+ VERSION = "0.15.0"
3
3
  end