Code:
// Kamera und acht Helligkeitsstufen mic 29.12.2010
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <inttypes.h>
#define colors 8 // Anzahl der Farbebenen (8 ist Maximum!)
// Variablen ------------------------------------------------------------------
volatile uint8_t ebene=0, col = 0; // Bildaufbau der LED-Matrix mit Timer2-ISR
uint8_t x, y, z, bildspeicher[colors][15];
uint8_t bild[4][160];
uint16_t counter=0;
uint8_t attrib=1;
prog_uint8_t font[5][17]={ // Zeichensatz für 3x5 7-Segmentanzeige 0 bis F und Blank (Speicherplatz im Flash)
{ 0b111, 0b001, 0b111, 0b111, 0b100, 0b111, 0b100, 0b111, 0b111, 0b111, 0b111, 0b100, 0b111, 0b001, 0b111, 0b111, 0b000},\
{ 0b101, 0b001, 0b001, 0b001, 0b101, 0b100, 0b100, 0b001, 0b101, 0b101, 0b101, 0b100, 0b100, 0b001, 0b100, 0b100, 0b000},\
{ 0b101, 0b001, 0b111, 0b111, 0b111, 0b111, 0b111, 0b001, 0b111, 0b111, 0b111, 0b111, 0b100, 0b111, 0b111, 0b111, 0b000},\
{ 0b101, 0b001, 0b100, 0b001, 0b001, 0b001, 0b101, 0b001, 0b101, 0b001, 0b101, 0b101, 0b100, 0b101, 0b100, 0b100, 0b000},\
{ 0b111, 0b001, 0b111, 0b111, 0b001, 0b111, 0b111, 0b001, 0b111, 0b001, 0b101, 0b111, 0b111, 0b111, 0b111, 0b100, 0b000} \
};
prog_uint8_t * fnt = (prog_uint8_t *) font; // Zeiger für den Zugriff auf den Zeichensatz (für plot_byte())
// Funktionen -----------------------------------------------------------------
void init(void);
void cls(void);
void plot_byte(uint8_t x, uint8_t y, uint8_t ziffer); // Ziffer von 0 bis F
void write_byte(uint8_t a, uint8_t z); // z=0 ist oben, z=1 ist unten
uint8_t Bild_aufnehmen(void);
void Bild_darstellen(uint8_t level);
void Bild_Info(void);
// Einen Bildpunkt an x, y setzen. Werte für c: 0 ist aus, 1 ist dunkel, 4 ist hell
void set(uint8_t x, uint8_t y, uint8_t c);
// Potiwert P2 an ADC6 einlesen als Byte! Kanal 7 ist die Cam
uint8_t readADC6(void);
// WatchDog beim Initialisieren ausschalten
// https://www.roboternetz.de/phpBB2/vi...=531597#531597
void kill_WD(void) __attribute__((naked)) __attribute__((section(".init3")));
void kill_WD(void) { MCUSR = 0; wdt_disable(); }
// Hauptschleife --------------------------------------------------------------
int main(void)
{
init();
for(x=0; x<12; x++)
for(y=0; y<10; y++)
set(x, y, (colors-((x+y)/3)%colors)); // Helligkeitsstufen anzeigen
_delay_ms(2000);
cls();
while(Bild_aufnehmen()); // Bildspeicher füllen
// Bild_Info(); // min - max - mitte - durchschnitt
while(1)
{
if(!col)
{
z=readADC6();
if(attrib)
{
for(y=5; y<10; y++)
for(x=0; x<12; x++) set(x, y, z/29); // 255/29 ergibt 8,8
}
else
{
while(Bild_aufnehmen());
Bild_darstellen(z);
}
if(z==0) if(attrib) { attrib=0; Bild_Info(); } // Bit0: Zeile
if(z==255) if(!attrib) { attrib=1;};
if(attrib) write_byte(z, attrib);
}
counter++;
}
return (0);
}
// Definitionen der Funktionen ------------------------------------------------
uint8_t Bild_aufnehmen(void)
{
static uint8_t bildnummer=0;
uint8_t *bildzeiger;
uint8_t zeile, sync, c;
bildnummer = (bildnummer+1) & 3; // Bildnummer von 0 bis 3
zeile=30; // 30 Zeilen am Bildanfang überlesen
bildzeiger = &bild[bildnummer][0];
do{sync=0;while (ADCH > 20);while (ADCH < 30) sync++;}while (sync < 40);
for(c=0; c<10; c++) // 10 Zeilen einlesen
{
sync=15; // 15 Werte sollen am Stück gelesen werden
while(zeile--){while (ADCH > 20);while (ADCH < 30);} // auf Zeile warten
*bildzeiger++=ADCH; // erster Wert!
ADCSRA |= (1<<ADIF);
while(sync--) // Werte 2-16 einlesen
{
while(!(ADCSRA & (1<<ADIF)));
*bildzeiger++=ADCH;
ADCSRA |= (1<<ADIF);
}
zeile=24; // 24 Zeilen überlesen (30+ 24*10 = 270 Zeilen)
}
return(bildnummer);
}
void Bild_darstellen(uint8_t level)
{
uint8_t x, y, temp;
uint8_t bild_temp[160];
uint16_t temp16;
for(x=0; x<160; x++)
{
temp16 = bild[0][x] + bild[1][x] + bild[2][x] + bild[3][x];
bild_temp[x] = temp = temp16/4;
}
if(level)
{
for(y=0; y<10; y++)
for(x=0; x<12; x++)
{
temp= bild_temp[16*y+x+2];
if(temp<level) set(x, 9-y, colors); else set(x, 9-y, 0);
}
}
else
for(y=0; y<10; y++)
for(x=0; x<12; x++)
{
temp= bild_temp[16*y+x+2];
set(x, 9-y, (temp-20)/8);
}
}
void Bild_Info(void)
{
uint8_t min=225, max=0, temp;
uint16_t durchschnitt=0, temp16;
for(x=0; x<160; x++)
{
temp16 = bild[0][x] + bild[1][x] + bild[2][x] + bild[3][x];
temp = temp16/4;
if(temp > max) max=temp;
else if(temp>20) if(temp < min) min=temp;
durchschnitt += temp;
}
durchschnitt /= 160;
cls();
write_byte(min, 1);
_delay_ms(1000);
cls();
write_byte(max, 0);
_delay_ms(1000);
cls();
write_byte((min+max)/2, 1);
_delay_ms(1000);
cls();
write_byte(durchschnitt, 0);
_delay_ms(1000);
}
void cls(void)
{
uint8_t x, y;
for(y=0; y<colors; y++)
for(x=0; x<15; x++)bildspeicher[y][x] = 0;
}
void set(uint8_t x, uint8_t y, uint8_t c)
{
uint8_t ebene;
y = 9-y; // Koordinatennullpunkt unten links
if(y < 8) // y 9 bis 2
for(ebene=0; ebene<colors; ebene++)
if(c>ebene) bildspeicher[ebene][x] |= (1 << y);
else bildspeicher[ebene][x] &= ~(1 << y);
else // y 1 und 0
for(ebene=0; ebene<colors; ebene++)
if(c>ebene) bildspeicher[ebene][12+(x>>2)] |= (1<<((x%4)*2+(y&1)));
else bildspeicher[ebene][12+(x>>2)] &= ~(1<<((x%4)*2+(y&1)));
}
void plot_byte(uint8_t x, uint8_t y, uint8_t ziffer)
{
uint8_t c, f1=colors, f2=0, fontbyte=0;
for(c=0; c<5; c++)
{
fontbyte = pgm_read_byte_near(fnt+17*c+ziffer); // Zeichensatz ist im Flash
if(fontbyte & 4) set(x , y-c, f1); else set(x , y-c, f2);
if(fontbyte & 2) set(x+1, y-c, f1); else set(x+1, y-c, f2);
if(fontbyte & 1) set(x+2, y-c, f1); else set(x+2, y-c, f2);
if(fontbyte & 0) set(x+3, y-c, f1); else set(x+3, y-c, f2);
}
}
void write_byte(uint8_t a, uint8_t z) // z=0 ist oben, z=1 ist unten
{
uint8_t c, temp=1;
c=0;
while(a >= 100) {a-=100; c++; }
if(c) plot_byte(0, 9-5*z, c); else { plot_byte(0, 9-5*z, 16); temp=0; }
c=0;
while(a >= 10) {a-=10; c++; }
if(c || temp) plot_byte(4, 9-5*z, c); else plot_byte(4, 9-5*z, 16);
c=0;
while(a >= 1) {a-=1; c++; }
plot_byte(8, 9-5*z, c);
}
uint8_t readADC6(void)
{
uint8_t adc6, dummy;
ADCSRA = (0 << ADEN);
dummy=ADCH;
// A/D Conversion (aus der asuro-Lib)
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); // clk/32
ADMUX = (1<<ADLAR) | (1 << REFS0) | (6);// AVCC reference with external capacitor
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
adc6=ADCH;
ADCSRA |= (1 << ADIF); // clear ADCIF
ADCSRA = (0 << ADEN);
dummy=ADCH;
// rechtsbündig, interne 2,56V-Referenz (0:1 5V, 1:1 2,56V) , Kanal 7
ADMUX = (1<<ADLAR) | (1<<REFS1) | (1<<REFS0) | 7;
// enable, start conversion, freerunning, prescaler /2
ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
return(adc6);
}
void init(void)
{
cli();
DDRB = 0xff;
DDRC = 0x0f;
DDRD = 0xf0;
TCCR2 = (1<<CS21) | (0<<CS20); // 8-bit Timer mit 1/8 Vorteiler
TCCR2 |= (1<<WGM21) | (1<<WGM20); // Fast PWM
TCCR2 |= (0<<COM21) | (0<<COM20); // no OC2-Pin
OCR2 = 100; // 0=dunkel, 255=hell
TIFR = (1<<OCF2) | (1<<TOV2); // Clear old flags
TIMSK |= (1<<TOIE2) | (1<<OCIE2); // overflow and compare interrupt
// rechtsbündig, interne 2,56V-Referenz (0:1 5V, 1:1 2,56V) , Kanal 7
ADMUX = (1<<ADLAR) | (1<<REFS1) | (1<<REFS0) | 7;
// enable, start conversion, freerunning, prescaler /2
ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
sei(); // Interrupts erlauben
}
// ISR ------------------------------------------------------------------------
SIGNAL (SIG_OUTPUT_COMPARE2)
{
OCR2 = (1<<ebene)-1; // hihi
PORTC &= ~0x0f; // Die Pins der Displaymatrix werden wieder auf Low gesetzt
PORTD &= ~0xf0;
PORTB &= ~0x03;
}
SIGNAL (SIG_OVERFLOW2)
{
uint8_t ledval, portb;
// Spalten
if(col) PORTB |= (1<<4); /* Danach Einsen hinterherschicken (PB4 = 1) */
else PORTB &= ~(1<<4); /* Bei der ersten Spalte eine 0 ausgeben (PB4 = 0) */
PORTB |= (1 << 3); /* PB3 = 1 (cl) */
PORTB &= ~(1 << 3); /* PB3 = 0 (!cl) */
PORTB |= (1 << 2); /* PB2 = 1 (str) */
PORTB &= ~(1 << 2); /* PB2 = 0 (!str) */
// Zeilen
ledval = bildspeicher[ebene][12+(col>>2)]; // y 1 und 0
portb = (ledval >> (col%4)*2) & 0x03;
ledval = bildspeicher[ebene][col]; // y 9 bis 2
PORTC |= ledval & 0x0f;
PORTD |= ledval & 0xf0;
PORTB |= portb;
col++;
if(col>11)
{
col=0;
ebene++;
if(ebene == colors) ebene=0;
}
}
Gruß
Lesezeichen