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.
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 00017 #include <iostream> 00018 #include <algorithm> 00019 00020 #include "I2CEeprom.h " 00021 00022 namespace 00023 { 00024 00025 //return true if system is little-endian 00026 inline bool little_endian() 00027 { 00028 int n = 1; 00029 // little endian if true 00030 return(*(char *)&n == 1); 00031 } 00032 00033 // Put EEprom address into 2 char array 00034 // in corrcet endiannness 00035 void convert_address(size_t const & addressIn, char* arOut) 00036 { 00037 constexpr size_t int_size = sizeof(size_t); 00038 union uu { 00039 uu(size_t a) : address{a} {} 00040 size_t address; 00041 const char ar[int_size]; 00042 } u{addressIn}; 00043 static_assert(sizeof(u) == int_size,""); 00044 if( little_endian()) { 00045 arOut[1] = u.ar[0]; 00046 arOut[0] = u.ar[1]; 00047 } else { 00048 // std::cout << "big endian\n"; 00049 arOut[1] = u.ar[int_size - 1]; // lsb 00050 arOut[0] = u.ar[int_size - 2]; //nextsb 00051 } 00052 } 00053 } 00054 00055 I2CEeprom::I2CEeprom( 00056 I2C & i2c, 00057 int address, 00058 size_t pageSize, 00059 size_t chipSize, 00060 uint8_t writeCycleTime_ms 00061 ): 00062 m_i2c{i2c}, 00063 m_i2cAddress(address), 00064 m_chipSize(chipSize), 00065 m_pageSize(pageSize), 00066 m_writeCycleTime_ms{writeCycleTime_ms} 00067 {} 00068 00069 size_t I2CEeprom::read(size_t address, char &value) 00070 { 00071 if (checkSpace(address, 1)) { 00072 char values[2]; 00073 convert_address(address,values); 00074 if (m_i2c.write(m_i2cAddress, values, 2) == 0) { 00075 if (m_i2c.read(m_i2cAddress, &value, 1) == 0) { 00076 return 1; 00077 } 00078 } 00079 } 00080 return 0; 00081 } 00082 00083 size_t I2CEeprom::read(size_t address, char *buffer, size_t size) 00084 { 00085 if (checkSpace(address, size)) { 00086 char values[2]; 00087 convert_address(address,values); 00088 if (m_i2c.write(m_i2cAddress, values, 2) == 0) { 00089 if (m_i2c.read(m_i2cAddress, buffer, size) == 0) { 00090 return size; 00091 } 00092 } 00093 } 00094 return 0; 00095 } 00096 00097 size_t I2CEeprom::write(size_t address, char value) 00098 { 00099 if (checkSpace(address, 1)) { 00100 char values[3]; 00101 convert_address(address,values); 00102 values[2] = value; 00103 if (m_i2c.write(m_i2cAddress, values, 3) != 0) { 00104 return 0; 00105 } 00106 waitForWrite(); 00107 return 1; 00108 } else { 00109 return 0; 00110 } 00111 } 00112 00113 size_t I2CEeprom::ll_write(size_t address, const char *buffer, size_t size) 00114 { 00115 if (m_i2c.write(m_i2cAddress, buffer, size) == 0) { 00116 waitForWrite(); 00117 return size; 00118 } else { 00119 std::cout << "EE i2c write failed\n"; 00120 return 0; 00121 } 00122 } 00123 00124 size_t I2CEeprom::write(size_t address, const char *buffer, size_t size) 00125 { 00126 if (checkSpace(address, size)) { 00127 size_t const malloc_size = std::min(size,m_pageSize) + 2U; 00128 char * tempBuffer = new char [malloc_size]; 00129 if ( tempBuffer == nullptr) { 00130 std::cout << "EE i2c buf malloc failed\n"; 00131 return 0; 00132 } 00133 size_t bytesLeft = size; 00134 size_t numBytesToWrite 00135 = std::min( size, m_pageSize - (address % m_pageSize)); 00136 while( bytesLeft ) { 00137 convert_address(address,tempBuffer); 00138 memcpy(tempBuffer + 2,buffer, numBytesToWrite); 00139 if ( ll_write(address,tempBuffer, numBytesToWrite + 2U) 00140 == numBytesToWrite + 2U) { 00141 buffer += numBytesToWrite; 00142 address += numBytesToWrite; 00143 bytesLeft -= numBytesToWrite; 00144 numBytesToWrite = std::min(bytesLeft,m_pageSize); 00145 } else { 00146 std::cout << "EE i2c write failed\n"; 00147 break; 00148 } 00149 } 00150 delete [] tempBuffer; 00151 return size - bytesLeft; 00152 } else { 00153 return 0; 00154 } 00155 } 00156 00157 void I2CEeprom::waitForWrite() 00158 { 00159 ThisThread::sleep_for(m_writeCycleTime_ms); 00160 // The chip doesn't ACK while writing to the actual EEPROM 00161 // so loop trying to do a zero byte write until it is ACKed 00162 // by the chip. 00163 while (m_i2c.write(m_i2cAddress, 0, 0) != 0) { 00164 ThisThread::sleep_for(1); 00165 } 00166 }
Generated on Wed Jul 27 2022 18:15:30 by
1.7.2