Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_DS28EC20_GPIO
DS28EC20.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 "DS28EC20.hpp" 00034 #include <MaximInterface/Links/OneWireMaster.hpp> 00035 #include <MaximInterface/Utilities/Error.hpp> 00036 #include <MaximInterface/Utilities/crc.hpp> 00037 00038 #include <algorithm> 00039 #include <string.h> 00040 00041 namespace MaximInterface { 00042 00043 typedef enum _Command_t 00044 { 00045 WriteScratchpad = 0x0F, 00046 ReadScratchpad = 0xAA, 00047 CopyScratchpad = 0x55, 00048 ReadMemory = 0xF0, 00049 ReadMemoryExt = 0xA5 00050 } Command; 00051 00052 00053 00054 error_code writeMemory(DS28EC20 & device, DS28EC20::Address targetAddress, 00055 const DS28EC20::Scratchpad & data) { 00056 error_code result = device.writeScratchpad(targetAddress, data); 00057 if (result) { 00058 return result; 00059 } 00060 DS28EC20::Scratchpad readData; 00061 uint_least8_t esByte; 00062 result = device.readScratchpad(readData, esByte); 00063 if (result) { 00064 return result; 00065 } 00066 result = device.copyScratchpad(targetAddress, esByte); 00067 return result; 00068 } 00069 00070 00071 error_code writeMemory(DS28EC20 & device, DS28EC20::Address inAddress, 00072 const uint_least8_t * dataIn, size_t dataLen) 00073 { 00074 DS28EC20::Scratchpad scratchpad; 00075 00076 DS28EC20::Address offset = inAddress - (inAddress & ~(DS28EC20::pageSizeBytes - 1)); 00077 DS28EC20::Address targetAddress = inAddress - offset; 00078 00079 uint_least8_t *p_Data = scratchpad.data(); 00080 p_Data += offset; 00081 00082 MaximInterface::error_code error; 00083 size_t readLen = (dataLen + offset); 00084 00085 /* ... Align length to page boundary */ 00086 readLen += readLen + (DS28EC20::pageSizeBytes - 1u); 00087 readLen &= ~(DS28EC20::pageSizeBytes - 1u); 00088 00089 for (size_t writeLen = 0u; writeLen < readLen; writeLen += DS28EC20::pageSizeBytes) { 00090 if (offset && dataLen){ 00091 error = device.readMemoryExt(targetAddress, scratchpad.data(), DS28EC20::pageSizeBytes); 00092 } 00093 00094 if (error) { 00095 return error; 00096 } 00097 00098 if (dataLen) { 00099 if (dataLen >= DS28EC20::pageSizeBytes) { 00100 (void)memcpy(p_Data, dataIn, DS28EC20::pageSizeBytes); 00101 dataIn += DS28EC20::pageSizeBytes; 00102 dataLen -= DS28EC20::pageSizeBytes; 00103 } 00104 else { 00105 (void)memcpy(p_Data, dataIn, dataLen); 00106 dataLen = 0; 00107 } 00108 p_Data = scratchpad.data(); 00109 } 00110 00111 error = writeMemory(device, targetAddress, scratchpad); 00112 targetAddress += DS28EC20::pageSizeBytes; 00113 00114 if (error) { 00115 return error; 00116 } 00117 00118 offset = 0; 00119 } 00120 00121 return error; 00122 } 00123 00124 00125 /* TODO: Test readMemory */ 00126 error_code DS28EC20::readMemory(Address beginAddress, uint_least8_t * data, 00127 size_t dataLen) const { 00128 error_code owmResult = selectRom(*master); 00129 if (owmResult) { 00130 return owmResult; 00131 } 00132 const uint_least8_t sendBlock[] = {ReadMemory, static_cast<uint_least8_t>(beginAddress), static_cast<uint_least8_t>(beginAddress >> 8)}; 00133 owmResult = 00134 master->writeBlock(make_span(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]))); 00135 if (owmResult) { 00136 return owmResult; 00137 } 00138 owmResult = master->readBlock(make_span(data, dataLen)); 00139 return owmResult; 00140 } 00141 00142 #if 0 00143 static unsigned short crc16(const unsigned char* pin, int sz, unsigned short crc_in) 00144 { 00145 unsigned short crc = crc_in; 00146 unsigned short tmp, in; 00147 int i, index, bit; 00148 for (index = 0, bit = 0, i = 0; i < 8 * sz; i++) { 00149 in = pin[index]; 00150 in >>= (bit); 00151 tmp = (crc & 0x8000); 00152 tmp >>= 15; 00153 in ^= tmp; 00154 in &= 1; 00155 bit++; 00156 if (bit >= 8) { 00157 bit = 0; 00158 index++; 00159 } 00160 00161 crc <<= 1; 00162 tmp = crc; 00163 tmp &= 0x8004; 00164 if (in) { 00165 tmp ^= 0x8004; 00166 tmp &= 0x8004; 00167 } 00168 crc &= (~0x8004); 00169 crc |= tmp; 00170 if (in) 00171 crc |= 1; 00172 else 00173 crc &= (~1); 00174 } 00175 00176 tmp = (crc & 1); 00177 for (i = 0; i < 15; i++) { 00178 tmp <<= 1; 00179 crc >>= 1; 00180 tmp |= (crc & 1); 00181 } 00182 return ~tmp; 00183 } 00184 00185 # define CRC16(...)\ 00186 crc16(__VA_ARGS__) 00187 #else 00188 # define CRC16(data, len, ...)\ 00189 calculateCrc16(make_span(data, len), __VA_ARGS__) 00190 #endif 00191 00192 #define PAGE_SIZE_BYTES 32 00193 #define CRC_LEN_BYTES 2 00194 00195 00196 static error_code processCrc16(OneWireMaster *master, uint_least16_t & crcLocal) 00197 { 00198 /* ... Read CRC */ 00199 uint_least8_t crcRemote[CRC_LEN_BYTES]; 00200 error_code owmResult = master->readBlock(make_span(&crcRemote[0], sizeof(crcRemote) / sizeof(crcRemote[0]))); 00201 00202 if (owmResult) { 00203 return owmResult; 00204 } 00205 00206 crcLocal = ~crcLocal; 00207 crcLocal ^= crcRemote[0] | (static_cast<uint_least16_t>(crcRemote[1]) << 8); 00208 00209 if (crcLocal) { 00210 owmResult = make_error_code(DS28EC20::CrcError); 00211 return owmResult; 00212 } 00213 00214 crcLocal = 0; 00215 00216 return owmResult; 00217 } 00218 00219 00220 error_code DS28EC20::readMemoryExt(Address beginAddress, uint_least8_t * data, 00221 size_t dataLen) const 00222 { 00223 error_code owmResult = selectRom(*master); 00224 if (owmResult) { 00225 return owmResult; 00226 } 00227 00228 uint_least8_t addressMsb = static_cast<uint_least8_t>(beginAddress >> 8); 00229 uint_least8_t addressLsb = static_cast<uint_least8_t>(beginAddress >> 0); 00230 00231 uint_least8_t offset = addressLsb & ~(PAGE_SIZE_BYTES - 1); 00232 offset = addressLsb - offset; 00233 00234 const uint_least8_t sendBlock[] = { ReadMemoryExt, static_cast<uint_least8_t>(addressLsb - offset), addressMsb }; 00235 owmResult = master->writeBlock(make_span(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]))); 00236 00237 if (owmResult) { 00238 return owmResult; 00239 } 00240 00241 uint_least16_t crcLocal = 0; 00242 00243 /* ... Calculate CRC of control fields */ 00244 crcLocal = CRC16(&sendBlock[0], sizeof(sendBlock) / sizeof(sendBlock[0]), crcLocal); 00245 00246 uint_least8_t byte = 0; 00247 /* ... Calculate CRC of head bytes */ 00248 { 00249 uint32_t n = offset; 00250 while (n--) { 00251 owmResult = master->readByte(byte); 00252 crcLocal = CRC16(&byte, sizeof(byte), crcLocal); 00253 } 00254 } 00255 00256 /* ... Read data blocks */ 00257 const size_t blockCnt = dataLen / PAGE_SIZE_BYTES; 00258 size_t blockLen = PAGE_SIZE_BYTES - offset; 00259 for (size_t block = 0; block < blockCnt; ++block) 00260 { 00261 /* ... Read data */ 00262 owmResult = master->readBlock(make_span(data, blockLen)); 00263 00264 if (owmResult) { 00265 return owmResult; 00266 } 00267 00268 /* ... Calculate CRC of data */ 00269 crcLocal = CRC16(data, blockLen, crcLocal); 00270 data += blockLen; 00271 00272 /* ... Read CRC */ 00273 owmResult = processCrc16(master, crcLocal); 00274 00275 if (owmResult) { 00276 return owmResult; 00277 } 00278 00279 blockLen = PAGE_SIZE_BYTES; 00280 } 00281 00282 00283 /* ... Read data reminder */ 00284 size_t dataBlockLen = 0; 00285 size_t remLen = 0; 00286 if (PAGE_SIZE_BYTES > blockLen) 00287 { 00288 00289 /* ... Total amount of user data is less than one block */ 00290 if (PAGE_SIZE_BYTES > (offset + dataLen)) { 00291 /* ... Total length does not cross block boundary. 00292 * Read till the end of block. */ 00293 dataBlockLen = dataLen; 00294 remLen = blockLen - dataBlockLen; 00295 00296 } 00297 else { 00298 /* ... Total length is longer than one block. 00299 * Read till the end of block and then the rest. */ 00300 dataBlockLen = blockLen; 00301 00302 /* ... Read data */ 00303 owmResult = master->readBlock(make_span(data, dataBlockLen)); 00304 00305 if (owmResult) { 00306 return owmResult; 00307 } 00308 00309 /* ... Calculate CRC of data */ 00310 crcLocal = CRC16(data, dataBlockLen, crcLocal); 00311 data += dataBlockLen; 00312 00313 /* ... Read CRC */ 00314 owmResult = processCrc16(master, crcLocal); 00315 00316 if (owmResult) { 00317 return owmResult; 00318 } 00319 00320 dataBlockLen = dataLen - dataBlockLen; 00321 remLen = PAGE_SIZE_BYTES - dataBlockLen; 00322 } 00323 00324 } 00325 else 00326 { 00327 /* ... Total amount of data is more than one block */ 00328 dataBlockLen = dataLen % PAGE_SIZE_BYTES; 00329 remLen = PAGE_SIZE_BYTES - dataBlockLen; 00330 } 00331 00332 /* ... Read data */ 00333 owmResult = master->readBlock(make_span(data, dataBlockLen)); 00334 00335 if (owmResult) { 00336 return owmResult; 00337 } 00338 00339 /* ... Calculate CRC of data */ 00340 crcLocal = CRC16(data, dataBlockLen, crcLocal); 00341 data += dataBlockLen; 00342 00343 /* ... Read tail */ 00344 while (remLen--) { 00345 owmResult = master->readByte(byte); 00346 crcLocal = CRC16(&byte, sizeof(byte), crcLocal); 00347 00348 if (owmResult) { 00349 return owmResult; 00350 } 00351 } 00352 00353 /* ... Read CRC */ 00354 owmResult = processCrc16(master, crcLocal); 00355 00356 if (owmResult) { 00357 return owmResult; 00358 } 00359 00360 return owmResult; 00361 } 00362 00363 00364 error_code DS28EC20::writeScratchpad(Address targetAddress, 00365 const Scratchpad & data) { 00366 error_code owmResult = selectRom(*master); 00367 if (owmResult) { 00368 return owmResult; 00369 } 00370 00371 uint_least8_t addressMsb = static_cast<uint_least8_t>(targetAddress >> 8); 00372 uint_least8_t addressLsb = static_cast<uint_least8_t>(targetAddress >> 0); 00373 addressLsb &= ~(pageSizeBytes - 1); 00374 00375 array<uint_least8_t, 3 + Scratchpad::csize> block; 00376 block[0] = WriteScratchpad; 00377 block[1] = addressLsb; 00378 block[2] = addressMsb; 00379 00380 std::copy(data.begin(), data.end(), block.begin() + 3); 00381 owmResult = master->writeBlock(make_span(block.data(), block.size())); 00382 if (owmResult) { 00383 return owmResult; 00384 } 00385 const uint_fast16_t calculatedCrc = calculateCrc16(make_span(block.data(), block.size())) ^ 0xFFFFU; 00386 owmResult = master->readBlock(make_span(block.data(), 2)); 00387 if (owmResult) { 00388 return owmResult; 00389 } 00390 if (calculatedCrc != 00391 ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) { 00392 owmResult = make_error_code(CrcError); 00393 } 00394 return owmResult; 00395 } 00396 00397 error_code DS28EC20::readScratchpad(Scratchpad & data, uint_least8_t & esByte) { 00398 typedef array<uint_least8_t, 6 + Scratchpad::csize> Block; 00399 00400 error_code owmResult = selectRom(*master); 00401 if (owmResult) { 00402 return owmResult; 00403 } 00404 Block block; block[0] = ReadScratchpad; 00405 owmResult = master->writeByte(block.front()); 00406 if (owmResult) { 00407 return owmResult; 00408 } 00409 owmResult = master->readBlock(make_span(block.data() + 1, block.size() - 1)); 00410 if (owmResult) { 00411 return owmResult; 00412 } 00413 Block::const_iterator blockIt = block.end(); 00414 uint_fast16_t receivedCrc = static_cast<uint_fast16_t>(*(--blockIt)) << 8; 00415 receivedCrc |= *(--blockIt); 00416 const uint_fast16_t expectedCrc = calculateCrc16(make_span(block.data(), block.size() - 2)) ^ 0xFFFFU; 00417 if (expectedCrc == receivedCrc) { 00418 Block::const_iterator blockItEnd = blockIt; 00419 blockIt -= data.size(); 00420 std::copy(blockIt, blockItEnd, data.begin()); 00421 esByte = *(--blockIt); 00422 } else { 00423 owmResult = make_error_code(CrcError); 00424 } 00425 return owmResult; 00426 } 00427 00428 /* TODO: Test copyScratchpad */ 00429 error_code DS28EC20::copyScratchpad(Address targetAddress, uint_least8_t esByte) { 00430 error_code owmResult = selectRom(*master); 00431 if (owmResult) { 00432 return owmResult; 00433 } 00434 00435 uint_least8_t addressMsb = static_cast<uint_least8_t>(targetAddress >> 8); 00436 uint_least8_t addressLsb = static_cast<uint_least8_t>(targetAddress >> 0); 00437 addressLsb &= ~(pageSizeBytes - 1); 00438 00439 uint_least8_t block[] = {CopyScratchpad, addressLsb, addressMsb}; 00440 00441 owmResult = master->writeBlock(make_span(block, sizeof(block) / sizeof(block[0]))); 00442 if (owmResult) { 00443 return owmResult; 00444 } 00445 owmResult = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel); 00446 if (owmResult) { 00447 return owmResult; 00448 } 00449 (*sleep)(10); 00450 owmResult = master->setLevel(OneWireMaster::NormalLevel); 00451 if (owmResult) { 00452 return owmResult; 00453 } 00454 owmResult = master->readByte(block[0]); 00455 if (owmResult) { 00456 return owmResult; 00457 } 00458 if (block[0] != 0xAA) { 00459 owmResult = make_error_code(OperationFailure); 00460 } 00461 return owmResult; 00462 } 00463 00464 const error_category & DS28EC20::errorCategory() { 00465 static class : public error_category { 00466 public: 00467 virtual const char * name() const { return "DS28EC20"; } 00468 00469 virtual std::string message(int condition) const { 00470 switch (condition) { 00471 case CrcError: 00472 return "CRC Error"; 00473 00474 case OperationFailure: 00475 return "Operation Failure"; 00476 00477 default: 00478 return defaultErrorMessage(condition); 00479 } 00480 } 00481 } instance; 00482 return instance; 00483 } 00484 00485 } // namespace MaximInterface
Generated on Tue Jul 12 2022 23:29:45 by
1.7.2