Class: CCutrer::SerialPort

Inherits:
File
  • Object
show all
Defined in:
lib/ccutrer-serialport.rb,
lib/ccutrer/serial_port.rb,
lib/ccutrer/serial_port/version.rb

Defined Under Namespace

Modules: Termios

Constant Summary collapse

ON_WINDOWS =
RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
ON_LINUX =
RbConfig::CONFIG['host_os'] =~ /linux/i
VERSION =
"1.1.0"

Instance Method Summary collapse

Constructor Details

#initialize(address, baud: nil, data_bits: nil, parity: nil, stop_bits: nil) ⇒ SerialPort

Returns a new instance of SerialPort.

Raises:

  • (IOError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/ccutrer/serial_port.rb', line 6

def initialize(address, baud: nil, data_bits: nil, parity: nil, stop_bits: nil)
  super(address, IO::RDWR | IO::NOCTTY | IO::NONBLOCK)

  raise IOError, "Not a serial port" unless tty?

  fl = fcntl(Fcntl::F_GETFL, 0)
  fcntl(Fcntl::F_SETFL, ~Fcntl::O_NONBLOCK & fl)

  @termios = Termios::Termios.new
  refresh

  # base config
  @termios[:c_iflag] = Termios::IGNPAR
  @termios[:c_oflag] = 0
  @termios[:c_cflag] =
    Termios::CREAD |
    Termios::CLOCAL
  @termios[:c_lflag] = 0

  @termios[:c_cc][Termios::VTIME] = 0
  @termios[:c_cc][Termios::VMIN] = 0

  configure do
    self.baud = baud if baud
    self.data_bits = data_bits if data_bits
    self.parity = parity if parity
    self.stop_bits = stop_bits if stop_bits
  end
  raise Errno::EINVAL if baud && baud != self.baud
  raise Errno::EINVAL if data_bits && data_bits != self.data_bits
  raise Errno::EINVAL if parity && parity != self.parity
  raise Errno::EINVAL if stop_bits && stop_bits != self.stop_bits
end

Instance Method Details

#baudObject



50
51
52
# File 'lib/ccutrer/serial_port.rb', line 50

def baud
  Termios::BAUD_RATES.invert[Termios.cfgetispeed(@termios)]
end

#baud=(baud) ⇒ Object

Raises:

  • (ArgumentError)


54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ccutrer/serial_port.rb', line 54

def baud=(baud)
  raise ArgumentError, "Invalid baud" unless Termios::BAUD_RATES.key?(baud)

  err = Termios.cfsetispeed(@termios, Termios::BAUD_RATES[baud])
  raise SystemCallError, FFI.errno if err == -1
  err = Termios.cfsetospeed(@termios, Termios::BAUD_RATES[baud])
  raise SystemCallError, FFI.errno if err == -1
  apply  
  refresh
  self.baud
end

#configureObject



40
41
42
43
44
45
46
47
48
# File 'lib/ccutrer/serial_port.rb', line 40

def configure
  @configuring = true
  yield
  @configuring = false
  apply
  refresh
ensure
  @configuring = false
end

#data_bitsObject



66
67
68
# File 'lib/ccutrer/serial_port.rb', line 66

def data_bits
  Termios::DATA_BITS.invert[@termios[:c_cflag] & Termios::CSIZE]
end

#data_bits=(data_bits) ⇒ Object

Raises:

  • (ArgumentError)


70
71
72
73
74
75
76
77
78
# File 'lib/ccutrer/serial_port.rb', line 70

def data_bits=(data_bits)
  raise ArgumentError, "Invalid data bits" unless Termios::DATA_BITS.key?(data_bits)

  @termios[:c_cflag] &= ~Termios::CSIZE
  @termios[:c_cflag] |= Termios::DATA_BITS[data_bits]
  apply
  refresh
  self.data_bits
end

#inspectObject



108
109
110
# File 'lib/ccutrer/serial_port.rb', line 108

def inspect
  "#<#{self.class.name}:#{path} #{baud} #{data_bits}#{parity.to_s[0].upcase}#{stop_bits}>"
end

#parityObject



80
81
82
# File 'lib/ccutrer/serial_port.rb', line 80

def parity
  Termios::PARITY.invert[@termios[:c_cflag] & Termios::PARITY[:odd]]
end

#parity=(parity) ⇒ Object

Raises:

  • (ArgumentError)


84
85
86
87
88
89
90
91
92
# File 'lib/ccutrer/serial_port.rb', line 84

def parity=(parity)
  raise ArgumentError, "Invalid parity" unless Termios::PARITY.key?(parity)

  @termios[:c_cflag] &= ~Termios::PARITY[:odd]
  @termios[:c_cflag] |= Termios::PARITY[parity]
  apply
  refresh
  self.parity
end

#stop_bitsObject



94
95
96
# File 'lib/ccutrer/serial_port.rb', line 94

def stop_bits
  (@termios[:c_cflag] & Termios::CSTOPB) != 0 ? 2 : 1
end

#stop_bits=(stop_bits) ⇒ Object

Raises:

  • (ArgumentError)


98
99
100
101
102
103
104
105
106
# File 'lib/ccutrer/serial_port.rb', line 98

def stop_bits=(stop_bits)
  raise ArgumentError, "Invalid stop bits" unless Termios::STOP_BITS.key?(stop_bits)

  @termios[:c_cflag] &= ~Termios::CSTOPB
  @termios[:c_cflag] |= Termios::STOP_BITS[stop_bits]
  apply
  refresh
  self.stop_bits
end