Update current library to accommodate small devices.

Committer:
jonebuckman
Date:
Sun Oct 16 14:33:09 2016 +0000
Revision:
6:8dc89c3b4718
Parent:
5:02908f98dca1
Child:
7:3e1f751bcc81
Eliminated size check for write loop.

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