Statistics
| Branch: | Tag: | Revision:

amiro-os / components / input / mpr121.cpp @ 10687985

History | View | Annotate | Download (4.19 KB)

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

    
5
namespace amiro {
6

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

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

    
17
}
18

    
19
MPR121::
20
~MPR121() {
21

    
22
}
23

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

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

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

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

    
55
  }
56

    
57
  return res;
58

    
59
}
60

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

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

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

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

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

    
77
  if (res)
78
    return res;
79

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

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

    
85
}
86

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

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

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

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

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

    
107
  if (res)
108
    return res;
109

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

    
115
  this->tx_params.txbytes = 4;
116

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

    
119
}
120

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

    
125
  return this->button_state;
126

    
127
}
128

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

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

    
135
}
136

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

    
141
  return this->baseline_data[ix];
142

    
143
}
144

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

    
149
  return this->electrode_data[ix];
150

    
151
}
152

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

    
163
  I2CDriver *drv = this->driver;
164

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

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

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

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

    
175
    this->waitAnyEventTimeout(ALL_EVENTS, CAN::UPDATE_PERIOD_MSEC);
176
  }
177

    
178
  return RDY_OK;
179
}
180

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

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

    
195
  drv->acquireBus();
196

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

    
201
  if (res == RDY_OK) {
202

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

    
205
  }
206

    
207
  drv->releaseBus();
208

    
209
  return res;
210
}
211

    
212

    
213
} /* amiro */