#include <stdint.h>
#include <twi_def.h>
#include <BitDef.h>

/*************************************************************************	
  Vysle START podminku a adresu slave zarizeni.
  return 0 = zarizeni dostupne, 1= zarizeni nedostupne
*************************************************************************/

unsigned char i2c_startni(unsigned char address)
{
    uint8_t   twst;

        // vysle START podminku
        TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

        // ceka dokud neni prenos ukoncen
        while(!(TWCR & (1<<TWINT)));

        // zkontroluje hodnotu TWI status registru.
        twst = TWSR & 0xF8;
        if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

        // vysle adresu zarizeni
        TWDR = address;
        TWCR = (1<<TWINT) | (1<<TWEN);

        // ceka dokud neni prenos ukoncen a ACK/NACK bit prijat
        while(!(TWCR & (1<<TWINT)));

        // zkontroluje hodnotu TWI status registru.
        twst = TWSR & 0xF8;
        if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;

        return 0;

}


/*************************************************************************
 Vysle START podminku a adresu slave zarizeni.
 Pokud je zarizeni zaneprazdneno, ceka na ACK dokud neni zarizeni pripraveno
  
 Vstup:   adresa zarizeni
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
    uint8_t   twst;


    while ( 1 )
    {
            // vysle START podminku
            TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    
            // ceka dokud neni prenos ukoncen
            while(!(TWCR & (1<<TWINT)));
    
            // zkontroluje hodnotu TWI status registru
            twst = TWSR & 0xF8;
            if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
    
            // vysle adresu zarizeni
            TWDR = address;
            TWCR = (1<<TWINT) | (1<<TWEN);
    
           // ceka dokud neni prenos ukoncen
            while(!(TWCR & (1<<TWINT)));
    
            // zkontroluje hodnotu TWI status registru
            twst = TWSR & 0xF8;
            if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
            {                
                /* zarizeni zaneprazdneno, vysle stop podminku k preruseni zapisovaci operace */
                TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
                
                // ceka dokud stop podminka je vykonana a sbernice uvolnena
                while(TWCR & (1<<TWSTO));
                
                continue;
            }
            //if( twst != TW_MT_SLA_ACK) return 1;
            break;
     }

}


/************************************************************************* 
 Vykona opakovany start a vysle adresu zarizeni
 Vstup:   adresa zarizeni
 
 Vraci:  0 zarizeni dostupne
         1 zarizeni nedostupne
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
    return i2c_startni( address );

}


/*************************************************************************
  Prerusi prenos dat a uvolni sbernici
*************************************************************************/
void i2c_stopni(void)
{
        /* vysle stop podminku */
        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
        
        // ceka dokud stop podminka neni vykonana a uvolni sbernici
        while(TWCR & (1<<TWSTO));

}


/*************************************************************************
  Vysle jeden byte do zarizeni
  
  Vstup:    byte k vyslani
  Vraci:   0 zapis uspesny 
           1 zapis selhal
*************************************************************************/
unsigned char i2c_zapis( unsigned char data )
{        
    uint8_t   twst;
    
        // vysle data do naadresovaneho zarizeni
        TWDR = data;
        TWCR = (1<<TWINT) | (1<<TWEN);

        // ceka dokud neni prenos ukoncen
        while(!(TWCR & (1<<TWINT)));

        // zkontrluje hodnotu TWI status registru
        twst = TWSR & 0xF8;
        if( twst != TW_MT_DATA_ACK) return 1;
        return 0;
                                        
}


/*************************************************************************
 Precte jeden byte ze zarizeni, zada o dalsi data 
 
 
*************************************************************************/
unsigned char i2c_readAck(void)
{
        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
        while(!(TWCR & (1<<TWINT)));    

    return TWDR;

}


/*************************************************************************
 Precte jeden byte ze zarizeni, ukonceno stop podminkou 
 
 Vraci:  byte precteny ze zarizeni
*************************************************************************/
unsigned char i2c_readNak(void)
{
        TWCR = (1<<TWINT) | (1<<TWEN);
        while(!(TWCR & (1<<TWINT)));
        
    return TWDR;

}
