From d3b864362d500b0026b5a1bd63c3e39f903550be Mon Sep 17 00:00:00 2001 From: Jon Trulson Date: Wed, 18 Jan 2017 13:09:51 -0700 Subject: [PATCH] ds18b20: rewrite C++ to wrap C, add FTI, update examples Previously, the C++ and C versions of this driver were separate. Now the C++ implementation wraps the C implementation. In addition, the C++ init() function has been deprecated. It currently does nothing, and examples have been modified to remove it's calls. This function will be removed in a separate release. The examples have been further modified to update all detected devices and print their respective temperatures, instead of only reporting the on the first device detected. Signed-off-by: Jon Trulson --- docs/apichanges.md | 3 + examples/c++/ds18b20.cxx | 29 ++- examples/c/ds18b20.c | 2 +- examples/javascript/ds18b20.js | 23 +- examples/python/ds18b20.py | 23 +- src/ds18b20/CMakeLists.txt | 8 +- src/ds18b20/ds18b20.c | 448 ++++++++++++++++----------------- src/ds18b20/ds18b20.cxx | 262 +++---------------- src/ds18b20/ds18b20.h | 224 +++++++---------- src/ds18b20/ds18b20.hpp | 229 +++++++---------- src/ds18b20/ds18b20_defs.h | 63 +++++ src/ds18b20/ds18b20_fti.c | 120 +++++++++ src/ds18b20/javaupm_ds18b20.i | 3 +- src/ds18b20/jsupm_ds18b20.i | 3 +- src/ds18b20/pyupm_ds18b20.i | 2 + 15 files changed, 685 insertions(+), 757 deletions(-) create mode 100644 src/ds18b20/ds18b20_defs.h create mode 100644 src/ds18b20/ds18b20_fti.c diff --git a/docs/apichanges.md b/docs/apichanges.md index f43327b2..3af14181 100644 --- a/docs/apichanges.md +++ b/docs/apichanges.md @@ -4,6 +4,9 @@ API Changes {#apichanges} Here's a list of other API changes made to the library that break source/binary compatibility between releases: + * **ds18b20** The C++ interface init() function has been deprecated. + It is still present, but currently does nothing. It will be removed + in a future release. * **grove** Starting with UPM 1.0 the Grove libraries have been renamed from *upm-grove* to simply *upm-*. Class names also match this new format, with old classes marked as deprecated throughout the documentation. diff --git a/examples/c++/ds18b20.cxx b/examples/c++/ds18b20.cxx index f1eaa8c3..7855e238 100644 --- a/examples/c++/ds18b20.cxx +++ b/examples/c++/ds18b20.cxx @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -49,9 +49,6 @@ int main(int argc, char **argv) // Instantiate an DS18B20 instance using the default values (uart 0) upm::DS18B20 sensor; - // locate and setup our devices - sensor.init(); - cout << "Found " << sensor.devicesFound() << " device(s)" << endl; cout << endl; @@ -59,18 +56,26 @@ int main(int argc, char **argv) if (!sensor.devicesFound()) return 1; - // update and print available values every second + // update and print available values every 2 seconds while (shouldRun) { - // update our values for the first sensor - sensor.update(0); + // update our values for all of the detected sensors + sensor.update(-1); - // we show both C and F for temperature for the first sensor - cout << "Temperature: " << sensor.getTemperature(0) - << " C / " << sensor.getTemperature(0, true) << " F" - << endl; + // we show both C and F for temperature for the sensors + int i; + for (i=0; i - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -33,9 +33,6 @@ console.log("Initializing..."); // Instantiate an DS18B20 instance using the default values (uart 0) var sensor = new sensorObj.DS18B20(0); -// locate and setup our devices -sensor.init(); - console.log("Found", sensor.devicesFound(), "device(s)"); console.log(""); @@ -44,17 +41,21 @@ if (!sensor.devicesFound()) process.exit(1); } -// update and print available values every second +// update and print available values every 2 seconds setInterval(function() { - // update our values for the first sensor - sensor.update(0); + // update our values for all of the detected sensors + sensor.update(-1); - // we show both C and F for temperature for the first sensor - console.log("Temperature:", sensor.getTemperature(0), - "C /", sensor.getTemperature(0, true), "F"); + // we show both C and F for temperature for the sensors + for (var i=0; i -# Copyright (c) 2016 Intel Corporation. +# Copyright (c) 2016-2017 Intel Corporation. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -45,25 +45,26 @@ def main(): # Instantiate an DS18B20 instance using the default values (uart 0) sensor = sensorObj.DS18B20(0) - # locate and setup our devices - sensor.init() - print("Found", sensor.devicesFound(), "device(s)") print() if (not sensor.devicesFound()): sys.exit(1); - # update and print available values every second + # update and print available values every 2 seconds while (1): - # update our values for the first sensor - sensor.update(0) + # update our values for all of the detected sensors + sensor.update(-1) - # we show both C and F for temperature for the first sensor - print("Temperature:", sensor.getTemperature(0), "C /", end=' ') - print(sensor.getTemperature(0, True), "F") + # we show both C and F for temperature for the sensors + for i in range(sensor.devicesFound()): + print("Device:", i, end=' ') + print("Temperature:", sensor.getTemperature(i), "C /", end=' ') + print(sensor.getTemperature(i, True), "F") - time.sleep(1) + + print() + time.sleep(2) if __name__ == '__main__': main() diff --git a/src/ds18b20/CMakeLists.txt b/src/ds18b20/CMakeLists.txt index e60a4d9f..20f901f0 100644 --- a/src/ds18b20/CMakeLists.txt +++ b/src/ds18b20/CMakeLists.txt @@ -1,9 +1,9 @@ upm_mixed_module_init (NAME ds18b20 - DESCRIPTION "Programmable resolution 1-wire digital thermometer" - C_HDR ds18b20.h + DESCRIPTION "Programmable resolution DS 1-wire digital thermometer" + C_HDR ds18b20.h ds18b20_defs.h C_SRC ds18b20.c CPP_HDR ds18b20.hpp CPP_SRC ds18b20.cxx -# FTI_SRC ds18b20_fti.c -# CPP_WRAPS_C + FTI_SRC ds18b20_fti.c + CPP_WRAPS_C REQUIRES upmc-utilities mraa) diff --git a/src/ds18b20/ds18b20.c b/src/ds18b20/ds18b20.c index bfee586c..8b458bb2 100644 --- a/src/ds18b20/ds18b20.c +++ b/src/ds18b20/ds18b20.c @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -23,24 +23,15 @@ */ #include +#include #include "ds18b20.h" -// I'd rather use MRAA_UART_OW_ROMCODE_SIZE defined in uart_ow.h, but -// this then can't be used to specify array sizes since it's a static -// const int, rather than a define. This should be fixed in MRAA (PR -// submitted 9/2016). Until then, work around it. -#if !defined(MRAA_UART_OW_ROMCODE) -# define ROMCODE_SIZE 8 -#else -# define ROMCODE_SIZE MRAA_UART_OW_ROMCODE -#endif - // an internal struct we use to store information on the devices // found during initialization struct _ds18b20_info_t { - uint8_t id[ROMCODE_SIZE]; // 8-byte romcode id - float temperature; - DS18B20_RESOLUTIONS_T resolution; + uint8_t id[MRAA_UART_OW_ROMCODE_SIZE]; // 8-byte romcode id + float temperature; + DS18B20_RESOLUTIONS_T resolution; }; // internal utility function forward to read temperature from a single @@ -49,127 +40,127 @@ static float readSingleTemp(const ds18b20_context dev, unsigned int index); ds18b20_context ds18b20_init(unsigned int uart) { - // make sure MRAA is initialized - int mraa_rv; - if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) - { - printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); - return NULL; - } - - ds18b20_context dev = - (ds18b20_context)malloc(sizeof(struct _ds18b20_context)); - - if (!dev) - return NULL; - - // zero out context - memset((void *)dev, 0, sizeof(struct _ds18b20_context)); - - dev->ow = NULL; - - if (!(dev->ow = mraa_uart_ow_init(uart))) + // make sure MRAA is initialized + int mraa_rv; + if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) { - printf("%s: mraa_uart_ow_init() failed.\n", __FUNCTION__); - ds18b20_close(dev); - return NULL; + printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); + return NULL; } - // iterate through the bus and build up a list of detected DS18B20 - // devices (only) + ds18b20_context dev = + (ds18b20_context)malloc(sizeof(struct _ds18b20_context)); - mraa_result_t rv; - if ((rv = mraa_uart_ow_reset(dev->ow)) != MRAA_SUCCESS) + if (!dev) + return NULL; + + // zero out context + memset((void *)dev, 0, sizeof(struct _ds18b20_context)); + + dev->ow = NULL; + + if (!(dev->ow = mraa_uart_ow_init(uart))) { - printf("%s: mraa_uart_ow_reset() failed, no devices detected\n", - __FUNCTION__); - ds18b20_close(dev); - return NULL; + printf("%s: mraa_uart_ow_init() failed.\n", __FUNCTION__); + ds18b20_close(dev); + return NULL; } - uint8_t id[ROMCODE_SIZE]; + // iterate through the bus and build up a list of detected DS18B20 + // devices (only) - rv = mraa_uart_ow_rom_search(dev->ow, 1, id); - if (rv == MRAA_ERROR_UART_OW_NO_DEVICES) + mraa_result_t rv; + if ((rv = mraa_uart_ow_reset(dev->ow)) != MRAA_SUCCESS) { - // shouldn't happen, but.... - printf("%s: mraa_uart_ow_rom_search() failed, no devices detected\n", - __FUNCTION__); - ds18b20_close(dev); - return NULL; + printf("%s: mraa_uart_ow_reset() failed, no devices detected\n", + __FUNCTION__); + ds18b20_close(dev); + return NULL; } - if (rv == MRAA_ERROR_UART_OW_DATA_ERROR) + uint8_t id[MRAA_UART_OW_ROMCODE_SIZE]; + + rv = mraa_uart_ow_rom_search(dev->ow, 1, id); + if (rv == MRAA_ERROR_UART_OW_NO_DEVICES) { - printf("%s: mraa_uart_ow_rom_search() failed, Bus/Data error\n", - __FUNCTION__); - ds18b20_close(dev); - return NULL; + // shouldn't happen, but.... + printf("%s: mraa_uart_ow_rom_search() failed, no devices detected\n", + __FUNCTION__); + ds18b20_close(dev); + return NULL; } - while (rv == MRAA_SUCCESS) + if (rv == MRAA_ERROR_UART_OW_DATA_ERROR) { - // The first byte (id[0]]) is the device type (family) code. We - // are only interested in the family code for these devices. + printf("%s: mraa_uart_ow_rom_search() failed, Bus/Data error\n", + __FUNCTION__); + ds18b20_close(dev); + return NULL; + } - if ((uint8_t)id[0] == DS18B20_FAMILY_CODE) + while (rv == MRAA_SUCCESS) + { + // The first byte (id[0]]) is the device type (family) code. We + // are only interested in the family code for these devices. + + if ((uint8_t)id[0] == DS18B20_FAMILY_CODE) { - ds18b20_info_t *dsPtr = - (ds18b20_info_t *)realloc((void *)dev->devices, - sizeof(ds18b20_info_t) * - (dev->numDevices + 1)); + ds18b20_info_t *dsPtr = + (ds18b20_info_t *)realloc((void *)dev->devices, + sizeof(ds18b20_info_t) * + (dev->numDevices + 1)); - if (!dsPtr) + if (!dsPtr) { - printf("%s: realloc(%zu) failed\n", - __FUNCTION__, - sizeof(ds18b20_info_t) * (dev->numDevices + 1)); - ds18b20_close(dev); - return NULL; + printf("%s: realloc(%zu) failed\n", + __FUNCTION__, + sizeof(ds18b20_info_t) * (dev->numDevices + 1)); + ds18b20_close(dev); + return NULL; } - dev->devices = dsPtr; - // copy in the romcode - memcpy(dev->devices[dev->numDevices].id, id, - ROMCODE_SIZE); - // set defaults for now - dev->devices[dev->numDevices].temperature = 0.0; - dev->devices[dev->numDevices].resolution = - DS18B20_RESOLUTION_12BITS; + dev->devices = dsPtr; + // copy in the romcode + memcpy(dev->devices[dev->numDevices].id, id, + MRAA_UART_OW_ROMCODE_SIZE); + // set defaults for now + dev->devices[dev->numDevices].temperature = 0.0; + dev->devices[dev->numDevices].resolution = + DS18B20_RESOLUTION_12BITS; - dev->numDevices++; + dev->numDevices++; } - // on to the next one - rv = mraa_uart_ow_rom_search(dev->ow, 0, id); + // on to the next one + rv = mraa_uart_ow_rom_search(dev->ow, 0, id); } - if (!dev->numDevices || !dev->devices) + if (!dev->numDevices || !dev->devices) { - printf("%s: no DS18B20 devices found on bus\n", __FUNCTION__); - ds18b20_close(dev); - return NULL; + printf("%s: no DS18B20 devices found on bus\n", __FUNCTION__); + ds18b20_close(dev); + return NULL; } - // iterate through the found devices and query their resolutions - int i; - for (i=0; inumDevices; i++) + // iterate through the found devices and query their resolutions + int i; + for (i=0; inumDevices; i++) { - // read only the first 5 bytes of the scratchpad - static const int numScratch = 5; - uint8_t scratch[numScratch]; + // read only the first 5 bytes of the scratchpad + static const int numScratch = 5; + uint8_t scratch[numScratch]; - mraa_uart_ow_command(dev->ow, DS18B20_CMD_READ_SCRATCHPAD, - dev->devices[i].id); + mraa_uart_ow_command(dev->ow, DS18B20_CMD_READ_SCRATCHPAD, + dev->devices[i].id); - int j; - for (j=0; jow); + int j; + for (j=0; jow); - // config byte, shift the resolution to bit 0 - scratch[4] >>= _DS18B20_CFG_RESOLUTION_SHIFT; + // config byte, shift the resolution to bit 0 + scratch[4] >>= _DS18B20_CFG_RESOLUTION_SHIFT; - switch (scratch[4] & _DS18B20_CFG_RESOLUTION_MASK) + switch (scratch[4] & _DS18B20_CFG_RESOLUTION_MASK) { case 0: dev->devices[i].resolution = DS18B20_RESOLUTION_9BITS; break; case 1: dev->devices[i].resolution = DS18B20_RESOLUTION_10BITS; break; @@ -177,228 +168,233 @@ ds18b20_context ds18b20_init(unsigned int uart) case 3: dev->devices[i].resolution = DS18B20_RESOLUTION_12BITS; break; } - // reset the bus - mraa_uart_ow_reset(dev->ow); + // reset the bus + mraa_uart_ow_reset(dev->ow); } - return dev; + return dev; } void ds18b20_close(ds18b20_context dev) { - assert(dev != NULL); + assert(dev != NULL); - if (dev->devices) - free(dev->devices); - if (dev->ow) - mraa_uart_ow_stop(dev->ow); + if (dev->devices) + free(dev->devices); + if (dev->ow) + mraa_uart_ow_stop(dev->ow); - free(dev); + free(dev); } void ds18b20_update(const ds18b20_context dev, int index) { - assert(dev != NULL); + assert(dev != NULL); - if (index >= dev->numDevices) + if (index >= dev->numDevices) { - printf("%s: device index %d out of range\n", __FUNCTION__, index); - return; + printf("%s: device index %d out of range\n", __FUNCTION__, index); + return; } - // should we update all of them? - bool doAll = (index < 0) ? true : false; + // should we update all of them? + bool doAll = (index < 0) ? true : false; - if (doAll) + if (doAll) { - // if we want to update all of them, we will first send the - // convert command to all of them, then wait. This will be - // faster, timey-wimey wise, then converting, sleeping, and - // reading each individual sensor. + // if we want to update all of them, we will first send the + // convert command to all of them, then wait. This will be + // faster, timey-wimey wise, then converting, sleeping, and + // reading each individual sensor. - int i; - for (i=0; inumDevices; i++) - mraa_uart_ow_command(dev->ow, DS18B20_CMD_CONVERT, dev->devices[i].id); + int i; + for (i=0; inumDevices; i++) + mraa_uart_ow_command(dev->ow, DS18B20_CMD_CONVERT, dev->devices[i].id); } - else - mraa_uart_ow_command(dev->ow, DS18B20_CMD_CONVERT, dev->devices[index].id); + else + mraa_uart_ow_command(dev->ow, DS18B20_CMD_CONVERT, dev->devices[index].id); - // wait for conversion(s) to finish - usleep(750000); // 750ms max + // wait for conversion(s) to finish + upm_delay_ms(750000); // 750ms max - if (doAll) + if (doAll) { - int i; - for (i=0; inumDevices; i++) - dev->devices[i].temperature = readSingleTemp(dev, i); + int i; + for (i=0; inumDevices; i++) + dev->devices[i].temperature = readSingleTemp(dev, i); } - else - dev->devices[index].temperature = readSingleTemp(dev, index); + else + dev->devices[index].temperature = readSingleTemp(dev, index); } // utility function to read temp data from a single sensor static float readSingleTemp(const ds18b20_context dev, unsigned int index) { - assert(dev != NULL); + assert(dev != NULL); - if (index >= dev->numDevices) + if (index >= dev->numDevices) { - printf("%s: device index %d out of range\n", __FUNCTION__, index); - return 0.0; + printf("%s: device index %d out of range\n", __FUNCTION__, index); + return 0.0; } - static const int numScratch = 9; - uint8_t scratch[numScratch]; + static const int numScratch = 9; + uint8_t scratch[numScratch]; - // read the 9-byte scratchpad - mraa_uart_ow_command(dev->ow, DS18B20_CMD_READ_SCRATCHPAD, - dev->devices[index].id); - int i; - for (i=0; iow); + // read the 9-byte scratchpad + mraa_uart_ow_command(dev->ow, DS18B20_CMD_READ_SCRATCHPAD, + dev->devices[index].id); + int i; + for (i=0; iow); - // validate cksum -- if we get an error, we will warn and simply - // return the current (previously read) temperature - uint8_t crc = mraa_uart_ow_crc8(scratch, 8); + // validate cksum -- if we get an error, we will warn and simply + // return the current (previously read) temperature + uint8_t crc = mraa_uart_ow_crc8(scratch, 8); - if (crc != scratch[8]) + if (crc != scratch[8]) { - printf("%s: crc check failed for device %d, returning previously " - "measured temperature\n", __FUNCTION__, index); - return dev->devices[index].temperature; + printf("%s: crc check failed for device %d. Got %02x, expected %02x." + " Returning previously measured temperature\n", + __FUNCTION__, index, scratch[8], crc); + return dev->devices[index].temperature; } - // check the sign bit(s) - bool negative = (scratch[1] & 0x80) ? true : false; + // check the sign bit(s) + bool negative = (scratch[1] & 0x80) ? true : false; - // shift everything into position - int16_t temp = (scratch[1] << 8) | scratch[0]; + // shift everything into position + int16_t temp = (scratch[1] << 8) | scratch[0]; - // grab the fractional - uint8_t frac = temp & 0x0f; + // grab the fractional + uint8_t frac = temp & 0x0f; - // depending on the resolution, some frac bits should be ignored, so - // we mask them off. For 12bits, all bits are valid so we leve them - // alone. + // depending on the resolution, some frac bits should be ignored, so + // we mask them off. For 12bits, all bits are valid so we leve them + // alone. - switch (dev->devices[index].resolution) + switch (dev->devices[index].resolution) { case DS18B20_RESOLUTION_9BITS: frac &= 0x08; break; case DS18B20_RESOLUTION_10BITS: frac &= 0x0c; break; case DS18B20_RESOLUTION_11BITS: frac &= 0x0e; break; - // use all bits for 12b + // use all bits for 12b case DS18B20_RESOLUTION_12BITS: break; + default: + printf("%s: Internal error, invalid resolution %d\n", + __FUNCTION__, (int)dev->devices[index].resolution); + break; } - // remove the fractional with extreme prejudice - temp >>= 4; + // remove the fractional with extreme prejudice + temp >>= 4; - // compensate for sign - if (negative) - temp -= 65536; // 2^^16 + // compensate for sign + if (negative) + temp -= 65536; // 2^^16 - // convert - return ( (float)temp + ((float)frac * 0.0625) ); + // convert + return ( (float)temp + ((float)frac * 0.0625) ); } float ds18b20_get_temperature(const ds18b20_context dev, unsigned int index) { - assert(dev != NULL); + assert(dev != NULL); - if (index >= dev->numDevices) + if (index >= dev->numDevices) { - printf("%s: device index %d out of range\n", __FUNCTION__, index); - return 0.0; + printf("%s: device index %d out of range\n", __FUNCTION__, index); + return 0.0; } - return dev->devices[index].temperature; + return dev->devices[index].temperature; } void ds18b20_set_resolution(const ds18b20_context dev, unsigned int index, DS18B20_RESOLUTIONS_T res) { - assert(dev != NULL); + assert(dev != NULL); - if (index >= dev->numDevices) + if (index >= dev->numDevices) { - printf("%s: device index %d out of range\n", __FUNCTION__, index); - return; + printf("%s: device index %d out of range\n", __FUNCTION__, index); + return; } - static const int numScratch = 9; - uint8_t scratch[numScratch]; + static const int numScratch = 9; + uint8_t scratch[numScratch]; - // read the 9-byte scratchpad - mraa_uart_ow_command(dev->ow, DS18B20_CMD_READ_SCRATCHPAD, - dev->devices[index].id); - int i; - for (i=0; iow); + // read the 9-byte scratchpad + mraa_uart_ow_command(dev->ow, DS18B20_CMD_READ_SCRATCHPAD, + dev->devices[index].id); + int i; + for (i=0; iow); - // resolution is stored in byte 4 - scratch[4] = ((scratch[4] & ~(_DS18B20_CFG_RESOLUTION_MASK << - _DS18B20_CFG_RESOLUTION_SHIFT)) - | (res << _DS18B20_CFG_RESOLUTION_SHIFT)); + // resolution is stored in byte 4 + scratch[4] = ((scratch[4] & ~(_DS18B20_CFG_RESOLUTION_MASK << + _DS18B20_CFG_RESOLUTION_SHIFT)) + | (res << _DS18B20_CFG_RESOLUTION_SHIFT)); - // now, write back, we only write 3 bytes (2-4), no cksum. - mraa_uart_ow_command(dev->ow, DS18B20_CMD_WRITE_SCRATCHPAD, - dev->devices[index].id); - for (i=0; i<3; i++) - mraa_uart_ow_write_byte(dev->ow, scratch[i+2]); + // now, write back, we only write 3 bytes (2-4), no cksum. + mraa_uart_ow_command(dev->ow, DS18B20_CMD_WRITE_SCRATCHPAD, + dev->devices[index].id); + for (i=0; i<3; i++) + mraa_uart_ow_write_byte(dev->ow, scratch[i+2]); } -void ds18b20_copy_scratch_pad(const ds18b20_context dev, unsigned int index) +void ds18b20_copy_scratchpad(const ds18b20_context dev, unsigned int index) { - assert(dev != NULL); + assert(dev != NULL); - if (index >= dev->numDevices) + if (index >= dev->numDevices) { - printf("%s: device index %d out of range\n", __FUNCTION__, index); - return; + printf("%s: device index %d out of range\n", __FUNCTION__, index); + return; } - // issue the command - mraa_uart_ow_command(dev->ow, DS18B20_CMD_COPY_SCRATCHPAD, - dev->devices[index].id); + // issue the command + mraa_uart_ow_command(dev->ow, DS18B20_CMD_COPY_SCRATCHPAD, + dev->devices[index].id); - sleep(1); // to be safe... + upm_delay(1); // to be safe... } -void ds18b20_recallEEPROM(const ds18b20_context dev, unsigned int index) +void ds18b20_recall_eeprom(const ds18b20_context dev, unsigned int index) { - assert(dev != NULL); + assert(dev != NULL); - if (index >= dev->numDevices) + if (index >= dev->numDevices) { - printf("%s: device index %d out of range\n", __FUNCTION__, index); - return; + printf("%s: device index %d out of range\n", __FUNCTION__, index); + return; } - // issue the command - mraa_uart_ow_command(dev->ow, DS18B20_CMD_RECALL_EEPROM, - dev->devices[index].id); + // issue the command + mraa_uart_ow_command(dev->ow, DS18B20_CMD_RECALL_EEPROM, + dev->devices[index].id); - // issue read timeslots until a '1' is read back, indicating completion - while (!mraa_uart_ow_bit(dev->ow, 1)) - usleep(100); + // issue read timeslots until a '1' is read back, indicating completion + while (!mraa_uart_ow_bit(dev->ow, 1)) + upm_delay_us(100); } -int ds18b20_devices_found(const ds18b20_context dev) +unsigned int ds18b20_devices_found(const ds18b20_context dev) { - assert(dev != NULL); + assert(dev != NULL); - return dev->numDevices; + return dev->numDevices; } const uint8_t *ds18b20_get_id(const ds18b20_context dev, unsigned int index) { - assert(dev != NULL); + assert(dev != NULL); - if (index >= dev->numDevices) - return NULL; + if (index >= dev->numDevices) + return NULL; - static uint8_t id[ROMCODE_SIZE]; + static uint8_t id[MRAA_UART_OW_ROMCODE_SIZE]; - memcpy(id, dev->devices[index].id, ROMCODE_SIZE); - return id; + memcpy(id, dev->devices[index].id, MRAA_UART_OW_ROMCODE_SIZE); + return id; } diff --git a/src/ds18b20/ds18b20.cxx b/src/ds18b20/ds18b20.cxx index 26f2a5b8..2c265c83 100644 --- a/src/ds18b20/ds18b20.cxx +++ b/src/ds18b20/ds18b20.cxx @@ -23,9 +23,7 @@ */ #include -#include #include -#include #include "ds18b20.hpp" @@ -35,268 +33,88 @@ using namespace std; // conversion from celsius to fahrenheit static float c2f(float c) { - return (c * (9.0 / 5.0) + 32.0); + return (c * (9.0 / 5.0) + 32.0); } DS18B20::DS18B20(int uart) : - m_uart(uart) + m_ds18b20(ds18b20_init(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?"); - } + if (!m_ds18b20) + throw std::runtime_error(string(__FUNCTION__) + + ": ds18b20_init() failed"); } DS18B20::~DS18B20() { + ds18b20_close(m_ds18b20); } void DS18B20::init() { - // iterate through the bus and build up a list of detected DS18B20 - // devices (only) - - // empty the map, in case this method has already been run once - // before - m_devicesFound = 0; - m_deviceMap.clear(); - - sensor_info_t sinfo; - - // defaults - sinfo.temperature = 0.0; - sinfo.resolution = RESOLUTION_12BITS; - - // 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"); - } - - while (!id.empty()) - { - // The first byte (id[0]]) is the device type (family) code. We - // are only interested in the family code for these devices. - - if ((uint8_t)id[0] == DS18B20_FAMILY_CODE) - { - // we have a winner, add it to our map and continue searching - - sinfo.id = id; - m_deviceMap[m_devicesFound] = sinfo; - - m_devicesFound++; - } - - // continue search - id = m_uart.search(false); - } - - if (!m_devicesFound) - { - throw std::runtime_error(std::string(__FUNCTION__) + - ": no DS18B20 devices found on bus"); - } - - // iterate through the found devices and query their resolutions - for (int i=0; i>= _CFG_RESOLUTION_SHIFT; - - switch (scratch[4] & _CFG_RESOLUTION_MASK) - { - case 0: m_deviceMap[i].resolution = RESOLUTION_9BITS; break; - case 1: m_deviceMap[i].resolution = RESOLUTION_10BITS; break; - case 2: m_deviceMap[i].resolution = RESOLUTION_11BITS; break; - case 3: m_deviceMap[i].resolution = RESOLUTION_12BITS; break; - } - - // reset the bus - m_uart.reset(); - } + // deprecated function. Handled in ctor now. } void DS18B20::update(int index) { - if (index >= m_devicesFound) - { - throw std::out_of_range(std::string(__FUNCTION__) + - ": device index out of range"); - } + if (index >= (int)ds18b20_devices_found(m_ds18b20)) + throw std::out_of_range(string(__FUNCTION__) + + ": Invalid index"); - // should we update all of them? - bool doAll = (index < 0) ? true : false; - - if (doAll) - { - // if we want to update all of them, we will first send the - // convert command to all of them, then wait. This will be - // faster, timey-wimey wise, then converting, sleeping, and - // reading each individual sensor. - - for (int i=0; i= m_devicesFound) - { - throw std::out_of_range(std::string(__FUNCTION__) + - ": device index out of range"); - } + if (index >= ds18b20_devices_found(m_ds18b20)) + throw std::out_of_range(string(__FUNCTION__) + + ": Invalid index"); - static const int numScratch = 9; - uint8_t scratch[numScratch]; - - // read the 9-byte scratchpad - m_uart.command(CMD_READ_SCRATCHPAD, m_deviceMap[index].id); - for (int i=0; i>= 4; - - // compensate for sign - if (negative) - temp -= 65536; // 2^^16 - - // convert - return ( float(temp) + (float(frac) * 0.0625) ); + if (fahrenheit) + return c2f(ds18b20_get_temperature(m_ds18b20, index)); + else + return ds18b20_get_temperature(m_ds18b20, index); } -float DS18B20::getTemperature(int index, bool fahrenheit) +void DS18B20::setResolution(unsigned int index, DS18B20_RESOLUTIONS_T res) { - if (index < 0 || index >= m_devicesFound) + if (index >= ds18b20_devices_found(m_ds18b20)) { - throw std::out_of_range(std::string(__FUNCTION__) + - ": device index out of range"); + throw std::out_of_range(std::string(__FUNCTION__) + + ": device index out of range"); } - if (fahrenheit) - return c2f(m_deviceMap[index].temperature); - else - return m_deviceMap[index].temperature; + ds18b20_set_resolution(m_ds18b20, index, res); } -void DS18B20::setResolution(int index, RESOLUTIONS_T res) +void DS18B20::copyScratchPad(unsigned int index) { - if (index < 0 || index >= m_devicesFound) + if (index >= ds18b20_devices_found(m_ds18b20)) { - throw std::out_of_range(std::string(__FUNCTION__) + - ": device index out of range"); + throw std::out_of_range(std::string(__FUNCTION__) + + ": device index out of range"); } - static const int numScratch = 9; - uint8_t scratch[numScratch]; - - // read the 9-byte scratchpad - m_uart.command(CMD_READ_SCRATCHPAD, m_deviceMap[index].id); - for (int i=0; i= m_devicesFound) + if (index >= ds18b20_devices_found(m_ds18b20)) { - throw std::out_of_range(std::string(__FUNCTION__) + - ": device index out of range"); + throw std::out_of_range(std::string(__FUNCTION__) + + ": device index out of range"); } - // issue the command - m_uart.command(CMD_COPY_SCRATCHPAD, m_deviceMap[index].id); - - sleep(1); // to be safe... + ds18b20_recall_eeprom(m_ds18b20, index); } -void DS18B20::recallEEPROM(int index) +string DS18B20::getId(unsigned int index) { - if (index < 0 || index >= m_devicesFound) + if (index >= ds18b20_devices_found(m_ds18b20)) { - throw std::out_of_range(std::string(__FUNCTION__) + - ": device index out of range"); + throw std::out_of_range(std::string(__FUNCTION__) + + ": device index out of range"); } - - // issue the command - m_uart.command(CMD_RECALL_EEPROM, m_deviceMap[index].id); - - // issue read timeslots until a '1' is read back, indicating completion - while (!m_uart.writeBit(1)) - usleep(100); + return string((char *)ds18b20_get_id(m_ds18b20, index), + MRAA_UART_OW_ROMCODE_SIZE); } diff --git a/src/ds18b20/ds18b20.h b/src/ds18b20/ds18b20.h index 87c01a0f..f0010cb4 100644 --- a/src/ds18b20/ds18b20.h +++ b/src/ds18b20/ds18b20.h @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -28,150 +28,120 @@ #include #include - -#include "upm.h" +#include +#include "ds18b20_defs.h" #ifdef __cplusplus extern "C" { #endif -// The family code for these devices. We handle all of them that -// are found on the bus. -#define DS18B20_FAMILY_CODE 0x28 + /** + * @file ds18b20.h + * @library ds18b20 + * @brief C API for the DS18B20 1-Wire Temperature Sensor + * + * @include ds18b20.c + */ - /** - * @file ds18b20.h - * @library ds18b20 - * @brief C API for the DS18B20 1-Wire Temperature Sensor - * - * @include ds18b20.c - */ + // forward declaration + typedef struct _ds18b20_info_t ds18b20_info_t; - // forward declaration - typedef struct _ds18b20_info_t ds18b20_info_t; + /** + * Device context + */ + typedef struct _ds18b20_context { + mraa_uart_ow_context ow; - /** - * Device context - */ - typedef struct _ds18b20_context { - mraa_uart_ow_context ow; + // number of devices found + int numDevices; - // number of devices found - int numDevices; + // list of allocated ds18b20_info_t instances + ds18b20_info_t *devices; + } *ds18b20_context; - // list of allocated ds18b20_info_t instances - ds18b20_info_t *devices; - } *ds18b20_context; + /** + * This function will initilaize and search the 1-wire bus and store + * information on each DS18B20 device detected on the bus. If no + * devices are found, NULL is returned. Once this function + * completes successfully, you can use ds18b20_devices_found() to + * determine how many devices were detected. + * + * @return device context, or NULL on error. + */ + ds18b20_context ds18b20_init(unsigned int uart); - // commands - typedef enum { - DS18B20_CMD_CONVERT = 0x44, // start a temp conversion - DS18B20_CMD_WRITE_SCRATCHPAD = 0x4e, - DS18B20_CMD_READ_SCRATCHPAD = 0xbe, - DS18B20_CMD_COPY_SCRATCHPAD = 0x48, // copy scratchpad to EEPROM - DS18B20_CMD_RECALL_EEPROM = 0xb8, // copy EEPROM to scratchpad - DS18B20_CMD_READ_POWER_SUPPLY = 0xb4 // parasitically powered? - } DS18B20_CMD_T; + /** + * Close the device and deallocate all resources. + */ + void ds18b20_close(ds18b20_context dev); - // config register (scratchpad[4]) - typedef enum { - DS18B20_CFG_RESOLUTION_R0 = 0x20, - DS18B20_CFG_RESOLUTION_R1 = 0x40, - _DS18B20_CFG_RESOLUTION_MASK = 3, - _DS18B20_CFG_RESOLUTION_SHIFT = 5 + /** + * Update our stored temperature for a device. This method must + * be called prior to ds18b20_get_temperature(). + * + * @param index The device index to access (starts at 0). Specify + * -1 to query all detected devices. Default: -1 + */ + void ds18b20_update(const ds18b20_context dev, int index); - // all other bits reserved and non-writable - } DS18B20_CFG_BITS_T; + /** + * Get the current temperature. ds18b20_update() must have been + * called prior to calling this method. + * + * @param index The device index to access (starts at 0). + * @return The last temperature reading in Celsius. + */ + float ds18b20_get_temperature(const ds18b20_context dev, + unsigned int index); - typedef enum { - DS18B20_RESOLUTION_9BITS = 0, // 93.75ms (tconv/8) - DS18B20_RESOLUTION_10BITS = 1, // 187.5 (tconv/4) - DS18B20_RESOLUTION_11BITS = 2, // 375ms (tconv/2) - DS18B20_RESOLUTION_12BITS = 3 // 750ms (tconv) - } DS18B20_RESOLUTIONS_T; + /** + * Set the device resolution for a device. These devices support + * 9, 10, 11, and 12 bits of resolution, with the default from the + * factory at 12 bits. + * + * @param index The device index to access (starts at 0). + * @param res One of the DS18B20_RESOLUTIONS_T values + */ + void ds18b20_set_resolution(const ds18b20_context dev, unsigned int index, + DS18B20_RESOLUTIONS_T res); - /** - * This function will initilaize and search the 1-wire bus and store - * information on each DS18B20 device detected on the bus. If no - * devices are found, NULL is returned. Once this function - * completes successfully, you can use ds18b20_devices_found() to - * determine how many devices were detected. - * - * @return device context, or NULL on error. - */ - ds18b20_context ds18b20_init(unsigned int uart); + /** + * Copy the device's scratchpad memory to the EEPROM. This + * includes the configuration byte (resolution). + * + * @param index The device index to access (starts at 0). + */ + void ds18b20_copy_scratchpad(const ds18b20_context dev, unsigned int index); - /** - * Close the device and deallocate all resources. - */ - void ds18b20_close(ds18b20_context dev); + /** + * Copy the device's EEPROM memory to the scratchpad. This method + * will return when the copy completes. This operation is + * performed by the device automatically on power up, so it is + * rarely needed. + * + * @param index The device index to access (starts at 0). + */ + void ds18b20_recall_eeprom(const ds18b20_context dev, unsigned int index); - /** - * Update our stored temperature for a device. This method must - * be called prior to ds18b20_get_temperature(). - * - * @param index The device index to access (starts at 0). Specify - * -1 to query all detected devices. Default: -1 - */ - void ds18b20_update(const ds18b20_context dev, int index); + /** + * This method will return the number of DS18B20 devices that were + * found on the bus by ds18b20_init(). + * + * @return number of DS18B20's that were found on the bus + */ + unsigned int ds18b20_devices_found(const ds18b20_context dev); - /** - * Get the current temperature. ds18b20_update() must have been - * called prior to calling this method. - * - * @param index The device index to access (starts at 0). - * @return The last temperature reading in Celsius. - */ - float ds18b20_get_temperature(const ds18b20_context dev, - unsigned int index); - - /** - * Set the device resolution for a device. These devices support - * 9, 10, 11, and 12 bits of resolution, with the default from the - * factory at 12 bits. - * - * @param index The device index to access (starts at 0). - * @param res One of the DS18B20_RESOLUTIONS_T values - */ - void ds18b20_set_resolution(const ds18b20_context dev, unsigned int index, - DS18B20_RESOLUTIONS_T res); - - /** - * Copy the device's scratchpad memory to the EEPROM. This - * includes the configuration byte (resolution). - * - * @param index The device index to access (starts at 0). - */ - void ds18b20_copy_scratchpad(const ds18b20_context dev, unsigned int index); - - /** - * Copy the device's EEPROM memory to the scratchpad. This method - * will return when the copy completes. This operation is - * performed by the device automatically on power up, so it is - * rarely needed. - * - * @param index The device index to access (starts at 0). - */ - void ds18b20_recall_eeprom(const ds18b20_context dev, unsigned int index); - - /** - * This method will return the number of DS18B20 devices that were - * found on the bus by ds18b20_init(). - * - * @return number of DS18B20's that were found on the bus - */ - int ds18b20_devices_found(const ds18b20_context dev); - - /** - * Return an 8 byte string representing the unique device ID (1-wire - * romcode) for a given device index. The pointer returned is - * statically allocated and will be overwritten on each call. - * - * @param index The device index to access (starts at 0). - * @return pointer to 8 byte DS18B20_ROMCODE_T representing the 1-wire - * device's unique romcode, or NULL on error. - */ - const uint8_t *get_id(const ds18b20_context dev, unsigned int index); + /** + * Return an 8 byte string representing the unique device ID (1-wire + * romcode) for a given device index. The pointer returned is + * statically allocated and will be overwritten on each call. + * + * @param index The device index to access (starts at 0). + * @return pointer to 8 byte DS18B20_ROMCODE_T representing the 1-wire + * device's unique romcode, or NULL on error. + */ + const uint8_t *ds18b20_get_id(const ds18b20_context dev, + unsigned int index); #ifdef __cplusplus } diff --git a/src/ds18b20/ds18b20.hpp b/src/ds18b20/ds18b20.hpp index 978016c3..a7e5dfc3 100644 --- a/src/ds18b20/ds18b20.hpp +++ b/src/ds18b20/ds18b20.hpp @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -34,6 +34,8 @@ #include #include +#include + #define DS18B20_DEFAULT_UART 0 namespace upm { @@ -112,158 +114,103 @@ namespace upm { class DS18B20 { public: - // The family code for these devices. We handle all of them that - // are found on the bus. - static const uint8_t DS18B20_FAMILY_CODE = 0x28; + /** + * DS18B20 object constructor + * + * 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. + * + * @param uart Default UART to use (0 or 1). Default is 0. + */ + DS18B20(int uart=DS18B20_DEFAULT_UART); - // commands - typedef enum { - CMD_CONVERT = 0x44, // start a temp conversion - CMD_WRITE_SCRATCHPAD = 0x4e, - CMD_READ_SCRATCHPAD = 0xbe, - CMD_COPY_SCRATCHPAD = 0x48, // copy scratchpad to EEPROM - CMD_RECALL_EEPROM = 0xb8, // copy EEPROM to scratchpad - CMD_READ_POWER_SUPPLY = 0xb4 // parasitically powered? - } CMD_T; + /** + * DS18B20 object destructor + */ + ~DS18B20(); - // config register (scratchpad[4]) - typedef enum { - CFG_RESOLUTION_R0 = 0x20, - CFG_RESOLUTION_R1 = 0x40, - _CFG_RESOLUTION_MASK = 3, - _CFG_RESOLUTION_SHIFT = 5 + /** + * @deprecated This method is deprecated. It's functionality is + * handled in the constructor now. + */ + void init(); - // all other bits reserved and non-writable - } CFG_BITS_T; + /** + * Update our stored temperature for a device. This method must + * be called prior to getTemperature(). + * + * @param index The device index to access (starts at 0). Specify + * -1 to query all detected devices. Default: -1 + */ + void update(int index=-1); - typedef enum { - RESOLUTION_9BITS = 0, // 93.75ms (tconv/8) - RESOLUTION_10BITS = 1, // 187.5 (tconv/4) - RESOLUTION_11BITS = 2, // 375ms (tconv/2) - RESOLUTION_12BITS = 3 // 750ms (tconv) - } RESOLUTIONS_T; + /** + * Get the current temperature. update() must have been called + * prior to calling this method. + * + * @param index The device index to access (starts at 0). + * @param fahrenheit true to return the temperature in degrees + * fahrenheit, false to return the temperature in degrees celsius. + * The default is false (degrees Celsius). + * @return The last temperature reading in Celsius or Fahrenheit + */ + float getTemperature(unsigned int index, bool fahrenheit=false); - /** - * DS18B20 object constructor - * - * @param uart Default UART to use (0 or 1). Default is 0. - */ - DS18B20(int uart=DS18B20_DEFAULT_UART); + /** + * Set the device resolution for a device. These devices support + * 9, 10, 11, and 12 bits of resolution, with the default from the + * factory at 12 bits. + * + * @param index The device index to access (starts at 0). + * @param res One of the RESOLUTIONS_T values + */ + void setResolution(unsigned int index, DS18B20_RESOLUTIONS_T res); - /** - * DS18B20 object destructor - */ - ~DS18B20(); + /** + * Copy the device's scratchpad memory to the EEPROM. This + * includes the configuration byte (resolution). + * + * @param index The device index to access (starts at 0). + */ + void copyScratchPad(unsigned int index); - /** - * 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. This method must be executed first - * before any others below. - */ - void init(); + /** + * Copy the device's EEPROM memory to the scratchpad. This method + * will return when the copy completes. This operation is + * performed by the device automatically on power up, so it is + * rarely needed. + * + * @param index The device index to access (starts at 0). + */ + void recallEEPROM(unsigned int index); - /** - * Update our stored temperature for a device. This method must - * be called prior to getTemperature(). - * - * @param index The device index to access (starts at 0). Specify - * -1 to query all detected devices. Default: -1 - */ - void update(int index=-1); + /** + * This method will return the number of DS18B20 devices that were + * found on the bus by init(). + * + * @return number of DS18B20's that were found on the bus + */ + int devicesFound() + { + return ds18b20_devices_found(m_ds18b20); + } - /** - * Get the current temperature. update() must have been called - * prior to calling this method. - * - * @param index The device index to access (starts at 0). - * @param fahrenheit true to return the temperature in degrees - * fahrenheit, false to return the temperature in degrees celsius. - * The default is false (degrees Celsius). - * @return The last temperature reading in Celsius or Fahrenheit - */ - float getTemperature(int index, bool fahrenheit=false); - - /** - * Set the device resolution for a device. These devices support - * 9, 10, 11, and 12 bits of resolution, with the default from the - * factory at 12 bits. - * - * @param index The device index to access (starts at 0). - * @param res One of the RESOLUTIONS_T values - */ - void setResolution(int index, RESOLUTIONS_T res); - - /** - * Copy the device's scratchpad memory to the EEPROM. This - * includes the configuration byte (resolution). - * - * @param index The device index to access (starts at 0). - */ - void copyScratchPad(int index); - - /** - * Copy the device's EEPROM memory to the scratchpad. This method - * will return when the copy completes. This operation is - * performed by the device automatically on power up, so it is - * rarely needed. - * - * @param index The device index to access (starts at 0). - */ - void recallEEPROM(int index); - - /** - * This method will return the number of DS18B20 devices that were - * found on the bus by init(). - * - * @return number of DS18B20's that were found on the bus - */ - int devicesFound() - { - return m_devicesFound; - } - - /** - * Return an 8 byte string representing the unique device ID - * (1-wire romcode) for a given device index. - * - * @param index The device index to access (starts at 0). - * @return 8 byte string representing the 1-wire device's unique - * romcode. - */ - std::string getId(int index) - { - if (index < 0 || index >= m_devicesFound) - { - throw std::out_of_range(std::string(__FUNCTION__) + - ": device index out of range"); - } - return m_deviceMap[index].id; - } + /** + * Return an 8 byte string representing the unique device ID + * (1-wire romcode) for a given device index. + * + * @param index The device index to access (starts at 0). + * @return 8 byte string representing the 1-wire device's unique + * romcode. + */ + std::string getId(unsigned int index); protected: - mraa::UartOW m_uart; - - // the total number of devices found - int m_devicesFound; - - // this struct will generate SWIG warnings on build, but as it's not - // exposed outside the class, they can be safely ignored - - // data we need to store for each sensor we are dealing with - typedef struct { - std::string id; // 8-byte romcode id - float temperature; - RESOLUTIONS_T resolution; - } sensor_info_t; - - std::map m_deviceMap; + ds18b20_context m_ds18b20; private: - // internal utility function to read temperature from a single - // device - float readSingleTemp(int index); }; } diff --git a/src/ds18b20/ds18b20_defs.h b/src/ds18b20/ds18b20_defs.h new file mode 100644 index 00000000..b7ba3337 --- /dev/null +++ b/src/ds18b20/ds18b20_defs.h @@ -0,0 +1,63 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 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 + +#ifdef __cplusplus +extern "C" { +#endif + +// The family code for these devices. We handle all of them that +// are found on the bus. +#define DS18B20_FAMILY_CODE 0x28 + + // commands + typedef enum { + DS18B20_CMD_CONVERT = 0x44, // start a temp conversion + DS18B20_CMD_WRITE_SCRATCHPAD = 0x4e, + DS18B20_CMD_READ_SCRATCHPAD = 0xbe, + DS18B20_CMD_COPY_SCRATCHPAD = 0x48, // copy scratchpad to EEPROM + DS18B20_CMD_RECALL_EEPROM = 0xb8, // copy EEPROM to scratchpad + DS18B20_CMD_READ_POWER_SUPPLY = 0xb4 // parasitically powered? + } DS18B20_CMD_T; + + // config register (scratchpad[4]) + typedef enum { + DS18B20_CFG_RESOLUTION_R0 = 0x20, + DS18B20_CFG_RESOLUTION_R1 = 0x40, + _DS18B20_CFG_RESOLUTION_MASK = 3, + _DS18B20_CFG_RESOLUTION_SHIFT = 5 + + // all other bits reserved and non-writable + } DS18B20_CFG_BITS_T; + + typedef enum { + DS18B20_RESOLUTION_9BITS = 0, // 93.75ms (tconv/8) + DS18B20_RESOLUTION_10BITS = 1, // 187.5 (tconv/4) + DS18B20_RESOLUTION_11BITS = 2, // 375ms (tconv/2) + DS18B20_RESOLUTION_12BITS = 3 // 750ms (tconv) + } DS18B20_RESOLUTIONS_T; + +#ifdef __cplusplus +} +#endif diff --git a/src/ds18b20/ds18b20_fti.c b/src/ds18b20/ds18b20_fti.c new file mode 100644 index 00000000..f7d89611 --- /dev/null +++ b/src/ds18b20/ds18b20_fti.c @@ -0,0 +1,120 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 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 "ds18b20.h" + +#include +#include + +#include "upm_fti.h" +#include "upm_sensor.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_ds18b20_name[] = "DS18B20"; +const char upm_ds18b20_description[] = "DS18B20 DS 1-wire Temperature Sensor"; +const upm_protocol_t upm_ds18b20_protocol[] = {UPM_UART}; +const upm_sensor_t upm_ds18b20_category[] = {UPM_TEMPERATURE}; + +// forward declarations +const upm_sensor_descriptor_t upm_ds18b20_get_descriptor(); +const void* upm_ds18b20_get_ft(upm_sensor_t sensor_type); +upm_result_t upm_ds18b20_get_value(void* dev, float* tempval, + upm_temperature_u unit); +void* upm_ds18b20_init_name(); +void upm_ds18b20_close(void* dev); + +const upm_sensor_descriptor_t upm_ds18b20_get_descriptor() +{ + upm_sensor_descriptor_t usd; + usd.name = upm_ds18b20_name; + usd.description = upm_ds18b20_description; + usd.protocol_size = 1; + usd.protocol = upm_ds18b20_protocol; + usd.category_size = 1; + usd.category = upm_ds18b20_category; + return usd; +} + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = &upm_ds18b20_init_name, + .upm_sensor_close = &upm_ds18b20_close, + .upm_sensor_get_descriptor = &upm_ds18b20_get_descriptor +}; + +static const upm_temperature_ft tft = +{ + .upm_temperature_get_value = &upm_ds18b20_get_value, +}; + +const void* upm_ds18b20_get_ft(upm_sensor_t sensor_type) +{ + if (sensor_type == UPM_SENSOR) + return &ft; + + if (sensor_type == UPM_TEMPERATURE) + return &tft; + + return NULL; +} + +void* upm_ds18b20_init_name() +{ + return NULL; +} + +void upm_ds18b20_close(void* dev) +{ + ds18b20_close((ds18b20_context)dev); +} + +// FTI/temp has no way to indicate devices on a bus, so we always use +// index 0 (the first detected device) for all queries. +upm_result_t upm_ds18b20_get_value(void* dev, float* tempval, + upm_temperature_u unit) +{ + ds18b20_update((ds18b20_context)dev, 0); + // always returned in C + float temp = ds18b20_get_temperature((ds18b20_context)dev, 0); + + switch (unit) + { + case CELSIUS: + *tempval = temp; + return UPM_SUCCESS; + + case KELVIN: + *tempval = temp + 273.15; + return UPM_SUCCESS; + + case FAHRENHEIT: + *tempval = temp * (9.0/5.0) + 32.0; + return UPM_SUCCESS; + } + + return UPM_SUCCESS; +} diff --git a/src/ds18b20/javaupm_ds18b20.i b/src/ds18b20/javaupm_ds18b20.i index 918f6135..170bc2c2 100644 --- a/src/ds18b20/javaupm_ds18b20.i +++ b/src/ds18b20/javaupm_ds18b20.i @@ -3,11 +3,12 @@ %include "carrays.i" %include "std_string.i" +%include "ds18b20_defs.h" +%include "ds18b20.hpp" %{ #include "ds18b20.hpp" %} -%include "ds18b20.hpp" %array_class(char, charArray); %pragma(java) jniclasscode=%{ diff --git a/src/ds18b20/jsupm_ds18b20.i b/src/ds18b20/jsupm_ds18b20.i index 8f882b6b..64d57345 100644 --- a/src/ds18b20/jsupm_ds18b20.i +++ b/src/ds18b20/jsupm_ds18b20.i @@ -3,9 +3,10 @@ %include "carrays.i" %include "std_string.i" +%include "ds18b20_defs.h" +%include "ds18b20.hpp" %{ #include "ds18b20.hpp" %} -%include "ds18b20.hpp" %array_class(char, charArray); diff --git a/src/ds18b20/pyupm_ds18b20.i b/src/ds18b20/pyupm_ds18b20.i index b0f019e5..d8803a5d 100644 --- a/src/ds18b20/pyupm_ds18b20.i +++ b/src/ds18b20/pyupm_ds18b20.i @@ -8,6 +8,8 @@ %feature("autodoc", "3"); +%include "ds18b20_defs.h" +%include "ds18b20.hpp" %{ #include "ds18b20.hpp" %}