annotate projects/mpr121/I2C_MPR121.cpp @ 268:8d80eda512cd prerelease

Added new overlay for using PRU0 or PRU1, a script to halt board on button press, and several example projects
author andrewm
date Tue, 17 May 2016 14:46:26 +0100
parents
children
rev   line source
andrewm@268 1 /*
andrewm@268 2 * I2C_MPR121.cpp
andrewm@268 3 *
andrewm@268 4 * Created on: Oct 14, 2013
andrewm@268 5 * Author: Victor Zappi
andrewm@268 6 */
andrewm@268 7
andrewm@268 8
andrewm@268 9 #include "I2C_MPR121.h"
andrewm@268 10
andrewm@268 11 I2C_MPR121::I2C_MPR121() {
andrewm@268 12
andrewm@268 13 }
andrewm@268 14
andrewm@268 15 boolean I2C_MPR121::begin(uint8_t bus, uint8_t i2caddr) {
andrewm@268 16 _i2c_address = i2caddr;
andrewm@268 17
andrewm@268 18 if(initI2C_RW(bus, i2caddr, 0) > 0)
andrewm@268 19 return false;
andrewm@268 20
andrewm@268 21 // soft reset
andrewm@268 22 writeRegister(MPR121_SOFTRESET, 0x63);
andrewm@268 23 usleep(1000);
andrewm@268 24 //delay(1);
andrewm@268 25 for (uint8_t i=0; i<0x7F; i++) {
andrewm@268 26 // Serial.print("$"); Serial.print(i, HEX);
andrewm@268 27 // Serial.print(": 0x"); Serial.println(readRegister8(i));
andrewm@268 28 }
andrewm@268 29
andrewm@268 30
andrewm@268 31 writeRegister(MPR121_ECR, 0x0);
andrewm@268 32
andrewm@268 33 uint8_t c = readRegister8(MPR121_CONFIG2);
andrewm@268 34
andrewm@268 35 if (c != 0x24) {
andrewm@268 36 rt_printf("MPR121 read 0x%x instead of 0x24\n", c);
andrewm@268 37 return false;
andrewm@268 38 }
andrewm@268 39
andrewm@268 40 setThresholds(12, 6);
andrewm@268 41 writeRegister(MPR121_MHDR, 0x01);
andrewm@268 42 writeRegister(MPR121_NHDR, 0x01);
andrewm@268 43 writeRegister(MPR121_NCLR, 0x0E);
andrewm@268 44 writeRegister(MPR121_FDLR, 0x00);
andrewm@268 45
andrewm@268 46 writeRegister(MPR121_MHDF, 0x01);
andrewm@268 47 writeRegister(MPR121_NHDF, 0x05);
andrewm@268 48 writeRegister(MPR121_NCLF, 0x01);
andrewm@268 49 writeRegister(MPR121_FDLF, 0x00);
andrewm@268 50
andrewm@268 51 writeRegister(MPR121_NHDT, 0x00);
andrewm@268 52 writeRegister(MPR121_NCLT, 0x00);
andrewm@268 53 writeRegister(MPR121_FDLT, 0x00);
andrewm@268 54
andrewm@268 55 writeRegister(MPR121_DEBOUNCE, 0);
andrewm@268 56 writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
andrewm@268 57 writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
andrewm@268 58
andrewm@268 59 // writeRegister(MPR121_AUTOCONFIG0, 0x8F);
andrewm@268 60
andrewm@268 61 // writeRegister(MPR121_UPLIMIT, 150);
andrewm@268 62 // writeRegister(MPR121_TARGETLIMIT, 100); // should be ~400 (100 shifted)
andrewm@268 63 // writeRegister(MPR121_LOWLIMIT, 50);
andrewm@268 64 // enable all electrodes
andrewm@268 65 writeRegister(MPR121_ECR, 0x8F); // start with first 5 bits of baseline tracking
andrewm@268 66
andrewm@268 67 return true;
andrewm@268 68 }
andrewm@268 69
andrewm@268 70 void I2C_MPR121::setThresholds(uint8_t touch, uint8_t release) {
andrewm@268 71 for (uint8_t i=0; i<12; i++) {
andrewm@268 72 writeRegister(MPR121_TOUCHTH_0 + 2*i, touch);
andrewm@268 73 writeRegister(MPR121_RELEASETH_0 + 2*i, release);
andrewm@268 74 }
andrewm@268 75 }
andrewm@268 76
andrewm@268 77 uint16_t I2C_MPR121::filteredData(uint8_t t) {
andrewm@268 78 if (t > 12) return 0;
andrewm@268 79 return readRegister16(MPR121_FILTDATA_0L + t*2);
andrewm@268 80 }
andrewm@268 81
andrewm@268 82 uint16_t I2C_MPR121::baselineData(uint8_t t) {
andrewm@268 83 if (t > 12) return 0;
andrewm@268 84 uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
andrewm@268 85 return (bl << 2);
andrewm@268 86 }
andrewm@268 87
andrewm@268 88 uint16_t I2C_MPR121::touched(void) {
andrewm@268 89 uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
andrewm@268 90 return t & 0x0FFF;
andrewm@268 91 }
andrewm@268 92
andrewm@268 93 /*********************************************************************/
andrewm@268 94
andrewm@268 95
andrewm@268 96 uint8_t I2C_MPR121::readRegister8(uint8_t reg) {
andrewm@268 97 unsigned char inbuf, outbuf;
andrewm@268 98 struct i2c_rdwr_ioctl_data packets;
andrewm@268 99 struct i2c_msg messages[2];
andrewm@268 100
andrewm@268 101 /*
andrewm@268 102 * In order to read a register, we first do a "dummy write" by writing
andrewm@268 103 * 0 bytes to the register we want to read from. This is similar to
andrewm@268 104 * the packet in set_i2c_register, except it's 1 byte rather than 2.
andrewm@268 105 */
andrewm@268 106 outbuf = reg;
andrewm@268 107 messages[0].addr = 0x5A;
andrewm@268 108 messages[0].flags = 0;
andrewm@268 109 messages[0].len = sizeof(outbuf);
andrewm@268 110 messages[0].buf = &outbuf;
andrewm@268 111
andrewm@268 112 /* The data will get returned in this structure */
andrewm@268 113 messages[1].addr = 0x5A;
andrewm@268 114 messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
andrewm@268 115 messages[1].len = sizeof(inbuf);
andrewm@268 116 messages[1].buf = &inbuf;
andrewm@268 117
andrewm@268 118 /* Send the request to the kernel and get the result back */
andrewm@268 119 packets.msgs = messages;
andrewm@268 120 packets.nmsgs = 2;
andrewm@268 121 if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
andrewm@268 122 rt_printf("Unable to send data");
andrewm@268 123 return 0;
andrewm@268 124 }
andrewm@268 125
andrewm@268 126 return inbuf;
andrewm@268 127 }
andrewm@268 128
andrewm@268 129 uint16_t I2C_MPR121::readRegister16(uint8_t reg) {
andrewm@268 130 unsigned char inbuf[2], outbuf;
andrewm@268 131 struct i2c_rdwr_ioctl_data packets;
andrewm@268 132 struct i2c_msg messages[2];
andrewm@268 133
andrewm@268 134 /*
andrewm@268 135 * In order to read a register, we first do a "dummy write" by writing
andrewm@268 136 * 0 bytes to the register we want to read from. This is similar to
andrewm@268 137 * the packet in set_i2c_register, except it's 1 byte rather than 2.
andrewm@268 138 */
andrewm@268 139 outbuf = reg;
andrewm@268 140 messages[0].addr = _i2c_address;
andrewm@268 141 messages[0].flags = 0;
andrewm@268 142 messages[0].len = sizeof(outbuf);
andrewm@268 143 messages[0].buf = &outbuf;
andrewm@268 144
andrewm@268 145 /* The data will get returned in this structure */
andrewm@268 146 messages[1].addr = _i2c_address;
andrewm@268 147 messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
andrewm@268 148 messages[1].len = sizeof(inbuf);
andrewm@268 149 messages[1].buf = inbuf;
andrewm@268 150
andrewm@268 151 /* Send the request to the kernel and get the result back */
andrewm@268 152 packets.msgs = messages;
andrewm@268 153 packets.nmsgs = 2;
andrewm@268 154 if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
andrewm@268 155 rt_printf("Unable to send data");
andrewm@268 156 return 0;
andrewm@268 157 }
andrewm@268 158
andrewm@268 159 return (uint16_t)inbuf[0] | (((uint16_t)inbuf[1]) << 8);
andrewm@268 160 }
andrewm@268 161
andrewm@268 162 /**************************************************************************/
andrewm@268 163 /*!
andrewm@268 164 @brief Writes 8-bits to the specified destination register
andrewm@268 165 */
andrewm@268 166 /**************************************************************************/
andrewm@268 167 void I2C_MPR121::writeRegister(uint8_t reg, uint8_t value) {
andrewm@268 168 uint8_t buf[2] = { reg, value };
andrewm@268 169
andrewm@268 170 if(write(i2C_file, buf, 2) != 2)
andrewm@268 171 {
andrewm@268 172 cout << "Failed to write register " << (int)reg << " on MPR121\n";
andrewm@268 173 return;
andrewm@268 174 }
andrewm@268 175 }
andrewm@268 176