/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.5 Standard
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : Multiswitch Sender
Version : 1.1
Date    : 31.10.2008
Author  : Wilhelm Krug                    
Company : 92345 Dietfurt, Germany         
Comments: 


Chip type           : ATmega8L
Program type        : Application
Clock frequency     : 8,000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega8.h>
#define TWIE 0
#define TWEN 2
#define TWWC 3
#define TWSTO 4
#define TWSTA 5
#define TWEA 6
#define TWINT 7



volatile bit ub_nextframe=0;                    /* Flag für nächsten Multiswitchimpuls */
volatile unsigned char uc_pulsecount=0;         /* Zähler zur Impulszählung 8 Pulse schalten 1 Frame weiter )*/
volatile unsigned char uc_framecount=0;         /* Zähler für de Framezählung 10 Pulse pro Sequenz */
volatile unsigned char uc_frame[10]={255,255,120,120,120,120,120,120,120,120}; /* Puffer für Impulshöhe */
volatile unsigned char uc_pulses=7;             /* Wird abhängig vom PD5 auf 7 oder 9 eingestellt */
const unsigned char uc_low=13;                  /* Konstanten für die Impulslängen bei digitalen Poti */
const unsigned char uc_mid=120;
const unsigned char uc_high=222;
const unsigned char uc_sync=255;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
TCNT0=0;                                        /* Reset der Zeitüberwachung der Impulspausen */
uc_pulsecount++;
if(uc_pulsecount>uc_pulses)                             /* war >7 Nach 8 Sync - >9 nach 10 Sync Impulsen wird ein Frame weitergeschaltet */
    {
    uc_pulsecount=0;
    uc_framecount++;
    if(uc_framecount>9){uc_framecount=0;};      /* Wurden bereits alle 10 ( 2.Sync + 8 Kanalimpulse ) übertragen ? */
    ub_nextframe=1;
    };
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
uc_pulsecount=0;                                /* Wenn 8ms kein neuer Impuls eingetroffen ist, wird der Pulszähler auf 0 gesetzt*/
}

// I2C Daten an das digitale Poti senden
void send_i2c(unsigned char uc_value)
{
TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN));         /* Start Condition senden */
while (!(TWCR&(1<<TWINT)));                     /* Warten bis fertig */
if ((TWSR&0xF8) != 0x08)                        /* Gab es Fehler */
    {
    //ERROR
    }
else
    {
    TWDR=0b01010000;                /* Control Byte in das I2C Poti schreiben ( SLA + W = Slave Adress + Write ) */
    TWCR=(1<<TWINT)|(1<<TWEN);
    while (!(TWCR&(1<<TWINT)));     /* Warten auf das Ende der Übertragung */
    if((TWSR&0xF8) !=0x18)
        {
        // ERROR
        }
    else
        {
        TWDR=0b10101111;                /* Command Byte in das I2C Poti schreiben wird als Data behandelt ( beide Potis ansteuern )*/
        TWCR=(1<<TWINT)|(1<<TWEN);
        while (!(TWCR&(1<<TWINT)));     /* Warten auf das Ende der Übertragung */
        if((TWSR&0xF8) !=0x28)
            {
            // ERROR
            }
        else
            {
            TWDR=uc_value;              /* Werte in das I2C Poti schreiben */
            TWCR=(1<<TWINT)|(1<<TWEN);
            while (!(TWCR&(1<<TWINT))); /* Warten auf das Ende der Übertragung */
            if((TWSR&0xF8) !=0x28)
                {
                // ERROR
                }
            else
                {
                TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO); /* Stopp Condition senden */
                };
            };
        };
    };
}

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=P State4=P State3=P State2=P State1=P State0=P 
PORTB=0b00111111;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=P State2=P State1=P State0=P 
PORTC=0b00001111;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=P State6=P State5=0 State4=P State3=P State2=T State1=P State0=P 
PORTD=0b11111011;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 31,250 kHz
TCCR0=0x04;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
GICR|=0x40;
MCUCR=0x03;
GIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// 2 Wire Bus initialization
// Generate Acknowledge Pulse: Off
// 2 Wire Bus Slave Address: 0h
// General Call Recognition: Off
// Bit Rate: 200,000 kHz - 400,000 kHz sollten auch gehen TWBR dazu auf 0x02 setzen
TWSR=0x00;
TWBR=0x0C;
TWAR=0x00;
TWCR=0x04;


if(PIND.5>0)
    {
    uc_pulses=7;                      // Der Jumper an PD5 ist offen = 8 Impulse Sync MC 16/20 o.Ä.
    }
else
    {
    uc_pulses=9;                     // Der Jumper an PD5 ist zu = 10 Impulse Sync = MC 19, MC22 o.Ä.
    } 

/* uc_pulses=9; */
// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/1024k
#pragma optsize-
WDTCR=0x1E;
WDTCR=0x0E;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
//**********************
//**** Testroutines ****



//*End of Testroutines*

send_i2c(uc_mid);                       /* Digitales Poti in Mittelstellung bringen */

// Global enable interrupts
#asm("sei")

while (1)
      {
      #asm ("wdr");
      
      
      // Sync Impulse
      uc_frame[0]=uc_sync;              /* Die beiden Sync Impulse in den Framebuffer laden */
      uc_frame[1]=uc_sync;
      
      // Schaltersatz 1 abfragen und den Wert in den Framebuffer laden
      if(PINC.0>0&&PINC.1>0)
        {
        uc_frame[2]=uc_mid;
        };
      if(PINC.0==0)
        {
        uc_frame[2]=uc_high;
        };
      if(PINC.1==0)
        {
        uc_frame[2]=uc_low;
        };
        // Schaltersatz 2 abfragen und den Wert in den Framebuffer laden 
      if(PINC.2>0&&PINC.3>0)
        {
        uc_frame[3]=uc_mid;
        };
      if(PINC.2==0)
        {
        uc_frame[3]=uc_high;
        };
      if(PINC.3==0)
        {
        uc_frame[3]=uc_low;
        };
      // Schaltersatz 3 abfragen und den Wert in den Framebuffer laden
      if(PIND.0>0&&PIND.1>0)
        {
        uc_frame[4]=uc_mid;
        };
      if(PIND.0==0)
        {
        uc_frame[4]=uc_high;
        };
      if(PIND.1==0)
        {
        uc_frame[4]=uc_low;
        };
      // Schaltersatz 4 abfragen und den Wert in den Framebuffer laden
      if(PIND.6>0&&PIND.7>0)
        {
        uc_frame[5]=uc_mid;
        };
      if(PIND.6==0)
        {
        uc_frame[5]=uc_high;
        };
      if(PIND.7==0)
        {
        uc_frame[5]=uc_low;
        };
      // Schaltersatz 5 abfragen und den Wert in den Framebuffer laden
      if(PINB.0>0&&PINB.1>0)
        {
        uc_frame[6]=uc_mid;
        };
      if(PINB.0==0)
        {
        uc_frame[6]=uc_high;
        };
      if(PINB.1==0)
        {
        uc_frame[6]=uc_low;
        };
      // Schaltersatz 6 abfragen und den Wert in den Framebuffer laden
      if(PINB.2>0&&PINB.3>0)
        {
        uc_frame[7]=uc_mid;
        };
      if(PINB.2==0)
        {
        uc_frame[7]=uc_high;
        };
      if(PINB.3==0)
        {
        uc_frame[7]=uc_low;
        };
      // Schaltersatz 7 abfragen und den Wert in den Framebuffer laden
      if(PIND.3>0&&PIND.4>0)
        {
        uc_frame[8]=uc_mid;
        };
      if(PIND.3==0)
        {
        uc_frame[8]=uc_high;
        };
      if(PIND.4==0)
        {
        uc_frame[8]=uc_low;
        };
      // Schaltersatz 8 abfragen und den Wert in den Framebuffer laden
      if(PINB.4>0&&PINB.5>0)
        {
        uc_frame[9]=uc_mid;
        };
      if(PINB.4==0)
        {
        uc_frame[9]=uc_high;
        };
      if(PINB.5==0)
        {
        uc_frame[9]=uc_low;
        };
      // Umschaltung des digitalen Potis auf nächsten Wert
      if(ub_nextframe>0)
        {
        ub_nextframe=0;
        send_i2c(uc_frame[uc_framecount]);                      /* I2C Routine aufrufen uc_framecount wird in der Interruptroutine INT0 hochgezählt*/
        }; 
      };
}
