Statistics
| Branch: | Tag: | Revision:

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

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 */