Extended MaximInterface
Dependents: mbed_DS28EC20_GPIO
Devices/DS28EC20.cpp@9:aeda90624ad0, 2019-12-19 (annotated)
- Committer:
- reARMnimator
- Date:
- Thu Dec 19 23:05:46 2019 +0100
- Revision:
- 9:aeda90624ad0
Added DS28EC20 20480-bit EEPROM
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
reARMnimator | 9:aeda90624ad0 | 1 | /******************************************************************************* |
reARMnimator | 9:aeda90624ad0 | 2 | * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. |
reARMnimator | 9:aeda90624ad0 | 3 | * |
reARMnimator | 9:aeda90624ad0 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
reARMnimator | 9:aeda90624ad0 | 5 | * copy of this software and associated documentation files (the "Software"), |
reARMnimator | 9:aeda90624ad0 | 6 | * to deal in the Software without restriction, including without limitation |
reARMnimator | 9:aeda90624ad0 | 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
reARMnimator | 9:aeda90624ad0 | 8 | * and/or sell copies of the Software, and to permit persons to whom the |
reARMnimator | 9:aeda90624ad0 | 9 | * Software is furnished to do so, subject to the following conditions: |
reARMnimator | 9:aeda90624ad0 | 10 | * |
reARMnimator | 9:aeda90624ad0 | 11 | * The above copyright notice and this permission notice shall be included |
reARMnimator | 9:aeda90624ad0 | 12 | * in all copies or substantial portions of the Software. |
reARMnimator | 9:aeda90624ad0 | 13 | * |
reARMnimator | 9:aeda90624ad0 | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
reARMnimator | 9:aeda90624ad0 | 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
reARMnimator | 9:aeda90624ad0 | 16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
reARMnimator | 9:aeda90624ad0 | 17 | * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES |
reARMnimator | 9:aeda90624ad0 | 18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
reARMnimator | 9:aeda90624ad0 | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
reARMnimator | 9:aeda90624ad0 | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
reARMnimator | 9:aeda90624ad0 | 21 | * |
reARMnimator | 9:aeda90624ad0 | 22 | * Except as contained in this notice, the name of Maxim Integrated |
reARMnimator | 9:aeda90624ad0 | 23 | * Products, Inc. shall not be used except as stated in the Maxim Integrated |
reARMnimator | 9:aeda90624ad0 | 24 | * Products, Inc. Branding Policy. |
reARMnimator | 9:aeda90624ad0 | 25 | * |
reARMnimator | 9:aeda90624ad0 | 26 | * The mere transfer of this software does not imply any licenses |
reARMnimator | 9:aeda90624ad0 | 27 | * of trade secrets, proprietary technology, copyrights, patents, |
reARMnimator | 9:aeda90624ad0 | 28 | * trademarks, maskwork rights, or any other form of intellectual |
reARMnimator | 9:aeda90624ad0 | 29 | * property whatsoever. Maxim Integrated Products, Inc. retains all |
reARMnimator | 9:aeda90624ad0 | 30 | * ownership rights. |
reARMnimator | 9:aeda90624ad0 | 31 | *******************************************************************************/ |
reARMnimator | 9:aeda90624ad0 | 32 | |
reARMnimator | 9:aeda90624ad0 | 33 | #include "DS28EC20.hpp" |
reARMnimator | 9:aeda90624ad0 | 34 | #include <MaximInterface/Links/OneWireMaster.hpp> |
reARMnimator | 9:aeda90624ad0 | 35 | #include <MaximInterface/Utilities/Error.hpp> |
reARMnimator | 9:aeda90624ad0 | 36 | #include <MaximInterface/Utilities/crc.hpp> |
reARMnimator | 9:aeda90624ad0 | 37 | |
reARMnimator | 9:aeda90624ad0 | 38 | #include <algorithm> |
reARMnimator | 9:aeda90624ad0 | 39 | #include <string.h> |
reARMnimator | 9:aeda90624ad0 | 40 | |
reARMnimator | 9:aeda90624ad0 | 41 | namespace MaximInterface { |
reARMnimator | 9:aeda90624ad0 | 42 | |
reARMnimator | 9:aeda90624ad0 | 43 | typedef enum _Command_t |
reARMnimator | 9:aeda90624ad0 | 44 | { |
reARMnimator | 9:aeda90624ad0 | 45 | WriteScratchpad = 0x0F, |
reARMnimator | 9:aeda90624ad0 | 46 | ReadScratchpad = 0xAA, |
reARMnimator | 9:aeda90624ad0 | 47 | CopyScratchpad = 0x55, |
reARMnimator | 9:aeda90624ad0 | 48 | ReadMemory = 0xF0, |
reARMnimator | 9:aeda90624ad0 | 49 | ReadMemoryExt = 0xA5 |
reARMnimator | 9:aeda90624ad0 | 50 | } Command; |
reARMnimator | 9:aeda90624ad0 | 51 | |
reARMnimator | 9:aeda90624ad0 | 52 | |
reARMnimator | 9:aeda90624ad0 | 53 | |
reARMnimator | 9:aeda90624ad0 | 54 | error_code writeMemory(DS28EC20 & device, DS28EC20::Address targetAddress, |
reARMnimator | 9:aeda90624ad0 | 55 | const DS28EC20::Scratchpad & data) { |
reARMnimator | 9:aeda90624ad0 | 56 | error_code result = device.writeScratchpad(targetAddress, data); |
reARMnimator | 9:aeda90624ad0 | 57 | if (result) { |
reARMnimator | 9:aeda90624ad0 | 58 | return result; |
reARMnimator | 9:aeda90624ad0 | 59 | } |
reARMnimator | 9:aeda90624ad0 | 60 | DS28EC20::Scratchpad readData; |
reARMnimator | 9:aeda90624ad0 | 61 | uint_least8_t esByte; |
reARMnimator | 9:aeda90624ad0 | 62 | result = device.readScratchpad(readData, esByte); |
reARMnimator | 9:aeda90624ad0 | 63 | if (result) { |
reARMnimator | 9:aeda90624ad0 | 64 | return result; |
reARMnimator | 9:aeda90624ad0 | 65 | } |
reARMnimator | 9:aeda90624ad0 | 66 | result = device.copyScratchpad(targetAddress, esByte); |
reARMnimator | 9:aeda90624ad0 | 67 | return result; |
reARMnimator | 9:aeda90624ad0 | 68 | } |
reARMnimator | 9:aeda90624ad0 | 69 | |
reARMnimator | 9:aeda90624ad0 | 70 | |
reARMnimator | 9:aeda90624ad0 | 71 | error_code writeMemory(DS28EC20 & device, DS28EC20::Address inAddress, |
reARMnimator | 9:aeda90624ad0 | 72 | const uint_least8_t * dataIn, size_t dataLen) |
reARMnimator | 9:aeda90624ad0 | 73 | { |
reARMnimator | 9:aeda90624ad0 | 74 | DS28EC20::Scratchpad scratchpad; |
reARMnimator | 9:aeda90624ad0 | 75 | |
reARMnimator | 9:aeda90624ad0 | 76 | DS28EC20::Address offset = inAddress - (inAddress & ~(DS28EC20::pageSizeBytes - 1)); |
reARMnimator | 9:aeda90624ad0 | 77 | DS28EC20::Address targetAddress = inAddress - offset; |
reARMnimator | 9:aeda90624ad0 | 78 | |
reARMnimator | 9:aeda90624ad0 | 79 | uint_least8_t *p_Data = scratchpad.data(); |
reARMnimator | 9:aeda90624ad0 | 80 | p_Data += offset; |
reARMnimator | 9:aeda90624ad0 | 81 | |
reARMnimator | 9:aeda90624ad0 | 82 | MaximInterface::error_code error; |
reARMnimator | 9:aeda90624ad0 | 83 | size_t readLen = (dataLen + offset); |
reARMnimator | 9:aeda90624ad0 | 84 | |
reARMnimator | 9:aeda90624ad0 | 85 | /* ... Align length to page boundary */ |
reARMnimator | 9:aeda90624ad0 | 86 | readLen += readLen + (DS28EC20::pageSizeBytes - 1u); |
reARMnimator | 9:aeda90624ad0 | 87 | readLen &= ~(DS28EC20::pageSizeBytes - 1u); |
reARMnimator | 9:aeda90624ad0 | 88 | |
reARMnimator | 9:aeda90624ad0 | 89 | for (size_t writeLen = 0u; writeLen < readLen; writeLen += DS28EC20::pageSizeBytes) { |
reARMnimator | 9:aeda90624ad0 | 90 | if (offset && dataLen){ |
reARMnimator | 9:aeda90624ad0 | 91 | error = device.readMemoryExt(targetAddress, scratchpad.data(), DS28EC20::pageSizeBytes); |
reARMnimator | 9:aeda90624ad0 | 92 | } |
reARMnimator | 9:aeda90624ad0 | 93 | |
reARMnimator | 9:aeda90624ad0 | 94 | if (error) { |
reARMnimator | 9:aeda90624ad0 | 95 | return error; |
reARMnimator | 9:aeda90624ad0 | 96 | } |
reARMnimator | 9:aeda90624ad0 | 97 | |
reARMnimator | 9:aeda90624ad0 | 98 | if (dataLen) { |
reARMnimator | 9:aeda90624ad0 | 99 | if (dataLen >= DS28EC20::pageSizeBytes) { |
reARMnimator | 9:aeda90624ad0 | 100 | (void)memcpy(p_Data, dataIn, DS28EC20::pageSizeBytes); |
reARMnimator | 9:aeda90624ad0 | 101 | dataIn += DS28EC20::pageSizeBytes; |
reARMnimator | 9:aeda90624ad0 | 102 | dataLen -= DS28EC20::pageSizeBytes; |
reARMnimator | 9:aeda90624ad0 | 103 | } |
reARMnimator | 9:aeda90624ad0 | 104 | else { |
reARMnimator | 9:aeda90624ad0 | 105 | (void)memcpy(p_Data, dataIn, dataLen); |
reARMnimator | 9:aeda90624ad0 | 106 | dataLen = 0; |
reARMnimator | 9:aeda90624ad0 | 107 | } |
reARMnimator | 9:aeda90624ad0 | 108 | p_Data = scratchpad.data(); |
reARMnimator | 9:aeda90624ad0 | 109 | } |
reARMnimator | 9:aeda90624ad0 | 110 | |
reARMnimator | 9:aeda90624ad0 | 111 | error = writeMemory(device, targetAddress, scratchpad); |
reARMnimator | 9:aeda90624ad0 | 112 | targetAddress += DS28EC20::pageSizeBytes; |
reARMnimator | 9:aeda90624ad0 | 113 | |
reARMnimator | 9:aeda90624ad0 | 114 | if (error) { |
reARMnimator | 9:aeda90624ad0 | 115 | return error; |
reARMnimator | 9:aeda90624ad0 | 116 | } |
reARMnimator | 9:aeda90624ad0 | 117 | |
reARMnimator | 9:aeda90624ad0 | 118 | offset = 0; |
reARMnimator | 9:aeda90624ad0 | 119 | } |
reARMnimator | 9:aeda90624ad0 | 120 | |
reARMnimator | 9:aeda90624ad0 | 121 | return error; |
reARMnimator | 9:aeda90624ad0 | 122 | } |
reARMnimator | 9:aeda90624ad0 | 123 | |
reARMnimator | 9:aeda90624ad0 | 124 | |
reARMnimator | 9:aeda90624ad0 | 125 | /* TODO: Test readMemory */ |
reARMnimator | 9:aeda90624ad0 | 126 | error_code DS28EC20::readMemory(Address beginAddress, uint_least8_t * data, |
reARMnimator | 9:aeda90624ad0 | 127 | size_t dataLen) const { |
reARMnimator | 9:aeda90624ad0 | 128 | error_code owmResult = selectRom(*master); |
reARMnimator | 9:aeda90624ad0 | 129 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 130 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 131 | } |
reARMnimator | 9:aeda90624ad0 | 132 | const uint_least8_t sendBlock[] = {ReadMemory, static_cast<uint_least8_t>(beginAddress), static_cast<uint_least8_t>(beginAddress >> 8)}; |
reARMnimator | 9:aeda90624ad0 | 133 | owmResult = |
reARMnimator | 9:aeda90624ad0 | 134 | master->writeBlock(make_span(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]))); |
reARMnimator | 9:aeda90624ad0 | 135 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 136 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 137 | } |
reARMnimator | 9:aeda90624ad0 | 138 | owmResult = master->readBlock(make_span(data, dataLen)); |
reARMnimator | 9:aeda90624ad0 | 139 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 140 | } |
reARMnimator | 9:aeda90624ad0 | 141 | |
reARMnimator | 9:aeda90624ad0 | 142 | #if 0 |
reARMnimator | 9:aeda90624ad0 | 143 | static unsigned short crc16(const unsigned char* pin, int sz, unsigned short crc_in) |
reARMnimator | 9:aeda90624ad0 | 144 | { |
reARMnimator | 9:aeda90624ad0 | 145 | unsigned short crc = crc_in; |
reARMnimator | 9:aeda90624ad0 | 146 | unsigned short tmp, in; |
reARMnimator | 9:aeda90624ad0 | 147 | int i, index, bit; |
reARMnimator | 9:aeda90624ad0 | 148 | for (index = 0, bit = 0, i = 0; i < 8 * sz; i++) { |
reARMnimator | 9:aeda90624ad0 | 149 | in = pin[index]; |
reARMnimator | 9:aeda90624ad0 | 150 | in >>= (bit); |
reARMnimator | 9:aeda90624ad0 | 151 | tmp = (crc & 0x8000); |
reARMnimator | 9:aeda90624ad0 | 152 | tmp >>= 15; |
reARMnimator | 9:aeda90624ad0 | 153 | in ^= tmp; |
reARMnimator | 9:aeda90624ad0 | 154 | in &= 1; |
reARMnimator | 9:aeda90624ad0 | 155 | bit++; |
reARMnimator | 9:aeda90624ad0 | 156 | if (bit >= 8) { |
reARMnimator | 9:aeda90624ad0 | 157 | bit = 0; |
reARMnimator | 9:aeda90624ad0 | 158 | index++; |
reARMnimator | 9:aeda90624ad0 | 159 | } |
reARMnimator | 9:aeda90624ad0 | 160 | |
reARMnimator | 9:aeda90624ad0 | 161 | crc <<= 1; |
reARMnimator | 9:aeda90624ad0 | 162 | tmp = crc; |
reARMnimator | 9:aeda90624ad0 | 163 | tmp &= 0x8004; |
reARMnimator | 9:aeda90624ad0 | 164 | if (in) { |
reARMnimator | 9:aeda90624ad0 | 165 | tmp ^= 0x8004; |
reARMnimator | 9:aeda90624ad0 | 166 | tmp &= 0x8004; |
reARMnimator | 9:aeda90624ad0 | 167 | } |
reARMnimator | 9:aeda90624ad0 | 168 | crc &= (~0x8004); |
reARMnimator | 9:aeda90624ad0 | 169 | crc |= tmp; |
reARMnimator | 9:aeda90624ad0 | 170 | if (in) |
reARMnimator | 9:aeda90624ad0 | 171 | crc |= 1; |
reARMnimator | 9:aeda90624ad0 | 172 | else |
reARMnimator | 9:aeda90624ad0 | 173 | crc &= (~1); |
reARMnimator | 9:aeda90624ad0 | 174 | } |
reARMnimator | 9:aeda90624ad0 | 175 | |
reARMnimator | 9:aeda90624ad0 | 176 | tmp = (crc & 1); |
reARMnimator | 9:aeda90624ad0 | 177 | for (i = 0; i < 15; i++) { |
reARMnimator | 9:aeda90624ad0 | 178 | tmp <<= 1; |
reARMnimator | 9:aeda90624ad0 | 179 | crc >>= 1; |
reARMnimator | 9:aeda90624ad0 | 180 | tmp |= (crc & 1); |
reARMnimator | 9:aeda90624ad0 | 181 | } |
reARMnimator | 9:aeda90624ad0 | 182 | return ~tmp; |
reARMnimator | 9:aeda90624ad0 | 183 | } |
reARMnimator | 9:aeda90624ad0 | 184 | |
reARMnimator | 9:aeda90624ad0 | 185 | # define CRC16(...)\ |
reARMnimator | 9:aeda90624ad0 | 186 | crc16(__VA_ARGS__) |
reARMnimator | 9:aeda90624ad0 | 187 | #else |
reARMnimator | 9:aeda90624ad0 | 188 | # define CRC16(data, len, ...)\ |
reARMnimator | 9:aeda90624ad0 | 189 | calculateCrc16(make_span(data, len), __VA_ARGS__) |
reARMnimator | 9:aeda90624ad0 | 190 | #endif |
reARMnimator | 9:aeda90624ad0 | 191 | |
reARMnimator | 9:aeda90624ad0 | 192 | #define PAGE_SIZE_BYTES 32 |
reARMnimator | 9:aeda90624ad0 | 193 | #define CRC_LEN_BYTES 2 |
reARMnimator | 9:aeda90624ad0 | 194 | |
reARMnimator | 9:aeda90624ad0 | 195 | |
reARMnimator | 9:aeda90624ad0 | 196 | static error_code processCrc16(OneWireMaster *master, uint_least16_t & crcLocal) |
reARMnimator | 9:aeda90624ad0 | 197 | { |
reARMnimator | 9:aeda90624ad0 | 198 | /* ... Read CRC */ |
reARMnimator | 9:aeda90624ad0 | 199 | uint_least8_t crcRemote[CRC_LEN_BYTES]; |
reARMnimator | 9:aeda90624ad0 | 200 | error_code owmResult = master->readBlock(make_span(&crcRemote[0], sizeof(crcRemote) / sizeof(crcRemote[0]))); |
reARMnimator | 9:aeda90624ad0 | 201 | |
reARMnimator | 9:aeda90624ad0 | 202 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 203 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 204 | } |
reARMnimator | 9:aeda90624ad0 | 205 | |
reARMnimator | 9:aeda90624ad0 | 206 | crcLocal = ~crcLocal; |
reARMnimator | 9:aeda90624ad0 | 207 | crcLocal ^= crcRemote[0] | (static_cast<uint_least16_t>(crcRemote[1]) << 8); |
reARMnimator | 9:aeda90624ad0 | 208 | |
reARMnimator | 9:aeda90624ad0 | 209 | if (crcLocal) { |
reARMnimator | 9:aeda90624ad0 | 210 | owmResult = make_error_code(DS28EC20::CrcError); |
reARMnimator | 9:aeda90624ad0 | 211 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 212 | } |
reARMnimator | 9:aeda90624ad0 | 213 | |
reARMnimator | 9:aeda90624ad0 | 214 | crcLocal = 0; |
reARMnimator | 9:aeda90624ad0 | 215 | |
reARMnimator | 9:aeda90624ad0 | 216 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 217 | } |
reARMnimator | 9:aeda90624ad0 | 218 | |
reARMnimator | 9:aeda90624ad0 | 219 | |
reARMnimator | 9:aeda90624ad0 | 220 | error_code DS28EC20::readMemoryExt(Address beginAddress, uint_least8_t * data, |
reARMnimator | 9:aeda90624ad0 | 221 | size_t dataLen) const |
reARMnimator | 9:aeda90624ad0 | 222 | { |
reARMnimator | 9:aeda90624ad0 | 223 | error_code owmResult = selectRom(*master); |
reARMnimator | 9:aeda90624ad0 | 224 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 225 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 226 | } |
reARMnimator | 9:aeda90624ad0 | 227 | |
reARMnimator | 9:aeda90624ad0 | 228 | uint_least8_t addressMsb = static_cast<uint_least8_t>(beginAddress >> 8); |
reARMnimator | 9:aeda90624ad0 | 229 | uint_least8_t addressLsb = static_cast<uint_least8_t>(beginAddress >> 0); |
reARMnimator | 9:aeda90624ad0 | 230 | |
reARMnimator | 9:aeda90624ad0 | 231 | uint_least8_t offset = addressLsb & ~(PAGE_SIZE_BYTES - 1); |
reARMnimator | 9:aeda90624ad0 | 232 | offset = addressLsb - offset; |
reARMnimator | 9:aeda90624ad0 | 233 | |
reARMnimator | 9:aeda90624ad0 | 234 | const uint_least8_t sendBlock[] = { ReadMemoryExt, static_cast<uint_least8_t>(addressLsb - offset), addressMsb }; |
reARMnimator | 9:aeda90624ad0 | 235 | owmResult = master->writeBlock(make_span(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]))); |
reARMnimator | 9:aeda90624ad0 | 236 | |
reARMnimator | 9:aeda90624ad0 | 237 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 238 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 239 | } |
reARMnimator | 9:aeda90624ad0 | 240 | |
reARMnimator | 9:aeda90624ad0 | 241 | uint_least16_t crcLocal = 0; |
reARMnimator | 9:aeda90624ad0 | 242 | |
reARMnimator | 9:aeda90624ad0 | 243 | /* ... Calculate CRC of control fields */ |
reARMnimator | 9:aeda90624ad0 | 244 | crcLocal = CRC16(&sendBlock[0], sizeof(sendBlock) / sizeof(sendBlock[0]), crcLocal); |
reARMnimator | 9:aeda90624ad0 | 245 | |
reARMnimator | 9:aeda90624ad0 | 246 | uint_least8_t byte = 0; |
reARMnimator | 9:aeda90624ad0 | 247 | /* ... Calculate CRC of head bytes */ |
reARMnimator | 9:aeda90624ad0 | 248 | { |
reARMnimator | 9:aeda90624ad0 | 249 | uint32_t n = offset; |
reARMnimator | 9:aeda90624ad0 | 250 | while (n--) { |
reARMnimator | 9:aeda90624ad0 | 251 | owmResult = master->readByte(byte); |
reARMnimator | 9:aeda90624ad0 | 252 | crcLocal = CRC16(&byte, sizeof(byte), crcLocal); |
reARMnimator | 9:aeda90624ad0 | 253 | } |
reARMnimator | 9:aeda90624ad0 | 254 | } |
reARMnimator | 9:aeda90624ad0 | 255 | |
reARMnimator | 9:aeda90624ad0 | 256 | /* ... Read data blocks */ |
reARMnimator | 9:aeda90624ad0 | 257 | const size_t blockCnt = dataLen / PAGE_SIZE_BYTES; |
reARMnimator | 9:aeda90624ad0 | 258 | size_t blockLen = PAGE_SIZE_BYTES - offset; |
reARMnimator | 9:aeda90624ad0 | 259 | for (size_t block = 0; block < blockCnt; ++block) |
reARMnimator | 9:aeda90624ad0 | 260 | { |
reARMnimator | 9:aeda90624ad0 | 261 | /* ... Read data */ |
reARMnimator | 9:aeda90624ad0 | 262 | owmResult = master->readBlock(make_span(data, blockLen)); |
reARMnimator | 9:aeda90624ad0 | 263 | |
reARMnimator | 9:aeda90624ad0 | 264 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 265 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 266 | } |
reARMnimator | 9:aeda90624ad0 | 267 | |
reARMnimator | 9:aeda90624ad0 | 268 | /* ... Calculate CRC of data */ |
reARMnimator | 9:aeda90624ad0 | 269 | crcLocal = CRC16(data, blockLen, crcLocal); |
reARMnimator | 9:aeda90624ad0 | 270 | data += blockLen; |
reARMnimator | 9:aeda90624ad0 | 271 | |
reARMnimator | 9:aeda90624ad0 | 272 | /* ... Read CRC */ |
reARMnimator | 9:aeda90624ad0 | 273 | owmResult = processCrc16(master, crcLocal); |
reARMnimator | 9:aeda90624ad0 | 274 | |
reARMnimator | 9:aeda90624ad0 | 275 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 276 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 277 | } |
reARMnimator | 9:aeda90624ad0 | 278 | |
reARMnimator | 9:aeda90624ad0 | 279 | blockLen = PAGE_SIZE_BYTES; |
reARMnimator | 9:aeda90624ad0 | 280 | } |
reARMnimator | 9:aeda90624ad0 | 281 | |
reARMnimator | 9:aeda90624ad0 | 282 | |
reARMnimator | 9:aeda90624ad0 | 283 | /* ... Read data reminder */ |
reARMnimator | 9:aeda90624ad0 | 284 | size_t dataBlockLen = 0; |
reARMnimator | 9:aeda90624ad0 | 285 | size_t remLen = 0; |
reARMnimator | 9:aeda90624ad0 | 286 | if (PAGE_SIZE_BYTES > blockLen) |
reARMnimator | 9:aeda90624ad0 | 287 | { |
reARMnimator | 9:aeda90624ad0 | 288 | |
reARMnimator | 9:aeda90624ad0 | 289 | /* ... Total amount of user data is less than one block */ |
reARMnimator | 9:aeda90624ad0 | 290 | if (PAGE_SIZE_BYTES > (offset + dataLen)) { |
reARMnimator | 9:aeda90624ad0 | 291 | /* ... Total length does not cross block boundary. |
reARMnimator | 9:aeda90624ad0 | 292 | * Read till the end of block. */ |
reARMnimator | 9:aeda90624ad0 | 293 | dataBlockLen = dataLen; |
reARMnimator | 9:aeda90624ad0 | 294 | remLen = blockLen - dataBlockLen; |
reARMnimator | 9:aeda90624ad0 | 295 | |
reARMnimator | 9:aeda90624ad0 | 296 | } |
reARMnimator | 9:aeda90624ad0 | 297 | else { |
reARMnimator | 9:aeda90624ad0 | 298 | /* ... Total length is longer than one block. |
reARMnimator | 9:aeda90624ad0 | 299 | * Read till the end of block and then the rest. */ |
reARMnimator | 9:aeda90624ad0 | 300 | dataBlockLen = blockLen; |
reARMnimator | 9:aeda90624ad0 | 301 | |
reARMnimator | 9:aeda90624ad0 | 302 | /* ... Read data */ |
reARMnimator | 9:aeda90624ad0 | 303 | owmResult = master->readBlock(make_span(data, dataBlockLen)); |
reARMnimator | 9:aeda90624ad0 | 304 | |
reARMnimator | 9:aeda90624ad0 | 305 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 306 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 307 | } |
reARMnimator | 9:aeda90624ad0 | 308 | |
reARMnimator | 9:aeda90624ad0 | 309 | /* ... Calculate CRC of data */ |
reARMnimator | 9:aeda90624ad0 | 310 | crcLocal = CRC16(data, dataBlockLen, crcLocal); |
reARMnimator | 9:aeda90624ad0 | 311 | data += dataBlockLen; |
reARMnimator | 9:aeda90624ad0 | 312 | |
reARMnimator | 9:aeda90624ad0 | 313 | /* ... Read CRC */ |
reARMnimator | 9:aeda90624ad0 | 314 | owmResult = processCrc16(master, crcLocal); |
reARMnimator | 9:aeda90624ad0 | 315 | |
reARMnimator | 9:aeda90624ad0 | 316 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 317 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 318 | } |
reARMnimator | 9:aeda90624ad0 | 319 | |
reARMnimator | 9:aeda90624ad0 | 320 | dataBlockLen = dataLen - dataBlockLen; |
reARMnimator | 9:aeda90624ad0 | 321 | remLen = PAGE_SIZE_BYTES - dataBlockLen; |
reARMnimator | 9:aeda90624ad0 | 322 | } |
reARMnimator | 9:aeda90624ad0 | 323 | |
reARMnimator | 9:aeda90624ad0 | 324 | } |
reARMnimator | 9:aeda90624ad0 | 325 | else |
reARMnimator | 9:aeda90624ad0 | 326 | { |
reARMnimator | 9:aeda90624ad0 | 327 | /* ... Total amount of data is more than one block */ |
reARMnimator | 9:aeda90624ad0 | 328 | dataBlockLen = dataLen % PAGE_SIZE_BYTES; |
reARMnimator | 9:aeda90624ad0 | 329 | remLen = PAGE_SIZE_BYTES - dataBlockLen; |
reARMnimator | 9:aeda90624ad0 | 330 | } |
reARMnimator | 9:aeda90624ad0 | 331 | |
reARMnimator | 9:aeda90624ad0 | 332 | /* ... Read data */ |
reARMnimator | 9:aeda90624ad0 | 333 | owmResult = master->readBlock(make_span(data, dataBlockLen)); |
reARMnimator | 9:aeda90624ad0 | 334 | |
reARMnimator | 9:aeda90624ad0 | 335 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 336 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 337 | } |
reARMnimator | 9:aeda90624ad0 | 338 | |
reARMnimator | 9:aeda90624ad0 | 339 | /* ... Calculate CRC of data */ |
reARMnimator | 9:aeda90624ad0 | 340 | crcLocal = CRC16(data, dataBlockLen, crcLocal); |
reARMnimator | 9:aeda90624ad0 | 341 | data += dataBlockLen; |
reARMnimator | 9:aeda90624ad0 | 342 | |
reARMnimator | 9:aeda90624ad0 | 343 | /* ... Read tail */ |
reARMnimator | 9:aeda90624ad0 | 344 | while (remLen--) { |
reARMnimator | 9:aeda90624ad0 | 345 | owmResult = master->readByte(byte); |
reARMnimator | 9:aeda90624ad0 | 346 | crcLocal = CRC16(&byte, sizeof(byte), crcLocal); |
reARMnimator | 9:aeda90624ad0 | 347 | |
reARMnimator | 9:aeda90624ad0 | 348 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 349 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 350 | } |
reARMnimator | 9:aeda90624ad0 | 351 | } |
reARMnimator | 9:aeda90624ad0 | 352 | |
reARMnimator | 9:aeda90624ad0 | 353 | /* ... Read CRC */ |
reARMnimator | 9:aeda90624ad0 | 354 | owmResult = processCrc16(master, crcLocal); |
reARMnimator | 9:aeda90624ad0 | 355 | |
reARMnimator | 9:aeda90624ad0 | 356 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 357 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 358 | } |
reARMnimator | 9:aeda90624ad0 | 359 | |
reARMnimator | 9:aeda90624ad0 | 360 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 361 | } |
reARMnimator | 9:aeda90624ad0 | 362 | |
reARMnimator | 9:aeda90624ad0 | 363 | |
reARMnimator | 9:aeda90624ad0 | 364 | error_code DS28EC20::writeScratchpad(Address targetAddress, |
reARMnimator | 9:aeda90624ad0 | 365 | const Scratchpad & data) { |
reARMnimator | 9:aeda90624ad0 | 366 | error_code owmResult = selectRom(*master); |
reARMnimator | 9:aeda90624ad0 | 367 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 368 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 369 | } |
reARMnimator | 9:aeda90624ad0 | 370 | |
reARMnimator | 9:aeda90624ad0 | 371 | uint_least8_t addressMsb = static_cast<uint_least8_t>(targetAddress >> 8); |
reARMnimator | 9:aeda90624ad0 | 372 | uint_least8_t addressLsb = static_cast<uint_least8_t>(targetAddress >> 0); |
reARMnimator | 9:aeda90624ad0 | 373 | addressLsb &= ~(pageSizeBytes - 1); |
reARMnimator | 9:aeda90624ad0 | 374 | |
reARMnimator | 9:aeda90624ad0 | 375 | array<uint_least8_t, 3 + Scratchpad::csize> block; |
reARMnimator | 9:aeda90624ad0 | 376 | block[0] = WriteScratchpad; |
reARMnimator | 9:aeda90624ad0 | 377 | block[1] = addressLsb; |
reARMnimator | 9:aeda90624ad0 | 378 | block[2] = addressMsb; |
reARMnimator | 9:aeda90624ad0 | 379 | |
reARMnimator | 9:aeda90624ad0 | 380 | std::copy(data.begin(), data.end(), block.begin() + 3); |
reARMnimator | 9:aeda90624ad0 | 381 | owmResult = master->writeBlock(make_span(block.data(), block.size())); |
reARMnimator | 9:aeda90624ad0 | 382 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 383 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 384 | } |
reARMnimator | 9:aeda90624ad0 | 385 | const uint_fast16_t calculatedCrc = calculateCrc16(make_span(block.data(), block.size())) ^ 0xFFFFU; |
reARMnimator | 9:aeda90624ad0 | 386 | owmResult = master->readBlock(make_span(block.data(), 2)); |
reARMnimator | 9:aeda90624ad0 | 387 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 388 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 389 | } |
reARMnimator | 9:aeda90624ad0 | 390 | if (calculatedCrc != |
reARMnimator | 9:aeda90624ad0 | 391 | ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) { |
reARMnimator | 9:aeda90624ad0 | 392 | owmResult = make_error_code(CrcError); |
reARMnimator | 9:aeda90624ad0 | 393 | } |
reARMnimator | 9:aeda90624ad0 | 394 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 395 | } |
reARMnimator | 9:aeda90624ad0 | 396 | |
reARMnimator | 9:aeda90624ad0 | 397 | error_code DS28EC20::readScratchpad(Scratchpad & data, uint_least8_t & esByte) { |
reARMnimator | 9:aeda90624ad0 | 398 | typedef array<uint_least8_t, 6 + Scratchpad::csize> Block; |
reARMnimator | 9:aeda90624ad0 | 399 | |
reARMnimator | 9:aeda90624ad0 | 400 | error_code owmResult = selectRom(*master); |
reARMnimator | 9:aeda90624ad0 | 401 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 402 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 403 | } |
reARMnimator | 9:aeda90624ad0 | 404 | Block block; block[0] = ReadScratchpad; |
reARMnimator | 9:aeda90624ad0 | 405 | owmResult = master->writeByte(block.front()); |
reARMnimator | 9:aeda90624ad0 | 406 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 407 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 408 | } |
reARMnimator | 9:aeda90624ad0 | 409 | owmResult = master->readBlock(make_span(block.data() + 1, block.size() - 1)); |
reARMnimator | 9:aeda90624ad0 | 410 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 411 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 412 | } |
reARMnimator | 9:aeda90624ad0 | 413 | Block::const_iterator blockIt = block.end(); |
reARMnimator | 9:aeda90624ad0 | 414 | uint_fast16_t receivedCrc = static_cast<uint_fast16_t>(*(--blockIt)) << 8; |
reARMnimator | 9:aeda90624ad0 | 415 | receivedCrc |= *(--blockIt); |
reARMnimator | 9:aeda90624ad0 | 416 | const uint_fast16_t expectedCrc = calculateCrc16(make_span(block.data(), block.size() - 2)) ^ 0xFFFFU; |
reARMnimator | 9:aeda90624ad0 | 417 | if (expectedCrc == receivedCrc) { |
reARMnimator | 9:aeda90624ad0 | 418 | Block::const_iterator blockItEnd = blockIt; |
reARMnimator | 9:aeda90624ad0 | 419 | blockIt -= data.size(); |
reARMnimator | 9:aeda90624ad0 | 420 | std::copy(blockIt, blockItEnd, data.begin()); |
reARMnimator | 9:aeda90624ad0 | 421 | esByte = *(--blockIt); |
reARMnimator | 9:aeda90624ad0 | 422 | } else { |
reARMnimator | 9:aeda90624ad0 | 423 | owmResult = make_error_code(CrcError); |
reARMnimator | 9:aeda90624ad0 | 424 | } |
reARMnimator | 9:aeda90624ad0 | 425 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 426 | } |
reARMnimator | 9:aeda90624ad0 | 427 | |
reARMnimator | 9:aeda90624ad0 | 428 | /* TODO: Test copyScratchpad */ |
reARMnimator | 9:aeda90624ad0 | 429 | error_code DS28EC20::copyScratchpad(Address targetAddress, uint_least8_t esByte) { |
reARMnimator | 9:aeda90624ad0 | 430 | error_code owmResult = selectRom(*master); |
reARMnimator | 9:aeda90624ad0 | 431 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 432 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 433 | } |
reARMnimator | 9:aeda90624ad0 | 434 | |
reARMnimator | 9:aeda90624ad0 | 435 | uint_least8_t addressMsb = static_cast<uint_least8_t>(targetAddress >> 8); |
reARMnimator | 9:aeda90624ad0 | 436 | uint_least8_t addressLsb = static_cast<uint_least8_t>(targetAddress >> 0); |
reARMnimator | 9:aeda90624ad0 | 437 | addressLsb &= ~(pageSizeBytes - 1); |
reARMnimator | 9:aeda90624ad0 | 438 | |
reARMnimator | 9:aeda90624ad0 | 439 | uint_least8_t block[] = {CopyScratchpad, addressLsb, addressMsb}; |
reARMnimator | 9:aeda90624ad0 | 440 | |
reARMnimator | 9:aeda90624ad0 | 441 | owmResult = master->writeBlock(make_span(block, sizeof(block) / sizeof(block[0]))); |
reARMnimator | 9:aeda90624ad0 | 442 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 443 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 444 | } |
reARMnimator | 9:aeda90624ad0 | 445 | owmResult = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel); |
reARMnimator | 9:aeda90624ad0 | 446 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 447 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 448 | } |
reARMnimator | 9:aeda90624ad0 | 449 | (*sleep)(10); |
reARMnimator | 9:aeda90624ad0 | 450 | owmResult = master->setLevel(OneWireMaster::NormalLevel); |
reARMnimator | 9:aeda90624ad0 | 451 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 452 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 453 | } |
reARMnimator | 9:aeda90624ad0 | 454 | owmResult = master->readByte(block[0]); |
reARMnimator | 9:aeda90624ad0 | 455 | if (owmResult) { |
reARMnimator | 9:aeda90624ad0 | 456 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 457 | } |
reARMnimator | 9:aeda90624ad0 | 458 | if (block[0] != 0xAA) { |
reARMnimator | 9:aeda90624ad0 | 459 | owmResult = make_error_code(OperationFailure); |
reARMnimator | 9:aeda90624ad0 | 460 | } |
reARMnimator | 9:aeda90624ad0 | 461 | return owmResult; |
reARMnimator | 9:aeda90624ad0 | 462 | } |
reARMnimator | 9:aeda90624ad0 | 463 | |
reARMnimator | 9:aeda90624ad0 | 464 | const error_category & DS28EC20::errorCategory() { |
reARMnimator | 9:aeda90624ad0 | 465 | static class : public error_category { |
reARMnimator | 9:aeda90624ad0 | 466 | public: |
reARMnimator | 9:aeda90624ad0 | 467 | virtual const char * name() const { return "DS28EC20"; } |
reARMnimator | 9:aeda90624ad0 | 468 | |
reARMnimator | 9:aeda90624ad0 | 469 | virtual std::string message(int condition) const { |
reARMnimator | 9:aeda90624ad0 | 470 | switch (condition) { |
reARMnimator | 9:aeda90624ad0 | 471 | case CrcError: |
reARMnimator | 9:aeda90624ad0 | 472 | return "CRC Error"; |
reARMnimator | 9:aeda90624ad0 | 473 | |
reARMnimator | 9:aeda90624ad0 | 474 | case OperationFailure: |
reARMnimator | 9:aeda90624ad0 | 475 | return "Operation Failure"; |
reARMnimator | 9:aeda90624ad0 | 476 | |
reARMnimator | 9:aeda90624ad0 | 477 | default: |
reARMnimator | 9:aeda90624ad0 | 478 | return defaultErrorMessage(condition); |
reARMnimator | 9:aeda90624ad0 | 479 | } |
reARMnimator | 9:aeda90624ad0 | 480 | } |
reARMnimator | 9:aeda90624ad0 | 481 | } instance; |
reARMnimator | 9:aeda90624ad0 | 482 | return instance; |
reARMnimator | 9:aeda90624ad0 | 483 | } |
reARMnimator | 9:aeda90624ad0 | 484 | |
reARMnimator | 9:aeda90624ad0 | 485 | } // namespace MaximInterface |