Statistics
| Branch: | Tag: | Revision:

amiro-os / components / gyro / l3g4200d.cpp @ b8b3a9c9

History | View | Annotate | Download (5.154 KB)

1 b4885314 Thomas Schöpping
#include <ch.hpp>
2
#include <hal.h>
3
#include <chprintf.h>
4 58fe0e0b Thomas Schöpping
#include <string.h>
5
6
#include <amiro/util/util.h>
7
#include <amiro/bus/spi/HWSPIDriver.hpp>
8
#include <amiro/gyro/l3g4200d.hpp>
9 b4885314 Thomas Schöpping
#include <amiro/Constants.h>
10 f8cf404d Thomas Schöpping
#include <global.hpp>
11 b4885314 Thomas Schöpping
12
using namespace chibios_rt;
13 58fe0e0b Thomas Schöpping
14 f8cf404d Thomas Schöpping
extern Global global;
15
16 58fe0e0b Thomas Schöpping
namespace amiro {
17
18
L3G4200D::L3G4200D(HWSPIDriver *driver)
19 b4885314 Thomas Schöpping
    : 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 58fe0e0b Thomas Schöpping
}
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 b4885314 Thomas Schöpping
  systime_t time = System::getTime();
37
  this->setName("l3g4200d");
38 58fe0e0b Thomas Schöpping
39
  while (!this->shouldTerminate()) {
40 f336542d Timo Korthals
    time += this->period_st;
41 58fe0e0b Thomas Schöpping
42
    updateSensorData();
43 b4885314 Thomas Schöpping
    calcAngular();
44 58fe0e0b Thomas Schöpping
45
    this->eventSource.broadcastFlags(1);
46
47 b4885314 Thomas Schöpping
    if (time >= System::getTime()) {
48
      chThdSleepUntil(time);
49
    } else {
50 f8cf404d Thomas Schöpping
      chprintf((BaseSequentialStream*) &global.sercanmux1, "WARNING l3g4200d: Unable to keep track\r\n");
51 f336542d Timo Korthals
    }
52 58fe0e0b Thomas Schöpping
  }
53
  return RDY_OK;
54
}
55
56
int16_t
57
L3G4200D::
58
getAngularRate(const uint8_t axis) {
59
  return this->angularRate[axis];
60 b4885314 Thomas Schöpping
}
61 58fe0e0b Thomas Schöpping
62 b4885314 Thomas Schöpping
int32_t
63
L3G4200D::
64
getAngularRate_udps(const uint8_t axis) {
65 f336542d Timo Korthals
  return int32_t(this->angularRate[axis]) * this->udpsPerTic;
66 b4885314 Thomas Schöpping
}
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 58fe0e0b Thomas Schöpping
}
80
81 b4885314 Thomas Schöpping
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 58fe0e0b Thomas Schöpping
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 b4885314 Thomas Schöpping
  chSysLock();
123 58fe0e0b Thomas Schöpping
  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 b4885314 Thomas Schöpping
  chSysUnlock();
132 58fe0e0b Thomas Schöpping
}
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 b4885314 Thomas Schöpping
  // 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 f336542d Timo Korthals
  this->period_st = US2ST(this->period_us);
164
  this->period_ms = this->period_us * 1e-3;
165 b4885314 Thomas Schöpping
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 f8cf404d Thomas Schöpping
176 58fe0e0b Thomas Schöpping
  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 */