Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS2480B.cpp Source File

DS2480B.cpp

00001 /*******************************************************************************
00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a
00005 * copy of this software and associated documentation files (the "Software"),
00006 * to deal in the Software without restriction, including without limitation
00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 * and/or sell copies of the Software, and to permit persons to whom the
00009 * Software is furnished to do so, subject to the following conditions:
00010 *
00011 * The above copyright notice and this permission notice shall be included
00012 * in all copies or substantial portions of the Software.
00013 *
00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 * OTHER DEALINGS IN THE SOFTWARE.
00021 *
00022 * Except as contained in this notice, the name of Maxim Integrated
00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 * Products, Inc. Branding Policy.
00025 *
00026 * The mere transfer of this software does not imply any licenses
00027 * of trade secrets, proprietary technology, copyrights, patents,
00028 * trademarks, maskwork rights, or any other form of intellectual
00029 * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 * ownership rights.
00031 *******************************************************************************/
00032 
00033 #include <MaximInterfaceCore/Error.hpp>
00034 #include "DS2480B.hpp"
00035 
00036 #define TRY MaximInterfaceCore_TRY
00037 #define TRY_VALUE MaximInterfaceCore_TRY_VALUE
00038 
00039 // Mode Commands
00040 #define MODE_DATA 0xE1
00041 #define MODE_COMMAND 0xE3
00042 #define MODE_STOP_PULSE 0xF1
00043 
00044 // Return byte value
00045 #define RB_CHIPID_MASK 0x1C
00046 #define RB_RESET_MASK 0x03
00047 #define RB_1WIRESHORT 0x00
00048 #define RB_PRESENCE 0x01
00049 #define RB_ALARMPRESENCE 0x02
00050 #define RB_NOPRESENCE 0x03
00051 
00052 #define RB_BIT_MASK 0x03
00053 #define RB_BIT_ONE 0x03
00054 #define RB_BIT_ZERO 0x00
00055 
00056 // Masks for all bit ranges
00057 #define CMD_MASK 0x80
00058 #define FUNCTSEL_MASK 0x60
00059 #define BITPOL_MASK 0x10
00060 #define SPEEDSEL_MASK 0x0C
00061 #define MODSEL_MASK 0x02
00062 #define PARMSEL_MASK 0x70
00063 #define PARMSET_MASK 0x0E
00064 
00065 // Command or config bit
00066 #define CMD_COMM 0x81
00067 #define CMD_CONFIG 0x01
00068 
00069 // Function select bits
00070 #define FUNCTSEL_BIT 0x00
00071 #define FUNCTSEL_SEARCHON 0x30
00072 #define FUNCTSEL_SEARCHOFF 0x20
00073 #define FUNCTSEL_RESET 0x40
00074 #define FUNCTSEL_CHMOD 0x60
00075 
00076 // Bit polarity/Pulse voltage bits
00077 #define BITPOL_ONE 0x10
00078 #define BITPOL_ZERO 0x00
00079 #define BITPOL_5V 0x00
00080 #define BITPOL_12V 0x10
00081 
00082 // One Wire speed bits
00083 #define SPEEDSEL_STD 0x00
00084 #define SPEEDSEL_FLEX 0x04
00085 #define SPEEDSEL_OD 0x08
00086 #define SPEEDSEL_PULSE 0x0C
00087 
00088 // Data/Command mode select bits
00089 #define MODSEL_DATA 0x00
00090 #define MODSEL_COMMAND 0x02
00091 
00092 // 5V Follow Pulse select bits
00093 #define PRIME5V_TRUE 0x02
00094 #define PRIME5V_FALSE 0x00
00095 
00096 // Parameter select bits
00097 #define PARMSEL_PARMREAD 0x00
00098 #define PARMSEL_SLEW 0x10
00099 #define PARMSEL_12VPULSE 0x20
00100 #define PARMSEL_5VPULSE 0x30
00101 #define PARMSEL_WRITE1LOW 0x40
00102 #define PARMSEL_SAMPLEOFFSET 0x50
00103 #define PARMSEL_ACTIVEPULLUPTIME 0x60
00104 #define PARMSEL_BAUDRATE 0x70
00105 
00106 // Pull down slew rate.
00107 #define PARMSET_Slew15Vus 0x00
00108 #define PARMSET_Slew2p2Vus 0x02
00109 #define PARMSET_Slew1p65Vus 0x04
00110 #define PARMSET_Slew1p37Vus 0x06
00111 #define PARMSET_Slew1p1Vus 0x08
00112 #define PARMSET_Slew0p83Vus 0x0A
00113 #define PARMSET_Slew0p7Vus 0x0C
00114 #define PARMSET_Slew0p55Vus 0x0E
00115 
00116 // 12V programming pulse time table
00117 #define PARMSET_32us 0x00
00118 #define PARMSET_64us 0x02
00119 #define PARMSET_128us 0x04
00120 #define PARMSET_256us 0x06
00121 #define PARMSET_512us 0x08
00122 #define PARMSET_1024us 0x0A
00123 #define PARMSET_2048us 0x0C
00124 #define PARMSET_infinite 0x0E
00125 
00126 // 5V strong pull up pulse time table
00127 #define PARMSET_16p4ms 0x00
00128 #define PARMSET_65p5ms 0x02
00129 #define PARMSET_131ms 0x04
00130 #define PARMSET_262ms 0x06
00131 #define PARMSET_524ms 0x08
00132 #define PARMSET_1p05s 0x0A
00133 #define PARMSET_dynamic 0x0C
00134 #define PARMSET_infinite 0x0E
00135 
00136 // Write 1 low time
00137 #define PARMSET_Write8us 0x00
00138 #define PARMSET_Write9us 0x02
00139 #define PARMSET_Write10us 0x04
00140 #define PARMSET_Write11us 0x06
00141 #define PARMSET_Write12us 0x08
00142 #define PARMSET_Write13us 0x0A
00143 #define PARMSET_Write14us 0x0C
00144 #define PARMSET_Write15us 0x0E
00145 
00146 // Data sample offset and Write 0 recovery time
00147 #define PARMSET_SampOff3us 0x00
00148 #define PARMSET_SampOff4us 0x02
00149 #define PARMSET_SampOff5us 0x04
00150 #define PARMSET_SampOff6us 0x06
00151 #define PARMSET_SampOff7us 0x08
00152 #define PARMSET_SampOff8us 0x0A
00153 #define PARMSET_SampOff9us 0x0C
00154 #define PARMSET_SampOff10us 0x0E
00155 
00156 // Active pull up on time
00157 #define PARMSET_PullUp0p0us 0x00
00158 #define PARMSET_PullUp0p5us 0x02
00159 #define PARMSET_PullUp1p0us 0x04
00160 #define PARMSET_PullUp1p5us 0x06
00161 #define PARMSET_PullUp2p0us 0x08
00162 #define PARMSET_PullUp2p5us 0x0A
00163 #define PARMSET_PullUp3p0us 0x0C
00164 #define PARMSET_PullUp3p5us 0x0E
00165 
00166 // Baud rate bits
00167 #define PARMSET_9600 0x00
00168 #define PARMSET_19200 0x02
00169 #define PARMSET_57600 0x04
00170 #define PARMSET_115200 0x06
00171 
00172 // DS2480B program voltage available
00173 #define DS2480BPROG_MASK 0x20
00174 
00175 namespace MaximInterfaceDevices {
00176 
00177 using namespace Core;
00178 
00179 Result<void> DS2480B::initialize() {
00180   level = NormalLevel;
00181   mode = MODSEL_COMMAND;
00182   speed = SPEEDSEL_STD;
00183 
00184   // Send a break to reset the DS2480B.
00185   // Switch to lower baud rate to ensure break is longer than 2 ms.
00186   Result<void> result = uart->setBaudRate(4800);
00187   if (!result) {
00188     return result;
00189   }
00190   result = uart->sendBreak();
00191   if (!result) {
00192     return result;
00193   }
00194   result = uart->setBaudRate(9600);
00195   if (!result) {
00196     return result;
00197   }
00198 
00199   // Wait for master reset.
00200   sleep->invoke(1);
00201 
00202   // Flush the read buffer.
00203   result = uart->clearReadBuffer();
00204   if (!result) {
00205     return result;
00206   }
00207 
00208   // Send the timing byte.
00209   result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD);
00210   if (!result) {
00211     return result;
00212   }
00213 
00214   // Change the DS2480 baud rate.
00215   result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200);
00216   if (!result) {
00217     return result;
00218   }
00219 
00220   // Change our baud rate.
00221   result = uart->setBaudRate(115200);
00222   if (!result) {
00223     return result;
00224   }
00225 
00226   // Verify response.
00227   uint_least8_t response;
00228   TRY_VALUE(response, uart->readByte());
00229   if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
00230       (PARMSEL_BAUDRATE | PARMSET_115200)) {
00231     return HardwareError;
00232   }
00233 
00234   // Set the SPUD time value.
00235   result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite);
00236   if (!result) {
00237     return result;
00238   }
00239 
00240   // Verify response.
00241   TRY_VALUE(response, uart->readByte());
00242   if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
00243       (PARMSEL_5VPULSE | PARMSET_infinite)) {
00244     return HardwareError;
00245   }
00246 
00247   return result;
00248 }
00249 
00250 Result<void> DS2480B::reset() {
00251   if (level != NormalLevel) {
00252     return InvalidLevelError;
00253   }
00254 
00255   uint_least8_t packet[2];
00256   int packetLen = 0;
00257 
00258   // Check for correct mode.
00259   if (mode != MODSEL_COMMAND) {
00260     mode = MODSEL_COMMAND;
00261     packet[packetLen++] = MODE_COMMAND;
00262   }
00263 
00264   // Construct the command.
00265   packet[packetLen++] = CMD_COMM | FUNCTSEL_RESET | speed;
00266 
00267   // Send the packet.
00268   TRY(uart->writeBlock(make_span(packet, packetLen)));
00269 
00270   // Read back the response.
00271   TRY_VALUE(packet[0], uart->readByte());
00272 
00273   // Make sure this byte looks like a reset byte.
00274   if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) {
00275     return ShortDetectedError;
00276   }
00277   if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) {
00278     return NoSlaveError;
00279   }
00280 
00281   return none;
00282 }
00283 
00284 Result<bool> DS2480B::touchBitSetLevel(bool sendBit, Level afterLevel) {
00285   if (level != NormalLevel) {
00286     return InvalidLevelError;
00287   }
00288 
00289   uint_least8_t packet[3];
00290   int packetLen = 0;
00291 
00292   // Check for correct mode.
00293   if (mode != MODSEL_COMMAND) {
00294     mode = MODSEL_COMMAND;
00295     packet[packetLen++] = MODE_COMMAND;
00296   }
00297 
00298   // Construct the command.
00299   packet[packetLen++] =
00300       CMD_COMM | FUNCTSEL_BIT | (sendBit ? BITPOL_ONE : BITPOL_ZERO) | speed;
00301   switch (afterLevel) {
00302   case NormalLevel:
00303     break;
00304 
00305   case StrongLevel:
00306     // Add the command to begin the pulse.
00307     packet[packetLen++] =
00308         CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
00309     break;
00310 
00311   default:
00312     return InvalidLevelError;
00313   }
00314 
00315   // Send the packet.
00316   TRY(uart->writeBlock(make_span(packet, packetLen)));
00317 
00318   // Read back the response.
00319   TRY_VALUE(packet[0], uart->readByte());
00320 
00321   // Interpret the response.
00322   if ((packet[0] & 0xE0) != 0x80) {
00323     return HardwareError;
00324   }
00325   level = afterLevel;
00326   return (packet[0] & RB_BIT_MASK) == RB_BIT_ONE;
00327 }
00328 
00329 Result<void> DS2480B::writeByteSetLevel(uint_least8_t sendByte,
00330                                         Level afterLevel) {
00331   if (level != NormalLevel) {
00332     return InvalidLevelError;
00333   }
00334 
00335   switch (afterLevel) {
00336   case NormalLevel:
00337     break;
00338 
00339   case StrongLevel:
00340     return OneWireMaster::writeByteSetLevel(sendByte, afterLevel);
00341 
00342   default:
00343     return InvalidLevelError;
00344   }
00345 
00346   uint_least8_t packet[3];
00347   int packetLen = 0;
00348 
00349   // Check for correct mode.
00350   if (mode != MODSEL_DATA) {
00351     mode = MODSEL_DATA;
00352     packet[packetLen++] = MODE_DATA;
00353   }
00354 
00355   // Add the byte to send.
00356   packet[packetLen++] = sendByte;
00357 
00358   // Check for duplication of data that looks like COMMAND mode.
00359   if (sendByte == MODE_COMMAND) {
00360     packet[packetLen++] = sendByte;
00361   }
00362 
00363   // Send the packet.
00364   TRY(uart->writeBlock(make_span(packet, packetLen)));
00365 
00366   // Read back the response.
00367   TRY_VALUE(packet[0], uart->readByte());
00368 
00369   // Interpret the response.
00370   if (packet[0] != sendByte) {
00371     return HardwareError;
00372   }
00373 
00374   return none;
00375 }
00376 
00377 Result<uint_least8_t> DS2480B::readByteSetLevel(Level afterLevel) {
00378   if (level != NormalLevel) {
00379     return InvalidLevelError;
00380   }
00381 
00382   switch (afterLevel) {
00383   case NormalLevel:
00384     break;
00385 
00386   case StrongLevel:
00387     return OneWireMaster::readByteSetLevel(afterLevel);
00388 
00389   default:
00390     return InvalidLevelError;
00391   }
00392 
00393   uint_least8_t packet[2];
00394   int packetLen = 0;
00395 
00396   // Check for correct mode.
00397   if (mode != MODSEL_DATA) {
00398     mode = MODSEL_DATA;
00399     packet[packetLen++] = MODE_DATA;
00400   }
00401 
00402   // Add the byte to send.
00403   packet[packetLen++] = 0xFF;
00404 
00405   // Send the packet.
00406   const Result<void> result = uart->writeBlock(make_span(packet, packetLen));
00407   if (!result) {
00408     return result.error();
00409   }
00410 
00411   // Read back the response.
00412   return uart->readByte();
00413 }
00414 
00415 Result<void> DS2480B::setSpeed(Speed newSpeed) {
00416   uint_least8_t newSpeedByte;
00417   switch (newSpeed) {
00418   case OverdriveSpeed:
00419     newSpeedByte = SPEEDSEL_OD;
00420     break;
00421 
00422   case StandardSpeed:
00423     newSpeedByte = SPEEDSEL_STD;
00424     break;
00425 
00426   default:
00427     return InvalidSpeedError;
00428   }
00429   if (speed == newSpeedByte) {
00430     return none;
00431   }
00432   speed = newSpeedByte;
00433 
00434   uint_least8_t packet[2];
00435   int packetLen = 0;
00436 
00437   // Check for correct mode.
00438   if (mode != MODSEL_COMMAND) {
00439     mode = MODSEL_COMMAND;
00440     packet[packetLen++] = MODE_COMMAND;
00441   }
00442 
00443   // Change DS2480 speed.
00444   packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed;
00445 
00446   // Send the packet.
00447   return uart->writeBlock(make_span(packet, packetLen));
00448 }
00449 
00450 Result<void> DS2480B::setLevel(Level newLevel) {
00451   if (level == newLevel) {
00452     return none;
00453   }
00454 
00455   uint_least8_t packet[2];
00456   int packetLen = 0;
00457 
00458   switch (newLevel) {
00459   case NormalLevel:
00460     // Stop pulse command.
00461     packet[packetLen++] = MODE_STOP_PULSE;
00462     break;
00463 
00464   case StrongLevel:
00465     // Check for correct mode.
00466     if (mode != MODSEL_COMMAND) {
00467       mode = MODSEL_COMMAND;
00468       packet[packetLen++] = MODE_COMMAND;
00469     }
00470 
00471     // Add the command to begin the pulse.
00472     packet[packetLen++] =
00473         CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
00474     break;
00475 
00476   default:
00477     return InvalidLevelError;
00478   }
00479 
00480   // Send the packet.
00481   TRY(uart->writeBlock(make_span(packet, packetLen)));
00482 
00483   if (newLevel == NormalLevel) {
00484     // Read back the response.
00485     TRY_VALUE(packet[0], uart->readByte());
00486 
00487     // Interpret the response.
00488     if ((packet[0] & 0xE0) != 0xE0) {
00489       return HardwareError;
00490     }
00491   }
00492 
00493   level = newLevel;
00494   return none;
00495 }
00496 
00497 Result<void> DS2480B::sendCommand(uint_least8_t command) {
00498   uint_least8_t packet[2];
00499   int packetLen = 0;
00500 
00501   // Check for correct mode.
00502   if (mode != MODSEL_COMMAND) {
00503     mode = MODSEL_COMMAND;
00504     packet[packetLen++] = MODE_COMMAND;
00505   }
00506 
00507   // Add command.
00508   packet[packetLen++] = command;
00509 
00510   // Send the packet.
00511   return uart->writeBlock(make_span(packet, packetLen));
00512 }
00513 
00514 const error_category & DS2480B::errorCategory() {
00515   static class : public error_category {
00516   public:
00517     virtual const char * name() const {
00518       return "MaximInterfaceDevices.DS2480B";
00519     }
00520 
00521     virtual std::string message(int condition) const {
00522       switch (condition) {
00523       case HardwareError:
00524         return "Hardware Error";
00525       }
00526       return defaultErrorMessage(condition);
00527     }
00528   } instance;
00529   return instance;
00530 }
00531 
00532 } // namespace MaximInterfaceDevices