Start of a microbit mpr121 library

Dependents:   microbitmpr121-example

Revision:
4:f63476855239
Parent:
3:a91b1bb396ca
Child:
5:4a8384331ca7
--- a/MicroBitMpr121.cpp	Mon Jan 16 14:31:36 2017 +0000
+++ b/MicroBitMpr121.cpp	Mon Jan 16 19:19:50 2017 +0000
@@ -1,128 +1,218 @@
-#include "MicroBit.h"
-#include "MicroBitI2C.h"
-#include "MicroBitMpr121.h"
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 British Broadcasting Corporation.
+This software is provided by Lancaster University by arrangement with the BBC.
 
-#define DEBUG 1
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
 
-//MicroBitMpr121::MicroBitMpr121(PinName sda, PinName scl, PinName irq, MPR121_ADDR addr)
-MicroBitMpr121::MicroBitMpr121()
+/**
+  * Class definition for MicroBit Mpr121.
+  *
+  * Represents an implementation of the Mpr121.
+  * Also includes ...
+  */
+#include "MicroBitConfig.h"
+#include "MicroBitPin.h"
+#include "MicroBitMpr121.h"
+#include "MicroBitFiber.h"
+#include "ErrorNo.h"
+
+/**
+  * An initialisation member function.
+  *
+  * @param id the unique identifier for this instance.
+  *
+  * @param address the base address  on the i2c bus.
+  */
+void MicroBitMpr121::init(uint16_t id, uint16_t address)
 {
-    MicroBitI2C::I2C _i2c(I2C_SDA0, I2C_SCL0);
-    uint8_t addr = ADDR_SDA;
-//   PinName _irq = irq; //TODO :: use
-    uint8_t _i2c_addr = (addr << 1); // To get 8bit address ...?
-    return;
+    this->id = id;
+    this->address = address;
+
+    // Indicate that we're up and running.
+    status |= MICROBIT_COMPONENT_RUNNING;
 }
 
-void MicroBitMpr121::init(void)
+/**
+  * Constructor.
+  * Create a software representation.
+  *
+  * @param _i2c an instance of i2c
+  *
+  * @param address the address register on the i2c bus. Defaults to MPR121_DEFAULT_ADDR.
+  *
+  * @param id the ID of the new object. Defaults to MPR121_DEFAULT_ADDR.
+  *
+  * @code
+  * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
+  *
+  * MicroBitMpr121 mpr121(i2c);
+  * @endcode
+  */
+MicroBitMpr121::MicroBitMpr121(MicroBitI2C& _i2c, uint16_t address, uint16_t id) :
+    int1(MICROBIT_PIN_P16),
+    i2c(_i2c)
+ 
 {
-   // P16.setPull(PullUp); //TODO use _irq and not hard code
-    MicroBitMpr121::write(SRST, 0x63);
-    MicroBitMpr121::write(MHDR, 0x1);
-    MicroBitMpr121::write(NHDR, 0x1);
-    MicroBitMpr121::write(NCLR, 0x0);
-    MicroBitMpr121::write(FDLR, 0x0);
-    MicroBitMpr121::write(MHDF, 0x1);
-    MicroBitMpr121::write(NHDF, 0x1);
-    MicroBitMpr121::write(NCLF, 0xFF);
-    MicroBitMpr121::write(FDLF, 0x2);
-    for(int i=0; i<(12*2); i+=2) {
-        MicroBitMpr121::write(static_cast<MPR121_REGISTER>(E0TTH+i), 0x20);
-    }
-    for(int i=0; i<(12*2); i+=2) {
-        MicroBitMpr121::write(static_cast<MPR121_REGISTER>(E0RTH+i), 0x10);
-    }
-    MicroBitMpr121::write(DT_DR, 0x11);
-    MicroBitMpr121::write(CDC_CONFIG, 0x10);
-    MicroBitMpr121::write(CDT_CONFIG, 0x20);
-    MicroBitMpr121::write(AUTO_CFG0, 0x33);
-    MicroBitMpr121::write(AUTO_CFG1, 0x07);
-    MicroBitMpr121::write(USL, 0xc9);
-    MicroBitMpr121::write(LSL, 0x83);
-    MicroBitMpr121::write(TL,  0xb5);
-    MicroBitMpr121::write(ECR, 0x8f);
-    return;
+    init(id, address);
 }
 
-void MicroBitMpr121::enable(void)
+/**
+  * Issues a standard, 2 byte I2C command write.
+  *
+  * Blocks the calling thread until complete.
+  *
+  * @param reg The address of the register to write to.
+  *
+  * @param value The value to write.
+  *
+  * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
+  */
+int MicroBitMpr121::writeCommand(uint8_t reg, uint8_t value)
 {
-    _button = 0;
-    _button_has_changed = 0;
-    MicroBitMpr121::write(ECR, 0x8f);
-   //TODO _irq->fall(this, &MicroBitMpr121::handler);
-    return;
+    uint8_t command[2];
+    command[0] = reg;
+    command[1] = value;
+
+    return i2c.write(address, (const char *)command, 2);
 }
 
-void MicroBitMpr121::disable(void)
+/**
+  * Issues a read command, copying data into the specified buffer.
+  *
+  * Blocks the calling thread until complete.
+  *
+  * @param reg The address of the register to access.
+  *
+  * @param buffer Memory area to read the data into.
+  *
+  * @param length The number of bytes to read.
+  *
+  * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
+  */
+int MicroBitMpr121::readCommand(uint8_t reg, uint8_t* buffer, int length)
 {
-  //TODO  _irq->fall(NULL);
-    _button = 0;
-    _button_has_changed = 0;
-    MicroBitMpr121::write(ECR, 0x0);
-    MicroBitMpr121::write(AUTO_CFG0, 0x0);
-    MicroBitMpr121::write(AUTO_CFG1, 0x0);
-    return;
-}
+    int result;
+
+    if (buffer == NULL || length <= 0)
+        return MICROBIT_INVALID_PARAMETER;
 
-uint32_t MicroBitMpr121::isPressed(void)
-{
-    return _button_has_changed;
+    result = i2c.write(address, (const char *)&reg, 1, true);
+    if (result !=0)
+        return MICROBIT_I2C_ERROR;
+
+    result = i2c.read(address, (char *)buffer, length);
+    if (result !=0)
+        return MICROBIT_I2C_ERROR;
+
+    return MICROBIT_OK;
 }
 
-uint16_t MicroBitMpr121::buttonPressed(void)
-{
-    _button_has_changed = 0;
-    return _button;
-}
-
-void MicroBitMpr121::registerDump() const
+/**
+  * Issues a read of a given address, and returns the value.
+  *
+  * Blocks the calling thread until complete.
+  *
+  * @param reg The address of the 16 bit register to access.
+  *
+  * @return The register value, interpreted as a 16 but signed value, or MICROBIT_I2C_ERROR if the read request failed.
+  */
+int MicroBitMpr121::read16(uint8_t reg)
 {
-    uint8_t reg_val = 0;
+    uint8_t cmd[2];
+    int result;
+
+    cmd[0] = reg;
+    result = i2c.write(address, (const char *)cmd, 1);
+    if (result !=0)
+        return MICROBIT_I2C_ERROR;
 
-    for(int i=0; i<0x80; i++) {
-        reg_val = MicroBitMpr121::read(static_cast<MPR121_REGISTER>(i));
-        printf("Reg 0x%02x: 0x%02x \n", i, reg_val);
-    }
+    cmd[0] = 0x00;
+    cmd[1] = 0x00;
 
-    return;
+    result = i2c.read(address, (char *)cmd, 2);
+    if (result !=0)
+        return MICROBIT_I2C_ERROR;
+
+    return (int16_t) ((cmd[1] | (cmd[0] << 8))); //concatenate the MSB and LSB
 }
 
-void MicroBitMpr121::handler(void)
+/**
+  * Issues a read of a given address, and returns the value.
+  *
+  * Blocks the calling thread until complete.
+  *
+  * @param reg The address of the 16 bit register to access.
+  *
+  * @return The register value, interpreted as a 8 bit unsigned value, or MICROBIT_I2C_ERROR if the magnetometer could not be accessed.
+  */
+int MicroBitMpr121::read8(uint8_t reg)
 {
-    uint16_t reg_val = 0, oor_val = 0;
-    reg_val  = MicroBitMpr121::read(ELE0_7_STAT);
-    reg_val |= MicroBitMpr121::read(ELE8_11_STAT) << 8;
-    oor_val  = MicroBitMpr121::read(ELE0_7_OOR_STAT);
-    oor_val |= MicroBitMpr121::read(ELE8_11_OOR_STAT) << 8;
-    if((0 != oor_val) && DEBUG) {
-        printf("MPR121 OOR failure - 0x%04x\n", oor_val);
-        wait(0.1f);
-        NVIC_SystemReset();
-    }
-    _button = reg_val;
-    _button_has_changed = 1;
-    return;
+    uint8_t data;
+    int result;
+
+    data = 0;
+    result = readCommand(reg, (uint8_t*) &data, 1);
+    if (result != MICROBIT_OK)
+        return MICROBIT_I2C_ERROR;
+
+    return data;
 }
 
-void MicroBitMpr121::write(MPR121_REGISTER const reg, uint8_t const data) const
+/**
+  * Periodic callback from MicroBit idle thread.
+  *
+  * Calls ...
+  */
+void MicroBitMpr121::idleTick()
 {
-    char buf[2] = {reg, data};
-    uint8_t result = 0;
-    result = _i2c.write(_i2c_addr, buf, 2);
-    if(result && DEBUG) {
-        printf("I2c write failed\n");
-    }
-    return;
+    
 }
 
-uint8_t MicroBitMpr121::read(MPR121_REGISTER const reg) const
+/**
+  * Attempts to read the 8 bit ID from the mpr121, this can be used for
+  * validation purposes. TODO?
+  *
+  * @return the 8 bit ID returned by the mpr121, or MICROBIT_I2C_ERROR if the request fails.
+  *
+  * @code
+  * compass.whoAmI();
+  * @endcode
+  */
+int MicroBitMpr121::whoAmI()
 {
-    char buf[1] = {reg}, data = 0;
-    uint8_t result = 1;
-    result &= _i2c.write(_i2c_addr, buf, 1, true); //TODO: Correct with true?
-    result &= _i2c.read(_i2c_addr, &data, 1);
-    if(result && DEBUG) {
-        printf("I2c read failed\n");
-    }
-    return data;
+    uint8_t data;
+    int result;
+
+ //   result = readCommand(MAG_WHOAMI, &data, 1);
+    if (result != MICROBIT_OK)
+        return MICROBIT_I2C_ERROR;
+
+    return (int)data;
 }
+
+/**
+  * Destructor, where we deregister this instance from the array of fiber components.
+  */
+MicroBitMpr121::~MicroBitMpr121()
+{
+    fiber_remove_idle_component(this);
+}