amiro-os / components / gyro / l3g4200d.cpp @ d314ad6f
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 */
|