Dallas 1-wire driver with DS18B20 temperature sensor support; custom bus driver to work with https://emir.googlecode.com/svn/emir2/trunk/eagle/emir-shield.sch

Dependents:   testing_RTC_OneWire EMIRv2

Files at this revision

API Documentation at this revision

Comitter:
alpov
Date:
Mon Apr 28 06:52:49 2014 +0000
Commit message:
initial version, working

Changed in this revision

1wire.cpp Show annotated file Show diff for this revision Revisions of this file
1wire.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/1wire.cpp	Mon Apr 28 06:52:49 2014 +0000
@@ -0,0 +1,257 @@
+#include "mbed.h"
+#include "1wire.h"
+
+OneWire::OneWire(PinName OwUp, PinName OwDn, PinName OwIn) : _OwUp(OwUp, !0), _OwDn(OwDn, !1), _OwIn(OwIn, PullNone)
+{
+}
+
+int OneWire::Reset(void)
+{
+    int result;
+    
+    DELAY_G();
+    __disable_irq();
+    _OwDn = !0;
+    DELAY_H();
+    _OwDn = !1;
+    DELAY_I();
+    result = _OwIn;
+    __enable_irq();
+    DELAY_J();
+    return result;
+}
+
+void OneWire::WriteBit(int bit)
+{
+    __disable_irq();
+    if (bit) {
+        _OwDn = !0;
+        DELAY_A();
+        _OwDn = !1;
+        DELAY_B();
+    } else {
+        _OwDn = !0;
+        DELAY_C();
+        _OwDn = !1;
+        DELAY_D();
+    }
+    __enable_irq();
+}
+
+int OneWire::ReadBit(void)
+{
+    int result;
+
+    __disable_irq();
+    _OwDn = !0;
+    DELAY_A();
+    _OwDn = !1;
+    DELAY_E();
+    result = _OwIn;
+    __enable_irq();
+    DELAY_F();
+    return result;
+}
+
+void OneWire::WriteByte(uint8_t data)
+{
+    for (int i = 0; i < 8; i++) {
+        WriteBit(data & 0x01);
+        data >>= 1;
+    }
+}
+
+uint8_t OneWire::ReadByte(void)
+{
+    uint8_t result = 0;
+    
+    for (int i = 0; i < 8; i++) {
+        result >>= 1;
+        if (ReadBit())
+            result |= 0x80;
+    }
+    return result;
+}
+
+void OneWire::SendCmd(uint8_t *ROMID, uint8_t cmd)
+{
+    Reset();
+    if (ROMID == NULL) {
+        WriteByte(OW_SKIP_ROM_CMD);
+    } else {
+        WriteByte(OW_MATCH_ROM_CMD);
+        for (int i = 0; i < 8; i++)
+            WriteByte(ROMID[i]);
+    }
+    WriteByte(cmd);
+}
+
+int OneWire::First(uint8_t *ROMID)
+{
+    /* Reset state */
+    OW_LastDiscrepancy = 0;
+    OW_LastDevice = 0;
+    OW_LastFamilyDiscrepancy = 0;
+    
+    /* Go looking */
+    return Next(ROMID);
+}
+
+int OneWire::Next(uint8_t *ROMID)
+{
+    uint8_t bit_test, search_direction, bit_number;
+    uint8_t last_zero, rom_byte_number, rom_byte_mask;
+    uint8_t lastcrc8, crcaccum;
+    int next_result;
+
+    /* Init for search */
+    bit_number = 1;
+    last_zero = 0;
+    rom_byte_number = 0;
+    rom_byte_mask = 1;
+    next_result = OW_NOMODULES;
+    lastcrc8 = 0;
+    crcaccum = 0;
+    
+    /* if the last call was not the last one */
+    if (!OW_LastDevice) {
+        /* reset the 1-wire if there are no parts on 1-wire, return 0 */
+        if (Reset()) {
+            /* reset the search */
+            OW_LastDiscrepancy = 0;
+            OW_LastFamilyDiscrepancy = 0;
+            return OW_NOPRESENCE;
+        }
+        
+        WriteByte(OW_SEARCH_ROM_CMD); /* issue the search command */
+        
+        /* pause before beginning the search - removed */
+        /* loop to do the search */
+        do {
+            /* read a bit and its compliment */
+            bit_test = ReadBit() << 1;
+            bit_test |= ReadBit();
+            
+            /* check for no devices on 1-wire */
+            if (bit_test == 3) {
+                return(OW_BADWIRE);
+            } else {
+                /* all devices coupled have 0 or 1 */
+                if (bit_test > 0)
+                    search_direction = !(bit_test & 0x01);  /* bit write value for search */
+                else {
+                    /* if this discrepancy is before the Last Discrepancy
+                     * on a previous OWNext then pick the same as last time */
+                    if (bit_number < OW_LastDiscrepancy)
+                        search_direction = ((ROMID[rom_byte_number] & rom_byte_mask) > 0);
+                    else
+                        /* if equal to last pick 1, if not then pick 0 */
+                        search_direction = (bit_number == OW_LastDiscrepancy);
+                    
+                    /* if 0 was picked then record its position in LastZero */
+                    if (search_direction == 0) {
+                        last_zero = bit_number;
+                        /* check for Last discrepancy in family */
+                        if (last_zero < 9)
+                            OW_LastFamilyDiscrepancy = last_zero;
+                    }
+                }
+                
+                /* set or clear the bit in the ROM byte rom_byte_number
+                 * with mask rom_byte_mask */
+                if (search_direction == 1)
+                    ROMID[rom_byte_number] |= rom_byte_mask;
+                else
+                    ROMID[rom_byte_number] &= ~rom_byte_mask;
+                
+                /* serial number search direction write bit */
+                WriteBit(search_direction);
+                
+                /* increment the byte counter bit_number
+                 * and shift the mask rom_byte_mask */
+                bit_number++;
+                rom_byte_mask <<= 1;
+                
+                /* if the mask is 0 then go to new ROM byte rom_byte_number
+                 * and reset mask */
+                if (rom_byte_mask == 0) {
+                    CRC(ROMID[rom_byte_number], &crcaccum);  /* accumulate the CRC */
+                    lastcrc8 = crcaccum;
+                    
+                    rom_byte_number++;
+                    rom_byte_mask = 1;
+                }
+            }
+        } while (rom_byte_number < 8);  /* loop until through all ROM bytes 0-7 */
+        
+        /* if the search was successful then */
+        if (!(bit_number < 65) || lastcrc8) {
+            if (lastcrc8) {
+                next_result = OW_BADCRC;
+            } else {
+                /*  search successful so set LastDiscrepancy,LastDevice,next_result */
+                OW_LastDiscrepancy = last_zero;
+                OW_LastDevice = (OW_LastDiscrepancy == 0);
+                next_result = OW_FOUND;
+            }
+        }
+    }
+    
+    /* if no device found then reset counters so next 'next' will be like a first */
+    if (next_result != OW_FOUND || ROMID[0] == 0) {
+        OW_LastDiscrepancy = 0;
+        OW_LastDevice = 0;
+        OW_LastFamilyDiscrepancy = 0;
+    }
+    
+    if (next_result == OW_FOUND && ROMID[0] == 0x00)
+        next_result = OW_BADWIRE;
+    
+    return next_result;
+}
+
+void OneWire::CRC(uint8_t x, uint8_t *crc)
+{
+    for (int j = 0; j < 8; j++) {
+        uint8_t mix = (*crc ^ x) & 0x01;
+        *crc >>= 1;
+        if (mix) *crc ^= 0x8C;
+        x >>= 1;
+    }
+}
+
+void OneWire::ConvertAll(bool wait)
+{
+    SendCmd(NULL, OW_CONVERT_T_CMD);
+    if (wait) {
+        _OwUp = !1;
+        wait_ms(CONVERT_T_DELAY);
+        _OwUp = !0;
+    }
+}
+
+int OneWire::ReadTemperature(uint8_t *ROMID, int *result)
+{       
+    uint8_t crc = 0, buf[8];
+    
+    SendCmd(ROMID, OW_RD_SCR_CMD);
+    for (int i = 0; i < 8; i++) {
+        buf[i] = ReadByte();
+        CRC(buf[i], &crc);
+    }
+    if (crc != ReadByte()) {
+        return ERR_BADCRC;
+    }
+
+    switch (ROMID[0]) {
+        case 0x10: // ds18s20
+            *result = (signed char)((buf[1] & 0x80) | (buf[0] >> 1)) * 100 + 75 - buf[6] * 100 / 16;
+            break;
+        case 0x28: // ds18b20
+            *result = (signed char)((buf[1] << 4) | (buf[0] >> 4)) * 100 + (buf[0] & 0x0F) * 100 / 16;
+            break;
+        default:
+            return ERR_BADFAMILY;
+    }
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/1wire.h	Mon Apr 28 06:52:49 2014 +0000
@@ -0,0 +1,94 @@
+#ifndef _1WIRE_H
+#define _1WIRE_H
+
+/* Dallas 1-wire driver with DS18B20 temperature sensor support
+ *
+ * Copyright (c) 2014 Ales Povalac, 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.
+ */
+
+class OneWire
+{
+public:
+    OneWire(PinName OwUp, PinName OwDn, PinName OwIn);
+
+    void ConvertAll(bool wait);
+    int ReadTemperature(uint8_t *ROMID, int *result);
+    
+    int First(uint8_t *ROMID);
+    int Next(uint8_t *ROMID);
+
+    void WriteByte(uint8_t data);
+    uint8_t ReadByte(void);
+    void SendCmd(uint8_t *ROMID, uint8_t cmd);
+    void CRC(uint8_t x, uint8_t *crc);
+    
+private:
+    DigitalOut _OwUp;
+    DigitalOut _OwDn;
+    DigitalIn _OwIn;
+
+    uint8_t OW_LastDevice;
+    uint8_t OW_LastDiscrepancy;
+    uint8_t OW_LastFamilyDiscrepancy;
+
+    int Reset(void);
+    void WriteBit(int bit);
+    int ReadBit(void);
+};
+        
+
+/* INTERNAL CONSTANTS everything below this line */
+
+#define ERR_BADCRC      0x8000
+#define ERR_BADFAMILY   0x8001
+
+/* Return codes for OWFirst()/OWNext() */
+#define OW_BADWIRE      -3
+#define OW_BADCRC       -2
+#define OW_NOPRESENCE   -1
+#define OW_NOMODULES    0
+#define OW_FOUND        1
+
+/* General 1 wire commands */
+#define OW_SEARCH_ROM_CMD   0xF0
+#define OW_READ_ROM_CMD     0x33
+#define OW_MATCH_ROM_CMD    0x55
+#define OW_SKIP_ROM_CMD     0xCC
+
+/* DS1820 commands */
+#define OW_CONVERT_T_CMD    0x44
+#define OW_RD_SCR_CMD       0xBE
+#define OW_WR_SCR_CMD       0x4E
+
+
+/* 1-wire delays */
+#define DELAY_A() wait_us(6)
+#define DELAY_B() wait_us(64)
+#define DELAY_C() wait_us(60)
+#define DELAY_D() wait_us(10)
+#define DELAY_E() wait_us(9)
+#define DELAY_F() wait_us(55)
+#define DELAY_G()
+#define DELAY_H() wait_us(480)
+#define DELAY_I() wait_us(70) 
+#define DELAY_J() wait_us(410)
+
+/* Other */
+#define CONVERT_T_DELAY 750
+
+#endif