zanduino / mb85_fram Goto Github PK
View Code? Open in Web Editor NEWFujitsu MB85-xxxx family of FRAM I2C Memory Chips
License: GNU General Public License v3.0
Fujitsu MB85-xxxx family of FRAM I2C Memory Chips
License: GNU General Public License v3.0
I found something strange when I attach different memories to i2c using the auto-identification method.
Analyzing the code I've found this in begin method:
Wire.write((uint8_t)memSize >> 8); // Write MSB of address
Wire.write((uint8_t)memSize); // Write LsB of address
But in C++ and Gcc the cast operator (type) takes precedence over the bitwise scroll operator >>.
https://en.cppreference.com/w/c/language/operator_precedence
In effect, what you obtain is to cast the memSize (which is 16bit unsigned) to an unsigned 8bit AND THEN scroll it 8 position right; but when you cast a 16bit over a 8 bit only the LsB part of the source is copied into the destination variable, so you completely loose the MSB part when you send data through the i2c bus.
This is why you need to add a special case to detect 32kb memory at the end of the for cycle.
Finally I correct your method as follows:
uint8_t MB85_FRAM_Class::begin(const uint32_t i2cSpeed) {
_wireCh->begin();
_wireCh->setClock(i2cSpeed);
for (uint8_t i = MB85_MIN_ADDRESS; i < MB85_MIN_ADDRESS + MB85_MAX_DEVICES; i++) // loop all possible addresses
{
_wireCh->beginTransmission(i);
if (_wireCh->endTransmission() == 0) // If no error we have a device at this address
{
_wireCh->beginTransmission(i); // Start transmission
_wireCh->write((uint8_t)0);
_wireCh->write((uint8_t)0); // Start at address 0
_TransmissionStatus = _wireCh->endTransmission(); // Close transmission
_wireCh->requestFrom(i, (uint8_t)1); // Request 1 byte of data
uint8_t minimumByte = _wireCh->read(); // Store value of byte 0
_wireCh->beginTransmission(i); // Start transmission
_wireCh->write((uint8_t)0);
_wireCh->write((uint8_t)0); // Start at address 0
_wireCh->write(0xFF); // write high value to address 0
_TransmissionStatus = _wireCh->endTransmission(); // Close transmission
for (uint16_t memSize = 8192; memSize != 0; memSize = memSize * 2) // Check each memory size
{
_wireCh->beginTransmission(i); // Start transmission
_wireCh->write((uint8_t)(memSize >> 8)); // Write MSB of address
_wireCh->write((uint8_t)memSize); // Write LsB of address
_TransmissionStatus = _wireCh->endTransmission(); // Close transmission
_wireCh->requestFrom(i, (uint8_t)1); // Request 1 byte of data
uint8_t maximumByte = _wireCh->read(); // Store value of high byte for chip
_wireCh->beginTransmission(i); // Start transmission
_wireCh->write((uint8_t)(memSize >> 8)); // Write MSB of address
_wireCh->write((uint8_t)memSize); // Write LsB of address
_wireCh->write(0x00); // write low value to max address
_TransmissionStatus = _wireCh->endTransmission(); // Close transmission
_wireCh->beginTransmission(i); // Start transmission
_wireCh->write((uint8_t)0);
_wireCh->write((uint8_t)0); // Start at address 0
_TransmissionStatus = _wireCh->endTransmission(); // Close transmission
_wireCh->requestFrom(i, (uint8_t)1); // Request 1 byte of data
uint8_t newMinimumByte = _wireCh->read(); // Store value of byte 0
if (newMinimumByte == 0x00) // If the value has changed
{
_I2C[i - MB85_MIN_ADDRESS] = memSize / 1024; // Store memory size in kB
_TotalMemory += memSize; // Add value to total
_wireCh->beginTransmission(i); // Start transmission
_wireCh->write((uint8_t)0);
_wireCh->write((uint8_t)0); // Position to address 0
_wireCh->write(minimumByte); // restore original value
_TransmissionStatus = _wireCh->endTransmission(); // Close transmission
break; // Exit the loop
} else {
_wireCh->beginTransmission(i); // Start transmission
_wireCh->write((uint8_t)(memSize >> 8)); // Write MSB of address
_wireCh->write((uint8_t)memSize); // Write LsB of address
_wireCh->write(maximumByte); // restore original value
_TransmissionStatus = _wireCh->endTransmission(); // Close transmission
} // of if-then-else we've got a wraparound
} // of for-next loop for each memory size
_DeviceCount++; // Increment the found count
} // of if-then we have found a device
} // of for-next each I2C address loop
return _DeviceCount; // return number of memories found
As you can notice, I also moved the read part of the 0 address out of the memSize for since you don't really need to read the 0 address each time. In addition I've added a new constructor to manage multiple i2c ports.
MB85_FRAM_Class::MB85_FRAM_Class(TwoWire *wireChannel) {
_wireCh = wireChannel;
}
And a local field to handle the instance:
TwoWire *_wireCh = &Wire; ///< Wire channel to use (for multi-channel platforms)
For "static" configurations I suggest you to add a begin override with a pre-defined configuration like this:
uint8_t MB85_FRAM_Class::begin(const uint8_t devices[MB85_MAX_DEVICES], const uint32_t i2cSpeed) {
_wireCh->begin();
_wireCh->setClock(i2cSpeed);
for (uint8_t i = MB85_MIN_ADDRESS; i < MB85_MIN_ADDRESS + MB85_MAX_DEVICES; i++)
{
if (devices[i - MB85_MIN_ADDRESS] != 0)
{
_wireCh->beginTransmission(i);
if (_wireCh->endTransmission() == 0) // If no error we have a device at this address
{
_I2C[i - MB85_MIN_ADDRESS] = devices[i - MB85_MIN_ADDRESS];
_TotalMemory += (devices[i - MB85_MIN_ADDRESS] * 1024);
_DeviceCount++;
}
}
}
return _DeviceCount;
}
In this case you can avoid to read and write memory to detect the configuration if system has a pre-determined one.
Obviously, other minor changes were made in the code to adapt to the Wire pointer.
HTH
Lorenz
This Family of memories supports up to 3400KHz I2C bus Speeds ("high Speed mode"), so the library should allow the user to specifiy faster Transfer Speeds than the Default 100KHz
Clean up the Directory structure and file names
Support all platforms on compile
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.