Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
Maxim Interface is a library framework focused on providing flexible and expressive hardware interfaces. Both communication interfaces such as I2C and 1-Wire and device interfaces such as DS18B20 are supported. Modern C++ concepts are used extensively while keeping compatibility with C++98/C++03 and requiring no external dependencies. The embedded-friendly design does not depend on exceptions or RTTI.
The full version of the project is hosted on GitLab: https://gitlab.com/iabenz/MaximInterface
Diff: Devices/DS2480B.cpp
- Revision:
- 7:9cd16581b578
- Parent:
- 6:471901a04573
- Child:
- 8:5ea891c7d1a1
--- a/Devices/DS2480B.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,559 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 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 <MaximInterface/Utilities/Error.hpp> -#include "DS2480B.hpp" - -// 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 - -namespace MaximInterface { - -error_code DS2480B::initialize() { - level = NormalLevel; - mode = MODSEL_COMMAND; - speed = SPEEDSEL_STD; - - // Send a break to reset the DS2480B. - // Switch to lower baud rate to ensure break is longer than 2 ms. - error_code result = uart->setBaudRate(4800); - if (result) { - return result; - } - result = uart->sendBreak(); - if (result) { - return result; - } - result = uart->setBaudRate(9600); - if (result) { - return result; - } - - // Wait for master reset. - sleep->invoke(1); - - // Flush the read buffer. - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // Send the timing byte. - result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD); - if (result) { - return result; - } - - // Change the DS2480 baud rate. - result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200); - if (result) { - return result; - } - - // Change our baud rate. - result = uart->setBaudRate(115200); - if (result) { - return result; - } - - uint_least8_t response; - - // Verify response. - result = uart->readByte(response); - if (result) { - return result; - } - if ((response & (PARMSEL_MASK | PARMSET_MASK)) != - (PARMSEL_BAUDRATE | PARMSET_115200)) { - return make_error_code(HardwareError); - } - - // Set the SPUD time value. - result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite); - if (result) { - return result; - } - - // Verify response. - result = uart->readByte(response); - if (result) { - return result; - } - if ((response & (PARMSEL_MASK | PARMSET_MASK)) != - (PARMSEL_5VPULSE | PARMSET_infinite)) { - return make_error_code(HardwareError); - } - - return result; -} - -error_code DS2480B::reset() { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Construct the command. - packet[packetLen++] = CMD_COMM | FUNCTSEL_RESET | speed; - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Make sure this byte looks like a reset byte. - if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) { - result = make_error_code(ShortDetectedError); - } else if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) { - result = make_error_code(NoSlaveError); - } - return result; -} - -error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[3]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Construct the command. - packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT | - (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed; - switch (afterLevel) { - case NormalLevel: - break; - - case StrongLevel: - // Add the command to begin the pulse. - packet[packetLen++] = - CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; - break; - - default: - return make_error_code(InvalidLevelError); - } - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Interpret the response. - if ((packet[0] & 0xE0) == 0x80) { - sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE); - level = afterLevel; - } else { - result = make_error_code(HardwareError); - } - return result; -} - -error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - switch (afterLevel) { - case NormalLevel: - break; - - case StrongLevel: - return OneWireMaster::writeByteSetLevel(sendByte, afterLevel); - - default: - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[3]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_DATA) { - mode = MODSEL_DATA; - packet[packetLen++] = MODE_DATA; - } - - // Add the byte to send. - packet[packetLen++] = sendByte; - - // Check for duplication of data that looks like COMMAND mode. - if (sendByte == MODE_COMMAND) { - packet[packetLen++] = sendByte; - } - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Interpret the response. - if (packet[0] != sendByte) { - result = make_error_code(HardwareError); - } - return result; -} - -error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - switch (afterLevel) { - case NormalLevel: - break; - - case StrongLevel: - return OneWireMaster::readByteSetLevel(recvByte, afterLevel); - - default: - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_DATA) { - mode = MODSEL_DATA; - packet[packetLen++] = MODE_DATA; - } - - // Add the byte to send. - packet[packetLen++] = 0xFF; - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(recvByte); - return result; -} - -error_code DS2480B::setSpeed(Speed newSpeed) { - uint_least8_t newSpeedByte; - switch (newSpeed) { - case OverdriveSpeed: - newSpeedByte = SPEEDSEL_OD; - break; - - case StandardSpeed: - newSpeedByte = SPEEDSEL_STD; - break; - - default: - return make_error_code(InvalidSpeedError); - } - if (speed == newSpeedByte) { - return error_code(); - } - speed = newSpeedByte; - - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Change DS2480 speed. - packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed; - - // Send the packet. - return uart->writeBlock(make_span(packet, packetLen)); -} - -error_code DS2480B::setLevel(Level newLevel) { - if (level == newLevel) { - return error_code(); - } - - uint_least8_t packet[2]; - int packetLen = 0; - - switch (newLevel) { - case NormalLevel: - // Stop pulse command. - packet[packetLen++] = MODE_STOP_PULSE; - break; - - case StrongLevel: - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Add the command to begin the pulse. - packet[packetLen++] = - CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; - break; - - default: - return make_error_code(InvalidLevelError); - } - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - if (newLevel == NormalLevel) { - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Interpret the response. - if ((packet[0] & 0xE0) != 0xE0) { - return make_error_code(HardwareError); - } - } - - level = newLevel; - return result; -} - -error_code DS2480B::sendCommand(uint_least8_t command) { - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Add command. - packet[packetLen++] = command; - - // Send the packet. - return uart->writeBlock(make_span(packet, packetLen)); -} - -const error_category & DS2480B::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS2480B"; } - - virtual std::string message(int condition) const { - switch (condition) { - case HardwareError: - return "Hardware Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace MaximInterface