Statistics
| Branch: | Tag: | Revision:

amiro-os / components / input / mpr121.cpp @ 3f899f5d

History | View | Annotate | Download (4.149 KB)

1
#include <amiro/bus/i2c/I2CDriver.hpp>
2
#include <amiro/input/mpr121.hpp>
3

    
4
namespace amiro {
5

    
6
MPR121::
7
MPR121(I2CDriver *driver, const uint8_t master_id) :
8
  BaseStaticThread<256>(),
9
  driver(driver),
10
  master_id(master_id),
11
  button_state(0x0000u) {
12

    
13
  chDbgCheck(master_id <= 0x03u, "MPR121 ctor master_id");
14
  this->tx_params.addr = MPR121::SLA | this->master_id;
15

    
16
}
17

    
18
MPR121::
19
~MPR121() {
20

    
21
}
22

    
23
msg_t
24
MPR121::
25
updateButtonData() {
26

    
27
  msg_t res;
28
  const uint8_t offset_touch = offsetof(MPR121::registers, touch_status);
29
  const uint8_t offset_electrode = offsetof(MPR121::registers, ele_filt_data);
30
  const uint8_t offset_baseline = offsetof(MPR121::registers, ele_baseline);
31
  uint8_t buffer[offsetof(MPR121::registers, mhd_rising) - offset_touch];
32
  uint8_t *tmp = buffer;
33
  uint8_t reg = offset_touch;
34
  uint8_t i;
35
  this->tx_params.txbuf = &reg;
36
  this->tx_params.txbytes = 1;
37
  this->tx_params.rxbuf = buffer;
38
  this->tx_params.rxbytes = sizeof(buffer);
39

    
40
  res = this->driver->masterTransmit(&this->tx_params);
41

    
42
  if (!res) {
43
    tmp = buffer + offset_touch;
44
    this->button_state = (*(tmp + 1) << 8) | *tmp;
45
    tmp = buffer + offset_electrode;
46
    for (i = 0x00; i < 13; i++) {
47
      this->electrode_data[i] = (*(tmp + 1) << 8) | *tmp;
48
      tmp += 2;
49
    }
50
    tmp = buffer + offset_baseline;
51
    for (i = 0x00; i < 13; i++)
52
      this->baseline_data[i] = *tmp++;
53

    
54
  }
55

    
56
  return res;
57

    
58
}
59

    
60
msg_t
61
MPR121::
62
softReset() {
63

    
64
  msg_t res;
65
  uint8_t buffer[2];
66

    
67
  buffer[0] = offsetof(MPR121::registers, soft_reset);
68
  buffer[1] = SOFT_RST_MAGIC;
69

    
70
  this->tx_params.txbuf = buffer;
71
  this->tx_params.txbytes = 2;
72
  this->tx_params.rxbytes = 0;
73

    
74
  res = this->driver->masterTransmit(&this->tx_params);
75

    
76
  if (res)
77
    return res;
78

    
79
  buffer[0] = offsetof(MPR121::registers, ele_config);
80
  buffer[1] = 0x00u; /* ele_config: make sure we are in stop mode */
81

    
82
  return this->driver->masterTransmit(&this->tx_params);
83

    
84
}
85

    
86
msg_t
87
MPR121::
88
writeConfig(const MPR121Config *cfg) {
89

    
90
  msg_t res;
91
  uint8_t buffer[6];
92

    
93
  buffer[0] = offsetof(MPR121::registers, auto_cfg_ctrl);
94
  buffer[1] = (cfg->auto_config & 0x00FFu);
95
  buffer[2] = (cfg->auto_config & 0xFF00u) >> 8;
96
  buffer[3] = cfg->up_side_limit;
97
  buffer[4] = cfg->low_side_limit;
98
  buffer[5] = cfg->target_level;
99

    
100
  this->tx_params.txbuf = buffer;
101
  this->tx_params.txbytes = 6;
102
  this->tx_params.rxbytes = 0;
103

    
104
  res = this->driver->masterTransmit(&this->tx_params);
105

    
106
  if (res)
107
    return res;
108

    
109
  buffer[0] = offsetof(MPR121::registers, cdc_config);
110
  buffer[1] = (cfg->global_config & 0x00FFu);
111
  buffer[2] = (cfg->global_config & 0xFF00u) >> 8;
112
  buffer[3] = cfg->ele_config;
113

    
114
  this->tx_params.txbytes = 4;
115

    
116
  return this->driver->masterTransmit(&this->tx_params);
117

    
118
}
119

    
120
uint16_t
121
MPR121::
122
getButtonStatus() {
123

    
124
  return this->button_state;
125

    
126
}
127

    
128
uint8_t
129
MPR121::
130
getButtonStatus(uint8_t ix) {
131

    
132
  return this->button_state & (1u << ix);
133

    
134
}
135

    
136
uint8_t
137
MPR121::
138
getBaselineData(uint8_t ix) {
139

    
140
  return this->baseline_data[ix];
141

    
142
}
143

    
144
uint16_t
145
MPR121::
146
getElectrodeData(uint8_t ix) {
147

    
148
  return this->electrode_data[ix];
149

    
150
}
151

    
152
/**
153
 * Main Sensor Thread.
154
 * Will not check whether sensor was actually configured prior to running.
155
 * @note   You should configure the sensor while stopped, then start.
156
 * @return RDY_OK on exit.
157
 */
158
msg_t
159
MPR121::
160
main(void) {
161

    
162
  I2CDriver *drv = this->driver;
163

    
164
  this->setName("MPR121");
165

    
166
  while (!this->shouldTerminate()) {
167

    
168
    drv->acquireBus();
169
    this->updateButtonData();
170
    drv->releaseBus();
171

    
172
    this->eventSource.broadcastFlags(0);
173

    
174
    this->waitAnyEventTimeout(ALL_EVENTS, MS2ST(100));
175
  }
176

    
177
  return RDY_OK;
178
}
179

    
180
/**
181
 * Configure the MPR121 touch sensor.
182
 * Will perform a soft reset and then apply the configuration \p cfg.
183
 * @note      Call only when sensor is stopped.
184
 * @param cfg The new configuration.
185
 * @return    RDY_OK if everything went well. Appropriate error otherwise.
186
 */
187
msg_t
188
MPR121::
189
configure(const MPR121Config *cfg) {
190

    
191
  I2CDriver *drv = this->driver;
192
  msg_t res;
193

    
194
  drv->acquireBus();
195

    
196
  // do a soft reset, in case config changes config mode
197
  // (auto config vs. configure all sensors individually)
198
  res = this->softReset();
199

    
200
  if (res == RDY_OK) {
201

    
202
    res = this->writeConfig(cfg);
203

    
204
  }
205

    
206
  drv->releaseBus();
207

    
208
  return res;
209
}
210

    
211

    
212
} /* amiro */