[Description]
Location = "Atmel\AVR\ATMega8";
Info = " Module for programming AVR microcontrollers via SPI interface.",
    " Chip: ATMega8. Manufacturer: Atmel",
    " ------------------------------------------------------------------------",
    " Bus: SPI.",
    " FLASH size: 8192 bytes (4096 words).",
    " EEPROM size: 512 bytes",
    "---------------------------------------------",
    " Author: ETL (c) 2006";
Buffer1 = "FLASH",8192;
Buffer2 = "EEPROM",512;
Picture = "AVR ICP.BMP";
VCC = 8;
GND = 4;
Voltage = 5.0;

[Menu]

//FullWrite = "Full write";
//Div8 = "-";
ReadSignature = "Read signature bytes",ChipInfoButton,"Read signature bytes";
Div1 = "-";
ReadFlash = "Read FLASH",ReadButton,"Read FLASH";
WriteFlash = "Write FLASH",WriteButton,"Write FLASH";
Compare = "Verify FLASH",CheckButton,"Verify FLASH";
Div2 = "-";
Erase = "Erase FLASH and EEPROM",EraseButton,"Erase FLASH and EEPROM";
Div3 = "-";
ReadEEPROM = "Read EEPROM",ReadEEPROMButton,"Read EEPROM";
WriteEEPROM = "Write EEPROM",WriteEEPROMButton,"Write EEPROM";
Div4 = "-";
ReadLock = "Read lock bits";
WriteLock = "Write lock bits";
Div5 ="-";
ReadFuse = "Read fuse bits";
WriteFuse = "Write fuse bits";
Div6 = "-";
ReadCalibration = "Read calibration byte";
Div7 = "-";
ModuleInfo = "About module",ModuleInfoButton,"About module";


[Interface window]

CheckBox(EraseBeforeWrite,"Erase before write",5,8,1);
CheckBox(VerifyDuringWrite,"Verify during write",115,8,1);

ComboBox(SPIClock,"SCK clock",42,35,115,"Highest","1 MHz","500 KHz","250 KHz","125 KHz","64 KHz","32 KHz",2);
ComboBox(LockLBMode,"Lock LB mode",23,60,115,"Not lock","LB1=1,LB2=0","LB1=0,LB2=0",0);
ComboBox(LockBLB0Mode,"Lock BLB0 mode",10,85,115,"Not lock","BLB02=1,BLB01=0",
                                                "BLB02=0;BLB01=0","BLB02=0;BLB01=1",0);
ComboBox(LockBLB1Mode,"Lock BLB1 mode",10,110,115,"Not lock","BLB12=1,BLB11=0",
                                                "BLB12=0;BLB11=0","BLB12=0;BLB11=1",0);

ComboBox(BootSize,"Boot size (words)",12,135,90,"128","256","512","1024",0);
ComboBox(ResetVector,"Reset vector",31,160,90,"Bootloader","Default",1);
ComboBox(BrownOutDetector,"Brown-out Detector",229,10,90,"Enabled","Disabled",1);
ComboBox(BrownOutVoltage,"Brown-out voltage",235,35,90,"4 V","2.7 V",0);
ComboBox(CKSEL,"CKSEL",287,60,90,"0000",
                                      "0001",
                                      "0010",
                                      "0011",
                                      "0100",
                                      "0101",
                                      "0110",
                                      "0111",
                                      "1000",
                                      "1001",
                                      "1010",
                                      "1011",
                                      "1100",
                                      "1101",
                                      "1110",
                                      "1111",
                                       1);
ComboBox(CKOPT,"CKOPT",285,85,90,"0","1",1);
ComboBox(SUT,"Start up time",262,110,110,"SUT1=0,SUT0=0","SUT1=0,SUT0=1","SUT1=1,SUT0=0","SUT1=1,SUT0=1",2);
ComboBox(EEsave,"EEPROM preseve",234,135,90,"Not erase","Erase",1);
ComboBox(WDTON,"Watchdog",271,160,120,"Always on","Enabled by WDTCR",1);

[Host]

define      FLASH_SIZE       8192            
define      FLASH_PAGE_SIZE 64           
define      EEPROM_SIZE      512     


//Proc FullWrite
//{
//    WriteFlash;
//    WriteFuse;
//    WriteLock;
//}

//***********************************************************************
//*             ReadSignature                                          **
//***********************************************************************
Proc ReadSignature 
{
    var B1,B2,B3,Signature;

    print("");
    print("   Reading signature bytes...");
    Run(InitSPI);
    B1 = SPIClock*10;
    USB = B1;
    B1 = USB;
    if(B1 != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    Run(ReadSignature);
    B1 = USB;
    B2 = USB;
    B3 = USB;
    print("");
    print("   Next signature bytes were readed: %b %b %b",B1,B2,B3);
    Signature = B2 << 8;
    Signature = Signature | B3;
    if(B1 = 0)
    {
      if(Signature = 0x0102) 
      {
        print("   Unknown device or locked device.");
        print("");
        print("   Note: The Lock Bits can only be erased with the Chip Erase operation.");
        return(0);
      }
    }
    if(B1 = 0x1E) { print("    Manufacturer: Atmel");    }
    else          { print("    Unknown manufacturer");   }
    if(Signature = 0x9307) { print("    Device: ATMega8"); }
    else          { print("    Device is not ATMega8. Use AVR detecor for identification."); }
}

Proc ReadFlash 
{
    var Address,Temp,FlashEnd;

    print("");
    print("   Reading FLASH...");
    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    Address = 0;
    Run(ReadFlash);
    PBMax = FLASH_SIZE;
    while(Address != FLASH_SIZE)
    {
        Temp = USB;
        if(Temp = 0x8000) { break; }
        FBUF[Address] = Temp;
        Address++;
        PBPos++;
    }
    Address = Address >> 1;
    print("");
    if(Temp = 0x8000)
    {
        print("   Reading error. Time out. Address %i.",Address);
    }
    else
    {
        print("   Reading is done. %i word were readed.",Address);
    }
}

Proc WriteFlash
{
    var Address,WritedWords,Temp,PageAddress,Counter,Temp2,Error,EmptyPage;

    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }

    if(EraseBeforeWrite = 1)
    {
        print("");
        print("   Erasing chip...");
        Run(ChipErase);
        Temp = USB;
        if(Temp = 0x8000)
        {
            print("");
            print("   Erasing error. Time out.");
            return;
        }
        else { print("\; Done.");}
    }
    print("");
    if(VerifyDuringWrite = 0)
    {
        print("   Writing FLASH...");
    }
    else
    {
        print("   Writing and verifying FLASH...");
    }
    Run(WriteFlash);
    USB = VerifyDuringWrite;
    PBPos = 0;
    PBMax = FLASH_SIZE;
    Address = 0;WritedWords = 0;Error = 0;
    PageAddress = 0;
    while(Address != FLASH_SIZE)
    {
        // if all cells in a page are 0xFF, not program this page

        Counter = FLASH_PAGE_SIZE;
        EmptyPage = 0;
        Address = PageAddress;
        while(Counter != 0)
        {
            Temp = FBUF[Address];
            if(Temp != 0xFF) { EmptyPage = 1;}
            Address++;
            Counter--;
        } 
        if(EmptyPage != 0)
        {
            WritedWords = WritedWords + FLASH_PAGE_SIZE;
            USB = 1;        // next page

            // load page

            Counter = FLASH_PAGE_SIZE;
            Address = PageAddress;
            BeginBlock;
            while(Counter != 0)
            {
                Temp = FBUF[Address];
                USB = Temp;
                Address++;
                Counter--;
            } 
            EndBlock;

            // send to ETSmart page address
            Temp = PageAddress >> 9;USB = Temp;   // high byte
            Temp = PageAddress >> 1;USB = Temp;   // low byte

            Error = USB;
            if(Error = 0x8000) { break; }
            if(VerifyDuringWrite != 0)

            {
                // read back and verify page
                Address = PageAddress;
                Error = 0x00;
                Counter = FLASH_PAGE_SIZE;
                while(Counter != 0)
                {
                    Temp = USB;
                    Temp2 = FBUF[Address];
                    if(Temp != Temp2)
                    {
                        if(Error = 0x00) { Error = Address + 1; }
                    }
                    Counter--;
                    Address++;
                }
                if(Error != 0) { break; }
            }
        }
        PageAddress = PageAddress + FLASH_PAGE_SIZE;
        PBPos = PageAddress;     
    }
    USB = 0;  // Finish writing      
    if(Error = 0x8000)
    {
        print("");
        print("   Writing error. Time out. Address: %i",PageAddress);
    }
    else
    {
        if(Error != 0)
        {
            Error--;
            print("");
            print("   Writing error. Address: %i",PageAddress);
        }
        else
        {
            print("");
            print("   Writing success. %i bytes were writed.",WritedWords);
        }
    }
}


Proc Compare
{
    var Address,Temp,FlashEnd,Byte,Mismatch;
    print("");
    print("   Verifying FLASH...");
    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    Address = 0;
    Run(ReadFlash);
    FlashEnd = FLASH_SIZE;
    PBMax = FlashEnd;
    Mismatch = 0;
    while(Address != FLASH_SIZE)
    {
        Temp = USB;
        if(Temp = 0x8000) { break; }
        Byte = FBUF[Address];
        if(Byte != Temp)
        {
            FSEL[Address] = 0;
            Mismatch++;    
        }
        else
        {
            FSEL[Address] = 1;
        }
        Address++;
        PBPos++;
    }
    Address = Address >> 1;
    print("");
    if(Temp = 0x8000)
    {
        print("   Verifying error. Time out. Address %i.",Address);
    }
    else
    {
        print("   Verifying is done. %i word were compared. Number of mismatch %i",Address,Mismatch);
    }
}

Proc ReadEEPROM
{
    var Address,Temp;
    print("");
    print("   Reading EEPROM...");
    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    Address = 0;
    Run(ReadEEPROM);
    PBMax = EEPROM_SIZE;
    while(Address != EEPROM_SIZE)
    {
        Temp = USB;
        if(Temp = 0x8000) { break; }
        EBUF[Address] = Temp;
        Address++;
        PBPos++;
    }
    print("");
    if(Temp = 0x8000)
    {
        print("   Reading error. Time out. Address %i.",Address);
    }
    else
    {
        print("   Reading is done. %i bytes were readed.",Address);
    }
}

Proc WriteEEPROM
{
    var Address,Temp,Value;
    print("");
    print("   Writing EEPROM...");
    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    Address = 0;
    Run(WriteEEPROM);
    PBMax = EEPROM_SIZE;
    while(Address != EEPROM_SIZE)
    {
        Temp = EBUF[Address];
        USB = Temp;
        Value = USB;
        if(Value = 0x8000) { break; }
        if(Value != Temp)
        {
            print("   Writing error. Address %i",Address);
            print("   Byte was writed: %b, but read back: %b",Temp,Value);
            Value = 0x4000;
            break;
        }
        Address++;
        PBPos++;
    }
    print("");
    if(Value = 0x8000)
    {
        print("   Writing error. Time out. Address %i.",Address);
    }
    else
    {
        if(Value != 0x4000)
        {
            print("   Writing is done. %i bytes were writed and verifyed.",Address);
        }
    }
}

Proc Erase
{
    var Temp;
    print("   Erasing...");
    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    Run(ChipErase);
    Temp = USB;
    if(Temp = 0x8000)
    {
        print("");
        print("   Erasing error. Time out.");    
    }
    else
    {
        print("");
        print("   Erasing success.");
    }
}

Proc WriteLock
{
    var Temp,Value;

    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    print("");
    print("   Writing lock bits...");
    print("");

    Value = 255;
    if(LockLBMode = 0)   { Temp = 0b11111111;}
    if(LockLBMode = 1)   { Temp = 0b11111110;}
    if(LockLBMode = 2)   { Temp = 0b11111100;}
    Value = Value & Temp;
    if(LockBLB0Mode = 0) { Temp = 0b11111111;}
    if(LockBLB0Mode = 1) { Temp = 0b11111011;}
    if(LockBLB0Mode = 2) { Temp = 0b11110011;}
    if(LockBLB0Mode = 3) { Temp = 0b11110111;}
    Value = Value & Temp;
    if(LockBLB1Mode = 0) { Temp = 0b11111111;}
    if(LockBLB1Mode = 1) { Temp = 0b11101111;}
    if(LockBLB1Mode = 2) { Temp = 0b11001111;}
    if(LockBLB1Mode = 3) { Temp = 0b11011111;}
    Value = Value & Temp;

    Run(WriteLock);
    USB = Value;
    Temp = USB;
    if(Temp = 0x8000)
    {
        print("   Writing error. Time out."); 
    }
    else
    {
        print("   Writing success.");
        ReadLock();
    }
}

Proc ReadLock
{
    var Temp,Value;

    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    print("");
    print("   Read lock bits...");
    Run(ReadLock);
    Temp = USB;
    print("");
    print("   Next lock bits were readed: %b",Temp);
    print("   -------------------------------------");
    Value = Temp & 0x01;
    print("   LB1 = %i",Value);
    Temp = Temp >> 1;
    Value = Temp & 0x01;
    print("   LB2 = %i",Value);
    Temp = Temp >> 1;
    Value = Temp & 0x01;
    print("   BLB01 = %i",Value);
    Temp = Temp >> 1;
    Value = Temp & 0x01;
    print("   BLB02 = %i",Value);
    Temp = Temp >> 1;
    Value = Temp & 0x01;
    print("   BLB11 = %i",Value);
    Temp = Temp >> 1;
    Value = Temp & 0x01;
    print("   BLB12 = %i",Value);
}

Proc ReadFuse
{
    var Temp,Value,Fuse,FuseH;
    print("   Read fuse bits...");
    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }

    Run(ReadFuse);
    Fuse = USB;
    if(Fuse = 0x8000)
    {
        print("   Reading error: time out");
        return;
    }
    FuseH = USB;
    if(FuseH = 0x8000)
    {
        print("   Reading error: time out");
        return;
    }
    print("\; Next fuse bits were readed:");
    print("");
    Value = FuseH >> 7;
    print("   RSTDISBL = %i: ",Value);
    if(Value = 0)  { print("\; PC6 is IO pin"); }
    else { print("\; PC6 is RESET pin"); }

    Value = FuseH >> 6; Value = Value & 1;
    print("       WDTON = %i: ",Value);
    if(Value = 0)  { print("\; WDT always on"); }
    else { print("\; WDT enabled by WDTCR"); }

    Value = FuseH >> 5; Value = Value & 1;
    print("          SPIEN = %i: ",Value);
    if(Value = 0)  { print("\; SPI programming enabled"); }
    else { print("\; SPI programming disabled"); }

    Value = FuseH >> 4; Value = Value & 1;
    print("         CKOPT = %i: ",Value);

    Value = FuseH >> 3; Value = Value & 1;
    print("       EESAVE = %i: ",Value);
    if(Value = 0)  { print("\; EEPROM preserved"); }
    else { print("\; EEPROM not preserved"); }

    Value = FuseH & 1;
    print("    BOOTRST = %i: ",Value);
    if(Value = 1)  { print("\; Reset vector - default"); }
    else 
    { 
        print("\; Reset vector - bootloader. "); 
        Value = FuseH >> 1;
        Value = Value & 3;
        print("\;Boot size: ");
        if(Value = 0) { print("\;1024 words"); }
        if(Value = 1) { print("\;512 words"); }
        if(Value = 2) { print("\;256 words"); }
        if(Value = 3) { print("\;128 words"); }
    }
    Value = Fuse >> 6; Value = Value & 1;
    print("  BODLEVEL = %i: ",Value);
    if(Value = 1) { print("\; Brown out detector disabled");}
    else
    {
        print("\; Brown out detector enabled. Level: "); 
        Value = Fuse >> 7;
        if(Value = 1) { print("\;2.7 V");}
        else { print("\;4.0 V");}
    }
    print("          SUT10 = ");
    Value = Fuse >> 5; Value = Value & 0x01;
    print("\;%i",Value);
    Value = Fuse >> 4; Value = Value & 0x01;
    print("\;%i",Value);
    print("   CKSEL3...0 = ");
    Value = Fuse >> 3; Value = Value & 0x01;print("\;%i",Value);
    Value = Fuse >> 2; Value = Value & 0x01;print("\;%i",Value);
    Value = Fuse >> 1; Value = Value & 0x01;print("\;%i",Value);
    Value = Fuse & 0x01;print("\;%i",Value);
}

Proc WriteFuse
{
    var Temp,Value;

    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    print("");
    print("   Writing Fuse bits... ");
    print("");    
    // --------   Fuse
    Value = 0xFF;
    if(BrownOutVoltage = 0) { Value = Value & 0b01111111; }
    if(BrownOutDetector = 0) { Value = Value & 0b10111111; }
    Temp = SUT << 4;
    Temp = Temp | 0b11001111;
    Value = Value & Temp;
    Temp = CKSEL | 0b11110000;
    Value = Value & Temp;
    print("Fuse value: %b",Value);
    Run(WriteFuse);
    USB = Value;
    Temp = USB;
    //-------- High fuse    
    Value = 0b11011111;         // SPI always enabled
    if(WDTON = 0)  { Value = Value & 0b10111111; } 
    if(CKOPT = 0)  { Value = Value & 0b11101111; } 
    if(EESave = 0) { Value = Value & 0b11110111; }
    Temp = 3 - BootSize;
    Temp = Temp << 1;
    Temp = Temp | 0b11111001;
    Value = Value & Temp;
    if(ResetVector = 0) { Value = Value & 0b11111110; }    
    USB = Value;
    Temp = USB;
    print("\;Done.");
    ReadFuse();
    USB = SPIClock;
}

Proc ReadCalibration
{
    var Temp;

    Run(InitSPI);
    Temp = SPIClock*10;
    USB = Temp;
    Temp = USB;
    if(Temp != 0x53)
    {
        print("   Error. Device not response");
        return;
    }
    print("");
    print("   Read calibration byte... ");
    Run(ReadCalibration);
    Temp = USB;
    if(Temp = 0x8000)
    {
        print("   Error. Time out.");
    }
    else
    {
        print("\;Success.");
        print("   Calibration byte value: %b(HEX), %i(DEC)",Temp,Temp);
    } 
}

Proc ModuleInfo {

    print("");
    print("    ***********************************************");
    print("    Module for programming a chip ATMega8.");
    print("    Low-voltage programming via SPI interface");
    print("    ***********************************************");
    print("    Author: ETL (c) 2006");
}



[Device]

define      RESET       POUT.0
define      SCK         POUT.6
define      MISO_OUT    POUT.5
define      MISO        PIN.5
define      MOSI        POUT.4

define      FLASH_END       4096
define      EEPROM_END      512
define      FLASH_PAGE_SIZE 32      // words

define      PROG_ENABLE             0b1010110001010011
define      READ_DEVICE_CODE        0b0011000000000000
define      READ_PROGRAM_MEMORY     0b0010000000000000
define      WRITE_PROGRAM_MEMORY    0b0100110000000000
define      LOAD_PROGRAM_MEMORY     0b0100000000000000
define      READ_EEPROM_MEMORY      0b1010000000000000
define      WRITE_EEPROM_MEMORY     0b1100000000000000
define      CHIP_ERASE              0b1010110010000000
define      WRITE_LOCK_BITS         0b1010110011100110
define      READ_LOCK_BITS          0b0101100000000000
define      WRITE_FUSE              0b1010110010100000
define      WRITE_H_FUSE            0b1010110010101000
define      READ_FUSE               0b0101000000000000
define      READ_H_FUSE             0b0101100000001000
define      READ_CALIBRATION        0b0011100000000000

var Counter,Address,InstructionW,InstructionB,SPIWord,SPIByte,Byte,FlashEnd,Echo,
    InitCounter,VerifyDuringWrite,VerifyWord, ReadedWord;

Proc ReadSignature
{
    SCK = 0;
    InstructionW = READ_DEVICE_CODE;
    InstructionB = 0x00FF;
    InstructionIn;
    USB = SPIWord;
    InstructionB = InstructionB + 0x0100;
    InstructionIn;
    USB = SPIWord;
    InstructionB = InstructionB + 0x0100;
    InstructionIn;
    USB = SPIWord;
}

Proc ReadFlash
{
    //InitSPI;
    Address = 0;
    while(Address != FLASH_END)
    {
        InstructionW = Address >> 8;
        InstructionW = InstructionW | READ_PROGRAM_MEMORY;
        InstructionB = Address << 8;
        InstructionIn;
        USB = SPIWord;
        InstructionW.11 = 1;
        InstructionIn;
        USB = SPIWord;
        Address++;
    }
}

Proc WriteFlash
{
    VerifyDuringWrite = USB;
    while
    {
        Byte = USB;
        if(Byte = 0) { break;}

        // ----- Load page into buffer

        InstructionW = LOAD_PROGRAM_MEMORY;
        Counter = 0;
        while(Counter != FLASH_PAGE_SIZE)
        {
            InstructionW.11 = 0;    
            InstructionB = USB;             // low byte of word
            Byte = Counter << 8;
            InstructionB = InstructionB | Byte;
            InstructionOut;
            InstructionW.11 = 1;    
            InstructionB = USB;             // high byte of word
            InstructionB = InstructionB | Byte;
            InstructionOut;
            Counter++;
        }
        // -----  get page address and program
        
        InstructionW = USB;          // high byte
        Address = InstructionW << 8;
        InstructionW = InstructionW | WRITE_PROGRAM_MEMORY;
        Byte = USB;                 // low byte
        Address = Address | Byte;
        InstructionB = Byte << 8;
        InstructionOut;

        // ------- wait until ready
        
        Delay(6000);
        USB = 0;

        if(VerifyDuringWrite != 0)
        {
            // verify writed page
            // read back and send to host
            Counter = FLASH_PAGE_SIZE;
            while(Counter != 0)
            {
                
                InstructionW = Address >> 8;
                InstructionW = InstructionW | READ_PROGRAM_MEMORY;
                InstructionB = Address << 8;
                InstructionIn;
                USB = SPIWord;
                InstructionW.11 = 1;
                InstructionIn;
                USB = SPIWord;
                Counter--;
                Address++;
            }
        }
    }
}


Proc ReadEEPROM
{
    Address = 0;
    InstructionW = READ_EEPROM_MEMORY;
    while(Address != EEPROM_END)
    {
        InstructionW.0 = Address.8;
        InstructionB = Address << 8;
        InstructionIn;
        USB = SPIWord;
        Address++;
    }
}

Proc WriteEEPROM
{
    Address = 0;
    while(Address != EEPROM_END)
    {
        InstructionW = WRITE_EEPROM_MEMORY;
        InstructionW.0 = Address.8;
        InstructionB = Address << 8;
        Byte = USB;
        InstructionB = InstructionB | Byte;
        InstructionOut;
        Delay(10000);
        
        //--------  read back for control

        InstructionW = READ_EEPROM_MEMORY;
        InstructionW.0 = Address.8;
        //InstructionB = Address << 8;
        InstructionIn;
        USB = SPIWord;
        if(Byte != SPIWord) { break;}
        Address++;
    }
}

Proc ChipErase
{
    InstructionW = CHIP_ERASE;
    InstructionB = 0xFFFF;
    InstructionOut;
    Delay(20000);
    USB = 0;
}

Proc ReadLock
{
    InstructionW = READ_LOCK_BITS;
    InstructionIn;
    USB = SPIWord;
}


Proc ReadFuse
{
    InstructionW = READ_FUSE;
    InstructionIn;
    USB = SPIWord;
    InstructionW = READ_H_FUSE;
    InstructionIn;
    USB = SPIWord;
}

Proc WriteFuse
{   
    InstructionW = WRITE_FUSE;
    InstructionB = USB;
    InstructionOut;
    Delay(21000);
    USB = 0;
    InstructionW = WRITE_H_FUSE;
    InstructionB = USB;
    InstructionOut;
    Delay(21000);
    USB = 0;
}

Proc WriteLock
{
    Byte = USB;
    InstructionW = WRITE_LOCK_BITS;
    InstructionB = Byte;
    InstructionOut;
    Delay(20000);
    USB = 0;
}

Proc ReadCalibration
{
    InstructionW = READ_CALIBRATION;
    InstructionB = 0;
    InstructionIn;
    USB = SPIWord;    
}

Proc SendWordToSPI
{
    SPIByte = SPIWord >> 8;
    BUSDATA = SPIByte;
    BUSDATA = SPIWord;
}

Proc InitSPI
{
    POUT = 0b00100000;
    RESET = 1;
    Delay(50000);
    RESET = 1;RESET = 0;
    Delay(50000);
    BusInit(6,5,4,1,1,0);
    Echo = USB;             // ----- set SPI speed
    BUSDELAY = Echo;
    InitCounter = 33;
    while
    {
        SPIWord = PROG_ENABLE;SendWordToSPI;

        // check echo
        Echo = BUSDATA;
        SCK = 0;
        BUSDATA = 0xFF;
        if(Echo = 0x53) { break; }
        SCK = 0;SCK = 1; SCK = 0;
        InitCounter--;
        if(InitCounter = 0) { break; }

        InitCounter--;
        if(InitCounter = 0) { break; }
    }
    SCK = 0;
    USB = Echo;
}

Proc InstructionIn
{
    SPIWord = InstructionW;
    SendWordToSPI;
    SPIWord = InstructionB >> 8;
    BUSDATA = SPIWord;
    SPIWord = BUSDATA;
    SCK = 0;
}

Proc InstructionOUT
{
    SPIWord = InstructionW;    
    SendWordToSPI;
    SPIWord = InstructionB;
    SendWordToSPI;
}

