#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("*");
}
}