/*
** SEE24 
** 24LCXX I2C serial EEPROM access demo
**
** 03/06/08 v1.00 LDJ 
** 
*/

#include <p24fj128ga010.h>
_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & ICS_PGx2 & FWDTEN_OFF)
_CONFIG2( FNOSC_PRIPLL & FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS)
#define FCY    16000000L

#include <i2c.h>
#include "see.h"

#define READ_CMD    1
#define WRITE_CMD   0
#define BUS_FRQ     100000L // 100kHz

void initSEE( long fcy)
// fcy = processor operating frequency in Hz (system clock)
{  // Configure I2C for 7 bit address mode 100kHz

    OpenI2C1(I2C_ON & I2C_IDLE_CON & I2C_7BIT_ADD & I2C_STR_EN
            & I2C_GCALL_DIS & I2C_SM_DIS & I2C_IPMI_DIS, 
        (fcy /(2*BUS_FRQ))-1);

    IdleI2C1();
    T1CON=0x8030;   
    TMR1=0;
    while( TMR1< 100);
    
} //initSEE 
 
 
int addressSEE( int add)
// send the address selection command
// repeat if SEE busy 
{
    int cmd;
    
    // 1. Form SEE command + address msb (3)
    cmd= 0xA0|((add>>7)&0xE);   
    
    // 2. WRITE(!) the Address msb
    // try send command and repeat until ACK is received
    while( 1)
    { 
        StartI2C1(); 
        IdleI2C1();
        
        // send command and address msb(3)
        MasterWriteI2C1( cmd+WRITE_CMD); 
        IdleI2C1();
        
        if (I2C1STATbits.ACKSTAT==0)
            break;
            
        StopI2C1();
        IdleI2C1();
    } // while waiting for ACK

    // 3. send address lsb
    MasterWriteI2C1( add); 
    IdleI2C1();

    // 4. exit returning the cmd byte
    return cmd;
} // addressSEE
    
    
int readSEE( int add)
// random access read command sequence
{
    int cmd, r; 
   
    // 1. select address
    cmd = addressSEE( add);
    
    StopI2C1();
    IdleI2C1();
      
    // 2. read command
    StartI2C1(); IdleI2C1();
    MasterWriteI2C1( cmd+READ_CMD);
    IdleI2C1();

    // 3. stream data in (will continue until NACK is sent)
    r= MasterReadI2C1( );
    
    AckI2C1(); IdleI2C1();      
    r|= (MasterReadI2C1()<<8);

    // 4. terminate read sequence (send NACK then STOP)
    NotAckI2C1(); IdleI2C1();
    StopI2C1(); IdleI2C1();
    
    return r;
} //readSEE  


void writeSEE( int add, int v)
// SEE write command sequence
{
    int cmd; 
    
    // 1. select address
    cmd = addressSEE( add);
         
    // 2. stream data out 
    MasterWriteI2C1( v&0xFF);  
    IdleI2C1();  

    MasterWriteI2C1( v>>8);
    IdleI2C1();  

    // 3. terminate the command sequence
    StopI2C1(); 
    IdleI2C1();
    
} //writeSEE   
  

int i, r;
  
main (void )
{
    
    initSEE( FCY); 
    
    for( i=0; i<1024; i++)
    {
        writeSEE( i<<1, i);
        r = readSEE( i<<1);
        if (r!=i) 
           break;
    }    

    // main loop
    while( 1)
    {
        asm( "nop");
        asm( "nop");
        asm( "nop");
    }    
}
