Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of I2CEeprom by
I2CEeprom.cpp
00001 /* Simple access class for I2C EEPROM chips like Microchip 24LC 00002 * Copyright (c) 2015 Robin Hourahane 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "I2CEeprom.h" 00017 00018 I2CEeprom::I2CEeprom(PinName sda, PinName scl, int address, size_t pageSize, size_t chipSize, int busSpeed): 00019 m_i2c(sda, scl), 00020 m_i2cAddress(address), 00021 m_chipSize(chipSize), 00022 m_pageSize(pageSize) 00023 { 00024 m_i2c.frequency(busSpeed); 00025 } 00026 00027 size_t I2CEeprom::read(size_t address, char &value) { 00028 // Check the address and size fit onto the chip. 00029 if (!checkSpace(address, 1)) 00030 return 0; 00031 00032 char values[] = { (address >> 8), (address & 0xFF) }; 00033 if (m_i2c.write(m_i2cAddress, values, 2) == 0) { 00034 if (m_i2c.read(m_i2cAddress, &value, 1) == 0) { 00035 return 1; 00036 } 00037 } 00038 00039 return 0; 00040 } 00041 00042 size_t I2CEeprom::read(size_t address, char *buffer, size_t size) { 00043 // Check the address and size fit onto the chip. 00044 if (!checkSpace(address, size)) 00045 return 0; 00046 00047 char values[] = { (address >> 8), (address & 0xFF) }; 00048 if (m_i2c.write(m_i2cAddress, values, 2) == 0) { 00049 if (m_i2c.read(m_i2cAddress, buffer, size) == 0) { 00050 return size; 00051 } 00052 } 00053 00054 return 0; 00055 } 00056 00057 size_t I2CEeprom::write(size_t address, char value) { 00058 // Check the address and size fit onto the chip. 00059 if (!checkSpace(address, 1)) 00060 return 0; 00061 00062 char values[] = { (address >> 8), (address & 0xFF), value }; 00063 if (m_i2c.write(m_i2cAddress, values, 3) != 0) { 00064 return 0; 00065 } 00066 00067 waitForWrite(); 00068 00069 return 1; 00070 } 00071 00072 size_t I2CEeprom::write(size_t address, const char *buffer, size_t size) { 00073 // Check the address and size fit onto the chip. 00074 if (!checkSpace(address, size)) 00075 return 0; 00076 00077 const char *page = buffer; 00078 size_t left = size; 00079 00080 // Whle we have some more data to write. 00081 while (left != 0) { 00082 // Calculate the number of bytes we can write in the current page. 00083 // If the address is not page aligned then write enough to page 00084 // align it. 00085 size_t toWrite; 00086 if ((address % m_pageSize) != 0) { 00087 toWrite = (((address / m_pageSize) + 1) * m_pageSize) - address; 00088 if (toWrite > size) { 00089 toWrite = size; 00090 } 00091 } else { 00092 if (left <= m_pageSize) { 00093 toWrite = left; 00094 } else { 00095 toWrite = m_pageSize; 00096 } 00097 } 00098 00099 //printf("Writing [%.*s] at %d size %d\n\r", toWrite, page, address, toWrite); 00100 // Start the page write with the addres ine one write call. 00101 char values[] = { (address >> 8), (address & 0xFF) }; 00102 00103 m_i2c.start(); 00104 if (m_i2c.write(m_i2cAddress) == 0) { 00105 return size - left; 00106 } 00107 if (m_i2c.write(values[0]) == 0) { 00108 return size - left; 00109 } 00110 if (m_i2c.write(values[1]) == 0) { 00111 return size - left; 00112 } 00113 00114 // Write the bytes out one at a time to avoid having to copy them to 00115 // another buffer. 00116 for (int count = 0; count != toWrite; ++count) { 00117 if (m_i2c.write(*page) == 0) { 00118 // Write failed to return bytes written so far. 00119 return size - left; 00120 } 00121 ++page; 00122 } 00123 00124 // Stop the transaction now we've completed the page 00125 // write. 00126 m_i2c.stop(); 00127 00128 waitForWrite(); 00129 00130 // Update the counters with the amount we've just written 00131 left -= toWrite; 00132 address += toWrite; 00133 } 00134 00135 return size; 00136 } 00137 00138 size_t I2CEeprom::fill(size_t address, char value, size_t size) { 00139 // Check the address and size fit onto the chip. 00140 if (!checkSpace(address, size)) 00141 return 0; 00142 00143 size_t left = size; 00144 00145 while (left != 0) { 00146 size_t toWrite; 00147 if ((address % m_pageSize) != 0) { 00148 toWrite = (((address / m_pageSize) + 1) * 64) - address; 00149 if (toWrite > size) { 00150 toWrite = size; 00151 } 00152 } else { 00153 if (left <= m_pageSize) { 00154 toWrite = left; 00155 } else { 00156 toWrite = m_pageSize; 00157 } 00158 } 00159 00160 //printf("Writing %d at %d size %d\n\r", value, address, toWrite); 00161 char values[] = { (address >> 8), (address & 0xFF) }; 00162 00163 m_i2c.start(); 00164 if (m_i2c.write(m_i2cAddress) == 0) { 00165 return size - left; 00166 } 00167 if (m_i2c.write(values[0]) == 0) { 00168 return size - left; 00169 } 00170 if (m_i2c.write(values[1]) == 0) { 00171 return size - left; 00172 } 00173 00174 for (int count = 0; count != toWrite; ++count) { 00175 if (m_i2c.write(value) == 0) 00176 return size - left; 00177 } 00178 00179 m_i2c.stop(); 00180 00181 waitForWrite(); 00182 00183 left -= toWrite; 00184 address += toWrite; 00185 } 00186 00187 return size; 00188 } 00189 00190 void I2CEeprom::waitForWrite() { 00191 // The chip doesn't ACK while writing to the actual EEPROM 00192 // so loop trying to do a zero byte write until it is ACKed 00193 // by the chip. 00194 while (m_i2c.write(m_i2cAddress, 0, 0) != 0) { 00195 // Wait for ack. 00196 wait_ms(1); 00197 } 00198 } 00199 00200 bool I2CEeprom::checkSpace(size_t address, size_t size) { 00201 // Only check if chip size is non-zero. 00202 if (m_chipSize != 0) { 00203 // Check that the address start in the chip and doesn't 00204 // extend past. 00205 if ((address >= m_chipSize) || ((address + size) >= m_chipSize)) 00206 return false; 00207 else 00208 return true; 00209 } 00210 00211 return true; 00212 } 00213
Generated on Sat Jul 23 2022 01:53:47 by
1.7.2
