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