Hallo Leute,

für die Experimentierplatine, die wir hier beschrieben haben:
https://www.roboternetz.de/phpBB2/ze...ag.php?t=53424
... und die hier:
http://www.rn-wissen.de/index.php/RP...itmach-Projekt
... gebaut wurde, hier ein zweites Programm für die M32. Es funktioniert ab der Phase 3 des Aufbaus.
Auf dem LCD wird die Zahl der CSync-Flanken bis zur 1. TV Zeile, die Anzahl der TV Zeilen und der Video Pegel der Austastlücke und einer TV Zeile angezeigt.
Code:
/* 
 * ****************************************************************************
 * RP6 ROBOT SYSTEM - RP6 CONTROL M32 TESTS
 * ****************************************************************************
 * Beispiel: Zählt die Video (TV) Zeilen einer CMOS Kamera
 * Autor(en): Dirk
 * ****************************************************************************
 * Beschreibung:
 *
 * Mit diesem Programm kann die Zeilenzahl einer CMOS Kamera (CONRAD 150001)
 * und die Zahl der CSync Flanken von VSync bis zur ersten TV Zeile auf dem
 * LCD angezeigt werden. Der Video Pegel der Austastlücke und einer TV Zeile
 * wird auch angezeigt.
 * Die Kamera ist an dieses Hardware Projekt (Phase 3 und höher) angeschlossen:
 *   http://www.rn-wissen.de/index.php/RP...itmach-Projekt
 * Die BAS Video Information (PG3) ist angeschlossen an ADC4 (M32 ADC Stecker,
 * Pin 3).
 * Die Synchronisationssignale sind wie folgt verbunden:
 *
 *	Signal		RP6 Name	Port	Funktion
 *	VSync		EINT2		PD3		INT1
 *	HSync		IO_PD6		PD6		ICP1
 *	Odd/Even	EINT3		PB2		INT2
 *
 * ############################################################################
 * Der Roboter bewegt sich NICHT in diesem Beispiel! Du kannst ihn einfach auf
 * einen Tisch neben deinen PC stellen und solltest ihn mit dem PC über das
 * USB-Interface verbinden!
 * ############################################################################
 * ****************************************************************************
 */

/*****************************************************************************/
// Einzufügende Dateien:

#include "RP6ControlLib.h" 		// Die RP6 Control Bibliothek. 
								// Muss immer eingefügt werden!

/*****************************************************************************/
// Definitionen:

#define FALLING		0					// Fallende Flanken
#define RISING		1					// Steigende Flanken
//-------------------------------
#define EDGE		FALLING				//<== Wähle FALLENDE oder
										//    STEIGENDE Flanken!
//-------------------------------

#define ODD			(1<<EINT3)			// Feld 1
#define EVEN		0					// Feld 2
//-------------------------------
#define FIELD		ODD					//<== Wähle Feld 1 oder Feld 2!
//-------------------------------

#define VIDEO_BLANK	108					//<== Passe den Video Pegel der
										//    Austastlücke an!

#define HSYNC		(PIND & IO_PD6)
#define VSYNC		(PIND & EINT2)
#define ODD_EVEN	(PINB & EINT3)
#define IRon()		(PORTC &= ~IO_PC6)
#define IRoff()		(PORTC |= IO_PC6)

/*****************************************************************************/
// Variablen:

volatile uint16_t edgecnt;
volatile uint16_t video;
volatile uint8_t tvlevelflag;
uint8_t field;
uint16_t blankedges;
uint16_t tvlines;
uint16_t videolevel_1;
uint16_t videolevel_2;

/*****************************************************************************/
// Funktionen:

/**
 * TIMER1 Capture ISR
 *
 * In dieser ISR werden die fallenden/steigenden Flanken des CSync Signals
 * ab VSync gezählt, und der Video Pegel wird einmal pro Zeile mit ADC4
 * gemessen. Im Hauptprogramm muss edgecnt direkt nach der fallenden
 * Flanke von VSync auf Null zurückgesetzt werden!
 * Die komplette Zeit der Messung vom Zeitpunkt des "Sample and Hold" bis
 * zum Ergebnis in ADC liegt in der ersten Hälfte der TV Zeile, weil
 * einige Impulse in der Austastlücke einen Abstand von ca. 32 µs (eine
 * halbe TV Zeile) haben. Daher darf die ISR nicht länger als eine halbe
 * TV Zeile dauern!
 * Der Video Pegel wird NICHT nach den ersten 10 CSync Flanken nach VSync
 * gemessen.
 *
 * Ausgabe: edgecnt     -> CSync Flankenzähler
 *          video       -> 10 Bit ADC Wert (Video Pegel)
 *          tvlevelflag -> true:  TV Zeile mit Video Inhalt
 *                         false: Austastlücke
 *
 * ACHTUNG: Die Konstante VIDEO_BLANK muss auf einen Video Pegel
 *          zwischen dem Pegel der Austastlücke und dem einer TV
 *          Zeile in einem völlig dunklen Raum angepaßt werden!
 *
 */
ISR (TIMER1_CAPT_vect)
{uint8_t h_delay;
	edgecnt++;
	tvlevelflag = false;
	if (edgecnt > 10) {
		h_delay=15; while (h_delay--) {nop();}; 
		ADMUX = (1<<REFS0) | (1<<REFS1) | (ADC_4<<MUX0);
		ADCSRA = (0<<ADIE) | (1<<ADSC) | (1<<ADEN)
		 | (1<<ADPS2) | (1<<ADPS1) | (1<<ADIF);
		while(ADCSRA & (1<<ADIF));
		ADCSRA |= (1<<ADIF);
		video = ADC;
		if (video > VIDEO_BLANK) tvlevelflag = true;
	}
}

/*****************************************************************************/
// Haupt Funktion - Das Programm beginnt hier:

int main(void)
{
	initRP6Control();

	initLCD();

	showScreenLCD("################", "################");
	mSleep(1500);
	showScreenLCD("<<RP6  Control>>", "<<LC - DISPLAY>>");
	mSleep(2500); 
	showScreenLCD(" Video Lines Cnt", "  Version 1.00  ");
	mSleep(2500);
	clearLCD();

	setLEDs(0b0000);
	
	// Initialisiere den M32 ICP Pin (PD6) als Eingang: 
	DDRD &= ~IO_PD6;					// ==> HSync
	PORTD |= IO_PD6;					// Pullup an
	// Initialisiere den M32 INT1 Pin (PD3) als Eingang: 
	DDRD &= ~EINT2;						// ==> VSync
	PORTD |= EINT2;						// Pullup an
	// Initialisiere den M32 INT2 Pin (PB2) als Eingang: 
	DDRB &= ~EINT3;						// ==> Odd/Even
	PORTB |= EINT3;						// Pullup an
	// Initialisiere den M32 TOSC1 Pin (PC6) als Ausgang: 
	DDRC |= IO_PC6;						// ==> IR
	IRoff();							// IR LEDs aus

	// Initialisiere die M32 Timer1 Input Capture Funktion:
 	TCCR1B = (1<<CS10)					// Trigger: Kein Vorteiler
	 | (1<<ICNC1);						//  und Noise Canceler
#if EDGE
	TCCR1B |= (1<<ICES1);				//  Steigende Flanke
#else
	TCCR1B &= ~(1<<ICES1);				//  Fallende Flanke
#endif
/*
// Zeige die ADC Werte der Austastlücke und einer TV Zeile:
//   Wenn man VIDEO_BLANK (für eine andere Kamera) anpassen will,
//   muss man diese Konstante auf einen Wert setzen, der zwischen
//   den beiden hier angezeigten Werten liegt. Das muss in einem
//   dunklen Raum gemacht werden, um einen sehr niedrigen TV
//   Video Pegel zu erreichen!
	TIMSK = (1<<TICIE1);				// Aktiviere Capture ISR
	while(true)
	{
		while(VSYNC);					// Warte auf Seitenanfang
		TIFR = (1<<ICF1);				// Lösche aktiven Interrupt
		edgecnt = 0;					// Flankenzähler zurücksetzen
		while(edgecnt < 18);			// Austastlücke!
		videolevel_2 = video;			// Speichere Pegel der Austastlücke
		while(edgecnt < 120);			// TV Zeilen Bereich!
		videolevel_1 = video;			// Speichere TV Video Pegel
		setCursorPosLCD(0, 0);
		writeStringLCD("Video Blank ");
		writeIntegerLengthLCD(videolevel_2, DEC, 3);
		setCursorPosLCD(1, 0);
		writeStringLCD("Video  TV   ");
		writeIntegerLengthLCD(videolevel_1, DEC, 3);
		while(!VSYNC);					// Warte auf VSync Highpegel
	}
*/	
// Zeige die Anzahl der CSync Flanken bis zur ersten TV Zeile,
// die Zahl der TV Zeilen, den Video Pegel der Austastlücke und
// einer TV Zeile an:
//   Wenn hier keine realistischen Werte angezeigt werden, muss
//   die Konstante VIDEO_BLANK (siehe oben!) angepaßt werden.
	while(true)
	{
		while(VSYNC);					// Warte auf Seitenanfang
		nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
		TIFR = (1<<ICF1);				// Lösche aktiven Interrupt
		edgecnt = 0;					// Flankenzähler zurücksetzen
		TIMSK = (1<<TICIE1);			// Aktiviere Capture ISR
		field = ODD_EVEN;				// Feld Nummer?
		if ((field && FIELD)
		 || ((!field) && (!FIELD))) { // Gewähltes Feld?
			tvlevelflag = false;
			while(!tvlevelflag);		// Zähle bis zur ersten TV Zeile
			blankedges = edgecnt;
			videolevel_1 = video;		// Speichere den TV Video Pegel
			blankedges--;				// HSync der ersten TV Zeile!
			while(tvlevelflag);			// Zähle bis zum Ende der TV Zeilen
			tvlines = edgecnt - blankedges;
			videolevel_2 = video;		// Speichere Pegel der Austastlücke
			tvlines--;					// Anzahl TV Zeilen!
			TIMSK &= ~(1<<TICIE1);		// Inaktiviere Capture ISR
			setCursorPosLCD(0, 0);
			writeStringLCD("Ebn");
			writeIntegerLengthLCD(blankedges, DEC, 3);
			setCursorPosLCD(0, 7);
			writeStringLCD("Ltv");
			writeIntegerLengthLCD(tvlines, DEC, 3);
			if (field) writeStringLCD(" :O"); // Zeige Odd/Even Feld
			else writeStringLCD(" :E");
			setCursorPosLCD(1, 0);
			writeStringLCD("Vbn");
			writeIntegerLengthLCD(videolevel_2, DEC, 3);
			setCursorPosLCD(1, 7);
			writeStringLCD("Vtv");
			writeIntegerLengthLCD(videolevel_1, DEC, 3);
#if (EDGE == FALLING)
			writeStringLCD(" :F");		// Zeige Falling/Rising Flanke
#else
			writeStringLCD(" :R");
#endif
			while(!VSYNC);				// Warte auf VSync Highpegel
		}
	}
	return 0;
}

/******************************************************************************
 * Additional info
 * ****************************************************************************
 * Changelog:
 * - v. 1.0 (initial release) 07.05.2010 by Dirk
 *
 * ****************************************************************************
 */

/*****************************************************************************/
Viel Spaß!

Gruß Dirk