Source file: /~heha/Mikrocontroller/Sternhimmel/Schnecke.zip/Schnecke.c

#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "PWM32.h"

/**********************************
 * Eigentliches Schneckenprogramm *
 **********************************/
BYTE nachteiler;
BYTE CurIdx;
DWORD CurColor=0xFFF200;

// Mit ≈ 200 Hz, also alle ≈ 5 ms
void Action200(void) {
// ADU beackern
 if (ADCSRA&0x10) {	// Interrupt anhängig? (Sollte immer der Fall sein!)
  int i=ADMUX-0x65;
  adu[i]=ADCH;
  i++; if (i>=3) i=0;
  ADMUX=0x65+i;		// nächster Eingang
  ADCSRA=0xD7;		// neu starten (25 ADU-Takte, 200 µs)
 }
 nachteiler++;
 if (!nachteiler || nachteiler>adu[1]) {	// R3 bestimmt die Ablaufgeschwindigkeit
  nachteiler=0;
  SetLed(CurIdx,CurColor);
  lht[0].r=CurIdx&1?0xFF:0;
  CurIdx++;
  if (CurIdx==54) {
   CurIdx=1;
   CurColor+=adu[2];
   CurColor^=0xFF0000;
  }
 }
}

RGB Verlauf[6] PROGMEM ={
 {255,255,0},	// gelb
 {255,128,0},	// orange
 {255,0,0},	// rot
 {255,0,255},	// lila
 {0,0,255},	// blau
 {0,255,0},	// grün
};

DWORD pgm_read_rgb(RGB*a) {
 DWORD ret;
 asm volatile(
"	lpm	%A0,Z+	\n"
"	lpm	%B0,Z+	\n"
"	lpm	%C0,Z	\n"
	: "=r" (ret), "=z" (a)
	: "1" (a));
 return ret;
}

static BYTE MixComponent(BYTE ca, BYTE ce, BYTE aa, BYTE ae) {
 return (ca*aa+ce*ae)/(BYTE)(aa+ae);
}

static DWORD MixColor(DWORD ca, DWORD ce, BYTE aa, BYTE ae) {
 return
   MixComponent((BYTE)ca,(BYTE)ce,aa,ae)
 | MixComponent((BYTE)(ca>>8),(BYTE)(ce>>8),aa,ae)<<8
 | (DWORD)MixComponent((BYTE)(ca>>16),(BYTE)(ce>>16),aa,ae)<<16;
}

static void V(int a, DWORD ca, int e, DWORD ce) {
 int l=e-a;
 int i=0;
 for (i=0; i<=l; i++,a++) {
  SetLed(a,MixColor(ca,ce,l-i,i));
 }
}

void LoadVerlauf(void) {
 union{
  DWORD d;
  RGB c;
 }c1,c2;
 int i=0,j=0;
 c2.d=pgm_read_rgb(&Verlauf[i]);
 do{
  i++;
  c1.c=c2.c;
  c2.d=pgm_read_rgb(&Verlauf[i]);
  V(j,c1.d,j+10,c2.d);
  j+=10;
 }while (i<6);
}

int main() __attribute__((noreturn));
int main() {
 LoadVerlauf();
 PWM32_INIT();
// Pseudozufallsgenerator initialisieren
	//TODO
 MCUCR=0x80;		// Sleep aktivieren
// Ports initialisieren
 PORTA=0;
 PORTB=0xFF;
 PORTC=0x0F;
 PORTD=0xFF;
 DDRA=0x1F;
 DDRB=0xFF;
 DDRC=0xFF;
 DDRD=0b11111010;
// ADU für die 3 Potis initialisieren (8 bit werden verwendet)
 ADMUX=0x65;		// potenziometrisch, linksbündig, ADC5
 ADCSRA=0xD7;		// Start, Taktteiler maximal (also langsam)
// ISR initialisieren
 PWM32_START();
 for(;;) {
  sleep_cpu();
  if (CurKatode) continue;
  Action200();
  //do sleep_cpu(); while (!CurKatode);	- Problem mit volatile!!
  asm volatile(
"a:	sleep		\n"
"	tst	r7	\n"
"	breq	a	\n"::);	
 }
}
Detected encoding: UTF-80