denko 0.13.6 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/{build_avr.yml → build_atmega_avr.yml} +18 -18
- data/.github/workflows/{build_megaavr.yml → build_atmega_megaavr.yml} +18 -18
- data/.github/workflows/{build_sam3x.yml → build_atsam3x.yml} +17 -17
- data/.github/workflows/{build_samd.yml → build_atsamd21.yml} +18 -18
- data/.github/workflows/build_esp32.yml +17 -18
- data/.github/workflows/build_esp32c3.yml +57 -0
- data/.github/workflows/build_esp32c6.yml +57 -0
- data/.github/workflows/build_esp32h2.yml +56 -0
- data/.github/workflows/build_esp32s2.yml +57 -0
- data/.github/workflows/build_esp32s3.yml +57 -0
- data/.github/workflows/build_esp8266.yml +15 -15
- data/.github/workflows/build_ra4m1.yml +16 -16
- data/.github/workflows/build_rp2040.yml +17 -16
- data/.github/workflows/ruby.yml +20 -20
- data/CHANGELOG.md +195 -11
- data/DEPS_CLI.md +9 -9
- data/DEPS_IDE.md +17 -18
- data/HARDWARE.md +50 -51
- data/README.md +61 -53
- data/Rakefile +1 -1
- data/benchmarks/analog_listen.rb +49 -0
- data/benchmarks/digital_write.rb +28 -0
- data/benchmarks/i2c_ssd1306_refresh.rb +13 -6
- data/build +1 -1
- data/denko.gemspec +5 -2
- data/examples/advanced/{m5_env.rb → m5_env3.rb} +12 -14
- data/examples/advanced/rotary_encoder_mac_volume.rb +18 -13
- data/examples/advanced/ssd1306_time_temp_rh.rb +8 -13
- data/examples/analog_io/ads1100.rb +48 -0
- data/examples/analog_io/ads1115.rb +2 -2
- data/examples/analog_io/ads1118.rb +3 -11
- data/examples/analog_io/input.rb +17 -16
- data/examples/analog_io/input_smoothing.rb +27 -0
- data/examples/analog_io/potentiometer.rb +31 -0
- data/examples/connection/binary_echo.rb +34 -0
- data/examples/connection/tcp.rb +12 -27
- data/examples/digital_io/button.rb +7 -3
- data/examples/digital_io/relay.rb +17 -0
- data/examples/digital_io/rotary_encoder.rb +21 -11
- data/examples/display/hd44780.rb +13 -5
- data/examples/display/ssd1306.rb +20 -17
- data/examples/display/ssd1306_s2_pico.rb +2 -2
- data/examples/i2c/search.rb +10 -26
- data/examples/led/apa102_bounce.rb +3 -4
- data/examples/led/apa102_fade.rb +44 -0
- data/examples/led/builtin_blink.rb +3 -1
- data/examples/led/builtin_fade.rb +19 -0
- data/examples/led/rgb_led.rb +31 -0
- data/examples/led/seven_segment_char_echo.rb +4 -2
- data/examples/led/ws2812_bounce.rb +5 -7
- data/examples/led/ws2812_builtin_blink.rb +3 -2
- data/examples/led/ws2812_fade.rb +43 -0
- data/examples/motor/l298.rb +10 -8
- data/examples/motor/servo.rb +4 -3
- data/examples/motor/stepper.rb +13 -13
- data/examples/one_wire/search.rb +32 -0
- data/examples/pulse_io/buzzer.rb +8 -3
- data/examples/pulse_io/ir_output.rb +51 -0
- data/examples/pulse_io/pwm_output.rb +30 -0
- data/examples/rtc/ds3231.rb +18 -35
- data/examples/sensor/aht10.rb +4 -6
- data/examples/sensor/aht20.rb +4 -6
- data/examples/sensor/bme280.rb +4 -4
- data/examples/sensor/bmp180.rb +9 -5
- data/examples/sensor/dht.rb +20 -15
- data/examples/sensor/ds18b20.rb +20 -21
- data/examples/sensor/generic_pir.rb +4 -2
- data/examples/sensor/hcsr04.rb +5 -2
- data/examples/sensor/htu21d.rb +9 -20
- data/examples/sensor/htu31d.rb +7 -9
- data/examples/sensor/neat_tph_readings.rb +15 -9
- data/examples/sensor/qmp6988.rb +5 -7
- data/examples/sensor/rcwl9620.rb +3 -3
- data/examples/sensor/sht3x.rb +4 -6
- data/examples/spi/bitbang_loopback.rb +46 -0
- data/examples/spi/input_register.rb +9 -19
- data/examples/spi/output_register.rb +9 -17
- data/examples/spi/ssd_through_registers.rb +28 -0
- data/examples/spi/two_registers.rb +18 -24
- data/examples/uart/bit_bang_demo.rb +25 -0
- data/examples/uart/board_passthrough.rb +19 -13
- data/examples/uart/hardware_loopback.rb +1 -1
- data/lib/denko/analog_io/ads1100.rb +127 -0
- data/lib/denko/analog_io/ads1115.rb +8 -25
- data/lib/denko/analog_io/ads1118.rb +10 -25
- data/lib/denko/analog_io/ads111x.rb +25 -11
- data/lib/denko/analog_io/input.rb +29 -55
- data/lib/denko/analog_io/input_helper.rb +42 -0
- data/lib/denko/analog_io/output.rb +5 -5
- data/lib/denko/analog_io/potentiometer.rb +6 -8
- data/lib/denko/analog_io.rb +2 -1
- data/lib/denko/behaviors/board_proxy.rb +13 -1
- data/lib/denko/behaviors/bus_controller.rb +1 -0
- data/lib/denko/behaviors/bus_controller_addressed.rb +1 -0
- data/lib/denko/behaviors/bus_peripheral.rb +3 -4
- data/lib/denko/behaviors/bus_peripheral_addressed.rb +8 -6
- data/lib/denko/behaviors/callbacks.rb +9 -7
- data/lib/denko/behaviors/component.rb +16 -14
- data/lib/denko/behaviors/input_pin.rb +14 -15
- data/lib/denko/behaviors/lifecycle.rb +51 -0
- data/lib/denko/behaviors/multi_pin.rb +22 -18
- data/lib/denko/behaviors/output_pin.rb +9 -4
- data/lib/denko/behaviors/single_pin.rb +1 -0
- data/lib/denko/behaviors/state.rb +15 -9
- data/lib/denko/behaviors/subcomponents.rb +72 -12
- data/lib/denko/behaviors.rb +2 -1
- data/lib/denko/board/core.rb +36 -18
- data/lib/denko/board/i2c.rb +14 -14
- data/lib/denko/board/i2c_bit_bang.rb +49 -0
- data/lib/denko/board/infrared.rb +6 -6
- data/lib/denko/board/led_array.rb +6 -5
- data/lib/denko/board/spi.rb +15 -10
- data/lib/denko/board/spi_bit_bang.rb +9 -7
- data/lib/denko/board.rb +35 -33
- data/lib/denko/connection/binary_echo.rb +17 -0
- data/lib/denko/connection/flow_control.rb +11 -15
- data/lib/denko/connection/handshake.rb +2 -0
- data/lib/denko/digital_io/button.rb +4 -0
- data/lib/denko/digital_io/c_bit_bang.rb +15 -0
- data/lib/denko/digital_io/input.rb +4 -5
- data/lib/denko/digital_io/output.rb +7 -6
- data/lib/denko/digital_io/relay.rb +2 -0
- data/lib/denko/digital_io/rotary_encoder.rb +78 -60
- data/lib/denko/digital_io.rb +1 -0
- data/lib/denko/display/hd44780.rb +136 -93
- data/lib/denko/display/sh1106.rb +42 -0
- data/lib/denko/display/ssd1306.rb +105 -45
- data/lib/denko/display.rb +1 -0
- data/lib/denko/eeprom/built_in.rb +19 -16
- data/lib/denko/i2c/bit_bang.rb +31 -0
- data/lib/denko/i2c/bus.rb +8 -36
- data/lib/denko/i2c/bus_common.rb +45 -0
- data/lib/denko/i2c/peripheral.rb +28 -19
- data/lib/denko/i2c.rb +2 -0
- data/lib/denko/led/apa102.rb +43 -29
- data/lib/denko/led/base.rb +8 -2
- data/lib/denko/led/rgb.rb +5 -7
- data/lib/denko/led/seven_segment.rb +24 -9
- data/lib/denko/led/ws2812.rb +10 -7
- data/lib/denko/message.rb +5 -0
- data/lib/denko/motor/l298.rb +11 -10
- data/lib/denko/motor/servo.rb +22 -10
- data/lib/denko/motor/stepper.rb +11 -14
- data/lib/denko/mutex_stub.rb +7 -0
- data/lib/denko/one_wire/bus.rb +9 -5
- data/lib/denko/one_wire/peripheral.rb +0 -3
- data/lib/denko/pulse_io/buzzer.rb +9 -3
- data/lib/denko/pulse_io/{ir_transmitter.rb → ir_output.rb} +9 -4
- data/lib/denko/pulse_io/pwm_output.rb +69 -15
- data/lib/denko/pulse_io.rb +3 -3
- data/lib/denko/rtc/ds3231.rb +11 -13
- data/lib/denko/sensor/aht.rb +22 -21
- data/lib/denko/sensor/bme280.rb +60 -63
- data/lib/denko/sensor/bmp180.rb +41 -38
- data/lib/denko/sensor/dht.rb +22 -5
- data/lib/denko/sensor/ds18b20.rb +40 -34
- data/lib/denko/sensor/hcsr04.rb +7 -5
- data/lib/denko/sensor/helper.rb +37 -0
- data/lib/denko/sensor/htu21d.rb +44 -55
- data/lib/denko/sensor/htu31d.rb +32 -33
- data/lib/denko/sensor/qmp6988.rb +25 -23
- data/lib/denko/sensor/rcwl9620.rb +2 -5
- data/lib/denko/sensor/sht3x.rb +23 -21
- data/lib/denko/sensor.rb +1 -2
- data/lib/denko/spi/base_register.rb +22 -22
- data/lib/denko/spi/bit_bang.rb +17 -51
- data/lib/denko/spi/bus.rb +15 -29
- data/lib/denko/spi/bus_common.rb +36 -0
- data/lib/denko/spi/input_register.rb +36 -30
- data/lib/denko/spi/output_register.rb +25 -40
- data/lib/denko/spi/peripheral.rb +93 -24
- data/lib/denko/spi.rb +6 -1
- data/lib/denko/uart/bit_bang.rb +5 -3
- data/lib/denko/uart/hardware.rb +9 -8
- data/lib/denko/version.rb +1 -1
- data/lib/denko.rb +10 -0
- data/lib/denko_cli/generator.rb +2 -2
- data/lib/denko_cli/packages.rb +8 -10
- data/lib/denko_cli/targets.rb +8 -8
- data/lib/denko_cli/targets.txt +4 -4
- data/lib/denko_cli/usage.txt +1 -1
- data/src/denko_ethernet.ino +0 -14
- data/src/denko_serial.ino +0 -14
- data/src/denko_wifi.ino +6 -15
- data/src/lib/Denko.cpp +39 -3
- data/src/lib/Denko.h +42 -26
- data/src/lib/DenkoCoreIO.cpp +57 -102
- data/src/lib/DenkoDefines.h +36 -31
- data/src/lib/DenkoI2C.cpp +54 -45
- data/src/lib/DenkoI2CBB.cpp +238 -0
- data/src/lib/DenkoIROut.cpp +12 -7
- data/src/lib/DenkoLEDArray.cpp +36 -13
- data/src/lib/DenkoSPI.cpp +6 -5
- data/src/lib/DenkoSPIBB.cpp +7 -6
- data/target.yml +37 -2
- data/test/analog_io/potentiometer_test.rb +10 -10
- data/test/behaviors/board_proxy_test.rb +1 -1
- data/test/behaviors/callbacks_test.rb +11 -3
- data/test/behaviors/component_test.rb +17 -9
- data/test/behaviors/input_pin_test.rb +14 -9
- data/test/behaviors/multi_pin_test.rb +14 -4
- data/test/behaviors/output_pin_test.rb +11 -8
- data/test/behaviors/poller_test.rb +1 -0
- data/test/behaviors/reader_test.rb +3 -2
- data/test/behaviors/subcomponents_test.rb +22 -2
- data/test/board/core_test.rb +15 -11
- data/test/board/i2c_test.rb +39 -33
- data/test/board/infrared_test.rb +1 -1
- data/test/board/message_test.rb +17 -11
- data/test/board/spi_test.rb +21 -21
- data/test/digital_io/button_test.rb +15 -0
- data/test/digital_io/relay_test.rb +18 -0
- data/test/digital_io/rotary_encoder_test.rb +80 -60
- data/test/eeprom/built_in_test.rb +9 -9
- data/test/i2c/bus_test.rb +30 -14
- data/test/i2c/peripheral_test.rb +36 -17
- data/test/led/base_test.rb +2 -1
- data/test/led/rgb_test.rb +6 -6
- data/test/led/seven_segment_test.rb +7 -7
- data/test/motor/servo_test.rb +1 -1
- data/test/motor/stepper_test.rb +2 -2
- data/test/one_wire/bus_test.rb +1 -0
- data/test/pulse_io/buzzer_test.rb +7 -4
- data/test/pulse_io/{ir_transmitter_test.rb → ir_output_test.rb} +10 -10
- data/test/pulse_io/pwm_output_test.rb +74 -18
- data/test/rtc/ds3231_test.rb +11 -13
- data/test/sensor/dht_test.rb +1 -1
- data/test/sensor/ds18b20_test.rb +4 -8
- data/test/spi/bus_test.rb +7 -7
- data/test/spi/input_register_test.rb +15 -15
- data/test/spi/output_register_test.rb +10 -28
- data/test/spi/peripheral_multi_pin_test.rb +53 -0
- data/test/spi/peripheral_single_pin_test.rb +48 -0
- data/test/test_helper.rb +36 -33
- data/tutorial/02-button/button.rb +5 -4
- data/tutorial/03-potentiometer/potentiometer.rb +9 -5
- data/tutorial/04-pwm_led/pwm_led.rb +14 -16
- data/tutorial/05-rgb_led/rgb_led.rb +6 -6
- data/tutorial/05-rgb_led/rgb_mapping.rb +11 -11
- data/vendor/board-maps/BoardMap.h +416 -56
- data/vendor/board-maps/lib/header_parser.rb +12 -2
- data/vendor/board-maps/yaml/ADAFRUIT_CAMERA_ESP32S3.yml +2 -2
- data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32C6.yml +15 -0
- data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32_V2.yml +1 -1
- data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_RP2040_ADALOGGER.yml +44 -0
- data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32C3.yml +1 -0
- data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S2.yml +1 -0
- data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_N4R2.yml +1 -0
- data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_NOPSRAM.yml +1 -0
- data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32_PICO.yml +1 -0
- data/vendor/board-maps/yaml/AMKEN_BB.yml +48 -0
- data/vendor/board-maps/yaml/AMKEN_ES.yml +48 -0
- data/vendor/board-maps/yaml/AMKEN_REVELOP.yml +48 -0
- data/vendor/board-maps/yaml/AMKEN_REVELOP_PLUS.yml +48 -0
- data/vendor/board-maps/yaml/ASL_CAN_X2.yml +41 -0
- data/vendor/board-maps/yaml/BLING.yml +25 -0
- data/vendor/board-maps/yaml/BPI_LEAF_S3.yml +1 -0
- data/vendor/board-maps/yaml/BRIDGETEK_IDM2040_7A.yml +48 -0
- data/vendor/board-maps/yaml/Bee_Motion_Mini.yml +13 -1
- data/vendor/board-maps/yaml/Breadstick_Raspberry.yml +31 -0
- data/vendor/board-maps/yaml/DFROBOT_BEETLE_ESP32C6.yml +8 -0
- data/vendor/board-maps/yaml/DFROBOT_FIREBEETLE_2_ESP32C6.yml +20 -0
- data/vendor/board-maps/yaml/DFROBOT_FIREBEETLE_ESP32.yml +46 -0
- data/vendor/board-maps/yaml/DPTECHNICS_WALTER.yml +39 -0
- data/vendor/board-maps/yaml/ELECROW_CROWPANEL_7.yml +8 -0
- data/vendor/board-maps/yaml/ESP32C2_DEV.yml +12 -0
- data/vendor/board-maps/yaml/ESP32C3_DEVKIT_LIPO.yml +14 -0
- data/vendor/board-maps/yaml/ESP32C6_DEV.yml +15 -0
- data/vendor/board-maps/yaml/ESP32C6_EVB.yml +15 -0
- data/vendor/board-maps/yaml/ESP32C6_QWIIC_POCKET.yml +15 -0
- data/vendor/board-maps/yaml/ESP32C6_THING_PLUS.yml +15 -0
- data/vendor/board-maps/yaml/ESP32H2_DEV.yml +13 -0
- data/vendor/board-maps/yaml/ESP32H2_DEVKIT_LIPO.yml +13 -0
- data/vendor/board-maps/yaml/ESP32S2_DEV.yml +1 -0
- data/vendor/board-maps/yaml/{RMP.yml → ESP32S2_DEVKIT_LIPO.yml} +2 -1
- data/vendor/board-maps/yaml/ESP32S2_DEVKIT_LIPO_USB.yml +44 -0
- data/vendor/board-maps/yaml/ESP32S3_DEVKIT_LIPO.yml +42 -0
- data/vendor/board-maps/yaml/ESP32S3_POWERFEATHER.yml +22 -0
- data/vendor/board-maps/yaml/ESP32_SBC_FABGL.yml +35 -0
- data/vendor/board-maps/yaml/EVN_ALPHA.yml +48 -0
- data/vendor/board-maps/yaml/FEATHERS3NEO.yml +32 -0
- data/vendor/board-maps/yaml/GEEKBLE_ESP32C3.yml +14 -0
- data/vendor/board-maps/yaml/HELTEC_CAPSULE_SENSOR_V3.yml +43 -0
- data/vendor/board-maps/yaml/HELTEC_WIFI_LORA_32_V3.yml +42 -0
- data/vendor/board-maps/yaml/HELTEC_WIRELESS_BRIDGE.yml +8 -0
- data/vendor/board-maps/yaml/HELTEC_WIRELESS_MINI_SHELL.yml +13 -0
- data/vendor/board-maps/yaml/HELTEC_WIRELESS_PAPER.yml +42 -0
- data/vendor/board-maps/yaml/HELTEC_WIRELESS_SHELL_V3.yml +42 -0
- data/vendor/board-maps/yaml/HELTEC_WIRELESS_STICK_LITE_V3.yml +30 -0
- data/vendor/board-maps/yaml/HELTEC_WIRELESS_TRACKER.yml +41 -0
- data/vendor/board-maps/yaml/HT_DE01.yml +42 -0
- data/vendor/board-maps/yaml/IMBRIOS_LOGSENS_V1P1.yml +1 -1
- data/vendor/board-maps/yaml/LILYGO_T3S3_LR1121.yml +9 -0
- data/vendor/board-maps/yaml/LILYGO_T3S3_SX1262.yml +9 -0
- data/vendor/board-maps/yaml/LILYGO_T3S3_SX1276.yml +9 -0
- data/vendor/board-maps/yaml/LILYGO_T3S3_SX1278.yml +9 -0
- data/vendor/board-maps/yaml/LILYGO_T3S3_SX1280.yml +9 -0
- data/vendor/board-maps/yaml/LILYGO_T3S3_SX1280PA.yml +8 -0
- data/vendor/board-maps/yaml/LILYGO_T_ETH_LITE.yml +21 -0
- data/vendor/board-maps/yaml/LOLIN_C3_PICO.yml +14 -0
- data/vendor/board-maps/yaml/LOLIN_S3.yml +1 -0
- data/vendor/board-maps/yaml/LOLIN_S3_MINI_PRO.yml +40 -0
- data/vendor/board-maps/yaml/Lion_Bit_Dev_Board.yml +0 -2
- data/vendor/board-maps/yaml/LoPy.yml +1 -0
- data/vendor/board-maps/yaml/LoPy4.yml +1 -0
- data/vendor/board-maps/yaml/M5STACK_CAPSULE.yml +8 -0
- data/vendor/board-maps/yaml/M5STACK_CARDPUTER.yml +8 -0
- data/vendor/board-maps/yaml/M5STACK_DIAL.yml +8 -0
- data/vendor/board-maps/yaml/M5STACK_FIRE.yml +0 -1
- data/vendor/board-maps/yaml/M5STACK_NANOC6.yml +17 -0
- data/vendor/board-maps/yaml/M5STACK_PAPER.yml +9 -0
- data/vendor/board-maps/yaml/M5STACK_POE_CAM.yml +5 -0
- data/vendor/board-maps/yaml/M5STACK_STAMP_C3.yml +13 -0
- data/vendor/board-maps/yaml/M5STACK_STAMP_S3.yml +4 -0
- data/vendor/board-maps/yaml/{M5Stick_C.yml → M5STACK_STICKC.yml} +0 -1
- data/vendor/board-maps/yaml/M5STACK_STICKC_PLUS.yml +9 -0
- data/vendor/board-maps/yaml/M5STACK_STICKC_PLUS2.yml +9 -0
- data/vendor/board-maps/yaml/M5STACK_TOUGH.yml +9 -0
- data/vendor/board-maps/yaml/M5STACK_UNIT_CAM.yml +10 -0
- data/vendor/board-maps/yaml/M5STACK_UNIT_CAMS3.yml +4 -0
- data/vendor/board-maps/yaml/M5Stack_ATOM.yml +0 -1
- data/vendor/board-maps/yaml/MAKERGO_C3_SUPERMINI.yml +14 -0
- data/vendor/board-maps/yaml/MARBLE_PICO.yml +48 -0
- data/vendor/board-maps/yaml/METEHOCA_AKANA_R1.yml +46 -0
- data/vendor/board-maps/yaml/NAMINO_BIANCO.yml +13 -0
- data/vendor/board-maps/yaml/NEBULAS3.yml +0 -1
- data/vendor/board-maps/yaml/NEWSAN_ARCHI.yml +48 -0
- data/vendor/board-maps/yaml/NOLOGO_ESP32C3_SUPER_MINI.yml +14 -0
- data/vendor/board-maps/yaml/NOLOGO_ESP32S3_PICO.yml +12 -0
- data/vendor/board-maps/yaml/OLIMEX_RP2040_PICO30_16MB.yml +48 -0
- data/vendor/board-maps/yaml/OLIMEX_RP2040_PICO30_2MB.yml +48 -0
- data/vendor/board-maps/yaml/OPTA_ANALOG.yml +7 -0
- data/vendor/board-maps/yaml/OPTA_DIGITAL.yml +5 -0
- data/vendor/board-maps/yaml/PINTRONIX_PINMAX.yml +42 -0
- data/vendor/board-maps/yaml/PYCOM_GPY.yml +1 -0
- data/vendor/board-maps/yaml/REDPILL_ESP32S3.yml +0 -1
- data/vendor/board-maps/yaml/SENSEBOX_MCU_ESP32S2.yml +12 -0
- data/vendor/board-maps/yaml/SPARKFUN_MICROMOD_RP2040.yml +48 -0
- data/vendor/board-maps/yaml/SPARKFUN_PRO_MICRO_ESP32C3.yml +24 -0
- data/vendor/board-maps/yaml/THINGPULSE_EPULSE_FEATHER.yml +31 -0
- data/vendor/board-maps/yaml/THINGPULSE_EPULSE_FEATHER_C6.yml +15 -0
- data/vendor/board-maps/yaml/TINYC6.yml +25 -0
- data/vendor/board-maps/yaml/UPESY_EDU_ESP32.yml +28 -0
- data/vendor/board-maps/yaml/UPESY_ESP32C3_BASIC.yml +13 -0
- data/vendor/board-maps/yaml/UPESY_ESP32C3_MINI.yml +12 -0
- data/vendor/board-maps/yaml/UPESY_ESP32S3_BASIC.yml +42 -0
- data/vendor/board-maps/yaml/VIRALINK_GATE32_01.yml +6 -0
- data/vendor/board-maps/yaml/VIRALINK_GATE32_11.yml +7 -0
- data/vendor/board-maps/yaml/WAVESHARE_ESP32S3_TOUCH_LCD_128.yml +8 -0
- data/vendor/board-maps/yaml/WAVESHARE_RP2040_MATRIX.yml +48 -0
- data/vendor/board-maps/yaml/WAVESHARE_RP2040_ONE.yml +1 -0
- data/vendor/board-maps/yaml/WAVESHARE_RP2040_PIZERO.yml +47 -0
- data/vendor/board-maps/yaml/WAVESHARE_RP2040_ZERO.yml +1 -0
- data/vendor/board-maps/yaml/WEACT_STUDIO_ESP32C3.yml +14 -0
- data/vendor/board-maps/yaml/WIPY3.yml +1 -0
- data/vendor/board-maps/yaml/WT32_SC01_PLUS.yml +7 -0
- data/vendor/board-maps/yaml/WiFiduinoV2.yml +1 -0
- data/vendor/board-maps/yaml/XIAO_ESP32C3.yml +0 -1
- data/vendor/board-maps/yaml/XIAO_ESP32C6.yml +22 -0
- data/vendor/board-maps/yaml/unphone9.yml +8 -0
- metadata +169 -30
- data/examples/led/apa102_breathe.rb +0 -45
- data/examples/pulse_io/ir_transmitter.rb +0 -55
- data/examples/spi/ssd_through_register.rb +0 -40
- data/examples/uart/bit_bang_read.rb +0 -16
- data/examples/uart/bit_bang_write.rb +0 -16
- data/lib/denko/analog_io/sensor.rb +0 -6
- data/lib/denko/sensor/virtual.rb +0 -42
- data/src/lib/DenkoIROutESP.cpp +0 -26
- data/vendor/board-maps/yaml/STAMP_S3.yml +0 -8
- /data/vendor/board-maps/yaml/{BRIDGETEK_IDM2040-7A.yml → BRIDGETEK_IDM2040_43A.yml} +0 -0
- /data/vendor/board-maps/yaml/{heltec_wifi_32_lora_V3.yml → HELTEC_WIRELESS_STICK_V3.yml} +0 -0
- /data/vendor/board-maps/yaml/{M5Stack_Core_ESP32.yml → M5STACK_CORE.yml} +0 -0
- /data/vendor/board-maps/yaml/{M5Stamp_Pico.yml → M5STACK_STAMP_PICO.yml} +0 -0
- /data/vendor/board-maps/yaml/{M5Stack-Timer-CAM.yml → M5STACK_TIMER_CAM.yml} +0 -0
@@ -3,7 +3,12 @@ require_relative 'canvas'
|
|
3
3
|
module Denko
|
4
4
|
module Display
|
5
5
|
class SSD1306
|
6
|
-
include
|
6
|
+
include Behaviors::BusPeripheral
|
7
|
+
include Behaviors::Lifecycle
|
8
|
+
|
9
|
+
# I2C Defaults
|
10
|
+
I2C_ADDRESS = 0x3C
|
11
|
+
I2C_FREQUENCY = 400_000
|
7
12
|
|
8
13
|
# Fundamental Commands
|
9
14
|
# Single byte (no need to OR with anything)
|
@@ -27,9 +32,13 @@ module Denko
|
|
27
32
|
PAGE_START = 0xB0 # page 0-7
|
28
33
|
|
29
34
|
# Double byte. Following byte sets value.
|
30
|
-
ADDRESSING_MODE
|
31
|
-
# Values:
|
32
|
-
|
35
|
+
ADDRESSING_MODE = 0x20
|
36
|
+
# Values:
|
37
|
+
# 0x00 = horizontal (Pages auto-increment. Used for SSD1306)
|
38
|
+
# 0x01 = vertical
|
39
|
+
# 0x02 = page (Default. Page and column must be set each time. Needed on SH1106)
|
40
|
+
ADDRESSING_MODE_DEFAULT = 0x00
|
41
|
+
|
33
42
|
# Triple byte. Following 2 bytes sets value. For H/V addressing modes only.
|
34
43
|
COLUMN_ADDRESS_RANGE = 0x21
|
35
44
|
PAGE_ADDRESS_RANGE = 0x22
|
@@ -61,38 +70,59 @@ module Denko
|
|
61
70
|
WIDTHS = [64,96,128]
|
62
71
|
HEIGHTS = [16,32,48,64]
|
63
72
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
attr_accessor :canvas
|
74
|
+
|
75
|
+
# Default to a 128x64 display.
|
76
|
+
def columns
|
77
|
+
@columns ||= params[:columns] || params[:width] || 128
|
68
78
|
end
|
69
79
|
|
70
|
-
def
|
71
|
-
|
80
|
+
def rows
|
81
|
+
@rows ||= params[:rows] || params[:height] || 64
|
82
|
+
end
|
72
83
|
|
73
|
-
|
74
|
-
@
|
75
|
-
@
|
84
|
+
def rotated
|
85
|
+
return @rotated unless @rotated.nil?
|
86
|
+
@rotated = params[:rotated]
|
87
|
+
@rotated = params[:rotate] if @rotated.nil?
|
88
|
+
@rotated = false if @rotated.nil?
|
89
|
+
@rotated
|
90
|
+
end
|
91
|
+
|
92
|
+
# Decide whether this instnace is I2C or SPI.
|
93
|
+
before_initialize do
|
94
|
+
bus = params[:bus] || params[:board]
|
76
95
|
|
96
|
+
if bus.class.ancestors.include?(Denko::SPI::Bus) || bus.class.ancestors.include?(Denko::SPI::BitBang)
|
97
|
+
mutate_spi
|
98
|
+
elsif bus.class.ancestors.include?(Denko::I2C::Bus) || bus.class.ancestors.include?(Denko::I2C::BitBang)
|
99
|
+
mutate_i2c
|
100
|
+
else
|
101
|
+
raise ArgumentError, "#{self.class} must be connected to either an I2C or SPI bus"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
after_initialize do
|
77
106
|
# Validate known sizes.
|
78
|
-
raise ArgumentError, "error in
|
79
|
-
raise ArgumentError, "error in
|
107
|
+
raise ArgumentError, "error in #{self.class} width: #{columns}. Must be in: #{WIDTHS.inspect}" unless WIDTHS.include?(columns)
|
108
|
+
raise ArgumentError, "error in #{self.class} height: #{rows}. Must be in: #{HEIGHTS.inspect}" unless HEIGHTS.include?(rows)
|
80
109
|
|
81
110
|
# Everything except 96x16 size uses clock 0x80.
|
82
111
|
clock = 0x80
|
83
|
-
clock = 0x60 if (
|
112
|
+
clock = 0x60 if (columns == 96 && rows == 16)
|
84
113
|
|
85
114
|
# 128x32 and 96x16 sizes use com pin config 0x02
|
86
115
|
com_pin_config = 0x12
|
87
|
-
com_pin_config = 0x02 if (
|
116
|
+
com_pin_config = 0x02 if (columns == 96 && rows == 16) || (columns == 128 && rows == 32)
|
88
117
|
|
89
118
|
# Reflecting horizontally and vertically to effectively rotate 180 degrees.
|
90
|
-
seg_remap =
|
91
|
-
com_direction =
|
119
|
+
seg_remap = rotated ? 0x01 : 0x00
|
120
|
+
com_direction = rotated ? 0x08 : 0x00
|
92
121
|
|
93
|
-
# Startup sequence
|
122
|
+
# Startup sequence (SPI doesn't work properly if this isn't sent twice.)
|
123
|
+
2.times do
|
94
124
|
command [
|
95
|
-
MULTIPLEX_RATIO,
|
125
|
+
MULTIPLEX_RATIO, rows - 1,
|
96
126
|
DISPLAY_OFFSET, 0x00,
|
97
127
|
START_LINE | 0x00,
|
98
128
|
SEGMENT_REMAP | seg_remap,
|
@@ -104,23 +134,22 @@ module Denko
|
|
104
134
|
VCOM_DESELECT_LEVEL, 0x20,
|
105
135
|
PRECHARGE_PERIOD, 0xF1, # Charge period for internal charge pump
|
106
136
|
CHARGE_PUMP, 0x14, # Internal charge pump
|
107
|
-
ADDRESSING_MODE,
|
137
|
+
ADDRESSING_MODE, self.class::ADDRESSING_MODE_DEFAULT,
|
108
138
|
DISPLAY_ON
|
109
139
|
]
|
110
|
-
|
140
|
+
end
|
141
|
+
|
111
142
|
# Create a new blank canvas and draw it.
|
112
|
-
self.canvas = Canvas.new(
|
143
|
+
self.canvas = Canvas.new(columns, rows)
|
113
144
|
draw
|
114
145
|
end
|
115
146
|
|
116
|
-
attr_accessor :canvas
|
117
|
-
|
118
147
|
def off
|
119
|
-
command
|
148
|
+
command [DISPLAY_OFF]
|
120
149
|
end
|
121
150
|
|
122
151
|
def on
|
123
|
-
command
|
152
|
+
command [DISPLAY_ON]
|
124
153
|
end
|
125
154
|
|
126
155
|
def contrast=(value)
|
@@ -128,24 +157,24 @@ module Denko
|
|
128
157
|
command [CONTRAST, value]
|
129
158
|
end
|
130
159
|
|
131
|
-
def draw(x_min=0, x_max=(
|
160
|
+
def draw(x_min=0, x_max=(columns-1), y_min=0, y_max=(rows-1))
|
132
161
|
# Convert y-coords to page coords.
|
133
162
|
p_min = y_min / 8
|
134
163
|
p_max = y_max / 8
|
135
|
-
|
164
|
+
|
136
165
|
# If drawing the whole frame (default), bypass temp buffer to save time.
|
137
|
-
if (x_min == 0) && (x_max ==
|
166
|
+
if (x_min == 0) && (x_max == columns-1) && (p_min == 0) && (p_max == rows/8)
|
138
167
|
draw_partial(canvas.framebuffer, x_min, x_max, p_min, p_max)
|
139
|
-
|
140
|
-
# Copy bytes for the given rectangle into a temp buffer.
|
168
|
+
|
169
|
+
# Copy bytes for the given rectangle into a temp buffer.
|
141
170
|
else
|
142
171
|
temp_buffer = []
|
143
172
|
(p_min..p_max).each do |page|
|
144
|
-
src_start = (
|
145
|
-
src_end = (
|
173
|
+
src_start = (columns * page) + x_min
|
174
|
+
src_end = (columns * page) + x_max
|
146
175
|
temp_buffer += canvas.framebuffer[src_start..src_end]
|
147
176
|
end
|
148
|
-
|
177
|
+
|
149
178
|
# And draw them.
|
150
179
|
draw_partial(temp_buffer, x_min, x_max, p_min, p_max)
|
151
180
|
end
|
@@ -154,25 +183,56 @@ module Denko
|
|
154
183
|
def draw_partial(buffer, x_min, x_max, p_min, p_max)
|
155
184
|
# Limit auto-incrementing GRAM address to the rectangle being drawn.
|
156
185
|
command [ COLUMN_ADDRESS_RANGE, x_min, x_max, PAGE_ADDRESS_RANGE, p_min, p_max ]
|
157
|
-
|
186
|
+
|
158
187
|
# Send all the bytes at once if within board I2C limit.
|
159
188
|
if buffer.length < (bus.board.i2c_limit - 1)
|
160
189
|
data(buffer)
|
161
|
-
|
190
|
+
|
162
191
|
# Or split into chunks.
|
163
|
-
else
|
192
|
+
else
|
164
193
|
buffer.each_slice(bus.board.i2c_limit - 1) { |slice| data(slice) }
|
165
194
|
end
|
166
195
|
end
|
167
196
|
|
168
|
-
|
169
|
-
|
170
|
-
|
197
|
+
def mutate_i2c
|
198
|
+
singleton_class.class_eval do
|
199
|
+
include I2C::Peripheral
|
200
|
+
|
201
|
+
# Commands are I2C messages prefixed with 0x00.
|
202
|
+
def command(bytes)
|
203
|
+
i2c_write([0x00] + bytes)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Data are I2C messages prefixed with 0x40.
|
207
|
+
def data(bytes)
|
208
|
+
i2c_write([0x40] + bytes)
|
209
|
+
end
|
210
|
+
end
|
171
211
|
end
|
172
212
|
|
173
|
-
|
174
|
-
|
175
|
-
|
213
|
+
def mutate_spi
|
214
|
+
singleton_class.class_eval do
|
215
|
+
include SPI::Peripheral::MultiPin
|
216
|
+
|
217
|
+
def initialize_pins(options={})
|
218
|
+
super(options)
|
219
|
+
proxy_pin :dc, DigitalIO::Output, board: bus.board
|
220
|
+
proxy_pin :reset, DigitalIO::Output, board: bus.board, optional: true
|
221
|
+
reset.high if reset
|
222
|
+
end
|
223
|
+
|
224
|
+
# Commands are SPI bytes written while DC pin low.
|
225
|
+
def command(bytes)
|
226
|
+
dc.low
|
227
|
+
spi_write(bytes)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Data are SPI SPI bytes written while DC pin high.
|
231
|
+
def data(bytes)
|
232
|
+
dc.high
|
233
|
+
spi_write(bytes)
|
234
|
+
end
|
235
|
+
end
|
176
236
|
end
|
177
237
|
end
|
178
238
|
end
|
data/lib/denko/display.rb
CHANGED
@@ -3,6 +3,7 @@ module Denko
|
|
3
3
|
class BuiltIn
|
4
4
|
include Behaviors::Component
|
5
5
|
include Behaviors::Reader
|
6
|
+
include Behaviors::Lifecycle
|
6
7
|
|
7
8
|
public :state=
|
8
9
|
|
@@ -10,12 +11,14 @@ module Denko
|
|
10
11
|
254
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
-
super(options)
|
15
|
-
self.state = Array.new(board.eeprom_length, nil)
|
14
|
+
after_initialize do
|
16
15
|
load
|
17
16
|
end
|
18
17
|
|
18
|
+
def state
|
19
|
+
state_mutex.synchronize { @state ||= Array.new(board.eeprom_length, nil) }
|
20
|
+
end
|
21
|
+
|
19
22
|
def load
|
20
23
|
state.each_slice(128).with_index do |slice, index|
|
21
24
|
read_using -> { board.eeprom_read(index * 128, slice.length) }
|
@@ -23,36 +26,36 @@ module Denko
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def save
|
26
|
-
|
29
|
+
state_mutex.synchronize do
|
27
30
|
@state.each_slice(128).with_index do |slice, index|
|
28
31
|
board.eeprom_write(index * 128, slice)
|
29
32
|
end
|
30
33
|
end
|
31
34
|
load
|
32
35
|
end
|
33
|
-
|
36
|
+
|
34
37
|
#
|
35
38
|
# Specific Array-like methods for convenience.
|
36
|
-
#
|
39
|
+
#
|
37
40
|
def length; board.eeprom_length; end
|
38
41
|
alias :count :length
|
39
|
-
|
42
|
+
|
40
43
|
def [](index)
|
41
|
-
|
44
|
+
state_mutex.synchronize { @state.send :[], index }
|
42
45
|
end
|
43
|
-
|
46
|
+
|
44
47
|
def []=(index, value)
|
45
|
-
|
48
|
+
state_mutex.synchronize { @state.send :[]=, index, value }
|
46
49
|
end
|
47
|
-
|
50
|
+
|
48
51
|
def each(&block)
|
49
|
-
|
52
|
+
state_mutex.synchronize { @state.send :each, &block }
|
50
53
|
end
|
51
|
-
|
54
|
+
|
52
55
|
def each_with_index(&block)
|
53
|
-
|
56
|
+
state_mutex.synchronize { @state.send :each_with_index, &block }
|
54
57
|
end
|
55
|
-
|
58
|
+
|
56
59
|
def pre_callback_filter(message)
|
57
60
|
address = message.split("-", 2)[0].to_i
|
58
61
|
bytes = message.split("-", 2)[1].split(",").map(&:to_i)
|
@@ -60,7 +63,7 @@ module Denko
|
|
60
63
|
end
|
61
64
|
|
62
65
|
def update_state(hash)
|
63
|
-
|
66
|
+
state_mutex.synchronize do
|
64
67
|
@state[hash[:address], hash[:data].length] = hash[:data]
|
65
68
|
end
|
66
69
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Denko
|
2
|
+
module I2C
|
3
|
+
class BitBang
|
4
|
+
include Behaviors::MultiPin
|
5
|
+
include Behaviors::Lifecycle
|
6
|
+
include BusCommon
|
7
|
+
|
8
|
+
def initialize_pins(options={})
|
9
|
+
proxy_pin :scl, DigitalIO::CBitBang
|
10
|
+
proxy_pin :sda, DigitalIO::CBitBang
|
11
|
+
end
|
12
|
+
|
13
|
+
after_initialize do
|
14
|
+
# Data received for the SDA pin is really for the bus.
|
15
|
+
sda.add_callback(:bus_forwarder) { |data| self.update(data) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def _search
|
19
|
+
board.i2c_bb_search(pins[:scl], pins[:sda])
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(address, bytes, frequency=nil, repeated_start=false)
|
23
|
+
board.i2c_bb_write(pins[:scl], pins[:sda], address, bytes, repeated_start)
|
24
|
+
end
|
25
|
+
|
26
|
+
def _read(address, register, num_bytes, frequency=nil, repeated_start=false)
|
27
|
+
board.i2c_bb_read(pins[:scl], pins[:sda], address, register, num_bytes, repeated_start)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/denko/i2c/bus.rb
CHANGED
@@ -1,51 +1,23 @@
|
|
1
1
|
module Denko
|
2
2
|
module I2C
|
3
3
|
class Bus
|
4
|
-
include Behaviors::
|
5
|
-
include
|
6
|
-
include Behaviors::Reader
|
4
|
+
include Behaviors::Lifecycle
|
5
|
+
include BusCommon
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
def after_initialize(options={})
|
11
|
-
super(options)
|
12
|
-
@found_devices = []
|
13
|
-
bubble_callbacks
|
7
|
+
def i2c_index
|
8
|
+
@i2c_index ||= params[:i2c_index] || params[:index] || 0
|
14
9
|
end
|
15
10
|
|
16
|
-
def
|
17
|
-
|
18
|
-
@found_devices = addresses.split(":").map(&:to_i) if addresses
|
11
|
+
def _search
|
12
|
+
board.i2c_search(i2c_index)
|
19
13
|
end
|
20
14
|
|
21
15
|
def write(address, bytes, frequency=100000, repeated_start=false)
|
22
|
-
board.i2c_write(address, bytes, frequency, repeated_start)
|
16
|
+
board.i2c_write(i2c_index, address, bytes, frequency, repeated_start)
|
23
17
|
end
|
24
18
|
|
25
19
|
def _read(address, register, num_bytes, frequency=100000, repeated_start=false)
|
26
|
-
board.i2c_read(address, register, num_bytes, frequency, repeated_start)
|
27
|
-
end
|
28
|
-
|
29
|
-
def bubble_callbacks
|
30
|
-
add_callback(:bus_controller) do |str|
|
31
|
-
if str && str.match(/\A\d+-/)
|
32
|
-
address, data = str.split("-", 2)
|
33
|
-
address = address.to_i
|
34
|
-
|
35
|
-
data = data.split(",").map(&:to_i)
|
36
|
-
data = nil if data.empty?
|
37
|
-
|
38
|
-
update_component(address, data)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def update_component(address, data)
|
44
|
-
components.each do |component|
|
45
|
-
if component.address == address
|
46
|
-
component.update(data)
|
47
|
-
end
|
48
|
-
end
|
20
|
+
board.i2c_read(i2c_index, address, register, num_bytes, frequency, repeated_start)
|
49
21
|
end
|
50
22
|
end
|
51
23
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Denko
|
2
|
+
module I2C
|
3
|
+
module BusCommon
|
4
|
+
include Behaviors::BusControllerAddressed
|
5
|
+
include Behaviors::Reader
|
6
|
+
include Behaviors::Lifecycle
|
7
|
+
|
8
|
+
after_initialize do
|
9
|
+
bubble_callbacks
|
10
|
+
end
|
11
|
+
|
12
|
+
def found_devices
|
13
|
+
@found_devices ||= []
|
14
|
+
end
|
15
|
+
attr_writer :found_devices
|
16
|
+
|
17
|
+
def search
|
18
|
+
addresses = read_using -> { _search }
|
19
|
+
@found_devices = addresses.split(":").map(&:to_i).reject{ |e| e==0 } if addresses
|
20
|
+
end
|
21
|
+
|
22
|
+
def bubble_callbacks
|
23
|
+
add_callback(:bus_controller) do |data|
|
24
|
+
bytes = nil
|
25
|
+
|
26
|
+
# Array data from PiBoard.
|
27
|
+
if data.class == Array
|
28
|
+
address = data.shift
|
29
|
+
bytes = data
|
30
|
+
|
31
|
+
# String data from microcontroller.
|
32
|
+
elsif (data.class == String) && (data.match /\A\d+-/)
|
33
|
+
address, bytes = data.split("-", 2)
|
34
|
+
address = address.to_i
|
35
|
+
bytes = bytes.split(",").map(&:to_i)
|
36
|
+
bytes = nil if bytes.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Update components.
|
40
|
+
components.each { |c| c.update(bytes) if c.address == address } if bytes
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/denko/i2c/peripheral.rb
CHANGED
@@ -3,35 +3,44 @@ module Denko
|
|
3
3
|
module Peripheral
|
4
4
|
include Behaviors::BusPeripheralAddressed
|
5
5
|
include Behaviors::Reader
|
6
|
+
include Behaviors::Lifecycle
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
# Set I2C defaults for including classes by defining these constants in them.
|
9
|
+
I2C_ADDRESS = nil
|
10
|
+
I2C_FREQUENCY = 100_000
|
11
|
+
I2C_REPEATED_START = false
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
def i2c_default(sym)
|
14
|
+
const_sym = "I2C_#{sym}".upcase.to_sym
|
15
|
+
self.class.const_get(const_sym) if self.class.const_defined?(const_sym)
|
16
|
+
end
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
@
|
18
|
+
# Use @address instead of @i2c_address for default BusPeripheral behavior.
|
19
|
+
def address
|
20
|
+
@address ||= params[:i2c_address] || params[:address] || i2c_default(:address)
|
21
|
+
end
|
22
|
+
alias :i2c_address :address
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
def i2c_frequency
|
25
|
+
@i2c_frequency ||= params[:i2c_frequency] || params[:frequency] || i2c_default(:frequency)
|
26
|
+
end
|
22
27
|
|
23
|
-
|
28
|
+
def i2c_repeated_start
|
29
|
+
return @i2c_repeated_start unless @i2c_repeated_start.nil?
|
30
|
+
@i2c_repeated_start = params[:i2c_repeated_start] if @i2c_repeated_start.nil?
|
31
|
+
@i2c_repeated_start = params[:repeated_start] if @i2c_repeated_start.nil?
|
32
|
+
@i2c_repeated_start = i2c_default(:repeated_start) if @i2c_repeated_start.nil?
|
33
|
+
@i2c_repeated_start
|
24
34
|
end
|
25
|
-
|
26
|
-
|
27
|
-
alias :i2c_address :address
|
35
|
+
|
36
|
+
attr_writer :i2c_frequency, :i2c_repeated_start
|
28
37
|
|
29
38
|
def i2c_write(bytes=[])
|
30
|
-
bus.write(
|
39
|
+
bus.write(i2c_address, bytes, i2c_frequency, i2c_repeated_start)
|
31
40
|
end
|
32
41
|
|
33
|
-
def i2c_read(
|
34
|
-
bus._read(
|
42
|
+
def i2c_read(num_bytes, register: nil)
|
43
|
+
bus._read(i2c_address, register, num_bytes, i2c_frequency, i2c_repeated_start)
|
35
44
|
end
|
36
45
|
end
|
37
46
|
end
|
data/lib/denko/i2c.rb
CHANGED
data/lib/denko/led/apa102.rb
CHANGED
@@ -1,39 +1,52 @@
|
|
1
1
|
module Denko
|
2
2
|
module LED
|
3
3
|
class APA102
|
4
|
-
include
|
4
|
+
include Behaviors::BusPeripheral
|
5
|
+
include Behaviors::Lifecycle
|
5
6
|
|
6
|
-
|
7
|
+
def pin; nil; end
|
7
8
|
|
8
|
-
def
|
9
|
-
|
10
|
-
super(options)
|
9
|
+
def length
|
10
|
+
@length ||= params[:length] || 1
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@length = options[:length]
|
13
|
+
# Start frame is always 32 0-bits (4 bytes).
|
14
|
+
def start_frame
|
15
|
+
@start_frame ||= Array.new(4) { 0 }
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
@
|
18
|
+
def end_frame
|
19
|
+
return @end_frame if @end_frame
|
21
20
|
|
22
|
-
# End frame must be at least
|
23
|
-
end_frame_bytes = (
|
21
|
+
# End frame must be at least length/2 bits long, and 32 bits (4 bytes) minimum.
|
22
|
+
end_frame_bytes = (length / 16.0).ceil
|
24
23
|
end_frame_bytes = 4 if end_frame_bytes < 4
|
25
24
|
|
26
25
|
# Use all 0's for end frame instead of 1's. Prevents extra pixel when using partial strip.
|
27
26
|
@end_frame = Array.new(end_frame_bytes) { 0 }
|
27
|
+
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
@
|
29
|
+
# This is BYTES per pixel, not bits per pixel.
|
30
|
+
# 0th byte is per-pixel brightness (PWM applied to all 3 colors).
|
31
|
+
def bpp
|
32
|
+
@bpp ||= 4
|
33
|
+
end
|
34
|
+
|
35
|
+
def buffer
|
36
|
+
@buffer ||= Array.new(length * bpp) { 0 }
|
37
|
+
end
|
33
38
|
|
39
|
+
attr_writer :buffer
|
40
|
+
|
41
|
+
before_initialize do
|
42
|
+
unless [Denko::SPI::Bus, Denko::SPI::BitBang].include? params[:bus].class
|
43
|
+
raise "APA102 must be connected to the output pin of a SPI bus"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
after_initialize do
|
34
48
|
# Default to max brightness.
|
35
49
|
self.brightness = 31
|
36
|
-
|
37
50
|
off
|
38
51
|
end
|
39
52
|
|
@@ -47,26 +60,26 @@ module Denko
|
|
47
60
|
@masked_brightness = 0b11100000 | @brightness
|
48
61
|
|
49
62
|
# Set brightness for all pixels.
|
50
|
-
(0
|
51
|
-
|
63
|
+
(0..length-1).each do |index|
|
64
|
+
buffer[index*bpp+0] = @masked_brightness
|
52
65
|
end
|
53
66
|
end
|
54
67
|
|
55
68
|
def []=(index, array)
|
56
69
|
# Per-pixel brightness control, as optional 3rd indexed element of array.
|
57
70
|
if array[3]
|
58
|
-
|
71
|
+
buffer[index*bpp+0] = 0b11100000 | array[3]
|
59
72
|
end
|
60
|
-
|
73
|
+
|
61
74
|
# APA102 uses BGR ordering.
|
62
|
-
|
63
|
-
|
64
|
-
|
75
|
+
buffer[index*bpp+1] = array[2]
|
76
|
+
buffer[index*bpp+2] = array[1]
|
77
|
+
buffer[index*bpp+3] = array[0]
|
65
78
|
end
|
66
79
|
|
67
80
|
def all_on
|
68
81
|
self.brightness = 31
|
69
|
-
|
82
|
+
self.buffer = buffer.each_slice(bpp).map { [@masked_brightness,255,255,255] }.flatten
|
70
83
|
show
|
71
84
|
end
|
72
85
|
|
@@ -76,11 +89,12 @@ module Denko
|
|
76
89
|
end
|
77
90
|
|
78
91
|
def clear
|
79
|
-
|
92
|
+
self.buffer = buffer.each_slice(bpp).map { [@masked_brightness,0,0,0] }.flatten
|
80
93
|
end
|
81
94
|
|
82
95
|
def show
|
83
|
-
|
96
|
+
data = start_frame + buffer + end_frame
|
97
|
+
bus.transfer(pin, write: data)
|
84
98
|
end
|
85
99
|
end
|
86
100
|
end
|
data/lib/denko/led/base.rb
CHANGED
@@ -2,11 +2,17 @@ module Denko
|
|
2
2
|
module LED
|
3
3
|
class Base < PulseIO::PWMOutput
|
4
4
|
def blink(interval=0.5)
|
5
|
-
|
5
|
+
self.blink_interval = interval
|
6
|
+
threaded_loop do
|
6
7
|
toggle
|
7
|
-
sleep
|
8
|
+
sleep @blink_interval
|
8
9
|
end
|
9
10
|
end
|
11
|
+
|
12
|
+
def blink_interval=(interval)
|
13
|
+
@blink_interval = interval
|
14
|
+
end
|
15
|
+
attr_reader :blink_interval
|
10
16
|
end
|
11
17
|
end
|
12
18
|
end
|