/****************************************************************************
     Software Uart Empfang
*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "../abc/basis.h"


/*
* Quarz mit 6144000 MHz

*
* Interupt Belegung                       wo              warum
*--------------------------------------------------------------------------
* INT0          external Int0             abc/clock.c     DCF77 Signal
* INT1          external Int1
* PCINT0        Pin Change 0              main.c          software uart
* PCINT1        Pin Change 1
* PCINT2        Pin Change 2
* WDT           Watchdog Time-out
* TIMER2 COMPA  compare match A           abc/clock.c     10 msek
* TIMER2 COMPB  compare match B
* TIMER2 OVF    overflow
* TIMER1 CAPT   capture event
* TIMER1 COMPA  campare match A           main.c          software uart
* TIMER1 COMPB  compare match B
* TIMER1 OVF    overflow
* TIMER0 COMPA  campare match A
* TIMER0 COMPB  compare match B
* TIMER0 OVF    overflow                  main.c          40 msek
* SPI           Serial Transfer
* USART RX      RX complete               abc/avr_uart.c  receive Zeichen da
* USART UDRE    Data Empty                abc/avr_uart.c  transmit Zeichen buffer leer
* USART TX      TX complete               abc/avr_uart.c  Transmit fertig
* ADC           ADC conversion complete
* EE_RDY        EE_PROM ready
* ANA_COMP      Analog comparator
* TWI           two wire Interface
* SPM_RDY       store pgm mem ready
*/

/* -------------------------------------------------------------------------------------------
* Prozessor:  Atmega168  (Atmega8 hat zuwenig Programm-Speicher)
* Frequenz:   6,144 MHz
*                                      +-------------------+
*                 (PCINT14,RESET) PC6 -|1       XXX      28|- PC5 (ADC5/SCL/PCINT13) Backlight Control
*                                      |                   |
*   Anzeige         (PCINT16/RXD) PD0 -|2                27|- PC4 (ADC4/SDA/PCINT12) LCD_DA data
*                                      |                   |
*   Anzeige/Gmess   (PCINT17/TXD) PD1 -|3                26|- PC3 (ADC3/PCINT11)     LCD_EN Enable
*                                      |                   |
*   Clock          (PCINT18/INT0) PD2 -|4                25|- PC2 (ADC2/PCINT10)     LCD_CP Clock
*                                      |                   |
*   Alarm LED (PCINT19/OC2B/INT1) PD3 -|5                24|- PC1 (ADC1/PCINT9)      DS1822 - Aussen GewächsHaus
*                                      |                   |
*   A1           (PCINT20/XCK/T0) PD4 -|6                23|- PC0 (ADC0/PCINT8)      DS1822 - Aussen Temperatur
*                                      |                   |
*                                 VCC -|7                22|- GND
*                                      |                   |
*                                 GND -|8                21|- AREF
*                                      |                   |
*   6,144MHz (PCINT6/XTAL1/TOSC1) PB6 -|9                20|- AVCC
*                                      |                   |
*   6,144MHz (PCINT7/XTAL2/TOSC2) PB7 -|10               19|- PB5 (SCK/PCINT5)       ISP, Regen Messer Software Uart Input
*                                      |                   |
*   A2          (PCINT21/OC0B/T1) PD5 -|11               18|- PB4 (MISO/PCINT4)      *****
*                                      |                   |
*   A3        (PCINT22/OC0A/AIN0) PD6 -|12               17|- PB3 (MOSI/OC2A/PCINT3) *****
*                                      |                   |
*   A4             (PCINT23/AIN1) PD7 -|13               16|- PB2 (SS/OC1B/PCINT2)   A5 14.7.2009
*                                      |                   |
*   S3 Taster  (PCINT0/CLKO/ICP1) PB0 -|14               15|- PB1 (OC1A/PCINT1)      S2 Taster
*                                      +-------------------+
*/



#define RBUF_SIZE 10

char srx_buffer[RBUF_SIZE];
unsigned char srx_ind = 0;           // receive Index

unsigned char volatile srx_count;    // software uart read
unsigned char volatile srx_data;
unsigned char volatile srx_bits;
unsigned char volatile srx_rbyte;
unsigned char volatile srx_start = 0;
unsigned char volatile srx_rflag = 0;



void soft_uart_read_init( void );
void decode_message( char *txt);


/*****************************************************************************
*  Timer2 = clock Steuerung und 10msek Int wegen Tastatur/ Alarm abfragen
*  Timer1 = 200msek Int
*/
int main(void)
{
   
   soft_uart_read_init();
   sei();                             // enable int

                                      // PCINT5 *
   DDRB  &=  ~(BIT5);                 // Input
   PORTB &=  ~(BIT5);                 // ohne Pull up Widerstand
   
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   for(;;)
   {
      
      /// 
     
      // ++++++++++++++++ Software UART Abfrage auf Zeichen empfangen ++++++
      if ( srx_rflag )
      {
         srx_rflag = 0;                     // clear

         if ( srx_rbyte == 0x02 )           // start of txt
         {
            srx_ind = 0;                    // receive Index auf 0
            for ( n=0; n < RBUF_SIZE; n++)  // clear receive buffer
               srx_buffer[ n ] = 0x00;
         }
                                            // zeichen im empfangsbuffer eintragen
         if ( srx_ind >= RBUF_SIZE )
            sflag |= T_ERROR;
         else
            srx_buffer[ srx_ind++ ] = srx_rbyte;

         if ( srx_rbyte == 0x03 )           // end of text ??
            decode_message(srx_buffer);
      }

   }
}



/*****************************************************************************
**  Message von der Anzeige decodieren (Quittungen)
**  qflag setzen = Sender frei
**  quitFlag bit reset = Anforderungen
*/
void decode_message( char *txt)
{
   unsigned char p;
   char *s;

   s = txt+2;
   switch (  txt[ 1 ] )        // 2. Zeichen
   {
                                          // sRF000pe      s= start of text, e = end of text
                                          //  |||  p= Prüfzahl
                                          //  |||- 3 stellige Zahl
                                          //  ||- Flag von 0-9
                                          //  |- R = Kennung
     case 'R':                            // Regen ticks
      p = berechne_PZ( s, 4 ) + 0x30 ;    // Pruefzeichen
      if ( p == s[4] )                    // Pruefzeichen ok
      {
         if ( s[0] != regen_flag )        // neue Nachricht ??
         {
            regen += a_to_i( s+1, 3 );    // summe bilden, wird nach 1h gelöscht
            regen_flag = s[0];
         }
      }
      regen_timer = 0;
      if ( alarm & A_REG )
      {
         alarm &= ~A_REG;                 // reset Alarm
         set_alarm_cnt();
      }
      break;

     case 'Z':                            // Temp Sensor
      break;

     case 'D':                            // Quittung Datum
      break;

     case 'S':                            // Quittung Sekunde
      break;

     case 'T':                            // Quittung Zeit
      break;

     case '<':                            // Quittung Alarm
      if ( qflag < 100 )
         qflag++;                         // quittung da
      break;

     default:
      // rflag |= T_ERROR ;
      break;
   }
}




/*****************************************************************************
**  software uart read, init      300 baud
**  T1 Timer als Zeitmesser
**  PIN Change Interrupt fuer das BIT PB5 = Input Soft UART
**  TIMER1_COMPA für jeds Bit in der Mitte
**  14.03.2011 li funktioniert von 0x00 bis 0xFF
*/

#if F_CPU == 6144000
#define SBIT_TIME  320               //
#endif

#if F_CPU == 14745600
#define SBIT_TIME  768
#endif

void soft_uart_read_init( void )
{
   PCICR |= (1<<PCIE0 );             // PCINT0 erlauben
   PCMSK0 |= BIT5;                   // PORT PB5
   srx_count = 0;                    //
   TCNT1 = 0;
   TIMSK1 = (1 << OCIE1A );          // enable compare match interrupt
   TCCR1C |= (1 << FOC1A );          // Force Output Compare for Channel A
   OCR1A  = SBIT_TIME;
   TCCR1B |= (1<<WGM12) + (1<<CS21) + (1<<CS20);  // prescaler auf 64 und CTC Modus
}



/*****************************************************************************
**  Software Uart
**  Interrupt in der Mitte jedes Bits
**  wird beim StartBit synchronisiert
**  srx_count = 11 : Start Bit
**  srx_count = 10 bis 2 = Bit0 bis BIT7
**  srx_count = 1: Stop Bit
*/
ISR ( TIMER1_COMPA_vect )
{
   unsigned char one = 1;

   if ( srx_start )
   {
      if ( srx_count == 9 )
      {
         if ( srx_bits == 8 )            // 8 bits da
         {
            srx_rbyte = srx_data;        // info sichern
            srx_rflag = 1;               // byte ready melden
         }
         srx_count = 0;                 // auf neues byte warten
         srx_start = 0;
         srx_bits = 0;
      }
      else
      {
         if ( srx_count  )
         {
            if ( PINB & BIT5 )             // RXD Signal = 1 ??
            {
               one <<= srx_bits;
               srx_data |= one;             // 1 dazu
            }
            srx_bits++;
         }
         srx_count++;
      }
   }
   else
   {
      if ( (PINB & BIT5) == 1 )    // RXD auf 0
      {
         srx_count = 0;           // auf neues byte wartensr
         srx_bits = 0;
      }
   }
}



/*****************************************************************************
**  software uart RXD read, PIN CHANGE INT
*/
ISR ( PCINT0_vect )
{
   if ( srx_start == 0 )           // 12 = warten auf Signal
   {
      if ( (PINB & BIT5) == 0 )    // RXD auf 0  ??
      {
         TCNT1 = SBIT_TIME / 2;    // sync auf RXD Signal Mitte
         srx_count = 0;            // start auswertung
         srx_start = 1;
         srx_data = 0;             // alle Bits auf 0
         srx_bits = 0;             // Bitcounter auf 0
      }
   }
}
