amiro-os / components / gyro / l3g4200d.cpp @ 6ad5c364
History | View | Annotate | Download (5.154 KB)
1 |
#include <ch.hpp> |
---|---|
2 |
#include <hal.h> |
3 |
#include <chprintf.h> |
4 |
#include <string.h> |
5 |
|
6 |
#include <amiro/util/util.h> |
7 |
#include <amiro/bus/spi/HWSPIDriver.hpp> |
8 |
#include <amiro/gyro/l3g4200d.hpp> |
9 |
#include <amiro/Constants.h> |
10 |
#include <global.hpp> |
11 |
|
12 |
using namespace chibios_rt; |
13 |
|
14 |
extern Global global;
|
15 |
|
16 |
namespace amiro {
|
17 |
|
18 |
L3G4200D::L3G4200D(HWSPIDriver *driver) |
19 |
: driver(driver), |
20 |
udpsPerTic(175000),
|
21 |
period_us(100000) {
|
22 |
this->period_ms = this->period_us * 1e-3; |
23 |
this->period_st = US2ST(this->period_us); |
24 |
} |
25 |
|
26 |
L3G4200D::~L3G4200D() { |
27 |
|
28 |
} |
29 |
|
30 |
chibios_rt::EvtSource* |
31 |
L3G4200D::getEventSource() { |
32 |
return &this->eventSource; |
33 |
} |
34 |
|
35 |
msg_t L3G4200D::main() { |
36 |
systime_t time = System::getTime(); |
37 |
this->setName("l3g4200d"); |
38 |
|
39 |
while (!this->shouldTerminate()) { |
40 |
time += this->period_st;
|
41 |
|
42 |
updateSensorData(); |
43 |
calcAngular(); |
44 |
|
45 |
this->eventSource.broadcastFlags(1); |
46 |
|
47 |
if (time >= System::getTime()) {
|
48 |
chThdSleepUntil(time); |
49 |
} else {
|
50 |
chprintf((BaseSequentialStream*) &global.sercanmux1, "WARNING l3g4200d: Unable to keep track\r\n");
|
51 |
} |
52 |
} |
53 |
return RDY_OK;
|
54 |
} |
55 |
|
56 |
int16_t |
57 |
L3G4200D:: |
58 |
getAngularRate(const uint8_t axis) {
|
59 |
return this->angularRate[axis]; |
60 |
} |
61 |
|
62 |
int32_t |
63 |
L3G4200D:: |
64 |
getAngularRate_udps(const uint8_t axis) {
|
65 |
return int32_t(this->angularRate[axis]) * this->udpsPerTic; |
66 |
} |
67 |
|
68 |
int32_t |
69 |
L3G4200D:: |
70 |
getAngular(const uint8_t axis) {
|
71 |
return this->angular[axis]; |
72 |
} |
73 |
|
74 |
int32_t |
75 |
L3G4200D:: |
76 |
getAngular_ud(const uint8_t axis) {
|
77 |
const int32_t angularRate_mdps = this->getAngularRate_udps(axis) * 1e-3; |
78 |
return angularRate_mdps * (this->integrationTic * this->period_ms); |
79 |
} |
80 |
|
81 |
void
|
82 |
L3G4200D:: |
83 |
calcAngular() { |
84 |
// Need to check for overflow!
|
85 |
++this->integrationTic;
|
86 |
chSysLock(); |
87 |
this->angular[L3G4200D::AXIS_X] += int32_t(this->angularRate[L3G4200D::AXIS_X]); |
88 |
this->angular[L3G4200D::AXIS_Y] += int32_t(this->angularRate[L3G4200D::AXIS_Y]); |
89 |
this->angular[L3G4200D::AXIS_Z] += int32_t(this->angularRate[L3G4200D::AXIS_Z]); |
90 |
chSysUnlock(); |
91 |
} |
92 |
|
93 |
// TODO: Outsource, so that everyone who needs this has an own instance of the integrator
|
94 |
void
|
95 |
L3G4200D:: |
96 |
angularReset() { |
97 |
this->angular[L3G4200D::AXIS_X] = 0; |
98 |
this->angular[L3G4200D::AXIS_Y] = 0; |
99 |
this->angular[L3G4200D::AXIS_Z] = 0; |
100 |
this->integrationTic = 0; |
101 |
} |
102 |
|
103 |
|
104 |
void L3G4200D::updateSensorData() {
|
105 |
|
106 |
const size_t buffer_size = offsetof(L3G4200D::registers, OUT_Z)
|
107 |
- offsetof(L3G4200D::registers, STATUS_REG) |
108 |
+ MEMBER_SIZE(L3G4200D::registers, OUT_Z) |
109 |
+ 1; /* addressing */ |
110 |
uint8_t buffer[buffer_size]; |
111 |
uint8_t sreg; |
112 |
|
113 |
/*Address of first data register*/
|
114 |
memset(buffer, 0xFF, sizeof(buffer)); |
115 |
buffer[0] = offsetof(L3G4200D::registers, STATUS_REG) | L3G4200D::SPI_READ | L3G4200D::SPI_MULT;
|
116 |
|
117 |
this->driver->exchange(buffer, buffer, buffer_size);
|
118 |
|
119 |
// assemble data
|
120 |
sreg = buffer[1];
|
121 |
|
122 |
chSysLock(); |
123 |
if (sreg & L3G4200D::XDA)
|
124 |
this->angularRate[L3G4200D::AXIS_X] = (buffer[3] << 8) + buffer[2]; |
125 |
|
126 |
if (sreg & L3G4200D::YDA)
|
127 |
this->angularRate[L3G4200D::AXIS_Y] = (buffer[5] << 8) + buffer[4]; |
128 |
|
129 |
if (sreg & L3G4200D::ZDA)
|
130 |
this->angularRate[L3G4200D::AXIS_Z] = (buffer[7] << 8) + buffer[6]; |
131 |
chSysUnlock(); |
132 |
} |
133 |
|
134 |
msg_t L3G4200D::configure(const L3G4200DConfig *config) {
|
135 |
|
136 |
const size_t ctrl_reg_size = offsetof(L3G4200D::registers, CTRL_REG5)
|
137 |
- offsetof(L3G4200D::registers, CTRL_REG1) |
138 |
+ MEMBER_SIZE(L3G4200D::registers, CTRL_REG5) |
139 |
+ 1; /* addressing */ |
140 |
|
141 |
const size_t buffer_size = ctrl_reg_size;
|
142 |
|
143 |
uint8_t buffer[buffer_size]; |
144 |
|
145 |
// write control config
|
146 |
// this might be three-wire so we need to send ones
|
147 |
memset(buffer, 0xFFu, buffer_size);
|
148 |
buffer[0] = offsetof(L3G4200D::registers, CTRL_REG1) | L3G4200D::SPI_MULT | L3G4200D::SPI_WRITE;
|
149 |
buffer[1] = config->ctrl1;
|
150 |
buffer[2] = config->ctrl2;
|
151 |
buffer[3] = config->ctrl3;
|
152 |
buffer[4] = config->ctrl4;
|
153 |
buffer[5] = config->ctrl5;
|
154 |
this->driver->write(buffer, 6); |
155 |
|
156 |
// Handle the new update time
|
157 |
switch(config->ctrl1 & L3G4200D::DR_MASK) {
|
158 |
case L3G4200D::DR_100_HZ: this->period_us = 10000; break; |
159 |
case L3G4200D::DR_200_HZ: this->period_us = 5000; break; |
160 |
case L3G4200D::DR_400_HZ: this->period_us = 2500; break; |
161 |
case L3G4200D::DR_800_HZ: this->period_us = 1250; break; |
162 |
} |
163 |
this->period_st = US2ST(this->period_us); |
164 |
this->period_ms = this->period_us * 1e-3; |
165 |
|
166 |
// Handle the new full scale
|
167 |
switch(config->ctrl1 & L3G4200D::FS_MASK) {
|
168 |
case L3G4200D::FS_250_DPS: this->udpsPerTic = 8750; break; |
169 |
case L3G4200D::FS_500_DPS: this->udpsPerTic = 17500; break; |
170 |
case L3G4200D::FS_2000_DPS: this->udpsPerTic = 70000; break; |
171 |
} |
172 |
|
173 |
// Reset the integration
|
174 |
this->angularReset();
|
175 |
|
176 |
return RDY_OK;
|
177 |
|
178 |
} |
179 |
|
180 |
uint8_t L3G4200D::getCheck() { |
181 |
|
182 |
const size_t buffer_size = 1 /* addressing */ |
183 |
+ 1; /* who am i */ |
184 |
uint8_t buffer[buffer_size]; |
185 |
|
186 |
// Exchange the data with the L3G4200D gyroscope
|
187 |
// Specify the adress and the mode
|
188 |
buffer[0] = offsetof(L3G4200D::registers, WHO_AM_I) | L3G4200D::SPI_READ;
|
189 |
this->driver->exchange(buffer, buffer, buffer_size);
|
190 |
// Check
|
191 |
if (buffer[1] == L3G4200D::L3G4200D_ID) { |
192 |
return L3G4200D::CHECK_OK;
|
193 |
} else {
|
194 |
return L3G4200D::CHECK_FAIL;
|
195 |
} |
196 |
|
197 |
} |
198 |
|
199 |
} /* amiro */
|