Maxim Integrated / OneWire

Dependents:   MAXREFDES131_Qt_Demo MAX32630FTHR_iButton_uSD_Logger MAX32630FTHR_DS18B20_uSD_Logger MAXREFDES130_131_Demo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS2480B.cpp Source File

DS2480B.cpp

00001 /******************************************************************//**
00002 * Copyright (C) 2016 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 "Masters/DS2480B/DS2480B.h"
00034 #include "Serial.h"
00035 #include "Timer.h"
00036 #include "wait_api.h"
00037 
00038 // Mode Commands
00039 #define MODE_DATA                      0xE1
00040 #define MODE_COMMAND                   0xE3
00041 #define MODE_STOP_PULSE                0xF1
00042 
00043 // Return byte value
00044 #define RB_CHIPID_MASK                 0x1C
00045 #define RB_RESET_MASK                  0x03
00046 #define RB_1WIRESHORT                  0x00
00047 #define RB_PRESENCE                    0x01
00048 #define RB_ALARMPRESENCE               0x02
00049 #define RB_NOPRESENCE                  0x03
00050 
00051 #define RB_BIT_MASK                    0x03
00052 #define RB_BIT_ONE                     0x03
00053 #define RB_BIT_ZERO                    0x00
00054 
00055 // Masks for all bit ranges
00056 #define CMD_MASK                       0x80
00057 #define FUNCTSEL_MASK                  0x60
00058 #define BITPOL_MASK                    0x10
00059 #define SPEEDSEL_MASK                  0x0C
00060 #define MODSEL_MASK                    0x02
00061 #define PARMSEL_MASK                   0x70
00062 #define PARMSET_MASK                   0x0E
00063 
00064 // Command or config bit
00065 #define CMD_COMM                       0x81
00066 #define CMD_CONFIG                     0x01
00067 
00068 // Function select bits
00069 #define FUNCTSEL_BIT                   0x00
00070 #define FUNCTSEL_SEARCHON              0x30
00071 #define FUNCTSEL_SEARCHOFF             0x20
00072 #define FUNCTSEL_RESET                 0x40
00073 #define FUNCTSEL_CHMOD                 0x60
00074 
00075 // Bit polarity/Pulse voltage bits
00076 #define BITPOL_ONE                     0x10
00077 #define BITPOL_ZERO                    0x00
00078 #define BITPOL_5V                      0x00
00079 #define BITPOL_12V                     0x10
00080 
00081 // One Wire speed bits
00082 #define SPEEDSEL_STD                   0x00
00083 #define SPEEDSEL_FLEX                  0x04
00084 #define SPEEDSEL_OD                    0x08
00085 #define SPEEDSEL_PULSE                 0x0C
00086 
00087 // Data/Command mode select bits
00088 #define MODSEL_DATA                    0x00
00089 #define MODSEL_COMMAND                 0x02
00090 
00091 // 5V Follow Pulse select bits 
00092 #define PRIME5V_TRUE                   0x02
00093 #define PRIME5V_FALSE                  0x00
00094 
00095 // Parameter select bits
00096 #define PARMSEL_PARMREAD               0x00
00097 #define PARMSEL_SLEW                   0x10
00098 #define PARMSEL_12VPULSE               0x20
00099 #define PARMSEL_5VPULSE                0x30
00100 #define PARMSEL_WRITE1LOW              0x40
00101 #define PARMSEL_SAMPLEOFFSET           0x50
00102 #define PARMSEL_ACTIVEPULLUPTIME       0x60
00103 #define PARMSEL_BAUDRATE               0x70
00104 
00105 // Pull down slew rate.
00106 #define PARMSET_Slew15Vus              0x00
00107 #define PARMSET_Slew2p2Vus             0x02
00108 #define PARMSET_Slew1p65Vus            0x04
00109 #define PARMSET_Slew1p37Vus            0x06
00110 #define PARMSET_Slew1p1Vus             0x08
00111 #define PARMSET_Slew0p83Vus            0x0A
00112 #define PARMSET_Slew0p7Vus             0x0C
00113 #define PARMSET_Slew0p55Vus            0x0E
00114 
00115 // 12V programming pulse time table
00116 #define PARMSET_32us                   0x00
00117 #define PARMSET_64us                   0x02
00118 #define PARMSET_128us                  0x04
00119 #define PARMSET_256us                  0x06
00120 #define PARMSET_512us                  0x08
00121 #define PARMSET_1024us                 0x0A
00122 #define PARMSET_2048us                 0x0C
00123 #define PARMSET_infinite               0x0E
00124 
00125 // 5V strong pull up pulse time table
00126 #define PARMSET_16p4ms                 0x00
00127 #define PARMSET_65p5ms                 0x02
00128 #define PARMSET_131ms                  0x04
00129 #define PARMSET_262ms                  0x06
00130 #define PARMSET_524ms                  0x08
00131 #define PARMSET_1p05s                  0x0A
00132 #define PARMSET_dynamic                0x0C
00133 #define PARMSET_infinite               0x0E
00134 
00135 // Write 1 low time
00136 #define PARMSET_Write8us               0x00
00137 #define PARMSET_Write9us               0x02
00138 #define PARMSET_Write10us              0x04
00139 #define PARMSET_Write11us              0x06
00140 #define PARMSET_Write12us              0x08
00141 #define PARMSET_Write13us              0x0A
00142 #define PARMSET_Write14us              0x0C
00143 #define PARMSET_Write15us              0x0E
00144 
00145 // Data sample offset and Write 0 recovery time
00146 #define PARMSET_SampOff3us             0x00
00147 #define PARMSET_SampOff4us             0x02
00148 #define PARMSET_SampOff5us             0x04
00149 #define PARMSET_SampOff6us             0x06
00150 #define PARMSET_SampOff7us             0x08
00151 #define PARMSET_SampOff8us             0x0A
00152 #define PARMSET_SampOff9us             0x0C
00153 #define PARMSET_SampOff10us            0x0E
00154 
00155 // Active pull up on time
00156 #define PARMSET_PullUp0p0us            0x00
00157 #define PARMSET_PullUp0p5us            0x02
00158 #define PARMSET_PullUp1p0us            0x04
00159 #define PARMSET_PullUp1p5us            0x06
00160 #define PARMSET_PullUp2p0us            0x08
00161 #define PARMSET_PullUp2p5us            0x0A
00162 #define PARMSET_PullUp3p0us            0x0C
00163 #define PARMSET_PullUp3p5us            0x0E
00164 
00165 // DS2480B program voltage available
00166 #define DS2480BPROG_MASK                0x20
00167 
00168 using OneWire::DS2480B;
00169 using OneWire::OneWireMaster;
00170 
00171 static uint32_t calculateBitTimeout(DS2480B::BaudRate baud)
00172 {    
00173     // Calculate bit timeout in microsecond.
00174     // 10x the time needed to transmit or receive. 
00175     // Double for 115200 due to timer inaccuracies.
00176     
00177     //*100 for 10 bits/byte and ten times the time needed
00178     
00179     uint32_t timeout = 1000000 * 100;
00180     
00181     switch (baud)
00182     {
00183     case DS2480B::Baud115200bps:
00184         timeout = (timeout * 2) / 115200;
00185         break;
00186 
00187     case DS2480B::Baud57600bps:
00188         timeout /= 57600;
00189         break;
00190 
00191     case DS2480B::Baud19200bps:
00192         timeout /= 19200;
00193         break;
00194 
00195     case DS2480B::Baud9600bps:
00196     default:
00197         timeout /= 9600;
00198         break;
00199     }
00200     
00201     return timeout;
00202 }
00203 
00204 DS2480B::DS2480B(PinName tx, PinName rx)
00205     : serial(tx, rx)
00206 {
00207     
00208 }
00209 
00210 OneWireMaster::CmdResult DS2480B::OWInitMaster()
00211 {
00212     return detect();
00213 }
00214 
00215 OneWireMaster::CmdResult DS2480B::OWReset()
00216 {
00217     OneWireMaster::CmdResult result;
00218 
00219     uint8_t readbuffer[10], sendpacket[10];
00220     uint8_t sendlen = 0;
00221 
00222     // make sure normal level
00223     result = OWSetLevel(OneWireMaster::NormalLevel);
00224     if (result == OneWireMaster::Success)
00225     {
00226         // check for correct mode
00227         if (mode != MODSEL_COMMAND)
00228         {
00229             mode = MODSEL_COMMAND;
00230             sendpacket[sendlen++] = MODE_COMMAND;
00231         }
00232 
00233         // construct the command
00234         sendpacket[sendlen++] = (uint8_t)(CMD_COMM | FUNCTSEL_RESET | speed);
00235 
00236         // flush the buffers
00237         flushCom();
00238 
00239         // send the packet
00240         result = writeCom(sendlen, sendpacket);
00241         if (result == OneWireMaster::Success)
00242         {
00243             // read back the 1 byte response
00244             result = readCom(1, readbuffer);
00245             if (result == OneWireMaster::Success)
00246             {
00247                 // make sure this byte looks like a reset byte
00248                 if (((readbuffer[0] & RB_RESET_MASK) == RB_PRESENCE) || ((readbuffer[0] & RB_RESET_MASK) == RB_ALARMPRESENCE))
00249                 {
00250                     result = OneWireMaster::Success;
00251                 }
00252                 else
00253                 {
00254                     result = OneWireMaster::OperationFailure;
00255                 }
00256             }
00257         }
00258     }
00259 
00260     return result;
00261 }
00262 
00263 OneWireMaster::CmdResult DS2480B::OWTouchBitSetLevel(uint8_t & sendRecvBit, OWLevel afterLevel)
00264 {
00265     OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;
00266 
00267     uint8_t readbuffer[10], sendpacket[10];
00268     uint8_t sendlen = 0;
00269 
00270     // make sure normal level
00271     OWSetLevel(OneWireMaster::NormalLevel);
00272 
00273     // check for correct mode
00274     if (mode != MODSEL_COMMAND)
00275     {
00276         mode = MODSEL_COMMAND;
00277         sendpacket[sendlen++] = MODE_COMMAND;
00278     }
00279 
00280     // construct the command
00281     sendpacket[sendlen] = (sendRecvBit != 0) ? BITPOL_ONE : BITPOL_ZERO;
00282     sendpacket[sendlen++] |= CMD_COMM | FUNCTSEL_BIT | speed;
00283 
00284     // flush the buffers
00285     flushCom();
00286 
00287     // send the packet
00288     result = writeCom(sendlen, sendpacket);
00289     if (result == OneWireMaster::Success)
00290     {
00291         // read back the response
00292         result = readCom(1, readbuffer);
00293         if (result == OneWireMaster::Success)
00294         {
00295             // interpret the response
00296             if (((readbuffer[0] & 0xE0) == 0x80) && ((readbuffer[0] & RB_BIT_MASK) == RB_BIT_ONE))
00297             {
00298                 sendRecvBit = 1;
00299                 result = OneWireMaster::Success;
00300             }
00301             else
00302             {
00303                 sendRecvBit = 0;
00304                 result = OneWireMaster::Success;
00305             }
00306         }
00307         else
00308         {
00309             result = OneWireMaster::CommunicationReadError;
00310         }
00311     }
00312     else
00313     {
00314         result = OneWireMaster::CommunicationWriteError;
00315     }
00316 
00317     if (result == OneWireMaster::Success)
00318     {
00319         result = OWSetLevel(afterLevel);
00320     }
00321 
00322     return result;
00323 }
00324 
00325 OneWireMaster::CmdResult DS2480B::OWWriteByteSetLevel(uint8_t sendByte, OWLevel afterLevel)
00326 {
00327     OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;
00328 
00329     uint8_t readbuffer[10], sendpacket[10];
00330     uint8_t sendlen = 0;
00331 
00332     // make sure normal level
00333     OWSetLevel(OneWireMaster::NormalLevel);
00334 
00335     // check for correct mode
00336     if (mode != MODSEL_DATA)
00337     {
00338         mode = MODSEL_DATA;
00339         sendpacket[sendlen++] = MODE_DATA;
00340     }
00341 
00342     // add the byte to send
00343     sendpacket[sendlen++] = sendByte;
00344 
00345     // check for duplication of data that looks like COMMAND mode
00346     if (sendByte == MODE_COMMAND)
00347     {
00348         sendpacket[sendlen++] = sendByte;
00349     }
00350 
00351     // flush the buffers
00352     flushCom();
00353 
00354     // send the packet
00355     result = writeCom(sendlen, sendpacket);
00356     if (result == OneWireMaster::Success)
00357     {
00358         // read back the 1 byte response
00359         result = readCom(1, readbuffer);
00360         if ((result == OneWireMaster::Success) && (readbuffer[0] == sendByte))
00361         {
00362             result = OneWireMaster::Success;
00363         }
00364         else
00365         {
00366             result = OneWireMaster::CommunicationReadError;
00367         }
00368     }
00369     else
00370     {
00371         result = OneWireMaster::CommunicationWriteError;
00372     }
00373 
00374     if (result == OneWireMaster::Success)
00375     {
00376         result = OWSetLevel(afterLevel);
00377     }
00378 
00379     return result;
00380 }
00381 
00382 OneWireMaster::CmdResult DS2480B::OWReadByteSetLevel(uint8_t & recvByte, OWLevel afterLevel)
00383 {
00384     OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;
00385 
00386     uint8_t readbuffer[10], sendpacket[10];
00387     uint8_t sendlen = 0;
00388 
00389     // make sure normal level
00390     OWSetLevel(OneWireMaster::NormalLevel);
00391 
00392     // check for correct mode
00393     if (mode != MODSEL_DATA)
00394     {
00395         mode = MODSEL_DATA;
00396         sendpacket[sendlen++] = MODE_DATA;
00397     }
00398 
00399     // add the byte to send
00400     sendpacket[sendlen++] = 0xFF;
00401 
00402     // flush the buffers
00403     flushCom();
00404 
00405     // send the packet
00406     result = writeCom(sendlen, sendpacket);
00407     if (result == OneWireMaster::Success)
00408     {
00409         // read back the 1 byte response
00410         result = readCom(1, readbuffer);
00411         if (result == OneWireMaster::Success)
00412         {
00413             recvByte = readbuffer[0];
00414             result = OneWireMaster::Success;
00415         }
00416         else
00417         {
00418             result = OneWireMaster::CommunicationReadError;
00419         }
00420     }
00421     else
00422     {
00423         result = OneWireMaster::CommunicationWriteError;
00424     }
00425 
00426     // an error occured so re-sync with DS2480B
00427     if (result == OneWireMaster::Success)
00428     {
00429         result = OWSetLevel(afterLevel);
00430     }
00431 
00432     return result;
00433 }
00434 
00435 OneWireMaster::CmdResult DS2480B::OWSetSpeed(OWSpeed newSpeed)
00436 {
00437     OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;
00438 
00439     uint8_t sendpacket[5];
00440     uint8_t sendlen = 0;
00441 
00442     // check if change from current mode
00443     if (((newSpeed == OneWireMaster::OverdriveSpeed) && (speed != SPEEDSEL_OD)) || 
00444         ((newSpeed == OneWireMaster::StandardSpeed) && (speed != SPEEDSEL_STD))) 
00445     {
00446         if (newSpeed == OneWireMaster::OverdriveSpeed) 
00447         {
00448             result = changeBaud(Baud115200bps);
00449             if (result == OneWireMaster::Success) 
00450             {
00451                 speed = SPEEDSEL_OD;
00452             }
00453         } 
00454         else if (newSpeed == OneWireMaster::StandardSpeed) 
00455         {
00456             result = changeBaud(Baud9600bps);
00457             if (result == OneWireMaster::Success) 
00458             {
00459                 speed = SPEEDSEL_STD;
00460             }
00461         }
00462 
00463         // if baud rate is set correctly then change DS2480 speed
00464         if (result == OneWireMaster::Success) 
00465         {
00466             // check if correct mode
00467             if (mode != MODSEL_COMMAND) 
00468             {
00469                 mode = MODSEL_COMMAND;
00470                 sendpacket[sendlen++] = MODE_COMMAND;
00471             }
00472 
00473             // proceed to set the DS2480 communication speed
00474             sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed;
00475 
00476             // send the packet
00477             result = writeCom(sendlen,sendpacket);
00478         }
00479     }
00480 
00481     return result;
00482 }
00483 
00484 OneWireMaster::CmdResult DS2480B::OWSetLevel(OWLevel newLevel)
00485 {
00486     OneWireMaster::CmdResult result = OneWireMaster::Success;
00487 
00488     uint8_t sendpacket[10], readbuffer[10];
00489     uint8_t sendlen = 0;
00490 
00491     // check if need to change level
00492     if (newLevel != level)
00493     {
00494         // check for correct mode
00495         if (mode != MODSEL_COMMAND)
00496         {
00497             mode = MODSEL_COMMAND;
00498             sendpacket[sendlen++] = MODE_COMMAND;
00499         }
00500 
00501         // check if just putting back to normal
00502         if (newLevel == OneWireMaster::NormalLevel)
00503         {
00504             // stop pulse command
00505             sendpacket[sendlen++] = MODE_STOP_PULSE;
00506 
00507             // add the command to begin the pulse WITHOUT prime
00508             sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
00509 
00510             // stop pulse command
00511             sendpacket[sendlen++] = MODE_STOP_PULSE;
00512 
00513             // flush the buffers
00514             flushCom();
00515 
00516             // send the packet
00517             result = writeCom(sendlen, sendpacket);
00518             if (result == OneWireMaster::Success)
00519             {
00520                 // read back the 1 byte response
00521                 result = readCom(2, readbuffer);
00522                 if (result == OneWireMaster::Success)
00523                 {
00524                     // check response byte
00525                     if (((readbuffer[0] & 0xE0) == 0xE0) && ((readbuffer[1] & 0xE0) == 0xE0))
00526                     {
00527                         level = OneWireMaster::NormalLevel;
00528                     }
00529                     else
00530                     {
00531                         result = OneWireMaster::OperationFailure;
00532                     }
00533                 }
00534             }
00535         }
00536         // set new level
00537         else
00538         {
00539             // set the SPUD time value
00540             sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite;
00541             // add the command to begin the pulse
00542             sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V;
00543 
00544             // flush the buffers
00545             flushCom();
00546 
00547             // send the packet
00548             result = writeCom(sendlen, sendpacket);
00549             if (result == OneWireMaster::Success)
00550             {
00551                 // read back the 1 byte response from setting time limit
00552                 result = readCom(1, readbuffer);
00553                 if (result == OneWireMaster::Success)
00554                 {
00555                     // check response byte
00556                     if ((readbuffer[0] & 0x81) == 0)
00557                     {
00558                         level = newLevel;
00559                     }
00560                     else
00561                     {
00562                         result = OneWireMaster::OperationFailure;
00563                     }
00564                 }
00565             }
00566         }
00567     }
00568 
00569     return result;
00570 }
00571 
00572 OneWireMaster::CmdResult DS2480B::detect()
00573 {
00574     OneWireMaster::CmdResult result;
00575 
00576     uint8_t sendpacket[10], readbuffer[10];
00577     uint8_t sendlen = 0;
00578 
00579     // reset modes
00580     level = OneWireMaster::NormalLevel;
00581     mode = MODSEL_COMMAND;
00582     baud = Baud9600bps;
00583     speed = SPEEDSEL_FLEX;
00584 
00585     // set the baud rate to 9600
00586     setComBaud(baud);
00587 
00588     // send a break to reset the DS2480B
00589     breakCom();
00590 
00591     // delay to let line settle
00592     wait_ms(2);
00593 
00594     // flush the buffers
00595     flushCom();
00596 
00597     // send the timing byte
00598     sendpacket[0] = 0xC1;
00599     result = writeCom(1, sendpacket);
00600     if (result == OneWireMaster::Success)
00601     {
00602         // delay to let line settle
00603         wait_ms(2);
00604 
00605         // set the FLEX configuration parameters
00606         // default PDSRC = 1.37Vus
00607         sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus;
00608         // default W1LT = 10us
00609         sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write10us;
00610         // default DSO/WORT = 8us
00611         sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff8us;
00612 
00613         // construct the command to read the baud rate (to test command block)
00614         sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
00615 
00616         // also do 1 bit operation (to test 1-Wire block)
00617         sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_BIT | baud | BITPOL_ONE;
00618 
00619         // flush the buffers
00620         flushCom();
00621 
00622         // send the packet
00623         result = writeCom(sendlen, sendpacket);
00624         if (result == OneWireMaster::Success)
00625         {
00626             // read back the response
00627             result = readCom(5, readbuffer);
00628             if (result == OneWireMaster::Success)
00629             {
00630                 // look at the baud rate and bit operation
00631                 // to see if the response makes sense
00632                 if (((readbuffer[3] & 0xF1) == 0x00) && ((readbuffer[3] & 0x0E) == baud) && ((readbuffer[4] & 0xF0) == 0x90) && ((readbuffer[4] & 0x0C) == baud))
00633                 {
00634                     result = OneWireMaster::Success;
00635                 }
00636                 else
00637                 {
00638                     result = OneWireMaster::OperationFailure;
00639                 }
00640             }
00641         }
00642     }
00643 
00644     return result;
00645 }
00646 
00647 OneWireMaster::CmdResult DS2480B::changeBaud(BaudRate newBaud)
00648 {
00649     OneWireMaster::CmdResult result = OneWireMaster::Success;
00650 
00651     uint8_t readbuffer[5], sendpacket[5], sendpacket2[5];
00652     uint8_t sendlen = 0, sendlen2 = 0;
00653 
00654     //see if diffenent then current baud rate
00655     if (baud != newBaud)
00656     {
00657         // build the command packet
00658         // check for correct mode
00659         if (mode != MODSEL_COMMAND)
00660         {
00661             mode = MODSEL_COMMAND;
00662             sendpacket[sendlen++] = MODE_COMMAND;
00663         }
00664         // build the command
00665         sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newBaud;
00666 
00667         // flush the buffers
00668         flushCom();
00669 
00670         // send the packet
00671         result = writeCom(sendlen, sendpacket);
00672         if (result == OneWireMaster::Success)
00673         {
00674             // make sure buffer is flushed
00675             wait_ms(5);
00676 
00677             // change our baud rate
00678             setComBaud(newBaud);
00679             baud = newBaud;
00680 
00681             // wait for things to settle
00682             wait_ms(5);
00683 
00684             // build a command packet to read back baud rate
00685             sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
00686 
00687             // flush the buffers
00688             flushCom();
00689 
00690             // send the packet
00691             result = writeCom(sendlen2, sendpacket2);
00692             if (result == OneWireMaster::Success)
00693             {
00694                 // read back the 1 byte response
00695                 result = readCom(1, readbuffer);
00696                 if (result == OneWireMaster::Success)
00697                 {
00698                     // verify correct baud
00699                     if ((readbuffer[0] & 0x0E) == (sendpacket[sendlen - 1] & 0x0E))
00700                     {
00701                         result = OneWireMaster::Success;
00702                     }
00703                     else
00704                     {
00705                         result = OneWireMaster::OperationFailure;
00706                     }
00707                 }
00708                 else
00709                 {
00710                     result = OneWireMaster::CommunicationReadError;
00711                 }
00712             }
00713             else
00714             {
00715                 result = OneWireMaster::CommunicationWriteError;
00716             }
00717         }
00718         else
00719         {
00720             result = OneWireMaster::CommunicationWriteError;
00721         }
00722     }
00723 
00724     return result;
00725 }
00726 
00727 OneWireMaster::CmdResult DS2480B::writeCom(size_t outlen, uint8_t *outbuf)
00728 {
00729     OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;
00730 
00731     mbed::Timer timer;
00732     uint32_t timeout = calculateBitTimeout(baud) * outlen;
00733     uint8_t idx = 0;
00734 
00735     timer.start();
00736     do
00737     {
00738         while ((idx < outlen) && serial.writeable())
00739         {
00740             serial.putc(outbuf[idx++]);
00741         }
00742 
00743     } while ((idx < outlen) && (static_cast<unsigned int>(timer.read_us()) < timeout));
00744     
00745     if (idx == outlen)
00746     {
00747         result = OneWireMaster::Success;
00748     }
00749     else
00750     {
00751         result = OneWireMaster::TimeoutError;
00752     }
00753 
00754     return result;
00755 }
00756 
00757 OneWireMaster::CmdResult DS2480B::readCom(size_t inlen, uint8_t *inbuf)
00758 {
00759     OneWireMaster::CmdResult result;
00760     mbed::Timer timer;
00761     uint32_t num_bytes_read = 0;
00762     uint32_t timeout = (calculateBitTimeout(baud) * inlen);
00763 
00764     timer.start();
00765     do
00766     {
00767         while ((num_bytes_read < inlen) && serial.readable())
00768         {
00769             inbuf[num_bytes_read++] = serial.getc();
00770         }
00771     } while ((num_bytes_read < inlen) && (static_cast<unsigned int>(timer.read_us()) < timeout));
00772     timer.stop();
00773 
00774     if (num_bytes_read == inlen)
00775     {
00776         result = OneWireMaster::Success;
00777     }
00778     else
00779     {
00780         result = OneWireMaster::TimeoutError;
00781     }
00782 
00783     return result;
00784 }
00785 
00786 void DS2480B::breakCom()
00787 {
00788     // Switch to lower baud rate to ensure break is longer than 2 ms.
00789     serial.baud(4800);
00790     serial.send_break();
00791     setComBaud(baud);
00792 }
00793 
00794 void DS2480B::flushCom()
00795 {
00796     // Clear receive buffer.
00797     while (serial.readable())
00798     {
00799         serial.getc();
00800     }
00801 
00802     /* No apparent way to clear transmit buffer.
00803      * From the example in AN192 (http://pdfserv.maximintegrated.com/en/an/AN192.pdf),
00804      * the data shouldn't be sent, just aborted and the buffer cleaned out.
00805      * Below is what was used in AN192 example code using windows drivers:
00806      * PurgeComm(ComID, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
00807      */
00808 }
00809 
00810 void DS2480B::setComBaud(BaudRate new_baud)
00811 {
00812     switch (new_baud)
00813     {
00814     case Baud115200bps:
00815         serial.baud(115200);
00816         break;
00817 
00818     case Baud57600bps:
00819         serial.baud(57600);
00820         break;
00821 
00822     case Baud19200bps:
00823         serial.baud(19200);
00824         break;
00825 
00826     case Baud9600bps:
00827     default:
00828         serial.baud(9600);
00829         break;
00830     }
00831 }