Check-in [cbe12efdf4]

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

Overview
Comment:General configration section of dIMU class and Multisenor example working.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:cbe12efdf436b24712cb2aa020765abb3245506b4f67529c73d03f508d5c8c4a
User & Date: gwlester 2018-02-09 22:38:06
Context
2018-02-09
22:39
Correction of wide spread typo. check-in: cecb467b84 user: gwlester tags: trunk
22:38
General configration section of dIMU class and Multisenor example working. check-in: cbe12efdf4 user: gwlester tags: trunk
2018-02-08
05:50
Correct several bugs. check-in: a2782097ce user: gwlester tags: trunk
Changes

Changes to examples/Multisensor_Example.tcl.

48
49
50
51
52
53
54
55







56
57
58
59
60
61

62
63
64
65
66
67
68
..
75
76
77
78
79
80
81

























































82
83
84
85
86
87
88
...
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
...
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
...
220
221
222
223
224
225
226








227
228
229
230
231
232
233
...
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
264
265
266
267
268
269
270




271


































































































272
273
274
275
276

















277
278
279
280
281
282
283
...
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
...
404
405
406
407
408
409
410


411
412
413
414
415
416
417
...
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
470
471
472
473


474
475
476
477
478
479
480
...
500
501
502
503
504
505
506
507
508
509

510
511
512
513
514
515
516
...
526
527
528
529
530
531
532


533
534
535
536
537
538
539
...
563
564
565
566
567
568
569


570
571
572
573
574
575


576

577
578

579
580

581
582

583
584
585
586
587


588
589
590
591
592
593
594
595
596
597
598
...
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814

815
816
817





array set MagValues {
    range 2000dps
    digits 5
    decimals 1
    minChange 0.1
    formatStr {%7.1}
}








array set Configuration {
    i2cbus 1
    dIMUaddress 0x28
}

array set UI {

    operation,map,label {
        configmode      "Configuration Mode"
        acconly         "Accelerometer Only"
        magonly         "Magnetometer Only"
        gyroonly        "Gyroscope Only"
        accmag          "Accelerometer and Magnetometer Only"
        accgyro         "Accelerometer and Gyroscope Only"
................................................................................
        ndof            "9 Degrees of Freedom -- Fast Magnetometer Calibration On"
    }
    power,map,label     {
        normal          "Normal"
        low             "Low"
        suspend         "Suspend"
    }

























































}

foreach key [array names UI "*,map,label"] {
    lassign [split $key ","] option
    set maxLabelSize -1
    foreach {symbol label} $UI($key) {
        dict set UI($option,map,symbol) $label $symbol
................................................................................
##
## Begin procedure definition section
##
proc ChangeOperationMode {varName index op} {
    global UI
    global Configuration

    set mode [dict get $UI(operation,map,symbol) $Configuration(operation]

    if {$mode ne "configmode"} {
        DisableConfigurationWidgets
        EnableTabs $mode
    } else {
        EnableConfigurationWidgets
        DisableTabs













    }
}

proc ConfigurationChange {varName index op} {
    global UI
    global CurrentValue
    upvar #0 $varName configuration




    set value $configuration($index)
    if  {$index eq refreshRate} {
        return
    } elseif {[info exists UI($index,map,symbol)]} {
        set value [dict get $UI($index,map,symbol) $value]
    }
    $CurrentValue(handle) configure -$index $value
}
































proc DisableTabs {} {
    global UI

    set notebook $UI(mainNotebook)
    foreach {tab widget} [array get UI {main,*}] {
        $nodebook tab $widget -state disabled
    }

    $nodebook tab $UI(main,configuration) -state normal
    $nodebook select $UI(main,configuration)
}

proc EnableTags {mode} {
    global UI

    DisableTabs

    set notebook $UI(mainNotebook)
    switch -exact -- $mode {
        configmode -
................................................................................
        }
        imu -
        compass -
        m4g -
        ndof_fmc_off -
        ndof {
            foreach {tab widget} [array get UI {main,*}] {
                $nodebook tab $widget -state normal
            }
        }
    }
}

proc ReadGyro {} {
    global CurrentValue
    global GryoValues

    ##
    ## Read the gyroscope
    ##
    set currentReadings [$CurrentValue(handle) readGyro]
    set formatStr $GryoValues(formatStr)
    set x [format $formatStr [dict get $currentReadings x]]
    set y [format $formatStr [dict get $currentReadings z]]
    set z [format $formatStr [dict get $currentReadings z]]
    set minChange $GryoValues(minChange
    if {abs($x - $CurrentValue(gyroscope,x)) > $minChange ||
        abs($y - $CurrentValue(gyroscope,y)) > $minChange ||
        abs($z - $CurrentValue(gyroscope,z)) > $minChange
    } {
        LogValues $x $y $z
        
        ##
................................................................................
        set CurrentValue(gyroscope,x) $x
        set CurrentValue(gyroscope,y) $y
        set CurrentValue(gyroscope,z) $z
    }

    return
}









proc LogValues {type} {
    variable WidgetData
    variable CurrentValue

    #if {[info exists CurrentValue(logId)]} {
    #    after cancel $CurrentValue(logId)
................................................................................
    set x $CurrentValue($type,x)
    set y $CurrentValue($type,y)
    set z $CurrentValue($type,z)
    $WidgetData($type,history) insert {} end -values [list $timeStamp $x $y $z]
}

proc StartReading {} {
    global i2cbus dIMUaddress range CurrentValue

    if {$dIMUaddress eq {}} {
        return
    }

    .main.controls.buttons.start configure -state disabled
    .main.controls.buttons.stop configure -state normal
    StartGyro $CurrentValue(handle) $range
    ReadGyro

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







































































































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


















    set UI(mainNotebook) [ttk::notebook .main]
    grid configure .main -sticky nsew
    grid columnconfigure . .main -weight 1
    grid rowconfigure . .main -weight 1
    
    set UI(main,configuration) [ttk::frame .main.configuration]
    .main add .main.configuration -text {Configuration}
................................................................................
proc CreateGeneralConfigFrame {general} {
    ##
    ## General Configuration group
    ##
    ttk::label $general.busLbl \
        -text {I2C Bus:}
    ttk::combobox $general.busCMB \
        -textvariable ::Configuration(i2cbus) \
        -values [list 1] \
        -state readonly
    ttk::label $general.addrLbl \
        -text {iDMU Address:}
    ttk::entry $general.addrEnt \
        -width 5 \
        -textvariable ::Configuration(dIMUaddress) \
        -state readonly















    ttk::label $general.rateLbl1 \
        -text {Refresh Rate:}
    ttk::spinbox $general.rateEnt \
        -from 50.0 \
        -to 500.0 \
        -increment 10.0 \
        -format {%3.0f} \
        -wrap no \
        -command [format {set ::Configuration(refreshRate) [expr {entier([%1$s get])}]}  $general.rateEnt]
    ttk::label $general.rateLbl2 \
        -text { in microseconds}
    ttk::label $general.operLbl1 \
        -text {Operational Mode}
    # change values to be human readable
    ttk::combobox $general.operCMB \
        -textvariable ::Configuration(operation) \
        -values [dict keys $::UI(operation,map,symbol)] \
        -width $::UI(operation,maxLabelSize) \
        -state readonly
    ttk::label $general.pwrLbl1 \
        -text {Power Mode}
    ttk::combobox $general.pwrCMB \
        -textvariable ::Configuration(power) \
        -values [dict keys $::UI(power,map,symbol)] \
        -width $::UI(power,maxLabelSize) \
        -state readonly

    # Add axis remap and axis sign
    # Add self test results
    # Add clock select if sys_clk_status is true
    # Reset interupt
    # Reset system
    # Add self test trigger
    # Fusion Unit Type (Andriod vs Windows)
    # System Calibration status
    # Unique ID
    # Add temp source
    # Add Temp units
    # Add Temp reading
    # Add EUL units















    # Add System Status




    # Add System Error Code























































































    grid configure $general.busLbl $general.busCMB x x -padx 2 -pady 2 -sticky ew
    grid configure $general.addrLbl $general.addrEnt x x -padx 2 -pady 2 -sticky ew






    grid configure $general.rateLbl1 $general.rateEnt $general.rateLbl2 x -padx 2 -pady 2 -sticky ew
    grid configure $general.operLbl1 $general.operCMB x x -padx 2 -pady 2 -sticky ew
    grid configure $general.pwrLbl1 $general.pwrCMB x x -padx 2 -pady 2 -sticky ew





    grid columnconfigure $general $general.addrEnt -uniform entry















    grid columnconfigure $general 3 -weight 1


    $general.rateEnt set 50.0

}

proc CreateAccelConfigFrame {accel} {
    ##
    ## Accelerometer group
    ##
    ttk::label $accel.rangeLbl \
        -text {Range:}
    ttk::combobox $accel.rangeCMB \
        -textvariable ::range \
        -values [list 250dps 500dps 2000dps] \
        -state readonly

    ttk::label $accel.numDigitsLbl \
        -text {Digits before decimal}
    ttk::combobox $accel.numDigitsCMB \
        -textvariable ::AccelValues(digits) \
        -values [list 3 4] \
        -state readonly
    ttk::label $accel.numDecimalsLbl \
................................................................................
        -to 200.0 \
        -increment 0.1 \
        -format {%5.1f} \
        -wrap no \
        -textvariable ::AccelValues(minChange)
    ttk::label $accel.minChangeLbl2 \
        -text {dps change}


    # Add ACC units
    # Add Self Test status
    # Add Calibration status
    # Add Unit Select
    # Add offsets
    # Add radius
    # Add Acc No Motion Interrupt Status
................................................................................
proc CreateGyroConfigFrame {gyro} {
    ##
    ## Gyrometer
    ##
    ttk::label $gyro.rangeLbl \
        -text {Range:}
    ttk::combobox $gyro.rangeCMB \
        -textvariable ::range \
        -values [list 250dps 500dps 2000dps] \
        -state readonly

    ttk::label $gyro.numDigitsLbl \
        -text {Digits before decimal}
    ttk::combobox $gyro.numDigitsCMB \
        -textvariable ::GryoValues(digits) \
        -values [list 3 4] \
        -state readonly
    ttk::label $gyro.numDecimalsLbl \
        -text {Digits after decimal}
    ttk::combobox $gyro.numDecimalsCMB \
        -textvariable ::GryoValues(decimals) \
        -values [list 1 2 3 4] \
        -state readonly
    ttk::label $gyro.minChangeLbl1 \
        -text {Ignore less than}
    ttk::spinbox $gyro.minChangeEnt \
        -from 0.1 \
        -to 200.0 \
        -increment 0.1 \
        -format {%5.1f} \
        -wrap no \
        -textvariable ::GryoValues(minChange)
    ttk::label $gyro.minChangeLbl2 \
        -text {dps change}


    # Add Self Test status
    # Add Calibration status
    # Add Unit Select
    # Add offsets
    # Add Gyro High Rate Interrupt Status
    # Add Gyro Any Motion Interrupt Status
    # Add Gyro Any Motion Threashold
................................................................................
proc CreateMagConfigFrame {mag} {
    ##
    ## Magnetometer group
    ##
    ttk::label $mag.rangeLbl \
        -text {Range:}
    ttk::combobox $mag.rangeCMB \
        -textvariable ::range \
        -values [list 250dps 500dps 2000dps] \
        -state readonly

    ttk::label $mag.numDigitsLbl \
        -text {Digits before decimal}
    ttk::combobox $mag.numDigitsCMB \
        -textvariable ::MagValues(digits) \
        -values [list 3 4] \
        -state readonly
    ttk::label $mag.numDecimalsLbl \
................................................................................
        -to 200.0 \
        -increment 0.1 \
        -format {%5.1f} \
        -wrap no \
        -textvariable ::MagValues(minChange)
    ttk::label $mag.minChangeLbl2 \
        -text {dps change}


    # Add Self Test status
    # Add Calibration status
    # Add Unit Select
    # Add offsets
    # Add radius
    # Add Mag Power Mode
    # Add Mag Operation Mode
................................................................................
        -command StopReading
    grid configure x $control.start x  $control.stop x  -sticky ew
    grid columnconfigure $control {0 2 4} -weight 1

}

proc CreateConfigurationFrame {w} {


    set general $w.gen
    set accel $w.acc
    set gyro $w.gyro
    set mag $w.mag
    set control $w.controls



    ttk::labelframe $general \

        -text "General"
    ttk::labelframe $accel \

        -text "Accelerometer"
    ttk::labelframe $gyro \

        -text "Gyrometer"
    ttk::labelframe $mag \

        -text "Magnetometer"
    ttk::frame $control
    grid configure $general -sticky nsew -pady 2 -padx 4 -ipady 4
    grid configure $accel -sticky nsew -pady 2 -padx 4 -ipady 4
    grid configure $gyro -sticky nsew -pady 2 -padx 4 -ipady 4


    grid configure $mag -sticky nsew -pady 2 -padx 4 -ipady 4
    grid configure $control -sticky nsew -pady 4
    grid columnconfigure $w $mag -weight 1
    grid rowconfigure $w 5 -weight 1

    CreateGeneralConfigFrame $general
    CreateAccelConfigFrame $accel
    CreateGyroConfigFrame $gyro
    CreateMagConfigFrame $mag
    CreateControlConfigFrame $control
        
................................................................................
        -textvariable ::CurrentValue($type,$z) \
        -state readonly
    grid configure $w.xLabel $w.xValue $w.yLabel $w.yValue $w.zLabel $w.zValue x -sticky ew -padx 2 -pady 1
    grid columnconfigure $w [list $w.xLabel $w.yLabel $w.zLabel] -uniform labels -weight 0
    grid columnconfigure $w [list $w.xValue $w.yValue $w.zValue] -uniform values -weight 0
}

proc LoadCurrentConfiguration {} {
    global UI
    global Configuration
    global CurrentValue
    
    foreach optionValue [$CurrentValue(handle) configure] {
        lassign $optionValue option default value
        ##
        ## Remove the leading -
        ##
        set index [string range $option 1 end]
        if {[info exists UI($index,map,label)]} {
            try {
                set value [dict get $UI($index,map,label) $value]
            } on error {errMsg errInfo} {
                puts "Error: $errMsg"
                puts "Error on $index for '$value'"
            }
        }
        set Configuration($index) $value
    }
}

##
## Main Body
##
set CurrentValue(handle) [dimu new]
LoadCurrentConfiguration

CreateGui
trace add variable Configuration write ConfigurationChange
trace add variable ::Configuration(operation) write ChangeMode













>
>
>
>
>
>
>

|




>







 







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







 







|

|





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








>
>
>

|






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






|


|
|


|







 







|







|





|



|







 







>
>
>
>
>
>
>
>







 







|
<
<
<
<







 







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


|


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







 







|

|






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













<












>
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>

|
<
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>












|


>







 







>
>







 







|


>



|





|










|


>
>







 







|


>







 







>
>







 







>
>
|
|
|
|


>
>
|
>

|
>

|
>

|
>


<
<
<
>
>
|
|
|
|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






>


|
>
>
>
>
>
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
..
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
...
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
...
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
...
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
...
358
359
360
361
362
363
364
365




366
367
368
369
370
371
372
...
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
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
...
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
...
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
...
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
...
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
...
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982



983
984
985
986
987
988
989
990
991
992
993
994
995
....
1177
1178
1179
1180
1181
1182
1183






















1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
array set MagValues {
    range 2000dps
    digits 5
    decimals 1
    minChange 0.1
    formatStr {%7.1}
}

array set GyroValues {
    digits 5
    decimals 1
    minChange 0.1
    formatStr {%7.1}
}

array set Configuration {
    bus 1
    dIMUaddress 0x28
}

array set UI {
    InLoadCurrentConfiguration false
    operation,map,label {
        configmode      "Configuration Mode"
        acconly         "Accelerometer Only"
        magonly         "Magnetometer Only"
        gyroonly        "Gyroscope Only"
        accmag          "Accelerometer and Magnetometer Only"
        accgyro         "Accelerometer and Gyroscope Only"
................................................................................
        ndof            "9 Degrees of Freedom -- Fast Magnetometer Calibration On"
    }
    power,map,label     {
        normal          "Normal"
        low             "Low"
        suspend         "Suspend"
    }

    gyrorange,map,label {
        2000dps         "2,000 dps"
        1000dps         "1,000 dps"
        500dps          "500 dps"
        250dps          "250 dps"
        125dps          "125 dps"
    }
    configurationWidgets {
    }
    clocksource,map,label {
        internal        "Internal"
        external        "External"
    }
    temperaturesource,map,label {
        acc     "Accelerometer"
        gyro    "Gyroscope"
    }
    temperatureunits,map,label {
        c   "C"
        f   "F"
    }
    fusionunits,map,label {
        windows   "Windows"
        android   "Android"
    }
    eulunits,map,label {
        deg   "Degrees"
        rad   "Radians"
    }
    remap_x_sign,map,label {
        pos   "Unchanged"
        neg   "Inverse"
    }
    remap_y_sign,map,label {
        pos   "Unchanged"
        neg   "Inverse"
    }
    remap_z_sign,map,label {
        pos   "Unchanged"
        neg   "Inverse"
    }
    remap_x_axis,map,label {
        x   "Unchanged"
        y   "To Y"
        z   "To Z"
    }
    remap_y_axis,map,label {
        x   "To X"
        y   "Unchanged"
        z   "To Z"
    }
    remap_z_axis,map,label {
        x   "To X"
        y   "To Y"
        z   "Unchanged"
    }
}

foreach key [array names UI "*,map,label"] {
    lassign [split $key ","] option
    set maxLabelSize -1
    foreach {symbol label} $UI($key) {
        dict set UI($option,map,symbol) $label $symbol
................................................................................
##
## Begin procedure definition section
##
proc ChangeOperationMode {varName index op} {
    global UI
    global Configuration

    set mode [dict get $UI(operation,map,symbol) $Configuration(operation)]

    if {$mode ne "Configuration Mode"} {
        DisableConfigurationWidgets
        EnableTabs $mode
    } else {
        EnableConfigurationWidgets
        DisableTabs
        LoadCurrentConfiguration
    }
}

proc ClockSourceMode {widget varName index op} {
    global Configuration
    global UI

    set mode [dict get $UI(operation,map,symbol) $Configuration(operation)]
    if {$mode eq "Configuration Mode" && $Configuration($index)} {
        $widget configure -state normal
    } else {
        $widget configure -state disabled
    }
}

proc ConfigurationChange {varName index op} {
    global UI
    global CurrentValue
    upvar #0 $varName configuration

    if {$UI(InLoadCurrentConfiguration)} {
        return
    }
    set value $configuration($index)
    if  {$index eq "refreshRate"} {
        return
    } elseif {[info exists UI($index,map,symbol)]} {
        set value [dict get $UI($index,map,symbol) $value]
    }
    $CurrentValue(handle) configure -$index $value
}

proc DisableConfigurationWidgets {} {
    global UI

    foreach widget $UI(configurationWidgets) {
        $widget configure -state disabled
    }
}

proc EnableConfigurationWidgets {} {
    global UI
    
    foreach widget $UI(configurationWidgets) {
        if {[winfo class $widget eq "TCombobox"]} {
             $widget configure -state readonly
        } else {
             $widget configure -state normal
        }

    }
}

proc ChangeFormat {varName index op} {
    upvar #0 $varName configuration

    set digits $configuration(digits)
    set decimals $configuration(decimals)
    incr digits 1
    incr digits $decimals
    set configuration(fmtStr) "%${digits}.${decimals}f"
}

proc DisableTabs {} {
    global UI

    set notebook $UI(mainNotebook)
    foreach {tab widget} [array get UI {main,*}] {
        $notebook tab $widget -state disabled
    }

    $notebook tab $UI(main,configuration) -state normal
    $notebook select $UI(main,configuration)
}

proc EnableTabs {mode} {
    global UI

    DisableTabs

    set notebook $UI(mainNotebook)
    switch -exact -- $mode {
        configmode -
................................................................................
        }
        imu -
        compass -
        m4g -
        ndof_fmc_off -
        ndof {
            foreach {tab widget} [array get UI {main,*}] {
                $notebook tab $widget -state normal
            }
        }
    }
}

proc ReadGyro {} {
    global CurrentValue
    global GyroValues

    ##
    ## Read the gyroscope
    ##
    set currentReadings [$CurrentValue(handle) readGyro]
    set formatStr $GyroValues(formatStr)
    set x [format $formatStr [dict get $currentReadings x]]
    set y [format $formatStr [dict get $currentReadings z]]
    set z [format $formatStr [dict get $currentReadings z]]
    set minChange $GyroValues(minChange
    if {abs($x - $CurrentValue(gyroscope,x)) > $minChange ||
        abs($y - $CurrentValue(gyroscope,y)) > $minChange ||
        abs($z - $CurrentValue(gyroscope,z)) > $minChange
    } {
        LogValues $x $y $z
        
        ##
................................................................................
        set CurrentValue(gyroscope,x) $x
        set CurrentValue(gyroscope,y) $y
        set CurrentValue(gyroscope,z) $z
    }

    return
}
proc ReadTemperature {} {
    set ::GeneralValues(temperature) [format {%5.1f} [dict get [$::CurrentValue(handle) readTemperature] temperature]]
    return
}

proc RunSelfTest {} {
    $::CurrentValue(handle) runSelfTest
}

proc LogValues {type} {
    variable WidgetData
    variable CurrentValue

    #if {[info exists CurrentValue(logId)]} {
    #    after cancel $CurrentValue(logId)
................................................................................
    set x $CurrentValue($type,x)
    set y $CurrentValue($type,y)
    set z $CurrentValue($type,z)
    $WidgetData($type,history) insert {} end -values [list $timeStamp $x $y $z]
}

proc StartReading {} {
    global CurrentValue





    .main.controls.buttons.start configure -state disabled
    .main.controls.buttons.stop configure -state normal
    StartGyro $CurrentValue(handle) $range
    ReadGyro

}
................................................................................
    if {[info exists CurrentValue(logId)]} {
        after cancel $CurrentValue(logId)
    }
    
    .main.controls.buttons.start configure -state normal 
    .main.controls.buttons.stop configure -state disabled
}
proc LoadCurrentConfiguration {} {
    global UI
    global Configuration
    global CurrentValue
    
    set UI(InLoadCurrentConfiguration) true
    foreach optionValue [$CurrentValue(handle) configure] {
        lassign $optionValue option default value
        ##
        ## Remove the leading -
        ##
        set index [string range $option 1 end]
        if {[info exists UI($index,map,label)]} {
            try {
                set value [dict get $UI($index,map,label) $value]
            } on error {errMsg errInfo} {
                puts "Error: $errMsg"
                puts "Error on $index for '$value'"
            }
        }
        set Configuration($index) $value
    }
    set UI(InLoadCurrentConfiguration) false
}

proc SaveConfigurationToFile {} {
    global Configuration

    set fn [tk_getSaveFile \
                -confirmoverwrite yes \
                -defaultextension .cfg \
                -initialdir [file normalize ~] \
                -parent . \
                -title "Save Configuration" \
    ]
    if {$fn ne {}} {
        set ofd [open $fn w]
        try {
            puts $ofd [array get Configuration]
        } finally {
            close $ofd
        }
    }
    
}

proc LoadConfigurationFromFile {} {
    global Configuration
    global UI

    set fn [tk_getOpenFile \
                -defaultextension .cfg \
                -initialdir [file normalize ~] \
                -multiple no \
                -parent . \
                -title "Restore Configuration" \
    ]

    set ifd [open $fn r]
    set tempDict [read $ifd]
    close $ifd

    ##
    ## Save desired operation mode
    ##
    set newMode [dict get $tempDict operation]
    
    ##
    ## Remove readonly options
    ##
    foreach option {bus dIMUaddress operation
                    uniqueID softwareRev bootloaderRev
                    mcuSelfTest gyroSelfTest magSelfTest accelSelfTest
                    sysCalStatus accCalStatus gyrCalStatus magCalStatus
                    sysStatus sysError clockStatus} {
        dict unset tempDict $option
    }
    
    ##
    ## Load the new configuration
    ##
    set Configuration(operation) "Configuration Mode"
    array set Configuration $tempDict
    set Configuration(operation) $newMode
    
}

proc ResetInterrupts {} {
    $::CurrentValue(handle) reset interrupts
}

proc ResetSystem {} {
    $::CurrentValue(handle) reset system
}


##
## GUI Creation Routines
##
proc RemoveClassBindings {widget} {
    bindtags $widget [lreplace [bindtags $widget] 1 1]
    return;
}
proc CreateGui {} {
    global UI

    wm title . "dIMU Gyroscope Example"

    menu .menuBar
    . configure -menu .menuBar
    menu .menuBar.configuration
    .menuBar add cascade \
        -menu .menuBar.configuration \
        -label "Configuration"
    .menuBar.configuration add command \
        -command SaveConfigurationToFile \
        -label "Save Configuration..."
    .menuBar.configuration add command \
        -command LoadConfigurationFromFile \
        -label "Restore Configuration..."
    .menuBar.configuration add separator
    .menuBar.configuration add command \
        -command LoadCurrentConfiguration \
        -label "Load from Device"

    set UI(mainNotebook) [ttk::notebook .main]
    grid configure .main -sticky nsew
    grid columnconfigure . .main -weight 1
    grid rowconfigure . .main -weight 1
    
    set UI(main,configuration) [ttk::frame .main.configuration]
    .main add .main.configuration -text {Configuration}
................................................................................
proc CreateGeneralConfigFrame {general} {
    ##
    ## General Configuration group
    ##
    ttk::label $general.busLbl \
        -text {I2C Bus:}
    ttk::combobox $general.busCMB \
        -textvariable ::Configuration(bus) \
        -values [list 1] \
        -state disabled
    ttk::label $general.addrLbl \
        -text {iDMU Address:}
    ttk::entry $general.addrEnt \
        -width 5 \
        -textvariable ::Configuration(dIMUaddress) \
        -state readonly
    ttk::label $general.uuidLbl \
        -text {Unique ID:}
    ttk::entry $general.uuidEnt \
        -textvariable ::Configuration(uniqueID) \
        -state readonly
    ttk::label $general.softwareRevLbl \
        -text {Software Rev.:}
    ttk::entry $general.softwareRevEnt \
        -textvariable ::Configuration(softwareRev) \
        -state readonly
    ttk::label $general.bootloaderRevLbl \
        -text {Bootloader Rev.:}
    ttk::entry $general.bootloaderRevEnt \
        -textvariable ::Configuration(bootloaderRev) \
        -state readonly
    ttk::label $general.rateLbl1 \
        -text {Refresh Rate:}
    ttk::spinbox $general.rateEnt \
        -from 50.0 \
        -to 500.0 \
        -increment 10.0 \
        -format {%3.0f} \
        -wrap no \
        -command [format {set ::Configuration(refreshRate) [expr {entier([%1$s get])}]}  $general.rateEnt]
    ttk::label $general.rateLbl2 \
        -text { in microseconds}
    ttk::label $general.operLbl1 \
        -text {Operational Mode}

    ttk::combobox $general.operCMB \
        -textvariable ::Configuration(operation) \
        -values [dict keys $::UI(operation,map,symbol)] \
        -width $::UI(operation,maxLabelSize) \
        -state readonly
    ttk::label $general.pwrLbl1 \
        -text {Power Mode}
    ttk::combobox $general.pwrCMB \
        -textvariable ::Configuration(power) \
        -values [dict keys $::UI(power,map,symbol)] \
        -width $::UI(power,maxLabelSize) \
        -state readonly
    lappend UI(configurationWidgets) $general.pwrCMB
    ttk::labelframe $general.selfTest \
        -text {Self Test Results}
    ttk::checkbutton $general.selfTest.mcuVal \
        -text {Microcontroler} \
        -variable ::Configuration(mcuSelfTest)
    ttk::checkbutton $general.selfTest.accVal \
        -text {Accelerometer} \
        -variable ::Configuration(accelSelfTest)
    ttk::checkbutton $general.selfTest.gyroVal \
        -text {Gyroscope} \
        -variable ::Configuration(gyroSelfTest)
    ttk::checkbutton $general.selfTest.magVal \
        -text {Magnetometer} \
        -variable ::Configuration(magSelfTest)
    foreach widget {mcuVal accVal gyroVal magVal} {
        RemoveClassBindings $general.selfTest.$widget
    }
    ttk::frame $general.selfTest.btn
    ttk::button $general.selfTest.btn.runSelfTest \
        -text {Run Self Tests} \
        -command RunSelfTest
    lappend UI(configurationWidgets) $general.selfTest.runSelfTest
    ttk::label $general.calibrationLbl \
        -text {Calibration Status:}
    ttk::entry $general.calibrationVal \
        -textvariable ::Configuration(sysCalStatus) \
        -state readonly
    ttk::label $general.sysStatusLbl \
        -text {System Status:}
    ttk::entry $general.sysStatusVal \
        -textvariable ::Configuration(sysStatus) \
        -state readonly
    ttk::label $general.sysErrorLbl \
        -text {System Error:}
    ttk::entry $general.sysErrorVal \
        -textvariable ::Configuration(sysError) \
        -state readonly
    ttk::checkbutton $general.clockStatusVal \
        -text {Clock Configurable} \
        -variable ::Configuration(clockStatus)
    RemoveClassBindings $general.clockStatusVal 
    ttk::label $general.clockSourceLbl \
        -text {Clock Source}
    ttk::combobox $general.clockSourceVal \
        -textvariable ::Configuration(clocksource) \
        -values [dict keys $::UI(clocksource,map,symbol)] \
        -width $::UI(clocksource,maxLabelSize) 
    trace add variable ::Configuration(clockStatus) write [list ClockSourceMode $general.clockSourceVal]
    after 1 [list ClockSourceMode $general.clockSourceVal Configuration clockStatus write]
    ttk::labelframe $general.temp \
        -text {Temperature}
    ttk::entry $general.temp.value \
        -justify right \
        -width 6 \
        -textvariable ::GeneralValues(temperature) \
        -state readonly
    bind $general.temp.value <Double-Button-1> ReadTemperature
    ttk::combobox $general.temp.unitsCMB \
        -textvariable :::Configuration(temperatureunits) \
        -values [dict keys $::UI(temperatureunits,map,symbol)] \
        -width $::UI(temperatureunits,maxLabelSize)
    ttk::label $general.temp.sourceLbl \
        -text {from}
    ttk::combobox $general.temp.sourceCMB \
        -textvariable :::Configuration(temperaturesource) \
        -values [dict keys $::UI(temperaturesource,map,symbol)] \
        -width $::UI(temperaturesource,maxLabelSize) 
    lappend UI(configurationWidgets)  $general.temp.unitsCMB  $general.temp.sourceCMB
    ttk::label $general.fusionLbl \
        -text {Fusion Unit Type:}
    ttk::combobox $general.fusionCMB \
        -textvariable :::Configuration(fusionunits) \
        -values [dict keys $::UI(fusionunits,map,symbol)] \
        -width $::UI(fusionunits,maxLabelSize) 
    ttk::label $general.eulUnitsLbl \
        -text {Fusion Unit Type:}
    ttk::combobox $general.eulUnitsCMB \
        -textvariable :::Configuration(eulunits) \
        -values [dict keys $::UI(eulunits,map,symbol)] \
        -width $::UI(eulunits,maxLabelSize)
    lappend UI(configurationWidgets) $general.fusionCMB $general.eulUnitsCMB
    ttk::frame $general.remap
    ttk::label $general.remap.xLbl -text {X} -anchor c
    ttk::label $general.remap.yLbl -text {Y} -anchor c
    ttk::label $general.remap.zLbl -text {Z} -anchor c
    ttk::label $general.remap.signLbl -text {Remap Sign}
    ttk::label $general.remap.axisLbl -text {Remap Axis}
    ttk::combobox $general.remap.xSignCMB \
        -textvariable :::Configuration(remap_x_sign) \
        -values [dict keys $::UI(remap_x_sign,map,symbol)] \
        -width $::UI(remap_x_sign,maxLabelSize)
    ttk::combobox $general.remap.ySignCMB \
        -textvariable :::Configuration(remap_y_sign) \
        -values [dict keys $::UI(remap_y_sign,map,symbol)] \
        -width $::UI(remap_y_sign,maxLabelSize)
    ttk::combobox $general.remap.zSignCMB \
        -textvariable :::Configuration(remap_x_sign) \
        -values [dict keys $::UI(remap_z_sign,map,symbol)] \
        -width $::UI(remap_z_sign,maxLabelSize)
    ttk::combobox $general.remap.xAxisCMB \
        -textvariable :::Configuration(remap_x_axis) \
        -values [dict keys $::UI(remap_x_axis,map,symbol)] \
        -width $::UI(remap_x_axis,maxLabelSize)
    ttk::combobox $general.remap.yAxisCMB \
        -textvariable :::Configuration(remap_y_axis) \
        -values [dict keys $::UI(remap_y_axis,map,symbol)] \
        -width $::UI(remap_y_axis,maxLabelSize)
    ttk::combobox $general.remap.zAxisCMB \
        -textvariable :::Configuration(remap_x_axis) \
        -values [dict keys $::UI(remap_z_axis,map,symbol)] \
        -width $::UI(remap_z_axis,maxLabelSize)
    lappend UI(configurationWidgets) $general.remap.xSignCMB $general.remap.ySignCMB $general.remap.zSignCMB
    lappend UI(configurationWidgets) $general.remap.xAxisCMB $general.remap.yAxisCMB $general.remap.zAxisCMB
    ttk::frame $general.buttons
    ttk::button $general.buttons.resetInterrupt \
        -text "Reset Interrupts" \
        -command ResetInterrupts
    ttk::button $general.buttons.resetSystem\
        -text "Reset System" \
        -command ResetSystem

    grid configure $general.busLbl $general.busCMB $general.addrLbl $general.addrEnt -padx 2 -pady 2 -sticky ew

    grid configure $general.uuidLbl $general.uuidEnt - - -padx 2 -pady 2 -sticky ew
    grid configure $general.softwareRevLbl $general.softwareRevEnt $general.bootloaderRevLbl $general.bootloaderRevEnt -padx 2 -pady 2 -sticky ew
    grid configure $general.sysStatusLbl $general.sysStatusVal $general.sysErrorLbl $general.sysErrorVal -padx 2 -pady 2 -sticky ew
    grid configure $general.calibrationLbl $general.calibrationVal x x -padx 2 -pady 2 -sticky ew
    grid configure $general.clockStatusVal - $general.clockSourceLbl $general.clockSourceVal -padx 2 -pady 2 -sticky ew
    grid configure $general.selfTest - - - -padx 2 -pady 2 -sticky ew
    grid configure $general.rateLbl1 $general.rateEnt $general.rateLbl2 x -padx 2 -pady 2 -sticky ew
    grid configure $general.operLbl1 $general.operCMB $general.pwrLbl1 $general.pwrCMB  -padx 2 -pady 2 -sticky ew

    grid configure $general.temp - - - -padx 2 -pady 2 -sticky ew
    grid configure $general.fusionLbl $general.fusionCMB $general.eulUnitsLbl $general.eulUnitsCMB -padx 2 -pady 2 -sticky ew
    grid configure $general.remap - - - -padx 2 -pady 2 -sticky ew
    grid configure $general.buttons - - - -padx 2 -pady 2 -sticky ew

    grid columnconfigure $general {1 3} -weight 1

    grid configure x $general.selfTest.mcuVal x $general.selfTest.accVal x $general.selfTest.gyroVal x $general.selfTest.magVal x -padx 2 -pady 2 -sticky ew
    grid configure $general.selfTest.btn -columnspan 9 -sticky nsew
    grid configure x $general.selfTest.btn.runSelfTest x -sticky ew
    grid columnconfigure $general.selfTest.btn {0 3} -weight 1
    grid columnconfigure $general.selfTest {0 2 4 6 8} -weight 1
    grid columnconfigure $general.selfTest {1 3 5 7} -uniform selftests
    
    grid configure $general.temp.value $general.temp.unitsCMB $general.temp.sourceLbl $general.temp.sourceCMB -padx 2 -pady 2
    
    grid configure x $general.remap.xLbl $general.remap.yLbl $general.remap.zLbl -padx 2 -pady 2 -sticky ew    
    grid configure $general.remap.signLbl $general.remap.xSignCMB $general.remap.ySignCMB $general.remap.zSignCMB -padx 2 -pady 2 -sticky ew     
    grid configure $general.remap.axisLbl $general.remap.xAxisCMB $general.remap.yAxisCMB $general.remap.zAxisCMB -padx 2 -pady 2 -sticky ew
    
    grid configure x $general.buttons.resetInterrupt x $general.buttons.resetSystem x -sticky ew
    grid columnconfigure $general.buttons {0 2 4} -weight 1
    grid columnconfigure $general.buttons {1 3} -uniform buttons

    $general.rateEnt set 50.0

}

proc CreateAccelConfigFrame {accel} {
    ##
    ## Accelerometer group
    ##
    ttk::label $accel.rangeLbl \
        -text {Range:}
    ttk::combobox $accel.rangeCMB \
        -textvariable ::Configuration(accelrange) \
        -values [list 250dps 500dps 2000dps] \
        -state readonly
    lappend UI(configurationWidgets) $accel.rangeCMB
    ttk::label $accel.numDigitsLbl \
        -text {Digits before decimal}
    ttk::combobox $accel.numDigitsCMB \
        -textvariable ::AccelValues(digits) \
        -values [list 3 4] \
        -state readonly
    ttk::label $accel.numDecimalsLbl \
................................................................................
        -to 200.0 \
        -increment 0.1 \
        -format {%5.1f} \
        -wrap no \
        -textvariable ::AccelValues(minChange)
    ttk::label $accel.minChangeLbl2 \
        -text {dps change}
    trace add variable ::AccelValues(digits) write ChangeFormat
    trace add variable ::AccelValues(decimals) write ChangeFormat
    # Add ACC units
    # Add Self Test status
    # Add Calibration status
    # Add Unit Select
    # Add offsets
    # Add radius
    # Add Acc No Motion Interrupt Status
................................................................................
proc CreateGyroConfigFrame {gyro} {
    ##
    ## Gyrometer
    ##
    ttk::label $gyro.rangeLbl \
        -text {Range:}
    ttk::combobox $gyro.rangeCMB \
        -textvariable ::Configuration(gyrorange) \
        -values [list 250dps 500dps 2000dps] \
        -state readonly
    lappend UI(configurationWidgets) $gyro.rangeCMB
    ttk::label $gyro.numDigitsLbl \
        -text {Digits before decimal}
    ttk::combobox $gyro.numDigitsCMB \
        -textvariable ::GyroValues(digits) \
        -values [list 3 4] \
        -state readonly
    ttk::label $gyro.numDecimalsLbl \
        -text {Digits after decimal}
    ttk::combobox $gyro.numDecimalsCMB \
        -textvariable ::GyroValues(decimals) \
        -values [list 1 2 3 4] \
        -state readonly
    ttk::label $gyro.minChangeLbl1 \
        -text {Ignore less than}
    ttk::spinbox $gyro.minChangeEnt \
        -from 0.1 \
        -to 200.0 \
        -increment 0.1 \
        -format {%5.1f} \
        -wrap no \
        -textvariable ::GyroValues(minChange)
    ttk::label $gyro.minChangeLbl2 \
        -text {dps change}
    trace add variable ::GyroValues(digits) write ChangeFormat
    trace add variable ::GyroValues(decimals) write ChangeFormat
    # Add Self Test status
    # Add Calibration status
    # Add Unit Select
    # Add offsets
    # Add Gyro High Rate Interrupt Status
    # Add Gyro Any Motion Interrupt Status
    # Add Gyro Any Motion Threashold
................................................................................
proc CreateMagConfigFrame {mag} {
    ##
    ## Magnetometer group
    ##
    ttk::label $mag.rangeLbl \
        -text {Range:}
    ttk::combobox $mag.rangeCMB \
        -textvariable ::Configuration(magrange) \
        -values [list 250dps 500dps 2000dps] \
        -state readonly
    lappend UI(configurationWidgets) $mag.rangeCMB
    ttk::label $mag.numDigitsLbl \
        -text {Digits before decimal}
    ttk::combobox $mag.numDigitsCMB \
        -textvariable ::MagValues(digits) \
        -values [list 3 4] \
        -state readonly
    ttk::label $mag.numDecimalsLbl \
................................................................................
        -to 200.0 \
        -increment 0.1 \
        -format {%5.1f} \
        -wrap no \
        -textvariable ::MagValues(minChange)
    ttk::label $mag.minChangeLbl2 \
        -text {dps change}
    trace add variable ::MagValues(digits) write ChangeFormat
    trace add variable ::MagValues(decimals) write ChangeFormat
    # Add Self Test status
    # Add Calibration status
    # Add Unit Select
    # Add offsets
    # Add radius
    # Add Mag Power Mode
    # Add Mag Operation Mode
................................................................................
        -command StopReading
    grid configure x $control.start x  $control.stop x  -sticky ew
    grid columnconfigure $control {0 2 4} -weight 1

}

proc CreateConfigurationFrame {w} {

    set nb $w.nb
    set general $w.nb.gen
    set accel $w.nb.acc
    set gyro $w.nb.gyro
    set mag $w.nb.mag
    set control $w.controls

    ttk::notebook $nb

    ttk::frame $general
    $nb add $general \
        -text "General"
    ttk::frame $accel
    $nb add $accel \
        -text "Accelerometer"
    ttk::frame $gyro
    $nb add $gyro \
        -text "Gyrometer"
    ttk::frame $mag
    $nb add $mag \
        -text "Magnetometer"
    ttk::frame $control





    grid configure $nb -sticky nsew -pady 2 -padx 4 -ipady 4
    grid configure $control -sticky ew -pady 4
    grid columnconfigure $w $nb -weight 1
    grid rowconfigure $w $nb -weight 1

    CreateGeneralConfigFrame $general
    CreateAccelConfigFrame $accel
    CreateGyroConfigFrame $gyro
    CreateMagConfigFrame $mag
    CreateControlConfigFrame $control
        
................................................................................
        -textvariable ::CurrentValue($type,$z) \
        -state readonly
    grid configure $w.xLabel $w.xValue $w.yLabel $w.yValue $w.zLabel $w.zValue x -sticky ew -padx 2 -pady 1
    grid columnconfigure $w [list $w.xLabel $w.yLabel $w.zLabel] -uniform labels -weight 0
    grid columnconfigure $w [list $w.xValue $w.yValue $w.zValue] -uniform values -weight 0
}
























##
## Main Body
##
set CurrentValue(handle) [dimu new]
LoadCurrentConfiguration
ReadTemperature
CreateGui
trace add variable Configuration write ConfigurationChange
trace add variable Configuration(operation) write ChangeOperationMode
ChangeOperationMode Configuration operation write

##
## Go into the event loop
##

Changes to src/bno055/bno055.tcl.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
...
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
...
223
224
225
226
227
228
229
230
231
232
233
234
235


236
237
238
239
240
241
242
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    ## 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}
................................................................................
        gyr,am,thresh   {1 0x1f b 6:0}
        gyr,am,slope    {1 0x1f b 1:0}
        gyr,am,durr     {1 0x1f 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 binaryValue [format %b $value]

        set Constants($type,$binaryValue) ${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 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 0b00
    SymDef ACC_RANGE 4G 0b01
    SymDef ACC_RANGE 8G 0b10
    SymDef ACC_RANGE 16G 0b11
    SymDef ACC_BANDWIDTH 7.81HZ 0b000
    SymDef ACC_BANDWIDTH 15.63HZ 0b001
    SymDef ACC_BANDWIDTH 31.25HZ 0b010
................................................................................
        set ucSymbol [string toupper $symbolic]
        return $Constants(CONST,$ucSymbol)
    }

    proc getValue2 {type symbol} {
        variable Constants

        set ucType [string toupper $type]
        return $Constants(CONST,${ucType}_${symbol})
    }

    proc getSymbol {type value} {
        variable Constants

        set binaryValue [format %b $value]
        set ucType [string toupper $type]







|
|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




>

|


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







 







|





>
>







 







|
|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
...
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
...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
    ## 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 6:0}
        gyro,chipId     {0 0x03 b 6:0}
        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}
................................................................................
        gyr,am,thresh   {1 0x1f b 6:0}
        gyr,am,slope    {1 0x1f b 1:0}
        gyr,am,durr     {1 0x1f b 3:2}
        
        uniqueId        {1 0x50 m 16}
    }

























    proc SymDef {type symbolic value} {
        variable Constants

        set binaryValue [format %b $value]
        set ucSymbol [string toupper ${type}_${symbolic}]
        set Constants($type,$binaryValue) ${type}_${symbolic}
        set Constants(CONST,$ucSymbol) $value
    }

    SymDef    CALIB_STAT    {Not Calibrated} 0
    SymDef    CALIB_STAT    {In progress} 1
    SymDef    CALIB_STAT    {In progress} 2
    SymDef    CALIB_STAT    {Calibration Complete} 3
    SymDef    SYS_STATUS    {System Idle} 0
    SymDef    SYS_STATUS    {System Error} 1
    SymDef    SYS_STATUS    {Initializing peripherals} 2
    SymDef    SYS_STATUS    {System Initialization} 3
    SymDef    SYS_STATUS    {Executing selftest} 4
    SymDef    SYS_STATUS    {Sensor fusion algorithm running} 5
    SymDef    SYS_STATUS    {System running without fusion algorithm} 6
    SymDef    SYS_ERROR     {No error} 0
    SymDef    SYS_ERROR     {Peripheral initialization error} 1
    SymDef    SYS_ERROR     {System initialization error} 2
    SymDef    SYS_ERROR     {Self test result failed} 3
    SymDef    SYS_ERROR     {Register map value out of range} 4
    SymDef    SYS_ERROR     {Register map address out of range} 5
    SymDef    SYS_ERROR     {Register map write error} 6
    SymDef    SYS_ERROR     {BNO low power mode not available for selected operation mode} 7
    SymDef    SYS_ERROR     {Accelerometer power mode not available} 8
    SymDef    SYS_ERROR     {Fusion algorithm configuration error} 9
    SymDef    SYS_ERROR     {Sensor configuration error} 10

    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 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 GYRO 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 CLOCK_SOURCE INTERNAL 0
    SymDef CLOCK_SOURCE EXTERNAL 1
    SymDef ACC_RANGE 2G 0b00
    SymDef ACC_RANGE 4G 0b01
    SymDef ACC_RANGE 8G 0b10
    SymDef ACC_RANGE 16G 0b11
    SymDef ACC_BANDWIDTH 7.81HZ 0b000
    SymDef ACC_BANDWIDTH 15.63HZ 0b001
    SymDef ACC_BANDWIDTH 31.25HZ 0b010
................................................................................
        set ucSymbol [string toupper $symbolic]
        return $Constants(CONST,$ucSymbol)
    }

    proc getValue2 {type symbol} {
        variable Constants

        set ucSymbol [string toupper ${type}_${symbol}]
        return $Constants(CONST,$ucSymbol)
    }

    proc getSymbol {type value} {
        variable Constants

        set binaryValue [format %b $value]
        set ucType [string toupper $type]

Changes to src/dimu/dimu.tcl.

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
...
139
140
141
142
143
144
145



146
147
148
149
150
151
152
...
200
201
202
203
204
205
206

207
208
209



210
211
212
213
214
215
216
...
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
...
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
...
369
370
371
372
373
374
375
376



377









378





































379
::ooutil::singleton create dimu {
    #self mixin singleton

	self method init {} {
		variable HardwiredSettings
		variable ConfigurationRegisters
		variable OptionDef


		set OptionDef {
            -bus        	{-default 1}
			-power          {-register powerMode -allowed {normal low suspend} -type PWR_MODE}
			-operation		{-register operMode -immediate yes -allowed {configmode acconly magonly gyroonly accmag accgyro maggyro amg imu compass m4g ndof_fmc_off ndof} -type OPER_MODE}
            -gryorange		{-register gyr,range -allowed {2000dps 1000dps 500dps 250dps 125dps} -type GRY_RANGE}
            -gryobandwidth	{-register gyr,bandwidth -allowed {523hz 230hz 116hz 64hz 47hz 32hz 23hz 12hz} -type GRY_BANDWIDTH}
            -gyropowermode	{-register gyr,pwrMode -allowed {normal fast_up deep_suspend suspend advanced_powersave} -type GRY_POWER_MODE}
			-gyrounits		{-register gyr,units -allowed {dps rps} -type GRY_UNIT}
			-gryoautosleep	{-register gyr,autoSlpDur -allowed {4MS 5MS 8MS 10MS 15MS 20MS 40MS} -type GRY_AUTOSLP_DURR}
			-gryosleep		{-register gyr,sleepDur -allowed {4MS 5MS 8MS 10MS 15MS 18MS 20MS} -type GRY_SLEEP_DURR}
			-gryoawake		{-register gyr,am,durr -allowed {8samples 16samples 32samples 64samples} -type GYR_AWAKE_DURR}
			-gryoslope		{-register gyr,am,slope}
			-gryoxoffset	{-register gyr,x,offset}
			-gryoyoffset	{-register gyr,y,offset}
			-gryozoffset	{-register gyr,z,offset}




























		}

		set HardwiredSettings {
			address 0x28
		}

        set ConfigurationRegisters {
................................................................................
        }

		::oo::objdefine [self] deletemethod init
		

	}




    method ProcessArgs {inputArgs classArgsDict} {
        variable instanceInfo

        set unprocessedArgs {}
        array set missingRequiredArr {}
        if {![info exists instanceInfo]} {
            set instanceInfo {}
................................................................................
    
    method ReadCurrentConfiguration {} {
		variable instanceInfo
        variable currentConfiguration
		classvariable ConfigurationRegisters
        
        set currentConfiguration [bno055 readMultipleRegisters [dict get $instanceInfo handle] $ConfigurationRegisters]

    }





    constructor {args} {
		variable instanceInfo
		classvariable OptionDef
        classvariable HardwiredSettings
        variable currentConfiguration

        set remainingArgs [my ProcessArgs $args $OptionDef]
................................................................................
		##
		## Close the handle to the device
		##
        close [dict get $instanceInfo handle]
    }





    method cget {option} {
        variable instanceInfo
		classvariable OptionDef

        variable currentConfiguration

        if {[dict exists $instanceInfo options $option]} {
            return [dict get $instanceInfo options $option]
        } elseif {[dict exists $instanceInfo legalOption $option]} {
			set optionDict [dict get $OptionDef $option]
			set register [dict get $optionDict -register]
			set value [dict get $currentConfiguration $register]
			if {[dict exists $optionDict -type]} {
				set type [dict get $optionDict -type]
				set value [string tolower [bno055 getShortSymbol $type $value]]
			}
			return $value
        } else {
            set legalOptions [dict keys [dict get $instanceInfo legalOption]]
            throw [list TK LOOKUP OPTION $option] "unknown option \"$option\" -- legal options are: [join $legalOptions {,}]"
        }












    }

    method configure {args} {
        variable instanceInfo
		classvariable OptionDef

        variable currentConfiguration

        set argLen [llength $args]
        if {$argLen == 0} {
			set returnList {}
			foreach option [lsort -dictionary [dict keys [dict get $instanceInfo legalOption]]] {
				##
................................................................................
				} else {
					set optionDict [dict get $OptionDef $option]
					set register [dict get $optionDict -register]
					set value [dict get $currentConfiguration $register]
					if {[dict exists $optionDict -type]} {
						set type [dict get $optionDict -type]
						set value [string tolower [bno055 getShortSymbol $type $value]]





					}
					set itemList [list $option {} $value]
				}















				lappend returnList $itemList
			}

            return $returnList
        } elseif {$argLen == 1} {
            set option [lindex $args 0]
            return [my cget $option]
        } elseif {($argLen % 2) == 0} {
			set configureList {}
			set immediateList {}
			foreach {option value} $args {
                if {[dict exists $instanceInfo options $option]} {
                    dict set instanceInfo options $option $value



				} elseif {[dict exists $OptionDef $option -register]} {
					if {![string is entier $value]} {
						set value [bno055 getValue2 [dict get $OptionDef $option -type] $value]
					}
					set register [dict get $OptionDef $option -register]
					dict set currentConfiguration $register $value
					if {[dict exists $OptionDef $option -immediate] && [dict get $OptionDef $option -immediate]} {
						lappend immediateList [list $register $value]
					} else {
						lappend configureList $register $value
					}
                } else {
                    set legalOptions [dict keys [dict get $instanceInfo options]]
                    throw [list LOOKUP OPTION $option] "unknown option \"$option\" -- legal options are: [join $legalOptions {,}]"
                }
            }
			set handle [dict get $instanceInfo handle]
			if {[llength $configureList]} {
				bno055 writeRegister $handle operMode [bno055 getValue2 OPER_MODE CONFIGMODE]
				foreach item $configureList {
					bno055 writeRegister $handle {*}$item
				}
				bno055 writeRegister $handle operMode [dict get $currentConfiguration operMode]
			}
			if {[llength $immediateList]} {
				foreach item $immediateList {
					bno055 writeRegister $handle {*}$item
				}
			}
        }
            
        return;

    }
	
	method readGyro {} {
        variable instanceInfo
        variable currentConfiguration
		
		set operMode [string range [bno055 getSymbol OPER_MODE [dict get $currentConfiguration operMode]] 9 end]
		if {$operMode in {CONFIGMODE ACCONLY MAGONLY COMPASS M4G}} {
			throw [list DIMU SENDIS $operMode] "Gryoscope reading are not availble when dIMU is in '$operMode' mode."
		}
		
		set results {}
		set readings [bno055 readMultipleRegisters [dict get $instanceInfo handle] {gyr,data,x gyr,data,y gyr,data,z}]
		set range [bno055 getSymbol GRY_RANGE [dict get $currentConfiguration gyr,range]]
		switch -exact -- $range {
			GRY_RANGE_125DPS {
................................................................................
			dict set results units rps
			set divisor [expr {$divsor * 900 / 16}]
		}
		dict set results x [expr {[dict get $readings gyr,data,x] / $divisor}]
		dict set results y [expr {[dict get $readings gyr,data,y] / $divisor}]
		dict set results z [expr {[dict get $readings gyr,data,z] / $divisor}]
	}




}















































dimu init







>





|
|


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







 







>
>
>







 







>



>
>
>







 







>
>
>



>








|
|
|
|
|
<



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





>







 







>
>
>
>
>



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

>








|
|
>
>
>







|




<
<





|
|




|
|







|




|

|







 








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

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
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
...
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
...
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
...
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
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
::ooutil::singleton create dimu {
    #self mixin singleton

	self method init {} {
		variable HardwiredSettings
		variable ConfigurationRegisters
		variable OptionDef
		variable ReadOnly

		set OptionDef {
            -bus        	{-default 1}
			-power          {-register powerMode -allowed {normal low suspend} -type PWR_MODE}
			-operation		{-register operMode -immediate yes -allowed {configmode acconly magonly gyroonly accmag accgyro maggyro amg imu compass m4g ndof_fmc_off ndof} -type OPER_MODE}
            -gyrorange		{-register gyr,range -allowed {2000dps 1000dps 500dps 250dps 125dps} -type GRY_RANGE}
            -gyrobandwidth	{-register gyr,bandwidth -allowed {523hz 230hz 116hz 64hz 47hz 32hz 23hz 12hz} -type GRY_BANDWIDTH}
            -gyropowermode	{-register gyr,pwrMode -allowed {normal fast_up deep_suspend suspend advanced_powersave} -type GRY_POWER_MODE}
			-gyrounits		{-register gyr,units -allowed {dps rps} -type GRY_UNIT}
			-gyroautosleep	{-register gyr,autoSlpDur -allowed {4MS 5MS 8MS 10MS 15MS 20MS 40MS} -type GRY_AUTOSLP_DURR}
			-gyrosleep		{-register gyr,sleepDur -allowed {4MS 5MS 8MS 10MS 15MS 18MS 20MS} -type GRY_SLEEP_DURR}
			-gyroawake		{-register gyr,am,durr -allowed {8samples 16samples 32samples 64samples} -type GYR_AWAKE_DURR}
			-gyroslope		{-register gyr,am,slope}
			-gyroxoffset	{-register gyr,x,offset}
			-gyroyoffset	{-register gyr,y,offset}
			-gyrozoffset	{-register gyr,z,offset}
			-clocksource	{-register clockSource -type CLOCK_SOURCE}
			-temperaturesource	{-register tempSource -type TEMP_SRC}
			-temperatureunits	{-register temp,units -type TEMP_UNIT}
			-fusionunits	{-register format,opt -type ORI_MODE}
			-eulunits		{-register eul,units -type EUL_UNIT}
			-remap_x_sign	{-register remap,x,sign -type REMAP_SIGN}
			-remap_y_sign	{-register remap,y,sign -type REMAP_SIGN}
			-remap_z_sign	{-register remap,z,sign -type REMAP_SIGN}
			-remap_x_axis	{-register remap,x,value -type REMAP_TO}
			-remap_y_axis	{-register remap,y,value -type REMAP_TO}
			-remap_z_axis	{-register remap,z,value -type REMAP_TO}
		}
		
		set ReadOnly		{
			-uniqueID		{-register uniqueId}
			-softwareRev	{-register sw,rev -format "0x%1$x"}
			-bootloaderRev	{-register bl,rev -format "0x%1$x"}
			-mcuSelfTest	{-register mcu,selftest}
			-gyroSelfTest	{-register gyr,selftest}
			-magSelfTest	{-register mag,selftest}
			-accelSelfTest	{-register acc,selftest}
			-sysCalStatus	{-register sys,cab,status -msg CALIB_STAT}
			-accCalStatus	{-register acc,cab,status -msg CALIB_STAT}
			-gyrCalStatus	{-register gyr,cab,status -msg CALIB_STAT}
			-magCalStatus	{-register mag,cab,status -msg CALIB_STAT}
			-sysStatus		{-register sys,status -msg SYS_STATUS}
			-sysError		{-register sys,error -msg SYS_ERROR}
			-clockStatus	{-register sys,clk,status}
		}

		set HardwiredSettings {
			address 0x28
		}

        set ConfigurationRegisters {
................................................................................
        }

		::oo::objdefine [self] deletemethod init
		

	}

	##
	## Private Methods
	##
    method ProcessArgs {inputArgs classArgsDict} {
        variable instanceInfo

        set unprocessedArgs {}
        array set missingRequiredArr {}
        if {![info exists instanceInfo]} {
            set instanceInfo {}
................................................................................
    
    method ReadCurrentConfiguration {} {
		variable instanceInfo
        variable currentConfiguration
		classvariable ConfigurationRegisters
        
        set currentConfiguration [bno055 readMultipleRegisters [dict get $instanceInfo handle] $ConfigurationRegisters]
		return $currentConfiguration
    }


	##
	## Special Methods
	##
    constructor {args} {
		variable instanceInfo
		classvariable OptionDef
        classvariable HardwiredSettings
        variable currentConfiguration

        set remainingArgs [my ProcessArgs $args $OptionDef]
................................................................................
		##
		## Close the handle to the device
		##
        close [dict get $instanceInfo handle]
    }


	##
	## Public Methods
	##
    method cget {option} {
        variable instanceInfo
		classvariable OptionDef
		classvariable ReadOnly
        variable currentConfiguration

        if {[dict exists $instanceInfo options $option]} {
            return [dict get $instanceInfo options $option]
        } elseif {[dict exists $instanceInfo legalOption $option]} {
			set optionDict [dict get $OptionDef $option]
			set register [dict get $optionDict -register]
			set value [dict get $currentConfiguration $register]
        } elseif {[dict exists $ReadOnly $option]} {
			set optionDict [dict get $ReadOnly $option]
			set register [dict get $optionDict -register]
			set value [bno055 readRegister [dict get $instanceInfo handle] $register]
		} else {

            set legalOptions [dict keys [dict get $instanceInfo legalOption]]
            throw [list TK LOOKUP OPTION $option] "unknown option \"$option\" -- legal options are: [join $legalOptions {,}]"
        }
		
		if {[dict exists $optionDict -type]} {
			set type [dict get $optionDict -type]
			set value [string tolower [bno055 getShortSymbol $type $value]]
		} elseif {[dict exists $optionDict -msg]} {
			set type [dict get $optionDict -msg]
			set value [string tolower [bno055 getSymbol $type $value]]
		} elseif {[dict exists $optionDict -format]} {
			set value [format [dict get $optionDict -format] $value]
		}
		
		return $value
    }

    method configure {args} {
        variable instanceInfo
		classvariable OptionDef
		classvariable ReadOnly
        variable currentConfiguration

        set argLen [llength $args]
        if {$argLen == 0} {
			set returnList {}
			foreach option [lsort -dictionary [dict keys [dict get $instanceInfo legalOption]]] {
				##
................................................................................
				} else {
					set optionDict [dict get $OptionDef $option]
					set register [dict get $optionDict -register]
					set value [dict get $currentConfiguration $register]
					if {[dict exists $optionDict -type]} {
						set type [dict get $optionDict -type]
						set value [string tolower [bno055 getShortSymbol $type $value]]
					} elseif {[dict exists $optionDict -msg]} {
						set type [dict get $optionDict -msg]
						set value [string tolower [bno055 getSymbol $type $value]]
					} elseif {[dict exists $optionDict -format]} {
						set value [format [dict get $optionDict -format] $value]
					}
					set itemList [list $option {} $value]
				}
				lappend returnList $itemList
			}
			foreach option [lsort -dictionary [dict keys $ReadOnly]] {
				set optionDict [dict get $ReadOnly $option]
				set register [dict get $optionDict -register]
				set value [bno055 readRegister [dict get $instanceInfo handle] $register]
				if {[dict exists $optionDict -type]} {
					set type [dict get $optionDict -type]
					set value [string tolower [bno055 getShortSymbol $type $value]]
				}  elseif {[dict exists $optionDict -msg]} {
					set type [dict get $optionDict -msg]
					set value [string tolower [bno055 getSymbol $type $value]]
				} elseif {[dict exists $optionDict -format]} {
					set value [format [dict get $optionDict -format] $value]
				}
				lappend returnList [list $option {} $value]
			}
			
            return $returnList
        } elseif {$argLen == 1} {
            set option [lindex $args 0]
            return [my cget $option]
        } elseif {($argLen % 2) == 0} {
			set configureList {}
			set immediateList {}
			foreach {option value} $args {
                if {![dict exists $OptionDef $option] || $option eq "-bus"} {
                    set legalOptions [dict keys $OptionDef]
					set index [lsearch -exact $legalOptions "-bus"]
					set legalOptions [lreplace $legalOptions $index $index]
                    throw [list LOOKUP OPTION $option] "unknown option \"$option\" -- legal options are: [join $legalOptions {,}]"
				} elseif {[dict exists $OptionDef $option -register]} {
					if {![string is entier $value]} {
						set value [bno055 getValue2 [dict get $OptionDef $option -type] $value]
					}
					set register [dict get $OptionDef $option -register]
					dict set currentConfiguration $register $value
					if {[dict exists $OptionDef $option -immediate] && [dict get $OptionDef $option -immediate]} {
						lappend immediateList $register $value
					} else {
						lappend configureList $register $value
					}
                } else {


                }
            }
			set handle [dict get $instanceInfo handle]
			if {[llength $configureList]} {
				bno055 writeRegister $handle operMode [bno055 getValue2 OPER_MODE CONFIGMODE]
				foreach {register value} $configureList {
					bno055 writeRegister $handle $register $value
				}
				bno055 writeRegister $handle operMode [dict get $currentConfiguration operMode]
			}
			if {[llength $immediateList]} {
				foreach {register value} $immediateList {
					bno055 writeRegister $handle $register $value
				}
			}
        }
            
        return;

    }

	method readGyro {} {
        variable instanceInfo
        variable currentConfiguration
		
		set operMode [bno055 getShortSymbol OPER_MODE [dict get $currentConfiguration operMode]]
		if {$operMode in {CONFIGMODE ACCONLY MAGONLY COMPASS M4G}} {
			throw [list DIMU SENDIS $operMode] "Gyroscope reading are not availble when dIMU is in '$operMode' mode."
		}
		
		set results {}
		set readings [bno055 readMultipleRegisters [dict get $instanceInfo handle] {gyr,data,x gyr,data,y gyr,data,z}]
		set range [bno055 getSymbol GRY_RANGE [dict get $currentConfiguration gyr,range]]
		switch -exact -- $range {
			GRY_RANGE_125DPS {
................................................................................
			dict set results units rps
			set divisor [expr {$divsor * 900 / 16}]
		}
		dict set results x [expr {[dict get $readings gyr,data,x] / $divisor}]
		dict set results y [expr {[dict get $readings gyr,data,y] / $divisor}]
		dict set results z [expr {[dict get $readings gyr,data,z] / $divisor}]
	}

	method readTemperature {} {
        variable instanceInfo
        variable currentConfiguration

		set results {}
		set readings [bno055 readRegister [dict get $instanceInfo handle] temp,data]
		set units [bno055 getSymbol GRY_UNIT [dict get $currentConfiguration temp,units]]
		if {$units in {C c}} {
			dict set results units C
			set divisor 1.0
		} else {
			dict set results units V
			set divisor 2.0
		}
		dict set results temperature [expr {$readings / $divisor}]
	}
	
	method reset {what} {
        variable instanceInfo

		set handle [dict get $instanceInfo handle]

		switch -exact $what {
			interrupts {
				bno055 writeRegister $handle resetInt 1
			}
			system {
				bno055 writeRegister $handle systemReset 1
			}
			default {
				throw [list  DMIU UNKACT $what] "unkown action '$what', must be either intterupts or system."
			}
		}

	}

	method runSelfTest {} {
        variable instanceInfo
        variable currentConfiguration

		set operMode [bno055 getShortSymbol OPER_MODE [dict get $currentConfiguration operMode]]
		if {$operMode ni {CONFIGMODE}} {
			throw [list DIMU SENDIS $operMode] "Running Self Test is not availble when dIMU is in '$operMode' mode."
		}
		bno055 writeRegister [dict get $instanceInfo handle] runSelfTest 1

		return
	}

}

dimu init