// ---------------------------- Szitkovits Gábor ---------- 2012.06.01 -----------------------------
// ------------ MSP430g2xx1-g2xx2 USI I2C kommunikáció ---------------------------------------------
/* Megjegyzés: 
               - "i2c init" : USI periféria beállítása i2c master módra
               - "i2c start" : i2c kommunikáció indítása
               - "i2c stop" : i2c kommunikáció leállítása
               - "i2c slave cím" : Slave eszköz címe. A program balra igazítja !!! 
                                   A program balra igazítja !!! Nem midegyik eszközhöz jó !!!
                                   Írásnál 0xXY,0 , ahol a "0" az R/W bit.
                                   Olvasásnál 0xXY,1 , ahol a "1" az R/W bit. 
               - "i2c write byte" : egy bájt küldése, slave eszköznek.
               - "i2c read byte" : egy bájt fogadása, slave eszközről.
               - "i2c ack" : NACK/ACK küldés. Ha "1", akkor ACK küldés, ha "0", akkor NACK.
*/
#include "io430.h"
#include "stdint.h"
#include "i2c_g2xx2.h"

// --------------------- i2c inicializálás ---------------------------------------------------------
void i2c_init(void){
    USICTL0 = USIPE7 + USIPE6 + USIMST + USIOE + USISWRST;
    // master mód, adat ki engedélyezés, P1.6 SCL P1.7 SDA engedélyezés, szoftveres reset
    USICKCTL = USIDIV_7 + USISSEL_2 + USICKPL;                // óra=SMCLK/64
    USICTL1 = USII2C;                                         // I2C mód
    USICTL0 &= ~USISWRST;                                     // reset USI engedélyezés
    USICTL1 &= ~(USIIFG + USISTTIFG);                         // flag törlése
}                                   // void
// --------------------- i2c indítása --------------------------------------------------------------
void i2c_start(void){
    USISRL = 0xFF;
    USICTL0 |= USIGE;
    USICTL0 &= ~(USIGE + USIOE);  
    __delay_cycles(100);
    USISRL = 0x00;
    USICTL0 |= USIGE + USIOE;
    USICTL0 &= ~USIGE;
}                                   // void
// --------------------- i2c start ismétlés --------------------------------------------------------
void i2c_start_ismetles(void){
    USICTL0 |= USIOE;
    USISRL = 0xFF;
    USICNT = 1;
    while((USICTL1 & USIIFG) != 0x01);
    __delay_cycles(100);
    USISRL = 0x00;
    USICTL0 |= USIGE+USIOE;
    USICTL0 &= ~USIGE;
}                                   // void
// --------------------- i2c leállítása ------------------------------------------------------------
void i2c_stop(void){
    USICTL0 |= USIOE;
    USISRL = 0x00;
    USICNT = 1;                             // 1 bit küldése
    while((USICTL1 & USIIFG) != 0x01);      // várunk míg USIIFG, egy nem lesz
    USISRL = 0xFF;
    USICTL0 |= USIGE;
    USICTL0 &= ~(USIGE + USIOE);
}                                   // void
// --------------------- i2c slave cím küldése -----------------------------------------------------
uint8_t i2c_slave_cim(uint8_t scim, char olvas){
    scim <<= 1;
    if(olvas){
        scim |= 0x01;
    }
    return(i2c_write_byte(scim));
}                                   // int
// --------------------- i2c 1 bájt küldése --------------------------------------------------------
uint8_t i2c_write_byte(uint8_t byte){
    USICTL0 |= USIOE;                       // küldés
    USISRL = byte;                          // küldendő bájt
    USICNT = 8;                             // 8 bit
    while((USICTL1 & USIIFG) != 0x01);      // várunk míg USIIFG, egy nem lesz
                      //  NACK/ACK ellenőrzés
    USICTL0 &= ~USIOE;
    USICNT = 1;
    while((USICTL1 & USIIFG) != 0x01);      // várunk míg USIIFG, egy nem lesz

    if(USISRL & 0x01){
	return 0;
    }
    return 1;
}                                   // int
// --------------------- i2c 1 bájt olvasása -------------------------------------------------------
uint8_t i2c_read_byte(void){
    USICTL0 &= ~USIOE;
    USICNT = 8;
    while((USICTL1 & USIIFG) != 0x01);      // várunk míg USIIFG, egy nem lesz
    return USISRL;
}                                   // int
// --------------------- NACK/ACK küldése ----------------------------------------------------------
void i2c_ack(char ack){                    // (N)ACK bit küldése
    USICTL0 |= USIOE;
    if(ack){
        USISRL = 0x00;
    }
    else{
        USISRL = 0xFF;
    }
    USICNT = 1;
    while((USICTL1 & USIIFG) != 0x01);      // várunk míg USIIFG, egy nem lesz
    USICTL0 &= ~USIOE;
}                                   // void