Implementation of 1-Wire with added Alarm Search Functionality
Dependents: Max32630_One_Wire_Interface
Diff: Masters/DS2480B/DS2480B.cpp
- Revision:
- 73:2cecc1372acc
- Parent:
- 72:6892702709ee
- Child:
- 74:23be10c32fa3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Masters/DS2480B/DS2480B.cpp Thu May 12 14:38:16 2016 -0500 @@ -0,0 +1,990 @@ +/******************************************************************//** +* 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); + } +}