denko 0.13.1 → 0.13.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_avr.yml +2 -4
  3. data/.github/workflows/build_esp32.yml +2 -3
  4. data/.github/workflows/build_esp8266.yml +2 -3
  5. data/.github/workflows/build_megaavr.yml +2 -4
  6. data/.github/workflows/build_ra4m1.yml +57 -0
  7. data/.github/workflows/build_rp2040.yml +2 -4
  8. data/.github/workflows/build_sam3x.yml +1 -3
  9. data/.github/workflows/build_samd.yml +2 -4
  10. data/CHANGELOG.md +60 -0
  11. data/DEPS_CLI.md +8 -6
  12. data/DEPS_IDE.md +9 -7
  13. data/HARDWARE.md +90 -74
  14. data/README.md +19 -28
  15. data/benchmarks/i2c_ssd1306_refresh.rb +74 -0
  16. data/examples/analog_io/ads1115.rb +57 -0
  17. data/examples/analog_io/ads1118.rb +8 -9
  18. data/examples/analog_io/dac_loopback.rb +6 -4
  19. data/examples/analog_io/input.rb +39 -36
  20. data/examples/connection/tcp.rb +1 -1
  21. data/examples/display/hd44780.rb +3 -3
  22. data/examples/display/ssd1306.rb +1 -1
  23. data/examples/pulse_io/buzzer.rb +40 -0
  24. data/lib/denko/analog_io/ads1115.rb +61 -0
  25. data/lib/denko/analog_io/ads1118.rb +10 -120
  26. data/lib/denko/analog_io/ads111x.rb +123 -0
  27. data/lib/denko/analog_io/output.rb +2 -1
  28. data/lib/denko/analog_io.rb +2 -0
  29. data/lib/denko/behaviors/reader.rb +14 -13
  30. data/lib/denko/behaviors/subcomponents.rb +2 -2
  31. data/lib/denko/board/core.rb +1 -1
  32. data/lib/denko/board/i2c.rb +1 -4
  33. data/lib/denko/board/map.rb +9 -0
  34. data/lib/denko/board/servo.rb +2 -6
  35. data/lib/denko/board.rb +32 -20
  36. data/lib/denko/connection/board_uart.rb +3 -3
  37. data/lib/denko/connection/flow_control.rb +10 -2
  38. data/lib/denko/digital_io/output.rb +1 -1
  39. data/lib/denko/display/hd44780.rb +18 -18
  40. data/lib/denko/led/seven_segment.rb +18 -19
  41. data/lib/denko/message.rb +6 -14
  42. data/lib/denko/pulse_io/ir_transmitter.rb +1 -2
  43. data/lib/denko/version.rb +1 -1
  44. data/lib/denko_cli/packages.rb +7 -1
  45. data/lib/denko_cli/targets.rb +8 -5
  46. data/lib/denko_cli/usage.txt +8 -4
  47. data/src/denko_ethernet.ino +15 -23
  48. data/src/denko_serial.ino +3 -14
  49. data/src/denko_wifi.ino +35 -50
  50. data/src/lib/Denko.cpp +23 -6
  51. data/src/lib/Denko.h +6 -16
  52. data/src/lib/DenkoCoreIO.cpp +3 -3
  53. data/src/lib/DenkoDefines.h +62 -16
  54. data/src/lib/DenkoEEPROM.cpp +9 -1
  55. data/src/lib/DenkoI2C.cpp +11 -9
  56. data/src/lib/DenkoLEDArray.cpp +1 -1
  57. data/target.yml +35 -1
  58. data/test/behaviors/reader_test.rb +8 -1
  59. data/test/board/helper_test.rb +0 -4
  60. data/test/display/hd44780_test.rb +10 -0
  61. data/test/led/seven_segment_test.rb +30 -8
  62. data/test/test_helper.rb +17 -2
  63. data/vendor/board-maps/.gitmodules +3 -0
  64. data/vendor/board-maps/BoardMap.h +40 -12
  65. data/vendor/board-maps/README.md +1 -0
  66. data/vendor/board-maps/lib/header_parser.rb +30 -5
  67. data/vendor/board-maps/run.rb +11 -1
  68. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32S3.yml +6 -1
  69. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32S3_NOPSRAM.yml +6 -1
  70. data/vendor/board-maps/yaml/ADAFRUIT_FEATHER_ESP32_V2.yml +5 -1
  71. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32S3_N4R2.yml +20 -0
  72. data/vendor/board-maps/yaml/ADAFRUIT_QTPY_ESP32_PICO.yml +2 -1
  73. data/vendor/board-maps/yaml/ARTRONSHOP_RP2_NANO.yml +32 -0
  74. data/vendor/board-maps/yaml/AVR_CIRCUITPLAY.yml +1 -1
  75. data/vendor/board-maps/yaml/AVR_ESPLORA.yml +1 -1
  76. data/vendor/board-maps/yaml/AVR_INDUSTRIAL101.yml +1 -1
  77. data/vendor/board-maps/yaml/AVR_LEONARDO.yml +1 -1
  78. data/vendor/board-maps/yaml/AVR_LEONARDO_ETH.yml +1 -1
  79. data/vendor/board-maps/yaml/AVR_LILYPAD_USB.yml +1 -1
  80. data/vendor/board-maps/yaml/AVR_LININO_ONE.yml +1 -1
  81. data/vendor/board-maps/yaml/AVR_MICRO.yml +1 -1
  82. data/vendor/board-maps/yaml/AVR_ROBOT_CONTROL.yml +1 -1
  83. data/vendor/board-maps/yaml/AVR_ROBOT_MOTOR.yml +1 -1
  84. data/vendor/board-maps/yaml/AVR_YUN.yml +1 -1
  85. data/vendor/board-maps/yaml/AVR_YUNMINI.yml +1 -1
  86. data/vendor/board-maps/yaml/BPI_LEAF_S3.yml +11 -1
  87. data/vendor/board-maps/yaml/BeeMotionS3.yml +6 -1
  88. data/vendor/board-maps/yaml/Bee_Motion.yml +3 -0
  89. data/vendor/board-maps/yaml/Bee_S3.yml +1 -1
  90. data/vendor/board-maps/yaml/CHALLENGER_2040_WIFI6_BLE_RP2040.yml +42 -0
  91. data/vendor/board-maps/yaml/CYTRON_MAKER_FEATHER_AIOT_S3.yml +4 -1
  92. data/vendor/board-maps/yaml/CoreESP32.yml +5 -1
  93. data/vendor/board-maps/yaml/D1_MINI32.yml +10 -1
  94. data/vendor/board-maps/yaml/DENKY.yml +10 -1
  95. data/vendor/board-maps/yaml/DENKY_PICOV3.yml +10 -1
  96. data/vendor/board-maps/yaml/DENKY_WROOM32.yml +10 -1
  97. data/vendor/board-maps/yaml/DFROBOT_FIREBEETLE_2_ESP32E.yml +6 -1
  98. data/vendor/board-maps/yaml/DPU_ESP32.yml +10 -1
  99. data/vendor/board-maps/yaml/D_Duino_32.yml +9 -1
  100. data/vendor/board-maps/yaml/ESP32S2_DEV.yml +11 -1
  101. data/vendor/board-maps/yaml/ESP32S2_THING_PLUS.yml +11 -1
  102. data/vendor/board-maps/yaml/ESP32S2_USB.yml +11 -1
  103. data/vendor/board-maps/yaml/ESP32_DEV.yml +10 -1
  104. data/vendor/board-maps/yaml/ESP32_DEVKIT_LIPO.yml +10 -1
  105. data/vendor/board-maps/yaml/ESP32_IOT_REDBOARD.yml +10 -1
  106. data/vendor/board-maps/yaml/ESP32_PICO.yml +10 -1
  107. data/vendor/board-maps/yaml/ESP32_S3_BOX.yml +4 -1
  108. data/vendor/board-maps/yaml/ESP32_THING.yml +10 -1
  109. data/vendor/board-maps/yaml/ESP32_THING_PLUS.yml +4 -1
  110. data/vendor/board-maps/yaml/ESP32_THING_PLUS_C.yml +4 -1
  111. data/vendor/board-maps/yaml/ESP32_WROOM_DA.yml +10 -1
  112. data/vendor/board-maps/yaml/ESP32_WROVER_KIT.yml +10 -1
  113. data/vendor/board-maps/yaml/ESPECTRO32.yml +10 -1
  114. data/vendor/board-maps/yaml/ESPea32.yml +10 -1
  115. data/vendor/board-maps/yaml/ESPino32.yml +10 -1
  116. data/vendor/board-maps/yaml/FEATHERS2.yml +11 -1
  117. data/vendor/board-maps/yaml/FEATHERS2NEO.yml +2 -1
  118. data/vendor/board-maps/yaml/FEATHERS3.yml +3 -0
  119. data/vendor/board-maps/yaml/FEATHER_ESP32.yml +5 -1
  120. data/vendor/board-maps/yaml/FRANZININHO_WIFI.yml +11 -1
  121. data/vendor/board-maps/yaml/FRANZININHO_WIFI_MSC.yml +11 -1
  122. data/vendor/board-maps/yaml/FROG_ESP32.yml +10 -1
  123. data/vendor/board-maps/yaml/HEALTHYPI_4.yml +10 -1
  124. data/vendor/board-maps/yaml/HONEYLEMON.yml +10 -1
  125. data/vendor/board-maps/yaml/HORNBILL_ESP32_DEV.yml +10 -1
  126. data/vendor/board-maps/yaml/HORNBILL_ESP32_MINIMA.yml +4 -1
  127. data/vendor/board-maps/yaml/IMBRIOS_LOGSENS_V1P1.yml +5 -1
  128. data/vendor/board-maps/yaml/LILYGO_T_DISPLAY_S3.yml +7 -1
  129. data/vendor/board-maps/yaml/LOLIN32.yml +10 -1
  130. data/vendor/board-maps/yaml/LOLIN32_LITE.yml +10 -1
  131. data/vendor/board-maps/yaml/LOLIN_D32.yml +10 -1
  132. data/vendor/board-maps/yaml/LOLIN_D32_PRO.yml +10 -1
  133. data/vendor/board-maps/yaml/LOLIN_S2_MINI.yml +11 -1
  134. data/vendor/board-maps/yaml/LOLIN_S2_PICO.yml +11 -1
  135. data/vendor/board-maps/yaml/LOLIN_S3.yml +9 -1
  136. data/vendor/board-maps/yaml/LOLIN_S3_MINI.yml +9 -1
  137. data/vendor/board-maps/yaml/LOLIN_S3_PRO.yml +9 -1
  138. data/vendor/board-maps/yaml/LoPy.yml +11 -1
  139. data/vendor/board-maps/yaml/LoPy4.yml +11 -1
  140. data/vendor/board-maps/yaml/MAGTAG29_ESP32S2.yml +11 -1
  141. data/vendor/board-maps/yaml/METRO_ESP32S2.yml +11 -1
  142. data/vendor/board-maps/yaml/MGBOT_IOTIK32A.yml +10 -1
  143. data/vendor/board-maps/yaml/MGBOT_IOTIK32B.yml +10 -1
  144. data/vendor/board-maps/yaml/MH_ET_LIVE_ESP32DEVKIT.yml +10 -1
  145. data/vendor/board-maps/yaml/MH_ET_LIVE_ESP32MINIKIT.yml +10 -1
  146. data/vendor/board-maps/yaml/MICROS2.yml +11 -1
  147. data/vendor/board-maps/yaml/MINIMA.yml +15 -0
  148. data/vendor/board-maps/yaml/NANO32.yml +10 -1
  149. data/vendor/board-maps/yaml/Node32s.yml +10 -1
  150. data/vendor/board-maps/yaml/NodeMCU_32S.yml +10 -1
  151. data/vendor/board-maps/yaml/ONEHORSE_ESP32_DEV.yml +11 -1
  152. data/vendor/board-maps/yaml/PIMORONI_PLASMA2040.yml +29 -0
  153. data/vendor/board-maps/yaml/PORTENTA_C33.yml +28 -0
  154. data/vendor/board-maps/yaml/PROS3.yml +6 -1
  155. data/vendor/board-maps/yaml/PYCOM_GPY.yml +11 -1
  156. data/vendor/board-maps/yaml/Piranha.yml +7 -1
  157. data/vendor/board-maps/yaml/Pocket32.yml +10 -1
  158. data/vendor/board-maps/yaml/QUANTUM.yml +10 -1
  159. data/vendor/board-maps/yaml/REDPILL_ESP32S3.yml +11 -1
  160. data/vendor/board-maps/yaml/RMP.yml +11 -1
  161. data/vendor/board-maps/yaml/SAMD_CIRCUITPLAYGROUND_EXPRESS.yml +0 -1
  162. data/vendor/board-maps/yaml/SAM_DUE.yml +3 -1
  163. data/vendor/board-maps/yaml/SONOFF_DUALR3.yml +10 -1
  164. data/vendor/board-maps/yaml/TAMC_TERMOD_S3.yml +11 -1
  165. data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1262.yml +6 -1
  166. data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1268.yml +6 -1
  167. data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1276.yml +6 -1
  168. data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1278.yml +6 -1
  169. data/vendor/board-maps/yaml/TBEAM_USE_RADIO_SX1280.yml +6 -1
  170. data/vendor/board-maps/yaml/TBeam.yml +6 -1
  171. data/vendor/board-maps/yaml/TINYPICO.yml +10 -1
  172. data/vendor/board-maps/yaml/TINYS2.yml +11 -1
  173. data/vendor/board-maps/yaml/TTGO_LoRa32_V1.yml +11 -1
  174. data/vendor/board-maps/yaml/TTGO_LoRa32_V2.yml +11 -1
  175. data/vendor/board-maps/yaml/TTGO_LoRa32_v21new.yml +11 -1
  176. data/vendor/board-maps/yaml/TTGO_T1.yml +10 -1
  177. data/vendor/board-maps/yaml/TTGO_T7_V13_Mini32.yml +10 -1
  178. data/vendor/board-maps/yaml/TTGO_T7_V14_Mini32.yml +10 -1
  179. data/vendor/board-maps/yaml/TWATCH_2020_V1.yml +0 -1
  180. data/vendor/board-maps/yaml/TWATCH_2020_V2.yml +0 -1
  181. data/vendor/board-maps/yaml/TWATCH_2020_V3.yml +0 -1
  182. data/vendor/board-maps/yaml/TWATCH_BASE.yml +0 -1
  183. data/vendor/board-maps/yaml/TWatch.yml +0 -1
  184. data/vendor/board-maps/yaml/UBLOX_NINA_W10.yml +10 -1
  185. data/vendor/board-maps/yaml/UNOWIFIR4.yml +17 -0
  186. data/vendor/board-maps/yaml/WIPY3.yml +11 -1
  187. data/vendor/board-maps/yaml/XIAO_ESP32S3.yml +2 -1
  188. data/vendor/board-maps/yaml/connaxio_espoir.yml +7 -1
  189. data/vendor/board-maps/yaml/esp32vn_iot_uno.yml +10 -1
  190. data/vendor/board-maps/yaml/heltec_wifi_32_lora_V3.yml +11 -1
  191. data/vendor/board-maps/yaml/heltec_wifi_kit_32.yml +11 -1
  192. data/vendor/board-maps/yaml/heltec_wifi_kit_32_V3.yml +11 -1
  193. data/vendor/board-maps/yaml/heltec_wifi_lora_32.yml +10 -1
  194. data/vendor/board-maps/yaml/heltec_wifi_lora_32_V2.yml +10 -1
  195. data/vendor/board-maps/yaml/heltec_wireless_stick.yml +10 -1
  196. data/vendor/board-maps/yaml/heltec_wireless_stick_LITE.yml +10 -1
  197. data/vendor/board-maps/yaml/openkb.yml +11 -1
  198. data/vendor/board-maps/yaml/roboheart_hercules.yml +10 -1
  199. data/vendor/board-maps/yaml/sensesiot_weizen.yml +10 -1
  200. data/vendor/board-maps/yaml/uPesy_WROOM.yml +10 -1
  201. data/vendor/board-maps/yaml/uPesy_WROVER.yml +10 -1
  202. data/vendor/board-maps/yaml/unphone8.yml +11 -1
  203. data/vendor/board-maps/yaml/unphone9.yml +11 -1
  204. metadata +14 -2
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 :board_name, :version, :aux_limit, :eeprom_length
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(io, options={})
10
- # Connect the IO, and get the ACK.
11
- @io = io
12
- ack = io.handshake
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
- # Parse map, version and eeprom_legnth.
16
- @name = nil if @name.empty?
17
- @version = nil if @version.empty?
18
- @eeprom_length = @eeprom_length.to_i
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
- # Load the board map.
24
- @map = load_map(@name)
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
- # Allow the IO to call #update on the board when messages received.
27
- io.add_observer(self)
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 = options[:read_bits] || 10
45
+ self.analog_read_resolution = options[:read_bits] || 10
34
46
  end
35
47
 
36
48
  def finish_write
37
- sleep 0.001 while @io.writing?
49
+ sleep 0.001 while @transport.writing?
38
50
  write "\n91\n"
39
- sleep 0.001 while @io.writing?
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
- @io.write(msg)
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
- @io.write(msg, true)
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
- BAUD = 115200
4
+ DEFAULT_BAUD = 115200
5
5
 
6
- def initialize(uart, options={})
6
+ def initialize(uart, baud: DEFAULT_BAUD)
7
7
  @uart = uart
8
- @uart.start(options[:baud] || BAUD)
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 = BOARD_BUFFER - @transit_bytes
104
+ available = @remote_buffer_size - @transit_bytes
97
105
  reserved = (length > available) ? available : length
98
106
  @transit_bytes += reserved
99
107
  reserved
@@ -16,7 +16,7 @@ module Denko
16
16
  end
17
17
 
18
18
  def digital_write(value)
19
- board.digital_write(pin, value)
19
+ @board.digital_write(@pin, value)
20
20
  self.state = value
21
21
  end
22
22
 
@@ -63,7 +63,7 @@ module Denko
63
63
  end
64
64
 
65
65
  def after_initialize(options={})
66
- super(options) if defined?(super)
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
- segments.each do |pin|
24
- pin.low if cathode
25
- pin.high if anode
26
- end
26
+ write(BLANK)
27
27
  end
28
28
 
29
- def display(char)
30
- char = char.to_s
31
- return scroll(char) if char.length > 1
32
- off; write(char); on
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.to_s.upcase]
91
- unless bits
92
- clear
93
- else
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
- display(char)
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, options={})
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
- # Pad right with null bytes if asked.
74
- if options[:pad] && options[:pad] > str.length
75
- (options[:pad] - str.length).times do
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
- # Max should probably always be set to avoid overruning aux message RAM.
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
@@ -3,7 +3,7 @@ module Denko
3
3
  class IRTransmitter
4
4
  include Behaviors::OutputPin
5
5
 
6
- def emit(pulses=[], options={})
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/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Denko
2
- VERSION = "0.13.1"
2
+ VERSION = "0.13.2"
3
3
  end
@@ -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",
@@ -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 ith as no extra hardware UART.
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 IR support on SAM3X / Due.
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
- # SAMD includes all standard packages.
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],
@@ -1,8 +1,10 @@
1
1
 
2
2
  Usage:
3
+
3
4
  denko task [options]
4
5
 
5
6
  Tasks:
7
+
6
8
  sketch SKETCH [options]
7
9
  help
8
10
  targets
@@ -12,23 +14,25 @@
12
14
  --target TARGET (default: mega. Run 'denko targets' for more info)
13
15
  --debug (default: off)
14
16
 
15
- Available sketches and sketch for each sketch:
17
+ Available sketches and options specific to each sketch:
16
18
 
17
19
  serial
18
- --baud BAUD (default: 115200)
20
+ --baud BAUD (default: 115200)
19
21
 
20
22
  ethernet
21
23
  --mac XX:XX:XX:XX:XX:XX (required)
22
24
  --ip XXX.XXX.XXX.XXX (required, no DHCP)
23
25
  --port PORT (default: 3466)
26
+ --baud BAUD (default: 115200, serial fallback)
24
27
 
25
28
  wifi
26
29
  --ssid SSID (required)
27
30
  --password PASSWORD (required)
28
31
  --port PORT (default: 3466)
32
+ --baud BAUD (default: 115200, serial fallback)
29
33
 
30
34
  Examples:
31
35
 
32
36
  denko sketch ethernet --mac 12:34:56:78:90:12 --ip 192.168.1.2
33
- denko sketch serial --baud 57600
34
- denko sketch serial --baud 9600 -target core
37
+ denko sketch serial --baud 57600 --target esp32
38
+ denko sketch serial --baud 9600 --target core
@@ -2,17 +2,6 @@
2
2
  #include <SPI.h>
3
3
  #include <Ethernet.h>
4
4
 
5
- // Define 'serial' as the serial interface to use.
6
- // Uses SerialUSB (left port), which is native USB, on Arduino Due and Zero, or Serial otherwise.
7
- // On many boards, eg. Arduino Due, RP2040, Serial may be native USB anyway.
8
- #if defined(__SAM3X8E__) || defined(__SAMD21G18A__)
9
- #define serial SerialUSB
10
- // Use this for Programming USB port (right) on Due and Zero.
11
- // #define serial Serial
12
- #else
13
- #define serial Serial
14
- #endif
15
-
16
5
  // Configure your MAC address, IP address, and HTTP port here.
17
6
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0x30, 0x31, 0x32 };
18
7
  IPAddress ip(192,168,0,77);
@@ -31,8 +20,8 @@ void printEthernetStatus() {
31
20
 
32
21
  void setup() {
33
22
  // Wait for serial ready.
34
- serial.begin(115200);
35
- while(!serial);
23
+ DENKO_SERIAL_IF.begin(115200);
24
+ while(!DENKO_SERIAL_IF);
36
25
 
37
26
  // Explicitly disable the SD card.
38
27
  pinMode(4,OUTPUT);
@@ -41,9 +30,7 @@ void setup() {
41
30
  // Start up the network connection and server.
42
31
  Ethernet.begin(mac, ip);
43
32
  server.begin();
44
- #ifdef debug
45
- printEthernetStatus();
46
- #endif
33
+ printEthernetStatus();
47
34
 
48
35
  // Add listener callbacks for local logic.
49
36
  denko.digitalListenCallback = onDigitalListen;
@@ -51,20 +38,25 @@ void setup() {
51
38
  }
52
39
 
53
40
  void loop() {
41
+ // End connection if client disconnects.
42
+ if (client && !client.connected()) {
43
+ client.stop();
44
+ }
45
+
54
46
  // Allow one client at a time to be connected. Set it as the denko IO stream.
55
47
  if (!client){
56
48
  client = server.available();
57
- if (client) denko.stream = &client;
49
+ if (client) {
50
+ // TCP Client
51
+ denko.stream = &client;
52
+ } else {
53
+ // Serial fallback
54
+ denko.stream = &DENKO_SERIAL_IF;
55
+ }
58
56
  }
59
57
 
60
58
  // Main loop of the denko library.
61
59
  denko.run();
62
-
63
- // End the connection when client disconnects and revert to serial IO.
64
- if (client && !client.connected()){
65
- client.stop();
66
- denko.stream = &serial;
67
- }
68
60
  }
69
61
 
70
62
  // This runs every time a digital pin that denko is listening to changes value.
data/src/denko_serial.ino CHANGED
@@ -2,24 +2,13 @@
2
2
 
3
3
  Denko denko;
4
4
 
5
- // Define 'serial' as the serial interface to use.
6
- // Uses SerialUSB (left port), which is native USB, on Arduino Due and Zero, or Serial otherwise.
7
- // On many boards, eg. Arduino Due, RP2040, Serial may be native USB anyway.
8
- #if defined(__SAM3X8E__) || defined(__SAMD21G18A__)
9
- #define serial SerialUSB
10
- // Use this for Programming USB port (right) on Due and Zero.
11
- // #define serial Serial
12
- #else
13
- #define serial Serial
14
- #endif
15
-
16
5
  void setup() {
17
6
  // Wait for serial ready.
18
- serial.begin(115200);
19
- while(!serial);
7
+ DENKO_SERIAL_IF.begin(115200);
8
+ while(!DENKO_SERIAL_IF);
20
9
 
21
10
  // Pass serial stream to denko so it can read/write.
22
- denko.stream = &serial;
11
+ denko.stream = &DENKO_SERIAL_IF;
23
12
 
24
13
  // Add listener callbacks for local logic.
25
14
  denko.digitalListenCallback = onDigitalListen;
data/src/denko_wifi.ino CHANGED
@@ -17,18 +17,6 @@
17
17
  #define WIFI_STATUS_LED 13
18
18
  #endif
19
19
 
20
-
21
- // Define 'serial' as the serial interface to use.
22
- // Uses SerialUSB (left port), which is native USB, on Arduino Due and Zero, or Serial otherwise.
23
- // On many boards, eg. Arduino Due, RP2040, Serial may be native USB anyway.
24
- #if defined(__SAM3X8E__) || defined(__SAMD21G18A__)
25
- #define serial SerialUSB
26
- // Use this for Programming USB port (right) on Due and Zero.
27
- // #define serial Serial
28
- #else
29
- #define serial Serial
30
- #endif
31
-
32
20
  // Configure your WiFi options here. IP address is not configurable. Uses DHCP.
33
21
  int port = 3466;
34
22
  char* ssid = "yourNetwork";
@@ -50,16 +38,16 @@ void indicateWiFi(byte value) {
50
38
  }
51
39
 
52
40
  void printWifiStatus() {
53
- serial.println("WiFi Connected");
54
- serial.print("SSID: ");
55
- serial.println(WiFi.SSID());
56
- serial.print("Signal Strength (RSSI):");
57
- serial.print(WiFi.RSSI());
58
- serial.println(" dBm");
59
- serial.print("IP Address: ");
60
- serial.println(WiFi.localIP());
61
- serial.print("Denko TCP Port: ");
62
- serial.println(port);
41
+ DENKO_SERIAL_IF.println("WiFi Connected");
42
+ DENKO_SERIAL_IF.print("SSID: ");
43
+ DENKO_SERIAL_IF.println(WiFi.SSID());
44
+ DENKO_SERIAL_IF.print("Signal Strength (RSSI):");
45
+ DENKO_SERIAL_IF.print(WiFi.RSSI());
46
+ DENKO_SERIAL_IF.println(" dBm");
47
+ DENKO_SERIAL_IF.print("IP Address: ");
48
+ DENKO_SERIAL_IF.println(WiFi.localIP());
49
+ DENKO_SERIAL_IF.print("Denko TCP Port: ");
50
+ DENKO_SERIAL_IF.println(port);
63
51
  indicateWiFi(true);
64
52
  }
65
53
 
@@ -70,37 +58,29 @@ void connect(){
70
58
  #endif
71
59
 
72
60
  // Try to connect.
73
- serial.print("Connecting to WiFi ");
61
+ DENKO_SERIAL_IF.print("Connecting to WiFi ");
74
62
  WiFi.begin(ssid, pass);
75
63
 
76
64
  // Delay until connected.
77
65
  while (WiFi.status() != WL_CONNECTED) {
78
66
  delay(500);
79
- serial.print(".");
67
+ DENKO_SERIAL_IF.print(".");
80
68
  }
81
69
  connected = true;
70
+ printWifiStatus();
82
71
  }
83
72
 
84
73
  void maintainWiFi(){
85
- if (connected == true){
86
- if (WiFi.status() == WL_CONNECTED) return;
74
+ if (WiFi.status() != WL_CONNECTED) {
87
75
  connected = false;
88
76
  connect();
89
77
  }
90
- if (connected == false){
91
- if (WiFi.status() != WL_CONNECTED) {
92
- connect();
93
- return;
94
- }
95
- connected = true;
96
- printWifiStatus();
97
- }
98
78
  }
99
79
 
100
80
  void setup() {
101
81
  // Wait for serial ready.
102
- serial.begin(115200);
103
- while(!serial);
82
+ DENKO_SERIAL_IF.begin(115200);
83
+ while(!DENKO_SERIAL_IF);
104
84
 
105
85
  // Enable over the air updates on the ESP8266.
106
86
  #if defined(ESP8266)
@@ -117,33 +97,38 @@ void setup() {
117
97
  denko.digitalListenCallback = onDigitalListen;
118
98
  denko.analogListenCallback = onAnalogListen;
119
99
 
120
- // Use serial as the denko IO stream until we get a TCP connection.
121
- denko.stream = &serial;
100
+ // Use DENKO_SERIAL_IF as the denko IO stream until we get a TCP connection.
101
+ denko.stream = &DENKO_SERIAL_IF;
122
102
  }
123
103
 
124
104
  void loop() {
125
105
  // Reconnect if we've lost WiFi.
126
106
  maintainWiFi();
127
107
 
108
+ // Handle OTA updates.
109
+ #if defined(ESP8266)
110
+ ArduinoOTA.handle();
111
+ #endif
112
+
113
+ // End connection if client disconnects.
114
+ if (client && !client.connected()) {
115
+ client.stop();
116
+ }
117
+
128
118
  // Allow one client at a time to be connected. Set it as the denko IO stream.
129
119
  if (!client){
130
120
  client = server.available();
131
- if (client) denko.stream = &client;
121
+ if (client) {
122
+ // TCP Client
123
+ denko.stream = &client;
124
+ } else {
125
+ // Serial fallback
126
+ denko.stream = &DENKO_SERIAL_IF;
127
+ }
132
128
  }
133
129
 
134
130
  // Main loop of the denko library.
135
131
  denko.run();
136
-
137
- // End the connection when client disconnects and revert to serial IO.
138
- if (client && !client.connected()){
139
- client.stop();
140
- denko.stream = &serial;
141
- }
142
-
143
- // Handle OTA updates.
144
- #if defined(ESP8266)
145
- ArduinoOTA.handle();
146
- #endif
147
132
  }
148
133
 
149
134
  // This runs every time a digital pin that denko is listening to changes value.