235 lines
8.6 KiB
C
235 lines
8.6 KiB
C
/*
|
||
* Copyright (c) 2014-2016 IBM Corporation.
|
||
* All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions are met:
|
||
* * Redistributions of source code must retain the above copyright
|
||
* notice, this list of conditions and the following disclaimer.
|
||
* * Redistributions in binary form must reproduce the above copyright
|
||
* notice, this list of conditions and the following disclaimer in the
|
||
* documentation and/or other materials provided with the distribution.
|
||
* * Neither the name of the <organization> nor the
|
||
* names of its contributors may be used to endorse or promote products
|
||
* derived from this software without specific prior written permission.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
*/
|
||
|
||
|
||
//
|
||
// driver functions to access peripherals on the LoRaMote (Blipper) board
|
||
//
|
||
|
||
#include "hw.h"
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// Altimeter, Thermometer and Pressure sensor MPL3115A2
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
#define MPL3115A2_ADDR (0x60<<1)
|
||
#define MPL3115A2_CTRL_REG1 0x26
|
||
#define MPL3115A2_CTRL_REG1_SBYB_ACTIVE 0x81 // (ALT|ACTIVE)
|
||
#define MPL3115A2_OUT_P_MSB 0x01
|
||
#define MPL3115A2_OUT_T_MSB 0x04
|
||
|
||
// init temperature reading on Freescale's MPL3115A2 sensor
|
||
void blipper_temp_init() {
|
||
u1_t buf[2] = { MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_REG1_SBYB_ACTIVE };
|
||
i2c_xfer(MPL3115A2_ADDR, buf, 2, 0); // write 2, read 0
|
||
}
|
||
|
||
// read temperature from Freescale's MPL3115A2 sensor
|
||
//
|
||
// The DR_STATUS register, OUT_P_MSB, OUT_P_CSB, OUT_P_LSB, OUT_T_MSB,
|
||
// and OUT_T_LSB are stored in the auto-incrementing address range of
|
||
// 0x00 to 0x05. This allows the host controller to read the status
|
||
// register followed by the 20-bit Pressure/Altitude and 12-bit
|
||
// Temperature in a 6 byte I2C transaction.
|
||
u2_t blipper_temp_read() {
|
||
u1_t buf[2] = { MPL3115A2_OUT_T_MSB }; // read reg OUT_T_MSB, OUT_T_LSB
|
||
i2c_xfer(MPL3115A2_ADDR, buf, 1, 2); // write 1, read 2
|
||
return buf[0]<<8 | buf[1];
|
||
}
|
||
|
||
// read altitude from Freescale's MPL3115A2 sensor
|
||
//
|
||
// The Altitude data is arranged as 20-bit 2’s complement value in meters.
|
||
// The data is stored as meters with the 16 bits of OUT_P_MSB and OUT_P_CSB
|
||
// and with fractions of a meter stored in bits 7-4 of OUT_P_LSB.
|
||
// Be aware that the fractional bits are not signed, therefore,
|
||
// they are not represented in 2’s complement.
|
||
s2_t blipper_alt_read() {
|
||
u1_t buf[2] = { MPL3115A2_OUT_P_MSB }; // read reg OUT_P_MSB, OUT_P_CSB
|
||
i2c_xfer(MPL3115A2_ADDR, buf, 1, 2); // write 1, read 2
|
||
return buf[0]<<8 | buf[1];
|
||
}
|
||
|
||
// format temp value as 5-digit string "+99.9"
|
||
//
|
||
// The Temperature data is arranged as 12-bit 2's complement
|
||
// value in degrees C. The 8 bits of OUT_T_MSB representing
|
||
// degrees and with fractions of a degree are stored in 4 bits
|
||
// in position 7-4 of OUT_T_LSB. Be aware that the fractional
|
||
// bits are not signed, therefore, they are not represented in
|
||
// 2's complement. When RAW is selected then the RAW value is
|
||
// stored in all 16 bits of OUT_T_MSB and OUT_T_LSB
|
||
void blipper_temp_str(u2_t temp, u1_t* str) {
|
||
u1_t t1 = temp >> 8;
|
||
u1_t t2 = temp & 0xFF;
|
||
if(t1 & 0x80) {
|
||
str[0] = '-';
|
||
t1 = 256 - t1;
|
||
} else {
|
||
str[0] = '+';
|
||
}
|
||
str[2] = (t1 % 10) + '0';
|
||
t1 /= 10;
|
||
str[1] = (t1!=0) ? (t1 + '0') : ' ';
|
||
str[3] = '.';
|
||
str[4] = (t2>>4)*10/16 + '0';
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// 3-Axis Accelerometer sensor MMA8451Q
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
#define MMA8451Q_ADDR (0x1C<<1)
|
||
#define MMA8451Q_CTRL_REG1 0x2A
|
||
#define MMA8451Q_CTRL_REG1_ACTIVE 0x01
|
||
#define MMA8451Q_STATUS 0x00
|
||
|
||
// init accelerometer reading from Freescale's MMA8451Q sensor
|
||
void blipper_accel_init (void) {
|
||
u1_t buf[2] = { MMA8451Q_CTRL_REG1, MMA8451Q_CTRL_REG1_ACTIVE };
|
||
i2c_xfer(MMA8451Q_ADDR, buf, 2, 0); // write 2, read 0
|
||
}
|
||
|
||
// read accelaration from Freescale's MMA8451Q sensor (0xSSXXYYZZ)
|
||
//
|
||
// The measured acceleration data is stored in the OUT_X_MSB,
|
||
// OUT_X_LSB, OUT_Y_MSB, OUT_Y_LSB, OUT_Z_MSB, and OUT_Z_LSB registers
|
||
// as 2's complement 14-bit numbers. The most significant 8-bits of
|
||
// each axis are stored in OUT_X (Y , Z)_MSB, so applications needing
|
||
// only 8-bit results can use these 3 registers and ignore OUT_X,Y ,
|
||
// Z_LSB. To do this, the F_READ bit in CTRL_REG1 must be set. When
|
||
// the F_READ bit is cleared, the fast read mode is disabled.
|
||
u4_t blipper_accel_read (void) {
|
||
u1_t buf[7] = { MMA8451Q_STATUS }; // read reg STATUS, X, X, Y, Y, Z, Z
|
||
i2c_xfer(MMA8451Q_ADDR, buf, 1, 7); // write 1, read 7
|
||
return buf[0]<<24 | buf[1]<<16 | buf[3]<<8 | buf[5]; // (0xSSXXYYZZ)
|
||
}
|
||
|
||
// format acceleration value as 5-digit string "+0.00"
|
||
//
|
||
// When the full-scale is set to 2g, the measurement range is -2g to
|
||
// +1.99975g, and each count corresponds to 1g/4096 (0.25 mg) at 14-bits
|
||
// resolution. When the full-scale is set to 8g, the measurement range
|
||
// is -8g to +7.999g, and each count corresponds to 1g/1024 (0.98 mg)
|
||
// at 14-bits resolution. The resolution is reduced by a factor of 64
|
||
// if only the 8-bit results are used. For more information on the
|
||
// data manipulation between data formats and modes, refer to
|
||
// Freescale application.
|
||
void blipper_accel_str (u1_t acc, u1_t* str) {
|
||
if(acc & 0x80) {
|
||
str[0] = '-';
|
||
acc = 256 - acc;
|
||
} else {
|
||
str[0] = '+';
|
||
}
|
||
u2_t g = acc*200/128; // map values 0..127 to 0..200 (0..2g)
|
||
str[4] = (g % 10) + '0';
|
||
g /= 10;
|
||
str[3] = (g % 10) + '0';
|
||
g /= 10;
|
||
str[2] = '.';
|
||
str[1] = (g % 10) + '0';
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// IO Expander SX1509
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
// RegDirB RegDirA
|
||
// B7 B6 B5 B4 B3 B2 B1 B0 A7 A6 A5 A4 A3 A2 A1 A0
|
||
// 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||
// IN YE GR RE IN IN IN IN IN IN IN IN IN IN IN IN 0x8F 0xFF
|
||
|
||
#define SX1509_ADDR (0x3E<<1)
|
||
#define SX1509_RegDirB 0x0E
|
||
#define SX1509_RegDirA 0x0F
|
||
#define SX1509_RegDataB 0x10
|
||
#define SX1509_RegDataA 0x11
|
||
|
||
// initialize SX1509 IO expander
|
||
void blipper_ioexp_init (u2_t dir, u2_t data) {
|
||
u1_t buf[5] = { SX1509_RegDirB };
|
||
|
||
if(dir == 0x0000) { // use default
|
||
dir = 0x8FFF; // direction of LEDs OUT, all other IN
|
||
data = 0x7000; // output values for LEDs HIGH (OFF)
|
||
}
|
||
|
||
buf[1] = dir >> 8;
|
||
buf[2] = dir;
|
||
buf[3] = data >> 8;
|
||
buf[4] = data;
|
||
|
||
i2c_xfer(SX1509_ADDR, buf, 5, 0); // write 5, read 0
|
||
}
|
||
|
||
// get pin states of IO expander
|
||
u2_t blipper_ioexp_read (void) {
|
||
u1_t buf[2] = { SX1509_RegDataB };
|
||
i2c_xfer(SX1509_ADDR, buf, 1, 2); // write 1, read 2
|
||
return buf[0]<<8 | buf[1];
|
||
}
|
||
|
||
// set pin states of IO expander
|
||
void blipper_ioexp_write (u2_t data) {
|
||
u1_t buf[3] = { SX1509_RegDataB, data >> 8, data };
|
||
i2c_xfer(SX1509_ADDR, buf, 3, 0); // write 3, read 0
|
||
}
|
||
|
||
// get LED state (no 0-2)
|
||
u1_t blipper_led_get (u1_t no) {
|
||
return ((blipper_ioexp_read() & (1 << 12+no)) == 0);
|
||
}
|
||
|
||
// set LED state (no 0-2, mode 0=off, 1=on, 2=toggle)
|
||
void blipper_led_set (u1_t no, u1_t mode) {
|
||
u2_t state = blipper_ioexp_read();
|
||
u2_t mask = 1 << 12+no;
|
||
switch(mode) {
|
||
case 0: state |= mask; break; // off, set to high
|
||
case 1: state &= ~mask; break; // on, set to low
|
||
case 2: state ^= mask; break; // toggle, invert
|
||
}
|
||
blipper_ioexp_write(state);
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// 3-Axis Magnetometer sensor MAG3110
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
// TBD
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// GPS module UP501
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
// TBD
|