SPI Flash Library for AT45

Dependents:   AT45_spi_flash_example AT45_spi_flash_example PLC1608-V1 RL0201-V1

Fork of AT45 by Steen Jørgensen

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AT45.cpp Source File

AT45.cpp

00001 /* mbed AT45 Library, for driving the Atmel AT45 series Dataflash with Serial Interface (SPI)
00002  * Copyright (c) 2012, Created by Steen Joergensen (stjo2809) inspired by Chris Styles AT45 library
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020  * THE SOFTWARE.
00021  */
00022 
00023 #include "mbed.h"
00024 #include "AT45.h"
00025 
00026 //=============================================================================
00027 // Public functions
00028 //=============================================================================
00029 
00030 AT45::AT45(SPI *spi, PinName ncs) : _spi(spi), _ncs(ncs)
00031 {    
00032     
00033     _pages = -1;        // number of pages
00034     _pagesize = -1;     // size of pages 256/264, 512/528, 1024/1056
00035     _devicesize = -1;   // In bytes
00036     _deep_down = true; // variable for deep power down function (awake ?)
00037     _deep_down_onoff = false; // variable for deep power down function (On/Off) 
00038 
00039     _initialize();     // Populate all this stuff
00040     
00041 }
00042 
00043 // This function returns the char
00044 char AT45::read_byte(int address) 
00045 {   
00046     // return byte from address
00047     return (_memread( address ));
00048 }  
00049 
00050 int AT45::read_page(char* data, int page)         
00051 {
00052     int address = -1;
00053     
00054     if(_pagesize == 256)
00055     {
00056         address = page * 256;
00057     }
00058     else if(_pagesize == 264)
00059     {
00060         address = page * 512;
00061     }
00062     else if(_pagesize == 512)
00063     {
00064         address = page * 512;
00065     }
00066     else if(_pagesize == 528)
00067     {
00068         address = page * 1024;
00069     }
00070     else if(_pagesize == 1024)
00071     {
00072         address = page * 1024;
00073     }
00074     else if(_pagesize == 1056)
00075     {
00076         address = page * 2048;
00077     }
00078     else 
00079     {
00080         return (-1); // something isnt configured right
00081     }
00082                 
00083     _busy();        
00084     _flashread(1,address); // read the first page of the block into SRAM buffer 1
00085     _busy();               // Wait until First page has loaded into buffer 1
00086         
00087     // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
00088     _select();
00089     _spi->write(0xd4);
00090     _sendaddr (0x0);
00091     _spi->write (0x0);   // dont care byte
00092         
00093     for(int i=0; i<_pagesize ;i++) 
00094     {
00095         data[i] = _spi->write (0x0);  
00096     }
00097     _deselect();            
00098               
00099     return (0);
00100 }
00101 int AT45::read_block(char *data, int block)  // under construction F&#65533;R CHECK AF MIC OG LERCHE
00102 {    
00103     char temp_data[_pagesize];
00104     int page_start;
00105 
00106     if (block < _blocks || block == 0) {
00107         page_start = block * 8;
00108 
00109         for (int i=0; i<8; i++) {
00110             read_page(temp_data, page_start);
00111             //printf("%d Read round, Data is: %d\r\n",i,*temp_data);
00112             page_start = page_start + 1;
00113             for (int z=0; z<_pagesize ; z++) {
00114                 data[z+(_pagesize*i)] = temp_data[z];
00115             }
00116         }
00117     } else {
00118         //do nothing
00119     }
00120     //printf("Read done, Data is: %d\r\n",*data);
00121     return (0);
00122 }
00123      
00124 int AT45::read_block(char *data[], int block)       // under construction F&#65533; CHECK AF MIC OG LERCHE 
00125 {
00126     char temp_data[_pagesize];
00127     int page_start;
00128     
00129     if(block < _blocks || block == 0)   
00130     {
00131         page_start = block * 8;
00132     
00133         for(int i=0; i<8 ;i++)                         // 8 pages in a block
00134         {
00135             read_page(temp_data, page_start);
00136             page_start = page_start + 1;
00137             for(int z=0; z<_pagesize ;z++)
00138             {
00139                 data[i][z] = temp_data[z];
00140             }  
00141         }
00142     }
00143     else
00144     {
00145         //do nothing   
00146     }
00147  
00148     return (0);
00149 }
00150        
00151 // This function writes the char to the address supplied
00152 // Note : We pass the raw address to the underlying functions
00153 void AT45::write_byte(int address, char data) 
00154 {
00155     _busy();   
00156     _flashread(1,address);             // read the Flash page into SRAM buffer
00157     _busy();                           // wait for the read to complete
00158     _sramwrite(1,address,data);        // Write new data into SRAM
00159     _busy();                           // Make sure flash isnt busy
00160     _flashwrite(1,address);            // Write back to the page address
00161 }       
00162       
00163 int AT45::write_page(char* data, int page)
00164 {
00165     int address = -1;
00166     
00167     if(_pagesize == 256)
00168     {
00169         address = page * 256;
00170     }
00171     else if(_pagesize == 264)
00172     {
00173         address = page * 512;
00174     }
00175     else if(_pagesize == 512)
00176     {
00177         address = page * 512;
00178     }
00179     else if(_pagesize == 528)
00180     {
00181         address = page * 1024;
00182     }
00183     else if(_pagesize == 1024)
00184     {
00185         address = page * 1024;
00186     }
00187     else if(_pagesize == 1056)
00188     {
00189         address = page * 2048;
00190     }
00191     else 
00192     {
00193         return (-1); // something isnt configured right
00194     }
00195     
00196     _select();
00197     _spi->write(0x84); // writing to buffer #1
00198     _sendaddr (0); // we are writing to the entire buffer
00199 
00200     for(int i=0; i<_pagesize ;i++) 
00201     {
00202         _spi->write (data[i]);  
00203     }
00204     _deselect();        
00205         
00206     _busy(); // make sure the Flahs isnt busy
00207                 
00208     // issue command to write buffer 1 to the appropraite flash page
00209     _select();  
00210     _spi->write (0x83);  
00211     _sendaddr (_getpaddr(address));  
00212     _deselect();
00213     
00214     return (0);   
00215 }
00216 int AT45::write_block(char *data, int block) // under construction F&#65533;R CHECK AF MIC OG LERCHE
00217 {    
00218     
00219     int page_start;
00220     char page_arr[_pagesize];
00221     
00222     if (block < _blocks || block == 0) 
00223     {
00224         page_start = block * 8;
00225         
00226         for (int i=0; i<8 ; i++) 
00227         {
00228             // Copy data from *data at 0 to 511 _ 512 - 1023, and so on every round.  
00229             memcpy(page_arr, &data[_pagesize*i], _pagesize); 
00230             
00231             write_page(page_arr, page_start);
00232             page_start = page_start + 1;
00233         }
00234     } else {
00235         //do nothing
00236     }
00237 
00238     return (0);
00239 }
00240 int AT45::write_block(char *data[], int block)      // under construction F&#65533; CHECK AF MIC OG LERCHE 
00241 {
00242     char temp_data[_pagesize];
00243     int page_start;
00244     
00245     if(block < _blocks || block == 0)   
00246     {
00247         page_start = block * 8;
00248     
00249         for(int i=0; i<8 ;i++) 
00250         {
00251             for(int z=0; z<_pagesize ;z++)
00252             {
00253                temp_data[z] = data[i][z];    
00254             }   
00255             write_page(temp_data, page_start);
00256             page_start = page_start + 1;
00257         }
00258     }
00259     else
00260     {
00261         //do nothing   
00262     }
00263  
00264     return (0);
00265 }
00266 
00267 int AT45::FAT_read(char* data, int page)          
00268 {
00269     // For 256 byte pages, we read two pages
00270     if((_pagesize == 256) || (_pagesize == 264)) 
00271     {
00272         int address = page * 512; // This is the start address of the 512 byte block
00273            
00274         _flashread(1,address); // read the first page of the block into SRAM buffer 1
00275         _busy(); // Wait until First page has loaded into buffer 1
00276         
00277         // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
00278         _select();
00279         _spi->write(0xd4);
00280         _sendaddr (0x0);
00281         _spi->write (0x0);   // dont care byte
00282         
00283         for(int i=0;i<256;i++) 
00284         {
00285             data[i] = _spi->write (0x0);  
00286         }
00287         _deselect();            
00288                 
00289         _flashread(1,address+256); // read the second page of the block into SRAM buffer 2
00290         _busy(); // Wait until second page has loaded into buffer 2
00291         
00292         // Now the second page is loaded, pull this out into the second half of the data buffer
00293         // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
00294         _select();
00295         _spi->write(0xd4);
00296         _sendaddr (0x0);
00297         _spi->write (0x0);   // dont care byte
00298         
00299         for(int i=0;i<256;i++) 
00300         {
00301             data[256+i] = _spi->write (0x0);  
00302         }
00303         _deselect();                
00304         return (0);
00305     }
00306     
00307     // For 512 byte pages, we read just the single page, transfer it    
00308     else if((_pagesize == 512) || (_pagesize == 528)) 
00309     {
00310         int address = page * 512; // This is the start address of the 512 byte block
00311     
00312         _busy(); // Wait until First page has loaded into buffer 1
00313         _flashread(1,address); // read the first page of the block into SRAM buffer 1
00314         _busy(); // Wait until First page has loaded into buffer 1
00315         
00316         // Now the page has loaded, simply transfer it from the sram buffer to the data array
00317         // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
00318         _select();
00319         _spi->write(0xd4);
00320         _sendaddr (0x0);
00321         _spi->write (0x0);   // dont care byte
00322         
00323         for(int i=0;i<512;i++) 
00324         {
00325             data[i] = _spi->write (0x0);  
00326         }
00327         _deselect();            
00328         return (0);
00329     }
00330 
00331     // For 1024 byte pages, we read just a single page, transfer half of it
00332     else if((_pagesize == 1024) || (_pagesize == 1056)) 
00333     {
00334         int address = _getpaddr(page * 512); // This is the start address of the 512 byte block
00335 
00336         _busy(); // Wait until First page has loaded into buffer 1
00337     
00338         _flashread(1,address); // read the first page of the block into SRAM buffer 1
00339 
00340         _busy(); // Wait until First page has loaded into buffer 1
00341         
00342         // Now the page has loaded, simply transfer it from the sram buffer to the data array
00343         // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
00344 
00345         _select();
00346         _spi->write(0xd4);
00347 
00348         if (page %2) // odd numbered block, read from adress 0x200
00349         { 
00350             _sendaddr (0x200);
00351         }
00352         else // even numbered block, then we are reading from sram buffer 0x0 
00353         {
00354             _sendaddr (0x0);
00355         }
00356 
00357         _spi->write (0x0);   // dont care byte
00358         
00359         for(int i=0;i<512;i++) 
00360         {
00361             data[i] = _spi->write (0x0);  
00362         }
00363         _deselect();            
00364         return (0);
00365     }
00366     else 
00367     {
00368         return (-1); // something isnt configured right
00369     }
00370 }
00371        
00372 int AT45::FAT_write(char* data, int page)        
00373 {
00374     // For 256 byte pages, we overwrite two pages
00375     if((_pagesize == 256) || (_pagesize == 264))
00376     {
00377         
00378         // fill the first buffer with the first half of the block
00379         // do this directly, for better performance
00380         _select();
00381         _spi->write(0x84); // writing to buffer #1
00382         _sendaddr (0); // we are writing to the entire buffer
00383 
00384         for(int i=0;i<256;i++) {
00385             _spi->write (data[i]);  
00386         }
00387         _deselect();        
00388                 
00389         _flashwrite(1,(page*512));
00390 
00391         // fill the buffer with the second half of the block
00392         // do this directly, for better performance
00393         _select();
00394         _spi->write(0x84); // writing to buffer #1
00395         _sendaddr (0); // we are writing to the entire buffer
00396 
00397         for(int i=0;i<256;i++) {
00398             _spi->write (data[256+i]);  
00399         }
00400         _deselect();        
00401 
00402         _flashwrite(1,((page*512)+256));
00403     }
00404         
00405     // For 512 byte pages, we overwrite a single page
00406     else if((_pagesize == 512) || (_pagesize == 528)) 
00407     {
00408     
00409         // fill the first buffer with the block data
00410         // do this directly, for better performance
00411         _select();
00412         _spi->write(0x84); // writing to buffer #1
00413         _sendaddr (0); // we are writing to the entire buffer
00414 
00415         for(int i=0;i<512;i++) {
00416             _spi->write (data[i]);  
00417         }
00418         _deselect();        
00419         
00420         _busy(); // make sure the Flahs isnt busy
00421                 
00422         // issue command to write buffer 1 to the appropraite flash page
00423         _select();  
00424         _spi->write (0x83);  
00425         _sendaddr (_getpaddr(page * 512));  
00426         _deselect();                
00427     }
00428 
00429     // For 1024 byte pages, we do a read modify write
00430     // must make sure we overwrite the right half of the page!
00431     else if((_pagesize == 1024) || (_pagesize == 1056)) 
00432     {
00433 
00434         _busy(); // make sure the flash isnt busy
00435 
00436         int address = _getpaddr(page*512);
00437 
00438         // Read the page into sram
00439         _flashread(1,address);  
00440         
00441         // wait for this operation to complete
00442         _busy();
00443         
00444         // Overwrite the appropriate half
00445         // do this directly, for better performance
00446         _select();
00447         _spi->write(0x84); // writing to buffer #1
00448 
00449         if(page%2)  // this is an odd block number, overwrite second half of buffer 
00450         {  
00451             _sendaddr (0x200); // we are writing to the entire buffer
00452         }
00453         else        // this is an even block, overwrite the first half
00454         {  
00455             _sendaddr (0x0); // we are writing to the entire buffer
00456         }
00457 
00458         for(int i=0;i<512;i++) 
00459         {
00460             _spi->write (data[i]);  
00461         }
00462         _deselect();        
00463         
00464         // Write the page back
00465         _busy();
00466         _flashwrite(1,address); 
00467     }
00468     
00469     // Something has gone wrong
00470     else 
00471     {
00472         return (-1);
00473     }
00474     
00475     return (0);
00476 }
00477        
00478 // Erase the entire chip
00479 void AT45::chip_erase() 
00480 { 
00481     _busy(); // make sure flash isnt already in busy.
00482 
00483     _select();
00484     // 4 byte command sequence
00485     _spi->write(0xc7);
00486     _spi->write(0x94);
00487     _spi->write(0x80);
00488     _spi->write(0x9a);
00489     _deselect();  
00490 
00491     _busy(); // Make erase a blocking function
00492 }        
00493 
00494 // Erase one block  
00495 void AT45::block_erase(int block)      
00496 {
00497     int address = -1;
00498     
00499     // Calculate page addresses
00500     if(block < _blocks || block == 0)   
00501     {
00502         if(_pagesize == 256)
00503         {
00504             address = block * 2048;
00505         }
00506         else if(_pagesize == 264)
00507         {
00508             address = block * 4096;
00509         }
00510         else if(_pagesize == 512)
00511         {
00512             address = block * 4096;
00513         }
00514         else if(_pagesize == 528)
00515         {
00516             address = block * 8192;
00517         }
00518         else if(_pagesize == 1024)
00519         {
00520             address = block * 8192;
00521         }
00522         else if(_pagesize == 1056)
00523         {
00524             address = block * 16384;
00525         }
00526         
00527         _busy();
00528         _select();
00529         _spi->write(0x50);
00530         _sendaddr (address);
00531         _deselect();
00532         _busy();   
00533     }
00534     else
00535     {
00536         //do nothing   
00537     }
00538 }
00539 
00540 // Erase one page       
00541 void AT45::page_erase(int page)
00542 {
00543     int address = -1;
00544     
00545     // Calculate page addresses
00546     if(page < _pages || page == 0)   
00547     {
00548         if(_pagesize == 256)
00549         {
00550             address = page * 256;
00551         }
00552         else if(_pagesize == 264)
00553         {
00554             address = page * 512;
00555         }
00556         else if(_pagesize == 512)
00557         {
00558             address = page * 512;
00559         }
00560         else if(_pagesize == 528)
00561         {
00562             address = page * 1024;
00563         }
00564         else if(_pagesize == 1024)
00565         {
00566             address = page * 1024;
00567         }
00568         else if(_pagesize == 1056)
00569         {
00570             address = page * 2048;
00571         }
00572         
00573         _busy();
00574         _select();
00575         _spi->write(0x81);
00576         _sendaddr (address);
00577         _deselect();
00578         _busy();   
00579     }
00580     else
00581     {
00582         //do nothing   
00583     }
00584 }
00585       
00586 // return the size of the part in bytes
00587 int AT45::device_size() 
00588 { 
00589     return _devicesize;
00590 }       
00591 
00592 // return the numbers of pages
00593 int AT45::pages() 
00594 { 
00595     return _pages;
00596 }       
00597        
00598 // return the page size of the part in bytes
00599 int AT45::pagesize() 
00600 { 
00601     return _pagesize;
00602 }       
00603        
00604 // A one-time programmable configuration
00605 void AT45::set_pageszie_to_binary()
00606 {
00607     _busy(); // make sure flash isnt already in busy.
00608 
00609     _select();
00610     // 4 byte command sequence
00611     _spi->write(0x3d);
00612     _spi->write(0x2a);
00613     _spi->write(0x80);
00614     _spi->write(0xa6);
00615     _deselect();  
00616 
00617     _busy(); // Make erase a blocking function   
00618 }
00619 
00620 // Return the number of blocks in this device in accordance with the datasheet
00621 int AT45::blocks() 
00622 {  
00623     return _blocks;
00624 }
00625        
00626 // Return the Id of the part
00627 int AT45::id() 
00628 { 
00629     int id = 0;
00630     _select();
00631     _spi->write(0x9f);
00632     id = (_spi->write(0x00) << 8);
00633     id |= _spi->write(0x00);
00634     _deselect();            
00635     return id; 
00636 }
00637          
00638 // return the Status
00639 int AT45::status() 
00640 { 
00641     int status = 0;
00642     _select();
00643     _spi->write(0xd7);
00644     status = (_spi->write(0x00));
00645     _deselect();            
00646     return status; 
00647 }
00648           
00649 // Make sure the Flash isnt already doing something
00650 void AT45::busy() 
00651 {
00652     _busy();
00653 }
00654 
00655 void AT45::deep_power_down(bool _deep_down_onoff) 
00656 {
00657     if(_deep_down_onoff == false) // Wake up from deep power down
00658     {
00659         _select();
00660         _spi->write(0xab);
00661         _deselect();
00662         _deep_down = true;
00663         // remenber to want 35uS before using the device.          
00664     }
00665     else if(_deep_down_onoff == true) // Go to deep power down
00666     {
00667         _busy();
00668         _select();
00669         _spi->write(0xb9);
00670         _deselect();
00671         _deep_down = false;
00672     }
00673     else
00674     {
00675         //do nothing   
00676     }       
00677 }
00678 
00679 bool AT45::is_it_awake()
00680 {
00681     return _deep_down;
00682 }
00683 
00684 //=============================================================================
00685 // Private functions
00686 //=============================================================================
00687 
00688 void AT45::_initialize()
00689 {
00690     int _id = 0;
00691     int _status = 0;
00692 
00693     _id = id();
00694     _status = status();
00695     
00696     if ((_id & 0x1f) == 0x3)  // 2Mbits 
00697     { 
00698         _devicesize = 262144; // Size in bytes
00699         _pages = 1024;        // Number of pages
00700         _blocks = 128;        // Number of blocks
00701         if (_status & 0x1) 
00702         {
00703             _pagesize = 256;
00704         }
00705         else 
00706         {
00707             _pagesize = 264;
00708         }    
00709     }
00710     else if ( (_id & 0x1f) == 0x4) // 4Mbits 
00711     { 
00712         _devicesize = 524288;
00713         _pages = 2048;
00714         _blocks = 256;        
00715         if (_status & 0x1) 
00716         {
00717             _pagesize = 256;
00718         }
00719         else 
00720         {
00721             _pagesize = 264;
00722         }    
00723     }
00724     else if ( (_id & 0x1f) == 0x5) // 8Mbits 
00725     { 
00726         _devicesize = 1048576;
00727         _pages = 4096;
00728         _blocks = 512;        
00729         if (_status & 0x1) 
00730         {
00731             _pagesize = 256;
00732         }
00733         else 
00734         {
00735             _pagesize = 264;
00736         }    
00737     }
00738     else if ( (_id & 0x1f) == 0x6) // 16Mbits 
00739     { 
00740         _devicesize = 2097152;
00741         _pages = 4096;
00742         _blocks = 512;        
00743         if (_status & 0x1) 
00744         {
00745             _pagesize = 512;
00746         }
00747         else 
00748         {
00749             _pagesize = 528;
00750         }
00751     }
00752     else if ( (_id & 0x1f) == 0x7) // 32Mbits 
00753     { 
00754         _devicesize = 4194304;
00755         _pages = 8192;
00756         _blocks = 1024;        
00757         if (_status & 0x1) 
00758         {
00759             _pagesize = 512;
00760         }
00761         else 
00762         {
00763             _pagesize = 528;
00764         }
00765     }
00766     else if ( (_id & 0x1f) == 0x8) // 64Mbits 
00767     { 
00768         _devicesize = 8388608;
00769         _pages = 8192;
00770         _blocks = 1024;
00771         if (_status & 0x1) 
00772         {
00773             _pagesize = 1024;
00774         }
00775         else 
00776         {
00777             _pagesize = 1056;
00778         }
00779     }
00780     else 
00781     {
00782         _devicesize = -1;
00783         _pages = -1;
00784         _pagesize = -1;
00785         _blocks = -1;
00786     }
00787 }
00788 
00789 void AT45::_select()
00790 {
00791     _ncs = 0;    
00792 }
00793 
00794 void AT45::_deselect()
00795 {
00796     _ncs = 1;
00797 }
00798 
00799 void AT45::_busy() {
00800     volatile int iambusy = 1;  
00801     while (iambusy) {
00802         // if bit 7 is set, we can proceed
00803         if ( status() & 0x80 ) {
00804             iambusy = 0;}
00805     }
00806 }
00807 
00808 // Write to an SRAM buffer
00809 // Note : We create buffer and page addresses in _sram and _flash        
00810 void AT45::_sramwrite(int buffer, int address, int data)
00811 {
00812 
00813     int cmd = 0;
00814     int baddr = 0;
00815   
00816     baddr = _getbaddr(address);
00817   
00818     _busy();
00819   
00820     _select();
00821   
00822     if (buffer == 1) 
00823         {cmd = 0x84;}
00824     else 
00825         {cmd = 0x87;}
00826 
00827     _spi->write(cmd);
00828     _sendaddr (baddr);
00829     _spi->write (data);  
00830 
00831     _deselect();            
00832 }
00833 
00834 // Read from an SRAM buffer
00835 // Note : We create buffer and page addresses in _sram and _flash
00836 int AT45::_sramread(int buffer, int address) 
00837 {
00838 
00839     int cmd = 0;
00840     int baddr = 0;
00841     int bufdata = 0;
00842   
00843     baddr = _getbaddr(address);
00844   
00845     _select();
00846   
00847     if(buffer == 1) 
00848         {cmd = 0xd4;}
00849     else 
00850         {cmd = 0xd6;}
00851   
00852     _spi->write(cmd);
00853     _sendaddr (baddr);
00854     _spi->write (0x0);   // dont care byte
00855     bufdata = _spi->write (0x0);  
00856   
00857     _deselect();            
00858  
00859     return (bufdata);
00860 }
00861 
00862 // Write and SRAM buffer to main memory
00863 void AT45::_flashwrite (int buffer, int address)
00864 {
00865 
00866     int cmd = 0;
00867     int paddr = _getpaddr(address);
00868  
00869     _busy();  // Check flash is not busy 
00870     
00871     _select();  
00872 
00873     if (buffer == 1) 
00874         {cmd = 0x83;}
00875     else 
00876         {cmd = 0x86;}
00877       
00878     _spi->write (cmd);  
00879     _sendaddr (paddr);  
00880     _deselect();     
00881 
00882     _busy();  // Check flash is not busy 
00883 }
00884 
00885 // Read from Flash memory into SRAM buffer
00886 void AT45::_flashread (int buffer, int address) 
00887 {
00888 
00889     int cmd = 0;
00890     int paddr = _getpaddr(address); // calculate page address
00891   
00892     _busy();  // Check flash is not busy
00893     _select();
00894       
00895     if (buffer == 1)
00896         {cmd = 0x53;}
00897     else
00898         {cmd = 0x55;}
00899 
00900     _spi->write (cmd);  
00901     _sendaddr (paddr);
00902     _deselect();            
00903 }
00904 
00905 // Read directly from main memory
00906 int AT45::_memread (int address) 
00907 {
00908 
00909     int data = 0;        
00910     int addr;
00911 
00912     addr = _getpaddr(address) | _getbaddr(address);
00913 
00914     _busy();
00915 
00916     _select();
00917 
00918     _spi->write (0xd2);  // Direct read command
00919     _sendaddr (addr);
00920   
00921     // 4 dont care bytes
00922     _spi->write (0x00);  
00923     _spi->write (0x00);  
00924     _spi->write (0x00);  
00925     _spi->write (0x00);  
00926   
00927     // this one clocks the data
00928     data = _spi->write (0x00);  
00929     _deselect();            
00930 
00931     _busy();
00932 
00933     return data;
00934 }
00935 
00936 // Work out the page address
00937 // If we have a 2^N page size, it is just the top N bits
00938 // If we have non-2^N, we use the shifted address
00939 int AT45::_getpaddr(int address) 
00940 {
00941 
00942     int paddr;
00943 
00944     if (_pagesize == 256) {                 
00945         paddr = address & 0xffffff00;}    
00946     else if (_pagesize == 264) {                 
00947         paddr = (address << 1) & 0xfffffe00;}
00948     else if (_pagesize == 512) {                 
00949         paddr = address & 0xfffffe00;}
00950     else if (_pagesize == 528 ) {           
00951        paddr = (address << 1) & 0xfffffc00;}
00952     else if (_pagesize == 1024) {                 
00953        paddr = address & 0xfffffc00;}
00954     else if (_pagesize == 1056 ) {           
00955         paddr = (address << 1) & 0xfffff800;}
00956     else {
00957         paddr = -1;}
00958     
00959     return (paddr);
00960 }
00961 
00962 // Clean the buffer address. This is the 8/9/10 LSBs
00963 int AT45::_getbaddr(int address) 
00964 {
00965 
00966     int baddr;
00967 
00968     if ((_pagesize == 256) || (_pagesize == 264 )) {
00969         baddr = address & 0xff;}
00970     else if ((_pagesize == 512) || (_pagesize == 528 )) {
00971         baddr = address & 0x1ff;}
00972     else if ((_pagesize == 1024) || (_pagesize == 1056 )) {
00973         baddr = address & 0x3ff;}
00974     else {
00975         baddr = -1;}
00976 
00977     return (baddr);
00978 }
00979 
00980 // Sends the three lest significant bytes of the supplied address
00981 void AT45::_sendaddr (int address) 
00982 {
00983     _spi->write(address >> 16);
00984     _spi->write(address >> 8);
00985     _spi->write(address);      
00986 }