rbuspirate 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ea1e9f18b739184a2722b3dd7d8cc4c8d64830291fe9caa93099360ade5ab41e
4
+ data.tar.gz: e7ad361bd69818d82d73b1fb0942c184808428d835b66c894b70f1843fee4fa3
5
+ SHA512:
6
+ metadata.gz: 67bb082b478a92a839d8d8f5c8d0806ada5944d82cb8edf7de25626890519b6ed3afeae18fb0280c40ba4b503ef1f615a40307d1fad888d58294587160079fc7
7
+ data.tar.gz: 8f066117c4100121d93ac477d1eea45f815a8e016651ad246e11e5fd81044553de5ada39080aa363323d399249b01d1caaaaaf39006b715bfa051826ff23a3ad
@@ -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.3)
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,107 @@
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
+ def self.register_mode(
15
+ name_symbol, switch_command,
16
+ wait_timeout, enter_response,
17
+ interface_class
18
+ )
19
+ define_method("enter_#{name_symbol}".to_sym) do
20
+ switch_mode(
21
+ name_symbol, switch_command,
22
+ wait_timeout, enter_response,
23
+ interface_class
24
+ )
25
+ end
26
+ end
27
+
28
+ attr_reader :mode, :interface, :needs_reset
29
+ alias iface interface
30
+
31
+ def initialize(dvc, sync: true)
32
+ raise ArgumentError, 'Shitty arg' unless [SerialPort, String].include?(dvc.class)
33
+
34
+ if dvc.instance_of?(String)
35
+ raise 'Connect buspirate first' unless File.exist?(dvc)
36
+ raise 'Device argument must be device' if File.stat(dvc).rdev.zero?
37
+
38
+ dvc = SerialPort.new(dvc, 115_200, 8, 1, SerialPort::NONE)
39
+ dvc.flow_control = SerialPort::NONE
40
+ end
41
+ @le_port = dvc
42
+ @le_port.sync = true if sync
43
+ @needs_reset = false
44
+ reset_binary_mode
45
+ end
46
+
47
+ def reset_binary_mode
48
+ raise 'Device needs reset to change mode' if @needs_reset
49
+
50
+ 20.times do
51
+ @le_port.putc(Commands::RESET_BITBANG)
52
+ resp = @le_port.expect(
53
+ Responses::BITBANG_MODE, Timeouts::BINARY_RESET
54
+ )
55
+
56
+ if resp
57
+ @interface = nil
58
+ @mode = :bitbang
59
+ return true
60
+ end
61
+ end
62
+
63
+ raise 'Enter to bitbang failied'
64
+ end
65
+ [
66
+ [
67
+ :i2c, Commands::I2C::ENTER,
68
+ Timeouts::I2C::ENTER, Responses::I2C::ENTER,
69
+ Interfaces::I2C
70
+ ],
71
+ [
72
+ :uart, Commands::UART::ENTER,
73
+ Timeouts::UART::ENTER, Responses::UART::ENTER,
74
+ Interfaces::UART
75
+ ],
76
+ [
77
+ :'1wire', Commands::LE1WIRE::ENTER,
78
+ Timeouts::LE1WIRE::ENTER, Responses::LE1WIRE::ENTER,
79
+ Interfaces::LE1WIRE
80
+ ]
81
+ ].each do |mode|
82
+ register_mode(*mode)
83
+ end
84
+
85
+ private
86
+
87
+ def switch_mode(
88
+ name_symbol, switch_command,
89
+ wait_timeout, enter_response,
90
+ interface_class
91
+ )
92
+ raise 'Device needs reset to change mode' if @needs_reset
93
+ reset_binary_mode
94
+ @le_port.write(switch_command.chr)
95
+ resp = @le_port.expect(
96
+ enter_response, wait_timeout
97
+ )
98
+ if resp
99
+ @mode = name_symbol
100
+ @interface = interface_class.new(@le_port, self)
101
+ return true
102
+ end
103
+
104
+ raise "Switch to #{name_symbol.to_s.upcase} failied"
105
+ end
106
+ end
107
+ 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.3'
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.3
5
+ platform: ruby
6
+ authors:
7
+ - sh7d
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-02-14 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: []