Library to use 25LCxxx chips

Dependents:   loststone

Fork of 25LCxxx_SPI by Hendrik Lipka

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Ser25lcxxx.cpp Source File

Ser25lcxxx.cpp

00001 /*
00002 * Ser25lcxxx library
00003 * Copyright (c) 2010 Hendrik Lipka
00004 * 
00005 * Permission is hereby granted, free of charge, to any person obtaining a copy
00006 * of this software and associated documentation files (the "Software"), to deal
00007 * in the Software without restriction, including without limitation the rights
00008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 * copies of the Software, and to permit persons to whom the Software is
00010 * furnished to do so, subject to the following conditions:
00011 * 
00012 * The above copyright notice and this permission notice shall be included in
00013 * all copies or substantial portions of the Software.
00014 * 
00015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 * THE SOFTWARE.
00022 */
00023 
00024 #include "Ser25lcxxx.h"
00025 #include "wait_api.h"
00026 
00027 #define HIGH(x) ((x&0xff00)>>8)
00028 #define LOW(x) (x&0xff)
00029 
00030 Ser25LCxxx::Ser25LCxxx(SPI *spi, PinName enable, uint32_t bytes, uint32_t pagesize) {
00031     _spi=spi;
00032     _enable=new DigitalOut(enable);
00033     _size=bytes;
00034     _pageSize=pagesize;
00035     _enable->write(1);
00036 }
00037 
00038 Ser25LCxxx::~Ser25LCxxx() {
00039     delete _enable;
00040 }
00041 
00042 uint8_t* Ser25LCxxx::read( uint32_t startAdr,  uint32_t len) {
00043     // assertion
00044     if (startAdr+len>_size)
00045         return NULL;
00046     uint8_t* ret=(uint8_t*)malloc(len);
00047     _enable->write(0);
00048     wait_us(1);
00049     // send address
00050     if (_size<512) { // 256 and 128 bytes
00051         _spi->write(0x03);
00052         _spi->write(LOW(startAdr));
00053     } else if (512==_size) { // 4k variant adds 9th address bit to command
00054         _spi->write(startAdr>255?0xb:0x3);
00055         _spi->write(LOW(startAdr));
00056     } else if (_size<131072) { // everything up to 512k
00057         _spi->write(0x03);
00058         _spi->write(HIGH(startAdr));
00059         _spi->write(LOW(startAdr));
00060     } else { // 25xx1024, needs 3 byte address
00061         _spi->write(0x03);
00062         _spi->write(startAdr>>16);
00063         _spi->write(HIGH(startAdr));
00064         _spi->write(LOW(startAdr));
00065     }
00066     // read data into buffer
00067     for (uint8_t i=0;i<len;i++) {
00068         ret[i]=_spi->write(0);
00069     }
00070     wait_us(1);
00071     _enable->write(1);
00072     return ret;
00073 }
00074 
00075 bool Ser25LCxxx::write( uint32_t startAdr,  uint32_t len, const uint8_t* data) {
00076     if (startAdr+len>_size)
00077         return -1;
00078 
00079     uint8_t ofs=0;
00080     while (ofs<len) {
00081         // calculate amount of data to write into current page
00082         uint8_t pageLen=_pageSize-((startAdr+ofs)%_pageSize);
00083         if (ofs+pageLen>len)
00084             pageLen=len-ofs;
00085         // write single page
00086         bool b=writePage(startAdr+ofs,pageLen,data+ofs);
00087         if (!b)
00088             return false;
00089         // and switch to next page
00090         ofs+=pageLen;
00091     }
00092     return true;
00093 }
00094 
00095 bool Ser25LCxxx::writePage( uint32_t startAdr,  uint32_t len, const uint8_t* data) {
00096     enableWrite();
00097 
00098     _enable->write(0);
00099     wait_us(1);
00100 
00101     if (_size<512) { // 256 and 128 bytes
00102         _spi->write(0x02);
00103         _spi->write(LOW(startAdr));
00104     } else if (512==_size) { // 4k variant adds 9th address bit to command
00105         _spi->write(startAdr>255?0xa:0x2);
00106         _spi->write(LOW(startAdr));
00107     } else if (_size<131072) { // everything up to 512k
00108         _spi->write(0x02);
00109         _spi->write(HIGH(startAdr));
00110         _spi->write(LOW(startAdr));
00111     } else { // 25xx1024, needs 3 byte address
00112         _spi->write(0x02);
00113         _spi->write(startAdr>>16);
00114         _spi->write(HIGH(startAdr));
00115         _spi->write(LOW(startAdr));
00116     }
00117 
00118     // do real write
00119     for (uint8_t i=0;i<len;i++) {
00120         _spi->write(data[i]);
00121     }
00122     wait_us(1);
00123     // disable to start physical write
00124     _enable->write(1);
00125     
00126     waitForWrite();
00127 
00128     return true;
00129 }
00130 
00131 bool Ser25LCxxx::clearPage( uint32_t pageNum) {
00132     enableWrite();
00133     if (_size<65535) {
00134         uint8_t* s=(uint8_t*)malloc(_pageSize);
00135         for (uint8_t i=0;i<_pageSize;i++) {
00136             s[i]=0xff;
00137         }
00138         bool b=writePage(_pageSize*pageNum,_pageSize,s);
00139         delete s;
00140         return b;
00141     } else {
00142         _enable->write(0);
00143         wait_us(1);
00144         _spi->write(0x42);
00145         _spi->write(HIGH(_pageSize*pageNum));
00146         _spi->write(LOW(_pageSize*pageNum));
00147         wait_us(1);
00148         _enable->write(1);
00149 
00150         waitForWrite();
00151     }
00152     return true;
00153 }
00154 
00155 void Ser25LCxxx::clearMem() {
00156     enableWrite();
00157     if (_size<65535) {
00158         for (uint8_t i=0;i<_size/_pageSize;i++) {
00159             if (!clearPage(i))
00160                 break;
00161         }
00162     }
00163     else
00164     {
00165         _enable->write(0);
00166         wait_us(1);
00167         _spi->write(0xc7);
00168         wait_us(1);
00169         _enable->write(1);
00170 
00171         waitForWrite();
00172     }
00173 }
00174 
00175 uint8_t Ser25LCxxx::readStatus() {
00176     _enable->write(0);
00177     wait_us(1);
00178     _spi->write(0x5);
00179     uint8_t status=_spi->write(0x00);
00180     wait_us(1);
00181     _enable->write(1);
00182     return status;
00183 }
00184 
00185 void Ser25LCxxx::waitForWrite() {
00186     while (true) {
00187         if (0==readStatus()&1)
00188             break;
00189         wait_us(10);
00190     }
00191 }
00192 
00193 void Ser25LCxxx::enableWrite()
00194 {
00195     _enable->write(0);
00196     wait_us(1);
00197     _spi->write(0x06);
00198     wait_us(1);
00199     _enable->write(1);
00200 }