Phumphathai Chansriwong / 25LCxxx_SPI
Revision:
3:be69a9f6f738
Parent:
2:3a3404dbd3eb
Child:
4:9ac3c5c3a4c6
--- a/Ser25lcxxx.cpp	Sat Feb 19 18:29:20 2011 +0000
+++ b/Ser25lcxxx.cpp	Fri Jul 17 09:47:32 2015 +0000
@@ -24,177 +24,204 @@
 #include "Ser25lcxxx.h"
 #include "wait_api.h"
 
-#define HIGH(x) ((x&0xff00)>>8)
-#define LOW(x) (x&0xff)
+#define HIGH(x)     ((x&0xff00)>>8)
+#define LOW(x)      (x&0xff)
 
-Ser25LCxxx::Ser25LCxxx(SPI *spi, PinName enable, int bytes, int pagesize) {
-    _spi=spi;
-    _enable=new DigitalOut(enable);
-    _size=bytes;
-    _pageSize=pagesize;
-    _enable->write(1);
+Ser25LCxxx::Ser25LCxxx (PinName sck, PinName si, PinName so, PinName enable,
+                                                int pagenumber, int pagesize):
+                                                spi(si, so, sck), cs(enable) {
+    spi.format(8,3);
+    spi.frequency(EEPROM_SPI_SPEED);
+    size = pagesize*pagesize;
+    pageSize = pagesize;
+    pageNumber = pagenumber;
+    cs.write(1);
 }
 
-Ser25LCxxx::~Ser25LCxxx() {
-    delete _enable;
+unsigned int Ser25LCxxx::read (unsigned int startAdr, unsigned int len,
+                                                        unsigned char* buf) {
+    // assertion
+    if ((startAdr+len) > size)
+        return 0;
+
+    //active the device
+    cs = 0;
+    wait_us(1);
+
+    //send command and address
+    if (size<512) { // 256 and 128 bytes
+        spi.write(EEPROM_CMD_READ);
+        spi.write(LOW(startAdr));
+    } else if (512==size) { // 4k variant adds 9th address bit to command
+        spi.write(startAdr>255?0xb:EEPROM_CMD_READ);
+        spi.write(LOW(startAdr));
+    } else if (size<131072) { // everything up to 512k
+        spi.write(EEPROM_CMD_READ);
+        spi.write(HIGH(startAdr));
+        spi.write(LOW(startAdr));
+    } else { // 25xx1024, needs 3 byte address
+        spi.write(EEPROM_CMD_READ);
+        spi.write(startAdr>>16);
+        spi.write(HIGH(startAdr));
+        spi.write(LOW(startAdr));
+    }
+
+    //read data into buffer
+    for (int i=0; i<len; i++)
+        buf[i] = spi.write(0);
+    wait_us(1);
+
+    cs = 1;
+
+    return len;
+}
+
+unsigned int Ser25LCxxx::write (unsigned int startAdr, unsigned int len,
+                                                   const unsigned char* data) {
+    if ((startAdr+len) > size)
+        return 0;
+
+    unsigned int remaining = len;
+    unsigned int count = 0;
+
+    while (remaining > 0) {
+        // calculate amount of data to write into current page
+        int page_left = pageSize - (startAdr % pageSize);
+        int to_be_written = (remaining > page_left)? page_left : remaining;
+        if (writePage(startAdr, to_be_written, data+count) != to_be_written)
+            return count;
+        // and switch to next page
+        count += to_be_written;
+        remaining -= to_be_written;
+        startAdr += to_be_written;
+    }
+    return count;
 }
 
-char* Ser25LCxxx::read(unsigned int startAdr, unsigned int len) {
-    // assertion
-    if (startAdr+len>_size)
-        return NULL;
-    char* ret=(char*)malloc(len);
-    _enable->write(0);
+unsigned int Ser25LCxxx::writePage (unsigned int startAdr, unsigned int len,
+                                                   const unsigned char* data) {
+    //deactivate write-protection latch
+    enableWrite();
+
+    //activate eeprom
+    cs = 0;
     wait_us(1);
-    // send address
-    if (_size<512) { // 256 and 128 bytes
-        _spi->write(0x03);
-        _spi->write(LOW(startAdr));
-    } else if (512==_size) { // 4k variant adds 9th address bit to command
-        _spi->write(startAdr>255?0xb:0x3);
-        _spi->write(LOW(startAdr));
-    } else if (_size<131072) { // everything up to 512k
-        _spi->write(0x03);
-        _spi->write(HIGH(startAdr));
-        _spi->write(LOW(startAdr));
+
+    //send command and address
+    if (size<512) { // 256 and 128 bytes
+        spi.write(EEPROM_CMD_WRITE);
+        spi.write(LOW(startAdr));
+    } else if (512==size) { // 4k variant adds 9th address bit to command
+        spi.write(startAdr>255?0xa:EEPROM_CMD_WRITE);
+        spi.write(LOW(startAdr));
+    } else if (size<131072) { // everything up to 512k
+        spi.write(EEPROM_CMD_WRITE);
+        spi.write(HIGH(startAdr));
+        spi.write(LOW(startAdr));
     } else { // 25xx1024, needs 3 byte address
-        _spi->write(0x03);
-        _spi->write(startAdr>>16);
-        _spi->write(HIGH(startAdr));
-        _spi->write(LOW(startAdr));
+        spi.write(EEPROM_CMD_WRITE);
+        spi.write(startAdr>>16);
+        spi.write(HIGH(startAdr));
+        spi.write(LOW(startAdr));
     }
-    // read data into buffer
-    for (int i=0;i<len;i++) {
-        ret[i]=_spi->write(0);
-    }
+
+    //write data
+    for (int i=0; i<len; i++)
+        spi.write(data[i]);
     wait_us(1);
-    _enable->write(1);
-    return ret;
+
+    //disable eeprom
+    cs = 1;
+
+    //wait until write operation ends
+    if (!waitForWrite())
+        return 0;
+
+    return len;
 }
 
-bool Ser25LCxxx::write(unsigned int startAdr, unsigned int len, const char* data) {
-    if (startAdr+len>_size)
-        return -1;
+unsigned int Ser25LCxxx::clearPage (unsigned int pageNum) {
+    unsigned char s[pageSize];
+    memset(s, EEPROM_CLEAN_BYTE, pageSize);
+
+    return writePage(pageSize*pageNum, pageSize, s);
+}
+
+unsigned int Ser25LCxxx::clearMem () {
+    /* the implementation does not exploit clearPage to optimize the use
+       of the buffer s - it is not set for each page but just once for the
+       whole eeprom memory */
+    unsigned char s[pageSize];
+    unsigned int counter = 0;
+
+    memset(s, EEPROM_CLEAN_BYTE, pageSize);
+
+    for (int i=0; i<pageNumber; i++) {
+        if (writePage(pageSize*i, pageSize, s) != pageSize)
+            return counter;
+        counter += pageSize;
+    }
+
+    return counter;
+}
 
-    int ofs=0;
-    while (ofs<len) {
-        // calculate amount of data to write into current page
-        int pageLen=_pageSize-((startAdr+ofs)%_pageSize);
-        if (ofs+pageLen>len)
-            pageLen=len-ofs;
-        // write single page
-        bool b=writePage(startAdr+ofs,pageLen,data+ofs);
-        if (!b)
+int Ser25LCxxx::readStatus() {
+    //activate eeprom
+    cs = 0;
+    wait_us(1);
+    
+    //send command
+    spi.write(EEPROM_CMD_RDSR);
+    
+    //read value
+    int status = spi.write(0x00);
+    wait_us(1);
+    
+    //deactivate eeprom
+    cs = 1;
+
+    return status;
+}
+
+bool Ser25LCxxx::waitForWrite() {
+    unsigned int counter = 0;
+
+    while (isWriteInProgress()) {
+        wait_us(10);
+        if ((++counter) > 500)
             return false;
-        // and switch to next page
-        ofs+=pageLen;
     }
+    
     return true;
 }
 
-bool Ser25LCxxx::writePage(unsigned int startAdr, unsigned int len, const char* data) {
-    enableWrite();
-
-    _enable->write(0);
+void Ser25LCxxx::enableWrite () {
+    //enable eeprom
+    cs = 0;
     wait_us(1);
 
-    if (_size<512) { // 256 and 128 bytes
-        _spi->write(0x02);
-        _spi->write(LOW(startAdr));
-    } else if (512==_size) { // 4k variant adds 9th address bit to command
-        _spi->write(startAdr>255?0xa:0x2);
-        _spi->write(LOW(startAdr));
-    } else if (_size<131072) { // everything up to 512k
-        _spi->write(0x02);
-        _spi->write(HIGH(startAdr));
-        _spi->write(LOW(startAdr));
-    } else { // 25xx1024, needs 3 byte address
-        _spi->write(0x02);
-        _spi->write(startAdr>>16);
-        _spi->write(HIGH(startAdr));
-        _spi->write(LOW(startAdr));
-    }
-
-    // do real write
-    for (int i=0;i<len;i++) {
-        _spi->write(data[i]);
-    }
+    //send command
+    spi.write(EEPROM_CMD_WREN);
     wait_us(1);
-    // disable to start physical write
-    _enable->write(1);
     
-    waitForWrite();
-
-    return true;
+    //disable eeprom
+    cs = 1;
 }
 
-bool Ser25LCxxx::clearPage(unsigned int pageNum) {
-    enableWrite();
-    if (_size<65535) {
-        char* s=(char*)malloc(_pageSize);
-        for (int i=0;i<_pageSize;i++) {
-            s[i]=0xff;
-        }
-        bool b=writePage(_pageSize*pageNum,_pageSize,s);
-        delete s;
-        return b;
-    } else {
-        _enable->write(0);
-        wait_us(1);
-        _spi->write(0x42);
-        _spi->write(HIGH(_pageSize*pageNum));
-        _spi->write(LOW(_pageSize*pageNum));
-        wait_us(1);
-        _enable->write(1);
-
-        waitForWrite();
-    }
-    return true;
-}
-
-void Ser25LCxxx::clearMem() {
+void Ser25LCxxx::writeStatus (unsigned char val) {
     enableWrite();
-    if (_size<65535) {
-        for (int i=0;i<_size/_pageSize;i++) {
-            if (!clearPage(i))
-                break;
-        }
-    }
-    else
-    {
-        _enable->write(0);
-        wait_us(1);
-        _spi->write(0xc7);
-        wait_us(1);
-        _enable->write(1);
 
-        waitForWrite();
-    }
-}
-
-int Ser25LCxxx::readStatus() {
-    _enable->write(0);
+    //enable eeprom
+    cs = 0;
     wait_us(1);
-    _spi->write(0x5);
-    int status=_spi->write(0x00);
-    wait_us(1);
-    _enable->write(1);
-    return status;
-}
 
-void Ser25LCxxx::waitForWrite() {
-    while (true) {
-        if (0==readStatus()&1)
-            break;
-        wait_us(10);
-    }
-}
+    //send command
+    spi.write(EEPROM_CMD_WRSR);
+    
+    //write stautus
+    spi.write(val);
+    wait_us(1);
 
-void Ser25LCxxx::enableWrite()
-{
-    _enable->write(0);
-    wait_us(1);
-    _spi->write(0x06);
-    wait_us(1);
-    _enable->write(1);
+    //disable eeprom
+    cs = 1;
 }