I2C EEPROM library. Originally published by rhourahane.

Fork of I2CEeprom by Robin Hourahane

Committer:
martom01
Date:
Tue Jul 02 07:57:33 2019 +0000
Revision:
3:c3d4caec943a
Parent:
2:973c4289c44c
Arm6 compiler not allow implicit cast. Fix by added explicit cast.

Who changed what in which revision?

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