Update current library to accommodate small devices.

Committer:
jonebuckman
Date:
Sun Oct 16 11:54:09 2016 +0000
Revision:
4:5b7d065a1c78
Parent:
3:16227c782723
Child:
5:02908f98dca1
Added extended addressing.

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 4:5b7d065a1c78 41 char i2caddr = (m_i2cAddress | address >> 7) & 0xFF;
jonebuckman 4:5b7d065a1c78 42 char values[] = { (address & 0xFF) };
jonebuckman 4:5b7d065a1c78 43 if (m_i2c.write(i2caddr, values, 1) == 0) {
jonebuckman 0:bcc1f1890330 44 if (m_i2c.read(m_i2cAddress, &value, 1) == 0) {
jonebuckman 0:bcc1f1890330 45 return 1;
jonebuckman 0:bcc1f1890330 46 }
jonebuckman 0:bcc1f1890330 47 }
jonebuckman 0:bcc1f1890330 48 }
jonebuckman 0:bcc1f1890330 49
jonebuckman 0:bcc1f1890330 50 return 0;
jonebuckman 0:bcc1f1890330 51 }
jonebuckman 0:bcc1f1890330 52
jonebuckman 0:bcc1f1890330 53 size_t I2CEEPROM::read(size_t address, char *buffer, size_t size) {
jonebuckman 0:bcc1f1890330 54 // Check the address and size fit onto the chip.
jonebuckman 0:bcc1f1890330 55 if (!checkSpace(address, size))
jonebuckman 0:bcc1f1890330 56 return 0;
jonebuckman 0:bcc1f1890330 57
jonebuckman 3:16227c782723 58 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 0:bcc1f1890330 59 char values[] = { (address & 0xFF) };
jonebuckman 0:bcc1f1890330 60 if (m_i2c.write(m_i2cAddress, values, 1) == 0) {
jonebuckman 0:bcc1f1890330 61 if (m_i2c.read(m_i2cAddress, buffer, size) == 0) {
jonebuckman 0:bcc1f1890330 62 return size;
jonebuckman 0:bcc1f1890330 63 }
jonebuckman 0:bcc1f1890330 64 }
jonebuckman 0:bcc1f1890330 65 }
jonebuckman 0:bcc1f1890330 66 else {
jonebuckman 4:5b7d065a1c78 67 char i2caddr = (m_i2cAddress | address >> 7) & 0xFF;
jonebuckman 4:5b7d065a1c78 68 char values[] = { (address & 0xFF) };
jonebuckman 4:5b7d065a1c78 69 if (m_i2c.write(i2caddr, values, 1) == 0) {
jonebuckman 4:5b7d065a1c78 70 if (m_i2c.read(i2caddr, buffer, size) == 0) {
jonebuckman 0:bcc1f1890330 71 return size;
jonebuckman 0:bcc1f1890330 72 }
jonebuckman 0:bcc1f1890330 73 }
jonebuckman 0:bcc1f1890330 74 }
jonebuckman 0:bcc1f1890330 75
jonebuckman 0:bcc1f1890330 76 return 0;
jonebuckman 0:bcc1f1890330 77 }
jonebuckman 0:bcc1f1890330 78
jonebuckman 0:bcc1f1890330 79 size_t I2CEEPROM::write(size_t address, char value) {
jonebuckman 0:bcc1f1890330 80 // Check the address and size fit onto the chip.
jonebuckman 0:bcc1f1890330 81 if (!checkSpace(address, 1))
jonebuckman 0:bcc1f1890330 82 return 0;
jonebuckman 0:bcc1f1890330 83
jonebuckman 3:16227c782723 84 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 0:bcc1f1890330 85 char values[] = { (address & 0xFF), value };
jonebuckman 0:bcc1f1890330 86 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 0:bcc1f1890330 87 return 0;
jonebuckman 0:bcc1f1890330 88 }
jonebuckman 0:bcc1f1890330 89 }
jonebuckman 0:bcc1f1890330 90 else {
jonebuckman 4:5b7d065a1c78 91 char i2caddr = (m_i2cAddress | address >> 7) & 0xFF;
jonebuckman 4:5b7d065a1c78 92 char values[] = { (address & 0xFF), value };
jonebuckman 4:5b7d065a1c78 93 if (m_i2c.write(i2caddr, values, 2) != 0) {
jonebuckman 0:bcc1f1890330 94 return 0;
jonebuckman 0:bcc1f1890330 95 }
jonebuckman 0:bcc1f1890330 96 }
jonebuckman 0:bcc1f1890330 97
jonebuckman 0:bcc1f1890330 98 waitForWrite();
jonebuckman 0:bcc1f1890330 99
jonebuckman 0:bcc1f1890330 100 return 1;
jonebuckman 0:bcc1f1890330 101 }
jonebuckman 0:bcc1f1890330 102
jonebuckman 0:bcc1f1890330 103 size_t I2CEEPROM::write(size_t address, const char *buffer, size_t size) {
jonebuckman 0:bcc1f1890330 104 // Check the address and size fit onto the chip.
jonebuckman 3:16227c782723 105 if (!checkSpace(address, size)) {
jonebuckman 0:bcc1f1890330 106 return 0;
jonebuckman 3:16227c782723 107 }
jonebuckman 0:bcc1f1890330 108
jonebuckman 0:bcc1f1890330 109 const char *page = buffer;
jonebuckman 0:bcc1f1890330 110 size_t left = size;
jonebuckman 0:bcc1f1890330 111
jonebuckman 0:bcc1f1890330 112 // Whle we have some more data to write.
jonebuckman 0:bcc1f1890330 113 while (left != 0) {
jonebuckman 0:bcc1f1890330 114 // Calculate the number of bytes we can write in the current page.
jonebuckman 0:bcc1f1890330 115 // If the address is not page aligned then write enough to page
jonebuckman 0:bcc1f1890330 116 // align it.
jonebuckman 0:bcc1f1890330 117 size_t toWrite;
jonebuckman 0:bcc1f1890330 118 if ((address % m_pageSize) != 0) {
jonebuckman 0:bcc1f1890330 119 toWrite = (((address / m_pageSize) + 1) * m_pageSize) - address;
jonebuckman 0:bcc1f1890330 120 if (toWrite > size) {
jonebuckman 0:bcc1f1890330 121 toWrite = size;
jonebuckman 0:bcc1f1890330 122 }
jonebuckman 0:bcc1f1890330 123 } else {
jonebuckman 0:bcc1f1890330 124 if (left <= m_pageSize) {
jonebuckman 0:bcc1f1890330 125 toWrite = left;
jonebuckman 0:bcc1f1890330 126 } else {
jonebuckman 0:bcc1f1890330 127 toWrite = m_pageSize;
jonebuckman 0:bcc1f1890330 128 }
jonebuckman 0:bcc1f1890330 129 }
jonebuckman 0:bcc1f1890330 130
jonebuckman 3:16227c782723 131 //pc.printf("Writing [%.*s] at %d size %d\n\r", toWrite, page, address, toWrite);
jonebuckman 3:16227c782723 132 // Start the page write with the address in one write call.
jonebuckman 3:16227c782723 133 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 3:16227c782723 134 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 135 int addr = address + count;
jonebuckman 3:16227c782723 136 char values[] = { (addr & 0xFF), *page };
jonebuckman 3:16227c782723 137 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 3:16227c782723 138 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 139 return size - left;
jonebuckman 3:16227c782723 140 }
jonebuckman 3:16227c782723 141 ++page;
jonebuckman 3:16227c782723 142 waitForWrite();
jonebuckman 0:bcc1f1890330 143 }
jonebuckman 0:bcc1f1890330 144 }
jonebuckman 0:bcc1f1890330 145 else {
jonebuckman 3:16227c782723 146 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 147 int addr = address + count;
jonebuckman 4:5b7d065a1c78 148 char i2caddr = (m_i2cAddress | addr >> 7) & 0xFF;
jonebuckman 4:5b7d065a1c78 149 char values[] = { (addr & 0xFF), *page };
jonebuckman 4:5b7d065a1c78 150 if (m_i2c.write(i2caddr, values, 2) != 0) {
jonebuckman 3:16227c782723 151 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 152 return size - left;
jonebuckman 3:16227c782723 153 }
jonebuckman 3:16227c782723 154 ++page;
jonebuckman 3:16227c782723 155 waitForWrite();
jonebuckman 0:bcc1f1890330 156 }
jonebuckman 0:bcc1f1890330 157 }
jonebuckman 0:bcc1f1890330 158
jonebuckman 0:bcc1f1890330 159 // Update the counters with the amount we've just written
jonebuckman 0:bcc1f1890330 160 left -= toWrite;
jonebuckman 0:bcc1f1890330 161 address += toWrite;
jonebuckman 0:bcc1f1890330 162 }
jonebuckman 3:16227c782723 163
jonebuckman 0:bcc1f1890330 164 return size;
jonebuckman 0:bcc1f1890330 165 }
jonebuckman 0:bcc1f1890330 166
jonebuckman 0:bcc1f1890330 167 size_t I2CEEPROM::fill(size_t address, char value, size_t size) {
jonebuckman 0:bcc1f1890330 168 // Check the address and size fit onto the chip.
jonebuckman 0:bcc1f1890330 169 if (!checkSpace(address, size))
jonebuckman 0:bcc1f1890330 170 return 0;
jonebuckman 0:bcc1f1890330 171
jonebuckman 0:bcc1f1890330 172 size_t left = size;
jonebuckman 3:16227c782723 173
jonebuckman 0:bcc1f1890330 174 while (left != 0) {
jonebuckman 3:16227c782723 175 //i2c.start();
jonebuckman 3:16227c782723 176 int toWrite;
jonebuckman 0:bcc1f1890330 177 if ((address % m_pageSize) != 0) {
jonebuckman 0:bcc1f1890330 178 toWrite = (((address / m_pageSize) + 1) * m_pageSize) - address;
jonebuckman 0:bcc1f1890330 179 if (toWrite > size) {
jonebuckman 0:bcc1f1890330 180 toWrite = size;
jonebuckman 0:bcc1f1890330 181 }
jonebuckman 0:bcc1f1890330 182 } else {
jonebuckman 0:bcc1f1890330 183 if (left <= m_pageSize) {
jonebuckman 0:bcc1f1890330 184 toWrite = left;
jonebuckman 0:bcc1f1890330 185 } else {
jonebuckman 0:bcc1f1890330 186 toWrite = m_pageSize;
jonebuckman 0:bcc1f1890330 187 }
jonebuckman 0:bcc1f1890330 188 }
jonebuckman 0:bcc1f1890330 189
jonebuckman 0:bcc1f1890330 190 //printf("Writing %d at %d size %d\n\r", value, address, toWrite);
jonebuckman 3:16227c782723 191 // Start the page write with the address in one write call.
jonebuckman 3:16227c782723 192 if(m_chipSize == 256 || m_chipSize == 128) {
jonebuckman 3:16227c782723 193 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 194 int addr = address + count;
jonebuckman 3:16227c782723 195 char values[] = { (addr & 0xFF), value };
jonebuckman 3:16227c782723 196 if (m_i2c.write(m_i2cAddress, values, 2) != 0) {
jonebuckman 3:16227c782723 197 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 198 return size - left;
jonebuckman 3:16227c782723 199 }
jonebuckman 3:16227c782723 200 waitForWrite();
jonebuckman 0:bcc1f1890330 201 }
jonebuckman 0:bcc1f1890330 202 }
jonebuckman 0:bcc1f1890330 203 else {
jonebuckman 3:16227c782723 204 for (int count = 0; count != toWrite; ++count) {
jonebuckman 3:16227c782723 205 int addr = address + count;
jonebuckman 4:5b7d065a1c78 206 char i2caddr = (m_i2cAddress | addr >> 7) & 0xFF;
jonebuckman 4:5b7d065a1c78 207 char values[] = { (addr & 0xFF), value };
jonebuckman 4:5b7d065a1c78 208 if (m_i2c.write(i2caddr, values, 2) != 0) {
jonebuckman 3:16227c782723 209 // Write failed to return bytes written so far.
jonebuckman 3:16227c782723 210 return size - left;
jonebuckman 3:16227c782723 211 }
jonebuckman 3:16227c782723 212 waitForWrite();
jonebuckman 0:bcc1f1890330 213 }
jonebuckman 0:bcc1f1890330 214 }
jonebuckman 0:bcc1f1890330 215
jonebuckman 3:16227c782723 216 // Update the counters with the amount we've just written
jonebuckman 0:bcc1f1890330 217 left -= toWrite;
jonebuckman 0:bcc1f1890330 218 address += toWrite;
jonebuckman 0:bcc1f1890330 219 }
jonebuckman 0:bcc1f1890330 220
jonebuckman 0:bcc1f1890330 221 return size;
jonebuckman 0:bcc1f1890330 222 }
jonebuckman 0:bcc1f1890330 223
jonebuckman 0:bcc1f1890330 224 void I2CEEPROM::waitForWrite() {
jonebuckman 0:bcc1f1890330 225 // The chip doesn't ACK while writing to the actual EEPROM
jonebuckman 0:bcc1f1890330 226 // so loop trying to do a zero byte write until it is ACKed
jonebuckman 0:bcc1f1890330 227 // by the chip.
jonebuckman 3:16227c782723 228 //while (m_i2c.write(m_i2cAddress, 0, 0) != 0) {
jonebuckman 0:bcc1f1890330 229 // Wait for ack.
jonebuckman 3:16227c782723 230 wait_ms(5);
jonebuckman 3:16227c782723 231 //}
jonebuckman 0:bcc1f1890330 232 }
jonebuckman 0:bcc1f1890330 233
jonebuckman 0:bcc1f1890330 234 bool I2CEEPROM::checkSpace(size_t address, size_t size) {
jonebuckman 0:bcc1f1890330 235 // Only check if chip size is non-zero.
jonebuckman 0:bcc1f1890330 236 if (m_chipSize != 0) {
jonebuckman 0:bcc1f1890330 237 // Check that the address start in the chip and doesn't
jonebuckman 0:bcc1f1890330 238 // extend past.
jonebuckman 0:bcc1f1890330 239 if ((address >= m_chipSize) || ((address + size) >= m_chipSize))
jonebuckman 0:bcc1f1890330 240 return false;
jonebuckman 0:bcc1f1890330 241 else
jonebuckman 0:bcc1f1890330 242 return true;
jonebuckman 0:bcc1f1890330 243 }
jonebuckman 0:bcc1f1890330 244
jonebuckman 0:bcc1f1890330 245 return true;
jonebuckman 0:bcc1f1890330 246 }
jonebuckman 0:bcc1f1890330 247