[Description]
Location = "Atmel\EEPROM\MW EEPROM\93C46 (rotated)",
           "Microchip\EEPROM\MW EEPROM\93C46 (rotated)";
Info = " Module for programming 3-Wire Serial EEPROMs memory types: 93C46.",
       " ---------------------------------------------------------- ",
       "    Bus: MicroWire.",
       "    Size: 128 byte (64 words).",
       " ---------------------------------------------------------- ",
       "    Author: ETL (C) 2006";

Buffer1 = "EEPROM",128;
Picture = "93CXXrotated.bmp";
VCC = 2;
GND = 7;
View1 = 16;

Voltage = 5.0;

[Menu]

Read        = "&Read",ReadButton,"Read chip",F2;
div10       = "-";
Write       = "&Write",WriteButton,"Write chip",F5;
WriteChanges= "Write &changes",WriteChangesButton,"Write changes",F6;
Div1        = "-";
Erase       = "&Erase",EraseButton,"Erase chip",F9;
Compare     = "&Verify",CheckButton,"Compare with buffer",F3;
Divisor     = "-";
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);
    if(WordMode1 = 0)
    {
        print("\; 8-bit mode...");
        print("");
        USB = 0;
    }
    else
    {
        USB = 1;
        print("\; 16-bit mode...");
        print("");
    }
    Address = 0;PBPos = 0;PBMax = END_ADR;
    while(Address != END_ADR)
    {
        Error = USB;
        if(Error = 0)
        {
            Value = USB;FBUF[Address] = Value;Address++;
            if(WordMode1 = 1)
            {
                Value = USB;FBUF[Address] = Value;Address++;
                PBPos++;
            }
            PBPos++;
        }
        else { break; }        
    }
    if(WordMode1 = 1) { Address = Address / 2; }
    if(Error = 0x8000)
    {
        print("  Reading error: Time out");
    }
    if(Error = 0)
    {
        if(ForceCloseAfterRead != 0) { return(0x7FFFFFFF); }
        print("  Reading is done. %i words were read.",Address);
    }
    if(Error = 0xff)
    {
        print("  Reading error. Chip not response. Address %i",Address);
    }
}


Proc Write  {

    var Address,Error,Value;
    print("");
    print("  Writing chip...");
    Run(Write);
    if(WordMode1 = 0)
    {
        print("\; 8-bit mode...");
        print("");
        USB = 0;
    }
    else
    {
        USB = 1;
        print("\; 16-bit mode...");
        print("");
    }

    Address = 0;PBPos = 0;PBMax = END_ADR;
    while(Address != END_ADR)
    {
        Value = FBUF[Address];USB = Value;Address++;
        if(WordMode1 = 1)
        {
            Value = FBUF[Address];USB = Value;Address++;
            PBPos++;
        }
        Error = USB;
        if(Error != 0) { break; }
        PBPos++;
    }
    if(WordMode1 = 1) { Address = Address / 2; }
    if(Error = 0x8000)
    {
        print("  Writing error: Time out");
    }
    if(Error = 0xFF)
    {
        print("  Wrintig error. Chip not response. Address %i", Address);
    }
    if(Error = 0)
    {
        if(GlobalVerify != 0) { Compare(); }
        if(ForcecloseAfterWrite != 0) { return(0x7FFFFFFF); }
        print("   Writing is done. %i cells were write.",Address);
    }
}

Proc Compare {

    var Address,Error,Value,Value2,Mismatch;
    print("");
    print("  Verifying chip...");
    Run(Read);
    if(WordMode1 = 0)
    {
        print("\; 8-bit mode...");
        print("");
        USB = 0;
    }
    else
    {
        USB = 1;
        print("\; 16-bit mode...");
        print("");
    }
    Address = 0;PBPos = 0;PBMax = END_ADR;
    Mismatch = 0;
    while(Address != END_ADR)
    {
        Error = USB;
        if(Error = 0)
        {
            // byte mode
            Value = USB;
            Value2 = FBUF[Address];
            if(Value != Value2) { Mismatch++; FSEL[Address] = 0; }
            else                { FSEL[Address] = 1; }
            Address++;
            PBPos++;
            if(WordMode1 = 1)
            {
                Value = USB;
                Value2 = FBUF[Address];
                if(Value != Value2) { Mismatch++; FSEL[Address] = 0; }
                else                { FSEL[Address] = 1; }
                Address++;
                PBPos++;
            }
        }
        else { break; }
    }
    
    if(WordMode1 = 1)   { Address = Address / 2;}

    if(Error = 0x8000)
    {
        print("  Verifying error: Time out");
    }
    if(Error = 0)
    {
        if(ForceCloseAfterVerify != 0) { return(0x7FFFFFFF); }
        if(WordMode1 = 1)
        {
            Value = Mismatch & 1;
            if(Value = 1) { Mismatch++;}
            Mismatch = Mismatch / 2;
            print("  Verifying is done. %i words were read. Number of mismatch: %i",Address,Mismatch);
        }
        else
        {
            print("  Verifying is done. %i bytes were read. Number of mismatch: %i",Address,Mismatch);
        }
    }
    if(Error = 0xFF)
    {
        print("  Verifying error. Chip not response. Address %i", Address);
    }
}

Proc Erase
{
    var Address,Error;
    print("");
    print("  Erasing chip...");
    Run(Erase);
    Error = USB;
    if(Error = 0)
    {
        if(ForcecloseAfterWrite != 0) { return(0x7FFFFFFF); }
        print("  Erasing is done",Address);
    }
    if(Error = 0x8000)
    {
        print("  Erasing error: Time out");
    }
}

Proc WriteChanges
{
    var Address,Temp,Value,Error,Mismatch,Writed;
    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;
        Writed = 0;
        while(Address != END_ADR)
        {
            if(WordMode1 != 0)
            {
                    Mismatch = FSEL[Address];
                    Value = FBUF[Address];                    
                    Address++;
                    Temp = FSEL[Address];
                    Mismatch = Mismatch + Temp;
                    Temp = FBUF[Address];
                    if(Mismatch < 2)
                    {
                        Run(WriteWord);
                        Error = Address >> 1;
                        USB = Error;
                        USB = Value;
                        USB = Temp;
                        Error = USB;
                        if(Error != 0) { break;}
                        Writed++;
                    }
                    PBPos++;
            }
            else
            {
                Value = FSEL[Address];
                if(Value = 0)
                {
                    // write byte
                    //print("   Address: %i",Address);
                    Value = FBUF[Address];
                    Run(WriteByte);
                    USB = Address;
                    USB = Value;
                    Error = USB;
                    if(Error != 0) { break;}
                    Writed++;
                }
            }
            Address++;
            PBPos++;
        }
        if(WordMode1 = 1) { Address = Address >> 1; }
        if(Error = 0)
        {
            if(GlobalVerify != 0) { Compare(); }
            if(ForceCloseAfterWrite != 0) { return(0x7FFFFFFF); }
            print("   Writing is done. %i cells were write.",Writed);
        }
        if(Error = 255)
        {
            print("   Writing error. Address %i",Address);
        }
        if(Error = 0x8000)
        {
            print("   Writing error. Time out. Address %i",Address);
        }
    }
}

Proc Info
{
  print("");
  print("  Module for programming 3-Wire eeprom types 96C46.");
  print("  Note: rotated package.");
  print("");
  print("  Copyright (C) 2006 ETL.");
}

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

[Device]

define      CS          POUT.2
define      SK          POUT.3
define      DI          POUT.4
define      DO          POUT.5
define      DOIN        PIN.5
define      ORG         POUT.7

define      END_ADR     128    

define      READINS     0b0000000110000000
define      WRITEINS    0b0000000101000000
define      ERALINS     0b0000000100100000
define      EWENINS     0b0000000100110000                  


// Variables

var Address,Error,Temp,DataWord,Counter,DataL,DataH,Mode,WordAddress,
    ControlWord;

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

    POUT = 0b10110010;                  // init
                                        // CS=0, SK=0, DI=1, DO=1, ORG=1
    ControlWord = READINS;

    Mode = USB;

    if(Mode = 0) 
    { 
        ORG = 0;
        ControlWord = ControlWord << 1; 
    }

    while(Address != END_ADR)
    {
        CS = 1;                         // Select chip
        DataWord = ControlWord;
        ShiftOutWord;                   
        DO = 1;DI = 1;  
        if(DOIN != 0)
        {
            // chip not present
            // send to host error byte (0xFF) and break
            USB = 0xFF;break;
        }
        USB = 0x00;                    // send to host OK byte (0x00)
        if(Mode = 1)
        {
            ShiftInWord;                   // get data word from chip
            CS = 0;                        // release chip
            USB = DataWord;                // send to host low byte of data word
            DataWord = DataWord >> 8;
            USB = DataWord;                // send to host high byte of data word
            Address = Address + 2;                      // next address
        }
        else
        {
            ShiftInByte;                    // get data byte from chip
            CS = 0;                         // release chip
            USB = DataWord;                // send to host low byte of data word
            Address++;
        }
        ControlWord++;
    }
}

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

Proc Write
{
    Error = 0;Address = 0;

    POUT = 0b10110010;                  // init
                                        // CS=0, SK=0, DI=1, DO=1, ORG=1
    Mode = USB;

    DataWord = EWENINS;                 // Send to chip WRITE ENABLE command 
    if(Mode = 0) 
    { 
        ORG = 0;
        DataWord = DataWord << 1; 
    }

    CS = 1;
    ShiftOutWord;                 
    CS = 0;

    ControlWord = WRITEINS;
    if(Mode = 0) 
    { 
        ControlWord = ControlWord << 1; 
    }

    while(Address != END_ADR)
    {
        DataL = USB;
        if(Mode = 1) { DataH = USB; }
        CS = 1;
        DataWord = ControlWord;  
        ShiftOutWord;
        if(Mode = 0) 
        { 
            DataWord = DataL;
            ShiftOutByte;
        }
        else
        {                  
            DataWord = DataH << 8;          
            DataWord = DataWord | DataL;
            ShiftOutWord;                   
        }
        CS = 0;

        //   wait until chip ready
        DO = 1; DI = 1; // release bus
        CS = 1;
        while(DOIN = 0) {}
        CS = 0; 
        USB = 0;
        ControlWord++;
        Address++;
        if(Mode = 1) { Address++; }
    }
}


Proc ShiftOutWord
{
    Counter = 16;                   // bit counter
    while(Counter != 0)
    {
        DI = DataWord.15;           // msb on the input data pin
        SK = 1; SK = 0;             // rising edge SK
        DataWord = DataWord << 1;   // next bit
        Counter--;          
    }    
}

Proc ShiftOutByte
{
    Counter = 8;                    // bit counter
    while(Counter != 0)
    {
        DI = DataWord.7;            // msb on the input data pin
        SK = 1; SK = 0;             // rising edge SK
        DataWord = DataWord << 1;   // next bit
        Counter--;          
    }    
}

Proc ShiftInWord
{
    Counter = 16;                   // bit counter
    DataWord = 0;
    while(Counter != 0)
    {
        DataWord = DataWord << 1;   // next bit
        SK = 1;                             
        DataWord.0 = DOIN;       // next bit from bus into lowest bit DataWord
        SK = 0;
        Counter--;
    }
}

Proc ShiftInByte
{
    Counter = 8;                   // bit counter
    DataWord = 0;
    while(Counter != 0)
    {
        DataWord = DataWord << 1;   // next bit
        SK = 1;                             
        DataWord.0 = DOIN;       // next bit from bus into lowest bit DataWord
        SK = 0;
        Counter--;
    }
}

Proc Erase
{
    POUT = 0b10110010;                  // init
                                        // CS=0, SK=0, DI=1, DO=1, ORG=1
    CS = 1;
    DataWord = EWENINS;                 // Send to chip WRITE ENABLE command
    ShiftOutWord;
    CS = 0;

    CS = 1;
    DataWord = ERALINS;                 // Send to chip ERASE ALL command
    ShiftOutWord;
    CS = 0;

    //   wait until chip ready
    DO = 1; DI = 1; // release bus
    CS = 1;
    while(DOIN = 0) {}
    CS = 0;
    USB = 0;
}

Proc WriteWord
{
    POUT = 0b10110010;      // init: CS=0, SK=0, DI=1, DO=1, ORG=1

    CS = 1;
    DataWord = EWENINS;     // Send to chip WRITE ENABLE command
    ShiftOutWord;
    CS = 0;    

    DataWord = WRITEINS;
    Temp = USB;
    DataWord = DataWord | Temp;

    CS = 1;
    ShiftOutWord;
    DataWord = USB;
    DataL = USB;
    DataL = DataL << 8;
    DataWord = DataWord | DataL;
    ShiftOutWord;
    CS = 0;

    //   wait until chip ready
    DO = 1; DI = 1; // release bus
    CS = 1;
    while(DOIN = 0) {}
    CS = 0;
    USB = 0;
}

Proc WriteByte
{
    POUT = 0b00110010;          // init:  CS=0, SK=0, DI=1, DO=1, ORG=0

    CS = 1;
    DataWord = EWENINS << 1;    // Send to chip WRITE ENABLE command
    ShiftOutWord;
    CS = 0;    

    DataWord = WRITEINS << 1;
    Temp = USB;
    DataWord = DataWord | Temp;

    CS = 1;
    ShiftOutWord;
    DataWord = USB;
    ShiftOutByte;
    CS = 0;

    //   wait until chip ready
    DO = 1; DI = 1; // release bus
    CS = 1;
    while(DOIN = 0) {}
    CS = 0;
    USB = 0;
}
