Update current library to accommodate small devices.

Committer:
jonebuckman
Date:
Sat Oct 15 19:28:18 2016 +0000
Revision:
3:16227c782723
Parent:
2:5c40bd66662e
Child:
4:5b7d065a1c78
Fixed read and write issues.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jonebuckman 0:bcc1f1890330 1 /* Simple access class for I2C EEPROM chips like Microchip 24LC
jonebuckman 0:bcc1f1890330 2 * Copyright (c) 2016 Jon Buckman
jonebuckman 0:bcc1f1890330 3 * Copyright (c) 2015 Robin Hourahane
jonebuckman 0:bcc1f1890330 4 *
jonebuckman 0:bcc1f1890330 5 * Licensed under the Apache License, Version 2.0 (the "License");
jonebuckman 0:bcc1f1890330 6 * you may not use this file except in compliance with the License.
jonebuckman 0:bcc1f1890330 7 * You may obtain a copy of the License at
jonebuckman 0:bcc1f1890330 8 *
jonebuckman 0:bcc1f1890330 9 * http://www.apache.org/licenses/LICENSE-2.0
jonebuckman 0:bcc1f1890330 10 *
jonebuckman 0:bcc1f1890330 11 * Unless required by applicable law or agreed to in writing, software
jonebuckman 0:bcc1f1890330 12 * distributed under the License is distributed on an "AS IS" BASIS,
jonebuckman 0:bcc1f1890330 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
jonebuckman 0:bcc1f1890330 14 * See the License for the specific language governing permissions and
jonebuckman 0:bcc1f1890330 15 * limitations under the License.
jonebuckman 0:bcc1f1890330 16 */
jonebuckman 0:bcc1f1890330 17 #include "I2CEEPROM.h"
jonebuckman 0:bcc1f1890330 18
jonebuckman 0:bcc1f1890330 19 I2CEEPROM::I2CEEPROM(PinName sda, PinName scl, int address, size_t pageSize, size_t chipSize, int busSpeed):
jonebuckman 0:bcc1f1890330 20 m_i2c(sda, scl),
jonebuckman 0:bcc1f1890330 21 m_i2cAddress(address),
jonebuckman 0:bcc1f1890330 22 m_chipSize(chipSize),
jonebuckman 0:bcc1f1890330 23 m_pageSize(pageSize)
jonebuckman 0:bcc1f1890330 24 {
jonebuckman 0:bcc1f1890330 25 m_i2c.frequency(busSpeed);
jonebuckman 0:bcc1f1890330 26 }
jonebuckman 0:bcc1f1890330 27
jonebuckman 0:bcc1f1890330 28 size_t I2CEEPROM::read(size_t address, char &value) {
jonebuckman 0:bcc1f1890330 29 // Check the address and size fit onto the chip.
jonebuckman 0:bcc1f1890330 30 if (!checkSpace(address, 1))
jonebuckman 0:bcc1f1890330 31 return 0;
jonebuckman 3:16227c782723 32 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 0:bcc1f1890330 33 char values[] = { (address & 0xFF) };
jonebuckman 0:bcc1f1890330 34 if (m_i2c.write(m_i2cAddress, values, 1) == 0) {
jonebuckman 0:bcc1f1890330 35 if (m_i2c.read(m_i2cAddress, &value, 1) == 0) {
jonebuckman 0:bcc1f1890330 36 return 1;
jonebuckman 0:bcc1f1890330 37 }
jonebuckman 0:bcc1f1890330 38 }
jonebuckman 0:bcc1f1890330 39 }
jonebuckman 0:bcc1f1890330 40 else {
jonebuckman 0:bcc1f1890330 41 char values[] = { (address >> 8), (address & 0xFF) };
jonebuckman 0:bcc1f1890330 42 if (m_i2c.write(m_i2cAddress, values, 2) == 0) {
jonebuckman 0:bcc1f1890330 43 if (m_i2c.read(m_i2cAddress, &value, 1) == 0) {
jonebuckman 0:bcc1f1890330 44 return 1;
jonebuckman 0:bcc1f1890330 45 }
jonebuckman 0:bcc1f1890330 46 }
jonebuckman 0:bcc1f1890330 47 }
jonebuckman 0:bcc1f1890330 48
jonebuckman 0:bcc1f1890330 49 return 0;
jonebuckman 0:bcc1f1890330 50 }
jonebuckman 0:bcc1f1890330 51
jonebuckman 0:bcc1f1890330 52 size_t I2CEEPROM::read(size_t address, char *buffer, size_t size) {
jonebuckman 0:bcc1f1890330 53 // Check the address and size fit onto the chip.
jonebuckman 0:bcc1f1890330 54 if (!checkSpace(address, size))
jonebuckman 0:bcc1f1890330 55 return 0;
jonebuckman 0:bcc1f1890330 56
jonebuckman 3:16227c782723 57 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 0:bcc1f1890330 58 char values[] = { (address & 0xFF) };
jonebuckman 0:bcc1f1890330 59 if (m_i2c.write(m_i2cAddress, values, 1) == 0) {
jonebuckman 0:bcc1f1890330 60 if (m_i2c.read(m_i2cAddress, buffer, size) == 0) {
jonebuckman 0:bcc1f1890330 61 return size;
jonebuckman 0:bcc1f1890330 62 }
jonebuckman 0:bcc1f1890330 63 }
jonebuckman 0:bcc1f1890330 64 }
jonebuckman 0:bcc1f1890330 65 else {
jonebuckman 0:bcc1f1890330 66 char values[] = { (address >> 8), (address & 0xFF) };
jonebuckman 0:bcc1f1890330 67 if (m_i2c.write(m_i2cAddress, values, 2) == 0) {
jonebuckman 0:bcc1f1890330 68 if (m_i2c.read(m_i2cAddress, buffer, size) == 0) {
jonebuckman 0:bcc1f1890330 69 return size;
jonebuckman 0:bcc1f1890330 70 }
jonebuckman 0:bcc1f1890330 71 }
jonebuckman 0:bcc1f1890330 72 }
jonebuckman 0:bcc1f1890330 73
jonebuckman 0:bcc1f1890330 74 return 0;
jonebuckman 0:bcc1f1890330 75 }
jonebuckman 0:bcc1f1890330 76
jonebuckman 0:bcc1f1890330 77 size_t I2CEEPROM::write(size_t address, char value) {
jonebuckman 0:bcc1f1890330 78 // Check the address and size fit onto the chip.
jonebuckman 0:bcc1f1890330 79 if (!checkSpace(address, 1))
jonebuckman 0:bcc1f1890330 80 return 0;
jonebuckman 0:bcc1f1890330 81
jonebuckman 3:16227c782723 82 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 0:bcc1f1890330 83 char values[] = { (address & 0xFF), value };
jonebuckman 0:bcc1f1890330 84 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 0:bcc1f1890330 85 return 0;
jonebuckman 0:bcc1f1890330 86 }
jonebuckman 0:bcc1f1890330 87 }
jonebuckman 0:bcc1f1890330 88 else {
jonebuckman 0:bcc1f1890330 89 char values[] = { (address >> 8), (address & 0xFF), value };
jonebuckman 0:bcc1f1890330 90 if (m_i2c.write(m_i2cAddress, values, 3) != 0) {
jonebuckman 0:bcc1f1890330 91 return 0;
jonebuckman 0:bcc1f1890330 92 }
jonebuckman 0:bcc1f1890330 93 }
jonebuckman 0:bcc1f1890330 94
jonebuckman 0:bcc1f1890330 95 waitForWrite();
jonebuckman 0:bcc1f1890330 96
jonebuckman 0:bcc1f1890330 97 return 1;
jonebuckman 0:bcc1f1890330 98 }
jonebuckman 0:bcc1f1890330 99
jonebuckman 0:bcc1f1890330 100 size_t I2CEEPROM::write(size_t address, const char *buffer, size_t size) {
jonebuckman 0:bcc1f1890330 101 // Check the address and size fit onto the chip.
jonebuckman 3:16227c782723 102 if (!checkSpace(address, size)) {
jonebuckman 0:bcc1f1890330 103 return 0;
jonebuckman 3:16227c782723 104 }
jonebuckman 0:bcc1f1890330 105
jonebuckman 0:bcc1f1890330 106 const char *page = buffer;
jonebuckman 0:bcc1f1890330 107 size_t left = size;
jonebuckman 0:bcc1f1890330 108
jonebuckman 0:bcc1f1890330 109 // Whle we have some more data to write.
jonebuckman 0:bcc1f1890330 110 while (left != 0) {
jonebuckman 0:bcc1f1890330 111 // Calculate the number of bytes we can write in the current page.
jonebuckman 0:bcc1f1890330 112 // If the address is not page aligned then write enough to page
jonebuckman 0:bcc1f1890330 113 // align it.
jonebuckman 0:bcc1f1890330 114 size_t toWrite;
jonebuckman 0:bcc1f1890330 115 if ((address % m_pageSize) != 0) {
jonebuckman 0:bcc1f1890330 116 toWrite = (((address / m_pageSize) + 1) * m_pageSize) - address;
jonebuckman 0:bcc1f1890330 117 if (toWrite > size) {
jonebuckman 0:bcc1f1890330 118 toWrite = size;
jonebuckman 0:bcc1f1890330 119 }
jonebuckman 0:bcc1f1890330 120 } else {
jonebuckman 0:bcc1f1890330 121 if (left <= m_pageSize) {
jonebuckman 0:bcc1f1890330 122 toWrite = left;
jonebuckman 0:bcc1f1890330 123 } else {
jonebuckman 0:bcc1f1890330 124 toWrite = m_pageSize;
jonebuckman 0:bcc1f1890330 125 }
jonebuckman 0:bcc1f1890330 126 }
jonebuckman 0:bcc1f1890330 127
jonebuckman 3:16227c782723 128 //pc.printf("Writing [%.*s] at %d size %d\n\r", toWrite, page, address, toWrite);
jonebuckman 3:16227c782723 129 // Start the page write with the address in one write call.
jonebuckman 3:16227c782723 130 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 3:16227c782723 131 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 132 int addr = address + count;
jonebuckman 3:16227c782723 133 char values[] = { (addr & 0xFF), *page };
jonebuckman 3:16227c782723 134 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 3:16227c782723 135 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 136 return size - left;
jonebuckman 3:16227c782723 137 }
jonebuckman 3:16227c782723 138 ++page;
jonebuckman 3:16227c782723 139 waitForWrite();
jonebuckman 0:bcc1f1890330 140 }
jonebuckman 0:bcc1f1890330 141 }
jonebuckman 0:bcc1f1890330 142 else {
jonebuckman 3:16227c782723 143 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 144 int addr = address + count;
jonebuckman 3:16227c782723 145 char values[] = { (addr >> 8), (addr & 0xFF) };
jonebuckman 3:16227c782723 146 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 3:16227c782723 147 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 148 return size - left;
jonebuckman 3:16227c782723 149 }
jonebuckman 3:16227c782723 150 ++page;
jonebuckman 3:16227c782723 151 waitForWrite();
jonebuckman 0:bcc1f1890330 152 }
jonebuckman 0:bcc1f1890330 153 }
jonebuckman 0:bcc1f1890330 154
jonebuckman 0:bcc1f1890330 155 // Update the counters with the amount we've just written
jonebuckman 0:bcc1f1890330 156 left -= toWrite;
jonebuckman 0:bcc1f1890330 157 address += toWrite;
jonebuckman 0:bcc1f1890330 158 }
jonebuckman 3:16227c782723 159
jonebuckman 0:bcc1f1890330 160 return size;
jonebuckman 0:bcc1f1890330 161 }
jonebuckman 0:bcc1f1890330 162
jonebuckman 0:bcc1f1890330 163 size_t I2CEEPROM::fill(size_t address, char value, size_t size) {
jonebuckman 0:bcc1f1890330 164 // Check the address and size fit onto the chip.
jonebuckman 0:bcc1f1890330 165 if (!checkSpace(address, size))
jonebuckman 0:bcc1f1890330 166 return 0;
jonebuckman 0:bcc1f1890330 167
jonebuckman 0:bcc1f1890330 168 size_t left = size;
jonebuckman 3:16227c782723 169
jonebuckman 0:bcc1f1890330 170 while (left != 0) {
jonebuckman 3:16227c782723 171 //i2c.start();
jonebuckman 3:16227c782723 172 int toWrite;
jonebuckman 0:bcc1f1890330 173 if ((address % m_pageSize) != 0) {
jonebuckman 0:bcc1f1890330 174 toWrite = (((address / m_pageSize) + 1) * m_pageSize) - address;
jonebuckman 0:bcc1f1890330 175 if (toWrite > size) {
jonebuckman 0:bcc1f1890330 176 toWrite = size;
jonebuckman 0:bcc1f1890330 177 }
jonebuckman 0:bcc1f1890330 178 } else {
jonebuckman 0:bcc1f1890330 179 if (left <= m_pageSize) {
jonebuckman 0:bcc1f1890330 180 toWrite = left;
jonebuckman 0:bcc1f1890330 181 } else {
jonebuckman 0:bcc1f1890330 182 toWrite = m_pageSize;
jonebuckman 0:bcc1f1890330 183 }
jonebuckman 0:bcc1f1890330 184 }
jonebuckman 0:bcc1f1890330 185
jonebuckman 0:bcc1f1890330 186 //printf("Writing %d at %d size %d\n\r", value, address, toWrite);
jonebuckman 3:16227c782723 187 // Start the page write with the address in one write call.
jonebuckman 3:16227c782723 188 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 3:16227c782723 189 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 190 int addr = address + count;
jonebuckman 3:16227c782723 191 char values[] = { (addr & 0xFF), value };
jonebuckman 3:16227c782723 192 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 3:16227c782723 193 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 194 return size - left;
jonebuckman 3:16227c782723 195 }
jonebuckman 3:16227c782723 196 waitForWrite();
jonebuckman 0:bcc1f1890330 197 }
jonebuckman 0:bcc1f1890330 198 }
jonebuckman 0:bcc1f1890330 199 else {
jonebuckman 3:16227c782723 200 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 201 int addr = address + count;
jonebuckman 3:16227c782723 202 char values[] = { (addr >> 8), (addr & 0xFF) };
jonebuckman 3:16227c782723 203 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 3:16227c782723 204 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 205 return size - left;
jonebuckman 3:16227c782723 206 }
jonebuckman 3:16227c782723 207 waitForWrite();
jonebuckman 0:bcc1f1890330 208 }
jonebuckman 0:bcc1f1890330 209 }
jonebuckman 0:bcc1f1890330 210
jonebuckman 3:16227c782723 211 // Update the counters with the amount we've just written
jonebuckman 0:bcc1f1890330 212 left -= toWrite;
jonebuckman 0:bcc1f1890330 213 address += toWrite;
jonebuckman 0:bcc1f1890330 214 }
jonebuckman 0:bcc1f1890330 215
jonebuckman 0:bcc1f1890330 216 return size;
jonebuckman 0:bcc1f1890330 217 }
jonebuckman 0:bcc1f1890330 218
jonebuckman 0:bcc1f1890330 219 void I2CEEPROM::waitForWrite() {
jonebuckman 0:bcc1f1890330 220 // The chip doesn't ACK while writing to the actual EEPROM
jonebuckman 0:bcc1f1890330 221 // so loop trying to do a zero byte write until it is ACKed
jonebuckman 0:bcc1f1890330 222 // by the chip.
jonebuckman 3:16227c782723 223 //while (m_i2c.write(m_i2cAddress, 0, 0) != 0) {
jonebuckman 0:bcc1f1890330 224 // Wait for ack.
jonebuckman 3:16227c782723 225 wait_ms(5);
jonebuckman 3:16227c782723 226 //}
jonebuckman 0:bcc1f1890330 227 }
jonebuckman 0:bcc1f1890330 228
jonebuckman 0:bcc1f1890330 229 bool I2CEEPROM::checkSpace(size_t address, size_t size) {
jonebuckman 0:bcc1f1890330 230 // Only check if chip size is non-zero.
jonebuckman 0:bcc1f1890330 231 if (m_chipSize != 0) {
jonebuckman 0:bcc1f1890330 232 // Check that the address start in the chip and doesn't
jonebuckman 0:bcc1f1890330 233 // extend past.
jonebuckman 0:bcc1f1890330 234 if ((address >= m_chipSize) || ((address + size) >= m_chipSize))
jonebuckman 0:bcc1f1890330 235 return false;
jonebuckman 0:bcc1f1890330 236 else
jonebuckman 0:bcc1f1890330 237 return true;
jonebuckman 0:bcc1f1890330 238 }
jonebuckman 0:bcc1f1890330 239
jonebuckman 0:bcc1f1890330 240 return true;
jonebuckman 0:bcc1f1890330 241 }
jonebuckman 0:bcc1f1890330 242