# command).
EXAMPLE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/examples/ \
- @CMAKE_CURRENT_SOURCE_DIR@/docs/
+ @CMAKE_CURRENT_SOURCE_DIR@/docs/ \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/max31855/
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
--- /dev/null
+Making a UPM module for MAX31855 {#max31855}
+================================
+
+The Maxim Integrated MAX31855 is a thermocouple amplifier allowing you to read
+from a K type themocouple. My board comes from the Pmod kit form Maxim
+(MAX31855PMB1) but you can get this from many different sources. The adafruit
+people made arduino code already so we'll use that as a
+[reference](https://github.com/adafruit/Adafruit-MAX31855-library/blob/master/Adafruit_MAX31855.cpp).
+
+### Basics
+
+This is a spi module so we will use the maa spi functions to build our module.
+First thing to do is to create a tree structure like this in upm/src/max31855:
+
+* max31855.cxx
+* max31855.h
+* jsupm_max31855.i
+* pyupm_max31855.i
+* CMakeLists.txt
+
+And then an example file to use & test our lib with in upm/examples/max31855.cxx.
+
+### Swig
+
+The .i files are used by swig, there is one for each python & javascript. They
+contain essentially the same thing and are very simple. The only thing to
+change between the javascript & node.js one is the argument to %module.
+
+@snippet jsupm_max31855.i Interesting
+
+The %include parameter defines which functions will be available to the
+node/python module created, Whilst the headers inside %{} will be explicitly
+required during compilation. Typically only the top level header is required in
+either of those args.
+
+### API
+
+Then we create the header (max31855.h) , a very simple header in our case we
+will have only a very basic api. We provide a getTemp() function which will
+return the same type as in the arduino library, a double.
+
+@snippet max31855.h Interesting
+
+Note that the header contains both the io that we will use, the gpio is in this
+case used as the chip select pin.
+
+### Implementing our API
+
+In the adafruit library the read function (our chip is a 3pin SPI so only read
+is possible), the spiread32() does all the work. It starts by setting up the io
+so we will do the same in our constructor.
+
+Note unlike on Arduino, we'll just set a 2Mhz clock and let the chip do the
+work.
+
+@snippet src/max31855/max31855.cxx Constructor
+
+Then we also need to implement a nice cleanup in our destructor.
+
+@snippet src/max31855/max31855.cxx Destructor
+
+Then to read data, we will use spi_write_buf which will allow us to write a
+whole uint32_t in order to get one back, which is what the arduino code does in
+spiread32. Obviously we set our chip select to low first. Here is the start of
+the implementation of MAX31855::getTemp()
+
+@snippet src/max31855/max31855.cxx spi
+
+Then using the arduino code as reference we simply reconstruct form the 4
+uint8_t values a 32bit int value and select only the valuable parts of
+information from that. The MAX31855 datahseet explains exactly which bits are
+useful, we will just do the same as the adafruit code, first checking the error
+bit and then scrapping everything but the 14bit of thermocouple data that are
+useful to us and converting it to a double.
+
+@snippet src/max31855/max31855.cxx conversion
+
+### Finalizing
+
+Our final example, very easy to use api!
+
+@snippet examples/max31855.cxx Interesting
+
+### Building
+
+The we need to add it to the examples/CMakeLists.txt. Only three lines are required
+
+~~~~~~~~~~~
+add_executable (max31855-example max31855.cxx)
+include_directories (${PROJECT_SOURCE_DIR}/src/max31855)
+target_link_libraries (max31855-example max31855 ${CMAKE_THREAD_LIBS_INIT})
+~~~~~~~~~~~
+
+Note you dont have to rebuild everything, cmake keeps target lists so if you
+named your example target <modulename>-example you can simply do make
+max31855-example and both the library & example will build.
Porting arduino libraries to libmaa as UPM libraries is usually fairly easy.
The issues typically come from misunderstanding of how a non real time OS deals
-with interupts and timers. It also highly depends on the sensor.
+with interupts and timers. It also highly depends on the sensor. A concrete
+example is explained in detail on @ref max31855
### Adding a new module to UPM
add_executable (proximity max44000.cxx)
add_executable (accelerometer mma7455.cxx)
add_executable (lcd st7735.cxx)
+add_executable (max31855-example max31855.cxx)
include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
include_directories (${PROJECT_SOURCE_DIR}/src/grove)
include_directories (${PROJECT_SOURCE_DIR}/src/max44000)
include_directories (${PROJECT_SOURCE_DIR}/src/mma7455)
include_directories (${PROJECT_SOURCE_DIR}/src/st7735)
+include_directories (${PROJECT_SOURCE_DIR}/src/max31855)
target_link_libraries (compass hmc5883l ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (groveled grove ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (proximity max44000 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (accelerometer mma7455 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (lcd st7735 ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries (max31855-example max31855 ${CMAKE_THREAD_LIBS_INIT})
--- /dev/null
+/*
+ * Author: Brendan Le Foll <brendan.le.foll@intel.com>
+ * Copyright (c) 2014 Intel Corporation.
+ *
+ * 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 <unistd.h>
+#include <iostream>
+#include <signal.h>
+
+//! [Interesting]
+#include "max31855.h"
+
+int
+main(int argc, char **argv)
+{
+ upm::MAX31855 *temp = new upm::MAX31855(0, 8);
+
+ std::cout << temp->getTemp() << std::endl;
+
+ return 0;
+}
+//! [Interesting]
--- /dev/null
+set (libname "max31855")
+set (libdescription "K type thermistor amplifier")
+set (module_src ${libname}.cxx)
+set (module_h ${libname}.h)
+upm_module_init()
--- /dev/null
+//! [Interesting]
+%module jsupm_max31855
+
+%{
+ #include "max31855.h"
+%}
+
+%include "max31855.h"
+//! [Interesting]
--- /dev/null
+/*
+ * Author: Brendan Le Foll <brendan.le.foll@intel.com>
+ * Copyright (c) 2014 Intel Corporation.
+ *
+ * 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 <iostream>
+#include <unistd.h>
+#include <stdlib.h>
+#include <functional>
+#include <string.h>
+
+#include "max31855.h"
+
+using namespace upm;
+
+//! [Constructor]
+MAX31855::MAX31855(int bus, int cs)
+{
+ // initialise chip select as a normal gpio
+ m_gpio = maa_gpio_init(cs);
+ maa_gpio_dir(m_gpio, MAA_GPIO_OUT);
+
+ // initialise the spi bus with a 2Mhz clock
+ m_sensor = maa_spi_init(bus);
+ maa_spi_frequency(m_sensor, 2000000);
+}
+//! [Constructor]
+
+//! [Destructor]
+MAX31855::~MAX31855()
+{
+ // close both m_sensor & m_gpio cleanly
+ maa_result_t error;
+ error = maa_spi_stop(m_sensor);
+ if (error != MAA_SUCCESS) {
+ maa_result_print(error);
+ }
+ error = maa_gpio_close(m_gpio);
+ if (error != MAA_SUCCESS) {
+ maa_result_print(error);
+ }
+}
+//! [Destructor]
+
+double
+MAX31855::getTemp()
+{
+//! [spi]
+ // set chip select low
+ maa_gpio_write(m_gpio, 0);
+
+ uint8_t buf[4];
+
+ // set our input buffer to 0, this is clean but not required
+ memset(buf, 0, sizeof(uint8_t)*4);
+
+ // Write buffer to the spi slave
+ uint8_t* x = maa_spi_write_buf(m_sensor, buf, 4);
+//! [spi]
+
+//! [conversion]
+ // Endian correct way of making our char array into an 32bit int
+ int32_t temp = (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3];;
+
+ // maa_spi_write_buf does not free the return buffer
+ free(x);
+
+ if (temp & 0x7) {
+ std::cerr << "Something went very wrong!" << std::endl;
+ }
+
+ // scrap all the data we dont care about
+ temp >>= 18;
+
+ // LSB = 0.25 degrees C
+ double c = (double) temp;
+ c *= 0.25;
+//! [conversion]
+
+ // set chip select high
+ maa_gpio_write(m_gpio, 1);
+
+ return c;
+}
--- /dev/null
+/*
+ * Author: Brendan Le Foll <brendan.le.foll@intel.com>
+ * Copyright (c) 2014 Intel Corporation.
+ *
+ * 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.
+ */
+#pragma once
+
+#include <string>
+#include <maa/spi.h>
+#include <maa/gpio.h>
+
+namespace upm {
+
+/**
+ * @brief C++ API for MAX31855
+ *
+ * This file defines the max31855 SPI sensor
+ *
+ * @snippet examples/max31855.cxx Interesting
+ *
+ */
+ //! [Interesting]
+class MAX31855 {
+ public:
+ /**
+ * Instanciates a MAX31855 object
+ *
+ * @param bus The spi bus to use
+ * @param cs The chip select pin
+ */
+ MAX31855(int bus, int cs);
+
+ /**
+ * MAX31855 object destructor
+ */
+ ~MAX31855();
+
+ /**
+ * Get the distance from the sensor
+ *
+ * @return value in degrees celcius
+ */
+ double getTemp();
+
+ private:
+ maa_spi_context m_sensor;
+ maa_gpio_context m_gpio;
+};
+//! [Interesting]
+
+}
--- /dev/null
+%module pyupm_max31855
+
+%include "stdint.i"
+
+%feature("autodoc", "3");
+
+%include "max31855.h"
+%{
+ #include "max31855.h"
+%}