Start of a microbit mpr121 library

Dependents:   microbitmpr121-example

Committer:
owenbrotherwood
Date:
Mon Jan 16 08:46:27 2017 +0000
Revision:
0:fb4572fc4901
Child:
1:f6fed00a3ff2
Start

Who changed what in which revision?

UserRevisionLine numberNew contents of line
owenbrotherwood 0:fb4572fc4901 1 /**
owenbrotherwood 0:fb4572fc4901 2 * @file MPR121.cpp
owenbrotherwood 0:fb4572fc4901 3 * @brief Device driver - MPR121 capactiive touch IC
owenbrotherwood 0:fb4572fc4901 4 * @author sam grove
owenbrotherwood 0:fb4572fc4901 5 * @version 1.0
owenbrotherwood 0:fb4572fc4901 6 * @see http://cache.freescale.com/files/sensors/doc/data_sheet/MPR121.pdf
owenbrotherwood 0:fb4572fc4901 7 *
owenbrotherwood 0:fb4572fc4901 8 * Copyright (c) 2013
owenbrotherwood 0:fb4572fc4901 9 *
owenbrotherwood 0:fb4572fc4901 10 * Licensed under the Apache License, Version 2.0 (the "License");
owenbrotherwood 0:fb4572fc4901 11 * you may not use this file except in compliance with the License.
owenbrotherwood 0:fb4572fc4901 12 * You may obtain a copy of the License at
owenbrotherwood 0:fb4572fc4901 13 *
owenbrotherwood 0:fb4572fc4901 14 * http://www.apache.org/licenses/LICENSE-2.0
owenbrotherwood 0:fb4572fc4901 15 *
owenbrotherwood 0:fb4572fc4901 16 * Unless required by applicable law or agreed to in writing, software
owenbrotherwood 0:fb4572fc4901 17 * distributed under the License is distributed on an "AS IS" BASIS,
owenbrotherwood 0:fb4572fc4901 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
owenbrotherwood 0:fb4572fc4901 19 * See the License for the specific language governing permissions and
owenbrotherwood 0:fb4572fc4901 20 * limitations under the License.
owenbrotherwood 0:fb4572fc4901 21 */
owenbrotherwood 0:fb4572fc4901 22 #include "MicroBit.h"
owenbrotherwood 0:fb4572fc4901 23 #include "microbit-mpr121-pi-cap.h"
owenbrotherwood 0:fb4572fc4901 24 #include "mbed_debug.h"
owenbrotherwood 0:fb4572fc4901 25
owenbrotherwood 0:fb4572fc4901 26 #define DEBUG 1
owenbrotherwood 0:fb4572fc4901 27
owenbrotherwood 0:fb4572fc4901 28 MicroBitMpr121::MicroBitMpr121(I2C &i2c, InterruptIn &pin, MPR121_ADDR i2c_addr)
owenbrotherwood 0:fb4572fc4901 29 {
owenbrotherwood 0:fb4572fc4901 30 _i2c = &i2c;
owenbrotherwood 0:fb4572fc4901 31 _irq = &pin;
owenbrotherwood 0:fb4572fc4901 32 _i2c_addr = (i2c_addr << 1);
owenbrotherwood 0:fb4572fc4901 33
owenbrotherwood 0:fb4572fc4901 34 return;
owenbrotherwood 0:fb4572fc4901 35 }
owenbrotherwood 0:fb4572fc4901 36
owenbrotherwood 0:fb4572fc4901 37 void MPR121::init(void)
owenbrotherwood 0:fb4572fc4901 38 {
owenbrotherwood 0:fb4572fc4901 39 // set the i2c speed
owenbrotherwood 0:fb4572fc4901 40 _i2c->frequency(400000);
owenbrotherwood 0:fb4572fc4901 41 // irq is open-collector and active-low
owenbrotherwood 0:fb4572fc4901 42 _irq->mode(PullUp);
owenbrotherwood 0:fb4572fc4901 43
owenbrotherwood 0:fb4572fc4901 44 // setup and registers - start with POR values (must be in stop mode)
owenbrotherwood 0:fb4572fc4901 45 MPR121::writeRegister(SRST, 0x63); //REG 0x80
owenbrotherwood 0:fb4572fc4901 46
owenbrotherwood 0:fb4572fc4901 47 // Baseline Filtering Control Register (changes response sensitivity)
owenbrotherwood 0:fb4572fc4901 48 // http://cache.freescale.com/files/sensors/doc/app_note/AN3891.pdf
owenbrotherwood 0:fb4572fc4901 49 MPR121::writeRegister(MHDR, 0x1); //REG 0x2B
owenbrotherwood 0:fb4572fc4901 50 MPR121::writeRegister(NHDR, 0x1); //REG 0x2C
owenbrotherwood 0:fb4572fc4901 51 MPR121::writeRegister(NCLR, 0x0); //REG 0x2D
owenbrotherwood 0:fb4572fc4901 52 MPR121::writeRegister(FDLR, 0x0); //REG 0x2E
owenbrotherwood 0:fb4572fc4901 53 MPR121::writeRegister(MHDF, 0x1); //REG 0x2F
owenbrotherwood 0:fb4572fc4901 54 MPR121::writeRegister(NHDF, 0x1); //REG 0x30
owenbrotherwood 0:fb4572fc4901 55 MPR121::writeRegister(NCLF, 0xFF); //REG 0x31
owenbrotherwood 0:fb4572fc4901 56 MPR121::writeRegister(FDLF, 0x2); //REG 0x32
owenbrotherwood 0:fb4572fc4901 57
owenbrotherwood 0:fb4572fc4901 58 // Touch / Release Threshold
owenbrotherwood 0:fb4572fc4901 59 // cache.freescale.com/files/sensors/doc/app_note/AN3892.pdf
owenbrotherwood 0:fb4572fc4901 60 for(int i=0; i<(12*2); i+=2) // touch
owenbrotherwood 0:fb4572fc4901 61 {
owenbrotherwood 0:fb4572fc4901 62 MPR121::writeRegister(static_cast<MPR121_REGISTER>(E0TTH+i), 0x20); //REG 0x41...0x58 odd
owenbrotherwood 0:fb4572fc4901 63 }
owenbrotherwood 0:fb4572fc4901 64 for(int i=0; i<(12*2); i+=2) // release
owenbrotherwood 0:fb4572fc4901 65 {
owenbrotherwood 0:fb4572fc4901 66 MPR121::writeRegister(static_cast<MPR121_REGISTER>(E0RTH+i), 0x10); //REG 0x41...0x58 even
owenbrotherwood 0:fb4572fc4901 67 }
owenbrotherwood 0:fb4572fc4901 68
owenbrotherwood 0:fb4572fc4901 69 // Debounce Register DR=b6...4, DT=b2...0
owenbrotherwood 0:fb4572fc4901 70 MPR121::writeRegister(DT_DR, 0x11); //REG 0x5B
owenbrotherwood 0:fb4572fc4901 71
owenbrotherwood 0:fb4572fc4901 72 // Filter and Global CDC CDT Configuration (sample time, charge current)
owenbrotherwood 0:fb4572fc4901 73 MPR121::writeRegister(CDC_CONFIG, 0x10); //REG 0x5C default 10
owenbrotherwood 0:fb4572fc4901 74 MPR121::writeRegister(CDT_CONFIG, 0x20); //REG 0x5D default 24
owenbrotherwood 0:fb4572fc4901 75
owenbrotherwood 0:fb4572fc4901 76 // Auto-Configuration Registers
owenbrotherwood 0:fb4572fc4901 77 // http://cache.freescale.com/files/sensors/doc/app_note/AN3889.pdf
owenbrotherwood 0:fb4572fc4901 78 MPR121::writeRegister(AUTO_CFG0, 0x33); // REG 0x7B
owenbrotherwood 0:fb4572fc4901 79 MPR121::writeRegister(AUTO_CFG1, 0x07); // REG 0x7C
owenbrotherwood 0:fb4572fc4901 80 MPR121::writeRegister(USL, 0xc9); // REG 0x7D((3.3-.07)/3.3) * 256
owenbrotherwood 0:fb4572fc4901 81 MPR121::writeRegister(LSL, 0x83); // REG 0x7E((3.3-.07)/3.3) * 256 * 0.65f
owenbrotherwood 0:fb4572fc4901 82 MPR121::writeRegister(TL, 0xb5); // REG 0x7F((3.3-.07)/3.3) * 256 * 0.9f
owenbrotherwood 0:fb4572fc4901 83 // 255 > USL > TL > LSL > 0
owenbrotherwood 0:fb4572fc4901 84
owenbrotherwood 0:fb4572fc4901 85 // Electrode Configuration Register - enable all 12 and start
owenbrotherwood 0:fb4572fc4901 86 MPR121::writeRegister(ECR, 0x8f);
owenbrotherwood 0:fb4572fc4901 87
owenbrotherwood 0:fb4572fc4901 88 return;
owenbrotherwood 0:fb4572fc4901 89 }
owenbrotherwood 0:fb4572fc4901 90
owenbrotherwood 0:fb4572fc4901 91 void MPR121::enable(void)
owenbrotherwood 0:fb4572fc4901 92 {
owenbrotherwood 0:fb4572fc4901 93 _button = 0;
owenbrotherwood 0:fb4572fc4901 94 _button_has_changed = 0;
owenbrotherwood 0:fb4572fc4901 95 // enable the 12 electrodes - allow disable to put device into
owenbrotherwood 0:fb4572fc4901 96 // lower current consumption mode
owenbrotherwood 0:fb4572fc4901 97 MPR121::writeRegister(ECR, 0x8f);
owenbrotherwood 0:fb4572fc4901 98 // and attach the interrupt handler
owenbrotherwood 0:fb4572fc4901 99 _irq->fall(this, &MPR121::handler);
owenbrotherwood 0:fb4572fc4901 100
owenbrotherwood 0:fb4572fc4901 101 return;
owenbrotherwood 0:fb4572fc4901 102 }
owenbrotherwood 0:fb4572fc4901 103
owenbrotherwood 0:fb4572fc4901 104 void MPR121::disable(void)
owenbrotherwood 0:fb4572fc4901 105 {
owenbrotherwood 0:fb4572fc4901 106 // detach the interrupt handler
owenbrotherwood 0:fb4572fc4901 107 _irq->fall(NULL);
owenbrotherwood 0:fb4572fc4901 108 _button = 0;
owenbrotherwood 0:fb4572fc4901 109 _button_has_changed = 0;
owenbrotherwood 0:fb4572fc4901 110 // put the device in low current consumption mode - dont re-init registers
owenbrotherwood 0:fb4572fc4901 111 MPR121::writeRegister(ECR, 0x0);
owenbrotherwood 0:fb4572fc4901 112 MPR121::writeRegister(AUTO_CFG0, 0x0); // REG 0x7B
owenbrotherwood 0:fb4572fc4901 113 MPR121::writeRegister(AUTO_CFG1, 0x0); // REG 0x7C
owenbrotherwood 0:fb4572fc4901 114
owenbrotherwood 0:fb4572fc4901 115 return;
owenbrotherwood 0:fb4572fc4901 116 }
owenbrotherwood 0:fb4572fc4901 117
owenbrotherwood 0:fb4572fc4901 118 uint32_t MPR121::isPressed(void)
owenbrotherwood 0:fb4572fc4901 119 {
owenbrotherwood 0:fb4572fc4901 120 return _button_has_changed;
owenbrotherwood 0:fb4572fc4901 121 }
owenbrotherwood 0:fb4572fc4901 122
owenbrotherwood 0:fb4572fc4901 123 uint16_t MPR121::buttonPressed(void)
owenbrotherwood 0:fb4572fc4901 124 {
owenbrotherwood 0:fb4572fc4901 125 _button_has_changed = 0;
owenbrotherwood 0:fb4572fc4901 126 return _button;
owenbrotherwood 0:fb4572fc4901 127 }
owenbrotherwood 0:fb4572fc4901 128
owenbrotherwood 0:fb4572fc4901 129 void MPR121::registerDump(Serial &obj) const
owenbrotherwood 0:fb4572fc4901 130 {
owenbrotherwood 0:fb4572fc4901 131 uint8_t reg_val = 0;
owenbrotherwood 0:fb4572fc4901 132
owenbrotherwood 0:fb4572fc4901 133 for(int i=0; i<0x80; i++)
owenbrotherwood 0:fb4572fc4901 134 {
owenbrotherwood 0:fb4572fc4901 135 reg_val = MPR121::readRegister(static_cast<MPR121_REGISTER>(i));
owenbrotherwood 0:fb4572fc4901 136 obj.printf("Reg 0x%02x: 0x%02x \n", i, reg_val);
owenbrotherwood 0:fb4572fc4901 137 }
owenbrotherwood 0:fb4572fc4901 138
owenbrotherwood 0:fb4572fc4901 139 return;
owenbrotherwood 0:fb4572fc4901 140 }
owenbrotherwood 0:fb4572fc4901 141
owenbrotherwood 0:fb4572fc4901 142 void MPR121::handler(void)
owenbrotherwood 0:fb4572fc4901 143 {
owenbrotherwood 0:fb4572fc4901 144 uint16_t reg_val = 0, oor_val = 0;
owenbrotherwood 0:fb4572fc4901 145 // read register 0 and 1
owenbrotherwood 0:fb4572fc4901 146 reg_val = MPR121::readRegister(ELE0_7_STAT);
owenbrotherwood 0:fb4572fc4901 147 reg_val |= MPR121::readRegister(ELE8_11_STAT) << 8;
owenbrotherwood 0:fb4572fc4901 148 // 2 and 3
owenbrotherwood 0:fb4572fc4901 149 oor_val = MPR121::readRegister(ELE0_7_OOR_STAT);
owenbrotherwood 0:fb4572fc4901 150 oor_val |= MPR121::readRegister(ELE8_11_OOR_STAT) << 8;
owenbrotherwood 0:fb4572fc4901 151
owenbrotherwood 0:fb4572fc4901 152 // debugging stuff and errors - if OOR fails someone was touching the pad during auto-config
owenbrotherwood 0:fb4572fc4901 153 // Just reboot until they're not doing this
owenbrotherwood 0:fb4572fc4901 154 if((0 != oor_val) && DEBUG)
owenbrotherwood 0:fb4572fc4901 155 {
owenbrotherwood 0:fb4572fc4901 156 debug("MPR121 OOR failure - 0x%04x\n", oor_val);
owenbrotherwood 0:fb4572fc4901 157 wait(0.1f);
owenbrotherwood 0:fb4572fc4901 158 NVIC_SystemReset();
owenbrotherwood 0:fb4572fc4901 159 }
owenbrotherwood 0:fb4572fc4901 160
owenbrotherwood 0:fb4572fc4901 161 _button = reg_val;
owenbrotherwood 0:fb4572fc4901 162 _button_has_changed = 1;
owenbrotherwood 0:fb4572fc4901 163
owenbrotherwood 0:fb4572fc4901 164 return;
owenbrotherwood 0:fb4572fc4901 165 }
owenbrotherwood 0:fb4572fc4901 166
owenbrotherwood 0:fb4572fc4901 167 void MPR121::writeRegister(MPR121_REGISTER const reg, uint8_t const data) const
owenbrotherwood 0:fb4572fc4901 168 {
owenbrotherwood 0:fb4572fc4901 169 char buf[2] = {reg, data};
owenbrotherwood 0:fb4572fc4901 170 uint8_t result = 0;
owenbrotherwood 0:fb4572fc4901 171
owenbrotherwood 0:fb4572fc4901 172 result = _i2c->write(_i2c_addr, buf, 2);
owenbrotherwood 0:fb4572fc4901 173
owenbrotherwood 0:fb4572fc4901 174 if(result && DEBUG)
owenbrotherwood 0:fb4572fc4901 175 {
owenbrotherwood 0:fb4572fc4901 176 debug("I2c write failed\n");
owenbrotherwood 0:fb4572fc4901 177 }
owenbrotherwood 0:fb4572fc4901 178
owenbrotherwood 0:fb4572fc4901 179 return;
owenbrotherwood 0:fb4572fc4901 180 }
owenbrotherwood 0:fb4572fc4901 181
owenbrotherwood 0:fb4572fc4901 182 uint8_t MPR121::readRegister(MPR121_REGISTER const reg) const
owenbrotherwood 0:fb4572fc4901 183 {
owenbrotherwood 0:fb4572fc4901 184 char buf[1] = {reg}, data = 0;
owenbrotherwood 0:fb4572fc4901 185 uint8_t result = 1;
owenbrotherwood 0:fb4572fc4901 186
owenbrotherwood 0:fb4572fc4901 187 result &= _i2c->write(_i2c_addr, buf, 1, true);
owenbrotherwood 0:fb4572fc4901 188 result &= _i2c->read(_i2c_addr, &data, 1);
owenbrotherwood 0:fb4572fc4901 189
owenbrotherwood 0:fb4572fc4901 190 if(result && DEBUG)
owenbrotherwood 0:fb4572fc4901 191 {
owenbrotherwood 0:fb4572fc4901 192 debug("I2c read failed\n");
owenbrotherwood 0:fb4572fc4901 193 }
owenbrotherwood 0:fb4572fc4901 194
owenbrotherwood 0:fb4572fc4901 195 return data;
owenbrotherwood 0:fb4572fc4901 196 }