/*
 * AVR_RTC_Test.c
 *
 */

 /* 
 * Geany Erstellen-Einstellungen für STK500 mit ATmega32
 
 * Compil.:  avr-gcc -mmcu=atmega32 -Os %f
 
 * Build  :  avr-objcopy -j .text -j .data -O ihex a.out
 
 * Flash  :  avrdude -c stk500 -P /dev/ttyS0 -p m32   -U flash:w:a.out
 
 * Exec-AVRDude : avrdude -c stk500 -P /dev/ttyS0 -p m32   -U flash:w:a.out
*/

/*====================================================================*/
/*                                                                    */
/*     MCU: ATMEGA32  auf STK500 Developerboard v. ATMEL              */
/*     FOsz. = 3,6864 MHz mit DS1307 an PC0/PC1 CLK/SDA               */
/*     PULL-Up R's = 4k7                                              */
/*====================================================================*/

#ifndef F_CPU
#define F_CPU 3686400UL // STK500-Norm
//#define F_CPU 8000000UL // STK500 ext. Quarz wegen I2C Clk
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <compat/twi.h>
#include <stdlib.h>
/* ================================================================== */
/*                                                                    */
/*              DS1307 Adresse:                                       */
/*              7-Bit format: 0b1101000  = 0x68                       */
/*              I2C Write:    0b11010000 = 0xD0                       */
/*              I2C Read:     0b11010001 = 0xD1                       */                                                        
/*                                                                    */
/* ================================================================== */
#define RTC_WR_ADDR             0xD0
#define RTC_RD_ADDR             0xD1
/* ================================================================== */
/*                                                                    */
/*                 Register-Adressen                                  */
/*                                                                    */
/*                                                                    */
/* ================================================================== */
#define RTC_REG_SEC             0x00
#define RTC_REG_MIN             0x01
#define RTC_REG_STD             0x02
#define RTC_REG_WTAG            0x03
#define RTC_REG_MTAG            0x04
#define RTC_REG_MON             0x05
#define RTC_REG_JAHR            0x06
#define RTC_REG_CONTR           0x07


chardays[7]= {"Son","Mon","Die","Mit","Don","Frei","Sam"};
uint8_t second,minute,hour,day,date,month;        // RTC Lesen
uint8_t s_sec,s_min,s_hour,s_day,s_date,s_month;  // RTC Setzen
unsigned int s_yearyear;                        // RTC Setzen/Lesen

/*====================================================================*/
/*                                                                    */
/*         TWI Prototypen der Funktionen/Routinen                     */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void MCU_Init(void);
void TWI_Init(void);
void TWI_Start(void);
void TWI_R_Start(void);
void TWI_Stop(void);
void TWI_Write_Adr(uint8_t Addr);  // Writeadresse senden
void TWI_Write_Data(unsigned char data); //Datenbyte schreiben
void TWI_Read_Adr(uint8_t Addr);   // ReadAdresse senden
uint8_t TWI_Read_Databyte_Nack(void);    // Datenbyte lesen
uint8_t TWI_Read_Databyte_Ack(void);
void RTC_Start(void);
void READ_Time(void);
void SET_Time(void);
void READ_Date(void);
void SET_Date(void);

uint8_t Decimal_To_BCD (uint8_t decimalByte);
uint8_t BCD_To_Decimal (uint8_t bcdByte);


//**********************************************************************
//
//      URAT Implementieren
//
//**********************************************************************

#ifndef BAUD
#define BAUD 9600UL  //UL wichtig !!!!!!!!!!!!!!!!!!!!!!!
#endif

#define UBRR_VALUE (((F_CPU/(16*BAUD))-1))
#ifndef UCHR
#define UCHR unsigned char
#endif


/* ================================================================== */
/*                                                                    */
/*         UART  Prototypen der Funktionen/Routinen                   */
/*                                                                    */
/* ================================================================== */
    
void UART_Init(void);
uint8_t UART_Read();
void UART_Read_Text(UCHR *Outputunsigned int length);
void UART_Write(UCHR data);
void UART_Write_Text(UCHR *text);
void UART_Write_Text_NL(UCHR *text);
void UART_Write_NL();
void UART_Write_Int(int zahl);
void UART_Write_Int_NL(int zahl);
void TIME_To_Serial();

/*====================================================================*/
/*                                                                    */
/*             Mainroutine                                            */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
int main(void)
{
    UART_Init();
    TWI_Init();
    while(1)
    {
    TIME_To_Serial();   
    _delay_ms(2000);
    }
    return 0;
}

/*====================================================================*/ 
/*                                                                    */                                                            
/*             MCU-Init                                               */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void MCU_Init(void)
{
    // fuer besondere Einstellungen
}

/*====================================================================*/
/*                                                                    */
/*             TWI Init                                               */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void TWI_Init(void)
{
    TWBR0x0A // ~100kHz bei 3,686400 MHz F_CPU  
    //TWBR=0x20; // Bit rate ~100kHz 8,0 MHhz F_CPU
    TWSR=(0<<TWPS1)|(0<<TWPS0);
    
}
/*====================================================================*/
/*                                                                    */
/*             TWI Start                                              */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void TWI_Start(void)
{
    TWCR = (1<< TWINT) | (1<< TWSTA) | (1<< TWEN);
    while(!(TWCR &  (1<< TWINT))); 
    while ((TWSR 0xF8) != TW_START );
    
}

/*====================================================================*/
/*                                                                    */
/*             TWI Repeatet Start                                     */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void TWI_R_Start(void)
    {
        TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
        while(!(TWCR & (1<<TWINT)));
        while((TWSR 0xF8) != TW_REP_START);
    }
 


/*====================================================================*/
/*                                                                    */
/*                TWI Stop                                            */
/*                                                                    */
/*                                                                    */
/*====================================================================*/

void TWI_Stop(void)
    {

    TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); 
    while(!(TWCR & (1<<TWSTO))); 
    }

/*====================================================================*/
/*                                                                    */
/*             Sende Adresse zum Schreiben m ACK                      */
/*             TW_MT_SLA_ACK                                          */
/*                                                                    */
/*====================================================================*/
void TWI_Write_Adr(uint8_t Addr)
    {
        TWDR=Addr;
        TWCR=(1<<TWINT)|(1<<TWEN);    
        while (!(TWCR & (1<<TWINT))); 
        while ((TWSR 0xF8)!= TW_MT_SLA_ACK); // Check ACK
    
    }

/*====================================================================*/
/*                                                                    */
/*             Sende Daten m ACK                                      */
/*             TW_MT_DATA_ACK                                         */
/*                                                                    */
/*====================================================================*/
 
void TWI_Write_Data(unsigned char data)
    {
        TWDR=data;
        TWCR=(1<<TWINT)|(1<<TWEN);
        while (!(TWCR & (1<<TWINT)));
        while((TWSR 0xF8) != TW_MT_DATA_ACK); // Check ACK
    }

/*====================================================================*/
/*                                                                    */
/*             Sende Adresse zum Lesen m ACK                          */
/*             TW_MR_SLA_ACK                                          */
/*                                                                    */
/*====================================================================*/

void TWI_Read_Adr(uint8_t Addr)
    {
        TWDR=Addr;
        TWCR= (1<<TWINT)|(1<<TWEN);
        while (!(TWCR & (1<<TWINT)));
        while ((TWSR 0xF8) != TW_MR_SLA_ACK); // Check ACK
    }
/*====================================================================*/
/*                                                                    */
/*              Empfange Daten  m NACK                                */
/*              TW_MR_DATA_NACK                                       */
/*                                                                    */
/*====================================================================*/

uint8_t TWI_Read_Databyte_Nack(void)
    {
        TWCR=(1<<TWINT)|(1<<TWEN);
        while (!(TWCR & (1<<TWINT)));
        while((TWSR 0xF8) != TW_MR_DATA_NACK); // Check NACK
        return TWDR;
    }


/*====================================================================*/
/*                                                                    */
/*              Empfange Daten  m ACK                                 */
/*              TW_MR_DATA_ACK                                        */
/*                                                                    */
/*====================================================================*/

uint8_t TWI_Read_Databyte_Ack(void)
    {
        TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWEA);
        while (!(TWCR & (1<<TWINT)));
        while((TWSR 0xF8) != TW_MR_DATA_ACK); // Check ACK  Fehler ??
        return TWDR;
    }   

/*====================================================================*/
/*                                                                    */
/*               Lese Zeit                                            */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void READ_Time(void)
{   uint8_t contr;
    TWI_Start();    
    UART_Write_Text_NL("TWI Start OK");
    TWI_Write_Adr(0xD0);    /* Sende Chip Adresse*/
    TWI_Write_Data(0x00);   /* erstes Zeitregister*/
    TWI_R_Start();          /* Repeated start */
    TWI_Read_Adr(0xD1);    /* Read Adresse schreiben*/
    
    UART_Write_Text_NL("TWI Repeat-Start OK");
    
                        // Register nacheinander abfragen
    second TWI_Read_Databyte_Ack();   /* Lese second */
    minute TWI_Read_Databyte_Ack();   /* Lese minute */
    hour   TWI_Read_Databyte_Ack();   /* Lese hour */
    // Zum Test auch Datum lesen
    day    TWI_Read_Databyte_Ack();   /* Lese day */ 
    date   TWI_Read_Databyte_Ack();   /* Lese date */
    month  TWI_Read_Databyte_Ack();   /* Lese month */
    year   TWI_Read_Databyte_Ack();  /* Lese year  */
    contr  TWI_Read_Databyte_Nack();
    /* ============================================================== */
    UART_Write_Text_NL("Zeit decodieren");
    /* ============================================================== */
    second =  BCD_To_Decimal(second);
    minute =  BCD_To_Decimal(minute);
    hour   =  BCD_To_Decimal(hour);


    day    =  BCD_To_Decimal(day);
    date   =  BCD_To_Decimal(date);
    month  =  BCD_To_Decimal(month);
    year   =  BCD_To_Decimal(year);
    /* ============================================================== */
    UART_Write_Text_NL("Zeit Register abgefragt");
    /* ============================================================== */
    
    TWI_Stop();     
}
/*====================================================================*/
/*                                                                    */
/*           Datum lesen                                              */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void READ_Date(void)
{
    /* ============================================================== */
        UART_Write_Text_NL("Bin in READ Datum");
    /* ============================================================== */
    TWI_Start();
    TWI_Write_Adr(0xD0);    /*Sende ChipAdresse*/
    TWI_Write_Data(0x03);   /* erstes Datumsregister */
    TWI_R_Start();          /* Repeated start */
    TWI_Read_Adr(0x0D1);    // Read Adresse schreiben
            // 4 Register nacheinander abfragen
    /* ============================================================== */
        UART_Write_Text_NL("Frage Datum Register ab");
    /* ============================================================== */
    day   TWI_Read_Databyte_Ack();    /* Lese day */ 
    date  TWI_Read_Databyte_Ack();    /* Lese date */
    month TWI_Read_Databyte_Ack();    /* Lese month */
    year  TWI_Read_Databyte_Nack();   /* Lese year & Nack */
    /* ============================================================== */
    UART_Write_Text_NL("Datum Register abgefragt");
    /* ============================================================== */
    TWI_Stop(); 
}

/*====================================================================*/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void TIME_To_Serial(void)
{
    READ_Time();
    UART_Write_NL();
    UART_Write_Text("Zeit : ");
    UART_Write_Int(hour);
    UART_Write_Text(" : ");
    UART_Write_Int(minute);
    UART_Write_Text(" : ");
    UART_Write_Int_NL(second);
    UART_Write_NL();
    UART_Write_Text_NL("==========================="); // wegen Uebersicht
    UART_Write_NL();
    UART_Write_Text("Datum : ");
    UART_Write_Text(days[day]);
    UART_Write_Text(" : ");
    UART_Write_Int(date);
    UART_Write_Text(" : ");
    UART_Write_Int(month);
    UART_Write_Text(" : ");
    UART_Write_Int_NL(year);
    UART_Write_NL();
    _delay_ms(500);
    //READ_Date();
    
}

/*====================================================================*/
/*                                                                    */
/*             Uart der MCU initalisieren                             */
/*                                                                    */
/*                                                                    */
/*====================================================================*/

void UART_Init(void)
    
        UBRRL UBRR_VALUE;         //set baud rate
        UBRRH UBRR_VALUE >> 8;
        UCSRA 0;                 
        UCSRC 1<<URSEL^1<<UCSZ1^1<<UCSZ0//8 Bit
        UCSRB 1<<RXEN^1<<TXEN;        //enable RX, TX
    }

/*====================================================================*/
/*                                                                    */
/*             Sende ein einzelnes Zeichen(Char)                      */
/*                                                                    */
/*                                                                    */
/*====================================================================*/

void UART_Write(UCHR c )
    {
        while( (UCSRA 1<<UDRE) == );
        UDR c;
    }

/*====================================================================*/
/*                                                                    */
/*             Sende einen String                                     */
/*                                                                    */
/*                                                                    */
/*====================================================================*/

void UART_Write_Text(UCHR *text)
    {
    while (*text)
        {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
            UART_Write(*text);
            text++;
        }
  
    }

/*====================================================================*/
/*                                                                    */
/*                                                                    */
/*             Sende einen String mit CR/NL                           */
/*                                                                    */
/*====================================================================*/

void UART_Write_Text_NL(UCHR *text)
    {
    while (*text)
        {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen*/
            UART_Write(*text);
            text++;
        }
        UART_Write('\r');
        UART_Write('\n');
    }

/*====================================================================*/
/*                                                                    */
/*             Sende ein CR/NL                                        */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
void UART_Write_NL(void)
    {
        UART_Write('\r');
        UART_Write('\n');   
    }

/*====================================================================*/
/*                                                                    */
/*             Sende einen Integerzahl                                */
/*                                                                    */
/*                                                                    */
/*====================================================================*/

void UART_Write_Int(int zahl)
    {
        char string[8];    //Variable string[8] Hier konvertiert itoa später die Zahl hinein
        //itoa(zahl,string, 10);  //Convert Integer zum String, Radix=10  
        while( (UCSRA 1<<UDRE) == );  /* warten bis Senden moeglich */
        
            UART_Write_Text(itoa(zahl,string10)); //vereinfachen der Ausgabe
    }

/*====================================================================*/
/*                                                                    */
/*             Sende eine Integerzahl mit CR/NL                      */
/*                                                                    */
/*                                                                    */
/*====================================================================*/

void UART_Write_Int_NL(int zahl)
    {
        char string[8];    //Variable string[8] Hier konvertiert itoa später die Zahl hinein
        //itoa(string,zahl, 10);  //Convert Integer zum String, Radix=10  
        while((UCSRA 1<<UDRE) == );  /* warten bis Senden moeglich */
        
        UART_Write_Text_NL(itoa(zahl,string,  10)); //vereinfachen der Ausgabe
    }

/*====================================================================*/
/*                                                                    */
/*             Lese empfangenes Zeichen                               */
/*                                                                    */
/*                                                                    */
/*====================================================================*/

uint8_t UART_Read()
    {
        while (!(UCSRA & (1<<RXC)));   // warten bis Zeichen verfuegbar
            
        return UDR;
    }

/*====================================================================*/
/*                                                                    */
/*            Konvertiere empfangene Daten                            */
/*                                                                    */
/*                                                                    */
/*====================================================================*/
uint8_t BCD_To_Decimal (uint8_t bcdByte)
{
  return (((bcdByte 0xF0) >> 4) * 10) + (bcdByte 0x0F);
}

/*********************************************************/
 
uint8_t Decimal_To_BCD (uint8_t decimalByte)
{
  return (((decimalByte 10) << 4) | (decimalByte 10));
}

/* ================================================================== */
/*                                                                    */
/*                                                                    */
/*                    E N D E                                         */
/*                                                                    */
/* ================================================================== */