forked from loboris/mecrisp-stellaris
-
Notifications
You must be signed in to change notification settings - Fork 1
/
imu.txt
425 lines (331 loc) · 11.5 KB
/
imu.txt
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
\ Intertial sensing with accelerometer, magnetometer and gyroscope
\ needs basisdefinitions.txt
\ --------------------------------------------------------------
\ Connections of Inertial Sensors to Pins of STM32F3 Discovery
\ --------------------------------------------------------------
\
\ PA5: Gyro SCL/SPC PA5 with AF05: SPI1_SCK
\ PA6: Gyro SAO/SDO PA6 with AF05: SPI1_MISO
\ PA7: Gyro SDA/SDI/SDO PA7 with AF05: SPI1_MOSI
\
\ PB6: Mag SCL
\ PB7: Mag SDA
\
\ PE0: Gyro INT1
\ PE1: Gyro DRDY/INT2
\ PE2: Mag DRDY
\ PE3: Gyro CS_I2C/SPI
\ PE4: Mag INT1
\ PE5: Mag INT2
\ -----------------------------
\ Bit-Bang SPI Implementation
\ -----------------------------
1 3 lshift constant gyro-select
: gyro-sel ( -- ) gyro-select 16 lshift porte_bsrr ! ; \ Assuming positive logic
: gyro-unsel ( -- ) gyro-select porte_bsrr ! ;
\ Primitives for SPI bit-banging
1 5 lshift constant spi-sck
1 6 lshift constant spi-miso
1 7 lshift constant spi-mosi
: sck-high ( -- ) spi-sck porta_bsrr ! ;
: sck-low ( -- ) spi-sck 16 lshift porta_bsrr ! ;
: mosi-high ( -- ) spi-mosi porta_bsrr ! ;
: mosi-low ( -- ) spi-mosi 16 lshift porta_bsrr ! ;
: miso ( -- ? ) spi-miso porta_idr bit@ ;
: spi-init ( -- )
\ Select pins as outputs and deselect
3 2* lshift porte_moder bis! \ Set select pin as output
gyro-unsel
\ Do line initialisation for SPI bit-banging
5 2* lshift \ Set SCK pin as output
\ MISO is input after Reset
7 2* lshift or porta_moder bis! \ Set MOSI pin as output
sck-high
\ Finished.
;
: bit-spix ( ? -- ? )
if mosi-high else mosi-low then
sck-low
sck-high
miso
;
: spix ( x -- x ) $FF and
dup 128 and bit-spix if 128 or else 128 bic then
dup 64 and bit-spix if 64 or else 64 bic then
dup 32 and bit-spix if 32 or else 32 bic then
dup 16 and bit-spix if 16 or else 16 bic then
dup 8 and bit-spix if 8 or else 8 bic then
dup 4 and bit-spix if 4 or else 4 bic then
dup 2 and bit-spix if 2 or else 2 bic then
dup 1 and bit-spix if 1 or else 1 bic then
;
: >spi ( x -- ) spix drop ;
: spi> ( -- x ) 0 spix ;
\ -----------------------------
\ Bit-Bang I2C Implementation
\ -----------------------------
\ Low-level target specific pin configurations
1 6 lshift constant i2c-scl
1 7 lshift constant i2c-sda
: scl-high ( -- ) i2c-scl portb_bsrr ! ;
: scl-low ( -- ) i2c-scl 16 lshift portb_bsrr ! ;
: sda-high ( -- ) i2c-sda portb_bsrr ! ;
: sda-low ( -- ) i2c-sda 16 lshift portb_bsrr ! ;
: scl-@ ( -- f ) 20 0 do loop i2c-scl portb_idr bit@ ;
: sda-@ ( -- f ) 20 0 do loop i2c-sda portb_idr bit@ ;
: I2C-Init ( -- )
6 2* lshift
7 2* lshift or portb_moder bis! \ Set both I2C lines as outputs
i2c-scl i2c-sda or portb_otyper bis! \ Open Drain mode
scl-high sda-high \ Bus free default state. During communication, SCL is low for default.
;
\ Low-Level I2C-Protocol
: I2C-Start ( -- ) sda-high scl-high sda-low scl-low ;
: I2C-Stop ( -- ) sda-low scl-high sda-high ;
: I2C-Bit-TX ( f -- )
if sda-high else sda-low then
scl-high begin scl-@ until
scl-low
;
: I2C-Bit-RX ( -- f )
sda-high
scl-high begin scl-@ until
sda-@
scl-low
;
\ Higher level I2C-Protocol
: I2C-TX ( b -- f )
dup $80 and I2C-Bit-TX
dup $40 and I2C-Bit-TX
dup $20 and I2C-Bit-TX
dup $10 and I2C-Bit-TX
dup $08 and I2C-Bit-TX
dup $04 and I2C-Bit-TX
dup $02 and I2C-Bit-TX
$01 and I2C-Bit-TX
I2C-Bit-RX 0=
;
: I2C-RX ( f -- b )
I2C-Bit-RX $80 and
I2C-Bit-RX $40 and or
I2C-Bit-RX $20 and or
I2C-Bit-RX $10 and or
I2C-Bit-RX $08 and or
I2C-Bit-RX $04 and or
I2C-Bit-RX $02 and or
I2C-Bit-RX $01 and or
swap 0= I2C-Bit-TX
;
\ I2C device detection
: u.2 s>d <# # # #> type ;
: i2c-ping? ( addr - f ) i2c-start shl i2c-tx i2c-stop ;
: i2c-7bitaddr? ( addr -- f ) dup $7 u>= swap $77 u<= and ;
: i2c-detect ( -- )
i2c-init cr
base @ hex
4 spaces $10 0 do i space u.2 loop
$80 0 do
i $0f and 0= if
cr i u.2 [char] : emit space
then
i i2c-7bitaddr? if
i i2c-ping? if \ does device respond?
i space u.2
else
." --"
then
else
." "
then
loop
cr base !
;
\ I2C Register primitives
: i2c-reg! ( data register address -- )
i2c-start
shl i2c-tx not if ." I2C device not connected." cr quit then \ Transmit address
i2c-tx drop \ Transmit register
i2c-tx drop \ Transmit data
i2c-stop
;
: i2c-first-reg@ ( register address -- data )
shl tuck ( address register address )
i2c-start
i2c-tx not if ." I2C device not connected." cr quit then \ Transmit address
i2c-tx drop \ Transmit register
i2c-start
1 or \ Set Read bit in address
i2c-tx drop
true i2c-rx
;
: i2c-next-reg@ ( -- data ) true i2c-rx ;
: i2c-last-reg@ ( -- data ) false i2c-rx i2c-stop ;
: i2c-reg@ ( register address -- data )
shl tuck ( address register address )
i2c-start
i2c-tx not if ." I2C device not connected." cr quit then \ Transmit address
i2c-tx drop \ Transmit register
i2c-start
1 or \ Set Read bit in address
i2c-tx drop
false i2c-rx
i2c-stop
;
\ ------------------------
\ Magnetometer Interface
\ ------------------------
: sign16 ( s16 -- n ) [ $b236 h, ] inline ; \ sxth r6, r6 Opcode
$19 constant i2c-addr-accel
$1E constant i2c-addr-mag
: mag-init ( -- )
i2c-init
$00 $02 i2c-addr-mag i2c-reg! \ Enable the magnetometer
$1C $00 i2c-addr-mag i2c-reg! \ Set 220 Hz rate
$20 $01 i2c-addr-mag i2c-reg! \ Set gain to known level
;
: mag-xyz ( -- x y z )
$03 i2c-addr-mag i2c-first-reg@ 8 lshift
i2c-next-reg@ or sign16
i2c-next-reg@ 8 lshift
i2c-next-reg@ or sign16
i2c-next-reg@ 8 lshift
i2c-last-reg@ or sign16
;
\ -------------------------
\ Accelerometer Interface
\ -------------------------
: accel-init ( -- )
i2c-init
$67 $20 i2c-addr-accel i2c-reg! \ Enable the accelerometer, 200 Hz rate
;
: accel-xyz ( -- x y z )
$28 i2c-addr-accel i2c-reg@
$29 i2c-addr-accel i2c-reg@ 8 lshift or sign16
$2A i2c-addr-accel i2c-reg@
$2B i2c-addr-accel i2c-reg@ 8 lshift or sign16
$2C i2c-addr-accel i2c-reg@
$2D i2c-addr-accel i2c-reg@ 8 lshift or sign16
;
\ ---------------------
\ Gyroscope interface
\ ---------------------
: gyro! ( c addr -- ) gyro-sel >spi >spi gyro-unsel ;
: gyro@ ( addr -- c ) gyro-sel $80 or >spi spi> gyro-unsel ;
: gyro-init ( -- )
spi-init
$0F gyro@ $D4 = if ." Gyro connected." else ." Gyro not ready." quit then
\ Set CTRL_REG1 (0x20)
\ ====================================================================
\ BIT Symbol Description Default
\ --- ------ --------------------------------------------- -------
\ 7-6 DR1/0 Output data rate 00
\ 5-4 BW1/0 Bandwidth selection 00
\ 3 PD 0 = Power-down mode, 1 = normal/sleep mode 0
\ 2 ZEN Z-axis enable (0 = disabled, 1 = enabled) 1
\ 1 YEN Y-axis enable (0 = disabled, 1 = enabled) 1
\ 0 XEN X-axis enable (0 = disabled, 1 = enabled) 1
$0F $20 gyro! \ Switch to normal mode and enable all three channels
\ Set CTRL_REG2 (0x21)
\ ====================================================================
\ BIT Symbol Description Default
\ --- ------ --------------------------------------------- -------
\ 5-4 HPM1/0 High-pass filter mode selection 00
\ 3-0 HPCF3..0 High-pass filter cutoff frequency selection 0000
\ Nothing to do ... keep default values
\ Set CTRL_REG3 (0x22)
\ ====================================================================
\ BIT Symbol Description Default
\ --- ------ --------------------------------------------- -------
\ 7 I1_Int1 Interrupt enable on INT1 (0=disable,1=enable) 0
\ 6 I1_Boot Boot status on INT1 (0=disable,1=enable) 0
\ 5 H-Lactive Interrupt active config on INT1 (0=high,1=low) 0
\ 4 PP_OD Push-Pull/Open-Drain (0=PP, 1=OD) 0
\ 3 I2_DRDY Data ready on DRDY/INT2 (0=disable,1=enable) 0
\ 2 I2_WTM FIFO wtrmrk int on DRDY/INT2 (0=dsbl,1=enbl) 0
\ 1 I2_ORun FIFO overrun int on DRDY/INT2 (0=dsbl,1=enbl) 0
\ 0 I2_Empty FIFI empty int on DRDY/INT2 (0=dsbl,1=enbl) 0
\ Nothing to do ... keep default values
\ Set CTRL_REG4 (0x23)
\ ====================================================================
\ BIT Symbol Description Default
\ --- ------ --------------------------------------------- -------
\ 7 BDU Block Data Update (0=continuous, 1=LSB/MSB) 0
\ 6 BLE Big/Little-Endian (0=Data LSB, 1=Data MSB) 0
\ 5-4 FS1/0 Full scale selection 00
\ 00 = 250 dps
\ 01 = 500 dps
\ 10 = 2000 dps
\ 11 = 2000 dps
\ 0 SIM SPI Mode (0=4-wire, 1=3-wire) 0
\ Adjust resolution if requested
0 $23 gyro!
\ Set CTRL_REG5 (0x24)
\ ====================================================================
\ BIT Symbol Description Default
\ --- ------ --------------------------------------------- -------
\ 7 BOOT Reboot memory content (0=normal, 1=reboot) 0
\ 6 FIFO_EN FIFO enable (0=FIFO disable, 1=enable) 0
\ 4 HPen High-pass filter enable (0=disable,1=enable) 0
\ 3-2 INT1_SEL INT1 Selection config 00
\ 1-0 OUT_SEL Out selection config 00
\ Nothing to do ... keep default values
;
: gyro-xyz ( -- x y z )
gyro-sel
$28 $40 or $80 or >spi \ X-Low Register, Address Autoincrement, Read
spi> \ X-Low
spi> 8 lshift or \ X-High
sign16
spi> \ Y-Low
spi> 8 lshift or \ Y-High
sign16
spi> \ Z-Low
spi> 8 lshift or \ Z-High
sign16
gyro-unsel
;
\ -------------------------------------
\ Demos to try out individual sensors
\ -------------------------------------
: mag-demo ( -- )
mag-init
begin
mag-xyz ." z: " . ." y: " . ." x: " . cr
key? until
;
: accel-demo ( -- )
accel-init
begin
accel-xyz ." z: " . ." y: " . ." x: " . cr
key? until
;
: gyro-demo ( -- )
gyro-init
begin
gyro-xyz ." z: " . ." y: " . ." x: " . cr
key? until
;
: ledangle ( u -- ) \ Let it shine, 0 through 7
$FF00 16 lshift PORTE_BSRR !
1 swap 8 lshift PORTE_BSRR !
;
: compass ( -- )
$55550000 PORTE_MODER ! \ Outputs PE8-PE15
mag-init
begin
mag-xyz nip ( x z ) \ Forget y, as this is the axis outside of the LEDs plane.
\ Determine which LED should glow:
dup 0< if abs
over 0< if swap abs swap
>= if 1 else 0 then ( z-, x- )
else >= if 6 else 7 then ( z-, x )
then
else
over 0< if swap abs swap
>= if 2 else 3 then ( z , x- )
else >= if 5 else 4 then ( z , x )
then
then
ledangle
key? until
;