Martyn Gilbertson / M24512
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers M24512.cpp Source File

M24512.cpp

00001 /* ISL MBED Libraries
00002  * Copyright (C) 2019 - Invisible Systems Ltd. All Rights Reserved.
00003  */
00004 #include "M24512.h"
00005 #include "mbed.h"
00006 
00007 
00008 
00009 /** I2C Frequency
00010      Roughly calculate time to write a full page based on freq
00011      ((1 / 500000) * (130*9) * 1000) + 5
00012 */
00013 #define M24512_DEFAULT_FREQUENCY (uint32_t)50000
00014 
00015 /** Read command | on device address
00016 */
00017 #define M24512_COMMAND_READ     (uint8_t)0
00018 
00019 /** Write command | on device address
00020 */
00021 #define M24512_COMMAND_WRITE    (uint8_t)1
00022 
00023 /** Device Page Size
00024 */
00025 #define M24512_EEPROM_PAGE_SIZE (uint16_t)128
00026 
00027 /** Device Page Count
00028 */
00029 #define M24512_EEPROM_PAGES     (uint16_t)512
00030 
00031 
00032 
00033 M24512::M24512(PinName sda, PinName scl, uint8_t address) : _i2c(sda,scl), _addr(address)
00034 {
00035     frequency(M24512_DEFAULT_FREQUENCY);
00036 }
00037 
00038 
00039 M24512::~M24512()
00040 {
00041 
00042 }
00043 
00044 
00045 void M24512::frequency(uint32_t hz)
00046 {
00047     _i2c.frequency(hz);
00048 }
00049 
00050 
00051 uint32_t M24512::get_total_memory() const
00052 {
00053     return (get_page_size() * get_page_count()) / 1024 ;
00054 }
00055 
00056 
00057 uint16_t M24512::get_page_size() const
00058 {
00059     return M24512_EEPROM_PAGE_SIZE;
00060 }
00061 
00062 
00063 uint16_t M24512::get_page_count() const
00064 {
00065     return M24512_EEPROM_PAGES;
00066 }
00067 
00068 
00069 M24512::status_t M24512::ready()
00070 {
00071     int8_t ack;
00072     char cmd[2] = {0,0};
00073     int timeout = 60;
00074 
00075     // Wait for end of write
00076     do{
00077         // read from addr 0 with a length of 0 just to check the i2c state
00078         ack = _i2c.write( _addr | M24512_COMMAND_READ, cmd, 0 );
00079         if (ack == 0 || timeout-- == 0)
00080         {
00081             return (ack == 0) ? M24512::M24512_SUCCESS  : M24512::M24512_RDY_TIMEOUT ;
00082         }else
00083         {
00084             //printf("waiting for ready...\r\n");
00085         }
00086     }while(ack != 0);
00087 
00088     return (ack == 0) ? M24512::M24512_SUCCESS  : M24512::M24512_I2C_ERROR ;
00089 }
00090 
00091 
00092 M24512::status_t M24512::read(uint16_t addr, char* data, uint16_t size)
00093 {
00094     int ret = 0;
00095     char cmd[2];
00096 
00097 
00098     // check for overflow
00099     if ( ( addr + size) > (get_page_size() * get_page_count()) )
00100     {
00101         return M24512::M24512_MEM_OVERFLOW ;
00102     }
00103 
00104     cmd[0] = addr >> 8;
00105     cmd[1] = addr;
00106 
00107     // set address to read from
00108     ret = _i2c.write(_addr | M24512_COMMAND_READ, (const char*)&cmd, 2, true );
00109     if (ret != 0)
00110     {
00111         return M24512::M24512_I2C_ERROR ;
00112     }
00113 
00114     // read data into buffer
00115     ret = _i2c.read(_addr | M24512_COMMAND_READ, (char*)data, size );
00116     if (ret != 0)
00117     {
00118         return M24512::M24512_I2C_ERROR ;
00119     }
00120 
00121     return ready();
00122 }
00123 
00124 
00125 M24512::status_t M24512::write_page(uint16_t addr, const char* data, uint16_t size)
00126 {
00127     /** TODO - Change this to dynamic incase page size increase! */
00128     char cmd[M24512_EEPROM_PAGE_SIZE];
00129     int ret = 0;
00130     int8_t retry = 3;
00131 
00132     // check for overflow
00133     if ( ( addr + size) > (get_page_size() * get_page_count()) )
00134     {
00135         return M24512::M24512_MEM_OVERFLOW ;
00136     }
00137 
00138     // check for page boundary
00139     /** TODO - Change this to get_page_size incase change in size */
00140     if (size > M24512_EEPROM_PAGE_SIZE)
00141     {
00142         return M24512::M24512_MEM_OVERFLOW ;
00143     }
00144 
00145     cmd[0] = addr >> 8;
00146     cmd[1] = addr;
00147 
00148     for (uint8_t i = 0;  i < size ; i++)
00149     {
00150         cmd[2+i] = data[i];
00151     }
00152 
00153     while (retry--)
00154     {
00155         ret = _i2c.write(_addr | M24512_COMMAND_WRITE, (const char*)&cmd, size + 2 );
00156         if (ret != 0)
00157         {
00158             osDelay(100);
00159         }else{
00160             break;
00161         }
00162     }
00163 
00164     if (ret != 0)
00165     {
00166         return M24512::M24512_I2C_ERROR ;
00167     }
00168 
00169     return ready();
00170 }
00171 
00172 
00173 M24512::status_t M24512::write(uint16_t addr, const char* data, uint16_t size)
00174 {
00175     M24512::status_t ret = M24512_SUCCESS ;
00176 
00177     int16_t wlen = 0; // write length
00178     int16_t dlen = size; // data length remaining
00179     int16_t addr_ofst = 0; // address to write
00180 
00181 
00182     while (dlen > 0)
00183     {
00184         wlen = ((dlen > get_page_size()) ? get_page_size() : dlen);
00185 
00186         // if addr is not at the start of a page then write bytes until we hit the boundary
00187         if ( addr_ofst == 0 && (addr % get_page_size()) != 0 )
00188         {
00189             wlen = get_page_size() - (addr % get_page_size());
00190             // check we have enough data to hit end of page if not just write the entire length
00191             if (size < wlen)
00192             {
00193                 wlen = size;
00194             }
00195         }
00196 
00197         //printf("Write: Addr:%d Write: %d Remain: %d next: %d\n", addr + addr_ofst,  wlen, dlen - wlen , addr_ofst + wlen);
00198 
00199         // write in blocks of %page_size%
00200         ret = write_page( addr + addr_ofst, data + addr_ofst, wlen );
00201         if (  ret != M24512::M24512_SUCCESS  )
00202         {
00203             return ret;
00204         }
00205 
00206         dlen -= wlen;
00207         addr_ofst += wlen;
00208     }
00209 
00210     return ret;
00211 }
00212 
00213