1/*
2 * Author: Brendan Le Foll <brendan.le.foll@intel.com>
3 * Copyright (c) 2014 Intel Corporation.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <iostream>
26#include <string>
27#include <stdexcept>
28#include <unistd.h>
29#include <stdlib.h>
30#include <functional>
31#include <string.h>
32
33#include "max31855.h"
34
35using namespace upm;
36
37//! [Constructor]
38MAX31855::MAX31855(int bus, int cs)
39{
40    // initialise chip select as a normal gpio
41    if ( !(m_gpio = mraa_gpio_init(cs)) )
42      {
43        throw std::invalid_argument(std::string(__FUNCTION__) +
44                                    ": mraa_gpio_init(cs) failed, invalid pin?");
45        return;
46      }
47    mraa_gpio_dir(m_gpio, MRAA_GPIO_OUT);
48
49    // initialise the spi bus with a 2Mhz clock
50    m_sensor = mraa_spi_init(bus);
51    mraa_spi_frequency(m_sensor, 2000000);
52}
53//! [Constructor]
54
55//! [Destructor]
56MAX31855::~MAX31855()
57{
58    // close both m_sensor & m_gpio cleanly
59    mraa_result_t error;
60    error = mraa_spi_stop(m_sensor);
61    if (error != MRAA_SUCCESS) {
62        mraa_result_print(error);
63    }
64    error = mraa_gpio_close(m_gpio);
65    if (error != MRAA_SUCCESS) {
66        mraa_result_print(error);
67    }
68}
69//! [Destructor]
70
71double
72MAX31855::getTemp()
73{
74//! [spi]
75    // set chip select low
76    mraa_gpio_write(m_gpio, 0);
77
78    uint8_t buf[4];
79
80    // set our input buffer to 0, this is clean but not required
81    memset(buf, 0, sizeof(uint8_t)*4);
82
83    // Write buffer to the spi slave
84    uint8_t* x = mraa_spi_write_buf(m_sensor, buf, 4);
85//! [spi]
86
87//! [conversion]
88    // Endian correct way of making our char array into an 32bit int
89    int32_t temp = (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3];;
90
91    // mraa_spi_write_buf does not free the return buffer
92    free(x);
93
94    if (temp & 0x7) {
95        std::cerr << "Something went very wrong!" << std::endl;
96    }
97
98    // scrap all the data we dont care about
99    temp >>= 18;
100
101    // LSB = 0.25 degrees C
102    double c = (double) temp;
103    c *= 0.25;
104//! [conversion]
105
106    // set chip select high
107    mraa_gpio_write(m_gpio, 1);
108
109    return c;
110}
111