Class: ChipGPIO::HardwareSPI
- Inherits:
-
Object
- Object
- ChipGPIO::HardwareSPI
- Defined in:
- lib/chip-gpio/HardwareSpi.rb
Constant Summary collapse
- SPI_MAX_CHUNK_BYTES =
64- SPI_IOC_RD_MODE =
0x80016b01- SPI_IOC_WR_MODE =
0x40016b01- SPI_IOC_RD_LSB_FIRST =
0x80016b02- SPI_IOC_WR_LSB_FIRST =
0x40016b02- SPI_IOC_RD_BITS_PER_WORD =
0x80016b03- SPI_IOC_WR_BITS_PER_WORD =
0x40016b03- SPI_IOC_RD_MAX_SPEED_HZ =
0x80046b04- SPI_IOC_WR_MAX_SPEED_HZ =
0x40046b04- SPI_IOC_RD_MODE32 =
0x80046b05- SPI_IOC_WR_MODE32 =
0x40046b05- SPI_IOC_MESSAGE_1 =
can only be used to send one spi_ioc_transfer struct at a time
0x40206b00- SPI_CPHA =
0x01- SPI_CPOL =
0x02
Instance Attribute Summary collapse
-
#lsb_first ⇒ Object
readonly
Returns the value of attribute lsb_first.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#phase ⇒ Object
readonly
Returns the value of attribute phase.
-
#polarity ⇒ Object
readonly
Returns the value of attribute polarity.
-
#speed_hz ⇒ Object
readonly
Returns the value of attribute speed_hz.
-
#word_size ⇒ Object
readonly
Returns the value of attribute word_size.
Instance Method Summary collapse
- #break_words_into_nibbles(words: []) ⇒ Object
- #close ⇒ Object
-
#initialize(polarity: 0, phase: 0, word_size: 8, lsb_first: false) ⇒ HardwareSPI
constructor
A new instance of HardwareSPI.
- #pack_words_into_bytes(words: []) ⇒ Object
- #read_u32(msg) ⇒ Object
- #read_u8(msg) ⇒ Object
- #test ⇒ Object
- #to_s ⇒ Object
- #transfer_bytes(bytes: []) ⇒ Object
- #transfer_data(words: []) ⇒ Object
- #write_u32(msg, value) ⇒ Object
- #write_u8(msg, value) ⇒ Object
Constructor Details
#initialize(polarity: 0, phase: 0, word_size: 8, lsb_first: false) ⇒ HardwareSPI
Returns a new instance of HardwareSPI.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 28 def initialize(polarity: 0, phase: 0, word_size: 8, lsb_first: false) @polarity = polarity @phase = phase @word_size = word_size @lsb_first = lsb_first @speed_hz = 1000000 #TODO Configurable parameter @device = open("/dev/spidev32766.0", File::RDWR) @mode = 0 @mode = @mode | 0x01 if (phase == 1) @mode = @mode | 0x02 if (polarity == 1) write_u8(SPI_IOC_WR_MODE, @mode) write_u8(SPI_IOC_WR_LSB_FIRST, (@lsb_first ? 1 : 0)) write_u32(SPI_IOC_WR_MAX_SPEED_HZ, @speed_hz) end |
Instance Attribute Details
#lsb_first ⇒ Object (readonly)
Returns the value of attribute lsb_first.
6 7 8 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 6 def lsb_first @lsb_first end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
7 8 9 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 7 def mode @mode end |
#phase ⇒ Object (readonly)
Returns the value of attribute phase.
4 5 6 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 4 def phase @phase end |
#polarity ⇒ Object (readonly)
Returns the value of attribute polarity.
3 4 5 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 3 def polarity @polarity end |
#speed_hz ⇒ Object (readonly)
Returns the value of attribute speed_hz.
8 9 10 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 8 def speed_hz @speed_hz end |
#word_size ⇒ Object (readonly)
Returns the value of attribute word_size.
5 6 7 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 5 def word_size @word_size end |
Instance Method Details
#break_words_into_nibbles(words: []) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 73 def break_words_into_nibbles(words: []) nibbles_per_word = @word_size / 4 #for each word, output each nibble individually #(shifting by 4 each time since a nibble is 4 bits) words.each do |w| #this is basically the reverse of nibbles_per_word.times #we reverse it because we want to start at the most-significant nibble #which will be shifted the most times # #since we want to end up at 0, subtract one from nibbles_per_word #so we don't get an extra (nibbles_per_word - 1).downto(0).each do |i| yield w, ((w >> (i * 4)) & 0xf) end end end |
#close ⇒ Object
47 48 49 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 47 def close() @device.close() end |
#pack_words_into_bytes(words: []) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 92 def pack_words_into_bytes(words: []) nibbles_per_word = @word_size / 4 bytes = [] current_byte = 0 new_byte = true break_words_into_nibbles(words: words) do |current_word, current_nibble| if new_byte new_byte = false current_byte = current_byte | (current_nibble << 4) else current_byte = current_byte | current_nibble bytes << current_byte current_byte = 0 new_byte = true end end return bytes end |
#read_u32(msg) ⇒ Object
62 63 64 65 66 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 62 def read_u32(msg) value_packed = [0].pack("L") @device.ioctl(msg, value_packed) return value_packed.unpack("L")[0] end |
#read_u8(msg) ⇒ Object
51 52 53 54 55 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 51 def read_u8(msg) value_packed = [0].pack("C") @device.ioctl(msg, value_packed) return value_packed.unpack("C")[0] end |
#test ⇒ Object
159 160 161 162 163 164 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 159 def test() words = [] 24.times { |i| words << 0 } transfer_data(words: words) end |
#to_s ⇒ Object
166 167 168 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 166 def to_s return "\#<ChipGPIO:HardwareSPI mode=#{@mode} device=#{@device.path} word_size=#{@word_size} lsb_first=#{@lsb_first}>" end |
#transfer_bytes(bytes: []) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 115 def transfer_bytes(bytes: []) # http://stackoverflow.com/questions/11949538/pointers-to-buffer-in-ioctl-call raise "Too many bytes sent to transfer_bytes" if bytes.size > SPI_MAX_CHUNK_BYTES #begin spi_ioc_transfer struct (cat /usr/include/linux/spi/spidev.h) tx_buff = bytes.pack("C*") rx_buff = (Array.new(bytes.size) { 0 }).pack("C*") tx_buff_pointer = [tx_buff].pack("P").unpack("L!")[0] #u64 (zero-extended pointer) rx_buff_pointer = [rx_buff].pack("P").unpack("L!")[0] #u64 (zero-extended pointer) buff_len = bytes.size #u32 speed_hz = @speed_hz #u32 delay_usecs = 0 #u16 bits_per_word = 8 #u8 cs_change = 0 #u8 tx_nbits = 0 #u8 rx_nbits = 0 #u8 pad = 0 #u16 struct_array = [tx_buff_pointer, rx_buff_pointer, buff_len, speed_hz, delay_usecs, bits_per_word, cs_change, tx_nbits, rx_nbits, pad] struct_packed = struct_array.pack("QQLLSCCCCS") #end spi_ioc_transfer struct @device.ioctl(SPI_IOC_MESSAGE_1, struct_packed) return rx_buff.unpack("C*") end |
#transfer_data(words: []) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 146 def transfer_data(words: []) bytes_to_transfer = pack_words_into_bytes(words: words) result = [] bytes_to_transfer.each_slice(SPI_MAX_CHUNK_BYTES) do |chunk_bytes| result = result + transfer_bytes(bytes: chunk_bytes) end return result end |
#write_u32(msg, value) ⇒ Object
68 69 70 71 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 68 def write_u32(msg, value) value_packed = [value].pack("L") @device.ioctl(msg, value_packed) end |
#write_u8(msg, value) ⇒ Object
57 58 59 60 |
# File 'lib/chip-gpio/HardwareSpi.rb', line 57 def write_u8(msg, value) value_packed = [value].pack("C") @device.ioctl(msg, value_packed) end |