rbuspirate 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0b41cd3f0836279a307505163fc2689965c89f1da8a9e526388b805727e85b41
4
+ data.tar.gz: 9f8f4bd005c80e96776d0527b1a5f521fa1a639b095585551812f9f48da4d11d
5
+ SHA512:
6
+ metadata.gz: 206e7ca0c8075ef15f23ec0bb0b8e0d772d4173eb9abaec99388e2de095ed2cbc72d48e745e62c257898a94b541a910723f4005c8e4de8f200c63a14cabc2d0b
7
+ data.tar.gz: 62672ed1d3ffc5168f38d70796cae79d6120a732507076ad16567c211620ba34404834a42cc8d3d3fb3f187a7daafa74cee4cabb1461ef8f1ae0c77df7194efe
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rbuspirate.gemspec
4
+ gemspec
5
+
6
+ gem "pry", "~> 0.12.2"
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rbuspirate (0.2.2)
5
+ serialport (~> 1.3)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.1.2)
11
+ method_source (0.9.2)
12
+ pry (0.12.2)
13
+ coderay (~> 1.1.0)
14
+ method_source (~> 0.9.0)
15
+ rake (10.5.0)
16
+ serialport (1.3.1)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ bundler (~> 2.0)
23
+ pry (~> 0.12.2)
24
+ rake (~> 10.0)
25
+ rbuspirate!
26
+
27
+ BUNDLED WITH
28
+ 2.1.4
@@ -0,0 +1,43 @@
1
+ # Rbuspirate
2
+
3
+ Better ruby driver for buspirate
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'rbuspirate'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rbuspirate
20
+
21
+ ## Usage
22
+ See examples/ dir
23
+
24
+ ## Status
25
+
26
+ I2C: Full support
27
+ UART: Basic support (only bridge mode, no custom speed)
28
+ 1WIRE: Full support
29
+ Windows not supported, contributions are welcomed
30
+
31
+ ## Development
32
+
33
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
34
+
35
+ ## Contributing
36
+
37
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sh7d/rbuspirate.
38
+
39
+ ## Todo
40
+ * Documentation
41
+ * Full uart support
42
+ * SPI
43
+ * Other protocols
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'rbuspirate'
5
+ require 'optparse'
6
+ require 'pry'
7
+
8
+ le_options = {}
9
+
10
+ optparse = OptParse.new do |opts|
11
+ opts.on(
12
+ '-d device', '--device device', String, 'Path to buspirate device'
13
+ ) do |device|
14
+ dev_stat = File.stat(device).rdev rescue nil
15
+ raise 'Connect buspirate first' unless dev_stat
16
+ raise 'Device argument must be device' if dev_stat.zero?
17
+
18
+ le_options[:device] = device
19
+ end
20
+ end
21
+ optparse.parse!
22
+ le_options.freeze
23
+ if le_options[:device]
24
+ bp = SerialPort.new(le_options[:device], 115_200, 8, 1, SerialPort::NONE)
25
+ rs = Rbuspirate::Client.new(bp)
26
+
27
+ binding.pry
28
+ else
29
+ puts optparse.to_s
30
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,37 @@
1
+ require 'rbuspirate'
2
+
3
+ bp = Rbuspirate::Client.new('/dev/buspirate')
4
+ bp.enter_i2c
5
+ # valid settings are :'5khz', :'50khz', :'100khz', :'400khz'
6
+ bp.interface.speed = :'400khz'
7
+ # default vaules are false
8
+ bp.interface.configure_peripherals(
9
+ power: true, pullup: true, aux: false, cs: false
10
+ )
11
+ # you can see definet peripherals config via accesors
12
+ puts "Power #{bp.interface.power ? 'enabled' : 'disabled'}"
13
+ puts "Pull-up resitors #{bp.interface.pullup ? 'enabled' : 'disabled'}"
14
+ # Frist argument is command
15
+ # second expected data to read
16
+ # succes_timeout specifies timeout to read data from device
17
+ # allow_zerobyte: allows one single byte instead of expected data to read
18
+ data = bp.interface.write_then_read(0xA1.chr, 4, succes_timeout: 5, allow_zerobyte: false)
19
+ puts "First 4 bytes are #{data.unpack('H*').join}"
20
+
21
+ # You can also acces raw mode
22
+ # Block is optional
23
+ bp.interface.send_start
24
+ ack_array = bp.interface.bulk_write("\xA0\x00\x00\xDE\xAD".b, ack_timeout: 1, &method(:puts))
25
+ bp.interface.send_stop
26
+ puts ack_array
27
+
28
+ # And read
29
+ bp.interface.send_start
30
+ bp.interface.bulk_write("\xA0\x00\x00".b)
31
+ bp.interface.send_stop
32
+ bp.interface.send_start
33
+ bp.interface.bulk_write("\xA1".b)
34
+ # default vaules are true for acks, and 1 for readbyte_timeout
35
+ data = bp.interface.read(4, auto_ack: true, auto_nack: true, readbyte_timeout: 1)
36
+ bp.interface.send_stop
37
+ puts "First 4 bytes are: #{data.unpack('H*').join}"
@@ -0,0 +1,29 @@
1
+ require 'rbuspirate'
2
+
3
+ bp = Rbuspirate::Client.new('/dev/buspirate')
4
+ bp.enter_uart
5
+ # set speed
6
+ bp.interface.speed = 115_200
7
+ # parity_data possible vaules are: :n8, :e8, :o8, :n9
8
+ bp.interface.config_uart(
9
+ pin_out_33: true, stop_bits: 1, parity_data: :n8, rx_idle: true
10
+ )
11
+ # you can see defined settings via accesors
12
+ puts "Pin out voltage #{bp.interface.pin_out_33 ? '3.3V' : '5V'}"
13
+ # Enable power
14
+ bp.interface.configure_peripherals(
15
+ power: false, pullup: false, aux: false, cs: false
16
+ )
17
+ # you can call to configure_peripherals like configure_peripherals(power: true)
18
+ # rest of arguments will be in default state (false)
19
+ # you can also see peripherals config state via accesors
20
+ puts "Power #{bp.interface.power ? 'enabled' : 'disabled'}"
21
+ # Bridge mode
22
+ bp.interface.enter_bridge
23
+
24
+ # raw port is exposed via port accesor
25
+ port = bp.interface.port
26
+
27
+ while (line = port.readline)
28
+ puts line
29
+ end
@@ -0,0 +1,103 @@
1
+ require 'expect'
2
+ require 'serialport'
3
+
4
+ require 'rbuspirate/commands'
5
+ require 'rbuspirate/responses'
6
+ require 'rbuspirate/timeouts'
7
+ require 'rbuspirate/interfaces/abstract'
8
+ require 'rbuspirate/interfaces/i2c'
9
+ require 'rbuspirate/interfaces/uart'
10
+ require 'rbuspirate/interfaces/1wire'
11
+
12
+ module Rbuspirate
13
+ class Client
14
+ attr_reader :mode, :interface, :needs_reset
15
+
16
+ def initialize(dvc, sync: true)
17
+ raise ArgumentError, 'Shitty arg' unless [SerialPort, String].include?(dvc.class)
18
+
19
+ if dvc.instance_of?(String)
20
+ raise 'Connect buspirate first' unless File.exist?(dvc)
21
+ raise 'Device argument must be device' if File.stat(dvc).rdev.zero?
22
+
23
+ dvc = SerialPort.new(dvc, 115_200, 8, 1, SerialPort::NONE)
24
+ dvc.flow_control = SerialPort::NONE
25
+ end
26
+ @le_port = dvc
27
+ @le_port.sync = true if sync
28
+ @needs_reset = false
29
+ reset_binary_mode
30
+ end
31
+
32
+ def reset_binary_mode
33
+ raise 'Device needs reset to change mode' if @needs_reset
34
+
35
+ 20.times do
36
+ @le_port.putc(Commands::RESET_BITBANG)
37
+ resp = @le_port.expect(
38
+ Responses::BITBANG_MODE, Timeouts::BINARY_RESET
39
+ )
40
+
41
+ if resp
42
+ @interface = nil
43
+ @mode = :bitbang
44
+ return true
45
+ end
46
+ end
47
+
48
+ raise 'Enter to bitbang failied'
49
+ end
50
+
51
+ def enter_i2c
52
+ raise 'Device needs reset to change mode' if @needs_reset
53
+
54
+ switch_mode(
55
+ :i2c, Commands::I2C::ENTER,
56
+ Timeouts::I2C::ENTER, Responses::I2C::ENTER,
57
+ Interfaces::I2C
58
+ )
59
+ end
60
+
61
+ def enter_uart
62
+ raise 'Device needs reset to change mode' if @needs_reset
63
+
64
+ switch_mode(
65
+ :uart, Commands::UART::ENTER,
66
+ Timeouts::UART::ENTER, Responses::UART::ENTER,
67
+ Interfaces::UART
68
+ )
69
+ end
70
+
71
+ def enter_1wire
72
+ raise 'Device needs reset to change mode' if @needs_reset
73
+
74
+ switch_mode(
75
+ :'1wire', Commands::LE1WIRE::ENTER,
76
+ Timeouts::LE1WIRE::ENTER, Responses::LE1WIRE::ENTER,
77
+ Interfaces::LE1WIRE
78
+ )
79
+ end
80
+
81
+ private
82
+
83
+ def switch_mode(
84
+ name_symbol, switch_command,
85
+ wait_timeout, enter_response,
86
+ interface_class
87
+ )
88
+ raise 'Device needs reset to change mode' if @needs_reset
89
+
90
+ @le_port.write(switch_command.chr)
91
+ resp = @le_port.expect(
92
+ enter_response, wait_timeout
93
+ )
94
+ if resp
95
+ @mode = name_symbol
96
+ @interface = interface_class.new(@le_port, self)
97
+ return true
98
+ end
99
+
100
+ raise "Switch to #{name_symbol.to_s.upcase} failied"
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,82 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Rbuspirate
5
+ module Commands
6
+ RESET_BITBANG = 0b00000000
7
+ CONF_PER = 0b01000000
8
+
9
+ module Config
10
+ module Peripherals
11
+ POWER = 0b00001000
12
+ PULLUP = 0b00000100
13
+ AUX = 0b00000010
14
+ CS = 0b00000001
15
+ end
16
+ end
17
+
18
+ module LE1WIRE
19
+ ENTER = 0b00000100
20
+ RESET = 0b00000010
21
+
22
+ module IO
23
+ READ = 0b00000100
24
+ WRITE = 0b00010000
25
+ end
26
+ end
27
+
28
+ module I2C
29
+ ENTER = 0b00000010
30
+ PREPARE_WRITE = 0b00010000
31
+ READBYTE = 0b00000100
32
+ WRITE_THEN_READ = 0x8
33
+
34
+ module Config
35
+ module Speed
36
+ S5KHZ = 0b01100000
37
+ S50KHZ = 0b01100001
38
+ S100KHZ = 0b01100010
39
+ S400KHZ = 0b01100011
40
+ end
41
+ end
42
+
43
+ module Flow
44
+ START = 0b00000010
45
+ STOP = 0b00000011
46
+ ACK = 0b00000110
47
+ NACK = 0b00000111
48
+ end
49
+ end
50
+
51
+ module UART
52
+ ENTER = 0b00000011
53
+ START_BRIDGE = 0b00001111
54
+
55
+ module Config
56
+ CONF_UART = 0b10000000
57
+
58
+ module Speed
59
+ S300 = 0b01100000
60
+ S1200 = 0b01100001
61
+ S2400 = 0b01100010
62
+ S4800 = 0b01100011
63
+ S9600 = 0b01100100
64
+ S19200 = 0b01100101
65
+ S31250 = 0b01100110
66
+ S38400 = 0b01100111
67
+ S57600 = 0b01101000
68
+ S115200 = 0b01101010
69
+ end
70
+
71
+ module UartConf
72
+ PIN_OUT_33 = 0b00010000
73
+ DAT_PARITY_8E = 0b00000100
74
+ DAT_PARITY_80 = 0b00001000
75
+ DAT_PARITY_9N = 0b00001100
76
+ STOP_BIT_2 = 0b00000010
77
+ DISABLE_RX_IDLE = 0b00000001
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,16 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Rbuspirate
5
+ module Helpers
6
+ private
7
+
8
+ def simplex_command(command, tout, ex_message)
9
+ @le_port.write(command.chr)
10
+ resp = @le_port.expect(Responses::SUCCESS, tout)
11
+ return true if resp
12
+
13
+ raise ex_message
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,50 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Rbuspirate
5
+ module Interfaces
6
+ class LE1WIRE < Abstract
7
+ def initialize(serial, bup)
8
+ raise 'Bus pirate must be in 1wire mode' unless bup.mode == :'1wire'
9
+ @le_port = serial
10
+ end
11
+
12
+ def reset
13
+ simplex_command(
14
+ Commands::LE1WIRE::RESET,
15
+ Timeouts::LE1WIRE::RESET,
16
+ 'Unable to reset external device (comm timeout/no device)'
17
+ )
18
+ end
19
+
20
+ def write(data, write_slice_timeout: Timeouts::LE1WIRE::WRITE)
21
+ !(data.is_a?(String) && !data.empty?) &&
22
+ raise(ArgumentError, 'data must be non empty String instance')
23
+
24
+ data = StringIO.new(data)
25
+ while (slice = data.read(16))
26
+ command = Commands::LE1WIRE::IO::WRITE | slice.bytesize - 1
27
+ simplex_command(
28
+ command, write_slice_timeout, 'Prepare slice write timeout'
29
+ )
30
+ @le_port.write(slice)
31
+ res = @le_port.expect(Responses::SUCCESS, write_slice_timeout)
32
+ raise 'Write timeout' unless res
33
+ end
34
+ true
35
+ end
36
+
37
+ def read(bytes = 1, readbyte_timeout: Timeouts::LE1WIRE::READ)
38
+ result = ''.dup.b
39
+ bytes.times do
40
+ @le_port.write(Commands::LE1WIRE::IO::READ.chr)
41
+ Timeout.timeout(readbyte_timeout) do
42
+ result << @le_port.read(1)
43
+ end
44
+ end
45
+
46
+ result
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,40 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Rbuspirate
5
+ module Interfaces
6
+ class Abstract
7
+ def configure_peripherals(
8
+ power: false, pullup: false, aux: false, cs: false
9
+ )
10
+ [power, pullup, aux, cs].map(&:class).each do |cls|
11
+ raise ArgumentError, 'All args must be true or false' unless [FalseClass, TrueClass].include?(cls)
12
+ end
13
+
14
+ bit_config = Commands::CONF_PER
15
+ bit_config |= Commands::Config::Peripherals::POWER if power
16
+ bit_config |= Commands::Config::Peripherals::PULLUP if pullup
17
+ bit_config |= Commands::Config::Peripherals::AUX if aux
18
+ bit_config |= Commands::Config::Peripherals::CS if cs
19
+
20
+ simplex_command(
21
+ bit_config,
22
+ Timeouts::SUCCESS,
23
+ 'Unable to confgure peripherals'
24
+ )
25
+ @power, @pullup, @aux, @cs = power, pullup, aux, cs
26
+ end
27
+
28
+ protected
29
+
30
+ def simplex_command(command, tout, ex_message)
31
+ command = command.chr if command.instance_of?(Integer)
32
+ @le_port.write(command.chr)
33
+ resp = @le_port.expect(Responses::SUCCESS, tout)
34
+ return true if resp
35
+
36
+ raise ex_message
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,153 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ require 'timeout'
5
+
6
+ module Rbuspirate
7
+ module Interfaces
8
+ class I2C < Abstract
9
+ attr_reader :speed, :power, :pullup, :aux, :cs
10
+
11
+ def initialize(serial, bup)
12
+ raise 'Bus pirate must be in i2c mode' unless bup.mode == :i2c
13
+
14
+ @le_port = serial
15
+ set_speed(:'400khz')
16
+ end
17
+
18
+ def speed=(le_speed)
19
+ set_speed(le_speed)
20
+ end
21
+
22
+ def send_start
23
+ simplex_command(
24
+ Commands::I2C::Flow::START,
25
+ Timeouts::I2C::STARTSTOP,
26
+ 'Unable to sent start bit'
27
+ )
28
+ end
29
+
30
+ def send_stop
31
+ simplex_command(
32
+ Commands::I2C::Flow::STOP,
33
+ Timeouts::I2C::STARTSTOP,
34
+ 'Unable to sent stop bit'
35
+ )
36
+ end
37
+
38
+ def send_ack
39
+ simplex_command(
40
+ Commands::I2C::Flow::ACK,
41
+ Timeouts::I2C::ACKNACK,
42
+ 'Unable to sent ack'
43
+ )
44
+ end
45
+
46
+ def send_nack
47
+ simplex_command(
48
+ Commands::I2C::Flow::NACK,
49
+ Timeouts::I2C::ACKNACK,
50
+ 'Unable to sent nack'
51
+ )
52
+ end
53
+
54
+ def read(bytes = 1, auto_ack: true, auto_nack: true, readbyte_timeout: Timeouts::I2C::READ)
55
+ result = ''.dup.b
56
+ bytes.times do |t|
57
+ @le_port.write(Commands::I2C::READBYTE.chr)
58
+ Timeout.timeout(readbyte_timeout) do
59
+ result << @le_port.read(1)
60
+ end
61
+ send_ack if auto_ack && t + 1 != bytes
62
+ send_nack if auto_nack && t + 1 == bytes
63
+ end
64
+ result
65
+ end
66
+
67
+ def bulk_write(data, ack_timeout: Timeouts::I2C::SLAVE_ACKNACK)
68
+ raise ArgumentError, 'data must be String instance' unless data.instance_of?(String)
69
+
70
+ if !data.instance_of?(String) || data.instance_of?(String) && data.empty?
71
+ raise ArgumentError, 'Bad data argument'
72
+ end
73
+ raise ArgumentError, 'Data is too long' if data.bytesize > 16
74
+
75
+ bit_bulk_write = Commands::I2C::PREPARE_WRITE | data.bytesize - 1
76
+ simplex_command(
77
+ bit_bulk_write.chr,
78
+ Timeouts::I2C::PREPARE_WRITE,
79
+ 'Unable to prepare write mode'
80
+ )
81
+ ack_array = []
82
+ data.each_byte do |data_byte|
83
+ @le_port.write(data_byte.chr)
84
+ Timeout.timeout(ack_timeout) do
85
+ ack_array << case @le_port.read(1).ord
86
+ when 0
87
+ :ack
88
+ when 1
89
+ :nack
90
+ else
91
+ raise 'Unknown bytewrite response'
92
+ end
93
+ yield(ack_array.last) if block_given?
94
+ end
95
+ end
96
+ ack_array.freeze
97
+ end
98
+
99
+ def write_then_read(
100
+ data, expected_bytes = 0,
101
+ succes_timeout: Timeouts::I2C::WRITE_THEN_READ_S,
102
+ allow_zerobyte: false
103
+ )
104
+ raise ArgumentError, 'Bad data type' unless data.instance_of?(String)
105
+ raise ArgumentError, 'Data is too long' if data.bytesize > 4096
106
+ raise ArgumentError, 'Bad expected_bytes type' unless expected_bytes.instance_of?(Integer)
107
+ raise ArgumentError, 'Bad expected_bytes value' if expected_bytes.negative? || expected_bytes > 4096
108
+
109
+ binary_command = Commands::I2C::WRITE_THEN_READ.chr +
110
+ [data.bytesize, expected_bytes].pack('S>S>') +
111
+ data
112
+ @le_port.write(binary_command)
113
+ result = nil
114
+ # So fucking ugly
115
+ begin
116
+ Timeout.timeout(succes_timeout) do
117
+ result = @le_port.read(1)
118
+ end
119
+ rescue Timeout::Error
120
+ return false
121
+ end
122
+ return false if allow_zerobyte && result.ord.zero?
123
+ raise 'Write failed' if result.ord.zero?
124
+ if expected_bytes != 0
125
+ Timeout.timeout(Timeouts::I2C::WRITE_THEN_READ_D) do
126
+ result = @le_port.read(expected_bytes)
127
+ end
128
+ result
129
+ else
130
+ true
131
+ end
132
+ end
133
+ private
134
+ def set_speed(le_speed)
135
+ bit_speed = case le_speed.to_sym
136
+ when :'5khz'
137
+ Commands::I2C::Config::Speed::S5KHZ
138
+ when :'50khz'
139
+ Commands::I2C::Config::Speed::S50KHZ
140
+ when :'100khz'
141
+ Commands::I2C::Config::Speed::S100KHZ
142
+ when :'400khz'
143
+ Commands::I2C::Config::Speed::S400KHZ
144
+ else
145
+ raise ArgumentError, 'Bad speed argument'
146
+ end
147
+
148
+ simplex_command(bit_speed, Timeouts::SUCCESS, 'Unable to set speed')
149
+ @speed = le_speed
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,110 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ require 'timeout'
5
+
6
+ module Rbuspirate
7
+ module Interfaces
8
+ class UART < Abstract
9
+ attr_reader :bridge, :speed, :power, :pullup, :aux, :cs,
10
+ :pin_out_33, :parity_data, :stop_bits, :rx_idle,
11
+ :port
12
+
13
+ def initialize(serial, bup)
14
+ raise 'Bus pirate must be in uart mode' unless bup.mode == :uart
15
+
16
+ @bridge = false
17
+ @bup = bup
18
+ @le_port = serial
19
+ end
20
+
21
+ def configure_peripherals(...)
22
+ raise 'Device needs reset in order to reconfigure it' if @bridge
23
+
24
+ super
25
+ end
26
+
27
+ def speed=(le_speed)
28
+ raise 'Device needs reset in order to reconfigure it' if @bridge
29
+
30
+ bit_speed = case le_speed
31
+ when 300
32
+ Commands::UART::Config::Speed::S300
33
+ when 1200
34
+ Commands::UART::Config::Speed::S1200
35
+ when 2400
36
+ Commands::UART::Config::Speed::S2400
37
+ when 4800
38
+ Commands::UART::Config::Speed::S4800
39
+ when 9600
40
+ Commands::UART::Config::Speed::S9600
41
+ when 19_200
42
+ Commands::UART::Config::Speed::S19200
43
+ when 31_250
44
+ Commands::UART::Config::Speed::S31250
45
+ when 38_400
46
+ Commands::UART::Config::Speed::S38400
47
+ when 57_600
48
+ Commands::UART::Config::Speed::S57600
49
+ when 115_200
50
+ Commands::UART::Config::Speed::S115200
51
+ else
52
+ raise ArgumentError, 'Unsupported speed'
53
+ end
54
+
55
+ simplex_command(bit_speed, Timeouts::SUCCESS, 'Unable to set speed')
56
+ @speed = bit_speed
57
+ end
58
+
59
+ def config_uart(
60
+ pin_out_33: false, parity_data: :n8, stop_bits: 1, rx_idle: true
61
+ )
62
+ raise 'Device needs reset in order to reconfigure it' if @bridge
63
+
64
+ raise ArgumentError, 'Pin out should be false or true' unless [true, false].include?(pin_out_33)
65
+ raise ArgumentError, 'Unknown praity and databits mode' unless [:n8, :e8, :o8, :n9].include?(parity_data)
66
+ raise ArgumentError, 'Unknown stop bits mode' unless [1, 2].include?(stop_bits)
67
+ raise ArgumentError, 'Rx idle should be false or true' unless [true, false].include?(rx_idle)
68
+
69
+ bit_conf_uart = Commands::UART::Config::CONF_UART
70
+
71
+ bit_conf_uart |= Commands::UART::Config::UartConf::PIN_OUT_33 if pin_out_33
72
+ bit_conf_uart |= case parity_data
73
+ when :e8
74
+ Commands::UART::Config::UartConf::DAT_PARITY_8E
75
+ when :o8
76
+ Commands::UART::Config::UartConf::DAT_PARITY_8O
77
+ when :n9
78
+ Commands::UART::Config::UartConf::DAT_PARITY_9N
79
+ else
80
+ 0
81
+ end
82
+ bit_conf_uart |= Commands::UART::Config::UartConf::STOP_BIT_2 if stop_bits == 2
83
+ bit_conf_uart |= Commands::UART::Config::UartConf::DISABLE_RX_IDLE unless rx_idle
84
+
85
+ simplex_command(bit_conf_uart, Timeouts::SUCCESS, 'Unable to config uart')
86
+
87
+ @pin_out_33, @parity_data, @stop_bits, @rx_idle = pin_out_33, parity_data, stop_bits, rx_idle
88
+ end
89
+
90
+ def enter_bridge
91
+ return @bridge if @bridge
92
+
93
+ @le_port.write(Commands::UART::START_BRIDGE.chr)
94
+ @bridge = true
95
+ @bup.instance_variable_set(:@needs_reset, true)
96
+ @port = @le_port
97
+ end
98
+
99
+ def read(bytes = 0)
100
+ raise 'Enter to bridge mode first' unless @bridge
101
+ bytes.positive? ? @le_port.read(bytes) : @le_port.read
102
+ end
103
+
104
+ def write(data)
105
+ raise 'Enter to bridge mode first' unless @bridge
106
+ @le_port.write(data.to_s.b)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,21 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Rbuspirate
5
+ module Responses
6
+ BITBANG_MODE = 'BBIO1'
7
+ SUCCESS = 0x01.chr
8
+
9
+ module LE1WIRE
10
+ ENTER = '1W01'
11
+ end
12
+
13
+ module I2C
14
+ ENTER = 'I2C1'
15
+ end
16
+
17
+ module UART
18
+ ENTER = 'ART1'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ # Encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Rbuspirate
5
+ module Timeouts
6
+ BINARY_RESET = 0.05
7
+ SUCCESS = 0.1
8
+
9
+ module LE1WIRE
10
+ ENTER = 0.2
11
+ RESET = 0.5
12
+ WRITE = 1
13
+ READ = 1
14
+ end
15
+
16
+ module I2C
17
+ ENTER = 0.2
18
+ STARTSTOP = 0.5
19
+ PREPARE_WRITE = 0.1
20
+ ACKNACK = 0.3
21
+ READ = 1
22
+ SLAVE_ACKNACK = 0.5
23
+ WRITE_THEN_READ_S = 5
24
+ WRITE_THEN_READ_D = 5
25
+ end
26
+
27
+ module UART
28
+ ENTER = 0.2
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Rbuspirate
2
+ VERSION = '0.2.2'
3
+ end
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "rbuspirate/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rbuspirate"
7
+ spec.version = Rbuspirate::VERSION
8
+ spec.authors = ["sh7d"]
9
+ spec.email = ["sh7d@sh7d"]
10
+
11
+ spec.summary = %q{Ruby better buspirate interface}
12
+ spec.description = %q{Simple buspirate ruby interface}
13
+ spec.homepage = "https://github.com/sh7d/rbuspirate"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib'] + Dir.glob('lib/**').select(&File.method(:directory?))
25
+
26
+ spec.add_development_dependency "bundler", "~> 2.0"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "pry", "~> 0.12"
29
+ spec.add_dependency "serialport", "~> 1.3"
30
+ end
31
+
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbuspirate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - sh7d
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-02-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: serialport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ description: Simple buspirate ruby interface
70
+ email:
71
+ - sh7d@sh7d
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - Gemfile.lock
79
+ - README.md
80
+ - Rakefile
81
+ - bin/console
82
+ - bin/setup
83
+ - examples/i2c.rb
84
+ - examples/uart.rb
85
+ - lib/rbuspirate.rb
86
+ - lib/rbuspirate/commands.rb
87
+ - lib/rbuspirate/helpers.rb
88
+ - lib/rbuspirate/interfaces/1wire.rb
89
+ - lib/rbuspirate/interfaces/abstract.rb
90
+ - lib/rbuspirate/interfaces/i2c.rb
91
+ - lib/rbuspirate/interfaces/uart.rb
92
+ - lib/rbuspirate/responses.rb
93
+ - lib/rbuspirate/timeouts.rb
94
+ - lib/rbuspirate/version.rb
95
+ - rbuspirate.gemspec
96
+ homepage: https://github.com/sh7d/rbuspirate
97
+ licenses: []
98
+ metadata:
99
+ homepage_uri: https://github.com/sh7d/rbuspirate
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ - lib/rbuspirate
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.1.2
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Ruby better buspirate interface
120
+ test_files: []