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