Arsapol Manamunchaiyaporn / Mbed 2 deprecated CleaningM-Palm

Dependencies:   BEAR_Protocol_Edited BufferedSerial Debug MaxSonar PID Process QEI UI iSerial mbed

Fork of clean_V1 by Betago

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eeprom.cpp Source File

eeprom.cpp

00001 /***********************************************************
00002 Author: Bernard Borredon
00003 Date: 27 december 2011
00004 Version: 1.0
00005 ************************************************************/
00006 #include "mbed.h"
00007 #include "eeprom.h"
00008 
00009 #define BIT_SET(x,n) (x=x | (0x01<<n))
00010 #define BIT_TEST(x,n) (x & (0x01<<n))
00011 #define BIT_CLEAR(x,n) (x=x & ~(0x01<<n))
00012 
00013 EEPROM::EEPROM(PinName sda, PinName scl, uint8_t address, TypeEeprom type) : _i2c(sda, scl)
00014 {
00015 
00016     _errnum = EEPROM_NoError;
00017     _type = type;
00018 
00019     // Check address range
00020     _address = address;
00021     switch(type) {
00022         case T24C01 :
00023         case T24C02 :
00024             if(address > 7) {
00025                 _errnum = EEPROM_BadAddress;
00026             }
00027             _address = _address << 1;
00028             _page_write = 8;
00029             _page_number = 1;
00030             break;
00031         case T24C04 :
00032             if(address > 7) {
00033                 _errnum = EEPROM_BadAddress;
00034             }
00035             _address = (_address & 0xFE) << 1;
00036             _page_write = 16;
00037             _page_number = 2;
00038             break;
00039         case T24C08 :
00040             if(address > 7) {
00041                 _errnum = EEPROM_BadAddress;
00042             }
00043             _address = (_address & 0xFC) << 1;
00044             _page_write = 16;
00045             _page_number = 4;
00046             break;
00047         case T24C16 :
00048             _address = 0;
00049             _page_write = 16;
00050             _page_number = 8;
00051             break;
00052         case T24C32 :
00053         case T24C64 :
00054             if(address > 7) {
00055                 _errnum = EEPROM_BadAddress;
00056             }
00057             _address = _address << 1;
00058             _page_write = 32;
00059             _page_number = 1;
00060             break;
00061         case T24C128 :
00062         case T24C256 :
00063             if(address > 3) {
00064                 _errnum = EEPROM_BadAddress;
00065             }
00066             _address = _address << 1;
00067             _page_write = 64;
00068             _page_number = 1;
00069             break;
00070         case T24C512 :
00071             if(address > 3) {
00072                 _errnum = EEPROM_BadAddress;
00073             }
00074             _address = _address << 1;
00075             _page_write = 128;
00076             _page_number = 1;
00077             break;
00078         case T24C1024 :
00079             if(address > 7) {
00080                 _errnum = EEPROM_BadAddress;
00081             }
00082             _address = (_address & 0xFE) << 1;
00083             _page_write = 128;
00084             _page_number = 2;
00085             break;
00086         case T24C1025 :
00087             if(address > 3) {
00088                 _errnum = EEPROM_BadAddress;
00089             }
00090             _address = _address << 1;
00091             _page_write = 128;
00092             _page_number = 2;
00093             break;
00094     }
00095 
00096     // Size in bytes
00097     _size = _type;
00098     if(_type == T24C1025)
00099         _size = T24C1024;
00100 
00101     // Set I2C frequency
00102     _i2c.frequency(100000);
00103 }
00104 
00105 void EEPROM::write(uint16_t address, int8_t data)
00106 {
00107     uint8_t page;
00108     uint8_t addr;
00109     uint8_t cmd[3];
00110     int len;
00111     int ack;
00112 
00113     // Check error
00114     if(_errnum)
00115         return;
00116 
00117     // Check address
00118     if(!checkAddress(address)) {
00119         _errnum = EEPROM_OutOfRange;
00120         return;
00121     }
00122 
00123     // Compute page number
00124     page = 0;
00125     if(_type < T24C32)
00126         page = (uint8_t) (address / 256);
00127 
00128     // Device address
00129     addr = EEPROM_Address | _address | (page << 1);
00130 
00131     if(_type < T24C32) {
00132         len = 2;
00133 
00134         // Word address
00135         cmd[0] = (uint8_t) (address - page * 256);
00136 
00137         // Data
00138         cmd[1] = (uint8_t) data;
00139     } else {
00140         len = 3;
00141 
00142         // First word address (MSB)
00143         cmd[0] = (uint8_t) (address >> 8);
00144 
00145         // Second word address (LSB)
00146         cmd[1] = (uint8_t) address;
00147 
00148         // Data
00149         cmd[2] = (uint8_t) data;
00150     }
00151 
00152 // printf("len %d address %02x cmd[0] %02x cmd[1] %02x cmd[2] %02x\n",len,addr,cmd[0],cmd[1],cmd[2]);
00153 
00154     ack = _i2c.write((int)addr,(char *)cmd,len);
00155     if(ack != 0) {
00156         _errnum = EEPROM_I2cError;
00157         return;
00158     }
00159 
00160     // Wait end of write
00161     ready();
00162 
00163 }
00164 
00165 void EEPROM::write(uint16_t address, int8_t data[], uint16_t length)
00166 {
00167     uint8_t page;
00168     uint8_t addr;
00169     uint8_t blocs,remain;
00170     uint8_t fpart,lpart;
00171     uint8_t i,j,ind;
00172     uint8_t cmd[129];
00173     int ack;
00174 
00175     // Check error
00176     if(_errnum)
00177         return;
00178 
00179     // Check address
00180     if(!checkAddress(address)) {
00181         _errnum = EEPROM_OutOfRange;
00182         return;
00183     }
00184 
00185     // Check length
00186     if(!checkAddress(address + length - 1)) {
00187         _errnum = EEPROM_OutOfRange;
00188         return;
00189     }
00190 
00191     // Compute blocs numbers
00192     blocs = length / _page_write;
00193 
00194     // Compute remaining bytes
00195     remain = length - blocs * _page_write;
00196 
00197     for(i = 0; i < blocs; i++) {
00198         // Compute page number
00199         page = 0;
00200         if(_type < T24C32)
00201             page = (uint8_t) (address / 256);
00202 
00203         // Device address
00204         addr = EEPROM_Address | _address | (page << 1);
00205 
00206         if(_type < T24C32) {
00207             // Word address
00208             cmd[0] = (uint8_t) (address - page * 256);
00209 
00210             if((uint8_t) ((address + _page_write) / 256) == page) { // Data fit in the same page
00211                 // Add data
00212                 for(j = 0; j < _page_write; j++)
00213                     cmd[j + 1] = (uint8_t) data[i * _page_write + j];
00214 
00215                 // Write data
00216                 ack = _i2c.write((int)addr,(char *)cmd,_page_write + 1);
00217                 if(ack != 0) {
00218                     _errnum = EEPROM_I2cError;
00219                     return;
00220                 }
00221 
00222                 // Wait end of write
00223                 ready();
00224 
00225                 // Increment address
00226                 address += _page_write;
00227             } else { // Data on 2 pages. We must split the write
00228                 // Number of bytes in current page
00229                 fpart = (page + 1) * 256 - address;
00230 
00231                 // Add data for current page
00232                 for(j = 0; j < fpart; j++)
00233                     cmd[j + 1] = (uint8_t) data[i * _page_write + j];
00234 
00235                 // Write data for current page
00236                 ack = _i2c.write((int)addr,(char *)cmd,fpart + 1);
00237                 if(ack != 0) {
00238                     _errnum = EEPROM_I2cError;
00239                     return;
00240                 }
00241 
00242                 // Wait end of write
00243                 ready();
00244 
00245                 // Increment address
00246                 address += fpart;
00247 
00248                 if(page < _page_number - 1) {
00249                     // Increment page
00250                     page++;
00251 
00252                     // Device address
00253                     addr = EEPROM_Address | _address | (page << 1);
00254 
00255                     // Word address
00256                     cmd[0] = (uint8_t) (address - page * 256);
00257 
00258                     // Data index
00259                     ind = i * _page_write + fpart;
00260 
00261                     // Number of bytes in next page
00262                     lpart = _page_write - fpart;
00263 
00264                     // Add data for next page
00265                     for(j = 0; j < lpart; j++)
00266                         cmd[j + 1] = (uint8_t) data[ind + j];
00267 
00268                     // Write data for next page
00269                     ack = _i2c.write((int)addr,(char *)cmd,lpart + 1);
00270                     if(ack != 0) {
00271                         _errnum = EEPROM_I2cError;
00272                         return;
00273                     }
00274 
00275                     // Wait end of write
00276                     ready();
00277 
00278                     // Increment address
00279                     address += lpart;
00280                 }
00281             }
00282         } else {
00283             // First word address (MSB)
00284             cmd[0] = (uint8_t) (address >> 8);
00285 
00286             // Second word address (LSB)
00287             cmd[1] = (uint8_t) address;
00288 
00289             // Add data
00290             for(j = 0; j < _page_write; j++)
00291                 cmd[j + 2] = (uint8_t) data[i * _page_write + j];
00292 
00293             // Write data
00294             ack = _i2c.write((int)addr,(char *)cmd,_page_write + 2);
00295             if(ack != 0) {
00296                 _errnum = EEPROM_I2cError;
00297                 return;
00298             }
00299 
00300             // Wait end of write
00301             ready();
00302 
00303             // Increment address
00304             address += _page_write;
00305         }
00306     }
00307 
00308     // Compute page number
00309     page = 0;
00310     if(_type < T24C32)
00311         page = (uint8_t) (address / 256);
00312 
00313     // Device address
00314     addr = EEPROM_Address | _address | (page << 1);
00315 
00316     if(_type < T24C32) {
00317         // Word address
00318         cmd[0] = (uint8_t) (address - page * 256);
00319 
00320         if((uint8_t) ((address + remain) / 256) == page) { // Data fit in the same page
00321             // Add data for the current page
00322             for(j = 0; j < remain; j++)
00323                 cmd[j + 1] = (uint8_t) data[blocs * _page_write + j];
00324 
00325             // Write data for the current page
00326             ack = _i2c.write((int)addr,(char *)cmd,remain + 1);
00327             if(ack != 0) {
00328                 _errnum = EEPROM_I2cError;
00329                 return;
00330             }
00331 
00332             // Wait end of write
00333             ready();
00334         } else { // Data on 2 pages. We must split the write
00335             // Number of bytes in current page
00336             fpart = (page + 1) * 256 - address;
00337 
00338             // Add data for current page
00339             for(j = 0; j < fpart; j++)
00340                 cmd[j + 1] = (uint8_t) data[blocs * _page_write + j];
00341 
00342             // Write data for current page
00343             ack = _i2c.write((int)addr,(char *)cmd,fpart + 1);
00344             if(ack != 0) {
00345                 _errnum = EEPROM_I2cError;
00346                 return;
00347             }
00348 
00349             // Wait end of write
00350             ready();
00351 
00352             // Increment address
00353             address += fpart;
00354 
00355             if(page < _page_number - 1) {
00356                 // Increment page
00357                 page++;
00358 
00359                 // Device address
00360                 addr = EEPROM_Address | _address | (page << 1);
00361 
00362                 // Word address
00363                 cmd[0] = (uint8_t) (address - page * 256);
00364 
00365                 // Data index
00366                 ind = blocs * _page_write + fpart;
00367 
00368                 // Number of bytes in next page
00369                 lpart = remain - fpart;
00370 
00371                 // Add data for next page
00372                 for(j = 0; j < lpart; j++)
00373                     cmd[j + 1] = (uint8_t) data[ind + j];
00374 
00375                 // Write data for next page
00376                 ack = _i2c.write((int)addr,(char *)cmd,lpart + 1);
00377                 if(ack != 0) {
00378                     _errnum = EEPROM_I2cError;
00379                     return;
00380                 }
00381 
00382                 // Wait end of write
00383                 ready();
00384             }
00385         }
00386     } else {
00387         // Fist word address (MSB)
00388         cmd[0] = (uint8_t) (address >> 8);
00389 
00390         // Second word address (LSB)
00391         cmd[1] = (uint8_t) address;
00392 
00393         // Add data for the current page
00394         for(j = 0; j < remain; j++)
00395             cmd[j + 2] = (uint8_t) data[blocs * _page_write + j];
00396 
00397         // Write data for the current page
00398         ack = _i2c.write((int)addr,(char *)cmd,remain + 2);
00399         if(ack != 0) {
00400             _errnum = EEPROM_I2cError;
00401             return;
00402         }
00403 
00404         // Wait end of write
00405         ready();
00406     }
00407 
00408 }
00409 
00410 void EEPROM::write(uint16_t address, int16_t data)
00411 {
00412     int8_t cmd[2];
00413 
00414     // Check error
00415     if(_errnum)
00416         return;
00417 
00418     // Check address
00419     if(!checkAddress(address + 1)) {
00420         _errnum = EEPROM_OutOfRange;
00421         return;
00422     }
00423 
00424     memcpy(cmd,&data,2);
00425 
00426     write(address,cmd,2);
00427 
00428 }
00429 
00430 void EEPROM::write(uint16_t address, int32_t data)
00431 {
00432     int8_t cmd[4];
00433 
00434     // Check error
00435     if(_errnum)
00436         return;
00437 
00438     // Check address
00439     if(!checkAddress(address + 3)) {
00440         _errnum = EEPROM_OutOfRange;
00441         return;
00442     }
00443 
00444     memcpy(cmd,&data,4);
00445 
00446     write(address,cmd,4);
00447 
00448 }
00449 
00450 void EEPROM::write(uint16_t address, float data)
00451 {
00452     int8_t cmd[4];
00453 
00454     // Check error
00455     if(_errnum)
00456         return;
00457 
00458     // Check address
00459     if(!checkAddress(address + 3)) {
00460         _errnum = EEPROM_OutOfRange;
00461         return;
00462     }
00463 
00464     memcpy(cmd,&data,4);
00465 
00466     write(address,cmd,4);
00467 
00468 }
00469 
00470 void EEPROM::write(uint16_t address, void *data, uint16_t size)
00471 {
00472     int8_t *cmd = NULL;
00473 
00474     // Check error
00475     if(_errnum)
00476         return;
00477 
00478     // Check address
00479     if(!checkAddress(address + size - 1)) {
00480         _errnum = EEPROM_OutOfRange;
00481         return;
00482     }
00483 
00484     cmd = (int8_t *)malloc(size);
00485     if(cmd == NULL) {
00486         _errnum = EEPROM_MallocError;
00487         return;
00488     }
00489 
00490     memcpy(cmd,data,size);
00491 
00492     write(address,cmd,size);
00493 
00494     free(cmd);
00495 
00496 }
00497 
00498 void EEPROM::read(uint16_t address, int8_t& data)
00499 {
00500     uint8_t page;
00501     uint8_t addr;
00502     uint8_t cmd[2];
00503     uint8_t len;
00504     int ack;
00505 
00506     // Check error
00507     if(_errnum)
00508         return;
00509 
00510     // Check address
00511     if(!checkAddress(address)) {
00512         _errnum = EEPROM_OutOfRange;
00513         return;
00514     }
00515 
00516     // Compute page number
00517     page = 0;
00518     if(_type < T24C32)
00519         page = (uint8_t) (address / 256);
00520 
00521     // Device address
00522     addr = EEPROM_Address | _address | (page << 1);
00523 
00524     if(_type < T24C32) {
00525         len = 1;
00526 
00527         // Word address
00528         cmd[0] = (uint8_t) (address - page * 256);
00529     } else {
00530         len = 2;
00531 
00532         // First word address (MSB)
00533         cmd[0] = (uint8_t) (address >> 8);
00534 
00535         // Second word address (LSB)
00536         cmd[1] = (uint8_t)address;
00537     }
00538 
00539     // Write command
00540     ack = _i2c.write((int)addr,(char *)cmd,len,true);
00541     if(ack != 0) {
00542         _errnum = EEPROM_I2cError;
00543         return;
00544     }
00545 
00546     // Read data
00547     ack = _i2c.read((int)addr,(char *)&data,sizeof(data));
00548     if(ack != 0) {
00549         _errnum = EEPROM_I2cError;
00550         return;
00551     }
00552 
00553 }
00554 
00555 void EEPROM::read(uint16_t address, int8_t *data, uint16_t size)
00556 {
00557     uint8_t page;
00558     uint8_t addr;
00559     uint8_t cmd[2];
00560     uint8_t len;
00561     int ack;
00562 
00563     // Check error
00564     if(_errnum)
00565         return;
00566 
00567     // Check address
00568     if(!checkAddress(address)) {
00569         _errnum = EEPROM_OutOfRange;
00570         return;
00571     }
00572 
00573     // Check size
00574     if(!checkAddress(address + size - 1)) {
00575         _errnum = EEPROM_OutOfRange;
00576         return;
00577     }
00578 
00579     // Compute page number
00580     page = 0;
00581     if(_type < T24C32)
00582         page = (uint8_t) (address / 256);
00583 
00584     // Device address
00585     addr = EEPROM_Address | _address | (page << 1);
00586 
00587     if(_type < T24C32) {
00588         len = 1;
00589 
00590         // Word address
00591         cmd[0] = (uint8_t) (address - page * 256);
00592     } else {
00593         len = 2;
00594 
00595         // First word address (MSB)
00596         cmd[0] = (uint8_t) (address >> 8);
00597 
00598         // Second word address (LSB)
00599         cmd[1] = (uint8_t) address;
00600     }
00601 
00602     // Write command
00603     ack = _i2c.write((int)addr,(char *)cmd,len,true);
00604     if(ack != 0) {
00605         _errnum = EEPROM_I2cError;
00606         return;
00607     }
00608 
00609     // Sequential read
00610     ack = _i2c.read((int)addr,(char *)data,size);
00611     if(ack != 0) {
00612         _errnum = EEPROM_I2cError;
00613         return;
00614     }
00615 
00616 }
00617 
00618 void EEPROM::read(int8_t& data)
00619 {
00620     uint8_t addr;
00621     int ack;
00622 
00623     // Check error
00624     if(_errnum)
00625         return;
00626 
00627     // Device address
00628     addr = EEPROM_Address | _address;
00629 
00630     // Read data
00631     ack = _i2c.read((int)addr,(char *)&data,sizeof(data));
00632     if(ack != 0) {
00633         _errnum = EEPROM_I2cError;
00634         return;
00635     }
00636 
00637 }
00638 
00639 void EEPROM::read(uint16_t address, int16_t& data)
00640 {
00641     int8_t cmd[2];
00642 
00643     // Check error
00644     if(_errnum)
00645         return;
00646 
00647     // Check address
00648     if(!checkAddress(address + 1)) {
00649         _errnum = EEPROM_OutOfRange;
00650         return;
00651     }
00652 
00653     read(address,cmd,2);
00654 
00655     memcpy(&data,cmd,2);
00656 
00657 }
00658 
00659 void EEPROM::read(uint16_t address, int32_t& data)
00660 {
00661     int8_t cmd[4];
00662 
00663     // Check error
00664     if(_errnum)
00665         return;
00666 
00667     // Check address
00668     if(!checkAddress(address + 3)) {
00669         _errnum = EEPROM_OutOfRange;
00670         return;
00671     }
00672 
00673     read(address,cmd,4);
00674 
00675     memcpy(&data,cmd,4);
00676 
00677 }
00678 
00679 void EEPROM::read(uint16_t address, float& data)
00680 {
00681     int8_t cmd[4];
00682 
00683     // Check error
00684     if(_errnum)
00685         return;
00686 
00687     // Check address
00688     if(!checkAddress(address + 3)) {
00689         _errnum = EEPROM_OutOfRange;
00690         return;
00691     }
00692 
00693     read(address,cmd,4);
00694 
00695     memcpy(&data,cmd,4);
00696 
00697 }
00698 
00699 void EEPROM::read(uint16_t address, void *data, uint16_t size)
00700 {
00701     int8_t *cmd = NULL;
00702 
00703     // Check error
00704     if(_errnum)
00705         return;
00706 
00707     // Check address
00708     if(!checkAddress(address + size - 1)) {
00709         _errnum = EEPROM_OutOfRange;
00710         return;
00711     }
00712 
00713     cmd = (int8_t *)malloc(size);
00714     if(cmd == NULL) {
00715         _errnum = EEPROM_MallocError;
00716         return;
00717     }
00718 
00719     read(address,cmd,size);
00720 
00721     memcpy(data,cmd,size);
00722 
00723     free(cmd);
00724 
00725 }
00726 
00727 void EEPROM::ready(void)
00728 {
00729     int ack;
00730     uint8_t addr;
00731     uint8_t cmd;
00732 
00733     // Check error
00734     if(_errnum)
00735         return;
00736 
00737     // Device address
00738     addr = EEPROM_Address | _address;
00739 
00740     cmd = 0;
00741     /*
00742     // Wait end of write
00743     do {
00744          ack = _i2c.write((int)addr,(char *)cmd,0);
00745     } while(ack != 0);
00746     */
00747     wait_ms(5);
00748 }
00749 
00750 uint32_t EEPROM::getSize(void)
00751 {
00752     return(_size);
00753 }
00754 
00755 uint8_t EEPROM::getError(void)
00756 {
00757     return(_errnum);
00758 }
00759 
00760 bool EEPROM::checkAddress(uint16_t address)
00761 {
00762     bool ret = true;
00763 
00764     switch(_type) {
00765         case T24C01 :
00766             if(address >= T24C01)
00767                 ret = false;
00768             break;
00769         case T24C02 :
00770             if(address >= T24C02)
00771                 ret = false;
00772             break;
00773         case T24C04 :
00774             if(address >= T24C04)
00775                 ret = false;
00776             break;
00777         case T24C08 :
00778             if(address >= T24C08)
00779                 ret = false;
00780             break;
00781         case T24C16 :
00782             if(address >= T24C16)
00783                 ret = false;
00784             break;
00785         case T24C32 :
00786             if(address >= T24C32)
00787                 ret = false;
00788             break;
00789         case T24C64 :
00790             if(address >= T24C64)
00791                 ret = false;
00792             break;
00793         case T24C128 :
00794             if(address >= T24C128)
00795                 ret = false;
00796             break;
00797         case T24C256 :
00798             if(address >= T24C256)
00799                 ret = false;
00800             break;
00801         case T24C512 :
00802             if(address >= T24C512)
00803                 ret = false;
00804             break;
00805         case T24C1024 :
00806             if(address >= T24C1024)
00807                 ret = false;
00808             break;
00809         case T24C1025 :
00810             if(address >= T24C1025 - 1)
00811                 ret = false;
00812             break;
00813     }
00814 
00815     return(ret);
00816 }