Class: Rbuspirate::Interfaces::I2C

Inherits:
Abstract
  • Object
show all
Defined in:
lib/rbuspirate/interfaces/i2c.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Abstract

#configure_peripherals

Constructor Details

#initialize(serial, bup) ⇒ I2C

Returns a new instance of I2C.



11
12
13
14
15
16
# File 'lib/rbuspirate/interfaces/i2c.rb', line 11

def initialize(serial, bup)
  raise 'Bus pirate must be in i2c mode' unless bup.mode == :i2c

  @le_port = serial
  set_speed(:'400khz')
end

Instance Attribute Details

#auxObject (readonly)

Returns the value of attribute aux.



9
10
11
# File 'lib/rbuspirate/interfaces/i2c.rb', line 9

def aux
  @aux
end

#csObject (readonly)

Returns the value of attribute cs.



9
10
11
# File 'lib/rbuspirate/interfaces/i2c.rb', line 9

def cs
  @cs
end

#powerObject (readonly)

Returns the value of attribute power.



9
10
11
# File 'lib/rbuspirate/interfaces/i2c.rb', line 9

def power
  @power
end

#pullupObject (readonly)

Returns the value of attribute pullup.



9
10
11
# File 'lib/rbuspirate/interfaces/i2c.rb', line 9

def pullup
  @pullup
end

#speedObject

Returns the value of attribute speed.



9
10
11
# File 'lib/rbuspirate/interfaces/i2c.rb', line 9

def speed
  @speed
end

Instance Method Details

#bulk_write(data, ack_timeout: Timeouts::I2C::SLAVE_ACKNACK) ⇒ Object

Raises:

  • (ArgumentError)


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
# File 'lib/rbuspirate/interfaces/i2c.rb', line 67

def bulk_write(data, ack_timeout: Timeouts::I2C::SLAVE_ACKNACK)
  raise ArgumentError, 'data must be String instance' unless data.instance_of?(String)

  if !data.instance_of?(String) || data.instance_of?(String) && data.empty?
    raise ArgumentError, 'Bad data argument'
  end
  raise ArgumentError, 'Data is too long' if data.bytesize > 16

  bit_bulk_write = Commands::I2C::PREPARE_WRITE | data.bytesize - 1
  simplex_command(
    bit_bulk_write.chr,
    Timeouts::I2C::PREPARE_WRITE,
    'Unable to prepare write mode'
  )
  ack_array = []
  data.each_byte do |data_byte|
    @le_port.write(data_byte.chr)
    Timeout.timeout(ack_timeout) do
      ack_array << case @le_port.read(1).ord
                   when 0
                     :ack
                   when 1
                     :nack
                   else
                     raise 'Unknown bytewrite response'
                   end
      yield(ack_array.last) if block_given?
    end
  end
  ack_array.freeze
end

#read(bytes = 1, auto_ack: true, auto_nack: true, readbyte_timeout: Timeouts::I2C::READ) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rbuspirate/interfaces/i2c.rb', line 54

def read(bytes = 1, auto_ack: true, auto_nack: true, readbyte_timeout: Timeouts::I2C::READ)
  result = ''.dup.b
  bytes.times do |t|
    @le_port.write(Commands::I2C::READBYTE.chr)
    Timeout.timeout(readbyte_timeout) do
      result << @le_port.read(1)
    end
    send_ack if auto_ack && t + 1 != bytes
    send_nack if auto_nack && t + 1 == bytes
  end
  result
end

#send_ackObject



38
39
40
41
42
43
44
# File 'lib/rbuspirate/interfaces/i2c.rb', line 38

def send_ack
  simplex_command(
    Commands::I2C::Flow::ACK,
    Timeouts::I2C::ACKNACK,
    'Unable to sent ack'
  )
end

#send_nackObject



46
47
48
49
50
51
52
# File 'lib/rbuspirate/interfaces/i2c.rb', line 46

def send_nack
  simplex_command(
    Commands::I2C::Flow::NACK,
    Timeouts::I2C::ACKNACK,
    'Unable to sent nack'
  )
end

#send_startObject



22
23
24
25
26
27
28
# File 'lib/rbuspirate/interfaces/i2c.rb', line 22

def send_start
  simplex_command(
    Commands::I2C::Flow::START,
    Timeouts::I2C::STARTSTOP,
    'Unable to sent start bit'
  )
end

#send_stopObject



30
31
32
33
34
35
36
# File 'lib/rbuspirate/interfaces/i2c.rb', line 30

def send_stop
  simplex_command(
    Commands::I2C::Flow::STOP,
    Timeouts::I2C::STARTSTOP,
    'Unable to sent stop bit'
  )
end

#write_then_read(data, expected_bytes = 0, succes_timeout: Timeouts::I2C::WRITE_THEN_READ_S, allow_zerobyte: false) ⇒ Object

Raises:

  • (ArgumentError)


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/rbuspirate/interfaces/i2c.rb', line 99

def write_then_read(
  data, expected_bytes = 0,
  succes_timeout: Timeouts::I2C::WRITE_THEN_READ_S,
  allow_zerobyte: false
)
  raise ArgumentError, 'Bad data type' unless data.instance_of?(String)
  raise ArgumentError, 'Data is too long' if data.bytesize > 4096
  raise ArgumentError, 'Bad expected_bytes type' unless expected_bytes.instance_of?(Integer)
  raise ArgumentError, 'Bad expected_bytes value' if expected_bytes.negative? || expected_bytes > 4096

  binary_command = Commands::I2C::WRITE_THEN_READ.chr +
                   [data.bytesize, expected_bytes].pack('S>S>') +
                   data
  @le_port.write(binary_command)
  result = nil
  # So fucking ugly
  begin
    Timeout.timeout(succes_timeout) do
      result = @le_port.read(1)
    end
  rescue Timeout::Error
    return false
  end
  return false if allow_zerobyte && result.ord.zero?
  raise 'Write failed' if result.ord.zero?
  if expected_bytes != 0
    Timeout.timeout(Timeouts::I2C::WRITE_THEN_READ_D) do
      result = @le_port.read(expected_bytes)
    end
    result
  else
    true
  end
end