beaglebone 1.0.4 → 1.0.5
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/beaglebone.gemspec +1 -1
- data/examples/i2c.rb +2 -2
- data/lib/beaglebone/ain.rb +19 -21
- data/lib/beaglebone/beaglebone.rb +5 -4
- data/lib/beaglebone/gpio.rb +10 -10
- data/lib/beaglebone/i2c.rb +111 -37
- data/lib/beaglebone/pwm.rb +1 -1
- data/lib/beaglebone/shiftregister.rb +19 -0
- data/lib/beaglebone/spi.rb +145 -38
- data/lib/beaglebone/uart.rb +308 -78
- metadata +1 -1
data/lib/beaglebone/pwm.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
+
# == shiftregister.rb
|
2
|
+
# This file contains the shiftregister control methods
|
1
3
|
module Beaglebone
|
2
4
|
class ShiftRegister
|
3
5
|
|
6
|
+
# Create a shiftregister object based on 3 GPIO pins
|
7
|
+
#
|
8
|
+
# @param latch_pin should be a symbol representing the header pin, i.e. :P9_12
|
9
|
+
# @param clock_pin should be a symbol representing the header pin, i.e. :P9_13
|
10
|
+
# @param data_pin should be a symbol representing the header pin, i.e. :P9_14
|
11
|
+
# @param lsb optional, send least significant bit first if set
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# shiftregister = ShiftRegister.new(:P9_11, :P9_12, :P9_13)
|
4
15
|
def initialize(latch_pin, clock_pin, data_pin, lsb=nil)
|
5
16
|
|
6
17
|
@latch_pin = latch_pin
|
@@ -13,6 +24,14 @@ module Beaglebone
|
|
13
24
|
GPIO::pin_mode(@data_pin, :OUT)
|
14
25
|
end
|
15
26
|
|
27
|
+
# Send data to shift register
|
28
|
+
#
|
29
|
+
# @param data Integer value to write to the shift register
|
30
|
+
# @param lsb optional, send least significant bit first if set
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# shiftregister = ShiftRegister.new(:P9_11, :P9_12, :P9_13)
|
34
|
+
# shiftregister.shift_out(255)
|
16
35
|
def shiftout(data, lsb=nil)
|
17
36
|
GPIO::shift_out(@latch_pin, @clock_pin, @data_pin, data, lsb || @lsb)
|
18
37
|
end
|
data/lib/beaglebone/spi.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# == spi.rb
|
2
|
+
# This file contains SPI methods
|
3
|
+
module Beaglebone #:nodoc:
|
4
|
+
# == SPI
|
5
|
+
# Procedural methods for SPI control
|
6
|
+
# == Summary
|
7
|
+
# #setup is called to initialize an SPI device
|
3
8
|
module SPI
|
4
9
|
#some ioctl defines
|
5
10
|
IOC_NONE = 0
|
@@ -56,6 +61,69 @@ module Beaglebone
|
|
56
61
|
class << self
|
57
62
|
|
58
63
|
attr_accessor :spistatus, :spimutex
|
64
|
+
|
65
|
+
# Initialize an SPI device
|
66
|
+
#
|
67
|
+
# @param spi should be a symbol representing the SPI device
|
68
|
+
# @param mode optional, default 0, specifies the SPI mode :SPI_MODE_0 through 3
|
69
|
+
# @param speed optional, specifies the SPI communication speed
|
70
|
+
# @param bpw optional, specifies the bits per word
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# SPI.setup(:SPI0, SPI_MODE_0)
|
74
|
+
def setup(spi, mode=nil, speed=1000000, bpw=8)
|
75
|
+
check_spi_valid(spi)
|
76
|
+
|
77
|
+
#make sure spi not already enabled
|
78
|
+
return if get_spi_status(spi)
|
79
|
+
|
80
|
+
mode = mode || SPI_MODE_0
|
81
|
+
|
82
|
+
spiinfo = SPIS[spi]
|
83
|
+
|
84
|
+
#ensure dtb is loaded
|
85
|
+
Beaglebone::device_tree_load("#{spiinfo[:devicetree]}") if spiinfo[:devicetree]
|
86
|
+
|
87
|
+
#open the spi device.
|
88
|
+
spi_fd = File.open("#{spiinfo[:dev]}#{SPIS[:counter]}.0", 'r+')
|
89
|
+
|
90
|
+
set_spi_status(spi, :fd_spi, spi_fd)
|
91
|
+
set_spi_status(spi, :mutex, Mutex.new)
|
92
|
+
|
93
|
+
set_mode(spi, mode)
|
94
|
+
set_bpw(spi, bpw)
|
95
|
+
set_speed(spi, speed)
|
96
|
+
|
97
|
+
SPIS[:counter] += 1
|
98
|
+
|
99
|
+
spiinfo[:pins].each do |pin|
|
100
|
+
Beaglebone::set_pin_status(pin, :spi, spiinfo[:id])
|
101
|
+
Beaglebone::set_pin_status(pin, :type, :spi)
|
102
|
+
Beaglebone::set_pin_status(pin, :fd_spi, spi_fd)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
# Transfer data to and from the SPI device
|
108
|
+
#
|
109
|
+
# @return String data read from SPI device
|
110
|
+
#
|
111
|
+
# @param spi should be a symbol representing the SPI device
|
112
|
+
# @param tx_data data to transmit
|
113
|
+
# @param readbytes bytes to read, otherwise it sizeof tx_data is used
|
114
|
+
# @param speed optional, speed to xfer at
|
115
|
+
# @param delay optional delay
|
116
|
+
# @param bpw optional bits per word
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
# # communicate with MCP3008
|
120
|
+
# # byte 1: start bit
|
121
|
+
# # byte 2: single(1)/diff(0),3 bites for channel, null pad
|
122
|
+
# # byte 3: don't care
|
123
|
+
# SPI.setup(:SPI0, SPI_MODE_0)
|
124
|
+
# raw = SPI.xfer(:SPI0, [ 0b00000001, 0b10000000, 0].pack("C*"))
|
125
|
+
# data = raw.unpack("C*")
|
126
|
+
# val = ((data[1] & 0b00000011) << 8 ) | data[2]
|
59
127
|
def xfer(spi, tx_data, readbytes=0, speed=nil, delay=nil, bpw=nil)
|
60
128
|
check_spi_enabled(spi)
|
61
129
|
|
@@ -103,11 +171,18 @@ module Beaglebone
|
|
103
171
|
rx_data
|
104
172
|
end
|
105
173
|
|
174
|
+
# Return the file descriptor to the open SPI device
|
175
|
+
#
|
176
|
+
# @param spi should be a symbol representing the SPI device
|
106
177
|
def file(spi)
|
107
178
|
check_spi_enabled(spi)
|
108
179
|
get_spi_status(spi, :fd_spi)
|
109
180
|
end
|
110
181
|
|
182
|
+
# Set the communication speed of the specified SPI device
|
183
|
+
#
|
184
|
+
# @param spi should be a symbol representing the SPI device
|
185
|
+
# @param speed communication speed
|
111
186
|
def set_speed(spi, speed)
|
112
187
|
speed = speed.to_i
|
113
188
|
raise ArgumentError, "Speed (#{speed.to_s}) must be a positive integer" unless speed > 0
|
@@ -120,6 +195,10 @@ module Beaglebone
|
|
120
195
|
set_spi_status(spi, :speed, speed)
|
121
196
|
end
|
122
197
|
|
198
|
+
# Set the communication speed of the specified SPI device
|
199
|
+
#
|
200
|
+
# @param spi should be a symbol representing the SPI device
|
201
|
+
# @param mode should be a valid SPI mode, e.g. :SPI_MODE_0 through 3
|
123
202
|
def set_mode(spi, mode)
|
124
203
|
check_spi_enabled(spi)
|
125
204
|
raise ArgumentError, "Mode (#{mode.to_s}) is unknown" unless [SPI_MODE_0, SPI_MODE_1, SPI_MODE_2, SPI_MODE_3].include?(mode)
|
@@ -129,6 +208,10 @@ module Beaglebone
|
|
129
208
|
spi_fd.ioctl(SPI_IOC_RD_MODE, [mode].pack('C'))
|
130
209
|
end
|
131
210
|
|
211
|
+
# Set the bits per word of the specified SPI device
|
212
|
+
#
|
213
|
+
# @param spi should be a symbol representing the SPI device
|
214
|
+
# @param bpw should specify the bits per word
|
132
215
|
def set_bpw(spi, bpw)
|
133
216
|
bpw = bpw.to_i
|
134
217
|
raise ArgumentError, "BPW (#{bpw.to_s}) must be a positive integer" unless bpw > 0
|
@@ -141,39 +224,11 @@ module Beaglebone
|
|
141
224
|
set_spi_status(spi, :bpw, bpw)
|
142
225
|
end
|
143
226
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
mode = mode || SPI_MODE_0
|
151
|
-
|
152
|
-
spiinfo = SPIS[spi]
|
153
|
-
|
154
|
-
#ensure dtb is loaded
|
155
|
-
Beaglebone::device_tree_load("#{spiinfo[:devicetree]}") if spiinfo[:devicetree]
|
156
|
-
|
157
|
-
#open the spi device.
|
158
|
-
spi_fd = File.open("#{spiinfo[:dev]}#{SPIS[:counter]}.0", 'r+')
|
159
|
-
|
160
|
-
set_spi_status(spi, :fd_spi, spi_fd)
|
161
|
-
set_spi_status(spi, :mutex, Mutex.new)
|
162
|
-
|
163
|
-
set_mode(spi, mode)
|
164
|
-
set_bpw(spi, bpw)
|
165
|
-
set_speed(spi, speed)
|
166
|
-
|
167
|
-
SPIS[:counter] += 1
|
168
|
-
|
169
|
-
spiinfo[:pins].each do |pin|
|
170
|
-
Beaglebone::set_pin_status(pin, :spi, spiinfo[:id])
|
171
|
-
Beaglebone::set_pin_status(pin, :type, :spi)
|
172
|
-
Beaglebone::set_pin_status(pin, :fd_spi, spi_fd)
|
173
|
-
end
|
174
|
-
|
175
|
-
end
|
176
|
-
|
227
|
+
# Disable the specified SPI device
|
228
|
+
#
|
229
|
+
# @note device trees cannot be unloaded at this time without kernel panic.
|
230
|
+
#
|
231
|
+
# @param spi should be a symbol representing the SPI device
|
177
232
|
def disable(spi)
|
178
233
|
check_spi_valid(spi)
|
179
234
|
check_spi_enabled(spi)
|
@@ -189,6 +244,7 @@ module Beaglebone
|
|
189
244
|
|
190
245
|
end
|
191
246
|
|
247
|
+
# Disable all active SPI devices
|
192
248
|
def cleanup
|
193
249
|
#reset all spis we've used and unload the device tree
|
194
250
|
spistatus.clone.keys.each { |spi| disable(spi)}
|
@@ -196,6 +252,7 @@ module Beaglebone
|
|
196
252
|
|
197
253
|
private
|
198
254
|
|
255
|
+
#ensure spi is valid
|
199
256
|
def check_spi_valid(spi)
|
200
257
|
raise ArgumentError, "Invalid spi Specified #{spi.to_s}" unless SPIS[spi] && SPIS[spi][:sclk]
|
201
258
|
spiinfo = SPIS[spi.to_sym.upcase]
|
@@ -217,6 +274,7 @@ module Beaglebone
|
|
217
274
|
end
|
218
275
|
end
|
219
276
|
|
277
|
+
# lock spi
|
220
278
|
def lock_spi(spi)
|
221
279
|
check_spi_enabled(spi)
|
222
280
|
mutex = get_spi_status(spi, :mutex)
|
@@ -226,10 +284,12 @@ module Beaglebone
|
|
226
284
|
end
|
227
285
|
end
|
228
286
|
|
287
|
+
# ensure spi is enabled
|
229
288
|
def check_spi_enabled(spi)
|
230
289
|
raise ArgumentError, "spi not enabled #{spi.to_s}" unless get_spi_status(spi)
|
231
290
|
end
|
232
291
|
|
292
|
+
# disable spi pin
|
233
293
|
def disable_spi_pin(pin)
|
234
294
|
Beaglebone::check_valid_pin(pin, :spi)
|
235
295
|
|
@@ -290,33 +350,80 @@ module Beaglebone
|
|
290
350
|
end
|
291
351
|
end
|
292
352
|
|
293
|
-
#
|
353
|
+
# Object Oriented SPI Implementation.
|
354
|
+
# This treats the SPI device as an object.
|
294
355
|
class SPIDevice
|
356
|
+
# Initialize an SPI device. Returns an SPIDevice object
|
357
|
+
#
|
358
|
+
# @param spi should be a symbol representing the SPI device
|
359
|
+
# @param mode optional, default 0, specifies the SPI mode :SPI_MODE_0 through 3
|
360
|
+
# @param speed optional, specifies the SPI communication speed
|
361
|
+
# @param bpw optional, specifies the bits per word
|
362
|
+
#
|
363
|
+
# @example
|
364
|
+
# spi = SPIDevice.new(:SPI0, SPI_MODE_0)
|
295
365
|
def initialize(spi, mode=nil, speed=1000000, bpw=8)
|
296
366
|
@spi = spi
|
297
367
|
SPI::setup(@spi, mode, speed, bpw)
|
298
368
|
end
|
299
369
|
|
370
|
+
# Transfer data to and from the SPI device
|
371
|
+
#
|
372
|
+
# @return String data read from SPI device
|
373
|
+
#
|
374
|
+
# @param tx_data data to transmit
|
375
|
+
# @param readbytes bytes to read, otherwise it sizeof tx_data is used
|
376
|
+
# @param speed optional, speed to xfer at
|
377
|
+
# @param delay optional delay
|
378
|
+
# @param bpw optional bits per word
|
379
|
+
#
|
380
|
+
# @example
|
381
|
+
# # communicate with MCP3008
|
382
|
+
# # byte 1: start bit
|
383
|
+
# # byte 2: single(1)/diff(0),3 bites for channel, null pad
|
384
|
+
# # byte 3: don't care
|
385
|
+
# spi = SPIDevice.new(:SPI0)
|
386
|
+
# raw = spi.xfer([ 0b00000001, 0b10000000, 0].pack("C*"))
|
387
|
+
# data = raw.unpack("C*")
|
388
|
+
# val = ((data[1] & 0b00000011) << 8 ) | data[2]
|
300
389
|
def xfer(tx_data, readbytes=0, speed=nil, delay=nil, bpw=nil)
|
301
390
|
SPI::xfer(@spi, tx_data, readbytes, speed, delay, bpw)
|
302
391
|
end
|
303
392
|
|
304
|
-
|
305
|
-
|
393
|
+
# Return the file descriptor to the open SPI device
|
394
|
+
def file
|
395
|
+
SPI::file(@spi)
|
306
396
|
end
|
307
397
|
|
398
|
+
# Set the communication speed of the SPI device
|
399
|
+
#
|
400
|
+
# @param speed communication speed
|
308
401
|
def set_speed(speed)
|
309
402
|
SPI::set_speed(@spi, speed)
|
310
403
|
end
|
311
404
|
|
405
|
+
# Set the communication speed of the SPI device
|
406
|
+
#
|
407
|
+
# @param mode should be a valid SPI mode, e.g. :SPI_MODE_0 through 3
|
312
408
|
def set_mode(mode)
|
313
409
|
SPI::set_mode(@spi, mode)
|
314
410
|
end
|
315
411
|
|
412
|
+
# Set the bits per word of the SPI device
|
413
|
+
#
|
414
|
+
# @param bpw should specify the bits per word
|
316
415
|
def set_bpw(bpw)
|
317
416
|
SPI::set_bpw(@spi, bpw)
|
318
417
|
end
|
319
418
|
|
419
|
+
# Disable the specified SPI device
|
420
|
+
#
|
421
|
+
# @note device trees cannot be unloaded at this time without kernel panic.
|
422
|
+
#
|
423
|
+
def disable
|
424
|
+
SPI::disable(@spi)
|
425
|
+
end
|
426
|
+
|
320
427
|
end
|
321
428
|
|
322
429
|
end
|
data/lib/beaglebone/uart.rb
CHANGED
@@ -1,16 +1,135 @@
|
|
1
|
-
|
1
|
+
# == uart.rb
|
2
|
+
# This file contains UART methods
|
3
|
+
module Beaglebone #:nodoc:
|
4
|
+
# == UART
|
5
|
+
# Procedural methods for UART control
|
6
|
+
# == Summary
|
7
|
+
# #setup is called to initialize a UART device
|
2
8
|
module UART
|
9
|
+
# Valid UART speeds
|
3
10
|
SPEEDS = [ 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, 57600, 115200 ]
|
11
|
+
|
4
12
|
@uartstatus = {}
|
5
13
|
@uartmutex = Mutex.new
|
6
14
|
|
7
15
|
class << self
|
8
16
|
attr_accessor :uartstatus, :uartmutex
|
9
17
|
|
18
|
+
|
19
|
+
# Initialize a UART device
|
20
|
+
#
|
21
|
+
# @param uart should be a symbol representing the UART device
|
22
|
+
# @param speed should be an integer thats a valid speed. @see SPEEDS
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# UART.setup(:UART1, 9600)
|
26
|
+
def setup(uart, speed=9600)
|
27
|
+
check_uart_valid(uart)
|
28
|
+
check_speed_valid(speed)
|
29
|
+
|
30
|
+
#make sure uart not already enabled
|
31
|
+
return if get_uart_status(uart)
|
32
|
+
|
33
|
+
uartinfo = UARTS[uart]
|
34
|
+
|
35
|
+
#ensure dtb is loaded
|
36
|
+
Beaglebone::device_tree_load("#{TREES[:UART][:pin]}#{uartinfo[:id]}")
|
37
|
+
|
38
|
+
#open the uart device
|
39
|
+
uart_fd = File.open(uartinfo[:dev], 'r+')
|
40
|
+
|
41
|
+
if uartinfo[:tx]
|
42
|
+
Beaglebone::set_pin_status(uartinfo[:tx], :uart, uartinfo[:id])
|
43
|
+
Beaglebone::set_pin_status(uartinfo[:tx], :type, :uart)
|
44
|
+
Beaglebone::set_pin_status(uartinfo[:tx], :fd_uart, uart_fd)
|
45
|
+
end
|
46
|
+
|
47
|
+
if uartinfo[:rx]
|
48
|
+
Beaglebone::set_pin_status(uartinfo[:rx], :uart, uartinfo[:id])
|
49
|
+
Beaglebone::set_pin_status(uartinfo[:tx], :type, :uart)
|
50
|
+
Beaglebone::set_pin_status(uartinfo[:rx], :fd_uart, uart_fd)
|
51
|
+
end
|
52
|
+
|
53
|
+
system("stty -F #{uartinfo[:dev]} raw")
|
54
|
+
system("stty -F #{uartinfo[:dev]} #{speed}")
|
55
|
+
|
56
|
+
set_uart_status(uart, :fd_uart, uart_fd)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set the speed of the UART
|
60
|
+
#
|
61
|
+
# @param speed should be an integer thats a valid speed. @see SPEEDS
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# UART.set_speed(:UART1, 9600)
|
65
|
+
def set_speed(uart, speed)
|
66
|
+
check_uart_valid(uart)
|
67
|
+
check_speed_valid(speed)
|
68
|
+
|
69
|
+
uartinfo = UARTS[uart]
|
70
|
+
system("stty -F #{uartinfo[:dev]} #{speed}")
|
71
|
+
end
|
72
|
+
|
73
|
+
# Write data to a UART device
|
74
|
+
#
|
75
|
+
# @param uart should be a symbol representing the UART device
|
76
|
+
# @param data the data to write
|
77
|
+
#
|
78
|
+
# @return Integer the number of bytes written
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# UART.write(:UART1, "1234") => 4
|
82
|
+
def write(uart, data)
|
83
|
+
check_uart_enabled(uart)
|
84
|
+
|
85
|
+
pin_tx = UARTS[uart][:tx]
|
86
|
+
|
87
|
+
Beaglebone::check_valid_pin(pin_tx, :uart)
|
88
|
+
|
89
|
+
fd = Beaglebone::get_pin_status(pin_tx, :fd_uart)
|
90
|
+
|
91
|
+
ret = fd.write(data)
|
92
|
+
fd.flush
|
93
|
+
|
94
|
+
ret
|
95
|
+
end
|
96
|
+
|
97
|
+
# Write a line data to a UART device.
|
98
|
+
# This is a convenience method using #write
|
99
|
+
# @see #write
|
100
|
+
#
|
101
|
+
# @param uart should be a symbol representing the UART device
|
102
|
+
# @param data the data to write
|
103
|
+
#
|
104
|
+
# @return Integer the number of bytes written
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
# UART.writeln(:UART1, "1234") => 5
|
108
|
+
def writeln(uart, data)
|
109
|
+
write(uart, data + "\n")
|
110
|
+
end
|
111
|
+
|
112
|
+
# Read one character from a UART device
|
113
|
+
#
|
114
|
+
# @param uart should be a symbol representing the UART device
|
115
|
+
#
|
116
|
+
# @return String the character read from the UART device
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
# UART.readchars(:UART1) => "x"
|
10
120
|
def readchar(uart)
|
11
121
|
readchars(uart, 1)
|
12
122
|
end
|
13
123
|
|
124
|
+
# Read characters from a UART device
|
125
|
+
#
|
126
|
+
# @param uart should be a symbol representing the UART device
|
127
|
+
# @param bytes number of bytes to read
|
128
|
+
#
|
129
|
+
# @return String the characters read from the UART device
|
130
|
+
#
|
131
|
+
# @example
|
132
|
+
# UART.readchars(:UART1, 2) => "xx"
|
14
133
|
def readchars(uart, bytes)
|
15
134
|
check_uart_enabled(uart)
|
16
135
|
ensure_read_lock(uart)
|
@@ -34,6 +153,14 @@ module Beaglebone
|
|
34
153
|
buffer
|
35
154
|
end
|
36
155
|
|
156
|
+
# Read a line from a UART device
|
157
|
+
#
|
158
|
+
# @param uart should be a symbol representing the UART device
|
159
|
+
#
|
160
|
+
# @return String the line read from the UART device
|
161
|
+
#
|
162
|
+
# @example
|
163
|
+
# UART.readline(:UART1) => "A line of text"
|
37
164
|
def readline(uart)
|
38
165
|
check_uart_enabled(uart)
|
39
166
|
ensure_read_lock(uart)
|
@@ -53,6 +180,12 @@ module Beaglebone
|
|
53
180
|
data
|
54
181
|
end
|
55
182
|
|
183
|
+
# Read a character from a UART device and pass it to the specified block
|
184
|
+
#
|
185
|
+
# @param uart should be a symbol representing the UART device
|
186
|
+
#
|
187
|
+
# @example
|
188
|
+
# UART.each_char(:UART1) { |x| puts "read: #{x}" }
|
56
189
|
def each_char(uart)
|
57
190
|
loop do
|
58
191
|
data = readchars(uart, 1)
|
@@ -61,6 +194,13 @@ module Beaglebone
|
|
61
194
|
|
62
195
|
end
|
63
196
|
|
197
|
+
# Read characters from a UART device and pass them to the specified block
|
198
|
+
#
|
199
|
+
# @param uart should be a symbol representing the UART device
|
200
|
+
# @param chars should be the number of chars to read
|
201
|
+
#
|
202
|
+
# @example
|
203
|
+
# UART.each_chars(:UART1, 2) { |x| puts "read: #{x}" }
|
64
204
|
def each_chars(uart, chars)
|
65
205
|
loop do
|
66
206
|
data = readchars(uart, chars)
|
@@ -68,6 +208,13 @@ module Beaglebone
|
|
68
208
|
end
|
69
209
|
end
|
70
210
|
|
211
|
+
|
212
|
+
# Read lines from a UART device and pass them to the specified block
|
213
|
+
#
|
214
|
+
# @param uart should be a symbol representing the UART device
|
215
|
+
#
|
216
|
+
# @example
|
217
|
+
# UART.each_line(:UART1) { |x| puts "read: #{x}" }
|
71
218
|
def each_line(uart)
|
72
219
|
loop do
|
73
220
|
data = readline(uart)
|
@@ -75,29 +222,16 @@ module Beaglebone
|
|
75
222
|
end
|
76
223
|
end
|
77
224
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
fd = Beaglebone::get_pin_status(pin_tx, :fd_uart)
|
90
|
-
|
91
|
-
ret = fd.write(data)
|
92
|
-
fd.flush
|
93
|
-
|
94
|
-
ret
|
95
|
-
end
|
96
|
-
|
97
|
-
def run_once_on_each_line(callback, uart)
|
98
|
-
run_on_each_line(callback, uart, 1)
|
99
|
-
end
|
100
|
-
|
225
|
+
# Runs a callback after receiving a line of data from a UART device
|
226
|
+
# This creates a new thread that runs in the background
|
227
|
+
#
|
228
|
+
# @param callback A method to call when the data is received. This method should take 3 arguments, the UART, the line read, and the counter
|
229
|
+
# @param uart should be a symbol representing the UART device
|
230
|
+
# @param repeats is optional and specifies the number of times the callback will be run
|
231
|
+
#
|
232
|
+
# @example
|
233
|
+
# callback = lambda { |uart, line, count| puts "[#{uart}:#{count}] #{line} "}
|
234
|
+
# UART.run_on_each_line(callback, :UART1)
|
101
235
|
def run_on_each_line(callback, uart, repeats=nil)
|
102
236
|
check_uart_enabled(uart)
|
103
237
|
|
@@ -125,18 +259,23 @@ module Beaglebone
|
|
125
259
|
set_uart_status(uart, :thread, thread)
|
126
260
|
end
|
127
261
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
def run_once_on_each_chars(callback, uart, chars=1)
|
133
|
-
run_on_each_chars(callback, uart, chars, 1)
|
134
|
-
end
|
135
|
-
|
136
|
-
def run_on_each_char(callback, uart, repeats=nil)
|
137
|
-
run_on_each_chars(callback, uart, 1, repeats)
|
262
|
+
# Convenience method for run_on_each_line with repeats set to 1
|
263
|
+
# @see #run_on_each_line
|
264
|
+
def run_once_on_each_line(callback, uart)
|
265
|
+
run_on_each_line(callback, uart, 1)
|
138
266
|
end
|
139
267
|
|
268
|
+
# Runs a callback after receiving data from a UART device
|
269
|
+
# This creates a new thread that runs in the background
|
270
|
+
#
|
271
|
+
# @param callback A method to call when the data is received. This method should take 3 arguments, the UART, the line read, and the counter
|
272
|
+
# @param uart should be a symbol representing the UART device
|
273
|
+
# @param chars should be the number of chars to read
|
274
|
+
# @param repeats is optional and specifies the number of times the callback will be run
|
275
|
+
#
|
276
|
+
# @example
|
277
|
+
# callback = lambda { |uart, data, count| puts "[#{uart}:#{count}] #{data} "}
|
278
|
+
# UART.run_on_each_chars(callback, :UART1, 2)
|
140
279
|
def run_on_each_chars(callback, uart, chars=1, repeats=nil)
|
141
280
|
check_uart_enabled(uart)
|
142
281
|
|
@@ -164,47 +303,32 @@ module Beaglebone
|
|
164
303
|
set_uart_status(uart, :thread, thread)
|
165
304
|
end
|
166
305
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
uartinfo = UARTS[uart]
|
172
|
-
system("stty -F #{uartinfo[:dev]} #{speed}")
|
306
|
+
# Convenience method for run_on_each_chars with chars and repeats set to 1
|
307
|
+
# @see #run_on_each_chars
|
308
|
+
def run_once_on_each_char(callback, uart)
|
309
|
+
run_once_on_each_chars(callback, uart, 1)
|
173
310
|
end
|
174
311
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
return if get_uart_status(uart)
|
181
|
-
|
182
|
-
uartinfo = UARTS[uart]
|
183
|
-
|
184
|
-
#ensure dtb is loaded
|
185
|
-
Beaglebone::device_tree_load("#{TREES[:UART][:pin]}#{uartinfo[:id]}")
|
186
|
-
|
187
|
-
#open the uart device
|
188
|
-
uart_fd = File.open(uartinfo[:dev], 'r+')
|
189
|
-
|
190
|
-
if uartinfo[:tx]
|
191
|
-
Beaglebone::set_pin_status(uartinfo[:tx], :uart, uartinfo[:id])
|
192
|
-
Beaglebone::set_pin_status(uartinfo[:tx], :type, :uart)
|
193
|
-
Beaglebone::set_pin_status(uartinfo[:tx], :fd_uart, uart_fd)
|
194
|
-
end
|
195
|
-
|
196
|
-
if uartinfo[:rx]
|
197
|
-
Beaglebone::set_pin_status(uartinfo[:rx], :uart, uartinfo[:id])
|
198
|
-
Beaglebone::set_pin_status(uartinfo[:tx], :type, :uart)
|
199
|
-
Beaglebone::set_pin_status(uartinfo[:rx], :fd_uart, uart_fd)
|
200
|
-
end
|
201
|
-
|
202
|
-
system("stty -F #{uartinfo[:dev]} raw")
|
203
|
-
system("stty -F #{uartinfo[:dev]} #{speed}")
|
312
|
+
# Convenience method for run_on_each_chars with chars and repeats set to 1
|
313
|
+
# @see #run_on_each_chars
|
314
|
+
def run_once_on_each_chars(callback, uart, chars=1)
|
315
|
+
run_on_each_chars(callback, uart, chars, 1)
|
316
|
+
end
|
204
317
|
|
205
|
-
|
318
|
+
# Convenience method for run_on_each_chars with chars set to 1
|
319
|
+
# @see #run_on_each_chars
|
320
|
+
def run_on_each_char(callback, uart, repeats=nil)
|
321
|
+
run_on_each_chars(callback, uart, 1, repeats)
|
206
322
|
end
|
207
323
|
|
324
|
+
# Disable a UART device.
|
325
|
+
#
|
326
|
+
# @note device trees cannot be unloaded at this time without kernel panic.
|
327
|
+
#
|
328
|
+
# @param uart should be a symbol representing the UART device
|
329
|
+
#
|
330
|
+
# @example
|
331
|
+
# UART.disable(:UART1)
|
208
332
|
def disable(uart)
|
209
333
|
check_uart_valid(uart)
|
210
334
|
check_uart_enabled(uart)
|
@@ -217,7 +341,7 @@ module Beaglebone
|
|
217
341
|
delete_uart_status(uart)
|
218
342
|
end
|
219
343
|
|
220
|
-
#
|
344
|
+
# Stops any threads waiting for data on the specified UART
|
221
345
|
def stop_read_wait(uart)
|
222
346
|
thread = get_uart_status(uart, :thread)
|
223
347
|
|
@@ -225,6 +349,7 @@ module Beaglebone
|
|
225
349
|
thread.join if thread
|
226
350
|
end
|
227
351
|
|
352
|
+
# Disable all UART devices
|
228
353
|
def cleanup
|
229
354
|
#reset all UARTs we've used and unload the device tree
|
230
355
|
uartstatus.clone.keys.each { |uart| disable(uart)}
|
@@ -232,6 +357,7 @@ module Beaglebone
|
|
232
357
|
|
233
358
|
private
|
234
359
|
|
360
|
+
# return hash data for specified UART
|
235
361
|
def get_uart_status(uart, key = nil)
|
236
362
|
uartmutex.synchronize do
|
237
363
|
if key
|
@@ -242,6 +368,7 @@ module Beaglebone
|
|
242
368
|
end
|
243
369
|
end
|
244
370
|
|
371
|
+
# set hash data for specified UART
|
245
372
|
def set_uart_status(uart, key, value)
|
246
373
|
uartmutex.synchronize do
|
247
374
|
uartstatus[uart] ||= {}
|
@@ -249,6 +376,7 @@ module Beaglebone
|
|
249
376
|
end
|
250
377
|
end
|
251
378
|
|
379
|
+
# remove hash data for specified UART
|
252
380
|
def delete_uart_status(uart, key = nil)
|
253
381
|
uartmutex.synchronize do
|
254
382
|
if key.nil?
|
@@ -259,6 +387,7 @@ module Beaglebone
|
|
259
387
|
end
|
260
388
|
end
|
261
389
|
|
390
|
+
# ensure UART is valid
|
262
391
|
def check_uart_valid(uart)
|
263
392
|
raise ArgumentError, "Invalid UART Specified #{uart.to_s}" unless UARTS[uart]
|
264
393
|
uartinfo = UARTS[uart.to_sym.upcase]
|
@@ -273,10 +402,12 @@ module Beaglebone
|
|
273
402
|
|
274
403
|
end
|
275
404
|
|
405
|
+
# ensure UART is enabled
|
276
406
|
def check_uart_enabled(uart)
|
277
407
|
raise ArgumentError, "UART not enabled #{uart.to_s}" unless get_uart_status(uart)
|
278
408
|
end
|
279
409
|
|
410
|
+
# ensure we have a read lock for the UART
|
280
411
|
def ensure_read_lock(uart)
|
281
412
|
#ensure we're the only ones reading
|
282
413
|
if get_uart_status(uart, :thread) && get_uart_status(uart, :thread) != Thread.current
|
@@ -288,10 +419,12 @@ module Beaglebone
|
|
288
419
|
end
|
289
420
|
end
|
290
421
|
|
422
|
+
# check to make sure the specified speed is valid
|
291
423
|
def check_speed_valid(speed)
|
292
424
|
raise ArgumentError, "Invalid speed specified: #{speed}" unless SPEEDS.include?(speed)
|
293
425
|
end
|
294
426
|
|
427
|
+
# disable a uart pin
|
295
428
|
def disable_uart_pin(pin)
|
296
429
|
Beaglebone::check_valid_pin(pin, :uart)
|
297
430
|
|
@@ -309,77 +442,174 @@ module Beaglebone
|
|
309
442
|
end
|
310
443
|
end
|
311
444
|
|
312
|
-
#
|
445
|
+
# Object Oriented UART Implementation.
|
446
|
+
# This treats the UART device as an object.
|
313
447
|
class UARTDevice
|
448
|
+
# Initialize a UART device. Returns a UARTDevice object
|
449
|
+
#
|
450
|
+
# @param uart should be a symbol representing the UART device
|
451
|
+
# @param speed should be an integer thats a valid speed. @see SPEEDS
|
452
|
+
#
|
453
|
+
# @example
|
454
|
+
# uart1 = UARTDevice.new(:UART1, 9600)
|
314
455
|
def initialize(uart, speed=9600)
|
315
456
|
@uart = uart
|
316
457
|
UART::setup(@uart, speed)
|
317
458
|
end
|
318
459
|
|
460
|
+
# Set the speed of the UART
|
461
|
+
#
|
462
|
+
# @param speed should be an integer thats a valid speed. @see SPEEDS
|
463
|
+
#
|
464
|
+
# @example
|
465
|
+
# uart1.set_speed(9600)
|
319
466
|
def set_speed(speed)
|
320
467
|
UART::set_speed(@uart, speed)
|
321
468
|
end
|
322
469
|
|
470
|
+
# Write data to a UART device
|
471
|
+
#
|
472
|
+
# @param data the data to write
|
473
|
+
#
|
474
|
+
# @return Integer the number of bytes written
|
475
|
+
#
|
476
|
+
# @example
|
477
|
+
# uart1.write("1234") => 4
|
323
478
|
def write(data)
|
324
479
|
UART::write(@uart, data)
|
325
480
|
end
|
326
481
|
|
482
|
+
# Write a line data to a UART device.
|
483
|
+
# This is a convenience method using #write
|
484
|
+
# @see #write
|
485
|
+
#
|
486
|
+
# @param data the data to write
|
487
|
+
#
|
488
|
+
# @return Integer the number of bytes written
|
489
|
+
#
|
490
|
+
# @example
|
491
|
+
# uart1.writeln("1234") => 5
|
327
492
|
def writeln(data)
|
328
493
|
UART::writeln(@uart, data)
|
329
494
|
end
|
330
495
|
|
496
|
+
# Read one character from a UART device
|
497
|
+
#
|
498
|
+
# @return String the character read from the UART device
|
499
|
+
#
|
500
|
+
# @example
|
501
|
+
# uart1.readchars => "x"
|
331
502
|
def readchar
|
332
503
|
UART::readchar(@uart)
|
333
504
|
end
|
334
505
|
|
506
|
+
# Read characters from a UART device
|
507
|
+
#
|
508
|
+
# @param bytes number of bytes to read
|
509
|
+
#
|
510
|
+
# @return String the characters read from the UART device
|
511
|
+
#
|
512
|
+
# @example
|
513
|
+
# uart1.readchars(2) => "xx"
|
335
514
|
def readchars(bytes)
|
336
515
|
UART::readchars(@uart, bytes)
|
337
516
|
end
|
338
517
|
|
518
|
+
# Read a line from a UART device
|
519
|
+
#
|
520
|
+
# @return String the line read from the UART device
|
521
|
+
#
|
522
|
+
# @example
|
523
|
+
# uart1.readline => "A line of text"
|
339
524
|
def readline
|
340
525
|
UART::readline(@uart)
|
341
526
|
end
|
342
527
|
|
528
|
+
# Read a character from a UART device and pass it to the specified block
|
529
|
+
#
|
530
|
+
# @example
|
531
|
+
# uart1.each_char { |x| puts "read: #{x}" }
|
343
532
|
def each_char(&block)
|
344
533
|
UART::each_char(@uart, &block)
|
345
534
|
end
|
346
535
|
|
536
|
+
# Read characters from a UART device and pass them to the specified block
|
537
|
+
#
|
538
|
+
# @param chars should be the number of chars to read
|
539
|
+
#
|
540
|
+
# @example
|
541
|
+
# uart1.each_chars(2) { |x| puts "read: #{x}" }
|
347
542
|
def each_chars(chars, &block)
|
348
543
|
UART::each_chars(@uart, chars, &block)
|
349
544
|
end
|
350
545
|
|
546
|
+
# Read lines from a UART device and pass them to the specified block
|
547
|
+
#
|
548
|
+
# @example
|
549
|
+
# uart1.each_line { |x| puts "read: #{x}" }
|
351
550
|
def each_line(&block)
|
352
551
|
UART::each_line(@uart, &block)
|
353
552
|
end
|
354
553
|
|
554
|
+
# Runs a callback after receiving a line of data from a UART device
|
555
|
+
# This creates a new thread that runs in the background
|
556
|
+
#
|
557
|
+
# @param callback A method to call when the data is received. This method should take 3 arguments, the UART, the line read, and the counter
|
558
|
+
# @param repeats is optional and specifies the number of times the callback will be run
|
559
|
+
#
|
560
|
+
# @example
|
561
|
+
# callback = lambda { |uart, line, count| puts "[#{uart}:#{count}] #{line} "}
|
562
|
+
# uart1.run_on_each_line(callback)
|
355
563
|
def run_on_each_line(callback, repeats=nil)
|
356
564
|
UART::run_on_each_line(callback, @uart, repeats)
|
357
565
|
end
|
358
566
|
|
567
|
+
# Convenience method for run_on_each_line with repeats set to 1
|
568
|
+
# @see #run_on_each_line
|
359
569
|
def run_once_on_each_line(callback)
|
360
570
|
UART::run_once_on_each_line(callback, @uart)
|
361
571
|
end
|
362
572
|
|
363
|
-
|
364
|
-
|
573
|
+
# Runs a callback after receiving data from a UART device
|
574
|
+
# This creates a new thread that runs in the background
|
575
|
+
#
|
576
|
+
# @param callback A method to call when the data is received. This method should take 3 arguments, the UART, the line read, and the counter
|
577
|
+
# @param chars should be the number of chars to read
|
578
|
+
# @param repeats is optional and specifies the number of times the callback will be run
|
579
|
+
#
|
580
|
+
# @example
|
581
|
+
# callback = lambda { |uart, data, count| puts "[#{uart}:#{count}] #{data} "}
|
582
|
+
# uart1.run_on_each_chars(callback, 2)
|
583
|
+
def run_on_each_chars(callback, chars=1, repeats=nil)
|
584
|
+
UART::run_on_each_chars(callback, @uart, chars, repeats)
|
365
585
|
end
|
366
586
|
|
587
|
+
# Convenience method for run_on_each_chars with chars and repeats set to 1
|
588
|
+
# @see #run_on_each_chars
|
367
589
|
def run_once_on_each_char(callback)
|
368
590
|
UART::run_once_on_each_char(callback, @uart)
|
369
591
|
end
|
370
592
|
|
371
|
-
|
372
|
-
|
373
|
-
end
|
374
|
-
|
593
|
+
# Convenience method for run_on_each_chars with chars and repeats set to 1
|
594
|
+
# @see #run_on_each_chars
|
375
595
|
def run_once_on_each_chars(callback, chars=1)
|
376
596
|
UART::run_once_on_each_chars(callback, @uart, chars)
|
377
597
|
end
|
378
598
|
|
599
|
+
# Convenience method for run_on_each_chars with chars set to 1
|
600
|
+
# @see #run_on_each_chars
|
601
|
+
def run_on_each_char(callback, repeats=nil)
|
602
|
+
UART::run_on_each_char(callback, @uart, repeats)
|
603
|
+
end
|
604
|
+
|
605
|
+
# Stops any threads waiting for data on the specified UART
|
379
606
|
def stop_read_wait
|
380
607
|
UART::stop_read_wait(@uart)
|
381
608
|
end
|
382
609
|
|
610
|
+
# Disable a UART device.
|
611
|
+
#
|
612
|
+
# @note device trees cannot be unloaded at this time without kernel panic.
|
383
613
|
def disable
|
384
614
|
UART::disable(@uart)
|
385
615
|
end
|