GY-63_MS5611/libraries/FRAM_I2C/FRAM.cpp
2021-02-06 15:52:51 +01:00

269 lines
5.2 KiB
C++

//
// FILE: FRAM.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.3.1
// DATE: 2018-01-24
// PURPOSE: Arduino library for I2C FRAM
// URL: https://github.com/RobTillaart/FRAM_I2C
//
// HISTORY:
// 0.1.0 2018-01-24 initial version
// 0.1.1 2019-07-31 added suppport for Fujitsu 64Kbit MB85RC64T (kudos ysoyipek)
// 0.2.0 2020-04-30 refactor, add writeProtectPin code
// 0.2.1 2020-06-10 fix library.json
// 0.2.2 2020-12-23 arduino-CI + unit test + getWriteProtect()
// 0.2.3 2021-01-ii fix getMetaData (kudos to PraxisSoft
// 0.3.0 2021-01-13 fix #2 ESP32 + WireN support
// 0.3.1 2021-02-05 fix #7 typo in .cpp
#include "FRAM.h"
const uint8_t FRAM_SLAVE_ID_= 0x7C;
/////////////////////////////////////////////////////
//
// PUBLIC
//
FRAM::FRAM(TwoWire *wire)
{
_wire = wire;
_address = 0x50;
_writeProtectPin = -1;
}
#if defined (ESP8266) || defined(ESP32)
int FRAM::begin(uint8_t sda, uint8_t scl, const uint8_t address, int8_t writeProtectPin)
{
if (address < 0x50 || address > 0x57) return FRAM_ERROR_ADDR;
_wire = &Wire;
_address = address;
if ((sda < 255) && (scl < 255))
{
_wire->begin(sda, scl);
} else {
_wire->begin();
}
if (writeProtectPin > -1)
{
_writeProtectPin = writeProtectPin;
pinMode(_writeProtectPin, OUTPUT);
}
if (! isConnected()) return FRAM_ERROR_CONNECT;
return FRAM_OK;
}
#endif
int FRAM::begin(uint8_t address, int8_t writeProtectPin)
{
if (address < 0x50 || address > 0x57) return FRAM_ERROR_ADDR;
_address = address;
_wire->begin();
if (writeProtectPin > -1)
{
_writeProtectPin = writeProtectPin;
pinMode(_writeProtectPin, OUTPUT);
}
if (! isConnected()) return FRAM_ERROR_CONNECT;
return FRAM_OK;
}
bool FRAM::isConnected()
{
_wire->beginTransmission(_address);
return (_wire->endTransmission() == 0);
}
void FRAM::write8(uint16_t memaddr, uint8_t value)
{
uint8_t val = value;
writeBlock(memaddr, (uint8_t *)&val, 1);
}
void FRAM::write16(uint16_t memaddr, uint16_t value)
{
uint16_t val = value;
writeBlock(memaddr, (uint8_t *)&val, 2);
}
void FRAM::write32(uint16_t memaddr, uint32_t value)
{
uint32_t val = value;
writeBlock(memaddr, (uint8_t *)&val, 4);
}
void FRAM::write(uint16_t memaddr, uint8_t * obj, uint16_t size)
{
const int blocksize = 24;
uint8_t * p = obj;
while (size >= blocksize)
{
writeBlock(memaddr, p, blocksize);
memaddr += blocksize;
p += blocksize;
size -= blocksize;
}
// remaining
if (size > 0)
{
writeBlock(memaddr, p, size);
}
}
uint8_t FRAM::read8(uint16_t memaddr)
{
uint8_t val;
readBlock(memaddr, (uint8_t *)&val, 1);
return val;
}
uint16_t FRAM::read16(uint16_t memaddr)
{
uint16_t val;
readBlock(memaddr, (uint8_t *)&val, 2);
return val;
}
uint32_t FRAM::read32(uint16_t memaddr)
{
uint32_t val;
readBlock(memaddr, (uint8_t *)&val, 4);
return val;
}
void FRAM::read(uint16_t memaddr, uint8_t * obj, uint16_t size)
{
const uint8_t blocksize = 24;
uint8_t * p = obj;
while (size >= blocksize)
{
readBlock(memaddr, p, blocksize);
memaddr += blocksize;
p += blocksize;
size -= blocksize;
}
// remainder
if (size > 0)
{
readBlock(memaddr, p, size);
}
}
bool FRAM::setWriteProtect(bool b)
{
if (_writeProtectPin < 0) return false;
digitalWrite(_writeProtectPin, b ? HIGH : LOW);
return true;
}
bool FRAM::getWriteProtect()
{
if (_writeProtectPin < 0) return false;
return (digitalRead(_writeProtectPin) == HIGH);
}
uint16_t FRAM::getManufacturerID()
{
return getMetaData(0);
}
uint16_t FRAM::getProductID()
{
return getMetaData(1);
}
uint16_t FRAM::getSize()
{
uint16_t val = getMetaData(2); // density bits
if (val > 0) return 1UL << val;
return 0;
}
///////////////////////////////////////////////////////////
//
// PRIVATE
//
// metadata is packed as [....MMMM][MMMMDDDD][PPPPPPPP]
// M = manufacturerID
// D = density => memsize = 2^D KB
// P = product ID (together with D)
uint16_t FRAM::getMetaData(uint8_t field)
{
if (field > 2) return 0;
_wire->beginTransmission(FRAM_SLAVE_ID_);
_wire->write(_address << 1);
_wire->endTransmission(false);
int x = _wire->requestFrom(FRAM_SLAVE_ID_, (uint8_t)3);
if (x != 3) return -1;
uint32_t value = 0;
value = _wire->read();
value = value << 8;
value |= _wire->read();
value = value << 8;
value |= _wire->read();
// MANUFACTURER
if (field == 0) return (value >> 12) & 0xFF;
// PRODUCT ID
if (field == 1) return value & 0x0FFF;
// DENSITY
if (field == 2) return (value >> 8) & 0x0F;
return 0;
}
void FRAM::writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
{
// TODO constrain size < 30 ??
_wire->beginTransmission(_address);
_wire->write(memaddr >> 8);
_wire->write(memaddr & 0xFF);
uint8_t * p = obj;
for (uint8_t i = 0; i < size; i++)
{
_wire->write(*p++);
}
_wire->endTransmission();
}
void FRAM::readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
{
_wire->beginTransmission(_address);
_wire->write(memaddr >> 8);
_wire->write(memaddr & 0xFF);
_wire->endTransmission();
_wire->requestFrom(_address, size);
uint8_t * p = obj;
for (uint8_t i = 0; i < size; i++)
{
*p++ = _wire->read();
}
}
// -- END OF FILE --