denko 0.13.6 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|