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 ]
UARTTEMPLATE =

dts template for UART3 device

[]

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



397
398
399
400
# File 'lib/beaglebone/uart.rb', line 397

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



376
377
378
379
380
381
382
383
384
385
386
# File 'lib/beaglebone/uart.rb', line 376

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



233
234
235
236
237
238
239
# File 'lib/beaglebone/uart.rb', line 233

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



248
249
250
251
252
253
# File 'lib/beaglebone/uart.rb', line 248

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



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

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



164
165
166
# File 'lib/beaglebone/uart.rb', line 164

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



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/beaglebone/uart.rb', line 177

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



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/beaglebone/uart.rb', line 208

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.chop

  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


364
365
366
# File 'lib/beaglebone/uart.rb', line 364

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)


323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/beaglebone/uart.rb', line 323

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)


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_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


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

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


358
359
360
# File 'lib/beaglebone/uart.rb', line 358

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


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

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



109
110
111
112
113
114
115
# File 'lib/beaglebone/uart.rb', line 109

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



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/beaglebone/uart.rb', line 67

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 we have a dtb to load
  create_device_tree(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



389
390
391
392
393
394
# File 'lib/beaglebone/uart.rb', line 389

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



126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/beaglebone/uart.rb', line 126

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


152
153
154
# File 'lib/beaglebone/uart.rb', line 152

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