Hallo
Mit diesem kleinen Update beende ich mal den Ausflug in die Welt der HiRes-Bilder:
Code:
// RP6 sendet eine 48X64-HiRes-Bitmap über die serielle Schnittstelle 5.4.10 mic
// Das Bild ist um 90° nach links gedreht, oben links im TV ist unten links im BMP
// Es werden nur ca. 3/4 des Bildes erfasst. Um das ganze Bild einlesen zu können,
// muss man die Bildgröße des BMP ändern, also den Header anpassen.
// Das ist mir im Moment zuviel Aufwand ;)
#include "RP6RobotBaseLib.h"
void ADC_Init(void)
{
extIntOFF(); // schaltet den E_INT1-Port auf Eingang für den ADC
// ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4 (E_INT1)
ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) | 4;
// setze free running triggern
SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// kein Interupt, Wandler einschalten, prescaler /2, ADC läuft nun mit 4MHz!
ADCSRA = (0<<ADIE) | (1<<ADEN) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
// Autotriggern bedeutet jetzt free running aktivieren, altes Flag löschen
ADCSRA |= (1<<ADATE) | (1<<ADIF);
// Initialisierung starten
ADCSRA |= (1<<ADSC);
// und noch die empfohlene Initiallesung
while (!(ADCSRA & (1<<ADIF)));
ADCSRA |= (1<<ADIF);
}
int main(void)
{
uint8_t bildspeicher[100], *bildzeiger; // 100 Byte Bildspeicher sollten reichen
uint8_t zeile, spalte, sync, c, i; // und dürfen NICHT global sein!
uint8_t bmp_header_48_64_24bit[54]={
0x42, 0x4d, 0x36, 0x24, 00, 00, 00, 00, 00, 00, 0x36, 00, 00, 00, 0x28, 00,
00, 00, 0x30, 00, 00, 00, 0x40, 00, 00, 00, 01, 00, 0x18, 00, 00, 00,
00, 00, 00, 0x24, 00, 00, 0xc4, 0x0e, 00, 00, 0xc4, 0x0e, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00};
initRobotBase();
ADC_Init();
while(1)
{
for(c=0; c<54; c++) writeChar(bmp_header_48_64_24bit[c]); // Header senden
for(spalte=0; spalte<64; spalte+=2)
{
bildzeiger=&bildspeicher[0]; // Zeiger auf Start des Bildspeicherbereich
zeile=30; // aktuelle Zeile (35 Zeilen sind der Schrott beim Bildstart)
setLEDs(63-spalte); // working
cli();
do {sync=0; while (ADCH > 20); while (ADCH < 30) sync++;}while (sync < 40);
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
for(c=0; c<48; c++)
{
i=spalte; zeile=5; // Zeilensprung für 48 Zeilen
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
ADCSRA = (1<<ADATE)|(0<<ADEN)|(1<<ADIF)|(0<<ADSC)|(1<<ADPS0); // ADC stoppen
while(i--); // Pixel ansteuern
ADCSRA = (1<<ADATE)|(1<<ADEN)|(1<<ADIF)|(1<<ADSC)|(1<<ADPS0); // ADC wieder starten
while (!(ADCSRA & (1<<ADIF))); // 26 ADC-Takte warten bis Wandlung fertig
*bildzeiger++=ADCH; // das sind ca. 6,5µs
ADCSRA |= (1<<ADIF);
}
zeile=30;
setLEDs(62-spalte); // working
do {sync=0; while (ADCH > 20); while (ADCH < 30) sync++;}while (sync < 40);
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
for(c=0; c<48; c++)
{
i=spalte; zeile=5; // Zeilensprung für 48 Zeilen
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
ADCSRA = (1<<ADATE)|(0<<ADEN)|(1<<ADIF)|(0<<ADSC)|(1<<ADPS0); // ADC stoppen
nop(); nop(); // nächste Spalte zwei NOPs später einlesen
while(i--); // Pixel ansteuern
ADCSRA = (1<<ADATE)|(1<<ADEN)|(1<<ADIF)|(1<<ADSC)|(1<<ADPS0); // ADC wieder starten
while (!(ADCSRA & (1<<ADIF))); // 26 ADC-Takte warten bis Wandlung fertig
*bildzeiger++=ADCH; // das sind ca. 6,5µs
ADCSRA |= (1<<ADIF);
}
sei();
for(zeile=0; zeile<96; zeile++) // 96 Pixel senden
{
if (bildspeicher[zeile] > 20)
{
writeChar((bildspeicher[zeile]-20)*2); // RGB in Pixelfarbe
writeChar((bildspeicher[zeile]-20)*2);
writeChar((bildspeicher[zeile]-20)*2);
}
else
{
writeChar(0); // oder Schwarz
writeChar(0);
writeChar(0);
}
}
}
setLEDs(63); // ready
while(!(getBumperLeft() || getBumperRight())); // Neues Bild senden?
}
return(0);
}
Da spalte und i nun 8Bit-Variablen sind, dauert while(i--) nur noch drei Takte (bei i != 0). Um die Auflösung noch weiter zu steigern lese ich nun zweimal dieselbe Spalte, allerdings beim zweiten Durchgang mit zusätzlichen zwei NOPs vor der while(i--)-Schleife.
Beim Stoppen/Starten des ADC wird das ADCSRA-Register nur noch geschrieben und nicht mehr zuvor eingelesen (= anstelle von &= bzw. |=)
Einer der wenigen Buchstaben mit eindeutiger Orientierung ist das R:
Bild hier
Gruß
mic
[Edit]
64X96:
Code:
// RP6 sendet eine 64x96-HiRes-Bitmap über die serielle Schnittstelle 5.4.10 mic
#include "RP6RobotBaseLib.h"
void ADC_Init(void)
{
extIntOFF(); // schaltet den E_INT1-Port auf Eingang für den ADC
// ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4 (E_INT1)
ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) | 4;
// setze free running triggern
SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// kein Interupt, Wandler einschalten, prescaler /2, ADC läuft nun mit 4MHz!
ADCSRA = (0<<ADIE) | (1<<ADEN) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
// Autotriggern bedeutet jetzt free running aktivieren, altes Flag löschen
ADCSRA |= (1<<ADATE) | (1<<ADIF);
// Initialisierung starten
ADCSRA |= (1<<ADSC);
// und noch die empfohlene Initiallesung
while (!(ADCSRA & (1<<ADIF)));
ADCSRA |= (1<<ADIF);
}
int main(void)
{
uint8_t bildspeicher[150], *bildzeiger; // 150 Byte Bildspeicher sollten reichen
uint8_t zeile, spalte, sync, c, i; // und dürfen NICHT global sein!
uint8_t bmp_header_64_96_24bit[54]={
0x42, 0x4d, 0x36, 0x48, 00, 00, 00, 00, 00, 00, 0x36, 00, 00, 00, 0x28, 00,
00, 00, 0x40, 00, 00, 00, 0x60, 00, 00, 00, 01, 00, 0x18, 00, 00, 00,
00, 00, 00, 0x24, 00, 00, 0xc4, 0x0e, 00, 00, 0xc4, 0x0e, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00};
initRobotBase();
ADC_Init();
while(1)
{
for(c=0; c<54; c++) writeChar(bmp_header_64_96_24bit[c]); // Header senden
for(spalte=0; spalte<96; spalte+=2)
{
bildzeiger=&bildspeicher[0]; // Zeiger auf Start des Bildspeicherbereich
zeile=30; // aktuelle Zeile (35 Zeilen sind der Schrott beim Bildstart)
setLEDs(95-spalte); // working
cli();
do {sync=0; while (ADCH > 20); while (ADCH < 30) sync++;}while (sync < 40);
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
for(c=0; c<64; c++)
{
i=spalte; zeile=3; // Zeilensprung für 64 Zeilen
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
ADCSRA = (1<<ADATE)|(0<<ADEN)|(1<<ADIF)|(0<<ADSC)|(1<<ADPS0); // ADC stoppen
while(i--); // Pixel ansteuern
ADCSRA = (1<<ADATE)|(1<<ADEN)|(1<<ADIF)|(1<<ADSC)|(1<<ADPS0); // ADC wieder starten
while (!(ADCSRA & (1<<ADIF))); // 26 ADC-Takte warten bis Wandlung fertig
*bildzeiger++=ADCH; // das sind ca. 6,5µs
ADCSRA |= (1<<ADIF);
}
zeile=30;
setLEDs(94-spalte); // working
do {sync=0; while (ADCH > 20); while (ADCH < 30) sync++;}while (sync < 40);
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
for(c=0; c<64; c++)
{
i=spalte; zeile=3; // Zeilensprung für 64 Zeilen
while(zeile--) {while (ADCH > 20); while (ADCH < 30);}
ADCSRA = (1<<ADATE)|(0<<ADEN)|(1<<ADIF)|(0<<ADSC)|(1<<ADPS0); // ADC stoppen
nop(); nop(); // nächste Spalte zwei NOPs später einlesen
while(i--); // Pixel ansteuern
ADCSRA = (1<<ADATE)|(1<<ADEN)|(1<<ADIF)|(1<<ADSC)|(1<<ADPS0); // ADC wieder starten
while (!(ADCSRA & (1<<ADIF))); // 26 ADC-Takte warten bis Wandlung fertig
*bildzeiger++=ADCH; // das sind ca. 6,5µs
ADCSRA |= (1<<ADIF);
}
sei();
for(zeile=0; zeile<128; zeile++) // 2*64 Pixel senden
{
if (bildspeicher[zeile] > 20)
{
writeChar((bildspeicher[zeile]-20)*2); // RGB in Pixelfarbe
writeChar((bildspeicher[zeile]-20)*2);
writeChar((bildspeicher[zeile]-20)*2);
}
else
{
writeChar(0); // oder Schwarz
writeChar(0);
writeChar(0);
}
}
}
setLEDs(63); // ready
while(!(getBumperLeft() || getBumperRight())); // Neues Bild senden?
}
return(0);
}
Bild hier Bild hier Bild hier
Lesezeichen