Statistics
| Branch: | Tag: | Revision:

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

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