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