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

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

[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        = "-";
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 0x300-0x3FF is write protected",
         "Array 0x200-0x3FF is write protected",
         "All memory space is write protected",0);

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

[Host]

define  END_ADR     1024
define  PAGE_SIZE   32

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 readed.",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(ForceCloseAfterWrite != 0) { return(0x7FFFFFFF); }
        else
        {
            print("   Writing is done. %i 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 0300 - 03FF is write protected.");
    }
    if(Temp = 2)
    {
        print("\; Array 0200 - 03FF 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;
        while(Address != END_ADR)
        {
            Temp = FSEL[Address];
            if(Temp = 0)
            {
                Run(WriteByte);
                BeginBlock;
                USB = Address;
                Temp = Address >> 8;
                USB = Temp;
                Temp = FBUF[Address];
                USB = Temp;
                EndBlock;
                Error = USB;
                if(Error != 0) { break;}
            }
            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(ForceCloseAfterWrite != 0) { return(0x7FFFFFFF); }
        else
        {
            print("   Writing is done. %i bytes were write.",Address);
        }
    }
}

Proc Info
{
  print("");
  print("  Module for programming SPI serial EEPROMs memory types ATMEL 25080.");
  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      END_ADR     1024
define      PAGE_SIZE   32

// Variables

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

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

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

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

    while(Address != END_ADR)
    {
        // enable write sequence
        CS = 0;BUSDATA = WREN;SCK = 0;CS = 1;

        // write command
        CS = 0;BUSDATA = OPWRITE;
        SCK = 0;
        Byte = Address >> 8;
        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 (PAGE_SIZE bytes)
            PageCounter = PAGE_SIZE;
            while(PageCounter != 0)
            {
                Byte = USB;BUSDATA = Byte;
                PageCounter--;
                Address++;                
            }
        }
        SCK = 0;
        CS = 1;
        WaitReady;
        USB = 0;
    }
}


// ****************************************************************
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;      // low byte
        Byte = USB;         // high byte

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

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

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