diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index aeeb8f25..280538cf 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -265,6 +265,7 @@ if (BACNET_FOUND) add_example (e50hx) endif() add_example (vcap) +add_example (ds2413) # These are special cases where you specify example binary, source file and module(s) include_directories (${PROJECT_SOURCE_DIR}/src) diff --git a/examples/c++/ds2413.cxx b/examples/c++/ds2413.cxx new file mode 100644 index 00000000..bb6f1022 --- /dev/null +++ b/examples/c++/ds2413.cxx @@ -0,0 +1,59 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 +#include +#include +#include "ds2413.h" + +using namespace std; +using namespace upm; + +int main(int argc, char **argv) +{ +//! [Interesting] + // Instantiate a DS2413 Module on a Dallas 1-wire bus connected to UART 0 + upm::DS2413* sensor = new upm::DS2413(0); + + // find all of the DS2413 devices present on the bus + sensor->init(); + + // how many devices were found? + cout << "Found "<< sensor->devicesFound() << " device(s)" << endl; + + // read the gpio and latch values from the first device + // the lower 4 bits are of the form: + // + cout << "GPIO device 0 values: " << sensor->readGpios(0) << endl; + + // set the gpio latch values of the first device + cout << "Setting GPIO latches to on" << endl; + sensor->writeGpios(0, 0x03); + + cout << "Exiting..." << endl; + + delete sensor; +//! [Interesting] + return 0; +} diff --git a/examples/javascript/ds2413.js b/examples/javascript/ds2413.js new file mode 100644 index 00000000..069be3ac --- /dev/null +++ b/examples/javascript/ds2413.js @@ -0,0 +1,55 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * Author: Jon Trulson + * Copyright (c) 2015 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. + */ + + +var sensorObj = require('jsupm_ds2413'); + + +/************** Main code **************/ +// Instantiate a DS2413 Module on a Dallas 1-wire bus connected to UART 0 +var sensor = new sensorObj.DS2413(0); + +// find all of the DS2413 devices present on the bus +sensor.init(); + +// how many devices were found? +console.log("Found", sensor.devicesFound(), "device(s)"); + +// read the gpio and latch values from the first device +// the lower 4 bits are of the form: +// +console.log("GPIO device 0 values:", sensor.readGpios(0)); + +// set the gpio latch values of the first device +console.log("Setting GPIO latches to on");; +sensor.writeGpios(0, 0x03); + +sensor = null; +sensorObj.cleanUp(); +sensorObj = null; +console.log("Exiting..."); +process.exit(0); diff --git a/examples/python/ds2413.py b/examples/python/ds2413.py new file mode 100644 index 00000000..2dc95d83 --- /dev/null +++ b/examples/python/ds2413.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +# Author: Jon Trulson +# Copyright (c) 2015 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. + +import time, sys, signal, atexit +import pyupm_ds2413 as sensorObj + +# Instantiate a DS2413 Module on a Dallas 1-wire bus connected to UART 0 +sensor = sensorObj.DS2413(0) + +## Exit handlers ## +# This stops python from printing a stacktrace when you hit control-C +def SIGINTHandler(signum, frame): + raise SystemExit + +# This function lets you run code on exit +def exitHandler(): + print "Exiting..." + sys.exit(0) + +# Register exit handlers +atexit.register(exitHandler) +signal.signal(signal.SIGINT, SIGINTHandler) + +# find all of the DS2413 devices present on the bus +sensor.init(); + +# how many devices were found? +print "Found", sensor.devicesFound(), "device(s)" + +# read the gpio and latch values from the first device +# the lower 4 bits are of the form: +# +print "GPIO device 0 values:", sensor.readGpios(0) + +# set the gpio latch values of the first device +print "Setting GPIO latches to on" +sensor.writeGpios(0, 0x03); diff --git a/src/ds2413/CMakeLists.txt b/src/ds2413/CMakeLists.txt new file mode 100644 index 00000000..1d702b56 --- /dev/null +++ b/src/ds2413/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "ds2413") +set (libdescription "upm DS2413 1-wire Dual Channel Addressable Switch module") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/ds2413/ds2413.cxx b/src/ds2413/ds2413.cxx new file mode 100644 index 00000000..a708a799 --- /dev/null +++ b/src/ds2413/ds2413.cxx @@ -0,0 +1,165 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 +#include +#include + +#include "ds2413.h" + +using namespace upm; +using namespace std; + + +DS2413::DS2413(int uart) : + m_uart(uart) +{ + m_devicesFound = 0; + + // check basic access to the 1-wire bus (presence detect) + mraa::Result rv; + + if ((rv = m_uart.reset()) != mraa::SUCCESS) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": reset() failed, no devices on bus?"); + return; + } +} + +DS2413::~DS2413() +{ +} + +void DS2413::init() +{ + // iterate through the bus and build up a list of detected DS2413 + // devices (only) + + // empty the map, in case this method has already been run once + // before + m_devicesFound = 0; + m_deviceMap.clear(); + + // start the search from scratch + string id = m_uart.search(true); + + if (id.empty()) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": no devices detected on bus"); + return; + } + + while (!id.empty()) + { + // The first byte (id[0]]) is the device type (family) code. We + // are only interested in the family code for this device (0x3a). + + if ((uint8_t)id[0] == DS2413_FAMILY_CODE) + { + // we have a winner, add it to our map and continue searching + + m_deviceMap[m_devicesFound] = id; + m_devicesFound++; + } + + // continue search + id = m_uart.search(false); + } + + if (!m_devicesFound) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": no DS2413 devices found on bus"); + return; + } +} + +int DS2413::readGpios(int index) +{ + if (index < 0 || index >= m_devicesFound) + { + throw std::out_of_range(std::string(__FUNCTION__) + + ": device index out of range"); + return 0; + } + + m_uart.command(ACCESS_READ, m_deviceMap[index]); + + uint8_t value = m_uart.readByte(); + + // Validity is performed by taking the high nibble, inverting it, and + // copmpating it to the low nibble. If they are equal, then the + // data is good. + + if ( (value & 0x0f) != ((~value >> 4) & 0x0f) ) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": returned value failed integrity check"); + return 0; + } + + m_uart.reset(); + + // Only the 4 lsb's are relevant + return (value & 0x0f); +} + +void DS2413::writeGpios(int index, int value) +{ + if (index < 0 || index >= m_devicesFound) + { + throw std::out_of_range(std::string(__FUNCTION__) + + ": device index out of range"); + return; + } + + // mask out everything but the first 2 bits + uint8_t val = (uint8_t)value & 0x03; + + // the value must have the upper 8 bits written set to 1's + val |= 0xfc; + + m_uart.command(ACCESS_WRITE, m_deviceMap[index]); + + // first we write the new value, then the inverted value + m_uart.writeByte(val); + m_uart.writeByte(~val); + + // now we read back a response indicating success or failure + uint8_t resp = m_uart.readByte(); + + if (resp != ACK_SUCCESS) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": failed response validation"); + return; + } + + m_uart.reset(); + + return; + +} diff --git a/src/ds2413/ds2413.h b/src/ds2413/ds2413.h new file mode 100644 index 00000000..1e9e238b --- /dev/null +++ b/src/ds2413/ds2413.h @@ -0,0 +1,175 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 +#include +#include + +#include +#include +#include + +#include +#include + +#define DS2413_DEFAULT_UART 0 + +namespace upm { + /** + * @brief DS2413 modules + * @defgroup ds2413 libupm-ds2413 + * @ingroup maxim uart gpio + */ + + /** + * @library ds2413 + * @sensor ds2413 + * @comname DS2413 1-Wire Dual Channel Addressable Switch + * @type gpio + * @man maxim + * @con uart + * @web https://learn.adafruit.com/adafruit-1-wire-gpio-breakout-ds2413/overview + * + * @brief API for the DS2413 1-Wire Dual Channel Addressable Switch + * + * The DS2413 is a dual-channel programmable I/O 1-Wire® chip. The + * PIO outputs are configured as open-drain and provide up to 20mA + * continuous sink capability and off-state operating voltage up + * to 28V. Control and sensing of the PIO pins is performed with + * a dedicated device-level command protocol. + * + * This device requires the use of a UART to provide access to a + * Dallas 1-wire bus, via a new facility supported by MRAA (once + * the relevant PR is accepted), using the UartOW access class. + * It is important to realize that the UART is only being used to + * access and control a Dallas 1-wire compliant bus, it is not + * actually a UART device. + * + * Multiple DS2413 devices can be connected to this bus. This + * module will identify all such devices connected, and allow you + * to access them using an index starting at 0. + * + * @snippet ds2413.cxx Interesting + */ + + class DS2413 { + public: + + // The family code for these devices. We handle all of them that + // are found on the bus. + static const uint8_t DS2413_FAMILY_CODE = 0x3a; + + // commands + typedef enum { + ACCESS_READ = 0xf5, + ACCESS_WRITE = 0x5a + } DS2413_CMD_T; + + // possible ack responses for gpio writes + typedef enum { + ACK_SUCCESS = 0xaa, + ACK_FAILURE = 0xff + } DS2413_ACK_T; + + /** + * DS2413 object constructor + * + * @param uart Default UART to use (0 or 1). Default is 0. + */ + DS2413(int uart=DS2413_DEFAULT_UART); + + /** + * DS2413 object destructor + */ + ~DS2413(); + + /** + * This method will search the 1-wire bus and store information on + * each device detected on the bus. If no devices are found, an + * exception is thrown. Once this function completes + * successfully, you can use devicesFound() to determine how many + * devices were detected. + */ + void init(); + + /** + * This method will return the number of DS2413 devices that were + * found on the bus. + * + * @return number of DS2413's that were found on the bus + */ + int devicesFound() + { + return m_devicesFound; + } + + /** + * Read the GPIO latches and values for a given device. Only the + * lower 4 bits of the return value have any meaning. The bits + * are formatted as follows (from msb to lsb): + * + * + * @param index The device index to access (starts at 0). Default + * is the first device (index = 0) + * @return the 4 bit status of the 2 gpios + */ + int readGpios(int index=0); + + /** + * Write the given values to the gpio latches for a given device. + * Only the lower 2 bits of the value have any meaning. The lsb + * is gor gpioA and the next lsb is for gpioB: + * + * + * @param index The device index to access (starts at 0). + * @param value the value to write to the gpio latches + */ + void writeGpios(int index, int value); + + /** + * Return an 8 byte string representing the unique device ID for a + * given device index. If the index is invalid, an empty strig + * will be returned. + * + * @param index The device index to access (starts at 0). + * @return 8 byte string representing the 1-wire device's unique + * rom code. + */ + std::string getId(int index) + { + return m_deviceMap[index]; + } + + protected: + mraa::UartOW m_uart; + + // the total number of devices found + int m_devicesFound; + + std::map m_deviceMap; + + private: + }; +} diff --git a/src/ds2413/javaupm_ds2413.i b/src/ds2413/javaupm_ds2413.i new file mode 100644 index 00000000..687014a9 --- /dev/null +++ b/src/ds2413/javaupm_ds2413.i @@ -0,0 +1,22 @@ +%module javaupm_ds2413 +%include "../upm.i" +%include "carrays.i" +%include "std_string.i" + +%{ + #include "ds2413.h" +%} + +%include "ds2413.h" +%array_class(char, charArray); + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_ds2413"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/ds2413/jsupm_ds2413.i b/src/ds2413/jsupm_ds2413.i new file mode 100644 index 00000000..7ecd7470 --- /dev/null +++ b/src/ds2413/jsupm_ds2413.i @@ -0,0 +1,11 @@ +%module jsupm_ds2413 +%include "../upm.i" +%include "carrays.i" +%include "std_string.i" + +%{ + #include "ds2413.h" +%} + +%include "ds2413.h" +%array_class(char, charArray); diff --git a/src/ds2413/pyupm_ds2413.i b/src/ds2413/pyupm_ds2413.i new file mode 100644 index 00000000..62ff20ae --- /dev/null +++ b/src/ds2413/pyupm_ds2413.i @@ -0,0 +1,12 @@ +%module pyupm_ds2413 +%include "../upm.i" +%include "carrays.i" +%include "std_string.i" + +%feature("autodoc", "3"); + +%{ + #include "ds2413.h" +%} +%include "ds2413.h" +%array_class(char, charArray);