Aleksandrs Gumenuks / MaximInterface_Extended

Dependents:   mbed_DS28EC20_GPIO

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS2480B.cpp Source File

DS2480B.cpp

00001 /*******************************************************************************
00002 * Copyright (C) 2017 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 <MaximInterface/Utilities/Error.hpp>
00034 #include "DS2480B.hpp"
00035 
00036 // Mode Commands
00037 #define MODE_DATA 0xE1
00038 #define MODE_COMMAND 0xE3
00039 #define MODE_STOP_PULSE 0xF1
00040 
00041 // Return byte value
00042 #define RB_CHIPID_MASK 0x1C
00043 #define RB_RESET_MASK 0x03
00044 #define RB_1WIRESHORT 0x00
00045 #define RB_PRESENCE 0x01
00046 #define RB_ALARMPRESENCE 0x02
00047 #define RB_NOPRESENCE 0x03
00048 
00049 #define RB_BIT_MASK 0x03
00050 #define RB_BIT_ONE 0x03
00051 #define RB_BIT_ZERO 0x00
00052 
00053 // Masks for all bit ranges
00054 #define CMD_MASK 0x80
00055 #define FUNCTSEL_MASK 0x60
00056 #define BITPOL_MASK 0x10
00057 #define SPEEDSEL_MASK 0x0C
00058 #define MODSEL_MASK 0x02
00059 #define PARMSEL_MASK 0x70
00060 #define PARMSET_MASK 0x0E
00061 
00062 // Command or config bit
00063 #define CMD_COMM 0x81
00064 #define CMD_CONFIG 0x01
00065 
00066 // Function select bits
00067 #define FUNCTSEL_BIT 0x00
00068 #define FUNCTSEL_SEARCHON 0x30
00069 #define FUNCTSEL_SEARCHOFF 0x20
00070 #define FUNCTSEL_RESET 0x40
00071 #define FUNCTSEL_CHMOD 0x60
00072 
00073 // Bit polarity/Pulse voltage bits
00074 #define BITPOL_ONE 0x10
00075 #define BITPOL_ZERO 0x00
00076 #define BITPOL_5V 0x00
00077 #define BITPOL_12V 0x10
00078 
00079 // One Wire speed bits
00080 #define SPEEDSEL_STD 0x00
00081 #define SPEEDSEL_FLEX 0x04
00082 #define SPEEDSEL_OD 0x08
00083 #define SPEEDSEL_PULSE 0x0C
00084 
00085 // Data/Command mode select bits
00086 #define MODSEL_DATA 0x00
00087 #define MODSEL_COMMAND 0x02
00088 
00089 // 5V Follow Pulse select bits
00090 #define PRIME5V_TRUE 0x02
00091 #define PRIME5V_FALSE 0x00
00092 
00093 // Parameter select bits
00094 #define PARMSEL_PARMREAD 0x00
00095 #define PARMSEL_SLEW 0x10
00096 #define PARMSEL_12VPULSE 0x20
00097 #define PARMSEL_5VPULSE 0x30
00098 #define PARMSEL_WRITE1LOW 0x40
00099 #define PARMSEL_SAMPLEOFFSET 0x50
00100 #define PARMSEL_ACTIVEPULLUPTIME 0x60
00101 #define PARMSEL_BAUDRATE 0x70
00102 
00103 // Pull down slew rate.
00104 #define PARMSET_Slew15Vus 0x00
00105 #define PARMSET_Slew2p2Vus 0x02
00106 #define PARMSET_Slew1p65Vus 0x04
00107 #define PARMSET_Slew1p37Vus 0x06
00108 #define PARMSET_Slew1p1Vus 0x08
00109 #define PARMSET_Slew0p83Vus 0x0A
00110 #define PARMSET_Slew0p7Vus 0x0C
00111 #define PARMSET_Slew0p55Vus 0x0E
00112 
00113 // 12V programming pulse time table
00114 #define PARMSET_32us 0x00
00115 #define PARMSET_64us 0x02
00116 #define PARMSET_128us 0x04
00117 #define PARMSET_256us 0x06
00118 #define PARMSET_512us 0x08
00119 #define PARMSET_1024us 0x0A
00120 #define PARMSET_2048us 0x0C
00121 #define PARMSET_infinite 0x0E
00122 
00123 // 5V strong pull up pulse time table
00124 #define PARMSET_16p4ms 0x00
00125 #define PARMSET_65p5ms 0x02
00126 #define PARMSET_131ms 0x04
00127 #define PARMSET_262ms 0x06
00128 #define PARMSET_524ms 0x08
00129 #define PARMSET_1p05s 0x0A
00130 #define PARMSET_dynamic 0x0C
00131 #define PARMSET_infinite 0x0E
00132 
00133 // Write 1 low time
00134 #define PARMSET_Write8us 0x00
00135 #define PARMSET_Write9us 0x02
00136 #define PARMSET_Write10us 0x04
00137 #define PARMSET_Write11us 0x06
00138 #define PARMSET_Write12us 0x08
00139 #define PARMSET_Write13us 0x0A
00140 #define PARMSET_Write14us 0x0C
00141 #define PARMSET_Write15us 0x0E
00142 
00143 // Data sample offset and Write 0 recovery time
00144 #define PARMSET_SampOff3us 0x00
00145 #define PARMSET_SampOff4us 0x02
00146 #define PARMSET_SampOff5us 0x04
00147 #define PARMSET_SampOff6us 0x06
00148 #define PARMSET_SampOff7us 0x08
00149 #define PARMSET_SampOff8us 0x0A
00150 #define PARMSET_SampOff9us 0x0C
00151 #define PARMSET_SampOff10us 0x0E
00152 
00153 // Active pull up on time
00154 #define PARMSET_PullUp0p0us 0x00
00155 #define PARMSET_PullUp0p5us 0x02
00156 #define PARMSET_PullUp1p0us 0x04
00157 #define PARMSET_PullUp1p5us 0x06
00158 #define PARMSET_PullUp2p0us 0x08
00159 #define PARMSET_PullUp2p5us 0x0A
00160 #define PARMSET_PullUp3p0us 0x0C
00161 #define PARMSET_PullUp3p5us 0x0E
00162 
00163 // Baud rate bits
00164 #define PARMSET_9600 0x00
00165 #define PARMSET_19200 0x02
00166 #define PARMSET_57600 0x04
00167 #define PARMSET_115200 0x06
00168 
00169 // DS2480B program voltage available
00170 #define DS2480BPROG_MASK 0x20
00171 
00172 namespace MaximInterface {
00173 
00174 error_code DS2480B::initialize() {
00175   level = NormalLevel;
00176   mode = MODSEL_COMMAND;
00177   speed = SPEEDSEL_STD;
00178 
00179   // Send a break to reset the DS2480B.
00180   // Switch to lower baud rate to ensure break is longer than 2 ms.
00181   error_code result = uart->setBaudRate(4800);
00182   if (result) {
00183     return result;
00184   }
00185   result = uart->sendBreak();
00186   if (result) {
00187     return result;
00188   }
00189   result = uart->setBaudRate(9600);
00190   if (result) {
00191     return result;
00192   }
00193 
00194   // Wait for master reset.
00195   sleep->invoke(1);
00196 
00197   // Flush the read buffer.
00198   result = uart->clearReadBuffer();
00199   if (result) {
00200     return result;
00201   }
00202 
00203   // Send the timing byte.
00204   result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD);
00205   if (result) {
00206     return result;
00207   }
00208 
00209   // Change the DS2480 baud rate.
00210   result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200);
00211   if (result) {
00212     return result;
00213   }
00214 
00215   // Change our baud rate.
00216   result = uart->setBaudRate(115200);
00217   if (result) {
00218     return result;
00219   }
00220 
00221   uint_least8_t response;
00222 
00223   // Verify response.
00224   result = uart->readByte(response);
00225   if (result) {
00226     return result;
00227   }
00228   if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
00229       (PARMSEL_BAUDRATE | PARMSET_115200)) {
00230     return make_error_code(HardwareError);
00231   }
00232 
00233   // Set the SPUD time value.
00234   result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite);
00235   if (result) {
00236     return result;
00237   }
00238 
00239   // Verify response.
00240   result = uart->readByte(response);
00241   if (result) {
00242     return result;
00243   }
00244   if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
00245       (PARMSEL_5VPULSE | PARMSET_infinite)) {
00246     return make_error_code(HardwareError);
00247   }
00248 
00249   return result;
00250 }
00251 
00252 error_code DS2480B::reset() {
00253   if (level != NormalLevel) {
00254     return make_error_code(InvalidLevelError);
00255   }
00256 
00257   uint_least8_t packet[2];
00258   int packetLen = 0;
00259 
00260   // Check for correct mode.
00261   if (mode != MODSEL_COMMAND) {
00262     mode = MODSEL_COMMAND;
00263     packet[packetLen++] = MODE_COMMAND;
00264   }
00265 
00266   // Construct the command.
00267   packet[packetLen++] = CMD_COMM | FUNCTSEL_RESET | speed;
00268 
00269   // Send the packet.
00270   error_code result = uart->writeBlock(make_span(packet, packetLen));
00271   if (result) {
00272     return result;
00273   }
00274 
00275   // Read back the response.
00276   result = uart->readByte(packet[0]);
00277   if (result) {
00278     return result;
00279   }
00280 
00281   // Make sure this byte looks like a reset byte.
00282   if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) {
00283     result = make_error_code(ShortDetectedError);
00284   } else if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) {
00285     result = make_error_code(NoSlaveError);
00286   }
00287   return result;
00288 }
00289 
00290 error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) {
00291   if (level != NormalLevel) {
00292     return make_error_code(InvalidLevelError);
00293   }
00294 
00295   uint_least8_t packet[3];
00296   int packetLen = 0;
00297 
00298   // Check for correct mode.
00299   if (mode != MODSEL_COMMAND) {
00300     mode = MODSEL_COMMAND;
00301     packet[packetLen++] = MODE_COMMAND;
00302   }
00303 
00304   // Construct the command.
00305   packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT |
00306                         (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed;
00307   switch (afterLevel) {
00308   case NormalLevel:
00309     break;
00310 
00311   case StrongLevel:
00312     // Add the command to begin the pulse.
00313     packet[packetLen++] =
00314         CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
00315     break;
00316 
00317   default:
00318     return make_error_code(InvalidLevelError);
00319   }
00320 
00321   // Send the packet.
00322   error_code result = uart->writeBlock(make_span(packet, packetLen));
00323   if (result) {
00324     return result;
00325   }
00326 
00327   // Read back the response.
00328   result = uart->readByte(packet[0]);
00329   if (result) {
00330     return result;
00331   }
00332 
00333   // Interpret the response.
00334   if ((packet[0] & 0xE0) == 0x80) {
00335     sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE);
00336     level = afterLevel;
00337   } else {
00338     result = make_error_code(HardwareError);
00339   }
00340   return result;
00341 }
00342 
00343 error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte,
00344                                       Level afterLevel) {
00345   if (level != NormalLevel) {
00346     return make_error_code(InvalidLevelError);
00347   }
00348 
00349   switch (afterLevel) {
00350   case NormalLevel:
00351     break;
00352 
00353   case StrongLevel:
00354     return OneWireMaster::writeByteSetLevel(sendByte, afterLevel);
00355 
00356   default:
00357     return make_error_code(InvalidLevelError);
00358   }
00359 
00360   uint_least8_t packet[3];
00361   int packetLen = 0;
00362 
00363   // Check for correct mode.
00364   if (mode != MODSEL_DATA) {
00365     mode = MODSEL_DATA;
00366     packet[packetLen++] = MODE_DATA;
00367   }
00368 
00369   // Add the byte to send.
00370   packet[packetLen++] = sendByte;
00371 
00372   // Check for duplication of data that looks like COMMAND mode.
00373   if (sendByte == MODE_COMMAND) {
00374     packet[packetLen++] = sendByte;
00375   }
00376 
00377   // Send the packet.
00378   error_code result = uart->writeBlock(make_span(packet, packetLen));
00379   if (result) {
00380     return result;
00381   }
00382 
00383   // Read back the response.
00384   result = uart->readByte(packet[0]);
00385   if (result) {
00386     return result;
00387   }
00388 
00389   // Interpret the response.
00390   if (packet[0] != sendByte) {
00391     result = make_error_code(HardwareError);
00392   }
00393   return result;
00394 }
00395 
00396 error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte,
00397                                      Level afterLevel) {
00398   if (level != NormalLevel) {
00399     return make_error_code(InvalidLevelError);
00400   }
00401 
00402   switch (afterLevel) {
00403   case NormalLevel:
00404     break;
00405 
00406   case StrongLevel:
00407     return OneWireMaster::readByteSetLevel(recvByte, afterLevel);
00408 
00409   default:
00410     return make_error_code(InvalidLevelError);
00411   }
00412 
00413   uint_least8_t packet[2];
00414   int packetLen = 0;
00415 
00416   // Check for correct mode.
00417   if (mode != MODSEL_DATA) {
00418     mode = MODSEL_DATA;
00419     packet[packetLen++] = MODE_DATA;
00420   }
00421 
00422   // Add the byte to send.
00423   packet[packetLen++] = 0xFF;
00424 
00425   // Send the packet.
00426   error_code result = uart->writeBlock(make_span(packet, packetLen));
00427   if (result) {
00428     return result;
00429   }
00430 
00431   // Read back the response.
00432   result = uart->readByte(recvByte);
00433   return result;
00434 }
00435 
00436 error_code DS2480B::setSpeed(Speed newSpeed) {
00437   uint_least8_t newSpeedByte;
00438   switch (newSpeed) {
00439   case OverdriveSpeed:
00440     newSpeedByte = SPEEDSEL_OD;
00441     break;
00442 
00443   case StandardSpeed:
00444     newSpeedByte = SPEEDSEL_STD;
00445     break;
00446 
00447   default:
00448     return make_error_code(InvalidSpeedError);
00449   }
00450   if (speed == newSpeedByte) {
00451     return error_code();
00452   }
00453   speed = newSpeedByte;
00454 
00455   uint_least8_t packet[2];
00456   int packetLen = 0;
00457 
00458   // Check for correct mode.
00459   if (mode != MODSEL_COMMAND) {
00460     mode = MODSEL_COMMAND;
00461     packet[packetLen++] = MODE_COMMAND;
00462   }
00463 
00464   // Change DS2480 speed.
00465   packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed;
00466 
00467   // Send the packet.
00468   return uart->writeBlock(make_span(packet, packetLen));
00469 }
00470 
00471 error_code DS2480B::setLevel(Level newLevel) {
00472   if (level == newLevel) {
00473     return error_code();
00474   }
00475 
00476   uint_least8_t packet[2];
00477   int packetLen = 0;
00478 
00479   switch (newLevel) {
00480   case NormalLevel:
00481     // Stop pulse command.
00482     packet[packetLen++] = MODE_STOP_PULSE;
00483     break;
00484 
00485   case StrongLevel:
00486     // Check for correct mode.
00487     if (mode != MODSEL_COMMAND) {
00488       mode = MODSEL_COMMAND;
00489       packet[packetLen++] = MODE_COMMAND;
00490     }
00491 
00492     // Add the command to begin the pulse.
00493     packet[packetLen++] =
00494         CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
00495     break;
00496 
00497   default:
00498     return make_error_code(InvalidLevelError);
00499   }
00500 
00501   // Send the packet.
00502   error_code result = uart->writeBlock(make_span(packet, packetLen));
00503   if (result) {
00504     return result;
00505   }
00506 
00507   if (newLevel == NormalLevel) {
00508     // Read back the response.
00509     result = uart->readByte(packet[0]);
00510     if (result) {
00511       return result;
00512     }
00513 
00514     // Interpret the response.
00515     if ((packet[0] & 0xE0) != 0xE0) {
00516       return make_error_code(HardwareError);
00517     }
00518   }
00519 
00520   level = newLevel;
00521   return result;
00522 }
00523 
00524 error_code DS2480B::sendCommand(uint_least8_t command) {
00525   uint_least8_t packet[2];
00526   int packetLen = 0;
00527 
00528   // Check for correct mode.
00529   if (mode != MODSEL_COMMAND) {
00530     mode = MODSEL_COMMAND;
00531     packet[packetLen++] = MODE_COMMAND;
00532   }
00533 
00534   // Add command.
00535   packet[packetLen++] = command;
00536 
00537   // Send the packet.
00538   return uart->writeBlock(make_span(packet, packetLen));
00539 }
00540 
00541 const error_category & DS2480B::errorCategory() {
00542   static class : public error_category {
00543   public:
00544     virtual const char * name() const { return "DS2480B"; }
00545 
00546     virtual std::string message(int condition) const {
00547       switch (condition) {
00548       case HardwareError:
00549         return "Hardware Error";
00550 
00551       default:
00552         return defaultErrorMessage(condition);
00553       }
00554     }
00555   } instance;
00556   return instance;
00557 }
00558 
00559 } // namespace MaximInterface