[Description]
Location = "Atmel\EEPROM\I2C EEPROM\AT24C01","Xicor (X)\X24C01";
Info = " Module for programming 2-Wire Serial EEPROMs",
    " memory types: Atmel AT24C01, Xicor X2401",
    " ---------------------------------------------------------------------",
    " Bus: I2C.",
    " Size: 128 bytes",
    " ---------------------------------------------------------------------",
    " Supported modes: Read, write, verify.",
    " ---------------------------------------------------------------------",
    " Note: ATMEL 24C01 and Xicor 2401 are not compatible with", 
    " another general 24C01 chips.",
    " ",
    " Author: ETL (C) 2005";
Buffer1 = "EEPROM",128;
Picture = "At24c01.bmp";
VCC = 8;
GND = 4;
Voltage = 5.0;

[Menu]

Read    = "&Read",ReadButton,"Read chip",F2;
Div0    = "-";
Write   = "&Write",WriteButton,"Write chip",F5;
Div1    = "-";
Erase   = "&Erase",EraseButton,"Erase chip",F9;
Div2    = "-";
Compare = "&Verify",CheckButton,"Compare with buffer",F3;
Info    = "&About module",ModuleInfoButton,"Show module info",F1;

[Interface]


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

[Host]

define  END_ADR 128

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


Proc Write  {

    var Address,Error,Value;
    print("");
    print("  Writing chip...");
    Run(Write);
    Address = 0;PBPos = 0;PBMax = END_ADR;
    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");
    }
    if(Error = 0xFF)
    {
        print("  Wrintig error. Address %i", Address);
    }
    if(Error = 0)
    {
        if(GlobalVerify != 0) { Compare(); }
        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)
    {
        Error = USB;
        if(Error != 0) { break; }
        Value = USB;
        Value2 = FBUF[Address];
        if(Value != Value2)
        {
            Mismatch++;
            FSEL[Address] = 0;    
        }
        else
        {
            FSEL[Address] = 1;
        }
        Address++;
        PBPos++;
    }
    if(Error = 0x8000)
    {
        print("  Reading error: Time out");
    }
    if(Error = 0)
    {
        if(ForceCloseAfterVerify = 0)
        {
            print("  Verifying is done. %i bytes were read. Number of mismatch: %i",Address,Mismatch);
        }
        else { return(0x7FFFFFFF); }
    }
    if(Error = 0xFF)
    {
        print("  Verifying error. Chip not response. Address %i",Address);
    }
}

Proc Erase
{
    var Address,Error,Value;
    print("");
    print("  Erase chip...");
    Run(Write);
    Address = 0;PBPos = 0;PBMax = END_ADR;
    while(Address != END_ADR)
    {
        USB = 255;
        Error = USB;
        if(Error != 0) { break; }
        Address++;
        PBPos++;
    }
    if(Error = 0x8000)
    {
        print("  Erasing error: Time out");
    }
    if(Error = 0xFF)
    {
        print("  Erasing error. Address %i", Address);
    }
    if(Error = 0)
    {
        if(ForceCloseAfterWrite != 0) { return(0x7FFFFFFF); }
        else
        {
            print("  Erasing is done.");
        }
    }
}

Proc Info
{
  print("");
  print("  Module for programming 2-Wire(I2C) serial EEPROMs memory types AT24C01.");
  print("");
  print("  Note: ATMEL 24C01 is not compatible with another general 24C01 chips.");
  print("");
  print("  Copyright (C) 2006 ETL.");
}

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

[Device]

define      END_ADR     128    
define      SDAOUT      POUT.4
define      SDAIN       PIN.4
define      SCL         POUT.5

// Variables

var Address,Error,Temp,Byte,Counter,Data;

//***********************************************************
//*       Read                                             **
//***********************************************************
Proc Read {
 
    Error = 0;Address = 0;

    Init;

    // -----  Read loop  -------------
    while(Address != END_ADR)
    {
        StartI2C;                   // START condition
        Byte = Address << 1;        // compose adress byte
        Byte.0 = 1;                 // lowest byte is "1" - read operation
        ShiftByteToI2C;           // shift into chip
        CheckAck;                   // check acknowledge
        if(Error != 0)
        {
            // acknowledgement is not present
            // send error byte to host and break 
            USB = 0xFF;
            StopI2C;                    // STOP condition
            break;
        }
        ShiftByteFromI2C;           // get data byte from chip
        CheckAck;                   // check acknowledge
        StopI2C;                    // STOP condition
        USB = 0;                   // send to host OK byte
        USB = Byte;                // send to host data byte
        Address++;                  // next address
    }
}

Proc Write {

    Init;

    Address = 0;
    while(Address != END_ADR) 
    {
        
        // -------- Get command byte from host

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

        // -------- Get address of cell from host
        //Address = USB;

        // -------- Get data byte from host
        Data = USB;

        // -------- Write to chip
        StartI2C;

        // -----  Load adress
        // -----  Command byte 0xA0

        Byte = 0xa0;ShiftByteToI2C;CheckAck;
        if(Error != 0) { USB = 0xFF;return; }

        // ----- Address byte

        Byte = Address;ShiftByteToI2C;CheckAck;
        if(Error != 0) { USB = 0xFF;return; }

        // ----- Data byte

        Byte = DATA;ShiftByteToI2C;CheckAck;
        if(Error != 0) { USB = 0xFF;return; }

        StopI2C;

        // ----- Wait while device is not ready

        WaitReady;

        // ----- Send to host "OK" command

        USB = 0;
        Address++;
    }
}

Proc StartI2C {
    SDAOUT = 1; SCL = 1;
    SDAOUT = 0; SCL = 0;
} 

Proc StopI2C {
    SDAOUT = 0; SCL = 0;
    SCL = 1; SDAOUT = 1;
}

Proc ShiftByteToI2C
{
  Counter = 8;
  while(Counter != 0)
  {
    SDAOUT = Byte.7;SCL = 1;SCL = 0;
    Byte = Byte << 1;
    Counter--;
  }
  SDAOUT = 0;
}

Proc ShiftByteFromI2C
{
  Counter = 8;
  SDAOUT = 1;
  Byte = 0;
  while(Counter != 0)
  {
    Byte = Byte << 1;
    SCL = 1;
    Byte.0 = SDAIN;
    SCL = 0;
    Counter--;
  }
}

Proc CheckAck
{
    SDAOUT = 1;SCL = 1;
    Error.0 = SDAIN;
    SCL = 0;
    SDAOUT = 0;
}

Proc Init {
  POUT = 0;
  SDAOUT = 1;
  SCL = 1; 
  SDAOUT = 1;
  SCL = 1;
  SDAOUT = 1;
  SCL = 1;
}


Proc WaitReady {
    
  while {
    StartI2C; 
    Byte = 0xa0;
    ShiftByteToI2C;
    CheckAck;
    StopI2C;
    if(Error = 0) { break; }
  }
}
