Skip to content

Commit

Permalink
Merge pull request #1 from SV-Zanshin/Allow-Big-Structures
Browse files Browse the repository at this point in the history
Allow read and write of variables larger than 30 bytes
  • Loading branch information
SV-Zanshin authored Sep 8, 2017
2 parents af9a603 + 146ccdd commit 7c43502
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 25 deletions.
4 changes: 2 additions & 2 deletions Examples/ReadWrite/ReadWrite.ino
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
** **
** What sets this library apart is that it will autmatically detect up to 8 memories, in any combination of those **
** listed as supported above, and treats them as one contiguous block of memory. The read() and write() functions **
** also support structures and arrays. **
** also support structures and arrays. Although the internal I2C library has a 32 byte limitation on the buffer **
** size, the library allows for larger structures to be read and written. **
** **
** This program is free software: you can redistribute it and/or modify it under the terms of the GNU General **
** Public License as published by the Free Software Foundation, either version 3 of the License, or (at your **
Expand Down Expand Up @@ -100,7 +101,6 @@ void setup() { //
} // for-next each memory chip found // //
Serial.println("\nDemonstrating memory overlapping."); // //
uint32_t memAddress = FRAM.memSize(0); // Set to beginning of 2nd memory //
Serial.println(memAddress);
FRAM.write(memAddress-6,testArray); // Split test string across 2 chips //
Serial.println("Splitting text write across 2 memory chips."); // //
Serial.print("Reading from memory chip 2 gives text \""); // //
Expand Down
21 changes: 19 additions & 2 deletions MB85_FRAM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ uint8_t MB85_FRAM_Class::begin() { //
_TransmissionStatus = Wire.endTransmission(); // Close transmission //
} // of if-then-else we've got a wraparound // //
if (!_I2C[i-MB85_MIN_ADDRESS]) { // If none of the above, then 32kB //
_I2C[i-MB85_MIN_ADDRESS] = 32; // Set array value //
_I2C[i-MB85_MIN_ADDRESS] = 32; // Set array size //
_TotalMemory += 32768; // Add value to total //
} // of if-then we have the biggest memory // //
} // of if-then max memory // //
} // of for-next loop for each memory size // //
_DeviceCount++; // Increment the found count //
} // of if-then we have found a device // //
Expand Down Expand Up @@ -117,3 +117,20 @@ uint32_t MB85_FRAM_Class::memSize(const uint8_t memNumber) { //
if(memNumber<=_DeviceCount) return((uint32_t)_I2C[memNumber]*1024); // Return either memory size or the //
else return 0; // value of zero //
} // of method memSize() //----------------------------------//

/*******************************************************************************************************************
** Method requestI2C() is an internal call used in the read() template to send the 2 byte address and request a **
** number of bytes to be read from that address **
*******************************************************************************************************************/
void MB85_FRAM_Class::requestI2C(const uint8_t device,const uint32_t memAddr, // Address device and request data //
const uint16_t dataSize,const bool endTrans){// //
Wire.beginTransmission(device+MB85_MIN_ADDRESS); // Address the I2C device //
Wire.write(memAddr>>8); // Send MSB register address //
Wire.write((uint8_t)memAddr); // Send LSB address to read //
if (endTrans) { // Read request, so end transmission//
_TransmissionStatus = Wire.endTransmission(); // Close transmission //
Wire.requestFrom(device+MB85_MIN_ADDRESS, dataSize); // Request n-bytes of data //
return Wire.available(); // Return actual bytes read //
} // of if-then endTransmission switch is set // //
return dataSize; // Return the dataSize on write //
} // of internal method requestI2C() //----------------------------------//
39 changes: 18 additions & 21 deletions MB85_FRAM.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
** **
** Vers. Date Developer Comments **
** ====== ========== ============================= ============================================================== **
** 1.0.1 2017-09-06 https://github.com/SV-Zanshin Completed testing for large structures **
** 1.0.1b 2017-09-06 https://github.com/SV-Zanshin Allow structures > 32 bytes, optimized memory use **
** 1.0.0b 2017-09-04 https://github.com/SV-Zanshin Prepared for release, final testing **
** 1.0.0a 2017-08-27 https://github.com/SV-Zanshin Started coding **
** **
Expand Down Expand Up @@ -71,52 +73,45 @@
uint8_t structSize = sizeof(T); // Number of bytes in structure //
uint32_t memAddress = addr%_TotalMemory; // Ensure no value greater than max //
uint32_t endAddress = 0; // Last address on current memory //
uint8_t device = getDevice(memAddress,endAddress); // Compute the actual device to use //
Wire.beginTransmission(device+MB85_MIN_ADDRESS); // Address the I2C device //
Wire.write(memAddress>>8); // Send MSB register address //
Wire.write((uint8_t)memAddress); // Send LSB address to read //
_TransmissionStatus = Wire.endTransmission(); // Close transmission //
Wire.requestFrom(device+MB85_MIN_ADDRESS, sizeof(T)); // Request n-bytes of data //
structSize = Wire.available(); // Use the actual number of bytes //
uint8_t device = getDevice(memAddress,endAddress); // Compute the actual device to use //
for (uint8_t i=0;i<structSize;i++) { // loop for each byte to be read //
if(i%(BUFFER_LENGTH-2)==0) { // If the buffer is full, then we //
requestI2C(device,memAddress,structSize,true); // Get data from memory //
} // if our read buffer is full // //
*bytePtr++ = Wire.read(); // Put byte read to pointer address //
if(memAddress++==endAddress) { // If we've reached the end-of-chip //
for(uint8_t j=0;j<MB85_MAX_DEVICES;j++) { // loop to get the next device //
if (device++==MB85_MAX_DEVICES) device = 0; // Increment device or start at 0 //
if (_I2C[device]) { // On a match, address device //
Wire.beginTransmission(device+MB85_MIN_ADDRESS); // Address the I2C device //
Wire.write((uint8_t)0); // Send MSB register address //
Wire.write((uint8_t)0); // Send LSB address to read //
_TransmissionStatus = Wire.endTransmission(); // Close transmission //
Wire.requestFrom(device+MB85_MIN_ADDRESS, sizeof(T)); // Request n-bytes of data //
memAddress = 1; // New memory address //
requestI2C(device,0,structSize,true); // Get bytes from new memory chip //
memAddress = 0; // New memory address //
break; // And stop looking for a new memory//
} // of if we've got the next memory // //
} // of for-next loop through each device // //
} // of if-then we've reached the end of the physical memory // //
} // of loop for each byte // // //
return(structSize); // return the number of bytes read //
} // of method read() //----------------------------------//

template<typename T>uint8_t &write(const uint32_t addr,const T &value) {// method to write a structure //
const uint8_t* bytePtr = (const uint8_t*)&value; // Pointer to structure beginning //
uint8_t structSize = sizeof(T); // Number of bytes in structure //
uint32_t memAddress = addr%_TotalMemory; // Ensure no value greater than max //
uint32_t endAddress = 0; // Last address on current memory //
uint8_t device = getDevice(memAddress,endAddress); // Compute the actual device to use //
Wire.beginTransmission(device+MB85_MIN_ADDRESS); // Address the I2C device //
Wire.write(memAddress>>8); // Send MSB register address //
Wire.write((uint8_t)memAddress); // Send LSB address to read //
for (uint8_t i=0;i<sizeof(T);i++) { // loop for each byte to be written //
for (uint8_t i=0;i<structSize;i++) { // loop for each byte to be written //
if(i%(BUFFER_LENGTH-2)==0) { // Check if end of buffer reached //
if(i>0) _TransmissionStatus = Wire.endTransmission(); // Close active transmission //
requestI2C(device,memAddress,structSize,false); // Position for next buffer data //
} // if our write buffer is full // //
Wire.write(*bytePtr++); // Write current byte to memory //
if(memAddress++==endAddress) { // If we've reached the end-of-chip //
_TransmissionStatus = Wire.endTransmission(); // Close transmission //
for(uint8_t j=0;j<MB85_MAX_DEVICES;j++) { // loop to get the next device //
if (device++==MB85_MAX_DEVICES) device = 0; // Increment device or start at 0 //
if (_I2C[device]) { // On a match, address device //
Wire.beginTransmission(device+MB85_MIN_ADDRESS); // Address the I2C device //
Wire.write((uint8_t)0); // Send MSB register address //
Wire.write((uint8_t)0); // Send LSB address to read //
memAddress = 1; // New memory address //
requestI2C(device,0,structSize,false); // Position memory pointer to begin //
memAddress = 0; // New memory address //
break; // And stop looking for a new memory//
} // of if we've got the next memory // //
} // of for-next loop through each device // //
Expand All @@ -127,6 +122,8 @@
} // of method write() //----------------------------------//
private: // -------- Private methods ------- //
uint8_t getDevice(uint32_t &memAddress, uint32_t &endAddress); // Compute actual device to use //
void requestI2C(const uint8_t device,const uint32_t memAddress, // Address device and request data //
const uint16_t dataSize, const bool endTrans); // //
uint8_t _DeviceCount = 0; // Number of memories found //
uint32_t _TotalMemory = 0; // Number of bytes in total //
uint8_t _I2C[MB85_MAX_DEVICES] = {0}; // List of device kB capacities //
Expand Down

0 comments on commit 7c43502

Please sign in to comment.