Der Quelltext wie er bisher aussieht:


#include <io.h>
#include <signal.h>
#include <timer.h>
#include <progmem.h>
#include <interrupt.h>
#include <eeprom.h>

// Portbelegung
//
// Port C = Daten
// PA 0 = WR
// PA 1 = RD
// PA 2 = CS
// PA 3 = A0
// PA 4 = A1
//
// PB 0 = GATE 2

#define ANZ_OUT 12
#define ANZ_IN 9

// Wert, den der Timer ausgeben soll
int out_value[ANZ_OUT];

// Eingangswert
int in_value[ANZ_IN];
unsigned int in_value_merk[ANZ_IN];
unsigned char in_value_monitor[ANZ_IN];

unsigned int mx[ANZ_IN];

// nr ist die Nummer des Timers im Baustein (0-2)
// baseaddr ist die Basisadresse des Bausteines
const char in_timer_nr[]       =  { 2 , 1, 0, 0, 1, 2, 2, 1, 0 };
const char in_timer_baseaddr[] =  { 16,16,16,24,24,24,28,28,28 };

const char out_timer_nr[]       =  { 0,1,2,0,1,2,0,1,2, 0, 1, 2 };
const char out_timer_baseaddr[] =  { 0,0,0,4,4,4,8,8,8,12,12,12 };

#include "servo_linear.c"

// UART initialisieren
//--------------------------------------------------------------------------------
void uart_init( void )
{
// 10011000
//  outp(0x98, UCR); // Recive Interrupt enabled
  outp(0x18, UCR); // RX und TX, ohne interrupt
  outp( 12, UBRR); // 19200 Baud
}

// UART Zeichen ausgeben
//--------------------------------------------------------------------------------
void uart_outchar( unsigned char x )
{
  while( !(inp(USR) & 0x20) ) ;
  outp(x,UDR);
}

// UART Zeichen ausgeben
//--------------------------------------------------------------------------------
unsigned char uart_inchar( void )
{
  unsigned long t = 300000;
  while( !(inp(USR) & 0x80) && t-- > 0) ;
  inp(UDR);
}

// UART HEX Byte ausgeben
//--------------------------------------------------------------------------------
void uart_outhex( unsigned char x )
{
  if(((x & 0xF0) >> 4) <= 9)
    uart_outchar(((x & 0xF0) >> 4) + '0');
  else
    uart_outchar(((x & 0xF0) >> 4) + 'A' -10 );

  if((x & 0x0F) <= 9)
    uart_outchar((x & 0x0F) + '0');
  else
    uart_outchar((x & 0x0F) + 'A' -10 );
}

// UART String ausgeben
//--------------------------------------------------------------------------------
void uart_outword( unsigned int x )
{
  uart_outhex((x & 0xFF00) >> 8);
  uart_outhex(x & 0x00FF);
}

// UART String ausgeben
//--------------------------------------------------------------------------------
void uart_outstr( unsigned char *s )
{
  while(*s)
    uart_outchar(*s++);
}

// UART String ausgeben
//--------------------------------------------------------------------------------
void uart_outbuf( unsigned char *s ,int count)
{
  int i;
  for(i=0;i<count;i++)
    uart_outchar(s[i]);
}
 

// Interrupt wenn Zeichen vom UART eintrifft
//-----------------------------------------------------------------------------------
SIGNAL(SIG_UART_RECV)
{
  unsigned char ch;

  ch = inp(UDR); // Zeichen einlesen
  uart_outchar(ch); // und wieder ausgeben
  if (ch == 0x0d)
    uart_outchar(0x0a);
}

//------------------------------------------
// Ausgeben eines Wertes an den Timer
//
inline void out_timer(unsigned char b, unsigned char adresse)
{
outp(0xFF,DDRC); // Port C auf Ausgang
outp(b,PORTC);

//outp( (adresse << 3 ) | 0x06  ,PORTA);
outp( (adresse << 3 ) | 0x02  ,PORTA);
outp( (adresse << 3 ) | 0x06  ,PORTA);
outp( (adresse << 3 ) | 0x07  ,PORTA);

outp(0x00,DDRC); // Port C auf Eingang
outp(0x00,PORTC); // disable pullup
}

//------------------------------------------
// Einlesen eines Wertes vom Timer
//
inline unsigned char in_timer(unsigned char adresse)
{
unsigned char erg;

outp( (adresse << 3 ) | 0x01  ,PORTA);
erg = inp(PINC); // Das ist noch zu schnell !!!
erg = inp(PINC); // Hier sind die Daten jetzt stabil
outp( (adresse << 3 ) | 0x07  ,PORTA);
return erg;
}

//---------------------------------------------
// Hex Ziffer ausgeben
void out_hexb( unsigned char x)
{
unsigned char y;

y = (x & 0xF0) >> 4;

if(y < 0x0a)
  uart_outchar(y + '0');
else
  uart_outchar(y + 'A' - 10);

y = (x & 0x0F);

if(y < 0x0a)
  uart_outchar(y + '0');
else
  uart_outchar(y + 'A' - 10);
}

//---------------------------------------------
// Hex Integer ausgeben
out_hexint(unsigned int x)
{
  out_hexb((x & 0xFF00) >> 8);
  out_hexb(x & 0x00FF);
}
 
 

//------------------------------------------
// Die Timer 0 Interrupt routine
//
SIGNAL(SIG_OVERFLOW0)
{
static char  zykl = 0;
unsigned char  i;
unsigned int m;

if(zykl ++ >= 3) // alle 20ms die Ausgabetimer starten
  {
    for(i=0;i<ANZ_OUT;i++)
    {
      m=out_value[i] + 6000;
      out_timer(0x30 | (out_timer_nr[i]<<6),out_timer_baseaddr[i]+3); // Mode 0 Timer 2
      out_timer(m & 0xFF,out_timer_baseaddr[i]+out_timer_nr[i]);
      out_timer((m >> 8)& 0xFF,out_timer_baseaddr[i]+out_timer_nr[i]);
    }
    zykl = 0;
  }
   // Jedesmal, eingabetimer testen
  for(i=0;i<ANZ_IN;i++)
  {
    out_timer(in_timer_nr[i] << 6,in_timer_baseaddr[i]+3); // Latch Timer 1
    m = in_timer(in_timer_baseaddr[i]+in_timer_nr[i]) | (in_timer(in_timer_baseaddr[i]+in_timer_nr[i]) << 8);
    mx[i] = m;
    if(in_value_merk[i] != m)
    {
  // Timer laeuft noch
   in_value_merk[i] = m;
    }
    else if(m != 0xFFFE) // Timer ist noch nicht angelaufen
    {
       in_value_merk[i] = 0;
       m = 0xFFFE -m;
       if(m < 3000) m = 3000;
       if(m > 9000) m = 9000;
       in_value[i] =  m - 6000;
       in_value_monitor[i]=0;
       out_timer(0x30 | (in_timer_nr[i] << 6),in_timer_baseaddr[i]+3); // Mode 1 Timer 1
       out_timer(0xFE,in_timer_baseaddr[i]+in_timer_nr[i]); // der Startwert ist hier 0xFFFE
       out_timer(0xFF,in_timer_baseaddr[i]+in_timer_nr[i]);
    }

     // miermit wird der Timerlauf überwacht und evtl neu gestartet
      if(in_value_monitor[i]++ >= 28)
      {
        in_value_monitor[i]=20;
        in_value_merk[i] = 0;
        out_timer(0x30 | (in_timer_nr[i] << 6),in_timer_baseaddr[i]+3); // Mode 1 Timer 1
        out_timer(0xFE,in_timer_baseaddr[i]+in_timer_nr[i]); // der Startwert ist hier 0xFFFE
        out_timer(0xFF,in_timer_baseaddr[i]+in_timer_nr[i]);
//        uart_outstr("****************************************************\n\rRESTART!!!!!*****************************");
      }
  }
}

//------------------------------------------
// 120 Grad Mischer
//
void mixer_120( int *hinten, int *links, int *rechts, int roll, int nick, int pitch )
{
  *hinten = pitch/2 + nick/2;
  *links  = pitch/2 + ((roll*8)/20) - ((nick*8)/20);
  *rechts = pitch/2 - ((roll*8)/20) - ((nick*8)/20);
}
 

//-----------------------------------------------------------------------------------

int main (void)
{
  int i;
  int x;
  char c;
  char kreisel_init = 10;

  int roll,nick,pitch,heck;

  for(i=0;i< ANZ_OUT;i++)
    out_value[i] = 0; // Mittelstellung

  for(i=0;i<ANZ_IN;i++)
  {
    in_value[i] = 0;
    in_value_merk[i] = 0;
    in_value_monitor[i] = 30;
    out_timer(0x30 | (in_timer_nr[i] << 6),in_timer_baseaddr[i]+3); // Mode 0 Timer 1
    out_timer(0xFE,in_timer_baseaddr[i]+in_timer_nr[i]); // der Startwert ist hier 0xFFFF
    out_timer(0xFF,in_timer_baseaddr[i]+in_timer_nr[i]);
  }

  outp(0x80,SREG); // global Interrupt enable
  outp(0x02,TIMSK); // Timer 0 löst interrupt aus

  outp(0x03,TCCR0); // Prescaler CK/64 ergibt 4,096ms pro Durchlauf

  outp(0xFF,DDRA); // Port A ist ausgang
  outp(0xFF,PORTA); // high ist deaktiv

  outp(0xFF,PORTB);
  outp(0xFF,DDRB);

  uart_init();
  uart_outstr("Hello World\n\r");

//  x = eeprom_rb(10);
//  out_hexint(x);

//  eeprom_wb(10,0x73);

  while(1)
  {

    cli();  // Interrupts sperren

    out_value[8] = in_value[1]; // der Heck Kreisel
    out_value[6] = in_value[2]; // der nick Kreisel
    out_value[10] = in_value[3]; // der Roll Kreisel

    pitch = in_value[0];
    roll = in_value[8];
    nick = in_value[6];
    heck = in_value[7];
 

    mixer_120(&out_value[0],&out_value[1],&out_value[2],roll+heck/2,nick/8,pitch+nick/2);
    mixer_120(&out_value[3],&out_value[4],&out_value[5],roll-heck/2,nick/8,pitch-nick/2);
 

    sei();  // Interrupts freigeben
 

    cli();  // Interrupts sperren
 //   out_timer(in_timer_nr[1] << 6,in_timer_baseaddr[1]+3); // Latch Timer 1
 

  if(inp(USR) & 0x80)
  {
    c=inp(UDR);
    if(c==' ')
    {
      for(i=0;i<ANZ_IN;i++)
      {
        out_timer(0x30 | (in_timer_nr[i] << 6),in_timer_baseaddr[i]+3); // Mode 0 Timer 1
        out_timer(0xFE,in_timer_baseaddr[i]+in_timer_nr[i]); // der Startwert ist hier 0xFFFF
        out_timer(0xFF,in_timer_baseaddr[i]+in_timer_nr[i]);
      }
      uart_outstr("Timer Reset durchgeführt");
    }
  }
    sei();  // Interrupts freigeben

  if((in_value_monitor[6] < 20) &&
     (in_value_monitor[7] < 20) &&
     (in_value_monitor[8] < 20))
    {
      outp(inp(PORTB) & 0xFE,PORTB);

      if(kreisel_init == 0)
      {
        uart_outstr("Kreisel sind betriebsbereit\n\r");
        out_value[7] = -2000;         // Empfindlichkeitskanäle
        out_value[9] = -2000;
        out_value[11] = -2000;

        kreisel_init = -1;
      }
      else
        if(kreisel_init > 0)
          kreisel_init--;
        else // Kreisel sind im Betrieb
        {
/*----------------------
           if(in_value[6] < -20)
             out_value[6]++;
           else if(in_value[6] > 20)
             out_value[6]--;
           else
             out_value[6]=20;

          out_hexint(out_value[6]);
--------------------------*/
        }
    }
  else
      outp(inp(PORTB) | 0x01,PORTB);

  if((in_value_monitor[0] < 20) &&
     (in_value_monitor[1] < 20) &&
     (in_value_monitor[2] < 20) &&
     (in_value_monitor[3] < 20) &&
     (in_value_monitor[4] < 20) &&
     (in_value_monitor[5] < 20))
      outp(inp(PORTB) & 0xFD,PORTB);
  else
      outp(inp(PORTB) | 0x02,PORTB);

/*-----
    for(i=0;i<ANZ_IN;i++)
    {
      out_hexint(in_value[i]);
      uart_outstr(" ");
    }
    uart_outstr(" <-\n\r");
---------*/
    uart_outstr("*");
  }
}


(c) Ulrich Röhr, http://www.ulrich-roehr.de