Arduino library for I2C FRAM - Fujitsu MB85RC & Cypress FM24, CY15B
==============

I2C Ferroelectric Random Access Memory (FRAM). Read/write endurance for each memory slot : 10^12 cycles and more.
9~16 bit adresses, 8 bits data slots.

Supports 4K, 16K, 64K, 128K, 256K & 512K devices. Works for 1M devices when considering each device as 2 differents 512K devices

For SPI chips, please have a look on [Christophe Persoz's repo](https://github.com/christophepersoz/FRAM_MB85RS_SPI)


## Features ##
- Device settings detection (if Device ID feature is available)
- Device manual setting
- Manage single bit (read, set, clear, toggle) from a byte
- Write one 8-bits, 16-bits or 32-bits value
- Write one array of bytes 
- Read one 8-bits, 16-bits or 32-bits value
- Read one array of bytes (up to 256 per call - maximum supported by Arduino's Wire lib)
- Move a byte from an address to another
- Get device information
	- 1: Manufacturer ID
	- 2: Product ID
	- 3: Density code
	- 4: Density human readable
- Manage write protect pin
- Erase memory (set all chip to 0x00)
- Prevent cycling through memory map to avoid unwanted overwrites
- Debug mode manageable from header file

## Revision History ##


    v1.0 - First release
	v1.0.1 - Robustness enhancement
	v1.0.2 - fix constructor, introducing byte move in memory
	v1.0.3 - fix writeLong() function
	v1.0.4 - fix constructor call error
	v1.0.4.1 - Add example to help @porcao
	v1.0.5 - Enlarge density chip support by making check more flexible, Error codes not anymore hardcoded, add connect example, add Cypress FM24 & CY15B series comment.
	v1.1.0b - Adding support for devices without device IDs + 4K & 16 K devices support
	v1.1.0b1 - Fixing checkDevice() + end of range memory map check + better manual mode example
	v1.2.0 - Uses reinterpret_cast instead of bit shift / masking for performance. Breaks backward compatibility with previous code - See PR#6

## Devices ##

**Fujitsu FRAM** - manufacturer code 0x00A - [Fujitsu page](http://www.fujitsu.com/us/products/devices/semiconductor/memory/fram/lineup/index.html)

|  Model | Density (kB) | Device addressing | Device ID feature | Density code | Memory addressing | Tested |
|  ------ | :------: | :------: | :------: | :------: | :------: | :------: |
|  **MB85RC04V** | 4 | 6 bits | Yes | 0x00 | 9 bits (1) | No |
|  **MB85RC16V** | 16 | 4 bits | No | - | 11 bits (2) | Yes |
|  **MB85RC16** | 16 | 4 bits | No | - | 11 bits (2) | No |
|  **MB85RC64V** | 64 | 7 bits | No | - | 13 bits | No |
|  **MB85RC64A** | 64 | 7 bits | No | - | 13 bits | Yes |
|  **MB85RC64TA** | 64 | 7 bits | Yes | 0x03 | 13 bits | No |
|  **MB85RC128A** | 128 | 7 bits | No | - | 14 bits | No |
|  **MB85RC256V** | 256 | 7 bits | Yes | 0x05 | 15 bits | Yes |
|  **MB85RC512T** | 512 | 7 bits | Yes | 0x06 | 16 bits | No |
|  **MB85RC1MT** | 1024 | 6 bits | Yes | 0x07 | 17 bits (3) | No |

**Cypress FRAM** - manufacturer code 0x004 - [Cypress page](http://www.cypress.com/products/f-ram-serial)

|  Model | Density (kB) | Device addressing | Device ID feature | Density code | Memory addressing | Tested |
|  ------ | :------: | :------: | :------: | :------: | :------: | :------: |
|  **FM24CL04B** | 4 | 6 bits | No | - | 9 bits (1) | No |
|  **FM24C04B** | 4 | 6 bits | No | - | 9 bits (1) | No |
|  **FM24C16B** | 16 | 4 bits | No | - | 11 bits (2) | No |
|  **FM24C64B** | 64 | 7 bits | No | - | 13 bits | Yes |
|  **FM24CL64B** | 64 | 7 bits | No | - | 13 bits | No |
|  **CY15B128J** | 128 | 7 bits | Yes | 0x01 | 14 bits | No |
|  **FM24W256** | 256 | 7 bits | No | - | 15 bits | No |
|  **CY15B256J** | 256 | 7 bits | Yes | 0x02 | 15 bits | No |
|  **FM24V05** | 512 | 7 bits | Yes | 0x03 | 16 bits | No |
|  **FM24V10** | 1024 | 6 bits | Yes | 0x04 | 17 bits (3) | No |	


Note 1 : 4K devices have a 9 bits adressing memory map. The 9th bit is set in the device address byte

Note 2 : 16K devices a 11 bits adressing memory map. The 3 MSB are set in the device address byte in place of A2~A0

Note 3 : 1M a 17 bits adressing memory map. To manage this device, you need to consider it as 2 512K devices with 2 distincts adresses : 1010+A2+A1+0 and 1010+A2+A1+1. The library is set that way.


## Adresses ##
Devices address : b1010 + A2 + A1 + A0.

All devices are pulling down internaly A2, A1 & A0. Default address is b1010000 (0x50) - exception 1M chips which seems to be a double 512K devices in a single package. Please use 2 objects instances to deal with them.

4K devices have only A2 & A1 support. A0 is used for memory addressing. `i2c_addr = 0b1010xx0`

16K devices does not have A2, A1 nor A0 support. This is used for memory addressing `i2c_addr = 0b1010000`

An interesting [document](Docs/Fujitsu_FRAM_difference_addressing_scheme_over_I2C.pdf) from Fujitsu describes it quite well.



## Errors ##
The error management is eased by returning a byte value for almost each method. Most of the time, this is the status code from Wire.endTransmission() function.
- 0: success
- 1: data too long to fit in transmit buffer
- 2: received NACK on transmit of address
- 3: received NACK on transmit of data
- 4: Serial not accessible
- 5: Not referenced device ID
- 7: Fram chip unidentified
- 8: number of bytes asked to read null
- 9: bit position out of range
- 10: Not permitted operation
- 11: Out of memory range operation

## Testing ##
- Tested against MB85RC256V - breakout board from Adafruit http://www.adafruit.com/product/1895
- Tested on Arduino Mega with Arduino IDE 1.0.5 & 1.6.11
- Please comment about other devices (Memory & Arduino Boards) - A specific [thread](https://github.com/sosandroid/FRAM_MB85RC_I2C/issues/3) has been opened.

- @Porcao reports on [issue #2](https://github.com/sosandroid/FRAM_MB85RC_I2C/issues/2) a 16k labelled MB85RC chip behaving like a 64K+ device with no device ID feature. This chip has been bought from China (Aliexpress). Seems to be a mislabelled device or anything else. If the tests fails with your chip, feel free to test other densities using the "Manual Mode" example.

## To do ##
- Test all devices - [Testing thread](https://github.com/sosandroid/FRAM_MB85RC_I2C/issues/3)
- Create a more robust error management (function to handle that with higher layer)
- Rework the debug mode

## Q&A ##
Here some quick answers to some interesting questions:

- **Does this lib suitable for some others devices not listed here ?** _It can. To understand the way the lib works, just have a look on the datasheets of MB85RC256V & MB85RC16V. They will let you know about the details. Some other chips, FRAM or not, may use the same logic : MB85RC series, FM24 series, CY15B series or even some 24LC memory chips_

- **What if I run manual mode declaring another density than the one really embeded ?** _There are several options :_
	- _You have a 128K chip and declaring 64K. There is no issue and you'll only use the first half of the memory map_
	- _You have a 128K chip and declaring 16K or 4K. The memory address mamangement is not done the same way. This cannot work_
	- _You have a 128K chip and declaring 256K. You'll be able to loop through the whole memory map and overwritting some data. The worst bugs ever_
	- _You have a 16K chip and declaring 256K. The memory address mamangement is not done the same way. This cannot work_
		
- **Your chip or the lib does not behave as expected** _First check the datasheet to check either this is a lib bug or not. Using the various exmaples and playing around with settings would help. Have a look on [issue #2](https://github.com/sosandroid/FRAM_MB85RC_I2C/issues/2) to have ideas about some possible misbehavior's origins._

- **My devices is not recognized automatically** _Please run the `ReadIDs.ino` example and `manual_mode.ino` example to find out your real chip capabilities._

- **Your chip has device's IDs but not recognized by the lib** _Please open an issue to add it in the lib. Provide also all required data such as device's manufacturer, name, IDs and the tests done._

- **Sleep mode & High speed mode are not supported** _Those features are not supported at the moment as they require a huge rework of the lib. At this time they seem to be out of scope._

## Credits ##
- [Kevin Townsend](https://github.com/microbuilder) wrote the very first [Adafruit Lib](https://github.com/adafruit/Adafruit_FRAM_I2C) of which this one is forked.
- All testers who helped to improve this library