Check-in [c6c68c2381]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added low and higher level interfaces.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:c6c68c2381cb51dd583665e68a52c9fbb605579180aef5e41c72ed82ab004516
User & Date: gwlester 2018-01-24 03:56:08
Context
2018-01-25
00:26
Working bno055 module and Gryo Exmaple program using it. check-in: ba6362892d user: gwlester tags: trunk
2018-01-24
03:56
Added low and higher level interfaces. check-in: c6c68c2381 user: gwlester tags: trunk
2018-01-23
05:31
Gyro example coded. check-in: 8fb9d3b213 user: gwlester tags: trunk
Changes

Changes to Gryo_Example.tcl.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


103

104
105
106
107
108
109
110
...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135




136
137
138
139
140






141
142
143
144

145
146
147
148
149
150
151
152
153






154
155
156
157
158
159
160
...
219
220
221
222
223
224
225

226
227
228
229
230
231
232
    500dps  0x10
    2000dps 0x30
    250dps,divisor 128.0
    500dps,divisor 64.0
    2000dps,divisor 16.0
    divisor 1.0
    full_scale_range 0x30
    gryo,offset 0xD2
    gryo,x,axis 0x28
    gryo,y,axis 0x2a
    gryo,z,axis 0x2c
    rate 50.0
    freq 10.0
}

set i2cbus 1
set dIMUaddress {}
set range 2000dps






























































proc StartGyro {handle range} {
    global GyroValues

    set base $GyroValues(gryo,offset)

    ##
    ## Write CTRL_REG1 - Enable all axes. Disable power down.
    ##
    twowire writeregbyte $handle [expr {$base + 0x20}] 0x0F
    piio usleep 10
    set status [twowire readbyte $handle]

    ##
    ## Write CTRL_REG2 - No High Pass Filter.
    ##
    twowire writeregbyte $handle [expr {$base + 0x21}] 0x00
    piio usleep 10
    set status [twowire readbyte $handle]

    ##
    ## Write CTRL_REG3 - No interrupts.  Date ready.
    ##
    twowire writeregbyte $handle [expr {$base + 0x22}] 0x08
    piio usleep 10
    set status [twowire readbyte $handle]

    ##
    ## Write CTRL_REG4 - Specified scale range.
    ##
    twowire writeregbyte $handle [expr {$base + 0x23}] $GyroValues($range)
    piio usleep 10
    set status [twowire readbyte $handle]

    ##
    ## Write CTRL_REG5 - Enable all axes. Disable power down.
    ##
    twowire writeregbyte $handle [expr {$base + 0x24}] 0x00
    piio usleep 10
    set status [twowire readbyte $handle]

    ##
    ## Set divisor so that the output of our gyro axis readings can be turned
    ## into scaled values.
    ##
    set GyroValues(divisor) GyroValues($range,divisor)

    return;
}

##
## Gyro: gets a full axis reading, scaled to the full scale reading.  Returns
## in degrees per second.
##
proc GryoAxisGeading {axis} {
    global GyroValues



    set intValue [twowire readregword $GyroValues(handle) [expr {$base + $GyroValues(gryo,$axis,axis)}]]

    return [format {%8.3f} [expr {$intValue / $GyroValues(divisor)}]]
}

proc ClearHistory {} {
    global CurrentValue

    set CurrentValue(history) {}
................................................................................
    ##
    ## Read the GYROSCOPE
    ##
    set CurrentValue(x) [GryoAxisGeading x]
    set CurrentValue(y) [GryoAxisGeading y]
    set CurrentValue(z) [GryoAxisGeading z]

    ##
    ## See if we need to log it to the listbox widget
    ##
    if {[incr GyroValues(count)] >= $CurrentValue(freq)} {
        set GyroValues(count)
        set timeStamp [clock format [clock seconds]]
        .main.history.data insert {} end -values [list $timeStamp $CurrentValue(x) $CurrentValue(y) $CurrentValue(z)]
    }




}

proc StartReading {} {
    global i2cbus dIMUaddress range GyroValues







    set GyroValues(handle) [twowire twowire $i2cbus $dIMUaddress]
    StartGyro $GyroValues(handle) $range
    set GyroValues(count) 0
    ReadGyro


}

proc StopReading {} {
    global GyroValues

    if {[info exists GyroValues(afterId)]} {
        after cancel $GyroValues(afterId)
    }






}

proc CreateGui {} {
    wm title . "dIMU Gyroscope Example"

    ttk::frame .main
    grid configure .main -sticky nsew
................................................................................
        -text { in seconds}
    ttk::frame $w.buttons
    ttk::button $w.buttons.start \
        -text {Start} \
        -width 6 \
        -command StartReading
    ttk::button $w.buttons.stop \

        -text {Stop} \
        -width 6 \
        -command StopReading
    ttk::button $w.buttons.reset \
        -text {Clear Log} \
        -width 10 \
        -command {.main.history.data delete [.main.history.data children {}]}







<
|
|
|
|
|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











<






<






<






<





<






|











>
>

>







 







|
|
|
|
|
|
|
|
>
>
>
>





>
>
>
>
>
>




>









>
>
>
>
>
>







 







>







28
29
30
31
32
33
34

35
36
37
38
39
40
41
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
    500dps  0x10
    2000dps 0x30
    250dps,divisor 128.0
    500dps,divisor 64.0
    2000dps,divisor 16.0
    divisor 1.0
    full_scale_range 0x30

    gryo,x,axis 0x14
    gryo,y,axis 0x16
    gryo,z,axis 0x18
    rate 50
    freq 10
}

set i2cbus 1
set dIMUaddress {}
set range 2000dps

proc writeRegister {handle register value} {
    global Registers

    lassign $Registers($register) page addr type mask

    twowrite writeregbye $handle [lindex $Registers(page) 1] $page

    if {$mask eq {}} {
        set writeValue $value
    } else {
        ##
        ## Masked values are always byte oriented
        ##
        set writeValue [twowire readregbyte $handle $addr]
        set writeValue [format {%8.8b} $writeValue]
        lassign [split $mask] highBit lowBit
        set size [expr {1 + ($highBit - $lowBit)}]
        set tmp [format "%${size}.${size}b" $value]
        set writeValue [string replace $writeValue end-$hightBit end-$lowBit $tmp]
        scan $writeValue {%8.8b} writeValue
    }

    switch -exact -- $type {
        b {
            twowire writeregbyte $handle $addr $writeValue
        }
        w {
            twowire writeregword $handle $addr $writeValue
        }
    }

    return;
}

proc readRegister {handle register} {
    global Registers

    lassign $Registers($register) page addr type mask

    set result {}

    twowrite writeregbye $handle [lindex $Registers(page) 1] $page
    
    switch -exact -- $type {
        b {
            twowire readregbyte $handle $addr
        }
        w {
            twowire readregword $handle $addr
        }
    }

    if {$mask ne {}} {
        lassign [split $mask {:}] startbit stopbit
        set result [string range [format {%16.16b} $result] end-$startbit end-$stopbit]
        scan $result {%b} result
    }

    return $result
}

proc StartGyro {handle range} {
    global GyroValues

    set base $GyroValues(gryo,offset)

    ##
    ## Write CTRL_REG1 - Enable all axes. Disable power down.
    ##
    twowire writeregbyte $handle [expr {$base + 0x20}] 0x0F
    piio usleep 10


    ##
    ## Write CTRL_REG2 - No High Pass Filter.
    ##
    twowire writeregbyte $handle [expr {$base + 0x21}] 0x00
    piio usleep 10


    ##
    ## Write CTRL_REG3 - No interrupts.  Date ready.
    ##
    twowire writeregbyte $handle [expr {$base + 0x22}] 0x08
    piio usleep 10


    ##
    ## Write CTRL_REG4 - Specified scale range.
    ##
    twowire writeregbyte $handle [expr {$base + 0x23}] $GyroValues($range)
    piio usleep 10


    ##
    ## Write CTRL_REG5 - Enable all axes. Disable power down.
    ##
    twowire writeregbyte $handle [expr {$base + 0x24}] 0x00

    set status [twowire readbyte $handle]

    ##
    ## Set divisor so that the output of our gyro axis readings can be turned
    ## into scaled values.
    ##
    set GyroValues(divisor) $GyroValues($range,divisor)

    return;
}

##
## Gyro: gets a full axis reading, scaled to the full scale reading.  Returns
## in degrees per second.
##
proc GryoAxisGeading {axis} {
    global GyroValues

    set base $GyroValues(gryo,offset)

    set intValue [twowire readregword $GyroValues(handle) [expr {$base + $GyroValues(gryo,$axis,axis)}]]
    piio usleep 10
    return [format {%8.3f} [expr {$intValue / $GyroValues(divisor)}]]
}

proc ClearHistory {} {
    global CurrentValue

    set CurrentValue(history) {}
................................................................................
    ##
    ## Read the GYROSCOPE
    ##
    set CurrentValue(x) [GryoAxisGeading x]
    set CurrentValue(y) [GryoAxisGeading y]
    set CurrentValue(z) [GryoAxisGeading z]

}

proc LogValues {} {
    global GyroValues CurrentValue

    if {[info exists GyroValues(logId)]} {
        after cancel $GyroValues(logId)
    }
    set GyroValues(logId) [after [expr {$GyroValues(freq) * 100}] LogValues]

    set timeStamp [clock format [clock seconds]]
    .main.history.data insert {} end -values [list $timeStamp $CurrentValue(x) $CurrentValue(y) $CurrentValue(z)]
}

proc StartReading {} {
    global i2cbus dIMUaddress range GyroValues

    if {$dIMUaddress eq {}} {
        return
    }

    .main.controls.buttons.start configure -state disabled
    .main.controls.buttons.stop configure -state normal
    set GyroValues(handle) [twowire twowire $i2cbus $dIMUaddress]
    StartGyro $GyroValues(handle) $range
    set GyroValues(count) 0
    ReadGyro
    LogValues

}

proc StopReading {} {
    global GyroValues

    if {[info exists GyroValues(afterId)]} {
        after cancel $GyroValues(afterId)
    }
    if {[info exists GyroValues(logId)]} {
        after cancel $GyroValues(logId)
    }
    
    .main.controls.buttons.start configure -state normal 
    .main.controls.buttons.stop configure -state disabled
}

proc CreateGui {} {
    wm title . "dIMU Gyroscope Example"

    ttk::frame .main
    grid configure .main -sticky nsew
................................................................................
        -text { in seconds}
    ttk::frame $w.buttons
    ttk::button $w.buttons.start \
        -text {Start} \
        -width 6 \
        -command StartReading
    ttk::button $w.buttons.stop \
        -state disabled \
        -text {Stop} \
        -width 6 \
        -command StopReading
    ttk::button $w.buttons.reset \
        -text {Clear Log} \
        -width 10 \
        -command {.main.history.data delete [.main.history.data children {}]}

Added bno055_1.0.0.tm.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
##
## Provides a ensemble for low level access a Bosch Sensortec BNO055 Intelligent
## 9-axis absolute orientation sensor. The Data Sheet for this sensor is at:
##      https://www.mouser.com/pdfdocs/BST_BNO055_DS000_14.pdf
##
## This sensor can appear at the following addresses:
##  I2C:        0x29 (primary) or 0x28 (alternate)
##  HID-I2C:    0x40
##
## Please see sction 4.6 of the Data Sheet for details of selecting the address.
##
package require piio

namespace eval bno055 {
    ##
    ## Register definition format: page address b(yte)|w(word) ?highBit:lowBit?
    ## least significant bit is 0.
    ##
    ## NOTE -- some registers are read/read and some are read only, the software
    ##         does not check if an attempt is made to write to a read only
    ##         register.
    ##
    ## NOTE -- no checks are preformed to see if the device is in the correct
    ##         mode to read or write a perticular register. Accessing a register
    ##         when the device is not in the correct mode may result in either
    ##         an error or garbage being return.
    ##
    ## NOTE -- in the Data Sheet, PAGE_ID is colored as read only but the textual
    #          description in section 4.2 explicitly states it is used to switch
    #          between pages.
    ##
    array set Registers {
        main,chipId     {0 0x00 b}
        acc,chipId      {0 0x01 b}
        mag,chipId      {0 0x02 b}
        gyro,chipId     {0 0x03 b}
        sw,rev          {0 0x04 w}
        bl,rev          {0 0x06 b}
        page            {0 0x07 b}
        acc,data,x      {0 0x08 w}
        acc,data,y      {0 0x0a w}
        acc,data,z      {0 0x0c w}
        mag,data,x      {0 0x0e w}
        mag,data,y      {0 0x10 w}
        mag,data,z      {0 0x12 w}
        gyr,data,x      {0 0x04 w}
        gyr,data,y      {0 0x16 w}
        gyr,data,z      {0 0x18 w}
        heading         {0 0x1a w}
        roll            {0 0x1c w}
        pitch           {0 0x1e w}
        qua,data,w      {0 0x20 w}
        qua,data,x      {0 0x22 w}
        qua,data,y      {0 0x24 w}
        qua,data,z      {0 0x26 w}
        lia,data,x      {0 0x28 w}
        lia,data,y      {0 0x2a w}
        lia,data,z      {0 0x2c w}
        grv,data,x      {0 0x2e w}
        grv,data,y      {0 0x30 w}
        grv,data,z      {0 0x32 w}
        temp,data       {0 0x34 b}
        mag,cab,status  {0 0x35 b 1:0}
        acc,cab,status  {0 0x35 b 3:2}
        gyr,cab,status  {0 0x35 b 5:4}
        sys,cab,status  {0 0x35 b 7:6}
        acc,selftest    {0 0x36 b 0:0}
        mag,selftest    {0 0x36 b 1:1}
        gyr,selftest    {0 0x36 b 2:2}
        mcu,selftest    {0 0x36 b 3:3}
        gyr,anymotion   {0 0x37 b 2:2}
        gyr,highrate    {0 0x37 b 3:3}
        acc,highG       {0 0x37 b 5:5}
        acc,anymotion   {0 0x37 b 6:6}
        acc,nomotion    {0 0x37 b 7:7}
        sys,clk,status  (0 0x38 b 0:0)
        sys,status      {0 0x39 b}
        sys,error       (0 0x3a b)
        acc,units       {0 0x3b b 0:0}
        gyr,units       {0 0x3b b 1:1}
        eul,units       {0 0x3b b 2:2}
        temp,units      {0 0x3b b 4:4}
        format,opt      {0 0x3b b 7:7}
        operMode        {0 0x3d b 3:0}
        powerMode       {0 0x3e b 1:0}
        runSelfTest     {0 0x3f b 0:0}
        sytemReset      {0 0x3f b 5:5}
        resetInt        {0 0x3f b 6:6}
        clockSource     {0 0x3f b 7:7}
        tempSource      {0 0x40 b 1:0}
        remap,x,value   {0 0x41 b 1:0}
        remap,y,value   {0 0x41 b 3:2}
        remap,z,value   {0 0x41 b 5:4}
        remap,x,sign    {0 0x42 b 0:0}
        remap,y,sign    {0 0x43 b 1:1}
        remap,z,sign    {0 0x43 b 2:2}
        acc,x,offset    {0 0x55 w}
        acc,y,offset    {0 0x57 w}
        acc,z,offset    {0 0x59 w}
        mag,x,offset    {0 0x5b w}
        mag,y,offset    {0 0x5d w}
        mag,z,offset    {0 0x5f w}
        gyr,x,offset    {0 0x61 w}
        gyr,y,offset    {0 0x63 w}
        gyr,z,offset    {0 0x65 w}
        acc,radius      {0 0x67 w}
        mag,radius      {0 0x69 w}

        acc,range       {1 0x08 b 1:0}
        acc,bandwidth   {1 0x08 b 4:2}
        acc,pwrMode     {1 0x08 b 7:5}
        mag,rate        {1 0x09 b 2:0}
        mag,operMode    {1 0x09 b 4:3}
        mag,pwrMode     {1 0x09 b 6:5}
        gyr,range       {1 0x0a b 2:0}
        gyr,bandwidth   {1 0x0a b 5:3}
        gyr,pwrMode     {1 0x0b b 2:0}
        acc,sleepMode   {1 0x0c b 0:0}
        acc,sleepDur    {1 0x0c b 4:1}
        gyr,am,intMask  {1 0x0f b 2:2}
        gyr,hiR,intMask {1 0x0f b 3:3}
        acc,hiG,intMask {1 0x0f b 5:5}
        acc,am,intMask  {1 0x0f b 6:6}
        acc,nm,intMask  {1 0x0f b 7:7}
        gyr,am,intEnab  {1 0x10 b 2:2}
        gyr,hiR,intEnab {1 0x10 b 3:3}
        acc,hiG,intEnab {1 0x10 b 5:5}
        acc,am,intEnab  {1 0x10 b 6:6}
        acc,nm,intEnab  {1 0x10 b 7:7}
        acc,am,thresh   {1 0x11 b}
        acc,am,dur      {1 0x12 b 1:0}
        acc,an,x        {1 0x12 b 2:2}
        acc,an,y        {1 0x12 b 3:3}
        acc,an,z        {1 0x12 b 4:4}
        acc,hi,x        {1 0x12 b 5:5}
        acc,hi,y        {1 0x12 b 6:6}
        acc,hi,z        {1 0x12 b 7:7}
        acc,hi,thresh   {1 0x13 b}
        acc,hi,durr     {1 0x14 b}
        acc,nm,thresh   {1 0x15 b}
        acc,smnm,enab   {1 0x16 b 0:0}
        acc,smnm,durr   {1 0x16 b 7:1}
        gyr,am,x,enab   {1 0x17 b 0:0}
        gyr,am,y,enab   {1 0x17 b 1:1}
        gyr,am,z,enab   {1 0x17 b 2:2}
        gyr,hr,x,enab   {1 0x17 b 3:3}
        gyr,hr,y,enab   {1 0x17 b 4:4}
        gyr,hr,z,enab   {1 0x17 b 5:5}
        gyr,am,filter   {1 0x17 b 6:6}
        gyr,hr,filter   {1 0x17 b 7:7}
        gyr,hr,x,thres  {1 0x18 b 4:0}
        gyr,hr,x,hyst   {1 0x18 b 6:5}
        gyr,hr,x,durr   {1 0x19 b}
        gyr,hr,y,thres  {1 0x1a b 4:0}
        gyr,hr,y,hyst   {1 0x1a b 6:5}
        gyr,hr,y,durr   {1 0x1b b}
        gyr,hr,z,thres  {1 0x1c b 4:0}
        gyr,hr,z,hyst   {1 0x1c b 6:5}
        gyr,hr,z,durr   {1 0x1d b}
        gyr,am,slope    {1 0x1e b 1:0}
        gyr,am,durr     {1 0x1e b 3:2}
        
        uniqueId        {1 0x50 m 16}
    }

    array set Constants {
        CALIB_STAT,0    false
        CALIB_STAT,1    unknown
        CALIB_STAT,2    unknown
        CALIB_STAT,3    true
        SYS_STATUS,1    {System Error}
        SYS_STATUS,2    {Initializing peripherals}
        SYS_STATUS,3    {System Initialization}
        SYS_STATUS,4    {Executing selftest}
        SYS_STATUS,5    {Sensor fusion algorithm running}
        SYS_STATUS,6    {System running without fusion algorithm}
        SYS_ERROR,0     {No error}
        SYS_ERROR,1     {Peripheral initialization error}
        SYS_ERROR,2     {System initialization error}
        SYS_ERROR,3     {Self test result failed}
        SYS_ERROR,4     {Register map value out of range}
        SYS_ERROR,5     {Register map address out of range}
        SYS_ERROR,6     {Register map write error}
        SYS_ERROR,7     {BNO low power mode not available for selected operation mode}
        SYS_ERROR,8     {Accelerometer power mode not available}
        SYS_ERROR,9     {Fusion algorithm configuration error}
        SYS_ERROR,10    {Sensor configuration error}
    }

    proc SymDef {type symbolic value} {
        variable Constants

        set Constants($type,$value) ${type}_${symbolic}
        set Constants(CONST,${type}_${symbolic}) $value
    }

    SymDef ORI_MODE WINDOWS 0
    SymDef ORI_MODE ANDROID 1
    SymDef TEMP_UNIT C 0
    SymDef TEMP_UNIT F 1
    SymDef EUL_UNIT DEG 0
    SymDef EUL_UNIT RAD 1
    SymDef GRY_UNIT DPS 0
    SymDef GRY_UNIT RPS 1
    SymDef ACC_UNIT MPS2 0
    SymDef ACC_UNIT MG 1
    SymDef OPER_MODE CONFIGMODE 0b0000
    SymDef OPER_MODE ACCONLY 0b0001
    SymDef OPER_MODE MAGONLY 0b0010
    SymDef OPER_MODE GYROONLY 0b0011
    SymDef OPER_MODE ACCMAG 0b0100
    SymDef OPER_MODE ACCGYRO 0b0101
    SymDef OPER_MODE MAGGYRO 0b0110
    SymDef OPER_MODE AMG 0b0111
    SymDef OPER_MODE IMU 0b1000
    SymDef OPER_MODE COMPASS 0b1001
    SymDef OPER_MODE M4G 0b1010
    SymDef OPER_MODE NDOF_FMC_OFF 0b1011
    SymDef OPER_MODE NDOF 0b1100
    SymDef PWR_MODE NORMAL 0b00
    SymDef PWR_MODE LOW 0b01
    SymDef PWR_MODE SUSPEND 0b10
    SymDef TEMP_SRC ACC 0
    SymDef TEMP_SRC GRY 1
    SymDef REMAP_TO X 0b00
    SymDef REMAP_TO Y 0b01
    SymDef REMAP_TO Z 0b10
    SymDef REMAP_SIGN POS 0
    SymDef REMAP_SIGN NEG 1
    SymDef ACC_RANGE 2G 0b00B
    SymDef ACC_RANGE 4G 0b01B
    SymDef ACC_RANGE 8G 0b10B
    SymDef ACC_RANGE 16G 0b11B
    SymDef ACC_BANDWIDTH 7.81HZ 0b000
    SymDef ACC_BANDWIDTH 15.63HZ 0b001
    SymDef ACC_BANDWIDTH 31.25HZ 0b010
    SymDef ACC_BANDWIDTH 62.5HZ 0b011
    SymDef ACC_BANDWIDTH 125HZ 0b100
    SymDef ACC_BANDWIDTH 250HZ 0b101
    SymDef ACC_BANDWIDTH 500HZ 0b110
    SymDef ACC_BANDWIDTH 1000HZ 0b111
    SymDef ACC_OPER_MODE NORMAL 0b000
    SymDef ACC_OPER_MODE SUSPEND 0b001
    SymDef ACC_OPER_MODE LOW_POWER_1 0b010
    SymDef ACC_OPER_MODE STANDBY 0b011
    SymDef ACC_OPER_MODE LOW_POWER_2 0b100
    SymDef ACC_OPER_MODE DEEP_SUSPEND 0b101
    SymDef MAG_DATA_RATE 2Hz 0b000
    SymDef MAG_DATA_RATE 6Hz 0b001
    SymDef MAG_DATA_RATE 8Hz 0b010
    SymDef MAG_DATA_RATE 10Hz 0b011
    SymDef MAG_DATA_RATE 15Hz 0b100
    SymDef MAG_DATA_RATE 20Hz 0b101
    SymDef MAG_DATA_RATE 25Hz 0b110
    SymDef MAG_DATA_RATE 30Hz 0b111
    SymDef MAG_OPER_MODE LOW  0b00
    SymDef MAG_OPER_MODE REGULAR 0b01
    SymDef MAG_OPER_MODE ENHANCED 0b10
    SymDef MAG_OPER_MODE HIGH 0b11
    SymDef MAG_POWER_MODE NORMAL 0b00
    SymDef MAG_POWER_MODE SLEEP 0b01
    SymDef MAG_POWER_MODE SUSPEND 0b10
    SymDef MAG_POWER_MODE FORCE 0b11
    SymDef GRY_RANGE 2000DPS 0b000
    SymDef GRY_RANGE 1000DPS 0b001
    SymDef GRY_RANGE 500DPS 0b010
    SymDef GRY_RANGE 250DPS 0b011
    SymDef GRY_RANGE 125DPS 0b100
    SymDef GRY_BANDWIDTH 523HZ 0b000
    SymDef GRY_BANDWIDTH 230HZ 0b001
    SymDef GRY_BANDWIDTH 116HZ 0b010
    SymDef GRY_BANDWIDTH 47HZ 0b011
    SymDef GRY_BANDWIDTH 23HZ 0b100
    SymDef GRY_BANDWIDTH 12HZ 0b101
    SymDef GRY_BANDWIDTH 64HZ 0b110
    SymDef GRY_BANDWIDTH 32HZ 0b111
    SymDef GRY_POWER_MODE NORMAL 0b000
    SymDef GRY_POWER_MODE FAST_UP 0b001
    SymDef GRY_POWER_MODE DEEP_SUSPEND 0b010
    SymDef GRY_POWER_MODE SUSPEND 0b011
    SymDef GRY_POWER_MODE ADVANCED_POWERSAVE 0b100
    SymDef ACC_SLEEP_MODE EVENT 0
    SymDef ACC_SLEEP_MODE EQUIDISTANT 1
    set value 0
    foreach item {0.5MS 0.5MS 0.5MS 0.5MS 0.5MS 0.5MS 1MS 2MS 4MS 6MS 10MS 25MS 50MS 100MS 500MS 1000MS} {
        SymDef ACC_SLEEP_DURR $item $value
        incr value
    }
    set value 1
    foreach item {4MS 5MS 8MS 10MS 15MS 20MS 40MS} {
        SymDef GRY_AUTOSLP_DURR $item $value
        incr value
    }
    set value 0
    foreach item {4MS 5MS 8MS 10MS 15MS 18MS 20MS} {
        SymDef GRY_SLEEP_DURR $item $value
        incr value
    }
    unset value
    SymDef GYR_AWAKE_DURR 8SAMPLES 0
    SymDef GYR_AWAKE_DURR 16SAMPLES 1
    SymDef GYR_AWAKE_DURR 32SAMPLES 2
    SymDef GYR_AWAKE_DURR 64SAMPLES 3

    proc getValue {symbolic} {
        variable Constants

        return $Constants(symbol,$symbolic)
    }

    proc getSymbol {type value} {
        variable Constants

        return $Constants($type,$value)
    }

    proc writeRegister {handle register value} {
        global Registers

        lassign $Registers($register) page addr type mask

        twowrite writeregbye $handle [lindex $Registers(page) 0] $page

        if {$mask eq {}} {
            set writeValue $value
        } else {
            ##
            ## Masked values are always byte oriented
            ##
            set writeValue [twowire readregbyte $handle $addr]
            set writeValue [format {%16.16b} $writeValue]
            lassign [split $mask] highBit lowBit
            set size [expr {1 + ($highBit - $lowBit)}]
            set tmp [format "%${size}.${size}b" $value]
            set writeValue [string replace $writeValue end-$hightBit end-$lowBit $tmp]
            scan $writeValue {%b} writeValue
        }

        switch -exact -- $type {
            b {
                twowire writeregbyte $handle $addr $writeValue
            }
            w {
                twowire writeregword $handle $addr $writeValue
            }
            m {
                ##
                ## Not supported in write mode
                ##
                throw {UNSUP WRTMODE} "Multibyte writes are not supported at this time"
            }
        }

        return;
    }

    proc writeRegisterBlock {handle args} {
        global Registers

        ##
        ## Verify we need to do something
        ##
        if {[llength $args]} {
            return
        } elseif {[llength $args] == 2} {

        } elseif {([llength $args] % 2) != 0} {
            throw {BADARGCNT} {Arguements must be pairs of register value}
        }

        ##
        ## Build the detail list of what we need to do
        ##
        set detailList {}
        set targetpage [lindex $Registers([lindex $args 0]) 0]
        foreach {register value} {
            lassign $register page address type mask
            if {$mask eq {}} {
                throw [list NONMANKREG $register] "'$register' is not a bit field register, only bit field registers are supported in a block write."
            }
            lappend detailList [list $page $address type $mask $value]
            if {$targetpage ne $page} {
                throw {MULTIPAGE} "Multipage block writes are not allowed"
            }
        }
        
        ##
        ## Get it as an ordered list and verify no more than one word
        ##
        set detailList [lsort -integer -increasing -index 1 $detailList]
        set size [expr {1 + [lindex $detailList end 1] - [lindex $detailList 0 1]}]
        if {$size > 2} {
            throw [list RANGEERR $size] "Register range $size bytes too large.  Maximum size is 2 bytes."
        }
        set addr [lindex $detailList 0 1]
        
        ##
        ## Build the value to write
        ##
        set writeValue [string repeat 0 [expr {$size * 8}]]
        foreach registerInfo $detailList {
            lassign $registerInfo page address type mask value
            lassign [split $mask] highBit lowBit
            if {$address ne $addr} {
                incr highBit 8
                incr lowBit 8
            }
            set size [expr {1 + ($highBit - $lowBit)}]
            set tmp [format "%${size}.${size}b" $value]
            set writeValue [string replace $writeValue end-$hightBit end-$lowBit $tmp]
        }
        scan $writeValue {%b} writeValue

        twowrite writeregbye $handle [lindex $Registers(page) 0] $page

        switch -exact -- $size {
            1 {
                twowire writeregbyte $handle $addr $writeValue
            }
            2 {
                twowire writeregword $handle $addr $writeValue
            }
        }

        return;
    }

    proc readRegister {handle register} {
        global Registers

        lassign $Registers($register) page addr type mask

        set result {}

        twowrite writeregbye $handle [lindex $Registers(page) 0] $page

        switch -exact -- $type {
            b {
                set result [twowire readregbyte $handle $addr]
            }
            w {
                set result [twowire readregword $handle $addr]
            }
            m {
              for {set cnt 1} {$cnt <= $mask} {incr cnt; incr addr} {
                append result [format {%2.2x} [twowire readregbyte $handle $addr]]
              } 
            }
        }

        if {$mask ne {} && $type ne {m}} {
            lassign [split $mask {:}] startbit stopbit
            set result [string range [format {%16.16b} $result] end-$startbit end-$stopbit]
            scan $result {%b} result
        }

        return $result
    }


    namespace ensemble create -subcommands {
        getValue
        getSymbol
        readRegister
        writeRegister
        writeRegisterBlock
    }

}

Changes to dMIU.komodoproject.

1
2
3
4

5
6
<?xml version="1.0" encoding="UTF-8"?>
<!-- Komodo Project File - DO NOT EDIT -->
<project id="3be2a3a6-bb09-4bd7-bb7c-2bfdb3a7e0fa" kpf_version="5" name="dMIU.komodoproject">
<preference-set idref="3be2a3a6-bb09-4bd7-bb7c-2bfdb3a7e0fa" id="project" preftype="project">

</preference-set>
</project>




>


1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!-- Komodo Project File - DO NOT EDIT -->
<project id="3be2a3a6-bb09-4bd7-bb7c-2bfdb3a7e0fa" kpf_version="5" name="dMIU.komodoproject">
<preference-set idref="3be2a3a6-bb09-4bd7-bb7c-2bfdb3a7e0fa" id="project" preftype="project">
  <long id="prefs_version">1</long>
</preference-set>
</project>

Added dimu_1.0.0.tm.































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
##
## Provide a singlton class for the Dexter Industries Inertial Motion Unit (IMU) sensor.
##
package require piio
package require bno055
package require oo::util

oo::class create dimu {
    self mixin singleton

	self method init {} {
		variable HardwiredSettings
		variable OptionDef

		set OptionDef {
            -bus        {-default 1}
			-mode		{-default {}}
		}

		set HardwiredSettings {
			address 0x28
		}

		::oo::objdefine [self] deletemethod init
	}

    method ProcessArgs {inputArgs classArgsDict} {
        variable instanceInfo

        set unprocessedArgs {}
        array set missingRequiredArr {}
        if {![info exists instanceInfo]} {
            set instanceInfo {}
        }

        ##
        ## Set the class defaults
        ##
        foreach {arg argDefList} $classArgsDict {
            if {[dict exists $instanceInfo options $arg]} {
                ##
                ## Has already been processed by a subclass
                ##
                continue
            }
            if {"-boolean" in $argDefList} {
                dict set instanceInfo options $arg false
            }
            if {"-default" in $argDefList} {
                set i [lsearch -exact $argDefList "-default"]
                dict set instanceInfo options $arg [lindex $argDefList [incr i]]
                dict set instanceInfo defaults $arg [lindex $argDefList $i]
            } else {
                dict set instanceInfo defaults $arg {}
            }
            if {"-required" in $argDefList} {
                set missingRequiredArr($arg) 1
            }
        }

        ##
        ## Process each argument
        ##
        set argCount [llength $inputArgs]
        for {set i 0} {$i < $argCount} {incr i} {
            ##
            ## If argument is a class argument, overide the default
            ##
            set arg [lindex $inputArgs $i]
            if {[dict exists $classArgsDict $arg]} {
                set argDef [dict get $classArgsDict $arg]
                if {"-boolean" in $argDef} {
                    dict set instanceInfo options $arg true
                } else {
                    dict set instanceInfo options $arg [lindex $inputArgs [incr i]]
                }
                unset -nocomplain missingRequiredArr($arg)
            } else {
                ##
                ## If argument is not a class argument, append it to the unprocessed argument
                ##
                lappend unprocessedArgs $arg
            }
        }

        set missingRequired [array names missingRequiredArr]
        if {[llength $missingRequired]} {
            throw [list PTK MISSING OPTION $missingRequired] "missing required options: \"$missingRequired\""
        }

        return $unprocessedArgs
    }


    constructor {args} {
		variable instanceInfo
		variable OptionDef
        variable HardwiredSettings

        set remainingArgs [ProcessArgs $args $OptionDef]
        if {[llength $remainingArgs]} {
			set arg1 [lindex $remainingArgs 0]
			throw [list LOOKUP OPTION $arg1] "unknown option \"$arg1\""
		}

        set bus [my cget -bus]
		dict set instanceInfo handle [twowire twowire $bus $HardwiredSettings(address)]

		return
    }

    destructor {
		variable instanceInfo

		##
		## Close the handle to the device
		##
        close [dict get $instanceInfo handle]
    }
    
    
    method cget {option} {
        variable instanceInfo

        if {[dict exists $instanceInfo options $option]} {
            return [dict get $instanceInfo options $option]
        } else {
            set legalOptions [dict keys [dict get $instanceInfo options]]
            throw [list TK LOOKUP OPTION $option] "unknown option \"$option\" -- legal options are: [join $legalOptions {,}]"
        }
    }

    method configure {args} {
        variable instanceInfo

        set argLen [llength $args]
        if {$argLen == 0} {
            set returnList {}
            if {[dict exists $instanceInfo options]} {
                foreach option [lsort -dictionary [dict keys [dict get $instanceInfo options]]] {
                    ##
                    ## Order is optionName defaultValue currentValue
                    ##
                    set itemList [list $option [dict get $instanceInfo defaults $option] [dict get $instanceInfo options $option]]
                    lappend returnList $itemList
                }
            }
            return $returnList
        } elseif {$argLen == 1} {
            set option [lindex $args 0]
            if {[dict exists $instanceInfo options $option]} {
                return [dict get $instanceInfo options $option]
            } else {
                set legalOptions [dict keys [dict get $instanceInfo options]]
                throw [list LOOKUP OPTION $option] "unknown option \"$option\" -- legal options are: [join $legalOptions {,}]"
            }
        } elseif {($argLen % 2) == 0} {
            foreach {option value} $args {
                if {[dict exists $instanceInfo options $option]} {
                    dict set instanceInfo options $option $value
                    ## put in code to change the configureation
                } else {
                    set legalOptions [dict keys [dict get $instanceInfo options]]
                    throw [list LOOKUP OPTION $option] "unknown option \"$option\" -- legal options are: [join $legalOptions {,}]"
                }
            }
        }
            
        return;

    }

}

dimu init