Class: LGPIO::SPIBitBang

Inherits:
Object
  • Object
show all
Defined in:
lib/lgpio/spi_bitbang.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ SPIBitBang

Returns a new instance of SPIBitBang.

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/lgpio/spi_bitbang.rb', line 6

def initialize(options={})
  clock  = options[:clock]
  input  = options[:input]
  output = options[:output]

  @clock_handle   = clock[:handle] if clock
  @clock_line     = clock[:line]   if clock
  raise ArgumentError, ":clock pin required as Hash, with :handle and :line required" unless (@clock_handle && @clock_line)

  @input_handle   = input[:handle]  if input
  @input_line     = input[:line]    if input
  @output_handle  = output[:handle] if output
  @output_line    = output[:line]   if output
  unless ((@input_handle && @input_line) || (@output_handle && @output_line))
    raise ArgumentError, "either :input or :output pin required as Hash, with :handle and :line required"
  end

  @output_state = nil
  initialize_pins
end

Instance Attribute Details

#clock_handleObject (readonly)

Returns the value of attribute clock_handle.



3
4
5
# File 'lib/lgpio/spi_bitbang.rb', line 3

def clock_handle
  @clock_handle
end

#clock_lineObject (readonly)

Returns the value of attribute clock_line.



4
5
6
# File 'lib/lgpio/spi_bitbang.rb', line 4

def clock_line
  @clock_line
end

#input_handleObject (readonly)

Returns the value of attribute input_handle.



3
4
5
# File 'lib/lgpio/spi_bitbang.rb', line 3

def input_handle
  @input_handle
end

#input_lineObject (readonly)

Returns the value of attribute input_line.



4
5
6
# File 'lib/lgpio/spi_bitbang.rb', line 4

def input_line
  @input_line
end

#output_handleObject (readonly)

Returns the value of attribute output_handle.



3
4
5
# File 'lib/lgpio/spi_bitbang.rb', line 3

def output_handle
  @output_handle
end

#output_lineObject (readonly)

Returns the value of attribute output_line.



4
5
6
# File 'lib/lgpio/spi_bitbang.rb', line 4

def output_line
  @output_line
end

Instance Method Details

#configObject



27
28
29
# File 'lib/lgpio/spi_bitbang.rb', line 27

def config
  @config ||= [clock_handle, clock_line, input_handle, input_line, output_handle, output_line]
end

#initialize_pinsObject



31
32
33
34
35
# File 'lib/lgpio/spi_bitbang.rb', line 31

def initialize_pins
  LGPIO.gpio_claim_output(clock_handle,  clock_line,  LGPIO::SET_PULL_NONE, LGPIO::LOW)
  LGPIO.gpio_claim_input(input_handle,   input_line,  LGPIO::SET_PULL_NONE)             if input_line
  LGPIO.gpio_claim_output(output_handle, output_line, LGPIO::SET_PULL_NONE, LGPIO::LOW) if output_line
end

#set_output(level) ⇒ Object



37
38
39
40
# File 'lib/lgpio/spi_bitbang.rb', line 37

def set_output(level)
  return if (level == @output_state)
  LGPIO.gpio_write(output_handle, output_line, @output_state = level)
end

#transfer(write: [], read: 0, select: nil, order: :msbfirst, mode: 0) ⇒ Object

Raises:

  • (ArgumentError)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/lgpio/spi_bitbang.rb', line 94

def transfer(write: [], read: 0, select: nil, order: :msbfirst, mode: 0)
  # Idle clock state depends on SPI mode.
  case mode
  when 0..1
    LGPIO.gpio_write(clock_handle, clock_line, 0)
  when 2..3
    LGPIO.gpio_write(clock_handle, clock_line, 1)
  else
    raise ArgumentError, "invalid SPI mode: #{mode} given"
  end
  raise ArgumentError, "invalid Array for write: #{write}" unless write.kind_of?(Array)
  raise ArgumentError, "invalid Integer for read: #{read}" unless read.kind_of?(Integer)

  read_bytes = (read > 0) ? [] : nil
  LGPIO.gpio_write(select[:handle], select[:line], 0) if select

  i = 0
  while (i < read) || (i < write.length)
    read_byte = transfer_byte(write[i], reading: (i < read), order: order, mode: mode)
    read_bytes << read_byte if read_byte
    i = i + 1
  end

  LGPIO.gpio_write(select[:handle], select[:line], 1) if select
  read_bytes
end

#transfer_bit(write_bit, reading: false, mode: 0) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/lgpio/spi_bitbang.rb', line 42

def transfer_bit(write_bit, reading: false, mode: 0)
  case mode
  when 0
    set_output(write_bit) if write_bit
    LGPIO.gpio_write(clock_handle, clock_line, 1)
    read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
    LGPIO.gpio_write(clock_handle, clock_line, 0)
  when 1
    LGPIO.gpio_write(clock_handle, clock_line, 1)
    set_output(write_bit) if write_bit
    LGPIO.gpio_write(clock_handle, clock_line, 0)
    read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
  when 2
    set_output(write_bit) if write_bit
    LGPIO.gpio_write(clock_handle, clock_line, 0)
    read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
    LGPIO.gpio_write(clock_handle, clock_line, 1)
  when 3
    LGPIO.gpio_write(clock_handle, clock_line, 0)
    set_output(write_bit) if write_bit
    LGPIO.gpio_write(clock_handle, clock_line, 1)
    read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
  else
    raise ArgumentError, "invalid SPI mode: #{mode} given"
  end
  return reading ? read_bit : nil
end

#transfer_byte(byte, reading: false, order: :msbfirst, mode: 0) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/lgpio/spi_bitbang.rb', line 70

def transfer_byte(byte, reading: false, order: :msbfirst, mode: 0)
  read_byte = reading ? 0 : nil

  if (order == :msbfirst)
    i = 7
    while i >= 0
      write_bit = byte ? (byte >> i) & 0b1 : nil
      read_bit  = transfer_bit(write_bit, mode: mode, reading: reading)
      read_byte = (read_byte << 1) | read_bit if reading
      i = i - 1
    end
  else
    i = 0
    while i < 8
      write_bit = byte ? (byte >> i) : nil
      read_bit  = transfer_bit(write_bit, mode: mode, reading: reading)
      read_byte = read_byte | (read_bit << i) if reading
      i = i + 1
    end
  end

  read_byte
end