Library for the use of the atmospheric pressure sensor SCP1000

SCP1000.cpp

Committer:
s_inoue_mbed
Date:
2014-09-16
Revision:
0:a224293d7af4
Child:
1:1b2027cbe629

File content as of revision 0:a224293d7af4:

/* Copyright (c) 2014 Shigenori Inoue, MIT License
 *
 * 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.
 */

#include "SCP1000.h"

/* Constructor */
SCP1000::SCP1000(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName trig, PinName drdy) :
    _s(mosi, miso, sclk), _cs(cs), _trig(trig), _drdy(drdy)
{
    init();
}

/* Destructor */
SCP1000::~SCP1000() {}

/* Write an 8-bit data to an address in the SCP1000 via SPI */
void SCP1000::write(int addr, int data)
{
    uint8_t f_addr;
    uint8_t f_data;

    /* Creating the address frame, adding the WRITE bit */
    f_addr = ( static_cast<uint8_t>(addr << 2) | 0x02);

    /* Creating the data frame */
    f_data = static_cast<uint8_t>(data);

    _cs = 0;
    _s.write(f_addr);
    _s.write(f_data);
    _cs = 1;
}

/* Read an 8-bit data from an address in the SCP1000 via SPI */
int SCP1000::read8(int addr)
{
    uint8_t f_addr;
    uint8_t f_data;

    /* Creating the address frame, adding the WRITE bit */
    f_addr = static_cast<uint8_t>(addr << 2);

    _cs = 0;
    _s.write(f_addr);
    f_data = _s.write(0x00);
    _cs = 1;

    return static_cast<int>(f_data);
}

/* Read a 16-bit data from an address in the SCP1000 via SPI */
int SCP1000::read16(int addr)
{
    uint8_t f_addr;
    uint8_t f_data_h;
    uint8_t f_data_l;

    /* Creating the address frame, adding the WRITE bit */
    f_addr = static_cast<uint8_t>(addr << 2);

    _cs = 0;
    _s.write(f_addr);
    f_data_h = _s.write(0x00);
    f_data_l = _s.write(0x00);
    _cs = 1;

    return (static_cast<int>(f_data_h) << 8) + static_cast<int>(f_data_l);
}

/* Initialize the SCP1000 */
int SCP1000::init(void)
{
    int d_read;
    int cnt = 0;
    _cs = 1;
    _trig = 0;

    /* SPI setting */
    _s.format(8, 0);
    _s.frequency(1000000);

    /* Software reset of SCP1000 */
    write(RSTR, 0x01);

    /* Waiting for 60 ms as in the datasheet */
    wait_ms(60);

    /* Reading STATUS registor until its LSB = 0 */
    do {
        d_read = read8(STATUS);
        if ((d_read & 0x01) == 0) {
            break;
        } else {
            cnt++;
            wait_ms(10);
        }

        if (cnt > 100) {
            return ERR;
        }
    } while (true);

    /* Reading DATARD8 registor to check its LSB = 1 */
    d_read = read8(DATARD8);
    if ((d_read & 0x01) == 0) {
        return ERR;
    } else {
        return OK;
    }
}

/* Set the measurement mode of the SCP1000 */
void SCP1000::setMode(int mode)
{
    write(OPERATIONS, 0x00);
    wait_ms(50);
    switch(mode) {
        case HIGH_RESOLUTION:
            write(OPERATIONS, 0x0A);
            break;
        case HIGH_SPEED:
            write(OPERATIONS, 0x09);
            break;
        case ULTRA_LOW_POWER:
            write(OPERATIONS, 0x0B);
            break;
        case LOW_POWER_17BIT:
            write(ADDPTR, 0x00);
            write(DATAWR, 0x05);
            write(OPERATIONS, 0x02);
            write(OPERATIONS, 0x0C);
            break;
        case LOW_POWER_15BIT:
            write(ADDPTR, 0x00);
            write(DATAWR, 0x0D);
            write(OPERATIONS, 0x02);
            write(OPERATIONS, 0x0C);
            break;
        default: /* High resolution mode by default */
            write(OPERATIONS, 0x0A);
            break;
    }
}

/* Trigger the measurement by TRIG wire in Low Power Mode */
void SCP1000::triggerHard(void)
{
    _trig = 1;
    wait_us(1);
    _trig = 0;
}

/* Trigger the measurement by register writing in Low Power Mode */
void SCP1000::triggerSoft(void)
{
    write(OPERATIONS, 0x0C);
}

/* Check the data readiness */
bool SCP1000::IsReady(void)
{
    if (_drdy == 1) {
        return true;
    } else {
        return false;
    }
}

/* Read temperature measurement result in degrees Celcius */
float SCP1000::readTemperature(void)
{
    int temp_raw;
    temp_raw = read16(TEMPOUT);
    return static_cast<float>(temp_raw) * 0.05;
}

/* Read atmospheric pressure measurement result in hectopascal */
float SCP1000::readPressure(void)
{
    int press_raw_h;
    int press_raw_l;
    press_raw_h = read8(DATARD8);
    press_raw_l = read16(DATARD16);
    return static_cast<float>((press_raw_h << 16) + press_raw_l) * 0.0025;
}