[Description]
Location = "Atmel\EEPROM\SPI EEPROM\AT25F1024";
Info = " Module for programming SPI serial EEPROMs memory types AT25F1024.",
    " ----------------------------------------------------------------------------------------------------------------------",
    " Bus: SPI.",
    " Size: 131072 bytes (128 Kbytes)",
    " ---------------------------------------------------------------------------------------------------------------------- ",
    " Supported modes: Read, write, verify.",
    " ---------------------------------------------------------------------------------------------------------------------- ",
    " Author: ETL";

Buffer1 = "EEPROM",131072;
Picture = "25XX.bmp";
VCC = 8;
GND = 4;
Voltage = 2.8;

[Menu]

Read        = "&Read",ReadButton,"Read chip",F2;
Div10       = "-";
Write       = "&Write",WriteButton,"Write chip",F5;
WriteChanges= "Write &changes",WriteChangesButton,"Write changes",F6;
Div0        = "-";
Compare     = "&Verify",CheckButton,"Compare with buffer",F3;
Div1        = "-";
ReadStatus  = "Read status register";
WriteStatus = "Write status register";
Div2        = "-";
ReadID      = "Read &ID bytes",ChipInfoButton,"Read ID Bytes",Alt+F1;
Div3        = "-";
Erase       = "Chip &erase",EraseButton,"Erase chip",F9;
Div4        = "-";
Info        = "&About module",ModuleInfoButton,"Show module info",F1;

[Interface]

CheckBox(UsePageWrite,"Use page write",10,5,1);
ComboBox(Protection,"Protection mode",120,6,210,"None",
         "Array 0x18000-0x1FFFF is write protected",
         "Array 0x10000-0x1FFFF is write protected",
         "All memory space is write protected",0);

// ==================================================
//                  Host section
// ==================================================

[Host]

define  END_ADR     131072
define  PAGE_SIZE   64

Proc Read {
    
    var Address,Error,Value;
    print("");
    print("  Reading chip...");
    Run(Read);
    Address = 0;PBPos = 0;PBMax = END_ADR;
    while(Address != END_ADR)
    {
        Value = USB;
        if(Value = 0x8000) { break; }
        FBUF[Address] = Value;
        Address++;
        PBPos++;
    }        
    if(Value = 0x8000)
    {
        print("  Reading error: Time out");
    }
    else
    {
        if(ForceCloseAfterRead != 0) { return(0x7FFFFFFF); }
        else
        {
            print("   Reading is done. %i bytes were read.",Address);
        }
    }
}


Proc Write  {

    var Address,Error,Value,Counter,Temp;
    print("");
    print("  Writing chip...");
    Address = 0;PBPos = 0;PBMax = END_ADR;
    Run(Write);
    if(UsePageWrite = 1)
    {
        USB = 1;
        print("  Page mode...");
        while(Address != END_ADR)
        {
            Counter = PAGE_SIZE;
            BeginBlock;
            while(Counter != 0)
            {
                Temp = FBUF[Address];
                USB = Temp;
                Counter--;
                Address++;   
            }
            EndBlock;
            Error = USB;
            if(Error != 0) { break; }
            PBPos = Address;
        }
    }
    else
    {
        // writing in byte mode

        USB = 0;
        print("  Byte mode...");
        while(Address != END_ADR)
        {
            Value = FBUF[Address];
            USB = Value;
            Error = USB;
            if(Error != 0) { break; }
            Address++;
            PBPos++;
        }
    }
    if(Error = 0x8000)
    {
        print("  Writing error: Time out. Address %i.",Address);
    }
    if(Error = 0)
    {
        if(GlobalVerify != 0) { Compare(); }
        if(ForcecloseAfterWrite != 0) { return(0x7FFFFFFF); }
        else
        {
            print("   Writing is done. %  bytes were write.",Address);
        }
    }
}

Proc Compare {

    var Address,Error,Value,Value2,Mismatch;
    print("");
    print("  Verifying chip...");
    Run(Read);
    Address = 0;PBPos = 0;PBMax = END_ADR;Mismatch = 0;
    while(Address != END_ADR)
    {
        Value = USB;
        Value2 = FBUF[Address];
        if(Value != Value2)
        {
            Mismatch++;
            FSEL[Address] = 0;    
        }
        else
        {
            FSEL[Address] = 1;
        }
        Address++;
        PBPos++;
    }
    if(Error = 0x8000)
    {
        print("  Verifying error: Time out. Address %i",Address);
    }
    else
    {
        if(ForceCloseAfterVerify != 0) { return(0x7FFFFFFF); }
        else
        {
            print("  Verifying is done. %i bytes were compare. Number of mismatch: %i",Address,Mismatch);
        }
    }
}

Proc ReadStatus
{
    var Temp;
    print("");
    print("   Reading status register...");
    Run(ReadStatus);
    Temp = USB;
    print("   Value of status register: %b.",Temp);
    Temp = Temp >> 2;
    Temp = Temp & 0x03;
    Protection = Temp;
    if(Temp = 0)
    {
        print("\; Not memory lock features.");
    }
    if(Temp = 1)
    {
        print("\; Array 18000 - 1FFFF is write protected.");
    }
    if(Temp = 2)
    {
        print("\; Array 10000 - 1FFFF is write protected.");
    }
    if(Temp = 3)
    {
        print("\; All memory array is write protected.");
    }
}

Proc WriteStatus
{
    var Temp;
    print("");
    Temp = Protection;
    Temp = Temp << 2;
    print("   Value of status register: %b",Temp);
    print("   Writing status register... ");
    Run(WriteStatus);
    USB = Temp;
    while
    {
        Temp = USB;
        if(Temp.0 = 0) { break;}
    }
    print("\;Done.");
}

Proc WriteChanges
{
    var Address,Temp,Value,Mismatch,Error;
    Address = 0;Temp = 0;
    print("");
    while(Address != END_ADR)
    {
        Value = FSEL[Address];
        if(Value = 0) {Temp++;}
        Address++;    
    }
    if(Temp = 0)
    {        
        print("   Any mismatch is not found. Writing is canceled.");
        return;
    }
    else
    {
        print("   Writing changes...");
        PBpos = 0; PBMax = END_ADR;Address = 0;Error = 0;
        Mismatch = 0;
        while(Address != END_ADR)
        {
            Temp = FSEL[Address];
            if(Temp = 0)
            {
                Run(WriteByte);
                BeginBlock;
                USB = Address;
                Temp = Address >> 8;
                USB = Temp;
                Temp = Address >> 16;
                USB = Temp;
                Temp = FBUF[Address];
                USB = Temp;
                EndBlock;
                Error = USB;
                if(Error != 0) { break;}
                Mismatch++;
            }
            Address++;
            PBPos++;
        }
    }
    if(Error = 0x8000)
    {
        print("  Writing error: Time out. Address: %i",Address);
    }
    if(Error = 0xFF)
    {
        print("  Wrintig error. Device not response. Address %i", Address);
    }
    if(Error = 0)
    {
        if(GlobalVerify != 0) { Compare(); }
        if(ForceCloseAfterWrite != 0) { return(0x7FFFFFFF); }
        else
        {
            print("   Writing is done. %i bytes were write.",Mismatch);
        }
    }
}

Proc ReadID
{
    var Man,Dev;
    print("");
    print("   Read product ID...");
    Run(ReadID);
    Man = USB;
    Dev = USB;
    print("");
    print("   Next ID bytes readed:");
    print("");
    print("   Manufacturer code: %b",Man);
    if(Man = 0x1F) { print("\; (Atmel)"); }
    else { print("\; (unknown)");}
    print("   Device code:           %b",Dev);
    if(Dev = 0x60) { print("\; (25F1024)"); }
    else { print("\; (unknown)");}
}

Proc Erase
{
    var Result;
    print("");
    print("   Erasing in progress, wait please...");
    Run(Erase);
    while
    {
        USB = 255;
        Result = USB;
        if(Result.0 = 0) { break; }
    }
    USB = 0;
    if(ForceCloseAfterWrite != 0) { return(0x7FFFFFFF); }
    else
    {
        print("   Erasing is done");
    }
}

Proc Info
{
  print("");
  print("  Module for programming SPI serial EEPROMs memory types 25F1024.");
  print("");
  print("  Copyright (C) 2006 ETL.");
}


// ========================================================
//                    Device section
// ========================================================

[Device]

define      CS      POUT.0
define      SOOUT   POUT.1
define      SOIN    PIN.1
define      WP      POUT.2
define      SI      POUT.4
define      SCK     POUT.5
define      HOLD    POUT.6

define      WREN        0b00000110
define      WRDI        0b00000100
define      RDSR        0b00000101
define      WRSR        0b00000001
define      OPREAD      0b00000011
define      OPWRITE     0b00000010
define      RDID        0b00010101
define      CHIPERASE   0b01100010

define      PAGE_SIZE   64

// Variables

var AdrH,Address,Mode,Byte,Counter,Data,PageCounter;

//***********************************************************
//*       Read                                             **
//***********************************************************
Proc Read
{
    POUT = 0b11000111;
    BUSInit(5,1,4,1,0);
    BUSDELAY = 0;
    Address = 0;AdrH = 0;
    CS = 0;
    BUSDATA = OPREAD;BUSDATA = 0;BUSDATA = 0;BUSDATA = 0;
    SOOUT = 1;
    while
    {
        Byte = BUSDATA;
        USB = Byte;
        Address++;
        if(Address = 0) 
        { 
            AdrH++;
            if(AdrH = 2) { break; }
        }    
    } 
    CS = 1;
}

//**********************************************************
//*         Write                                         **
//**********************************************************

Proc Write
{
    POUT = 0b11000111;
    Address = 0;AdrH = 0;
    BUSInit(5,1,4,1,0);
    BUSDELAY = 0;
    Mode = USB;

    while
    {
        // enable write sequence
        CS = 0;BUSDATA = WREN;SCK = 0;CS = 1;

        // write command
        CS = 0;BUSDATA = OPWRITE;
        SCK = 0;
        Byte = Address >> 8;
        BUSDATA = AdrH;
        BUSDATA = Byte;
        BUSDATA = Address;
        if(Mode = 0)
        {
            // byte mode - send to chip one byte
            Byte = USB;BUSDATA = Byte;Address++;   
        }
        else
        {
            // page mode - send to chip one page (64 bytes)
            PageCounter = PAGE_SIZE;
            while(PageCounter != 0)
            {
                Byte = USB;BUSDATA = Byte;
                PageCounter--;
                Address++;                
            }
        }
        SCK = 0;
        CS = 1;
        WaitReady;
        USB = 0;
        if(Address = 0) 
        {
            AdrH++;
            if(AdrH = 2) { break; } 
        }
    }
}


// ****************************************************************
Proc WaitReady
{
    while
    {
        CS = 0;
        BUSDATA = RDSR;
        SOOUT = 1;
        Byte = BUSDATA;
        SCK = 0;
        CS = 1;
        if(Byte.0 = 0) { break; }
    }      
}
// ****************************************************************


Proc ReadStatus
{
    POUT = 0b11000111;
    BUSInit(5,1,4,1,0);
    CS = 0;
    BUSDATA = RDSR;
    SCK = 0;
    SOOUT = 1;
    Byte = BUSDATA;
    USB = Byte;
    SCK = 0;
    CS = 1;
}

Proc WriteStatus
{
    POUT = 0b11000111;
    BUSInit(5,1,4,1,0);
    Byte = USB;
    CS = 0;
    BUSDATA = WREN;
    CS = 1;
    CS = 0;
    BUSDATA = WRSR;
    BUSDATA = Byte;
    CS = 1;
    while
    {
        CS = 0;
        BUSDATA = RDSR;
        SOOUT = 1;
        Byte = BUSDATA;
        SCK = 0;
        USB = Byte;
        CS = 1;
        if(Byte.0 = 0) { break; }
    }     
}

Proc WriteByte
{
    POUT = 0b11000111;
    BUSInit(5,1,4,1,0);
    BUSDELAY = 0;

        Address = USB;      // address low byte
        Byte = USB;         // address high byte
        AdrH = USB;         // A16

        // enable write sequence
        CS = 0;BUSDATA = WREN;SCK = 0;CS = 1;

        // write command
        CS = 0;BUSDATA = OPWRITE;
        SCK = 0;
        BUSDATA = AdrH;
        BUSDATA = Byte;
        BUSDATA = Address;

        Byte = USB;
        BUSDATA = Byte;  
        SCK = 0;
        CS = 1;
        WaitReady;
        USB = 0;
}

Proc ReadID
{
    POUT = 0b11000111;
    BUSInit(5,1,4,1,0);
    CS = 0;
    BUSDATA = RDID;
    Byte = BUSDATA;USB = Byte;
    Byte = BUSDATA;USB = Byte;
    CS = 1;
}

Proc Erase
{
    POUT = 0b11000111;
    BUSInit(5,1,4,1,0);

    // ---------- enable write sequence
    CS = 0;BUSDATA = WREN;SCK = 0;CS = 1;

    // ---------- erase command
    CS = 0;BUSDATA = CHIPERASE;CS = 1;

    while
    {
        Byte = USB;
        if(Byte = 0) { break;}
        else
        {
            CS = 0;
            BUSDATA = RDSR;
            SCK = 0;
            SOOUT = 1;
            Byte = BUSDATA;
            USB = Byte;
            SCK = 0;
            CS = 1;            
        }
    }
}
