i2c-devices 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ #!rspec
2
+
3
+
4
+ $LOAD_PATH.unshift "lib"
5
+
6
+ require "tempfile"
7
+
8
+ require "i2c/device/adt7410"
9
+ require "i2c/driver/i2c-dev"
10
+ require "i2c/mocki2cdevice"
11
+
12
+ describe ADT7410 do
13
+ before do
14
+ @mock = MockI2CDevice.new
15
+ File.stub(:open) do
16
+ @mock.open
17
+ end
18
+ @driver = I2CDevice::Driver::I2CDev.new(@mock.path)
19
+ end
20
+
21
+ describe "#calculate_temperature" do
22
+ context "16bit" do
23
+ it "should treat positive fractial value" do
24
+ # status
25
+ @mock.memory[0x02] = 0b00000000
26
+ # temp
27
+ @mock.memory[0x00] = 0b00000000
28
+ @mock.memory[0x01] = 0b00000001
29
+
30
+ device = ADT7410.new(address: 0x50, driver: @driver)
31
+ expect(device.read_configuration).to eq({
32
+ :fault_queue => 1,
33
+ :ct_pin_polarity => false,
34
+ :int_pin_polarity => false,
35
+ :int_ct_mode => :interrupt_mode,
36
+ :operation_mode => :continuous_conversion,
37
+ :resolution => 16
38
+ })
39
+ expect(device.calculate_temperature).to eq(0.0078125)
40
+ end
41
+
42
+ it "should treat negative value" do
43
+ # status
44
+ @mock.memory[0x02] = 0b00000000
45
+ # temp
46
+ @mock.memory[0x00] = 0b10000000
47
+ @mock.memory[0x01] = 0b00000000
48
+
49
+ device = ADT7410.new(address: 0x50, driver: @driver)
50
+ expect(device.calculate_temperature).to eq(-256)
51
+ end
52
+ end
53
+
54
+ context "13bit" do
55
+ it "should treat positive fractial value" do
56
+ # status
57
+ @mock.memory[0x02] = 0b00000000
58
+ # temp
59
+ @mock.memory[0x00] = 0b00000000
60
+ @mock.memory[0x01] = 0b00001000
61
+
62
+ device = ADT7410.new(address: 0x50, driver: @driver)
63
+ device.configuration({
64
+ resolution: 13,
65
+ })
66
+
67
+ expect(device.calculate_temperature).to eq(0.0625)
68
+ end
69
+
70
+ it "should treat negative value" do
71
+ # status
72
+ @mock.memory[0x02] = 0b00000000
73
+ # temp
74
+ @mock.memory[0x00] = 0b11100100
75
+ @mock.memory[0x01] = 0b10000000
76
+
77
+ device = ADT7410.new(address: 0x50, driver: @driver)
78
+ device.configuration({
79
+ resolution: 13,
80
+ })
81
+
82
+ expect(device.calculate_temperature).to eq(-55)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
@@ -0,0 +1,155 @@
1
+ #!rspec
2
+
3
+
4
+ $LOAD_PATH.unshift "lib"
5
+
6
+ require "tempfile"
7
+
8
+ require "i2c/device/hd44780"
9
+ require "i2c/driver/i2c-dev"
10
+
11
+ describe HD44780 do
12
+ before do
13
+ @i2cout = ""
14
+ @i2cin = ""
15
+ @ioctl = nil
16
+
17
+ ioctl = proc do |cmd, arg|
18
+ @ioctl = [ cmd, arg ]
19
+ end
20
+
21
+ syswrite = proc do |str|
22
+ @i2cout << str
23
+ end
24
+
25
+ sysread = proc do |n|
26
+ @i2cin
27
+ end
28
+
29
+ @temp = Tempfile.new("i2c")
30
+ file = nil
31
+ open = File.method(:open)
32
+ File.stub(:open) do
33
+ file = open.call(@temp.path, "r+")
34
+ file.define_singleton_method(:ioctl) {|cmd,arg| ioctl.call(ioctl) }
35
+ file.define_singleton_method(:syswrite) {|str| syswrite.call(str) }
36
+ file.define_singleton_method(:sysread) {|n| sysread.call(n) }
37
+ file
38
+ end
39
+ @driver = I2CDevice::Driver::I2CDev.new(@temp.path)
40
+ end
41
+
42
+ describe "#initialize_lcd" do
43
+ it "should initialize lcd" do
44
+ lcd = HD44780.new(address: 0x10, driver: @driver)
45
+
46
+ expect(@i2cout.unpack("C*")).to eq([
47
+ 0b00000000,
48
+ 0b00111000,
49
+ 0b00000000,
50
+ 0b00111000,
51
+ 0b00000000,
52
+ 0b00111000,
53
+ 0b00000000,
54
+ 0b00111000,
55
+ 0b00000000,
56
+ 0b00001100,
57
+ 0b00000000,
58
+ 0b00000001,
59
+ ])
60
+ end
61
+ end
62
+
63
+ describe "#put_line" do
64
+ it "should be put_line 1/2" do
65
+ lcd = HD44780.new(address: 0x10, driver: @driver)
66
+
67
+ @i2cout.clear
68
+
69
+ lcd.put_line(0, "0123456789abcdef")
70
+
71
+ expect(@i2cout.unpack("C*")).to eq([
72
+ # set_ddram_address
73
+ 0b00000000, 0b10000000,
74
+
75
+ # write commands
76
+ 0b10000000, "0".ord,
77
+ 0b10000000, "1".ord,
78
+ 0b10000000, "2".ord,
79
+ 0b10000000, "3".ord,
80
+ 0b10000000, "4".ord,
81
+ 0b10000000, "5".ord,
82
+ 0b10000000, "6".ord,
83
+ 0b10000000, "7".ord,
84
+ 0b10000000, "8".ord,
85
+ 0b10000000, "9".ord,
86
+ 0b10000000, "a".ord,
87
+ 0b10000000, "b".ord,
88
+ 0b10000000, "c".ord,
89
+ 0b10000000, "d".ord,
90
+ 0b10000000, "e".ord,
91
+ 0b10000000, "f".ord,
92
+ ])
93
+
94
+ @i2cout.clear
95
+
96
+ lcd.put_line(1, "0123456789abcdef")
97
+
98
+ expect(@i2cout.unpack("C*")).to eq([
99
+ # set_ddram_address
100
+ 0b00000000, 0b11000000,
101
+
102
+ # write commands
103
+ 0b10000000, "0".ord,
104
+ 0b10000000, "1".ord,
105
+ 0b10000000, "2".ord,
106
+ 0b10000000, "3".ord,
107
+ 0b10000000, "4".ord,
108
+ 0b10000000, "5".ord,
109
+ 0b10000000, "6".ord,
110
+ 0b10000000, "7".ord,
111
+ 0b10000000, "8".ord,
112
+ 0b10000000, "9".ord,
113
+ 0b10000000, "a".ord,
114
+ 0b10000000, "b".ord,
115
+ 0b10000000, "c".ord,
116
+ 0b10000000, "d".ord,
117
+ 0b10000000, "e".ord,
118
+ 0b10000000, "f".ord,
119
+ ])
120
+ end
121
+ end
122
+
123
+ describe "#define_character" do
124
+ it "should define character" do
125
+ lcd = HD44780.new(address: 0x10, driver: @driver)
126
+
127
+ @i2cout.clear
128
+
129
+ lcd.define_character(0, [
130
+ 0,1,1,1,0,
131
+ 1,0,0,0,1,
132
+ 1,1,0,1,1,
133
+ 1,0,1,0,1,
134
+ 1,1,0,1,1,
135
+ 1,0,0,0,1,
136
+ 1,0,0,0,1,
137
+ 0,1,1,1,0,
138
+ ])
139
+
140
+ expect(@i2cout.unpack("C*")).to eq([
141
+ # set_cgram_address
142
+ 0b00000000, 0b01000000,
143
+
144
+ 0b10000000, 0b00001110,
145
+ 0b10000000, 0b00010001,
146
+ 0b10000000, 0b00011011,
147
+ 0b10000000, 0b00010101,
148
+ 0b10000000, 0b00011011,
149
+ 0b10000000, 0b00010001,
150
+ 0b10000000, 0b00010001,
151
+ 0b10000000, 0b00001110,
152
+ ])
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,514 @@
1
+ #!rspec
2
+
3
+ $LOAD_PATH.unshift "lib"
4
+
5
+ require "i2c"
6
+ require "i2c/driver/gpio"
7
+ require "tempfile"
8
+
9
+ class GPIOTimeline
10
+ attr_reader :events
11
+
12
+ def initialize
13
+ @timeline = {}
14
+ @pins = []
15
+ @events = []
16
+ @defaults = {}
17
+ @watchers = {}
18
+ end
19
+
20
+ def define(pin)
21
+ unless @timeline.include?(pin)
22
+ default(pin, 0)
23
+ @timeline[pin] = []
24
+ @watchers[pin] = []
25
+ @pins << pin
26
+ end
27
+ end
28
+
29
+ def add(pin, state)
30
+ event = {
31
+ time: Time.now,
32
+ state: state,
33
+ pin: pin,
34
+ }
35
+ @events << event
36
+ @timeline[pin] << event
37
+ @watchers[pin].each do |watcher|
38
+ watcher[:count][:total] += 1
39
+ watcher[:count][state.zero?? :low : :high] += 1
40
+ watcher[:block].call(state, watcher[:count])
41
+ end
42
+ end
43
+
44
+ def mark(label, position=:top)
45
+ event = {
46
+ time: Time.now,
47
+ label: label,
48
+ position: position,
49
+ }
50
+ @events << event
51
+ end
52
+
53
+ def default(pin, state=nil)
54
+ unless state.nil?
55
+ @defaults[pin] = state
56
+ end
57
+ @defaults[pin]
58
+ end
59
+
60
+ def state(pin)
61
+ @timeline[pin].last[:state]
62
+ end
63
+
64
+ def watch(pin, &block)
65
+ watcher= {
66
+ pin: pin,
67
+ block: block,
68
+ count: {
69
+ total: 0,
70
+ low: 0,
71
+ high: 0,
72
+ }
73
+ }
74
+ @watchers[pin] << watcher
75
+ unwatch = lambda {
76
+ @watchers[pin].delete(watcher)
77
+ }
78
+ end
79
+
80
+ def dump
81
+ require "cairo"
82
+
83
+ width = 1240
84
+ height = 300
85
+
86
+ surface = Cairo::ImageSurface.new(Cairo::FORMAT_ARGB32, width, height)
87
+ context = Cairo::Context.new(surface)
88
+
89
+ total = @events.last[:time] - @events.first[:time]
90
+ start = @events.first[:time]
91
+ px_per_sec = (width - 20) / total
92
+
93
+ h = 50
94
+
95
+ context.select_font_face("Lucida Console")
96
+ context.line_width = 3
97
+
98
+ @events.select {|i| i[:label] }.each do |event|
99
+ n = event[:time] - start
100
+ label = event[:label]
101
+ context.set_source_rgb(0.7, 0.7, 0.7)
102
+ context.stroke do
103
+ context.move_to(n * px_per_sec, 0)
104
+ context.line_to(n * px_per_sec, height)
105
+ end
106
+ context.set_source_rgb(0.3, 0.3, 0.3)
107
+ context.move_to(n * px_per_sec + 5, event[:position] == :top ? 20 : height - 20)
108
+ context.set_font_size(10)
109
+ context.show_text(label.to_s)
110
+ end
111
+
112
+ context.set_source_rgb(0.3, 0.3, 0.3)
113
+ context.line_width = 2
114
+
115
+ pin_count = 1
116
+ @pins.each do |pin|
117
+ context.save do
118
+ prev = 0
119
+ context.translate(0, 100 * pin_count)
120
+
121
+ context.move_to(0, prev)
122
+ context.line_to(10, prev)
123
+
124
+ context.translate(10, 0)
125
+
126
+ @timeline[pin].each do |event|
127
+ n = event[:time] - start
128
+
129
+ context.line_to(n * px_per_sec, prev * -h)
130
+ context.line_to(n * px_per_sec, event[:state] * -h)
131
+ prev = event[:state]
132
+ end
133
+
134
+ context.line_to(width, prev * -h)
135
+
136
+ context.stroke
137
+ end
138
+ pin_count += 1
139
+ end
140
+
141
+ surface.write_to_png("/tmp/dump.png")
142
+ end
143
+ end
144
+
145
+ describe I2CDevice::Driver::GPIO do
146
+ before do
147
+ @timeline = timeline = GPIOTimeline.new
148
+
149
+ I2CDevice::Driver::GPIO.define_singleton_method(:export) do |pin|
150
+ timeline.define(pin)
151
+ end
152
+
153
+ I2CDevice::Driver::GPIO.define_singleton_method(:unexport) do |pin|
154
+ end
155
+
156
+ I2CDevice::Driver::GPIO.define_singleton_method(:direction) do |pin, direction|
157
+ # p [:direction, pin]
158
+ state = 1
159
+ case direction
160
+ when :in
161
+ state = timeline.default(pin) # pulled-up
162
+ when :out
163
+ state = 0
164
+ when :high
165
+ state = 1
166
+ when :low
167
+ state = 0
168
+ end
169
+ timeline.add(pin, state)
170
+ end
171
+
172
+ I2CDevice::Driver::GPIO.define_singleton_method(:read) do |pin|
173
+ timeline.state(pin)
174
+ end
175
+
176
+ I2CDevice::Driver::GPIO.define_singleton_method(:write) do |pin, val|
177
+ timeline.add(pin, val ? 1 : 0)
178
+ end
179
+
180
+ @driver = I2CDevice::Driver::GPIO.new(
181
+ sda: 23,
182
+ scl: 24,
183
+ speed: 1,
184
+ )
185
+ @timeline.events.clear
186
+ @timeline.default(@driver.scl, 1)
187
+ @timeline.default(@driver.sda, 1)
188
+ end
189
+
190
+ describe "i2c protocol" do
191
+ it "should set start condition correctly" do
192
+ @driver.send(:start_condition)
193
+ expect(@timeline.state(@driver.scl)).to be(1)
194
+ expect(@timeline.state(@driver.sda)).to be(0)
195
+ expect(@timeline.events.map {|i| [i[:pin], i[:state]] }).to eq([[@driver.sda, 1], [@driver.scl, 1], [@driver.scl, 1], [@driver.sda, 0]])
196
+ end
197
+
198
+ it "should throw exception when bus is busy" do
199
+ @timeline.default(@driver.scl, 0)
200
+ expect { @driver.send(:start_condition) }.to raise_error(I2CDevice::I2CBUSBusy)
201
+ end
202
+
203
+ it "should set stop condition correctly" do
204
+ @driver.send(:start_condition)
205
+
206
+ @timeline.events.clear
207
+ @driver.send(:stop_condition)
208
+ expect(@timeline.events.map {|i| [i[:pin], i[:state]] }).to eq([ [@driver.scl, 0], [@driver.sda, 0], [@driver.scl, 1], [@driver.sda, 1] ])
209
+ expect(@timeline.state(@driver.scl)).to be(1)
210
+ expect(@timeline.state(@driver.sda)).to be(1)
211
+ end
212
+
213
+ it "should write 1 byte correctly and receive nack" do
214
+ @timeline.mark(:start)
215
+ @driver.send(:start_condition)
216
+
217
+ @timeline.mark(:write)
218
+ ret = @driver.send(:write, 0b01010011)
219
+ expect(@timeline.events.drop_while {|i| i[:label] != :write }.select {|i| i[:pin] == @driver.scl }.map {|i| i[:state] }).to eq([0, 1] * 9 + [0])
220
+ expect(ret).to be(false)
221
+ expect(@timeline.state(@driver.scl)).to be(0)
222
+
223
+ @timeline.mark(:stop)
224
+ @driver.send(:stop_condition)
225
+ end
226
+
227
+ it "should write 1 byte correctly and receive ack" do
228
+ @timeline.mark(:start)
229
+ @driver.send(:start_condition)
230
+
231
+ unwatch = @timeline.watch(@driver.scl) do |state, count|
232
+ case
233
+ when count[:high] == 8 && state == 0
234
+ # return ack
235
+ @timeline.default(@driver.sda, 0)
236
+ when count[:high] == 9 && state == 1
237
+ @timeline.mark("ack")
238
+ when count[:high] == 9 && state == 0
239
+ @timeline.default(@driver.sda, 1)
240
+ unwatch.call
241
+ end
242
+ end
243
+
244
+ @timeline.mark(:write)
245
+ ret = @driver.send(:write, 0b11111111)
246
+ expect(@timeline.events.drop_while {|i| i[:label] != :write}.select {|i| i[:pin] == @driver.scl }.map {|i| i[:state] }).to eq([0, 1] * 9 + [0])
247
+ expect(ret).to be(true)
248
+ expect(@timeline.state(@driver.scl)).to be(0)
249
+
250
+ @timeline.mark(:stop)
251
+ @driver.send(:stop_condition)
252
+ end
253
+
254
+ it "should read 1 byte correctly and return ack" do
255
+ @timeline.mark(:start)
256
+ @driver.send(:start_condition)
257
+
258
+ send = 0b00000000
259
+ unwatch = @timeline.watch(@driver.scl) do |state, count|
260
+ case
261
+ when count[:high] < 8 && state == 0
262
+ # send bit
263
+ bit = send[ 7 - count[:high] ]
264
+ @timeline.default(@driver.sda, bit)
265
+ @timeline.add(@driver.sda, bit)
266
+ when count[:high] == 9 && state == 1
267
+ # read ack
268
+ @timeline.mark(:ack)
269
+ expect(@timeline.state(@driver.sda)).to be(0)
270
+ unwatch.call
271
+ @timeline.default(@driver.sda, 1)
272
+ end
273
+ end
274
+ @timeline.mark(:read)
275
+ ret = @driver.send(:read, true)
276
+ expect(ret).to be(send)
277
+
278
+ send = 0b01010101
279
+ unwatch = @timeline.watch(@driver.scl) do |state, count|
280
+ case
281
+ when count[:high] < 8 && state == 0
282
+ # send bit
283
+ bit = send[ 7 - count[:high] ]
284
+ @timeline.default(@driver.sda, bit)
285
+ @timeline.add(@driver.sda, bit)
286
+ when count[:high] <= 8 && state == 1
287
+ @timeline.mark("#{8 - count[:high]}", :bottom)
288
+ when count[:high] == 9 && state == 1
289
+ # read ack
290
+ @timeline.mark(:ack)
291
+ expect(@timeline.state(@driver.sda)).to be(0)
292
+ unwatch.call
293
+ @timeline.default(@driver.sda, 1)
294
+ end
295
+ end
296
+ ret = @driver.send(:read, true)
297
+ expect(ret).to be(send)
298
+
299
+ @timeline.mark(:stop)
300
+ @driver.send(:stop_condition)
301
+ end
302
+
303
+ it "should read 1 byte correctly and return nack" do
304
+ @timeline.mark(:start)
305
+ @driver.send(:start_condition)
306
+
307
+ send = 0b01010101
308
+ unwatch = @timeline.watch(@driver.scl) do |state, count|
309
+ case
310
+ when count[:high] < 8 && state == 0
311
+ # send bit
312
+ bit = send[ 7 - count[:high] ]
313
+ @timeline.default(@driver.sda, bit)
314
+ @timeline.add(@driver.sda, bit)
315
+ when count[:high] == 9 && state == 1
316
+ # read ack
317
+ @timeline.mark(:nack)
318
+ expect(@timeline.state(@driver.sda)).to be(1)
319
+ unwatch.call
320
+ @timeline.default(@driver.sda, 1)
321
+ end
322
+ end
323
+ ret = @driver.send(:read, false)
324
+ expect(ret).to be(send)
325
+
326
+ @timeline.mark(:stop)
327
+ @driver.send(:stop_condition)
328
+ end
329
+ end
330
+
331
+ describe "i2c abstract interface:" do
332
+ it "should initialize with sda, scl properties" do
333
+ expect { I2CDevice::Driver::GPIO.new() }.to raise_error(/required/)
334
+ expect { I2CDevice::Driver::GPIO.new(sda: 1) }.to raise_error
335
+ expect { I2CDevice::Driver::GPIO.new(sda: 1, scl: 2) }.not_to raise_error
336
+ end
337
+
338
+ context "unknown slave address:" do
339
+ describe "i2cset" do
340
+ it "should throw exception on unknown slave address" do
341
+ expect { @driver.i2cset(0x20, 0x00) }.to raise_error(I2CDevice::I2CIOError)
342
+
343
+ expect(@timeline.state(@driver.scl)).to be(1)
344
+ expect(@timeline.state(@driver.sda)).to be(1)
345
+ end
346
+ end
347
+
348
+ describe "i2cget" do
349
+ it "should throw exception on unknown slave address" do
350
+ expect { @driver.i2cget(0x20, 0x00) }.to raise_error(I2CDevice::I2CIOError)
351
+
352
+ expect(@timeline.state(@driver.scl)).to be(1)
353
+ expect(@timeline.state(@driver.sda)).to be(1)
354
+ end
355
+ end
356
+ end
357
+
358
+ context "valid slave address:" do
359
+ before do
360
+ @status = :stop
361
+ @received = []
362
+ @memory = [0x00] * 5
363
+ @max_receive = 3
364
+
365
+ unwatch_scl = nil
366
+ @timeline.watch(@driver.sda) do |state, count|
367
+ case
368
+ when @timeline.state(@driver.scl) == 1 && state == 0
369
+ @status = :start
370
+ @timeline.mark(@status)
371
+ address = 0
372
+ data = 0
373
+ rw = nil
374
+ read_address = 0
375
+ ack = 1
376
+ unwatch_scl.call if unwatch_scl
377
+ unwatch_scl = @timeline.watch(@driver.scl) do |state, count|
378
+ # p [@status, state, count]
379
+ case @status
380
+ when :start
381
+ case
382
+ when state == 1 && count[:high] < 8
383
+ @timeline.mark(8 - count[:high], :bottom)
384
+ address = (address << 1) | @timeline.state(@driver.sda)
385
+ when state == 1 && count[:high] == 8
386
+ @timeline.mark('rw', :bottom)
387
+ rw = @timeline.state(@driver.sda)
388
+ # p " 0b%08b == 0b%08b %02x" % [0x20, address, address]
389
+ when state == 0 && count[:high] == 8
390
+ if address == 0x20
391
+ # ack
392
+ @timeline.default(@driver.sda, 0)
393
+ else
394
+ @status = :unkown
395
+ @timeline.mark(@status)
396
+ end
397
+ when state == 1 && count[:high] == 9
398
+ @timeline.mark('ack')
399
+ when state == 0 && count[:high] == 9
400
+ # reset
401
+ count[:high] = 0
402
+ count[:low] = 0
403
+ @timeline.default(@driver.sda, 1)
404
+ if rw.zero?
405
+ @status = :write
406
+ else
407
+ @status = :read
408
+ read_address = @received[0]
409
+ end
410
+ end
411
+ when :write
412
+ case
413
+ when state == 1 && count[:high] <= 8
414
+ @timeline.mark(8 - count[:high], :bottom)
415
+ data = (data << 1) | @timeline.state(@driver.sda)
416
+ when state == 0 && count[:high] == 8
417
+ if @received.size < @max_receive
418
+ @received << data
419
+ # ack
420
+ @timeline.default(@driver.sda, 0)
421
+ end
422
+ when state == 1 && count[:high] == 9
423
+ @timeline.mark(@received.size <= @max_receive ? 'ack' : 'nack')
424
+ when state == 0 && count[:high] == 9
425
+ # reset
426
+ data = 0
427
+ count[:high] = 0
428
+ count[:low] = 0
429
+ @timeline.default(@driver.sda, 1)
430
+ unless @received.size <= @max_receive
431
+ @status = :stop
432
+ end
433
+ end
434
+ when :read
435
+ case
436
+ when state == 0 && count[:high] < 8
437
+ # send bit
438
+ bit = @memory[read_address][ 7 - count[:high] ]
439
+ @timeline.default(@driver.sda, bit)
440
+ @timeline.add(@driver.sda, bit)
441
+ when state == 1 && count[:high] <= 8
442
+ @timeline.mark(8 - count[:high], :bottom)
443
+ when state == 0 && count[:high] == 8
444
+ @timeline.default(@driver.sda, 1)
445
+ when state == 1 && count[:high] == 9
446
+ ack = @timeline.state(@driver.sda)
447
+ if ack == 0
448
+ @timeline.mark("ack")
449
+ else
450
+ @timeline.mark("nack")
451
+ @status = :stop
452
+ end
453
+ when state == 0 && count[:high] == 9
454
+ read_address += 1
455
+ count[:high] = 0
456
+ count[:low] = 0
457
+ end
458
+ end
459
+ end
460
+ when @timeline.state(@driver.scl) == 1 && state == 1
461
+ @status = :stop
462
+ @timeline.mark(@status)
463
+ unwatch_scl.call
464
+ end
465
+ end
466
+ end
467
+
468
+ describe "i2cset" do
469
+ it "should works successfully" do
470
+ wrote = @driver.i2cset(0x20, 0x0f)
471
+ expect(wrote).to be(1)
472
+ expect(@received).to eq([0x0f])
473
+
474
+ expect(@timeline.state(@driver.scl)).to be(1)
475
+ expect(@timeline.state(@driver.sda)).to be(1)
476
+ end
477
+
478
+ it "should write until nack" do
479
+ @max_receive = 3
480
+ wrote = @driver.i2cset(0x20, 0x01, 0x02, 0x03, 0x04, 0x05)
481
+ expect(wrote).to be(3)
482
+ expect(@received).to eq([0x01, 0x02, 0x03])
483
+
484
+ expect(@timeline.state(@driver.scl)).to be(1)
485
+ expect(@timeline.state(@driver.sda)).to be(1)
486
+ end
487
+ end
488
+
489
+ describe "i2cget" do
490
+ it "should works successfully" do
491
+ @max_receive = 1
492
+ @memory = (0..4).to_a
493
+ got = @driver.i2cget(0x20, 0x01)
494
+ expect(got).to eq("\x01")
495
+
496
+ expect(@timeline.state(@driver.scl)).to be(1)
497
+ expect(@timeline.state(@driver.sda)).to be(1)
498
+ end
499
+
500
+ it "should works with length argument" do
501
+ @max_receive = 1
502
+ @memory = (0..4).to_a
503
+ got = @driver.i2cget(0x20, 0x01, 3)
504
+ expect(got).to eq("\x01\x02\x03")
505
+
506
+ expect(@timeline.state(@driver.scl)).to be(1)
507
+ expect(@timeline.state(@driver.sda)).to be(1)
508
+
509
+ @timeline.dump
510
+ end
511
+ end
512
+ end
513
+ end
514
+ end