[Description]
Location = "Atmel\AVR\ATTiny15L";
Info = " Module for programming AVR microcontrollers via SPI interface.",
    " Chip: ATTiny15L. Manufacturer: Atmel",
    " ------------------------------------------------------------------------",
    " Bus: SPI.",
    " FLASH size: 1024 bytes (512 words).",
    " EEPROM size: 64 bytes",
    "---------------------------------------------",
    " Author: ETL (c) 2004";
Buffer1 = "FLASH",1024;
Buffer2 = "EEPROM",64;
Picture = "ATTiny15.bmp";
VCC = 8;
GND = 4;
Voltage = 5.0;

[Menu]

ReadSignature = "Read signature bytes",ChipInfoButton,"Read signature bytes";
ReadFlash = "Read FLASH",ReadButton,"Read FLASH";
WriteFlash = "Write FLASH",WriteButton,"Write FLASH";
Compare = "Verify FLASH",CheckButton,"Verify FLASH";
Erase = "Erase FLASH and EEPROM",EraseButton,"Erase FLASH and EEPROM";
ReadEEPROM = "Read EEPROM",ReadEEPROMButton,"Read EEPROM";
WriteEEPROM = "Write EEPROM",WriteEEPROMButton,"Write EEPROM";
ModuleInfo = "About module",ModuleInfoButton,"About module";
WriteLock = "Write lock bits";
ReadLock = "Read lock bits";
ReadFuse = "Read Fuse bits";
WriteFuse = "Write Fuse bits";
ReadCalibrationByte = "ReadCalibrationByte";

[Interface window]

CheckBox(EraseBeforeWrite,"Erase before write",30,10,1);
CheckBox(VerifyDuringWrite,"Verify during write",30,30,1);

ComboBox(LockMode,"Lock mode",228,10,90,"Not lock","Lock bit 1 (LB1)",
         "Lock bit 2 (LB2)",0);
ComboBox(BrownOutDetecor,"Brown-out Detector",189,40,90,"Enabled","Disabled",1);
ComboBox(BrownOutVoltage,"Brown-out voltage",195,70,90,"4 V","2.7 V",0);
ComboBox(SPIEnabled,"SPI interface",220,100,90,"Enabled","Disabled",0);
ComboBox(PB5Function,"Reset function of pin PB5",160,130,90,"Enabled","Disabled",0);
ComboBox(CKSEL,"CKSEL",247,160,90,"00","01","10","11",0);

[Host]

define      FLASH_END   512
define      EEPROM_END  64
define      SIGN        0x9006

//***********************************************************************
//*             ReadSignature                                          **
//***********************************************************************
Proc ReadSignature
{
    var B1,B2,B3;
    print("");
    Run(ReadSignature);
    B1 = USB;
    B2 = USB;
    B3 = USB;
    print("   Next signature bytes were readed: %b %b %b",B1,B2,B3);
    print("");
    if(B1 = 0x1e)
    {
        print("    Manufacturer: Atmel");
    }     
    else
    {
        print("    Unknown manufacturer");
    }
    B2 = B2 << 8;
    B2 = B2 | B3;
    if(B2 = SIGN)
    {
        print("    Device: ATTiny15L");
    }
    else
    {
        print("    Device is not ATTiny15. Use AVR detector for identification.");        
    }
}

Proc ReadFlash
{
    var Address,Temp,FlashEnd;
    print("");
    print("   Reading FLASH...");
    Address = 0;
    Run(ReadFlash);
    FlashEnd = FLASH_END << 1;
    PBMax = FlashEnd;
    while(Address != FlashEnd)
    {
        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,Temp,FlashEnd;
    if(EraseBeforeWrite = 1)
    {
        print("");
        print("   Erasing chip...");
        Run(ChipErase);
        Temp = USB;
        if(Temp = 0x8000)
        {
            print("");
            print("   Erasing error. Time out.");
            return;
        }
    }
    print("");
    print("   Writing FLASH...");
    Address = 0;
    Run(WriteFlash);
    FlashEnd = FLASH_END << 1;
    PBMax = FlashEnd;
    while(Address != FlashEnd)
    {
        Temp = FBUF[Address];
        USB = Temp;
        Temp = USB;
        if(Temp = 0x8000) { break; }
        Address++;
        PBPos++;
        Temp = FBUF[Address];
        USB = Temp;
        Temp = USB;
        if(Temp = 0x8000) { break; }
        Address++;
        PBPos++;
    }
    if(Temp = 0x8000)
    {
        print("");
        print("   Writing error. Time out. Address: %i",Address);
    }
    else
    {
        Address = Address >> 1;
        print("");
        print("   Writing success. %i words were writed.",Address);
    }
}

Proc Compare
{
    var Address,Temp,FlashEnd,Byte,Mismatch;
    print("");
    print("   Verifying FLASH...");
    Address = 0;
    Run(ReadFlash);
    FlashEnd = FLASH_END << 1;
    PBMax = FlashEnd;
    Mismatch = 0;
    while(Address != FlashEnd)
    {
        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...");
    Address = 0;
    Run(ReadEEPROM);
    PBMax = EEPROM_END;
    while(Address != EEPROM_END)
    {
        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;
    print("");
    print("   Writing EEPROM...");
    Address = 0;
    Run(WriteEEPROM);
    PBMax = EEPROM_END;
    while(Address != EEPROM_END)
    {
        Temp = EBUF[Address];
        USB = Temp;
        Temp = USB;
        if(Temp = 0x8000) { break; }
        Address++;
        PBPos++;
    }
    print("");
    if(Temp = 0x8000)
    {
        print("   Writing error. Time out. Address %i.",Address);
    }
    else
    {
        print("   Writing is done. %i bytes were writed.",Address);
    }
}

Proc Erase
{
    var Temp;
    print("   Erasing...");
    Run(ChipErase);
    Temp = USB;
    if(Temp = 0x8000)
    {
        print("");
        print("   Erasing error. Time out.");    
    }
    else
    {
        print("");
        print("   Erasing success.");
    }
}

Proc ReadCalibrationByte
{
    var Temp;
    print("   Reading calibration byte...");
    Run(ReadCalibrationByte);
    Temp = USB;
    if(Temp = 0x8000)
    {
        print("");
        print("   Reading error. Time out."); 
    }
    else
    {
        print("");
        print("   Success. Value of calibration byte: %b (HEX), %i (DEC).",Temp,Temp);
    }
}

Proc ReadLock
{
    var Temp;
    print("   Reading lock bits...");
    Run(ReadLock);
    Temp = USB;
    if(Temp = 0x8000)
    {
        print("");
        print("   Reading error. Time out."); 
    }
    else
    {
        print("");
        print("   Lock bit 1 = ");
        if(Temp.1 = 0) { print("\;0 (programmed)"); }
        else { print("\;1 (unprogrammed)"); }
        print("   Lock bit 2 = ");
        if(Temp.2 = 0) { print("\;0 (programmed)"); }
        else { print("\;1 (unprogrammed)"); }
    }
}

Proc ReadFuse
{
    var Temp;
    print("   Reading FUSE bits...");
    Run(ReadFuse);
    Temp = USB;
    if(Temp = 0x8000)
    {
        print("");
        print("   Reading error. Time out."); 
    }
    else
    {
        print("");
        print("   Success. Next fuse bits were readed:");
        print("");
        print("   CLKSEL0   = ");
        if(Temp.0 = 0) { print("\;0 (programmed)"); }
        else { print("\;1 (unprogrammed)"); }
        print("   CLKSEL1   = ");
        if(Temp.1 = 0) { print("\;0 (programmed)"); }
        else { print("\;1 (unprogrammed)"); }
        print("   RSTDISBL = ");
        if(Temp.4 = 0) { print("\;0 (programmed). External reset function of pin PB5 is disabled. "); }
        else { print("\;1 (unprogrammed). External reset function of pin PB5 is enabled."); }
        print("   SPIEN        = ");
        if(Temp.5 = 0) { print("\;0 (programmed). SPI is enabled"); }
        else { print("\;1 (unprogrammed). SPI is disabled"); }
        print("   BODEN      = ");
        if(Temp.6 = 0) { print("\;0 (programmed). Brown-out Detector is enabled."); }
        else { print("\;1 (unprogrammed). Brown-out Detector is disabled."); }
        print("   BODLEVEL = ");
        if(Temp.7 = 0) { print("\;0 (programmed). Brown-out detection level is 4 V."); }
        else { print("\;1 (unprogrammed). Brown-out detection level is 2.7 V"); }
    }
}

Proc ModuleInfo {

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

[Device]

define      FLASH_END   512
define      EEPROM_END  64

define      PROG_ENABLE             0b1010110001010011
define      READ_DEVICE_CODE        0b0011000000000000
define      READ_PROGRAM_MEMORY     0b0010000000000000
define      WRITE_PROGRAM_MEMORY    0b0100000000000000
define      READ_EEPROM_MEMORY      0b1010000000000000
define      WRITE_EEPROM_MEMORY     0b1100000000000000
define      CHIP_ERASE              0b1010110010000000
define      WRITE_LOCK_BITS         0b1010110011111111
define      READ_LOCK_BITS          0b0101100000000000
define      READ_FUSE_BITS          0b0101000000000000
define      READ_CALIBRATION        0b0011100000000000
define      WRITE_FUSE_BITS         0b1010110010100000

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

define      DELAY_VALUE 30

var Counter,Address,SPIWord,InstructionW,InstructionB,Byte;

Proc ReadSignature
{
    InitSPI;
    InstructionW = READ_DEVICE_CODE;
    InstructionB = 0;
    InstructionIn;
    USB = SPIWord;
    InstructionB++;
    InstructionIn;
    USB = SPIWord;
    InstructionB++;
    InstructionIn;
    USB = SPIWord;
}


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

Proc WriteFlash
{
    InitSPI;
    Address = 0;
    while(Address != FLASH_END)
    {
        InstructionW = WRITE_PROGRAM_MEMORY;
        InstructionW.0 = Address.8;
        InstructionB = Address << 8;
        Byte = USB;
        InstructionB = InstructionB | Byte;
        InstructionOut;
        Delay(10000);
        USB = 0;
        InstructionW.11 = 1;
        Byte = USB;
        InstructionB = InstructionB & 0xFF00;
        InstructionB = InstructionB | Byte;
        InstructionOut;
        Delay(10000);
        USB = 0;
        Address++;
    }
}

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

Proc WriteEEPROM
{
    InitSPI;
    Address = 0;
    while(Address != EEPROM_END)
    {
        InstructionW = WRITE_EEPROM_MEMORY;
        InstructionB = Address << 8;
        Byte = USB;
        InstructionB = InstructionB | Byte;
        InstructionOut;
        Delay(10000);
        USB = 0;
        Address++;
    }
}

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

Proc ReadLock
{
    InitSPI;
    InstructionW = READ_LOCK_BITS;
    InstructionB = 0;
    InstructionIn;
    USB = SPIWord;    
}

Proc ReadFuse
{
    InitSPI;
    InstructionW = READ_FUSE_BITS;
    InstructionB = 0;
    InstructionIn;
    USB = SPIWord;    
}

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


Proc SendWordToSPI
{
    Counter = 16;
    while(Counter != 0)
    {
        MOSI = SPIWord.15;
        Delay(DELAY_VALUE);
        SCK = 0; 
        Delay(DELAY_VALUE);
        SCK = 1;
        Delay(DELAY_VALUE);
        SPIWord = SPIWord << 1;
        Counter--;    
    }
    SCK = 0;
}

Proc SendByteToSPI
{
    Counter = 8;
    while(Counter != 0)
    {
        MOSI = SPIWord.7;
        Delay(DELAY_VALUE);
        SCK = 0; 
        Delay(100);
        SCK = 1;
        Delay(DELAY_VALUE);
        SPIWord = SPIWord << 1;
        Counter--;    
    }
    SCK = 0;
}

Proc GetByteFromSPI
{
    Counter = 8;
    MISOOUT = 1;
        Delay(100);
    while(Counter != 0)
    {
        SPIWord = SPIWord << 1;
        SCK = 0;
        Delay(DELAY_VALUE);
        SPIWord.0 = MISO;
        SCK = 1;
        Delay(DELAY_VALUE);
        Counter--;    
    }
}

Proc InitSPI
{
    POUT = 0b10100110;
    Delay(50000);
    RESET = 1;RESET = 0;
    Delay(20000);
    SPIWord = PROG_ENABLE;
    SendWordToSPI;
    SPIWord = 0xFFFF;
    SendWordToSPI;
}

Proc InstructionIn
{
    SPIWord = InstructionW;
    SendWordToSPI;
    SPIWord = InstructionB;
    SendByteToSPI;
    GetByteFromSPI;
}

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

