1-Wire® library for mbed. Complete 1-Wire library that supports our silicon masters along with a bit-bang master on the MAX32600MBED platform with one common interface for mbed. Slave support has also been included and more slaves will be added as time permits.

Dependents:   MAXREFDES131_Qt_Demo MAX32630FTHR_iButton_uSD_Logger MAX32630FTHR_DS18B20_uSD_Logger MAXREFDES130_131_Demo ... more

Superseded by MaximInterface.

Masters/DS2480B/DS2480B.cpp

Committer:
IanBenzMaxim
Date:
2016-05-13
Revision:
74:23be10c32fa3
Parent:
73:2cecc1372acc
Child:
75:8b627804927c

File content as of revision 74:23be10c32fa3:

/******************************************************************//**
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* 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 MAXIM INTEGRATED 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.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
**********************************************************************/

#include "DS2480B.h"
#include "Serial.h"
#include "Timer.h"
#include "wait_api.h"

#define WRITE_FUNCTION                 0
#define READ_FUNCTION                  1

// Mode Commands
#define MODE_DATA                      0xE1
#define MODE_COMMAND                   0xE3
#define MODE_STOP_PULSE                0xF1

// Return byte value
#define RB_CHIPID_MASK                 0x1C
#define RB_RESET_MASK                  0x03
#define RB_1WIRESHORT                  0x00
#define RB_PRESENCE                    0x01
#define RB_ALARMPRESENCE               0x02
#define RB_NOPRESENCE                  0x03

#define RB_BIT_MASK                    0x03
#define RB_BIT_ONE                     0x03
#define RB_BIT_ZERO                    0x00

// Masks for all bit ranges
#define CMD_MASK                       0x80
#define FUNCTSEL_MASK                  0x60
#define BITPOL_MASK                    0x10
#define SPEEDSEL_MASK                  0x0C
#define MODSEL_MASK                    0x02
#define PARMSEL_MASK                   0x70
#define PARMSET_MASK                   0x0E

// Command or config bit
#define CMD_COMM                       0x81
#define CMD_CONFIG                     0x01

// Function select bits
#define FUNCTSEL_BIT                   0x00
#define FUNCTSEL_SEARCHON              0x30
#define FUNCTSEL_SEARCHOFF             0x20
#define FUNCTSEL_RESET                 0x40
#define FUNCTSEL_CHMOD                 0x60

// Bit polarity/Pulse voltage bits
#define BITPOL_ONE                     0x10
#define BITPOL_ZERO                    0x00
#define BITPOL_5V                      0x00
#define BITPOL_12V                     0x10

// One Wire speed bits
#define SPEEDSEL_STD                   0x00
#define SPEEDSEL_FLEX                  0x04
#define SPEEDSEL_OD                    0x08
#define SPEEDSEL_PULSE                 0x0C

// Data/Command mode select bits
#define MODSEL_DATA                    0x00
#define MODSEL_COMMAND                 0x02

// 5V Follow Pulse select bits 
#define PRIME5V_TRUE                   0x02
#define PRIME5V_FALSE                  0x00

// Parameter select bits
#define PARMSEL_PARMREAD               0x00
#define PARMSEL_SLEW                   0x10
#define PARMSEL_12VPULSE               0x20
#define PARMSEL_5VPULSE                0x30
#define PARMSEL_WRITE1LOW              0x40
#define PARMSEL_SAMPLEOFFSET           0x50
#define PARMSEL_ACTIVEPULLUPTIME       0x60
#define PARMSEL_BAUDRATE               0x70

// Pull down slew rate.
#define PARMSET_Slew15Vus              0x00
#define PARMSET_Slew2p2Vus             0x02
#define PARMSET_Slew1p65Vus            0x04
#define PARMSET_Slew1p37Vus            0x06
#define PARMSET_Slew1p1Vus             0x08
#define PARMSET_Slew0p83Vus            0x0A
#define PARMSET_Slew0p7Vus             0x0C
#define PARMSET_Slew0p55Vus            0x0E

// 12V programming pulse time table
#define PARMSET_32us                   0x00
#define PARMSET_64us                   0x02
#define PARMSET_128us                  0x04
#define PARMSET_256us                  0x06
#define PARMSET_512us                  0x08
#define PARMSET_1024us                 0x0A
#define PARMSET_2048us                 0x0C
#define PARMSET_infinite               0x0E

// 5V strong pull up pulse time table
#define PARMSET_16p4ms                 0x00
#define PARMSET_65p5ms                 0x02
#define PARMSET_131ms                  0x04
#define PARMSET_262ms                  0x06
#define PARMSET_524ms                  0x08
#define PARMSET_1p05s                  0x0A
#define PARMSET_dynamic                0x0C
#define PARMSET_infinite               0x0E

// Write 1 low time
#define PARMSET_Write8us               0x00
#define PARMSET_Write9us               0x02
#define PARMSET_Write10us              0x04
#define PARMSET_Write11us              0x06
#define PARMSET_Write12us              0x08
#define PARMSET_Write13us              0x0A
#define PARMSET_Write14us              0x0C
#define PARMSET_Write15us              0x0E

// Data sample offset and Write 0 recovery time
#define PARMSET_SampOff3us             0x00
#define PARMSET_SampOff4us             0x02
#define PARMSET_SampOff5us             0x04
#define PARMSET_SampOff6us             0x06
#define PARMSET_SampOff7us             0x08
#define PARMSET_SampOff8us             0x0A
#define PARMSET_SampOff9us             0x0C
#define PARMSET_SampOff10us            0x0E

// Active pull up on time
#define PARMSET_PullUp0p0us            0x00
#define PARMSET_PullUp0p5us            0x02
#define PARMSET_PullUp1p0us            0x04
#define PARMSET_PullUp1p5us            0x06
#define PARMSET_PullUp2p0us            0x08
#define PARMSET_PullUp2p5us            0x0A
#define PARMSET_PullUp3p0us            0x0C
#define PARMSET_PullUp3p5us            0x0E

// Baud rate bits
#define PARMSET_9600                   0x00
#define PARMSET_19200                  0x02
#define PARMSET_57600                  0x04
#define PARMSET_115200                 0x06

// DS2480B program voltage available
#define DS2480BPROG_MASK                0x20

// mode bit flags
#define MODE_NORMAL                    0x00
#define MODE_OVERDRIVE                 0x01
#define MODE_STRONG5                   0x02
#define MODE_PROGRAM                   0x04
#define MODE_BREAK                     0x08

#define MAX_BAUD                       PARMSET_115200

using OneWire::Masters::DS2480B;
using OneWire::Masters::OneWireMaster;

//*********************************************************************
DS2480B::DS2480B(mbed::Serial &p_serial)
    :_p_serial(&p_serial), _serial_owner(false)
{
}


//*********************************************************************
DS2480B::DS2480B(PinName tx, PinName rx)
    :_p_serial(new mbed::Serial(tx, rx)), _serial_owner(true)
{
}


//*********************************************************************
DS2480B::~DS2480B()
{
    if (_serial_owner)
    {
        delete _p_serial;
    }
}


//*********************************************************************
void DS2480B::rx_callback(void)
{
    while (_p_serial->readable())
    {
        rx_buffer.buff[rx_buffer.w_idx++] = _p_serial->getc();
        rx_buffer.rx_bytes_available++;
    }

    if (rx_buffer.w_idx == rx_buffer.r_idx)
    {
        rx_buffer.wrap_error = true;
    }
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::OWInitMaster(void)
{
    _p_serial->attach(this, &DS2480B::rx_callback, mbed::Serial::RxIrq);

    rx_buffer.w_idx = 0;
    rx_buffer.r_idx = 0;
    rx_buffer.rx_bytes_available = 0;
    rx_buffer.wrap_error = false;

    _ULevel = OneWireMaster::LEVEL_NORMAL;
    _UBaud = BPS_9600;
    _UMode = MODSEL_COMMAND;
    _USpeed = OneWireMaster::SPEED_STANDARD;

    return DS2480B_Detect();
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::OWReset(void)
{
    OneWireMaster::CmdResult result;

    uint8_t readbuffer[10], sendpacket[10];
    uint8_t sendlen = 0;

    // make sure normal level
    result = OWSetLevel(OneWireMaster::LEVEL_NORMAL);
    if (result == OneWireMaster::Success)
    {
        // check for correct mode
        if (_UMode != MODSEL_COMMAND)
        {
            _UMode = MODSEL_COMMAND;
            sendpacket[sendlen++] = MODE_COMMAND;
        }

        // construct the command
        sendpacket[sendlen++] = (uint8_t)(CMD_COMM | FUNCTSEL_RESET | _USpeed);

        FlushCOM();

        // send the packet
        result = WriteCOM(sendlen, sendpacket);
        if (result == OneWireMaster::Success)
        {
            // read back the 1 byte response
            result = ReadCOM(1, readbuffer);
            if (result == OneWireMaster::Success)
            {
                // make sure this byte looks like a reset byte
                if (((readbuffer[0] & RB_RESET_MASK) == RB_PRESENCE) || ((readbuffer[0] & RB_RESET_MASK) == RB_ALARMPRESENCE))
                {
                    result = OneWireMaster::Success;
                }
                else
                {
                    result = OneWireMaster::OperationFailure;
                }
            }
        }

        if (result != OneWireMaster::Success)
        {
            // an error occured so re-sync with DS2480B
            DS2480B_Detect();
        }
    }

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::OWTouchBitSetLevel(uint8_t & sendrecvbit, OWLevel after_level)
{
    OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;

    uint8_t readbuffer[10], sendpacket[10];
    uint8_t sendlen = 0;

    // make sure normal level
    OWSetLevel(OneWireMaster::LEVEL_NORMAL);

    // check for correct mode
    if (_UMode != MODSEL_COMMAND)
    {
        _UMode = MODSEL_COMMAND;
        sendpacket[sendlen++] = MODE_COMMAND;
    }

    // construct the command
    sendpacket[sendlen] = (sendrecvbit != 0) ? BITPOL_ONE : BITPOL_ZERO;
    sendpacket[sendlen++] |= CMD_COMM | FUNCTSEL_BIT | _USpeed;

    // flush the buffers
    FlushCOM();

    // send the packet
    result = WriteCOM(sendlen, sendpacket);
    if (result == OneWireMaster::Success)
    {
        // read back the response
        result = ReadCOM(1, readbuffer);
        if (result == OneWireMaster::Success)
        {
            // interpret the response
            if (((readbuffer[0] & 0xE0) == 0x80) && ((readbuffer[0] & RB_BIT_MASK) == RB_BIT_ONE))
            {
                sendrecvbit = 1;
                result = OneWireMaster::Success;
            }
            else
            {
                sendrecvbit = 0;
                result = OneWireMaster::Success;
            }
        }
        else
        {
            result = OneWireMaster::CommunicationReadError;
        }
    }
    else
    {
        result = OneWireMaster::CommunicationWriteError;
    }

    // an error occured so re-sync with DS2480B
    if (result != OneWireMaster::Success)
    {
        DS2480B_Detect();
    }
    else
    {
        result = OWSetLevel(after_level);
    }

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::OWWriteByteSetLevel(uint8_t sendbyte, OWLevel after_level)
{
    OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;

    uint8_t readbuffer[10], sendpacket[10];
    uint8_t sendlen = 0;

    // make sure normal level
    OWSetLevel(OneWireMaster::LEVEL_NORMAL);

    // check for correct mode
    if (_UMode != MODSEL_DATA)
    {
        _UMode = MODSEL_DATA;
        sendpacket[sendlen++] = MODE_DATA;
    }

    // add the byte to send
    sendpacket[sendlen++] = sendbyte;

    // check for duplication of data that looks like COMMAND mode
    if (sendbyte == MODE_COMMAND)
    {
        sendpacket[sendlen++] = sendbyte;
    }

    // flush the buffers
    FlushCOM();

    // send the packet
    result = WriteCOM(sendlen, sendpacket);
    if (result == OneWireMaster::Success)
    {
        // read back the 1 byte response
        result = ReadCOM(1, readbuffer);
        if ((result == OneWireMaster::Success) && (readbuffer[0] == sendbyte))
        {
            result = OneWireMaster::Success;
        }
        else
        {
            result = OneWireMaster::CommunicationReadError;
        }
    }
    else
    {
        result = OneWireMaster::CommunicationWriteError;
    }

    // an error occured so re-sync with DS2480B
    if (result != OneWireMaster::Success)
    {
        DS2480B_Detect();
    }
    else
    {
        result = OWSetLevel(after_level);
    }

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::OWReadByteSetLevel(uint8_t & recvbyte, OWLevel after_level)
{
    OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;

    uint8_t readbuffer[10], sendpacket[10];
    uint8_t sendlen = 0;

    // make sure normal level
    OWSetLevel(OneWireMaster::LEVEL_NORMAL);

    // check for correct mode
    if (_UMode != MODSEL_DATA)
    {
        _UMode = MODSEL_DATA;
        sendpacket[sendlen++] = MODE_DATA;
    }

    // add the byte to send
    sendpacket[sendlen++] = 0xFF;

    // flush the buffers
    FlushCOM();

    // send the packet
    result = WriteCOM(sendlen, sendpacket);
    if (result == OneWireMaster::Success)
    {
        // read back the 1 byte response
        result = ReadCOM(1, readbuffer);
        if (result == OneWireMaster::Success)
        {
            recvbyte = readbuffer[0];
            result = OneWireMaster::Success;
        }
        else
        {
            result = OneWireMaster::CommunicationReadError;
        }
    }
    else
    {
        result = OneWireMaster::CommunicationWriteError;
    }

    // an error occured so re-sync with DS2480B
    if (result != OneWireMaster::Success)
    {
        DS2480B_Detect();
    }
    else
    {
        result = OWSetLevel(after_level);
    }

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::OWSetSpeed(OWSpeed new_speed)
{
    OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;

    //TODO

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::OWSetLevel(OWLevel new_level)
{
    OneWireMaster::CmdResult result = OneWireMaster::Success;

    uint8_t sendpacket[10], readbuffer[10];
    uint8_t sendlen = 0;

    // check if need to change level
    if (new_level != _ULevel)
    {
        // check for correct mode
        if (_UMode != MODSEL_COMMAND)
        {
            _UMode = MODSEL_COMMAND;
            sendpacket[sendlen++] = MODE_COMMAND;
        }

        // check if just putting back to normal
        if (new_level == OneWireMaster::LEVEL_NORMAL)
        {
            // stop pulse command
            sendpacket[sendlen++] = MODE_STOP_PULSE;

            // add the command to begin the pulse WITHOUT prime
            sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;

            // stop pulse command
            sendpacket[sendlen++] = MODE_STOP_PULSE;

            FlushCOM();

            // send the packet
            result = WriteCOM(sendlen, sendpacket);
            if (result == OneWireMaster::Success)
            {
                // read back the 1 byte response
                result = ReadCOM(2, readbuffer);
                if (result == OneWireMaster::Success)
                {
                    // check response byte
                    if (((readbuffer[0] & 0xE0) == 0xE0) && ((readbuffer[1] & 0xE0) == 0xE0))
                    {
                        _ULevel = OneWireMaster::LEVEL_NORMAL;
                    }
                    else
                    {
                        result = OneWireMaster::OperationFailure;
                    }
                }
            }
        }
        // set new level
        else
        {
            // set the SPUD time value
            sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite;
            // add the command to begin the pulse
            sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V;

            FlushCOM();

            // send the packet
            result = WriteCOM(sendlen, sendpacket);
            if (result == OneWireMaster::Success)
            {
                // read back the 1 byte response from setting time limit
                result = ReadCOM(1, readbuffer);
                if (result == OneWireMaster::Success)
                {
                    // check response byte
                    if ((readbuffer[0] & 0x81) == 0)
                    {
                        _ULevel = new_level;
                    }
                    else
                    {
                        result = OneWireMaster::OperationFailure;
                    }
                }
            }
        }

        // if lost communication with DS2480B then reset
        if (result != OneWireMaster::Success)
        {
            DS2480B_Detect();
        }

    }

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::DS2480B_Detect(void)
{
    OneWireMaster::CmdResult result;

    uint8_t sendpacket[10], readbuffer[10];
    uint8_t sendlen = 0;

    // reset modes
    _UMode = MODSEL_COMMAND;
    _UBaud = BPS_9600;
    _USpeed = SPEEDSEL_FLEX;

    // set the baud rate to 9600
    SetBaudCOM(_UBaud);

    // send a break to reset the DS2480B
    BreakCOM();

    // delay to let line settle
    wait_ms(2);

    FlushCOM();

    // send the timing byte
    sendpacket[0] = 0xC1;
    result = WriteCOM(1, sendpacket);
    if (result == OneWireMaster::Success)
    {
        // delay to let line settle
        wait_ms(2);

        // set the FLEX configuration parameters
        // default PDSRC = 1.37Vus
        sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus;
        // default W1LT = 10us
        sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write10us;
        // default DSO/WORT = 8us
        sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff8us;

        // construct the command to read the baud rate (to test command block)
        sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);

        // also do 1 bit operation (to test 1-Wire block)
        sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_BIT | _UBaud | BITPOL_ONE;

        FlushCOM();

        // send the packet
        result = WriteCOM(sendlen, sendpacket);
        if (result == OneWireMaster::Success)
        {
            // read back the response
            result = ReadCOM(5, readbuffer);
            if (result == OneWireMaster::Success)
            {
                // look at the baud rate and bit operation
                // to see if the response makes sense
                if (((readbuffer[3] & 0xF1) == 0x00) && ((readbuffer[3] & 0x0E) == _UBaud) && ((readbuffer[4] & 0xF0) == 0x90) && ((readbuffer[4] & 0x0C) == _UBaud))
                {
                    result = OneWireMaster::Success;
                }
                else
                {
                    result = OneWireMaster::OperationFailure;
                }
            }
        }
    }

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::DS2480B_ChangeBaud(DS2480B_BPS newbaud)
{
    OneWireMaster::CmdResult result = OneWireMaster::Success;

    uint8_t readbuffer[5], sendpacket[5], sendpacket2[5];
    uint8_t sendlen = 0, sendlen2 = 0;

    //see if diffenent then current baud rate
    if (_UBaud != newbaud)
    {
        // build the command packet
        // check for correct mode
        if (_UMode != MODSEL_COMMAND)
        {
            _UMode = MODSEL_COMMAND;
            sendpacket[sendlen++] = MODE_COMMAND;
        }
        // build the command
        sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud;

        // flush the buffers
        FlushCOM();

        // send the packet
        result = WriteCOM(sendlen, sendpacket);
        if (result == OneWireMaster::Success)
        {
            // make sure buffer is flushed
            wait_ms(5);

            // change our baud rate
            SetBaudCOM(newbaud);
            _UBaud = newbaud;

            // wait for things to settle
            wait_ms(5);

            // build a command packet to read back baud rate
            sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);

            // flush the buffers
            FlushCOM();

            // send the packet
            result = WriteCOM(sendlen2, sendpacket2);
            if (result == OneWireMaster::Success)
            {
                // read back the 1 byte response
                result = ReadCOM(1, readbuffer);
                if (result == OneWireMaster::Success)
                {
                    // verify correct baud
                    if ((readbuffer[0] & 0x0E) == (sendpacket[sendlen - 1] & 0x0E))
                    {
                        result = OneWireMaster::Success;
                    }
                    else
                    {
                        result = OneWireMaster::OperationFailure;
                    }
                }
                else
                {
                    result = OneWireMaster::CommunicationReadError;
                }
            }
            else
            {
                result = OneWireMaster::CommunicationWriteError;
            }
        }
        else
        {
            result = OneWireMaster::CommunicationWriteError;
        }
    }

    // if lost communication with DS2480B then reset
    if (result != OneWireMaster::Success)
    {
        DS2480B_Detect();
    }

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::WriteCOM(uint32_t outlen, uint8_t *outbuf)
{
    OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;

    mbed::Timer t;
    uint32_t t_val;
    uint32_t timeout;
    uint8_t idx = 0;

    //calculate timeout, the time needed to tx 1 byte
    //double for 115200 due to timer object inaccuracies
    switch (_UBaud)
    {
    case BPS_115200:
        timeout = ((1000000 / 115200) * 20);
        break;

    case BPS_57600:
        timeout = ((1000000 / 57600) * 10);
        break;

    case BPS_19200:
        timeout = ((1000000 / 19200) * 10);
        break;

    case BPS_9600:
    default:
        timeout = ((1000000 / 9600) * 10);
        break;
    }

    t.start();
    do
    {
        t.reset();
        do
        {
            t_val = t.read_us();
        } while (!_p_serial->writeable() && (t_val < timeout));

        if (t_val < timeout)
        {
            _p_serial->putc(outbuf[idx++]);
            result = OneWireMaster::Success;
        }
        else
        {
            result = OneWireMaster::TimeoutError;
        }
    } while ((idx < outlen) && (result == OneWireMaster::Success));

    return result;
}


//*********************************************************************
OneWireMaster::CmdResult DS2480B::ReadCOM(uint32_t inlen, uint8_t *inbuf)
{
    OneWireMaster::CmdResult result;
    mbed::Timer t;
    uint32_t num_bytes_read = 0;
    uint32_t timeout;
    uint32_t micro_seconds;

    //calculate timeout, 10x the time needed to recieve inlen bytes 
    //double for 115200 due to timer object inaccuracies
    switch (_UBaud)
    {
    case BPS_115200:
        timeout = ((1000000 / 115200) * 200) * inlen;
        break;

    case BPS_57600:
        timeout = ((1000000 / 57600) * 100) * inlen;
        break;

    case BPS_19200:
        timeout = ((1000000 / 19200) * 100) * inlen;
        break;

    case BPS_9600:
    default:
        timeout = ((1000000 / 9600) * 100) * inlen;
        break;
    }

    if (rx_buffer.wrap_error)
    {
        //reset rx buffer, error, and return failure
        rx_buffer.w_idx = 0;
        rx_buffer.r_idx = 0;
        rx_buffer.rx_bytes_available = 0;
        rx_buffer.wrap_error = false;

        result = OneWireMaster::OperationFailure;
    }
    else
    {
        t.start();
        t.reset();
        do
        {
            do
            {
                micro_seconds = t.read_us();
            } while (!rx_buffer.rx_bytes_available && (micro_seconds < timeout));

            if (rx_buffer.rx_bytes_available)
            {
                inbuf[num_bytes_read++] = rx_buffer.buff[rx_buffer.r_idx++];
                rx_buffer.rx_bytes_available--;
            }
        } while ((num_bytes_read < inlen) && (micro_seconds < timeout) && !rx_buffer.wrap_error);
        t.stop();

        if (num_bytes_read == inlen)
        {
            result = OneWireMaster::Success;
        }
        else if (micro_seconds > timeout)
        {
            result = OneWireMaster::TimeoutError;
        }
        else
        {
            //reset rx buffer, error, and return failure
            rx_buffer.w_idx = 0;
            rx_buffer.r_idx = 0;
            rx_buffer.rx_bytes_available = 0;
            rx_buffer.wrap_error = false;

            result = OneWireMaster::CommunicationReadError;
        }
    }

    return result;
}


//*********************************************************************
void DS2480B::BreakCOM(void)
{
    while (!_p_serial->writeable());
    //for some reason send_break wouldn't work unless first sending char
    _p_serial->putc(0);
    _p_serial->send_break();
}


void DS2480B::FlushCOM(void)
{
    //reset soft rx_buffer
    rx_buffer.w_idx = 0;
    rx_buffer.r_idx = 0;
    rx_buffer.wrap_error = false;

    //make sure hardware rx buffer is empty
    while (_p_serial->readable())
    {
        _p_serial->getc();
    }

    /*Not sure how to flush tx buffer without sending data out on the bus.
      from the example in AN192, the data shouldn't be sent, just aborted
      and the buffer cleaned out, http://pdfserv.maximintegrated.com/en/an/AN192.pdf
      Below is what was used in AN192 example code using windows drivers
    */

    //PurgeComm(ComID, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
}


//*********************************************************************
void DS2480B::SetBaudCOM(uint8_t new_baud)
{
    switch (new_baud)
    {
    case BPS_115200:
        _p_serial->baud(115200);
        break;

    case BPS_57600:
        _p_serial->baud(57600);
        break;

    case BPS_19200:
        _p_serial->baud(19200);
        break;

    case BPS_9600:
    default:
        _p_serial->baud(9600);
        break;
    }
}


//*********************************************************************
int32_t DS2480B::bitacc(uint32_t op, uint32_t state, uint32_t loc, uint8_t *buf)
{
    int nbyt, nbit;

    nbyt = (loc / 8);
    nbit = loc - (nbyt * 8);

    if (op == WRITE_FUNCTION)
    {
        if (state)
        {
            buf[nbyt] |= (0x01 << nbit);
        }
        else
        {
            buf[nbyt] &= ~(0x01 << nbit);
        }

        return 1;
    }
    else
    {
        return ((buf[nbyt] >> nbit) & 0x01);
    }
}