Martyn Gilbertson / M24512
Committer:
Martyn Gilbertson
Date:
Fri Jun 07 14:45:45 2019 +0100
Revision:
0:11e6262c2981
Child:
3:b6d7714cd171
Initial Release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Martyn Gilbertson 0:11e6262c2981 1 /* ISL MBED Libraries
Martyn Gilbertson 0:11e6262c2981 2 * Copyright (C) 2019 - Invisible Systems Ltd. All Rights Reserved.
Martyn Gilbertson 0:11e6262c2981 3 */
Martyn Gilbertson 0:11e6262c2981 4 #include "M24512.h"
Martyn Gilbertson 0:11e6262c2981 5
Martyn Gilbertson 0:11e6262c2981 6
Martyn Gilbertson 0:11e6262c2981 7 /** I2C Frequency
Martyn Gilbertson 0:11e6262c2981 8 Roughly calculate time to write a full page based on freq
Martyn Gilbertson 0:11e6262c2981 9 ((1 / 500000) * (130*9) * 1000) + 5
Martyn Gilbertson 0:11e6262c2981 10 */
Martyn Gilbertson 0:11e6262c2981 11 #define M24512_DEFAULT_FREQUENCY (uint32_t)500000
Martyn Gilbertson 0:11e6262c2981 12
Martyn Gilbertson 0:11e6262c2981 13 /** Read command | on device address
Martyn Gilbertson 0:11e6262c2981 14 */
Martyn Gilbertson 0:11e6262c2981 15 #define M24512_COMMAND_READ (uint8_t)0
Martyn Gilbertson 0:11e6262c2981 16
Martyn Gilbertson 0:11e6262c2981 17 /** Write command | on device address
Martyn Gilbertson 0:11e6262c2981 18 */
Martyn Gilbertson 0:11e6262c2981 19 #define M24512_COMMAND_WRITE (uint8_t)1
Martyn Gilbertson 0:11e6262c2981 20
Martyn Gilbertson 0:11e6262c2981 21 /** Device Page Size
Martyn Gilbertson 0:11e6262c2981 22 */
Martyn Gilbertson 0:11e6262c2981 23 #define M24512_EEPROM_PAGE_SIZE (uint16_t)128
Martyn Gilbertson 0:11e6262c2981 24
Martyn Gilbertson 0:11e6262c2981 25 /** Device Page Count
Martyn Gilbertson 0:11e6262c2981 26 */
Martyn Gilbertson 0:11e6262c2981 27 #define M24512_EEPROM_PAGES (uint16_t)512
Martyn Gilbertson 0:11e6262c2981 28
Martyn Gilbertson 0:11e6262c2981 29
Martyn Gilbertson 0:11e6262c2981 30
Martyn Gilbertson 0:11e6262c2981 31 M24512::M24512(PinName sda, PinName scl, uint8_t address) : _i2c(sda,scl), _addr(address)
Martyn Gilbertson 0:11e6262c2981 32 {
Martyn Gilbertson 0:11e6262c2981 33 frequency(M24512_DEFAULT_FREQUENCY);
Martyn Gilbertson 0:11e6262c2981 34 }
Martyn Gilbertson 0:11e6262c2981 35
Martyn Gilbertson 0:11e6262c2981 36
Martyn Gilbertson 0:11e6262c2981 37 M24512::~M24512()
Martyn Gilbertson 0:11e6262c2981 38 {
Martyn Gilbertson 0:11e6262c2981 39
Martyn Gilbertson 0:11e6262c2981 40 }
Martyn Gilbertson 0:11e6262c2981 41
Martyn Gilbertson 0:11e6262c2981 42
Martyn Gilbertson 0:11e6262c2981 43 void M24512::frequency(uint32_t hz)
Martyn Gilbertson 0:11e6262c2981 44 {
Martyn Gilbertson 0:11e6262c2981 45 _i2c.frequency(hz);
Martyn Gilbertson 0:11e6262c2981 46 }
Martyn Gilbertson 0:11e6262c2981 47
Martyn Gilbertson 0:11e6262c2981 48
Martyn Gilbertson 0:11e6262c2981 49 uint32_t M24512::get_total_memory() const
Martyn Gilbertson 0:11e6262c2981 50 {
Martyn Gilbertson 0:11e6262c2981 51 return (get_page_size() * get_page_count()) / 1024 ;
Martyn Gilbertson 0:11e6262c2981 52 }
Martyn Gilbertson 0:11e6262c2981 53
Martyn Gilbertson 0:11e6262c2981 54
Martyn Gilbertson 0:11e6262c2981 55 uint16_t M24512::get_page_size() const
Martyn Gilbertson 0:11e6262c2981 56 {
Martyn Gilbertson 0:11e6262c2981 57 return M24512_EEPROM_PAGE_SIZE;
Martyn Gilbertson 0:11e6262c2981 58 }
Martyn Gilbertson 0:11e6262c2981 59
Martyn Gilbertson 0:11e6262c2981 60
Martyn Gilbertson 0:11e6262c2981 61 uint16_t M24512::get_page_count() const
Martyn Gilbertson 0:11e6262c2981 62 {
Martyn Gilbertson 0:11e6262c2981 63 return M24512_EEPROM_PAGES;
Martyn Gilbertson 0:11e6262c2981 64 }
Martyn Gilbertson 0:11e6262c2981 65
Martyn Gilbertson 0:11e6262c2981 66
Martyn Gilbertson 0:11e6262c2981 67 M24512::status_t M24512::ready()
Martyn Gilbertson 0:11e6262c2981 68 {
Martyn Gilbertson 0:11e6262c2981 69 int8_t ack;
Martyn Gilbertson 0:11e6262c2981 70 char cmd[2] = {0,0};
Martyn Gilbertson 0:11e6262c2981 71 int timeout = 20000;
Martyn Gilbertson 0:11e6262c2981 72
Martyn Gilbertson 0:11e6262c2981 73 // Wait for end of write
Martyn Gilbertson 0:11e6262c2981 74 do{
Martyn Gilbertson 0:11e6262c2981 75 // read from addr 0 with a length of 0 just to check the i2c state
Martyn Gilbertson 0:11e6262c2981 76 ack = _i2c.write( _addr | M24512_COMMAND_READ, cmd, 0 );
Martyn Gilbertson 0:11e6262c2981 77 if (timeout-- == 0)
Martyn Gilbertson 0:11e6262c2981 78 {
Martyn Gilbertson 0:11e6262c2981 79 return (ack == 0) ? M24512::M24512_SUCCESS : M24512::M24512_RDY_TIMEOUT;
Martyn Gilbertson 0:11e6262c2981 80 }
Martyn Gilbertson 0:11e6262c2981 81 }while(ack != 0);
Martyn Gilbertson 0:11e6262c2981 82
Martyn Gilbertson 0:11e6262c2981 83 return (ack == 0) ? M24512::M24512_SUCCESS : M24512::M24512_I2C_ERROR;
Martyn Gilbertson 0:11e6262c2981 84 }
Martyn Gilbertson 0:11e6262c2981 85
Martyn Gilbertson 0:11e6262c2981 86
Martyn Gilbertson 0:11e6262c2981 87 M24512::status_t M24512::read(uint16_t addr, char* data, uint16_t size)
Martyn Gilbertson 0:11e6262c2981 88 {
Martyn Gilbertson 0:11e6262c2981 89 int ret = 0;
Martyn Gilbertson 0:11e6262c2981 90 char cmd[2];
Martyn Gilbertson 0:11e6262c2981 91
Martyn Gilbertson 0:11e6262c2981 92 // check for overflow
Martyn Gilbertson 0:11e6262c2981 93 if ( ( addr + size) > (get_page_size() * get_page_count()) )
Martyn Gilbertson 0:11e6262c2981 94 {
Martyn Gilbertson 0:11e6262c2981 95 return M24512::M24512_MEM_OVERFLOW;
Martyn Gilbertson 0:11e6262c2981 96 }
Martyn Gilbertson 0:11e6262c2981 97
Martyn Gilbertson 0:11e6262c2981 98 cmd[0] = addr >> 8;
Martyn Gilbertson 0:11e6262c2981 99 cmd[1] = addr;
Martyn Gilbertson 0:11e6262c2981 100
Martyn Gilbertson 0:11e6262c2981 101 // set address to read from
Martyn Gilbertson 0:11e6262c2981 102 ret = _i2c.write(_addr | M24512_COMMAND_READ, (const char*)&cmd, 2, true );
Martyn Gilbertson 0:11e6262c2981 103 if (ret != 0)
Martyn Gilbertson 0:11e6262c2981 104 {
Martyn Gilbertson 0:11e6262c2981 105 return M24512::M24512_I2C_ERROR;
Martyn Gilbertson 0:11e6262c2981 106 }
Martyn Gilbertson 0:11e6262c2981 107
Martyn Gilbertson 0:11e6262c2981 108 // read data into buffer
Martyn Gilbertson 0:11e6262c2981 109 ret = _i2c.read(_addr | M24512_COMMAND_READ, (char*)data, size );
Martyn Gilbertson 0:11e6262c2981 110 if (ret != 0)
Martyn Gilbertson 0:11e6262c2981 111 {
Martyn Gilbertson 0:11e6262c2981 112 return M24512::M24512_I2C_ERROR;
Martyn Gilbertson 0:11e6262c2981 113 }
Martyn Gilbertson 0:11e6262c2981 114
Martyn Gilbertson 0:11e6262c2981 115 return ready();
Martyn Gilbertson 0:11e6262c2981 116 }
Martyn Gilbertson 0:11e6262c2981 117
Martyn Gilbertson 0:11e6262c2981 118
Martyn Gilbertson 0:11e6262c2981 119 M24512::status_t M24512::write_page(uint16_t addr, const char* data, uint16_t size)
Martyn Gilbertson 0:11e6262c2981 120 {
Martyn Gilbertson 0:11e6262c2981 121 /** TODO - Change this to dynamic incase page size increase! */
Martyn Gilbertson 0:11e6262c2981 122 char cmd[M24512_EEPROM_PAGE_SIZE];
Martyn Gilbertson 0:11e6262c2981 123 int ret = 0;
Martyn Gilbertson 0:11e6262c2981 124
Martyn Gilbertson 0:11e6262c2981 125 // check for overflow
Martyn Gilbertson 0:11e6262c2981 126 if ( ( addr + size) > (get_page_size() * get_page_count()) )
Martyn Gilbertson 0:11e6262c2981 127 {
Martyn Gilbertson 0:11e6262c2981 128 return M24512::M24512_MEM_OVERFLOW;
Martyn Gilbertson 0:11e6262c2981 129 }
Martyn Gilbertson 0:11e6262c2981 130
Martyn Gilbertson 0:11e6262c2981 131 // check for page boundary
Martyn Gilbertson 0:11e6262c2981 132 /** TODO - Change this to get_page_size incase change in size */
Martyn Gilbertson 0:11e6262c2981 133 if (size > M24512_EEPROM_PAGE_SIZE)
Martyn Gilbertson 0:11e6262c2981 134 {
Martyn Gilbertson 0:11e6262c2981 135 return M24512::M24512_MEM_OVERFLOW;
Martyn Gilbertson 0:11e6262c2981 136 }
Martyn Gilbertson 0:11e6262c2981 137
Martyn Gilbertson 0:11e6262c2981 138 cmd[0] = addr >> 8;
Martyn Gilbertson 0:11e6262c2981 139 cmd[1] = addr;
Martyn Gilbertson 0:11e6262c2981 140
Martyn Gilbertson 0:11e6262c2981 141 for (uint8_t i = 0; i < size ; i++)
Martyn Gilbertson 0:11e6262c2981 142 {
Martyn Gilbertson 0:11e6262c2981 143 cmd[2+i] = data[i];
Martyn Gilbertson 0:11e6262c2981 144 }
Martyn Gilbertson 0:11e6262c2981 145
Martyn Gilbertson 0:11e6262c2981 146 ret = _i2c.write(_addr | M24512_COMMAND_WRITE, (const char*)&cmd, size + 2 );
Martyn Gilbertson 0:11e6262c2981 147 if (ret != 0)
Martyn Gilbertson 0:11e6262c2981 148 {
Martyn Gilbertson 0:11e6262c2981 149 return M24512::M24512_I2C_ERROR;
Martyn Gilbertson 0:11e6262c2981 150 }
Martyn Gilbertson 0:11e6262c2981 151
Martyn Gilbertson 0:11e6262c2981 152 return ready();
Martyn Gilbertson 0:11e6262c2981 153
Martyn Gilbertson 0:11e6262c2981 154 }
Martyn Gilbertson 0:11e6262c2981 155
Martyn Gilbertson 0:11e6262c2981 156
Martyn Gilbertson 0:11e6262c2981 157 M24512::status_t M24512::write(uint16_t addr, const char* data, uint16_t size)
Martyn Gilbertson 0:11e6262c2981 158 {
Martyn Gilbertson 0:11e6262c2981 159 M24512::status_t ret = M24512_SUCCESS;
Martyn Gilbertson 0:11e6262c2981 160
Martyn Gilbertson 0:11e6262c2981 161 int16_t wlen = 0; // write length
Martyn Gilbertson 0:11e6262c2981 162 int16_t dlen = size; // data length remaining
Martyn Gilbertson 0:11e6262c2981 163 int16_t addr_ofst = 0; // address to write
Martyn Gilbertson 0:11e6262c2981 164
Martyn Gilbertson 0:11e6262c2981 165 while (dlen > 0)
Martyn Gilbertson 0:11e6262c2981 166 {
Martyn Gilbertson 0:11e6262c2981 167 wlen = ((dlen > get_page_size()) ? get_page_size() : dlen);
Martyn Gilbertson 0:11e6262c2981 168
Martyn Gilbertson 0:11e6262c2981 169 // if addr is not at the start of a page then write bytes until we hit the boundary
Martyn Gilbertson 0:11e6262c2981 170 if ( addr_ofst == 0 && (addr % get_page_size()) != 0 )
Martyn Gilbertson 0:11e6262c2981 171 {
Martyn Gilbertson 0:11e6262c2981 172 wlen = get_page_size() - (addr % get_page_size());
Martyn Gilbertson 0:11e6262c2981 173 // check we have enough data to hit end of page if not just write the entire length
Martyn Gilbertson 0:11e6262c2981 174 if (size < wlen)
Martyn Gilbertson 0:11e6262c2981 175 {
Martyn Gilbertson 0:11e6262c2981 176 wlen = size;
Martyn Gilbertson 0:11e6262c2981 177 }
Martyn Gilbertson 0:11e6262c2981 178 }
Martyn Gilbertson 0:11e6262c2981 179
Martyn Gilbertson 0:11e6262c2981 180 //printf("Write: Addr:%d Write: %d Remain: %d next: %d\n", addr + addr_ofst, wlen, dlen - wlen , addr_ofst + wlen);
Martyn Gilbertson 0:11e6262c2981 181
Martyn Gilbertson 0:11e6262c2981 182 // write in blocks of %page_size%
Martyn Gilbertson 0:11e6262c2981 183 ret = write_page( addr + addr_ofst, data + addr_ofst, wlen );
Martyn Gilbertson 0:11e6262c2981 184 if ( ret != M24512::M24512_SUCCESS )
Martyn Gilbertson 0:11e6262c2981 185 {
Martyn Gilbertson 0:11e6262c2981 186 return ret;
Martyn Gilbertson 0:11e6262c2981 187 }
Martyn Gilbertson 0:11e6262c2981 188
Martyn Gilbertson 0:11e6262c2981 189 dlen -= wlen;
Martyn Gilbertson 0:11e6262c2981 190 addr_ofst += wlen;
Martyn Gilbertson 0:11e6262c2981 191 }
Martyn Gilbertson 0:11e6262c2981 192
Martyn Gilbertson 0:11e6262c2981 193 return ret;
Martyn Gilbertson 0:11e6262c2981 194 }
Martyn Gilbertson 0:11e6262c2981 195
Martyn Gilbertson 0:11e6262c2981 196