denko 0.13.0 → 0.13.2
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 +2 -4
- data/.github/workflows/build_esp32.yml +2 -3
- data/.github/workflows/build_esp8266.yml +2 -3
- data/.github/workflows/build_megaavr.yml +2 -4
- data/.github/workflows/build_ra4m1.yml +57 -0
- data/.github/workflows/build_rp2040.yml +2 -4
- data/.github/workflows/build_sam3x.yml +1 -3
- data/.github/workflows/build_samd.yml +2 -4
- data/CHANGELOG.md +60 -0
- data/DEPS_CLI.md +8 -6
- data/DEPS_IDE.md +9 -7
- data/HARDWARE.md +98 -75
- data/README.md +48 -59
- data/benchmarks/i2c_ssd1306_refresh.rb +74 -0
- data/examples/analog_io/ads1115.rb +57 -0
- data/examples/analog_io/ads1118.rb +8 -9
- data/examples/analog_io/dac_loopback.rb +6 -4
- data/examples/analog_io/input.rb +39 -36
- data/examples/connection/tcp.rb +1 -1
- data/examples/display/hd44780.rb +3 -3
- data/examples/display/ssd1306.rb +1 -1
- data/examples/pulse_io/buzzer.rb +40 -0
- data/examples/sensor/aht20.rb +1 -1
- data/lib/denko/analog_io/ads1115.rb +61 -0
- data/lib/denko/analog_io/ads1118.rb +10 -120
- data/lib/denko/analog_io/ads111x.rb +123 -0
- data/lib/denko/analog_io/output.rb +2 -1
- data/lib/denko/analog_io.rb +2 -0
- data/lib/denko/behaviors/bus_peripheral_addressed.rb +1 -1
- data/lib/denko/behaviors/component.rb +1 -1
- data/lib/denko/behaviors/input_pin.rb +3 -0
- data/lib/denko/behaviors/reader.rb +14 -13
- data/lib/denko/behaviors/single_pin.rb +1 -3
- data/lib/denko/behaviors/state.rb +1 -0
- data/lib/denko/behaviors/subcomponents.rb +2 -2
- data/lib/denko/board/core.rb +1 -1
- data/lib/denko/board/i2c.rb +1 -4
- data/lib/denko/board/map.rb +9 -0
- data/lib/denko/board/servo.rb +2 -6
- data/lib/denko/board.rb +32 -20
- data/lib/denko/connection/board_uart.rb +3 -3
- data/lib/denko/connection/flow_control.rb +10 -2
- data/lib/denko/digital_io/output.rb +1 -1
- data/lib/denko/display/hd44780.rb +18 -18
- data/lib/denko/led/seven_segment.rb +18 -19
- data/lib/denko/message.rb +6 -14
- data/lib/denko/one_wire/bus.rb +1 -1
- data/lib/denko/one_wire/{bus_enumeration.rb → bus_enumerator.rb} +16 -8
- data/lib/denko/one_wire/helper.rb +1 -1
- data/lib/denko/one_wire.rb +1 -1
- data/lib/denko/pulse_io/ir_transmitter.rb +1 -2
- data/lib/denko/sensor/ds18b20.rb +1 -1
- data/lib/denko/version.rb +1 -1
- data/lib/denko_cli/packages.rb +7 -1
- data/lib/denko_cli/targets.rb +8 -5
- data/lib/denko_cli/usage.txt +8 -4
- data/src/denko_ethernet.ino +15 -23
- data/src/denko_serial.ino +3 -14
- data/src/denko_wifi.ino +35 -50
- data/src/lib/Denko.cpp +23 -6
- data/src/lib/Denko.h +6 -16
- data/src/lib/DenkoCoreIO.cpp +3 -3
- data/src/lib/DenkoDefines.h +62 -16
- data/src/lib/DenkoEEPROM.cpp +9 -1
- data/src/lib/DenkoI2C.cpp +11 -9
- data/src/lib/DenkoLEDArray.cpp +1 -1
- data/target.yml +35 -1
- data/test/behaviors/reader_test.rb +8 -1
- data/test/board/helper_test.rb +0 -4
- data/test/display/hd44780_test.rb +10 -0
- data/test/led/seven_segment_test.rb +30 -8
- data/test/one_wire/bus_enumerator_test.rb +4 -0
- data/test/one_wire/helper_test.rb +5 -5
- data/test/sensor/ds18b20_test.rb +10 -0
- data/test/test_helper.rb +17 -2
- data/vendor/board-maps/.gitmodules +3 -0
- data/vendor/board-maps/BoardMap.h +40 -12
- data/vendor/board-maps/README.md +1 -0
- data/vendor/board-maps/lib/header_parser.rb +30 -5
- data/vendor/board-maps/run.rb +11 -1
- data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32S3.yml +6 -1
- data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32S3_NOPSRAM.yml +6 -1
- data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32_V2.yml +5 -1
- data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_N4R2.yml +20 -0
- data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32_PICO.yml +2 -1
- data/vendor/board-maps/yaml/ARTRONSHOP_RP2_NANO.yml +32 -0
- data/vendor/board-maps/yaml/AVR_CIRCUITPLAY.yml +1 -1
- data/vendor/board-maps/yaml/AVR_ESPLORA.yml +1 -1
- data/vendor/board-maps/yaml/AVR_INDUSTRIAL101.yml +1 -1
- data/vendor/board-maps/yaml/AVR_LEONARDO.yml +1 -1
- data/vendor/board-maps/yaml/AVR_LEONARDO_ETH.yml +1 -1
- data/vendor/board-maps/yaml/AVR_LILYPAD_USB.yml +1 -1
- data/vendor/board-maps/yaml/AVR_LININO_ONE.yml +1 -1
- data/vendor/board-maps/yaml/AVR_MICRO.yml +1 -1
- data/vendor/board-maps/yaml/AVR_ROBOT_CONTROL.yml +1 -1
- data/vendor/board-maps/yaml/AVR_ROBOT_MOTOR.yml +1 -1
- data/vendor/board-maps/yaml/AVR_YUN.yml +1 -1
- data/vendor/board-maps/yaml/AVR_YUNMINI.yml +1 -1
- data/vendor/board-maps/yaml/BPI_LEAF_S3.yml +11 -1
- data/vendor/board-maps/yaml/BeeMotionS3.yml +6 -1
- data/vendor/board-maps/yaml/Bee_Motion.yml +3 -0
- data/vendor/board-maps/yaml/Bee_S3.yml +1 -1
- data/vendor/board-maps/yaml/CHALLENGER_2040_WIFI6_BLE_RP2040.yml +42 -0
- data/vendor/board-maps/yaml/CYTRON_MAKER_FEATHER_AIOT_S3.yml +4 -1
- data/vendor/board-maps/yaml/CoreESP32.yml +5 -1
- data/vendor/board-maps/yaml/D1_MINI32.yml +10 -1
- data/vendor/board-maps/yaml/DENKY.yml +10 -1
- data/vendor/board-maps/yaml/DENKY_PICOV3.yml +10 -1
- data/vendor/board-maps/yaml/DENKY_WROOM32.yml +10 -1
- data/vendor/board-maps/yaml/DFROBOT_FIREBEETLE_2_ESP32E.yml +6 -1
- data/vendor/board-maps/yaml/DPU_ESP32.yml +10 -1
- data/vendor/board-maps/yaml/D_Duino_32.yml +9 -1
- data/vendor/board-maps/yaml/ESP32S2_DEV.yml +11 -1
- data/vendor/board-maps/yaml/ESP32S2_THING_PLUS.yml +11 -1
- data/vendor/board-maps/yaml/ESP32S2_USB.yml +11 -1
- data/vendor/board-maps/yaml/ESP32_DEV.yml +10 -1
- data/vendor/board-maps/yaml/ESP32_DEVKIT_LIPO.yml +10 -1
- data/vendor/board-maps/yaml/ESP32_IOT_REDBOARD.yml +10 -1
- data/vendor/board-maps/yaml/ESP32_PICO.yml +10 -1
- data/vendor/board-maps/yaml/ESP32_S3_BOX.yml +4 -1
- data/vendor/board-maps/yaml/ESP32_THING.yml +10 -1
- data/vendor/board-maps/yaml/ESP32_THING_PLUS.yml +4 -1
- data/vendor/board-maps/yaml/ESP32_THING_PLUS_C.yml +4 -1
- data/vendor/board-maps/yaml/ESP32_WROOM_DA.yml +10 -1
- data/vendor/board-maps/yaml/ESP32_WROVER_KIT.yml +10 -1
- data/vendor/board-maps/yaml/ESPECTRO32.yml +10 -1
- data/vendor/board-maps/yaml/ESPea32.yml +10 -1
- data/vendor/board-maps/yaml/ESPino32.yml +10 -1
- data/vendor/board-maps/yaml/FEATHERS2.yml +11 -1
- data/vendor/board-maps/yaml/FEATHERS2NEO.yml +2 -1
- data/vendor/board-maps/yaml/FEATHERS3.yml +3 -0
- data/vendor/board-maps/yaml/FEATHER_ESP32.yml +5 -1
- data/vendor/board-maps/yaml/FRANZININHO_WIFI.yml +11 -1
- data/vendor/board-maps/yaml/FRANZININHO_WIFI_MSC.yml +11 -1
- data/vendor/board-maps/yaml/FROG_ESP32.yml +10 -1
- data/vendor/board-maps/yaml/HEALTHYPI_4.yml +10 -1
- data/vendor/board-maps/yaml/HONEYLEMON.yml +10 -1
- data/vendor/board-maps/yaml/HORNBILL_ESP32_DEV.yml +10 -1
- data/vendor/board-maps/yaml/HORNBILL_ESP32_MINIMA.yml +4 -1
- data/vendor/board-maps/yaml/IMBRIOS_LOGSENS_V1P1.yml +5 -1
- data/vendor/board-maps/yaml/LILYGO_T_DISPLAY_S3.yml +7 -1
- data/vendor/board-maps/yaml/LOLIN32.yml +10 -1
- data/vendor/board-maps/yaml/LOLIN32_LITE.yml +10 -1
- data/vendor/board-maps/yaml/LOLIN_D32.yml +10 -1
- data/vendor/board-maps/yaml/LOLIN_D32_PRO.yml +10 -1
- data/vendor/board-maps/yaml/LOLIN_S2_MINI.yml +11 -1
- data/vendor/board-maps/yaml/LOLIN_S2_PICO.yml +11 -1
- data/vendor/board-maps/yaml/LOLIN_S3.yml +9 -1
- data/vendor/board-maps/yaml/LOLIN_S3_MINI.yml +9 -1
- data/vendor/board-maps/yaml/LOLIN_S3_PRO.yml +9 -1
- data/vendor/board-maps/yaml/LoPy.yml +11 -1
- data/vendor/board-maps/yaml/LoPy4.yml +11 -1
- data/vendor/board-maps/yaml/MAGTAG29_ESP32S2.yml +11 -1
- data/vendor/board-maps/yaml/METRO_ESP32S2.yml +11 -1
- data/vendor/board-maps/yaml/MGBOT_IOTIK32A.yml +10 -1
- data/vendor/board-maps/yaml/MGBOT_IOTIK32B.yml +10 -1
- data/vendor/board-maps/yaml/MH_ET_LIVE_ESP32DEVKIT.yml +10 -1
- data/vendor/board-maps/yaml/MH_ET_LIVE_ESP32MINIKIT.yml +10 -1
- data/vendor/board-maps/yaml/MICROS2.yml +11 -1
- data/vendor/board-maps/yaml/MINIMA.yml +15 -0
- data/vendor/board-maps/yaml/NANO32.yml +10 -1
- data/vendor/board-maps/yaml/Node32s.yml +10 -1
- data/vendor/board-maps/yaml/NodeMCU_32S.yml +10 -1
- data/vendor/board-maps/yaml/ONEHORSE_ESP32_DEV.yml +11 -1
- data/vendor/board-maps/yaml/PIMORONI_PLASMA2040.yml +29 -0
- data/vendor/board-maps/yaml/PORTENTA_C33.yml +28 -0
- data/vendor/board-maps/yaml/PROS3.yml +6 -1
- data/vendor/board-maps/yaml/PYCOM_GPY.yml +11 -1
- data/vendor/board-maps/yaml/Piranha.yml +7 -1
- data/vendor/board-maps/yaml/Pocket32.yml +10 -1
- data/vendor/board-maps/yaml/QUANTUM.yml +10 -1
- data/vendor/board-maps/yaml/REDPILL_ESP32S3.yml +11 -1
- data/vendor/board-maps/yaml/RMP.yml +11 -1
- data/vendor/board-maps/yaml/SAMD_CIRCUITPLAYGROUND_EXPRESS.yml +0 -1
- data/vendor/board-maps/yaml/SAM_DUE.yml +3 -1
- data/vendor/board-maps/yaml/SONOFF_DUALR3.yml +10 -1
- data/vendor/board-maps/yaml/TAMC_TERMOD_S3.yml +11 -1
- data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1262.yml +6 -1
- data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1268.yml +6 -1
- data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1276.yml +6 -1
- data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1278.yml +6 -1
- data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1280.yml +6 -1
- data/vendor/board-maps/yaml/TBeam.yml +6 -1
- data/vendor/board-maps/yaml/TINYPICO.yml +10 -1
- data/vendor/board-maps/yaml/TINYS2.yml +11 -1
- data/vendor/board-maps/yaml/TTGO_LoRa32_V1.yml +11 -1
- data/vendor/board-maps/yaml/TTGO_LoRa32_V2.yml +11 -1
- data/vendor/board-maps/yaml/TTGO_LoRa32_v21new.yml +11 -1
- data/vendor/board-maps/yaml/TTGO_T1.yml +10 -1
- data/vendor/board-maps/yaml/TTGO_T7_V13_Mini32.yml +10 -1
- data/vendor/board-maps/yaml/TTGO_T7_V14_Mini32.yml +10 -1
- data/vendor/board-maps/yaml/TWATCH_2020_V1.yml +0 -1
- data/vendor/board-maps/yaml/TWATCH_2020_V2.yml +0 -1
- data/vendor/board-maps/yaml/TWATCH_2020_V3.yml +0 -1
- data/vendor/board-maps/yaml/TWATCH_BASE.yml +0 -1
- data/vendor/board-maps/yaml/TWatch.yml +0 -1
- data/vendor/board-maps/yaml/UBLOX_NINA_W10.yml +10 -1
- data/vendor/board-maps/yaml/UNOWIFIR4.yml +17 -0
- data/vendor/board-maps/yaml/WIPY3.yml +11 -1
- data/vendor/board-maps/yaml/XIAO_ESP32S3.yml +2 -1
- data/vendor/board-maps/yaml/connaxio_espoir.yml +7 -1
- data/vendor/board-maps/yaml/esp32vn_iot_uno.yml +10 -1
- data/vendor/board-maps/yaml/heltec_wifi_32_lora_V3.yml +11 -1
- data/vendor/board-maps/yaml/heltec_wifi_kit_32.yml +11 -1
- data/vendor/board-maps/yaml/heltec_wifi_kit_32_V3.yml +11 -1
- data/vendor/board-maps/yaml/heltec_wifi_lora_32.yml +10 -1
- data/vendor/board-maps/yaml/heltec_wifi_lora_32_V2.yml +10 -1
- data/vendor/board-maps/yaml/heltec_wireless_stick.yml +10 -1
- data/vendor/board-maps/yaml/heltec_wireless_stick_LITE.yml +10 -1
- data/vendor/board-maps/yaml/openkb.yml +11 -1
- data/vendor/board-maps/yaml/roboheart_hercules.yml +10 -1
- data/vendor/board-maps/yaml/sensesiot_weizen.yml +10 -1
- data/vendor/board-maps/yaml/uPesy_WROOM.yml +10 -1
- data/vendor/board-maps/yaml/uPesy_WROVER.yml +10 -1
- data/vendor/board-maps/yaml/unphone8.yml +11 -1
- data/vendor/board-maps/yaml/unphone9.yml +11 -1
- metadata +15 -3
@@ -12,28 +12,29 @@ module Denko
|
|
12
12
|
end
|
13
13
|
|
14
14
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
15
|
+
# Take a proc/lambda/method as the first agrument and use it to read.
|
16
|
+
# Arguments are passed through, allowing dynamic read methods to be defined.
|
17
|
+
# Eg. send commands (in args) to a bus, then wait for data read back.
|
18
|
+
#
|
19
|
+
# Block given is added as a one-time callback in the :read key, and
|
20
|
+
# the curent thread waits until data is received. Returns the result of
|
21
|
+
# calling #pre_callback_filter with the data.
|
19
22
|
#
|
20
|
-
|
21
|
-
#
|
22
|
-
def read_using(method, *args, **kwargs, &block)
|
23
|
+
def read_using(reader, *args, **kwargs, &block)
|
23
24
|
add_callback(:read, &block) if block_given?
|
24
25
|
|
25
|
-
|
26
|
+
return_value = nil
|
26
27
|
add_callback(:read) do |filtered_data|
|
27
|
-
|
28
|
+
return_value = filtered_data
|
28
29
|
end
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
reader.call(*args, **kwargs)
|
32
|
+
wait_for_read
|
32
33
|
|
33
|
-
|
34
|
+
return_value
|
34
35
|
end
|
35
36
|
|
36
|
-
def
|
37
|
+
def wait_for_read
|
37
38
|
loop do
|
38
39
|
break if !callbacks[:read]
|
39
40
|
sleep 0.001
|
@@ -11,15 +11,13 @@ module Denko
|
|
11
11
|
|
12
12
|
protected
|
13
13
|
|
14
|
-
attr_writer :pin
|
15
|
-
|
16
14
|
def convert_pins(options={})
|
17
15
|
raise ArgumentError, 'a pin is required for this component' unless options[:pin]
|
18
16
|
options[:pin] = board.convert_pin(options[:pin])
|
19
17
|
end
|
20
18
|
|
21
19
|
def initialize_pins(options={})
|
22
|
-
|
20
|
+
@pin = options[:pin]
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
@@ -10,8 +10,6 @@ module Denko
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def add_component(component)
|
13
|
-
components << component
|
14
|
-
|
15
13
|
if component.respond_to?(:pin) && component.pin.class == Integer
|
16
14
|
unless single_pin_components[component.pin]
|
17
15
|
single_pin_components[component.pin] = component
|
@@ -20,6 +18,8 @@ module Denko
|
|
20
18
|
"already in use by: #{single_pin_components[component.pin]}"
|
21
19
|
end
|
22
20
|
end
|
21
|
+
|
22
|
+
components << component
|
23
23
|
end
|
24
24
|
|
25
25
|
def remove_component(component)
|
data/lib/denko/board/core.rb
CHANGED
@@ -119,7 +119,7 @@ module Denko
|
|
119
119
|
# CMD = 95
|
120
120
|
def set_register_divider(value)
|
121
121
|
unless DIVIDERS.include?(value)
|
122
|
-
raise ArgumentError, "error in divider: #{
|
122
|
+
raise ArgumentError, "error in divider: #{value}. Should be one of: #{DIVIDERS.inspect}"
|
123
123
|
end
|
124
124
|
write Message.encode(command: 95, value: value)
|
125
125
|
end
|
data/lib/denko/board/i2c.rb
CHANGED
@@ -7,10 +7,7 @@ module Denko
|
|
7
7
|
3400000 => 0x03,
|
8
8
|
}
|
9
9
|
|
10
|
-
|
11
|
-
def i2c_limit
|
12
|
-
32
|
13
|
-
end
|
10
|
+
attr_reader :i2c_limit
|
14
11
|
|
15
12
|
def i2c_convert_frequency(freq)
|
16
13
|
# Default to 100 kHz.
|
data/lib/denko/board/map.rb
CHANGED
@@ -6,10 +6,19 @@ module Denko
|
|
6
6
|
|
7
7
|
attr_reader :map
|
8
8
|
|
9
|
+
def substitute_zero_pins
|
10
|
+
["SDA", "SCL", "MOSI", "MISO", "SCK", "SS"].each do |name|
|
11
|
+
symbol = name.to_sym
|
12
|
+
zero_symbol = (name + "0").to_sym
|
13
|
+
@map[symbol] = @map[zero_symbol] if (@map[zero_symbol] && !@map[symbol])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
9
17
|
def load_map(board_name)
|
10
18
|
if board_name
|
11
19
|
map_path = File.join(MAPS_FOLDER, "#{board_name}.yml")
|
12
20
|
@map = YAML.load_file(map_path)
|
21
|
+
substitute_zero_pins
|
13
22
|
else
|
14
23
|
@map = nil
|
15
24
|
end
|
data/lib/denko/board/servo.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
module Denko
|
2
2
|
class Board
|
3
3
|
# CMD = 10
|
4
|
-
def servo_toggle(pin, value=:off,
|
5
|
-
options[:min] ||= 544
|
6
|
-
options[:max] ||= 2400
|
7
|
-
aux = pack :uint16, [options[:min], options[:max]]
|
8
|
-
|
4
|
+
def servo_toggle(pin, value=:off, min: 544, max: 2400)
|
9
5
|
write Message.encode command: 10,
|
10
6
|
pin: pin,
|
11
7
|
value: (value == :off) ? 0 : 1,
|
12
|
-
aux_message:
|
8
|
+
aux_message: pack(:uint16, [min, max])
|
13
9
|
end
|
14
10
|
|
15
11
|
# CMD = 11
|
data/lib/denko/board.rb
CHANGED
@@ -1,42 +1,54 @@
|
|
1
1
|
# Require all files in board folder relative to this file.
|
2
|
-
Dir["#{Denko.root}/lib/denko/board/*.rb"].each {|file| require file }
|
2
|
+
Dir["#{Denko.root}/lib/denko/board/*.rb"].each { |file| require file }
|
3
3
|
|
4
4
|
module Denko
|
5
5
|
class Board
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :name, :version, :serial_buffer_size, :aux_limit, :eeprom_length
|
7
7
|
attr_reader :low, :high, :analog_write_high, :analog_read_high
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
#
|
11
|
-
@
|
12
|
-
ack =
|
13
|
-
@name, @version, @aux_limit, @eeprom_length = ack.split(",")
|
9
|
+
def initialize(transport, options={})
|
10
|
+
# Shake hands
|
11
|
+
@transport = transport
|
12
|
+
ack = transport.handshake
|
14
13
|
|
15
|
-
#
|
16
|
-
@name
|
17
|
-
|
18
|
-
|
14
|
+
# Split handshake acknowledgement into separate values.
|
15
|
+
@name, @version, @serial_buffer_size, @aux_limit, @eeprom_length, @i2c_limit = ack.split(",")
|
16
|
+
|
17
|
+
# Tell transport how much serial buffer the board has, for flow control.
|
18
|
+
@serial_buffer_size = @serial_buffer_size.to_i
|
19
|
+
raise StandardError, "no serial buffer size given in handshake" if @serial_buffer_size < 1
|
20
|
+
@transport.remote_buffer_size = @serial_buffer_size
|
21
|
+
|
22
|
+
# Load board map by name.
|
23
|
+
@name = nil if @name.empty?
|
24
|
+
load_map(@name)
|
19
25
|
|
20
26
|
# Leave room for null termination of aux messages.
|
21
27
|
@aux_limit = @aux_limit.to_i - 1
|
22
28
|
|
23
|
-
#
|
24
|
-
|
29
|
+
# Set I2C transaction size limit. Safe minimum is 32.
|
30
|
+
# This makes I2C fail silently if board does not implement.
|
31
|
+
@i2c_limit = @i2c_limit.to_i
|
32
|
+
@i2c_limit = 32 if @i2c_limit == 0
|
33
|
+
|
34
|
+
# Remaining settings
|
35
|
+
@version = nil if @version.empty?
|
36
|
+
@eeprom_length = @eeprom_length.to_i
|
25
37
|
|
26
|
-
#
|
27
|
-
|
38
|
+
# Transport calls #update on board when data is received.
|
39
|
+
transport.add_observer(self)
|
28
40
|
|
29
41
|
# Set digital and analog IO levels.
|
30
42
|
@low = 0
|
31
43
|
@high = 1
|
32
44
|
self.analog_write_resolution = options[:write_bits] || 8
|
33
|
-
self.analog_read_resolution
|
45
|
+
self.analog_read_resolution = options[:read_bits] || 10
|
34
46
|
end
|
35
47
|
|
36
48
|
def finish_write
|
37
|
-
sleep 0.001 while @
|
49
|
+
sleep 0.001 while @transport.writing?
|
38
50
|
write "\n91\n"
|
39
|
-
sleep 0.001 while @
|
51
|
+
sleep 0.001 while @transport.writing?
|
40
52
|
end
|
41
53
|
|
42
54
|
def analog_write_resolution=(value)
|
@@ -64,7 +76,7 @@ module Denko
|
|
64
76
|
alias :adc_high :analog_read_high
|
65
77
|
|
66
78
|
def write(msg)
|
67
|
-
@
|
79
|
+
@transport.write(msg)
|
68
80
|
end
|
69
81
|
|
70
82
|
#
|
@@ -78,7 +90,7 @@ module Denko
|
|
78
90
|
# signal is read by the TxRx, telling it to resume transmisison.
|
79
91
|
#
|
80
92
|
def write_and_halt(msg)
|
81
|
-
@
|
93
|
+
@transport.write(msg, true)
|
82
94
|
end
|
83
95
|
|
84
96
|
#
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Denko
|
2
2
|
module Connection
|
3
3
|
class BoardUART < Base
|
4
|
-
|
4
|
+
DEFAULT_BAUD = 115200
|
5
5
|
|
6
|
-
def initialize(uart,
|
6
|
+
def initialize(uart, baud: DEFAULT_BAUD)
|
7
7
|
@uart = uart
|
8
|
-
@uart.start(
|
8
|
+
@uart.start(baud)
|
9
9
|
end
|
10
10
|
|
11
11
|
def baud
|
@@ -1,11 +1,19 @@
|
|
1
1
|
module Denko
|
2
2
|
module Connection
|
3
3
|
module FlowControl
|
4
|
-
BOARD_BUFFER = 63
|
5
4
|
SLEEP_TIME = 0.001
|
6
5
|
|
6
|
+
# Let Board object tell us the remote buffer size after parsing handshake.
|
7
|
+
def remote_buffer_size=(size)
|
8
|
+
@transit_mutex.synchronize { @remote_buffer_size = size }
|
9
|
+
end
|
10
|
+
|
7
11
|
def initialize(*args)
|
8
12
|
super(*args)
|
13
|
+
# Start with minimum known buffer size. Board will update after handshake.
|
14
|
+
# WARNING: If not updated, and ack threshold on the board is > minimum,
|
15
|
+
# FlowControl will stop sending data, and appear to hang. Fix this.
|
16
|
+
@remote_buffer_size = 63
|
9
17
|
reset_flow_control
|
10
18
|
tx_resume
|
11
19
|
end
|
@@ -93,7 +101,7 @@ module Denko
|
|
93
101
|
# Keep transit mutex as short as possible, by only reserving bytes, and writing outside.
|
94
102
|
def reserve_bytes(length)
|
95
103
|
@transit_mutex.synchronize do
|
96
|
-
available =
|
104
|
+
available = @remote_buffer_size - @transit_bytes
|
97
105
|
reserved = (length > available) ? available : length
|
98
106
|
@transit_bytes += reserved
|
99
107
|
reserved
|
@@ -63,7 +63,7 @@ module Denko
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def after_initialize(options={})
|
66
|
-
super(options)
|
66
|
+
super(options)
|
67
67
|
|
68
68
|
# Default to 16x2 display if no options given.
|
69
69
|
@columns = options[:columns] || 16
|
@@ -212,7 +212,7 @@ module Denko
|
|
212
212
|
send(byte, board.low)
|
213
213
|
end
|
214
214
|
|
215
|
-
def write(byte)
|
215
|
+
def write(byte)
|
216
216
|
send(byte, board.high)
|
217
217
|
end
|
218
218
|
|
@@ -229,27 +229,27 @@ module Denko
|
|
229
229
|
end
|
230
230
|
|
231
231
|
def write4(bits)
|
232
|
-
d4.write bits[4]
|
233
|
-
d5.write bits[5]
|
234
|
-
d6.write bits[6]
|
235
|
-
d7.write bits[7]
|
232
|
+
d4.write bits[4].to_i
|
233
|
+
d5.write bits[5].to_i
|
234
|
+
d6.write bits[6].to_i
|
235
|
+
d7.write bits[7].to_i
|
236
236
|
pulse_enable
|
237
|
-
d4.write bits[0]
|
238
|
-
d5.write bits[1]
|
239
|
-
d6.write bits[2]
|
240
|
-
d7.write bits[3]
|
237
|
+
d4.write bits[0].to_i
|
238
|
+
d5.write bits[1].to_i
|
239
|
+
d6.write bits[2].to_i
|
240
|
+
d7.write bits[3].to_i
|
241
241
|
pulse_enable
|
242
242
|
end
|
243
243
|
|
244
244
|
def write8(bits)
|
245
|
-
d0.write bits[0]
|
246
|
-
d1.write bits[1]
|
247
|
-
d2.write bits[2]
|
248
|
-
d3.write bits[3]
|
249
|
-
d4.write bits[4]
|
250
|
-
d5.write bits[5]
|
251
|
-
d6.write bits[6]
|
252
|
-
d7.write bits[7]
|
245
|
+
d0.write bits[0].to_i
|
246
|
+
d1.write bits[1].to_i
|
247
|
+
d2.write bits[2].to_i
|
248
|
+
d3.write bits[3].to_i
|
249
|
+
d4.write bits[4].to_i
|
250
|
+
d5.write bits[5].to_i
|
251
|
+
d6.write bits[6].to_i
|
252
|
+
d7.write bits[7].to_i
|
253
253
|
pulse_enable
|
254
254
|
end
|
255
255
|
|
@@ -3,6 +3,9 @@ module Denko
|
|
3
3
|
class SevenSegment
|
4
4
|
include Behaviors::MultiPin
|
5
5
|
|
6
|
+
ALL_OFF = [0,0,0,0,0,0,0]
|
7
|
+
BLANK = " "
|
8
|
+
|
6
9
|
def initialize_pins(options={})
|
7
10
|
[:a, :b, :c, :d, :e, :f, :g].each do |symbol|
|
8
11
|
proxy_pin(symbol, DigitalIO::Output)
|
@@ -20,28 +23,30 @@ module Denko
|
|
20
23
|
attr_reader :segments
|
21
24
|
|
22
25
|
def clear
|
23
|
-
|
24
|
-
pin.low if cathode
|
25
|
-
pin.high if anode
|
26
|
-
end
|
26
|
+
write(BLANK)
|
27
27
|
end
|
28
28
|
|
29
|
-
def display(
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
def display(string)
|
30
|
+
on unless on?
|
31
|
+
string = string.to_s.upcase
|
32
|
+
(string.length > 1) ? scroll(string) : write(string)
|
33
33
|
end
|
34
34
|
|
35
35
|
def on
|
36
36
|
anode.high if anode
|
37
37
|
cathode.low if cathode
|
38
|
+
@on = true
|
38
39
|
end
|
39
40
|
|
40
41
|
def off
|
41
42
|
anode.low if anode
|
42
43
|
cathode.high if cathode
|
44
|
+
@on = false
|
43
45
|
end
|
44
46
|
|
47
|
+
def on?; @on; end
|
48
|
+
def off?; !@on; end
|
49
|
+
|
45
50
|
CHARACTERS = {
|
46
51
|
'0' => [1,1,1,1,1,1,0],
|
47
52
|
'1' => [0,1,1,0,0,0,0],
|
@@ -87,22 +92,16 @@ module Denko
|
|
87
92
|
private
|
88
93
|
|
89
94
|
def write(char)
|
90
|
-
bits = CHARACTERS[char
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
bits.each_with_index do |bit, index|
|
95
|
-
if anode
|
96
|
-
bit == 0 ? bit = 1 : bit = 0
|
97
|
-
end
|
98
|
-
segments[index].write(bit) unless (segments[index].state == bit)
|
99
|
-
end
|
95
|
+
bits = CHARACTERS[char] || ALL_OFF
|
96
|
+
bits.each_with_index do |bit, index|
|
97
|
+
bit = 1^bit if anode
|
98
|
+
segments[index].write(bit) unless (segments[index].state == bit)
|
100
99
|
end
|
101
100
|
end
|
102
101
|
|
103
102
|
def scroll(string)
|
104
103
|
string.chars.each do |char|
|
105
|
-
|
104
|
+
write(char)
|
106
105
|
sleep(0.5)
|
107
106
|
end
|
108
107
|
end
|
data/lib/denko/message.rb
CHANGED
@@ -57,7 +57,7 @@ module Denko
|
|
57
57
|
message = "#{command}#{message}\n"
|
58
58
|
end
|
59
59
|
|
60
|
-
def self.pack(type, data,
|
60
|
+
def self.pack(type, data, min: nil, max: nil)
|
61
61
|
# Always pack as little endian.
|
62
62
|
template = case type
|
63
63
|
when :uint64 then 'Q<*'
|
@@ -70,20 +70,12 @@ module Denko
|
|
70
70
|
# Can pass a single integer to get packed if we always [] then flatten.
|
71
71
|
str = [data].flatten.pack(template)
|
72
72
|
|
73
|
-
#
|
74
|
-
if
|
75
|
-
(
|
76
|
-
str = str + "\x00"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
if options[:min] && str.length < options[:min]
|
81
|
-
raise ArgumentError, "too few bytes given (expected at least #{options[:min]})"
|
73
|
+
# Enforce min and max.
|
74
|
+
if min && str.length < min
|
75
|
+
raise ArgumentError, "too few bytes given (expected at least #{min})"
|
82
76
|
end
|
83
|
-
|
84
|
-
|
85
|
-
if options[:max] && str.length > options[:max]
|
86
|
-
raise ArgumentError, "too many bytes given (expected at most #{options[:max]})"
|
77
|
+
if max && str.length > max
|
78
|
+
raise ArgumentError, "too many bytes given (expected at most #{max})"
|
87
79
|
end
|
88
80
|
|
89
81
|
str
|
data/lib/denko/one_wire/bus.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Denko
|
2
2
|
module OneWire
|
3
|
-
module
|
3
|
+
module BusEnumerator
|
4
|
+
include Constants
|
5
|
+
|
4
6
|
def _search(branch_mask)
|
5
7
|
reset
|
6
8
|
write(SEARCH_ROM)
|
@@ -42,12 +44,12 @@ module Denko
|
|
42
44
|
def parse_search_result(result)
|
43
45
|
address, complement = split_search_result(result)
|
44
46
|
|
45
|
-
raise "CRC error during OneWire search" unless Helper.crc_check(address)
|
46
|
-
|
47
47
|
if (address & complement) > 0
|
48
48
|
raise "OneWire device not connected or disconnected during search"
|
49
49
|
end
|
50
50
|
|
51
|
+
raise "CRC error during OneWire search" unless Helper.crc(address)
|
52
|
+
|
51
53
|
# Gives 0 at every discrepancy we didn't write 1 for on this search.
|
52
54
|
new_discrepancies = address ^ complement
|
53
55
|
|
@@ -73,12 +75,18 @@ module Denko
|
|
73
75
|
[address, complement]
|
74
76
|
end
|
75
77
|
|
76
|
-
#
|
78
|
+
#
|
79
|
+
# Set FAMILY_CODE in peripheral class, and add the class to this array
|
80
|
+
# for the class to be identified during search.
|
81
|
+
#
|
82
|
+
PERIPHERAL_CLASSES = [
|
83
|
+
Sensor::DS18B20,
|
84
|
+
]
|
85
|
+
|
77
86
|
def family_lookup(family_code)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
return obj if obj::FAMILY_CODE == family_code
|
87
|
+
PERIPHERAL_CLASSES.each do |klass|
|
88
|
+
if (klass.const_defined? "FAMILY_CODE")
|
89
|
+
return klass if klass::FAMILY_CODE == family_code
|
82
90
|
end
|
83
91
|
end
|
84
92
|
return nil
|
data/lib/denko/one_wire.rb
CHANGED
@@ -2,7 +2,7 @@ module Denko
|
|
2
2
|
module OneWire
|
3
3
|
autoload :Constants, "#{__dir__}/one_wire/constants"
|
4
4
|
autoload :Helper, "#{__dir__}/one_wire/helper"
|
5
|
-
autoload :
|
5
|
+
autoload :BusEnumerator, "#{__dir__}/one_wire/bus_enumerator"
|
6
6
|
autoload :Bus, "#{__dir__}/one_wire/bus"
|
7
7
|
autoload :Peripheral, "#{__dir__}/one_wire/peripheral"
|
8
8
|
end
|
@@ -3,7 +3,7 @@ module Denko
|
|
3
3
|
class IRTransmitter
|
4
4
|
include Behaviors::OutputPin
|
5
5
|
|
6
|
-
def emit(pulses=[],
|
6
|
+
def emit(pulses=[], frequency: 38)
|
7
7
|
if pulses.length > 256 || pulses.length < 1
|
8
8
|
raise ArgumentError, 'wrong number of IR pulses (expected 1 to 256)'
|
9
9
|
end
|
@@ -14,7 +14,6 @@ module Denko
|
|
14
14
|
raise ArgumentError, 'pulse too long (max 65535 ms)' if pulse > 65535
|
15
15
|
end
|
16
16
|
|
17
|
-
frequency = options[:frequency] || 38
|
18
17
|
board.infrared_emit(pin, frequency, pulses)
|
19
18
|
end
|
20
19
|
end
|
data/lib/denko/sensor/ds18b20.rb
CHANGED
@@ -47,7 +47,7 @@ module Denko
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def pre_callback_filter(bytes)
|
50
|
-
return { crc_error: true } unless Helper.
|
50
|
+
return { crc_error: true } unless OneWire::Helper.crc(bytes)
|
51
51
|
@resolution = decode_resolution(bytes)
|
52
52
|
|
53
53
|
decode_temperature(bytes).merge(raw: bytes)
|
data/lib/denko/version.rb
CHANGED
data/lib/denko_cli/packages.rb
CHANGED
@@ -12,10 +12,16 @@ PACKAGES = {
|
|
12
12
|
"Denko.cpp",
|
13
13
|
"DenkoCoreIO.cpp",
|
14
14
|
"DenkoPulseInput.cpp",
|
15
|
-
"DenkoEEPROM.cpp",
|
16
15
|
"../../vendor/board-maps/BoardMap.h",
|
17
16
|
]
|
18
17
|
},
|
18
|
+
eeprom: {
|
19
|
+
description: "Built-in EEPROM support",
|
20
|
+
directive: "DENKO_EEPROM",
|
21
|
+
files: [
|
22
|
+
"DenkoEEPROM.cpp",
|
23
|
+
]
|
24
|
+
},
|
19
25
|
one_wire: {
|
20
26
|
description: "OneWire bus support",
|
21
27
|
directive: "DENKO_ONE_WIRE",
|
data/lib/denko_cli/targets.rb
CHANGED
@@ -11,14 +11,17 @@ class DenkoCLI::Generator
|
|
11
11
|
mega168: [:core, :one_wire, :tone, :i2c, :spi, :servo],
|
12
12
|
|
13
13
|
# Other ATmega chips do everything.
|
14
|
-
# Add bit bang serial for 328p / UNO since
|
14
|
+
# Add bit bang serial for 328p / UNO since it has no extra hardware UART.
|
15
15
|
mega: STANDARD_PACKAGES + [:uart_bb],
|
16
16
|
|
17
|
-
# No tone or
|
18
|
-
sam3x: STANDARD_PACKAGES - [:tone, :ir_out],
|
17
|
+
# No tone, infrared or EEPROM on SAM3X / Due.
|
18
|
+
sam3x: STANDARD_PACKAGES - [:tone, :ir_out, :eeprom],
|
19
19
|
|
20
|
-
#
|
21
|
-
samd: STANDARD_PACKAGES,
|
20
|
+
# No EEPROM on SAMD / Zero.
|
21
|
+
samd: STANDARD_PACKAGES - [:eeprom],
|
22
|
+
|
23
|
+
# No IR out and WS2812 on the UNO R4. WS2812 compiles but doesn't work.
|
24
|
+
ra4m1: STANDARD_PACKAGES - [:ir_out, :led_array],
|
22
25
|
|
23
26
|
# ESP8266 + ESP32 use a different IR library.
|
24
27
|
esp8266: STANDARD_PACKAGES - [:ir_out] + [:ir_out_esp],
|