Module: Beaglebone::UART

Defined in:
lib/beaglebone/uart.rb

Overview

UART

Procedural methods for UART control

Summary

#setup is called to initialize a UART device

Constant Summary collapse

SPEEDS =

Valid UART speeds

[ 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, 57600, 115200 ]

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.uartmutexObject

Returns the value of attribute uartmutex.



16
17
18
# File 'lib/beaglebone/uart.rb', line 16

def uartmutex
  @uartmutex
end

.uartstatusObject

Returns the value of attribute uartstatus.



16
17
18
# File 'lib/beaglebone/uart.rb', line 16

def uartstatus
  @uartstatus
end

Class Method Details

.cleanupObject

Disable all UART devices



353
354
355
356
# File 'lib/beaglebone/uart.rb', line 353

def cleanup
  #reset all UARTs we've used and unload the device tree
  uartstatus.clone.keys.each { |uart| disable(uart)}
end

.disable(uart) ⇒ Object

Note:

device trees cannot be unloaded at this time without kernel panic.

Disable a UART device.

Examples:

UART.disable(:UART1)

Parameters:

  • uart

    should be a symbol representing the UART device



332
333
334
335
336
337
338
339
340
341
342
# File 'lib/beaglebone/uart.rb', line 332

def disable(uart)
  check_uart_valid(uart)
  check_uart_enabled(uart)

  stop_read_wait(uart)

  disable_uart_pin(UARTS[uart][:rx]) if UARTS[uart][:rx]
  disable_uart_pin(UARTS[uart][:tx]) if UARTS[uart][:tx]

  delete_uart_status(uart)
end

.each_char(uart) ⇒ Object

Read a character from a UART device and pass it to the specified block

Examples:

UART.each_char(:UART1) { |x| puts "read: #{x}" }

Parameters:

  • uart

    should be a symbol representing the UART device



189
190
191
192
193
194
195
# File 'lib/beaglebone/uart.rb', line 189

def each_char(uart)
  loop do
    data = readchars(uart, 1)
    yield data
  end

end

.each_chars(uart, chars) ⇒ Object

Read characters from a UART device and pass them to the specified block

Examples:

UART.each_chars(:UART1, 2) { |x| puts "read: #{x}" }

Parameters:

  • uart

    should be a symbol representing the UART device

  • chars

    should be the number of chars to read



204
205
206
207
208
209
# File 'lib/beaglebone/uart.rb', line 204

def each_chars(uart, chars)
  loop do
    data = readchars(uart, chars)
    yield data
  end
end

.each_line(uart) ⇒ Object

Read lines from a UART device and pass them to the specified block

Examples:

UART.each_line(:UART1) { |x| puts "read: #{x}" }

Parameters:

  • uart

    should be a symbol representing the UART device



218
219
220
221
222
223
# File 'lib/beaglebone/uart.rb', line 218

def each_line(uart)
  loop do
    data = readline(uart)
    yield data
  end
end

.readchar(uart) ⇒ Object

Read one character from a UART device

Examples:

UART.readchars(:UART1) => "x"

Parameters:

  • uart

    should be a symbol representing the UART device

Returns:

  • String the character read from the UART device



120
121
122
# File 'lib/beaglebone/uart.rb', line 120

def readchar(uart)
  readchars(uart, 1)
end

.readchars(uart, bytes) ⇒ Object

Read characters from a UART device

Examples:

UART.readchars(:UART1, 2) => "xx"

Parameters:

  • uart

    should be a symbol representing the UART device

  • bytes

    number of bytes to read

Returns:

  • String the characters read from the UART device



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/beaglebone/uart.rb', line 133

def readchars(uart, bytes)
  check_uart_enabled(uart)
  ensure_read_lock(uart)

  buffer = ''

  pin_rx = UARTS[uart][:rx]

  Beaglebone::check_valid_pin(pin_rx, :uart)

  fd = Beaglebone::get_pin_status(pin_rx, :fd_uart)

  set_uart_status(uart, :waiting, true)

  while bytes > 0 do
    buffer << fd.readchar
    bytes -= 1
  end
  set_uart_status(uart, :waiting, false)

  buffer
end

.readline(uart) ⇒ Object

Read a line from a UART device

Examples:

UART.readline(:UART1) => "A line of text"

Parameters:

  • uart

    should be a symbol representing the UART device

Returns:

  • String the line read from the UART device



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/beaglebone/uart.rb', line 164

def readline(uart)
  check_uart_enabled(uart)
  ensure_read_lock(uart)

  pin_rx = UARTS[uart][:rx]

  Beaglebone::check_valid_pin(pin_rx, :uart)

  fd = Beaglebone::get_pin_status(pin_rx, :fd_uart)

  set_uart_status(uart, :waiting, true)

  data = fd.readline.strip

  set_uart_status(uart, :waiting, false)

  data
end

.run_on_each_char(callback, uart, repeats = nil) ⇒ Object

Convenience method for run_on_each_chars with chars set to 1

See Also:

  • #run_on_each_chars


320
321
322
# File 'lib/beaglebone/uart.rb', line 320

def run_on_each_char(callback, uart, repeats=nil)
  run_on_each_chars(callback, uart, 1, repeats)
end

.run_on_each_chars(callback, uart, chars = 1, repeats = nil) ⇒ Object

Runs a callback after receiving data from a UART device This creates a new thread that runs in the background

Examples:

callback = lambda { |uart, data, count| puts "[#{uart}:#{count}] #{data} "}
UART.run_on_each_chars(callback, :UART1, 2)

Parameters:

  • callback

    A method to call when the data is received. This method should take 3 arguments, the UART, the line read, and the counter

  • uart

    should be a symbol representing the UART device

  • chars (defaults to: 1)

    should be the number of chars to read

  • repeats (defaults to: nil)

    is optional and specifies the number of times the callback will be run

Raises:

  • (StandardError)


279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/beaglebone/uart.rb', line 279

def run_on_each_chars(callback, uart, chars=1, repeats=nil)
  check_uart_enabled(uart)

  raise StandardError, "Already waiting for data on uart: #{uart}" if get_uart_status(uart, :waiting)
  raise StandardError, "Already waiting for data on uart: #{uart}" if get_uart_status(uart, :thread)

  thread = Thread.new(callback, uart, chars, repeats) do |c, u, ch, r|
    begin
      count = 0
      each_chars(u, ch) do |line|

        c.call(u, line, count) if c

        count += 1
        break if r && count >= r
      end
    rescue => ex
      puts ex
      puts ex.backtrace
    ensure
      delete_uart_status(u, :thread)
      set_uart_status(uart, :waiting, false)
    end
  end
  set_uart_status(uart, :thread, thread)
end

.run_on_each_line(callback, uart, repeats = nil) ⇒ Object

Runs a callback after receiving a line of data from a UART device This creates a new thread that runs in the background

Examples:

callback = lambda { |uart, line, count| puts "[#{uart}:#{count}] #{line} "}
UART.run_on_each_line(callback, :UART1)

Parameters:

  • callback

    A method to call when the data is received. This method should take 3 arguments, the UART, the line read, and the counter

  • uart

    should be a symbol representing the UART device

  • repeats (defaults to: nil)

    is optional and specifies the number of times the callback will be run

Raises:

  • (StandardError)


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/beaglebone/uart.rb', line 235

def run_on_each_line(callback, uart, repeats=nil)
  check_uart_enabled(uart)

  raise StandardError, "Already waiting for data on uart: #{uart}" if get_uart_status(uart, :waiting)
  raise StandardError, "Already waiting for data on uart: #{uart}" if get_uart_status(uart, :thread)

  thread = Thread.new(callback, uart, repeats) do |c, u, r|
    begin
      count = 0
      each_line(u) do |line|

        c.call(u, line, count) if c

        count += 1
        break if r && count >= r
      end
    rescue => ex
      puts ex
      puts ex.backtrace
    ensure
      delete_uart_status(u, :thread)
      set_uart_status(uart, :waiting, false)
    end
  end
  set_uart_status(uart, :thread, thread)
end

.run_once_on_each_char(callback, uart) ⇒ Object

Convenience method for run_on_each_chars with chars and repeats set to 1

See Also:

  • #run_on_each_chars


308
309
310
# File 'lib/beaglebone/uart.rb', line 308

def run_once_on_each_char(callback, uart)
  run_once_on_each_chars(callback, uart, 1)
end

.run_once_on_each_chars(callback, uart, chars = 1) ⇒ Object

Convenience method for run_on_each_chars with chars and repeats set to 1

See Also:

  • #run_on_each_chars


314
315
316
# File 'lib/beaglebone/uart.rb', line 314

def run_once_on_each_chars(callback, uart, chars=1)
  run_on_each_chars(callback, uart, chars, 1)
end

.run_once_on_each_line(callback, uart) ⇒ Object

Convenience method for run_on_each_line with repeats set to 1

See Also:

  • #run_on_each_line


264
265
266
# File 'lib/beaglebone/uart.rb', line 264

def run_once_on_each_line(callback, uart)
  run_on_each_line(callback, uart, 1)
end

.set_speed(uart, speed) ⇒ Object

Set the speed of the UART

Examples:

UART.set_speed(:UART1, 9600)

Parameters:

  • speed

    should be an integer thats a valid speed. @see SPEEDS



65
66
67
68
69
70
71
# File 'lib/beaglebone/uart.rb', line 65

def set_speed(uart, speed)
  check_uart_valid(uart)
  check_speed_valid(speed)

  uartinfo = UARTS[uart]
  system("stty -F #{uartinfo[:dev]} #{speed}")
end

.setup(uart, speed = 9600) ⇒ Object

Initialize a UART device

Examples:

UART.setup(:UART1, 9600)

Parameters:

  • uart

    should be a symbol representing the UART device

  • speed (defaults to: 9600)

    should be an integer thats a valid speed. @see SPEEDS



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/beaglebone/uart.rb', line 26

def setup(uart, speed=9600)
  check_uart_valid(uart)
  check_speed_valid(speed)

  #make sure uart not already enabled
  return if get_uart_status(uart)

  uartinfo = UARTS[uart]

  #ensure dtb is loaded
  Beaglebone::device_tree_load("#{TREES[:UART][:pin]}#{uartinfo[:id]}")

  #open the uart device
  uart_fd = File.open(uartinfo[:dev], 'r+')

  if uartinfo[:tx]
    Beaglebone::set_pin_status(uartinfo[:tx], :uart, uartinfo[:id])
    Beaglebone::set_pin_status(uartinfo[:tx], :type, :uart)
    Beaglebone::set_pin_status(uartinfo[:tx], :fd_uart, uart_fd)
  end

  if uartinfo[:rx]
    Beaglebone::set_pin_status(uartinfo[:rx], :uart, uartinfo[:id])
    Beaglebone::set_pin_status(uartinfo[:tx], :type, :uart)
    Beaglebone::set_pin_status(uartinfo[:rx], :fd_uart, uart_fd)
  end

  system("stty -F #{uartinfo[:dev]} raw")
  system("stty -F #{uartinfo[:dev]} #{speed}")

  set_uart_status(uart, :fd_uart, uart_fd)
end

.stop_read_wait(uart) ⇒ Object

Stops any threads waiting for data on the specified UART



345
346
347
348
349
350
# File 'lib/beaglebone/uart.rb', line 345

def stop_read_wait(uart)
  thread = get_uart_status(uart, :thread)

  thread.exit if thread
  thread.join if thread
end

.write(uart, data) ⇒ Object

Write data to a UART device

Examples:

UART.write(:UART1, "1234") => 4

Parameters:

  • uart

    should be a symbol representing the UART device

  • data

    the data to write

Returns:

  • Integer the number of bytes written



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/beaglebone/uart.rb', line 82

def write(uart, data)
  check_uart_enabled(uart)

  pin_tx = UARTS[uart][:tx]

  Beaglebone::check_valid_pin(pin_tx, :uart)

  fd = Beaglebone::get_pin_status(pin_tx, :fd_uart)

  ret = fd.write(data)
  fd.flush

  ret
end

.writeln(uart, data) ⇒ Object

Write a line data to a UART device. This is a convenience method using #write

Examples:

UART.writeln(:UART1, "1234") => 5

Parameters:

  • uart

    should be a symbol representing the UART device

  • data

    the data to write

Returns:

  • Integer the number of bytes written

See Also:

  • #write


108
109
110
# File 'lib/beaglebone/uart.rb', line 108

def writeln(uart, data)
  write(uart, data + "\n")
end