I2C EEPROM library for 1k to 512k chip
EEPROM.cpp@0:68c79e5c722b, 2016-06-23 (annotated)
- Committer:
- Wodji
- Date:
- Thu Jun 23 15:57:16 2016 +0000
- Revision:
- 0:68c79e5c722b
Library of i2c eeprom from 1k to 512k chip
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wodji | 0:68c79e5c722b | 1 | /** |
Wodji | 0:68c79e5c722b | 2 | ***************************************************************************** |
Wodji | 0:68c79e5c722b | 3 | * File Name : EEPROM.cpp |
Wodji | 0:68c79e5c722b | 4 | * |
Wodji | 0:68c79e5c722b | 5 | * Title : I2C EEPROM 24LCXXX Claass Source File |
Wodji | 0:68c79e5c722b | 6 | * Revision : 1.0 |
Wodji | 0:68c79e5c722b | 7 | * Notes : |
Wodji | 0:68c79e5c722b | 8 | * Target Board : mbed NXP LPC1768, mbed LPC1114FN28 etc |
Wodji | 0:68c79e5c722b | 9 | * |
Wodji | 0:68c79e5c722b | 10 | * Revision History: |
Wodji | 0:68c79e5c722b | 11 | * When Who Description of change |
Wodji | 0:68c79e5c722b | 12 | * ----------- ----------- ---------------------- |
Wodji | 0:68c79e5c722b | 13 | * |
Wodji | 0:68c79e5c722b | 14 | ***************************************************************************** |
Wodji | 0:68c79e5c722b | 15 | * |
Wodji | 0:68c79e5c722b | 16 | * Copyright (C) 2016 wodji |
Wodji | 0:68c79e5c722b | 17 | * |
Wodji | 0:68c79e5c722b | 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
Wodji | 0:68c79e5c722b | 19 | * and associated documentation files (the "Software"), to deal in the Software without restriction, |
Wodji | 0:68c79e5c722b | 20 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, |
Wodji | 0:68c79e5c722b | 21 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
Wodji | 0:68c79e5c722b | 22 | * furnished to do so, subject to the following conditions: |
Wodji | 0:68c79e5c722b | 23 | * |
Wodji | 0:68c79e5c722b | 24 | * The above copyright notice and this permission notice shall be included in all copies or |
Wodji | 0:68c79e5c722b | 25 | * substantial portions of the Software. |
Wodji | 0:68c79e5c722b | 26 | * |
Wodji | 0:68c79e5c722b | 27 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
Wodji | 0:68c79e5c722b | 28 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
Wodji | 0:68c79e5c722b | 29 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
Wodji | 0:68c79e5c722b | 30 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
Wodji | 0:68c79e5c722b | 31 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
Wodji | 0:68c79e5c722b | 32 | * |
Wodji | 0:68c79e5c722b | 33 | **/ |
Wodji | 0:68c79e5c722b | 34 | |
Wodji | 0:68c79e5c722b | 35 | #include <EEPROM.h> |
Wodji | 0:68c79e5c722b | 36 | |
Wodji | 0:68c79e5c722b | 37 | |
Wodji | 0:68c79e5c722b | 38 | EEPROM::EEPROM(I2C* i2c, const device_t device, const int deviceAddress) : |
Wodji | 0:68c79e5c722b | 39 | _deviceAddress(deviceAddress << 1), _i2c(i2c), _device(device){ |
Wodji | 0:68c79e5c722b | 40 | } |
Wodji | 0:68c79e5c722b | 41 | |
Wodji | 0:68c79e5c722b | 42 | EEPROM::EEPROM(PinName sda, PinName scl, const device_t device, |
Wodji | 0:68c79e5c722b | 43 | const int deviceAddress) : _deviceAddress(deviceAddress << 1), _device(device){ |
Wodji | 0:68c79e5c722b | 44 | _i2c = new I2C(sda, scl); |
Wodji | 0:68c79e5c722b | 45 | } |
Wodji | 0:68c79e5c722b | 46 | |
Wodji | 0:68c79e5c722b | 47 | int EEPROM::read(int memoryAddress, char* data, int dataLength){ |
Wodji | 0:68c79e5c722b | 48 | int errnum = -1; |
Wodji | 0:68c79e5c722b | 49 | if((memoryAddress + dataLength) > _device.maxAddress) return errnum; |
Wodji | 0:68c79e5c722b | 50 | int loc_deviceAddress = _deviceAddress; |
Wodji | 0:68c79e5c722b | 51 | |
Wodji | 0:68c79e5c722b | 52 | if (_device < C24LC04){ |
Wodji | 0:68c79e5c722b | 53 | char loc_memoryAddress = (char)memoryAddress; |
Wodji | 0:68c79e5c722b | 54 | errnum = readEXE(loc_deviceAddress, &loc_memoryAddress, 1, data, dataLength); |
Wodji | 0:68c79e5c722b | 55 | } |
Wodji | 0:68c79e5c722b | 56 | else if (_device > C24LC02 && _device < C24LC32){ |
Wodji | 0:68c79e5c722b | 57 | int totalBlocksSize = BLOCK_SIZE; |
Wodji | 0:68c79e5c722b | 58 | char loc_memoryAddres; |
Wodji | 0:68c79e5c722b | 59 | int startBlock, blocksToRead, remindLength, partLength = 0; |
Wodji | 0:68c79e5c722b | 60 | int loc_dataLength[_device.blockNumbers]; |
Wodji | 0:68c79e5c722b | 61 | |
Wodji | 0:68c79e5c722b | 62 | for (int i = 0; i < _device.blockNumbers; i++){ |
Wodji | 0:68c79e5c722b | 63 | if (memoryAddress < totalBlocksSize){ |
Wodji | 0:68c79e5c722b | 64 | startBlock = i; |
Wodji | 0:68c79e5c722b | 65 | loc_memoryAddres = memoryAddress - (BLOCK_SIZE * startBlock); |
Wodji | 0:68c79e5c722b | 66 | break; |
Wodji | 0:68c79e5c722b | 67 | } |
Wodji | 0:68c79e5c722b | 68 | else totalBlocksSize =+ BLOCK_SIZE; |
Wodji | 0:68c79e5c722b | 69 | } |
Wodji | 0:68c79e5c722b | 70 | |
Wodji | 0:68c79e5c722b | 71 | loc_dataLength[0] = BLOCK_SIZE - loc_memoryAddres; |
Wodji | 0:68c79e5c722b | 72 | if (dataLength <= loc_dataLength[0]){ |
Wodji | 0:68c79e5c722b | 73 | loc_dataLength[0] = dataLength; |
Wodji | 0:68c79e5c722b | 74 | blocksToRead = 1; |
Wodji | 0:68c79e5c722b | 75 | } |
Wodji | 0:68c79e5c722b | 76 | else { |
Wodji | 0:68c79e5c722b | 77 | remindLength = dataLength - loc_dataLength[0]; |
Wodji | 0:68c79e5c722b | 78 | for (int i = 1; i < _device.blockNumbers; i++) { |
Wodji | 0:68c79e5c722b | 79 | if (remindLength <= BLOCK_SIZE) { |
Wodji | 0:68c79e5c722b | 80 | loc_dataLength[i] = remindLength; |
Wodji | 0:68c79e5c722b | 81 | blocksToRead++; |
Wodji | 0:68c79e5c722b | 82 | break; |
Wodji | 0:68c79e5c722b | 83 | } |
Wodji | 0:68c79e5c722b | 84 | loc_dataLength[i] = BLOCK_SIZE; |
Wodji | 0:68c79e5c722b | 85 | remindLength -= BLOCK_SIZE; |
Wodji | 0:68c79e5c722b | 86 | } |
Wodji | 0:68c79e5c722b | 87 | } |
Wodji | 0:68c79e5c722b | 88 | |
Wodji | 0:68c79e5c722b | 89 | for (int i = 0; i < blocksToRead; i++){ |
Wodji | 0:68c79e5c722b | 90 | loc_deviceAddress &= 0xF0; |
Wodji | 0:68c79e5c722b | 91 | loc_deviceAddress |= (startBlock << 1); |
Wodji | 0:68c79e5c722b | 92 | errnum = readEXE(loc_deviceAddress, &loc_memoryAddres, 1, &data[partLength], loc_dataLength[i]); |
Wodji | 0:68c79e5c722b | 93 | if (errnum != 0) return errnum; |
Wodji | 0:68c79e5c722b | 94 | partLength += loc_dataLength[i]; |
Wodji | 0:68c79e5c722b | 95 | startBlock++; |
Wodji | 0:68c79e5c722b | 96 | loc_memoryAddres = 0x00; |
Wodji | 0:68c79e5c722b | 97 | } |
Wodji | 0:68c79e5c722b | 98 | } |
Wodji | 0:68c79e5c722b | 99 | else { |
Wodji | 0:68c79e5c722b | 100 | char loc_memoryAddress[2]; |
Wodji | 0:68c79e5c722b | 101 | loc_memoryAddress[0] = (char)(memoryAddress >> 8); // Read Address High byte set |
Wodji | 0:68c79e5c722b | 102 | loc_memoryAddress[1] = (char)memoryAddress; // Read Address Low byte set |
Wodji | 0:68c79e5c722b | 103 | errnum = readEXE(loc_deviceAddress, loc_memoryAddress, 2, data, dataLength); |
Wodji | 0:68c79e5c722b | 104 | } |
Wodji | 0:68c79e5c722b | 105 | return errnum; |
Wodji | 0:68c79e5c722b | 106 | } |
Wodji | 0:68c79e5c722b | 107 | |
Wodji | 0:68c79e5c722b | 108 | int EEPROM::write(int memoryAddress, const char* data, int dataLength){ |
Wodji | 0:68c79e5c722b | 109 | int errnum = -1; |
Wodji | 0:68c79e5c722b | 110 | if((memoryAddress + dataLength) > _device.maxAddress) return errnum; |
Wodji | 0:68c79e5c722b | 111 | |
Wodji | 0:68c79e5c722b | 112 | int offset = 0; |
Wodji | 0:68c79e5c722b | 113 | while(offset < dataLength) { |
Wodji | 0:68c79e5c722b | 114 | int loc_dataLength = _device.pageSize - ((memoryAddress + offset) % _device.pageSize); |
Wodji | 0:68c79e5c722b | 115 | if((offset + loc_dataLength) > dataLength) loc_dataLength = dataLength - offset; |
Wodji | 0:68c79e5c722b | 116 | errnum = writePage((memoryAddress + offset), (data + offset), loc_dataLength); |
Wodji | 0:68c79e5c722b | 117 | if(errnum != 0) return errnum; |
Wodji | 0:68c79e5c722b | 118 | offset += loc_dataLength; |
Wodji | 0:68c79e5c722b | 119 | } |
Wodji | 0:68c79e5c722b | 120 | return errnum; |
Wodji | 0:68c79e5c722b | 121 | } |
Wodji | 0:68c79e5c722b | 122 | |
Wodji | 0:68c79e5c722b | 123 | int EEPROM::writePage(int memoryAddress, const char* data, int dataLength){ |
Wodji | 0:68c79e5c722b | 124 | int errnum = -1; |
Wodji | 0:68c79e5c722b | 125 | if(((memoryAddress % _device.pageSize) + dataLength) > _device.pageSize) return errnum; |
Wodji | 0:68c79e5c722b | 126 | int loc_deviceAddress = _deviceAddress; |
Wodji | 0:68c79e5c722b | 127 | |
Wodji | 0:68c79e5c722b | 128 | if (_device < C24LC04) { |
Wodji | 0:68c79e5c722b | 129 | char loc_memoryAddress = (char)memoryAddress; |
Wodji | 0:68c79e5c722b | 130 | errnum = writeEXE(loc_deviceAddress, &loc_memoryAddress, sizeof(loc_memoryAddress), data, dataLength); |
Wodji | 0:68c79e5c722b | 131 | } |
Wodji | 0:68c79e5c722b | 132 | else if (_device > C24LC02 && _device < C24LC32){ |
Wodji | 0:68c79e5c722b | 133 | int totalBlocksSize = BLOCK_SIZE; |
Wodji | 0:68c79e5c722b | 134 | char loc_memoryAddres; |
Wodji | 0:68c79e5c722b | 135 | int startBlock, blocksToWrite, remindLength, partLength = 0; |
Wodji | 0:68c79e5c722b | 136 | int loc_dataLength[2]; |
Wodji | 0:68c79e5c722b | 137 | |
Wodji | 0:68c79e5c722b | 138 | for (int i = 0; i < _device.blockNumbers; i++){ |
Wodji | 0:68c79e5c722b | 139 | if (memoryAddress < totalBlocksSize){ |
Wodji | 0:68c79e5c722b | 140 | startBlock = i; |
Wodji | 0:68c79e5c722b | 141 | loc_memoryAddres = memoryAddress - (BLOCK_SIZE * startBlock); |
Wodji | 0:68c79e5c722b | 142 | break; |
Wodji | 0:68c79e5c722b | 143 | } |
Wodji | 0:68c79e5c722b | 144 | else totalBlocksSize =+ BLOCK_SIZE; |
Wodji | 0:68c79e5c722b | 145 | } |
Wodji | 0:68c79e5c722b | 146 | |
Wodji | 0:68c79e5c722b | 147 | loc_dataLength[0] = BLOCK_SIZE - loc_memoryAddres; |
Wodji | 0:68c79e5c722b | 148 | if (dataLength <= loc_dataLength[0]){ |
Wodji | 0:68c79e5c722b | 149 | loc_dataLength[0] = dataLength; |
Wodji | 0:68c79e5c722b | 150 | blocksToWrite = 1; |
Wodji | 0:68c79e5c722b | 151 | } |
Wodji | 0:68c79e5c722b | 152 | else { |
Wodji | 0:68c79e5c722b | 153 | loc_dataLength[1] = dataLength - loc_dataLength[0]; |
Wodji | 0:68c79e5c722b | 154 | blocksToWrite = 2; |
Wodji | 0:68c79e5c722b | 155 | } |
Wodji | 0:68c79e5c722b | 156 | |
Wodji | 0:68c79e5c722b | 157 | for (int i = 0; i < blocksToWrite; i++){ |
Wodji | 0:68c79e5c722b | 158 | loc_deviceAddress &= 0xF0; |
Wodji | 0:68c79e5c722b | 159 | loc_deviceAddress |= (startBlock << 1); |
Wodji | 0:68c79e5c722b | 160 | errnum = writeEXE(loc_deviceAddress, &loc_memoryAddres, 1, &data[partLength], loc_dataLength[i]); |
Wodji | 0:68c79e5c722b | 161 | if (errnum != 0) return errnum; |
Wodji | 0:68c79e5c722b | 162 | partLength += loc_dataLength[i]; |
Wodji | 0:68c79e5c722b | 163 | startBlock++; |
Wodji | 0:68c79e5c722b | 164 | loc_memoryAddres = 0x00; |
Wodji | 0:68c79e5c722b | 165 | } |
Wodji | 0:68c79e5c722b | 166 | } |
Wodji | 0:68c79e5c722b | 167 | else { |
Wodji | 0:68c79e5c722b | 168 | char loc_memoryAddress[2]; |
Wodji | 0:68c79e5c722b | 169 | loc_memoryAddress[0] = (char)(memoryAddress >> 8); // Write Address High byte set |
Wodji | 0:68c79e5c722b | 170 | loc_memoryAddress[1] = (char)memoryAddress; // Write Address Low byte set |
Wodji | 0:68c79e5c722b | 171 | errnum = writeEXE(loc_deviceAddress, loc_memoryAddress, sizeof(loc_memoryAddress), data, dataLength); |
Wodji | 0:68c79e5c722b | 172 | } |
Wodji | 0:68c79e5c722b | 173 | return errnum; |
Wodji | 0:68c79e5c722b | 174 | } |
Wodji | 0:68c79e5c722b | 175 | |
Wodji | 0:68c79e5c722b | 176 | int EEPROM::readEXE(int deviceAddress, char* address, int addressLength, char* data, int dataLength){ |
Wodji | 0:68c79e5c722b | 177 | int errnum; |
Wodji | 0:68c79e5c722b | 178 | errnum = _i2c->write(deviceAddress, address, addressLength, true); |
Wodji | 0:68c79e5c722b | 179 | if(errnum != 0)return errnum; |
Wodji | 0:68c79e5c722b | 180 | return _i2c->read(deviceAddress, data, dataLength, false); |
Wodji | 0:68c79e5c722b | 181 | } |
Wodji | 0:68c79e5c722b | 182 | |
Wodji | 0:68c79e5c722b | 183 | int EEPROM::writeEXE(int deviceAddress, char* memoryAddress, int addressLength, const char* data, int dataLength){ |
Wodji | 0:68c79e5c722b | 184 | int errnum; |
Wodji | 0:68c79e5c722b | 185 | char loc_data[addressLength + dataLength]; |
Wodji | 0:68c79e5c722b | 186 | for(int i = 0; i < addressLength; i++) loc_data[i] = memoryAddress[i]; |
Wodji | 0:68c79e5c722b | 187 | for(int i = 0; i < dataLength; i++) loc_data[i + addressLength] = data[i]; |
Wodji | 0:68c79e5c722b | 188 | errnum = _i2c->write(deviceAddress, loc_data, sizeof(loc_data), false); |
Wodji | 0:68c79e5c722b | 189 | wait_ms(5); |
Wodji | 0:68c79e5c722b | 190 | return errnum; |
Wodji | 0:68c79e5c722b | 191 | } |