[Description]

Location = "FLASH\Macronix\MX29F001";
Info = " Manufacturer: Macronix",
       " Device: MX29F001T(B)",
       " Memory size: 128 Kbytes (1 MBits)",
       " ",
       "  Note: special adapter are required!",
       " ",
       "  Supported functions:",
       "      Auto erase chip and auto program chip",
       "      Chip protect/unprotect",
       "      Chip read/verify",
       "------------------------------------------------",
       "  Copyright (C) ETL 2006";

Buffer1 = "FLASH",131072 ;
Voltage = 5.0;

[Menu]

Read        = "&Read",ReadButton;
Write       = "&Write",WriteButton,"Write chip";
Compare     = "&Verify",CheckButton,"Compare with buffer";
Div0        = "-";
Erase       = "&Erase",EraseButton,"Erase chip";
Div1        = "-";
AutoDetect  = "Read &signature",ChipInfoButton,"Read signature bytes";
Div2        = "-";
CheckProtect= "Verify chip protect/unprotect";
Protect     = "Protect chip";
UnProtect   = "Unprotect chip";
Div3        = "-";
Info        = "&About module",ModuleInfoButton,"Show module info";

[Interface]

CheckBox(EraseBeforeWrite,"Erase before write",10,10,1);
CheckBox(VerifyAfterErase,"Checking chip cleanness after erase",10,30,1);

[Host]


Proc Read 
{
    var Value,Address;
    print("");
    print("   Reading chip...");
    Value = 1;
    Address = 0;
    PBMax = 131072;
    Run(Read);
    while(Address != 131072) 
    {
        Value = USB;
        FBUF[Address] = Value;
        Address++;
        PBPos++;
    }
    print("");
    return(0x7FFFFFFF);
    //print("   Reading is done. %i bytes were readed.",Address);      
}


Proc Compare 
{
    var Value,Address,Temp,Mismatch;
    print("");
    print("   Verifying chip...");
    Value = 1;
    Address = 0;
    PBMax = 131072;
    Mismatch = 0;
    Run(Read);
    while(Address != 131072) 
    {
        Value = USB;
        Temp = FBUF[Address];
        if(Temp != Value)
        {
            Mismatch++;
            FSEL[Address] = 0;    
        }
        else
        {
            FSEL[Address] = 1;
        }
        Address++;
        PBPos++;
    }
    print("");
    print("   Verifying is done. %i bytes were compared. Mismatch: %i.",Address,Mismatch);
}

Proc AutoDetect
{
    var MC,DC;
    Run(Detect);
    MC = USB;
    DC = USB;
    print("   Read signature....");
    print("");
    print("   Next code was readed: %b%b.",MC,DC);      
}

Proc CheckProtect
{
    var Value;
    print("");
    print("   Check protect status...");
    Run(CheckProtect);
    Value = USB;
    if(Value = 1)
    {
        print("\; Device is protected.");
    }
    else
    {
        print("\; Device is unprotected.");
    }
}

Proc Erase
{
    var Value,NotErase,Address;
    print("");
    print("   Erasing chip, wait please...");
    Run(EraseChip);
    while
    {
        USB = 1;
        Value = USB;
        if(Value.7 = 1) { break;}
    }
    USB = 0;
    print("\; Done.");
    if(VerifyAfterErase != 0)
    {
        print("");
        print("   Checking chip cleanness...");
        PBPos = 0;
        PBMax = 131072;
        NotErase = 0;
        Run(Read);
        while(Address != 131072) 
        {   
            Value = USB;
            if(Value != 255) { NotErase++; }
            PBPos++;
            Address++;
        }
        if(NotErase = 0)
        {
            print("\; Success.");   
        }
        else
        {
            print("\; Error. %i bytes not cleared.",NotErase);
        }
    }
}


Proc Write
{
    var Value,Address,Counter,NotErase;
    
    PBMax = 131072;

    print("");
    if(EraseBeforeWrite != 0)
    {
        //--------- Erase device
        print("   Erasing chip, wait please...");
        Run(EraseChip);
        while
        {
            USB = 1;
            Value = USB;
            if(Value.7 = 1) { break;}
        }
        USB = 0;
        print("\; Done.");
        if(VerifyAfterErase != 0)
        {
            print("   Checking chip cleanness...");
            PBPos = 0;
            NotErase = 0;
            Run(Read);
            while(Address != 131072) 
            {   
                Value = USB;
                if(Value != 255) { NotErase++; }
                PBPos++;
                Address++;
            }
            if(NotErase = 0)
            {
                print("\; Success.");   
            }
            else
            {
                print("\; Error. %i bytes not cleared.",NotErase);
                print("Programming canceled");
                return;
            }
        }
    }
    //-------- Write device
    print("   Writing chip...");
    Address = 0;
    PBPos = 0;
    Run(Write);
    while(Address != 131072)
    {
        Counter = 64;
        BeginBlock;
        while(Counter != 0)
        {
            Value = FBUF[Address];
            USB = Value;
            Counter--;
            Address++;
        }
        EndBlock;
        Value = USB;
        if(Value != 0)
        {
            //--------- Writing error
            Value = Value - 65;
            Value = Value + Address;
            print("\; Error. Address: %i",Value);
            Value = 1;
            break;
        }
        PBPos = Address;
    }
    if(Value = 0)
    {
        print("\; Success.");
        print("\; %i bytes writed and verified",Address);    
    }
}

Proc Protect
{
    var Counter,Temp;
    print("");
    print("   Protect chip, wait please...");
    Counter = 32;
    Run(LockUnlock);
    while(Counter != 0)
    {
        USB = 1;
        USB = 1;
        Temp = USB;
        if(Temp = 1) { break;}
        Counter--;
    }
    USB = 0;
    if(Temp = 1)
    {
        print("\; Success.");
    }
    else
    {
        print("\; Error. Device failed.");
    }
}

Proc Unprotect
{
    var Counter,Temp;
    print("");
    print("   Unprotect chip, wait please...");
    Counter = 1000;
    Run(LockUnlock);
    while(Counter != 0)
    {
        USB = 1;
        USB = 0;
        Temp = USB;
        if(Temp = 0) { break;}
        Counter--;
    }
    USB = 0;
    if(Temp = 0)
    {
        print("\; Success.");
    }
    else
    {
        print("\; Error. Device failed.");
    }
}

Proc Info
{
    print("  Module for programming CMOS FLASH memory.");
    print("  ---------------------------------------------");
    print("  Note: special adapter are required!");
    print("  ---------------------------------------------");
    print("  Memory type:  MX29F001T/B");
    print("  Manufacturer: Macronix");
    print("  Supported functions:");
    print("      Auto erase chip and auto program chip");
    print("      Chip protect/unprotect");
    print("      Chip read/verify");
    print("  ---------------------------------------------");
    print("  Copyright (C) ETL 2006");
}


[Device]

ereg    ADRL,   0,1
ereg    ADRH,   1,1
ereg    CTRL,   2,1
ereg    DATAIN, 3,0    
ereg    DATAOUT,4,1
ereg    PWRCTRL,5,1

define  CS_AND_OE_LOW       0b11010111
define  CS_AND_OE_HIGH      0b00101000

define  OE  3
define  WE  4
define  CS  5
define  DE  7

var Value,Address,AddressH,Temp,Control,JEDECByte,Counter,Byte,Error;

Proc Read
{
    EP = 0x08;
    PWRCTRL = 0b00000001;
    Address = 0;AddressH = 0;
    Control = 0b11111110;
    Control = Control & CS_AND_OE_LOW;
    CTRL = Control;
    DATAOUT = 255;
    Delay(50000);
    while
    {
        ADRL = Address;
        Temp = Address >> 8;
        ADRH = Temp;
        //Control = Control & CS_AND_OE_LOW;
        Control = Control | AddressH;
        CTRL = Control;
        Value = DATAIN;
        //Control = Control | CS_AND_OE_HIGH;
        //CTRL = Control;
        USB = Value;
        Address++;
        if(Address = 0)
        {
            AddressH++;
            if(AddressH = 2) { break; }
        }
    }    
    PWRCTRL = 3;
}

Proc Erase
{
    EP = 0x08;
}

Proc WritePulse
{
    Control.WE = 0;CTRL = Control;
    Control.WE = 1;CTRL = Control;
}

Proc CheckProtect
{
    PWRCTRL = 1;
    EP = 0x08;
    Control = 0b11111000;   // Chip disable, Data out disable
    CTRL = Control;

    Delay(10000);

    //--------- Three-Byte Sequence for Verify chip protect

    JEDECByte = 0x90;JEDECSequence;

    //--------- Read Protect status

    ADRH = 2;ADRL = 2;                      // A9 = "1", A1 = "1" (protect status)
    DATAOUT = 255;
    Control = Control & CS_AND_OE_LOW;      // Enable chip for read
    CTRL = Control;                         
    Value = DATAIN;USB = Value;             // Manufacturer code
    CTRL = 0b11111110;                      // Disable chip
    PWRCTRL = 0b00000011;                   // Power OFF

}

Proc JEDECSequence
{
    //Control.DE = 0;CTRL = Control;               // Data output enable
    Control.CS = 0;CTRL = Control;               // Select chip for write
    ADRH = 0x55;ADRL = 0x55;DATAOUT = 0xAA;      // Address = 0x5555, Data = 0xAA
    WritePulse;                                  // Write pulse
    ADRH = 0x2A;ADRL = 0xAA;DATAOUT = 0x55;      // Address = 0x2AAA, Data = 0x55
    WritePulse;                                  // Write pulse
    ADRH = 0x55;ADRL = 0x55;DATAOUT = JEDECByte; // Command byte
    WritePulse;                                  // Write pulse
    //Control.DE = 1;CTRL = Control;               // Data output disable
    Control.CS = 1;CTRL = Control;               // Deselect chip
}

Proc EraseChip
{
    PWRCTRL = 1;
    EP = 0x08;
    Control = 0b11111000;   // Chip disable, Data out disable
    CTRL = Control;
    Delay(10000);

    //--------- Chip erase sequence
    JEDECByte = 0x80;JEDECSequence;
    JEDECByte = 0x10;JEDECSequence;
    DATAOUT = 255;
    //--------- Wait until erase
    while
    {
        Value = USB;
        if(Value = 0) { break;}
        Control = Control & CS_AND_OE_LOW;CTRL = Control;
        Value = DATAIN;
        Control = Control | CS_AND_OE_HIGH;CTRL = Control;
        USB = Value;
    }
}

Proc Write
{
    EP = 0x08;
    PWRCTRL = 1;
    Address = 0; AddressH = 0;    
    Control = 0b11111000;CTRL = Control;
    Counter = 0;
    Error = 0;
    while
    {
        Byte = USB;
        //-------- Write command
        JEDECByte = 0xA0;
        JEDECSequence;
        ADRL = Address;                 // Set Address
        Temp = Address >> 8;
        ADRH = Temp;
        DATAOUT = Byte;                 // Set data byte
        Control.DE = 0;                 // Enable data out
        Control.CS = 0;                 // Select chip
        CTRL = Control;       
        WritePulse;
        Control.CS = 1;                 // Deselect chip
        Control.DE = 1;                 // Disable data out
        CTRL = Control;

        //-------- Wait until ready
        WaitToggle;
        
        //-------- Verify byte
        ReadByte;
        if(Byte != Value)   
        { 
            if(Error = 0)
            {
                Error = Counter + 1;    // Remember address
            }
        }   
        Counter++;
        if(Counter = 64)
        {
            Counter = 0;
            USB = Error;
            if(Error != 0) { break;}
        }
        Address++;
        if(Address = 0)
        {
            AddressH++;
            if(AddressH = 2) { break;}
            Control.0 = 1;              // A16 = 1 
        }
    }
    PWRCTRL = 3;
}

Proc ReadByte
{
        Control = Control & CS_AND_OE_LOW;
        CTRL = Control;
        DATAOUT = 255;
        Value = DATAIN;
        Control = Control | CS_AND_OE_HIGH;
        CTRL = Control;
}

Proc WaitToggle
{
    ReadByte;
    Temp = Value & 0x40;
    while
    {
        ReadByte;
        Value = Value & 0x40;
        if(Temp = Value)
        {
            //------ Q6 not toggled, Program Operation Complete 
            return;
        }
        else 
        {
            //------ Q6 toggled
            Temp = Value;
        }
    }
}

Proc LockUnlock
{
    EP = 0x08;
    Control = 0b11111000;CTRL = Control;
    PWRCTRL = 1;
    Delay(10000);
    while
    {
        Byte = USB;
        if(Byte = 0) { break; }
        Byte = USB;     
        //---------- Unlock for chip protect/unprotect sequence

        JEDECByte = 0x80;JEDECSequence;
        JEDECByte = 0x20;JEDECSequence;
        if(Byte = 0)
        {
            //------ unprotect
            ADRL = 0b01000000;ADRH = 0b00000010;    // A6 = "1", A9 = "1"                
        }
        else
        {
            //------ protect
            ADRL = 0x00;ADRH = 0b00000010;          // A6 = "0", A9 = "1"                
        }
        Control.CS = 0;CTRL = Control;              // Select chip
        WritePulse;                                 // Write pulse

        //------ Wait toggle
        //------ Read first data byte
        Control.OE = 0;CTRL = Control;
        Temp = DATAIN;
        Control.OE = 1;CTRL = Control;
        while
        {
            //----- Read next bytes and check toggle
            Control.OE = 0;CTRL = Control;
            Value = DATAIN;
            Control.OE = 1;CTRL = Control;
            Temp = Temp ^ Value;
            Temp = Temp & 0x40;
            if(Temp = 0) { break; }
            Temp = Value;         
        }
        Control.CS = 1;CTRL = Control;              // Deselect chip

        ADRL = 2;ADRH = 2;                          // A1 = "1"; A9 ="1"
        ReadByte;                                   // Read protect status
        USB = Value;
    }     
}