#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-8 | 0
|