Martyn Gilbertson / M24512
Revision:
0:11e6262c2981
Child:
3:b6d7714cd171
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/M24512.cpp	Fri Jun 07 14:45:45 2019 +0100
@@ -0,0 +1,196 @@
+/* ISL MBED Libraries
+ * Copyright (C) 2019 - Invisible Systems Ltd. All Rights Reserved.
+ */
+#include "M24512.h"
+
+
+/** I2C Frequency
+     Roughly calculate time to write a full page based on freq
+	 ((1 / 500000) * (130*9) * 1000) + 5
+*/
+#define M24512_DEFAULT_FREQUENCY (uint32_t)500000
+
+/** Read command | on device address
+*/
+#define M24512_COMMAND_READ     (uint8_t)0
+
+/** Write command | on device address
+*/
+#define M24512_COMMAND_WRITE    (uint8_t)1
+
+/** Device Page Size
+*/
+#define M24512_EEPROM_PAGE_SIZE (uint16_t)128
+
+/** Device Page Count
+*/
+#define M24512_EEPROM_PAGES  	(uint16_t)512
+
+
+
+M24512::M24512(PinName sda, PinName scl, uint8_t address) : _i2c(sda,scl), _addr(address)
+{
+	frequency(M24512_DEFAULT_FREQUENCY);
+}
+
+
+M24512::~M24512()
+{
+
+}
+
+
+void M24512::frequency(uint32_t hz)
+{
+	_i2c.frequency(hz);
+}
+
+
+uint32_t M24512::get_total_memory() const
+{
+	return (get_page_size() * get_page_count()) / 1024 ;
+}
+
+
+uint16_t M24512::get_page_size() const
+{
+	return M24512_EEPROM_PAGE_SIZE;
+}
+
+
+uint16_t M24512::get_page_count() const
+{
+	return M24512_EEPROM_PAGES;
+}
+
+
+M24512::status_t M24512::ready()
+{
+	int8_t ack;
+	char cmd[2] = {0,0};
+	int timeout = 20000;
+
+	// Wait for end of write
+	do{
+		// read from addr 0 with a length of 0 just to check the i2c state
+		ack = _i2c.write( _addr | M24512_COMMAND_READ, cmd, 0 );
+		if (timeout-- == 0)
+		{
+			return (ack == 0) ? M24512::M24512_SUCCESS : M24512::M24512_RDY_TIMEOUT;
+		}
+	}while(ack != 0);
+
+	return (ack == 0) ? M24512::M24512_SUCCESS : M24512::M24512_I2C_ERROR;
+}
+
+
+M24512::status_t M24512::read(uint16_t addr, char* data, uint16_t size)
+{
+	int ret = 0;
+	char cmd[2];
+
+	// check for overflow
+	if ( ( addr + size) > (get_page_size() * get_page_count()) )
+	{
+		return M24512::M24512_MEM_OVERFLOW;
+	}
+
+	cmd[0] = addr >> 8;
+	cmd[1] = addr;
+
+	// set address to read from
+	ret = _i2c.write(_addr | M24512_COMMAND_READ, (const char*)&cmd, 2, true );
+	if (ret != 0)
+	{
+		return M24512::M24512_I2C_ERROR;
+	}
+
+	// read data into buffer
+	ret = _i2c.read(_addr | M24512_COMMAND_READ, (char*)data, size );
+	if (ret != 0)
+	{
+		return M24512::M24512_I2C_ERROR;
+	}
+
+	return ready();
+}
+
+
+M24512::status_t M24512::write_page(uint16_t addr, const char* data, uint16_t size)
+{
+    /** TODO - Change this to dynamic incase page size increase! */
+	char cmd[M24512_EEPROM_PAGE_SIZE];
+	int ret = 0;
+
+	// check for overflow
+	if ( ( addr + size) > (get_page_size() * get_page_count()) )
+	{
+		return M24512::M24512_MEM_OVERFLOW;
+	}
+
+	// check for page boundary
+    /** TODO - Change this to get_page_size incase change in size */
+	if (size > M24512_EEPROM_PAGE_SIZE)
+	{
+		return M24512::M24512_MEM_OVERFLOW;
+	}
+
+	cmd[0] = addr >> 8;
+	cmd[1] = addr;
+
+	for (uint8_t i = 0;  i < size ; i++)
+	{
+		cmd[2+i] = data[i];
+	}
+
+	ret = _i2c.write(_addr | M24512_COMMAND_WRITE, (const char*)&cmd, size + 2 );
+	if (ret != 0)
+	{
+		return M24512::M24512_I2C_ERROR;
+	}
+
+	return ready();
+
+}
+
+
+M24512::status_t M24512::write(uint16_t addr, const char* data, uint16_t size)
+{
+	M24512::status_t ret = M24512_SUCCESS;
+
+	int16_t wlen = 0; // write length
+	int16_t dlen = size; // data length remaining
+	int16_t addr_ofst = 0; // address to write
+
+	while (dlen > 0)
+	{
+		wlen = ((dlen > get_page_size()) ? get_page_size() : dlen);
+
+		// if addr is not at the start of a page then write bytes until we hit the boundary
+		if ( addr_ofst == 0 && (addr % get_page_size()) != 0 )
+		{
+			wlen = get_page_size() - (addr % get_page_size());
+			// check we have enough data to hit end of page if not just write the entire length
+			if (size < wlen)
+			{
+				wlen = size;
+			}
+		}
+
+		//printf("Write: Addr:%d Write: %d Remain: %d next: %d\n", addr + addr_ofst,  wlen, dlen - wlen , addr_ofst + wlen);
+
+		// write in blocks of %page_size%
+		ret = write_page( addr + addr_ofst, data + addr_ofst, wlen );
+		if (  ret != M24512::M24512_SUCCESS )
+		{
+			return ret;
+		}
+
+		dlen -= wlen;
+		addr_ofst += wlen;
+	}
+
+	return ret;
+}
+
+