<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Thorstenw</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Thorstenw"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Thorstenw"/>
	<updated>2026-04-12T08:53:09Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40214</id>
		<title>Scalable FPGA Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40214"/>
		<updated>2009-10-27T11:53:04Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Spannungsversorgung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;AT91SAM7 FPGA Board &#039;von Thorsten W.&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt soll dazu dienen ein Basis Projekt zu schaffen, bei dem ein Microcontroller und ein FPGA zum Einsatz kommen. Dabei soll der Microcontroller per USB mit dem PC kommunizieren und ein FPGA zum Einsatz kommen. Der FPGA wird über den Microncontroller geladen. Auf Steck-Modulen sollen dann die eigentlichen Schnittstellen implementiert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Liste von Features:&lt;br /&gt;
&lt;br /&gt;
* 32 Bit Microcontroller mit USB&lt;br /&gt;
* kleiner FPGA&lt;br /&gt;
* FPGA und Microcontroller per SPI verbunden&lt;br /&gt;
* zwei SD-Karten als Massenspeicher&lt;br /&gt;
* Microcontroller lädt den FPGA&lt;br /&gt;
&lt;br /&gt;
Projekt Status: Planung&lt;br /&gt;
&lt;br /&gt;
Next: Spannungs versorgung planen&lt;br /&gt;
&lt;br /&gt;
Todo: &lt;br /&gt;
 - Taktgewinnung für FPGA und MCU (48 MHz, wegen USB für MCU)&lt;br /&gt;
 - Debug und Test Möglichkeiten vorsehen&lt;br /&gt;
 - Schnittstellen zwischen MCU und FPGA definieren&lt;br /&gt;
 - genutzte MCU Schnittstellen &lt;br /&gt;
 - freie MCU Schnittstellen auflisten&lt;br /&gt;
 - freie FPGA-Ports abschätzen&lt;br /&gt;
 - Partitionierung der vorhandenen Resourcen auf homogene Konnektoren&lt;br /&gt;
 - Schaltplan Erstelleung&lt;br /&gt;
 - Test Software für FPGA schreiben und simulieren&lt;br /&gt;
 - MCU Code zusammen stellen, der die FPGA schnittstellen nutzen würde. Testprogramm zur Inbetriebnahme, FPGA per MUC laden&lt;br /&gt;
 - Design von Erweiterungs Platinen: RS232, CAN, USB, Ethernet, LWL&lt;br /&gt;
 - Platine routen&lt;br /&gt;
 - Musteraufbau&lt;br /&gt;
 - Inbetriebname&lt;br /&gt;
 - Applikative SW&lt;br /&gt;
&lt;br /&gt;
== Motivation ==&lt;br /&gt;
Typische FPGA Projekte implementieren die CPU im FPGA und verschwenden wertvolle universelle FPGA Hardware. Einen zusätzlichen Chip zum Laden des FPGAs muss man so oder so investieren. Die einfache Lösung ist hier einen FTDI-Chip zu verwenden. Dieses Projekt soll diesen Ansatz ein wenig erweitern, indem ein Microcontroller benutzt wird um mit dem PC zu kommunizieren. Die Aufteilung, was im Microcontroller und was im FPGA implementiert wird, kann später verfeinert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
Gesetzt sind, ein AT91SAM7S256 (oder pin-kompatibel) und XC3S50. Microcontroller und FPGA sind über SPI verbunden, so kann der Controller per DMA Daten aus dem FPGA lesen und schreiben. Diese Daten bilden ein memory mapped I/O Interface nach.&lt;br /&gt;
&lt;br /&gt;
TODO: Alternativ wäre ein 8bit MMIO Interface denkbar, gibt es einen AT91 Pin kompatiblen Typen, der das kann?&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
&lt;br /&gt;
Betrieben werden, soll die Schaltung über USB, der Microcontroller meldet sich am BUS an und schaltet dann die Spannungen für den FPGA ein. Zustzlich soll eine Externe Spannungsversorgung möglich sein, wenn die Schaltung (abhängig vom FPGA und den Erweiterungen) mehr als die erlaubten 500mA benötigt.&lt;br /&gt;
&lt;br /&gt;
Spannungsregler:&lt;br /&gt;
 - LM 1086 IT3,3 (1,5 A, etwa 1,10 EUR, 2,5 V 3,3 V&lt;br /&gt;
 - LM 317        (LM 317-220, 0,43 EUR 1,2 bis 37V, nicht low drop)&lt;br /&gt;
&lt;br /&gt;
=== Schnittstellen ===&lt;br /&gt;
&lt;br /&gt;
USB vom AT91. SPI an FPGA. Restliche I/O und Schnittstellen des Micro controller werden per Stiftleiste heraus geführt.&lt;br /&gt;
&lt;br /&gt;
An einem weiteren SPI des Microcontrollers soll eine SD-Karte angeschlossen werden, damit die MCU den FPGA autonom laden kann. &lt;br /&gt;
&lt;br /&gt;
Für den FPGA sollte ein DDRAM-Chip und eine weitere SD-Karte eingeplant werden.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Beschreibung der Software&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Sourcecode: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Kategorie:FPGA| ]] Wenn es fertig ist--&amp;gt;&lt;br /&gt;
[[Category:Projekte| ]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40213</id>
		<title>Scalable FPGA Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40213"/>
		<updated>2009-10-27T11:47:06Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Spannungsversorgung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;AT91SAM7 FPGA Board &#039;von Thorsten W.&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt soll dazu dienen ein Basis Projekt zu schaffen, bei dem ein Microcontroller und ein FPGA zum Einsatz kommen. Dabei soll der Microcontroller per USB mit dem PC kommunizieren und ein FPGA zum Einsatz kommen. Der FPGA wird über den Microncontroller geladen. Auf Steck-Modulen sollen dann die eigentlichen Schnittstellen implementiert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Liste von Features:&lt;br /&gt;
&lt;br /&gt;
* 32 Bit Microcontroller mit USB&lt;br /&gt;
* kleiner FPGA&lt;br /&gt;
* FPGA und Microcontroller per SPI verbunden&lt;br /&gt;
* zwei SD-Karten als Massenspeicher&lt;br /&gt;
* Microcontroller lädt den FPGA&lt;br /&gt;
&lt;br /&gt;
Projekt Status: Planung&lt;br /&gt;
&lt;br /&gt;
Next: Spannungs versorgung planen&lt;br /&gt;
&lt;br /&gt;
Todo: &lt;br /&gt;
 - Taktgewinnung für FPGA und MCU (48 MHz, wegen USB für MCU)&lt;br /&gt;
 - Debug und Test Möglichkeiten vorsehen&lt;br /&gt;
 - Schnittstellen zwischen MCU und FPGA definieren&lt;br /&gt;
 - genutzte MCU Schnittstellen &lt;br /&gt;
 - freie MCU Schnittstellen auflisten&lt;br /&gt;
 - freie FPGA-Ports abschätzen&lt;br /&gt;
 - Partitionierung der vorhandenen Resourcen auf homogene Konnektoren&lt;br /&gt;
 - Schaltplan Erstelleung&lt;br /&gt;
 - Test Software für FPGA schreiben und simulieren&lt;br /&gt;
 - MCU Code zusammen stellen, der die FPGA schnittstellen nutzen würde. Testprogramm zur Inbetriebnahme, FPGA per MUC laden&lt;br /&gt;
 - Design von Erweiterungs Platinen: RS232, CAN, USB, Ethernet, LWL&lt;br /&gt;
 - Platine routen&lt;br /&gt;
 - Musteraufbau&lt;br /&gt;
 - Inbetriebname&lt;br /&gt;
 - Applikative SW&lt;br /&gt;
&lt;br /&gt;
== Motivation ==&lt;br /&gt;
Typische FPGA Projekte implementieren die CPU im FPGA und verschwenden wertvolle universelle FPGA Hardware. Einen zusätzlichen Chip zum Laden des FPGAs muss man so oder so investieren. Die einfache Lösung ist hier einen FTDI-Chip zu verwenden. Dieses Projekt soll diesen Ansatz ein wenig erweitern, indem ein Microcontroller benutzt wird um mit dem PC zu kommunizieren. Die Aufteilung, was im Microcontroller und was im FPGA implementiert wird, kann später verfeinert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
Gesetzt sind, ein AT91SAM7S256 (oder pin-kompatibel) und XC3S50. Microcontroller und FPGA sind über SPI verbunden, so kann der Controller per DMA Daten aus dem FPGA lesen und schreiben. Diese Daten bilden ein memory mapped I/O Interface nach.&lt;br /&gt;
&lt;br /&gt;
TODO: Alternativ wäre ein 8bit MMIO Interface denkbar, gibt es einen AT91 Pin kompatiblen Typen, der das kann?&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
&lt;br /&gt;
Betrieben werden, soll die Schaltung über USB, der Microcontroller meldet sich am BUS an und schaltet dann die Spannungen für den FPGA ein. Zustzlich soll eine Externe Spannungsversorgung möglich sein, wenn die Schaltung (abhängig vom FPGA und den Erweiterungen) mehr als die erlaubten 500mA benötigt.&lt;br /&gt;
&lt;br /&gt;
Spannungsregler:&lt;br /&gt;
 - LM 1086 IT3,3 (1,5 A, etwa 1,10 EUR, 2,5 V 3,3 V&lt;br /&gt;
&lt;br /&gt;
=== Schnittstellen ===&lt;br /&gt;
&lt;br /&gt;
USB vom AT91. SPI an FPGA. Restliche I/O und Schnittstellen des Micro controller werden per Stiftleiste heraus geführt.&lt;br /&gt;
&lt;br /&gt;
An einem weiteren SPI des Microcontrollers soll eine SD-Karte angeschlossen werden, damit die MCU den FPGA autonom laden kann. &lt;br /&gt;
&lt;br /&gt;
Für den FPGA sollte ein DDRAM-Chip und eine weitere SD-Karte eingeplant werden.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Beschreibung der Software&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Sourcecode: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Kategorie:FPGA| ]] Wenn es fertig ist--&amp;gt;&lt;br /&gt;
[[Category:Projekte| ]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40212</id>
		<title>Scalable FPGA Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40212"/>
		<updated>2009-10-27T09:40:40Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Einleitung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;AT91SAM7 FPGA Board &#039;von Thorsten W.&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt soll dazu dienen ein Basis Projekt zu schaffen, bei dem ein Microcontroller und ein FPGA zum Einsatz kommen. Dabei soll der Microcontroller per USB mit dem PC kommunizieren und ein FPGA zum Einsatz kommen. Der FPGA wird über den Microncontroller geladen. Auf Steck-Modulen sollen dann die eigentlichen Schnittstellen implementiert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Liste von Features:&lt;br /&gt;
&lt;br /&gt;
* 32 Bit Microcontroller mit USB&lt;br /&gt;
* kleiner FPGA&lt;br /&gt;
* FPGA und Microcontroller per SPI verbunden&lt;br /&gt;
* zwei SD-Karten als Massenspeicher&lt;br /&gt;
* Microcontroller lädt den FPGA&lt;br /&gt;
&lt;br /&gt;
Projekt Status: Planung&lt;br /&gt;
&lt;br /&gt;
Next: Spannungs versorgung planen&lt;br /&gt;
&lt;br /&gt;
Todo: &lt;br /&gt;
 - Taktgewinnung für FPGA und MCU (48 MHz, wegen USB für MCU)&lt;br /&gt;
 - Debug und Test Möglichkeiten vorsehen&lt;br /&gt;
 - Schnittstellen zwischen MCU und FPGA definieren&lt;br /&gt;
 - genutzte MCU Schnittstellen &lt;br /&gt;
 - freie MCU Schnittstellen auflisten&lt;br /&gt;
 - freie FPGA-Ports abschätzen&lt;br /&gt;
 - Partitionierung der vorhandenen Resourcen auf homogene Konnektoren&lt;br /&gt;
 - Schaltplan Erstelleung&lt;br /&gt;
 - Test Software für FPGA schreiben und simulieren&lt;br /&gt;
 - MCU Code zusammen stellen, der die FPGA schnittstellen nutzen würde. Testprogramm zur Inbetriebnahme, FPGA per MUC laden&lt;br /&gt;
 - Design von Erweiterungs Platinen: RS232, CAN, USB, Ethernet, LWL&lt;br /&gt;
 - Platine routen&lt;br /&gt;
 - Musteraufbau&lt;br /&gt;
 - Inbetriebname&lt;br /&gt;
 - Applikative SW&lt;br /&gt;
&lt;br /&gt;
== Motivation ==&lt;br /&gt;
Typische FPGA Projekte implementieren die CPU im FPGA und verschwenden wertvolle universelle FPGA Hardware. Einen zusätzlichen Chip zum Laden des FPGAs muss man so oder so investieren. Die einfache Lösung ist hier einen FTDI-Chip zu verwenden. Dieses Projekt soll diesen Ansatz ein wenig erweitern, indem ein Microcontroller benutzt wird um mit dem PC zu kommunizieren. Die Aufteilung, was im Microcontroller und was im FPGA implementiert wird, kann später verfeinert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
Gesetzt sind, ein AT91SAM7S256 (oder pin-kompatibel) und XC3S50. Microcontroller und FPGA sind über SPI verbunden, so kann der Controller per DMA Daten aus dem FPGA lesen und schreiben. Diese Daten bilden ein memory mapped I/O Interface nach.&lt;br /&gt;
&lt;br /&gt;
TODO: Alternativ wäre ein 8bit MMIO Interface denkbar, gibt es einen AT91 Pin kompatiblen Typen, der das kann?&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
&lt;br /&gt;
Betrieben werden, soll die Schaltung über USB, der Microcontroller meldet sich am BUS an und schaltet dann die Spannungen für den FPGA ein. Zustzlich soll eine Externe Spannungsversorgung möglich sein, wenn die Schaltung (abhängig vom FPGA und den Erweiterungen) mehr als die erlaubten 500mA benötigt.&lt;br /&gt;
&lt;br /&gt;
Spannungsregler:&lt;br /&gt;
 - LM 1086 IT3,3 (1,5 A, etwa 1,10 EUR, 2,5 V 3,3 V&lt;br /&gt;
 - LM 317        (LM 317-220, 0,43 EUR 1,2 bis 37V, nicht low drop)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstellen ===&lt;br /&gt;
&lt;br /&gt;
USB vom AT91. SPI an FPGA. Restliche I/O und Schnittstellen des Micro controller werden per Stiftleiste heraus geführt.&lt;br /&gt;
&lt;br /&gt;
An einem weiteren SPI des Microcontrollers soll eine SD-Karte angeschlossen werden, damit die MCU den FPGA autonom laden kann. &lt;br /&gt;
&lt;br /&gt;
Für den FPGA sollte ein DDRAM-Chip und eine weitere SD-Karte eingeplant werden.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Beschreibung der Software&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Sourcecode: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Kategorie:FPGA| ]] Wenn es fertig ist--&amp;gt;&lt;br /&gt;
[[Category:Projekte| ]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40211</id>
		<title>Scalable FPGA Board</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Scalable_FPGA_Board&amp;diff=40211"/>
		<updated>2009-10-27T09:39:53Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Die Seite wurde neu angelegt: „&amp;#039;AT91SAM7 FPGA Board &amp;#039;von Thorsten W.&amp;#039;&amp;#039;   == Einleitung ==  Dieses Projekt soll dazu dienen ein Basis Projekt zu schaffen, bei dem ein Microcontroller und ein FPG…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;AT91SAM7 FPGA Board &#039;von Thorsten W.&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dieses Projekt soll dazu dienen ein Basis Projekt zu schaffen, bei dem ein Microcontroller und ein FPGA zum Einsatz kommen. Dabei soll der Microcontroller per USB mit dem PC kommunizieren und ein FPGA zum Einsatz kommen. Der FPGA wird über den Microncontroller geladen. Auf Steck-Modulen sollen dann die eigentlichen Schnittstellen implementiert werden.&lt;br /&gt;
&lt;br /&gt;
Eine Liste von Features:&lt;br /&gt;
&lt;br /&gt;
* 32 Bit Microcontroller mit USB&lt;br /&gt;
* kleiner FPGA&lt;br /&gt;
* FPGA und Microcontroller per SPI verbunden&lt;br /&gt;
* zwei SD-Karten als Massenspeicher&lt;br /&gt;
* Microcontroller lädt den FPGA&lt;br /&gt;
&lt;br /&gt;
Projekt Status: Planung&lt;br /&gt;
&lt;br /&gt;
Next: Spannungs versorgung planen&lt;br /&gt;
Todo: &lt;br /&gt;
 - Taktgewinnung für FPGA und MCU (48 MHz, wegen USB für MCU)&lt;br /&gt;
 - Debug und Test Möglichkeiten vorsehen&lt;br /&gt;
 - Schnittstellen zwischen MCU und FPGA definieren&lt;br /&gt;
 - genutzte MCU Schnittstellen &lt;br /&gt;
 - freie MCU Schnittstellen auflisten&lt;br /&gt;
 - freie FPGA-Ports abschätzen&lt;br /&gt;
 - Partitionierung der vorhandenen Resourcen auf homogene Konnektoren&lt;br /&gt;
 - Schaltplan Erstelleung&lt;br /&gt;
 - Test Software für FPGA schreiben und simulieren&lt;br /&gt;
 - MCU Code zusammen stellen, der die FPGA schnittstellen nutzen würde. Testprogramm zur Inbetriebnahme, FPGA per MUC laden&lt;br /&gt;
 - Design von Erweiterungs Platinen: RS232, CAN, USB, Ethernet, LWL&lt;br /&gt;
 - Platine routen&lt;br /&gt;
 - Musteraufbau&lt;br /&gt;
 - Inbetriebname&lt;br /&gt;
 - Applikative SW&lt;br /&gt;
&lt;br /&gt;
== Motivation ==&lt;br /&gt;
Typische FPGA Projekte implementieren die CPU im FPGA und verschwenden wertvolle universelle FPGA Hardware. Einen zusätzlichen Chip zum Laden des FPGAs muss man so oder so investieren. Die einfache Lösung ist hier einen FTDI-Chip zu verwenden. Dieses Projekt soll diesen Ansatz ein wenig erweitern, indem ein Microcontroller benutzt wird um mit dem PC zu kommunizieren. Die Aufteilung, was im Microcontroller und was im FPGA implementiert wird, kann später verfeinert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
Gesetzt sind, ein AT91SAM7S256 (oder pin-kompatibel) und XC3S50. Microcontroller und FPGA sind über SPI verbunden, so kann der Controller per DMA Daten aus dem FPGA lesen und schreiben. Diese Daten bilden ein memory mapped I/O Interface nach.&lt;br /&gt;
&lt;br /&gt;
TODO: Alternativ wäre ein 8bit MMIO Interface denkbar, gibt es einen AT91 Pin kompatiblen Typen, der das kann?&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgung ===&lt;br /&gt;
&lt;br /&gt;
Betrieben werden, soll die Schaltung über USB, der Microcontroller meldet sich am BUS an und schaltet dann die Spannungen für den FPGA ein. Zustzlich soll eine Externe Spannungsversorgung möglich sein, wenn die Schaltung (abhängig vom FPGA und den Erweiterungen) mehr als die erlaubten 500mA benötigt.&lt;br /&gt;
&lt;br /&gt;
Spannungsregler:&lt;br /&gt;
 - LM 1086 IT3,3 (1,5 A, etwa 1,10 EUR, 2,5 V 3,3 V&lt;br /&gt;
 - LM 317        (LM 317-220, 0,43 EUR 1,2 bis 37V, nicht low drop)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schnittstellen ===&lt;br /&gt;
&lt;br /&gt;
USB vom AT91. SPI an FPGA. Restliche I/O und Schnittstellen des Micro controller werden per Stiftleiste heraus geführt.&lt;br /&gt;
&lt;br /&gt;
An einem weiteren SPI des Microcontrollers soll eine SD-Karte angeschlossen werden, damit die MCU den FPGA autonom laden kann. &lt;br /&gt;
&lt;br /&gt;
Für den FPGA sollte ein DDRAM-Chip und eine weitere SD-Karte eingeplant werden.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Beschreibung der Software&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Sourcecode: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Kategorie:FPGA| ]] Wenn es fertig ist--&amp;gt;&lt;br /&gt;
[[Category:Projekte| ]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Programmierbare_Logik&amp;diff=40210</id>
		<title>Programmierbare Logik</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Programmierbare_Logik&amp;diff=40210"/>
		<updated>2009-10-27T08:47:25Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Entwicklungsboards */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programmierbare Logik ist eine Möglichkeit, digitale Schaltungen nahezu beliebiger Komplexität von der Digitaluhr über die eigene CPU bis zur Mobilfunk-Basisstation mit einzelnen, preiswerten, integrierten Schaltkreisen aufzubauen. &lt;br /&gt;
&lt;br /&gt;
Die Historie der programmierbaren digitalen Logik reicht von den starren ICs der 74***-Reihe über die schon programmierbaren &amp;quot;Urväter&amp;quot; [[GAL]] und [[PAL]] zu den heute oft eingesetzten [[CPLD]]s zu Hochleistungs-[[FPGA]]s mit intergrierter PowerPC-CPU. &lt;br /&gt;
Heute meint man mit Programmierbarer Logik Bausteine, die in einer Hochsprache wie [[VHDL]] oder [[Verilog]] beschrieben werden, also [[CPLD]]s oder [[FPGA]]s.&lt;br /&gt;
&lt;br /&gt;
Obwohl die Entwicklungsarbeit an einem FPGA der an einem Mikrocontroller ähnelt, sind FPGA- und Software-Entwicklung grundverschiedene Lösungsansätze.&lt;br /&gt;
&lt;br /&gt;
== Hardwarebeschreibungssprachen und Simulation allgemein ==&lt;br /&gt;
&lt;br /&gt;
* [[Hardwarebeschreibungssprachen|Übersicht zu VHDL, Verilog, ABEL etc.]]&lt;br /&gt;
* [http://www.symphonyeda.com/ Ein VHDL Simulator für Linux und Windows, auch mit kostenloser Lizenz] &lt;br /&gt;
* [http://ghdl.free.fr/ OpenSource VHDL Simulator unter GPL für Linux &amp;amp; Windows]&lt;br /&gt;
* [http://icarus.com/eda/verilog/ OpenSource Verilog Simulator unter GPL für Linux &amp;amp; Windows]&lt;br /&gt;
* [[ModelSim| Praxistipps zu ModelSim]]&lt;br /&gt;
* [http://home.nc.rr.com/gtkwave/ GTKWave] ist ein Program mit dem man .vcd Signal dumps ansehen kann. Es ist gerade interessant wenn man Simulatoren wie z.B. ghdl oder Icarus Verilog benutzt, die keine eigene GUI haben.&lt;br /&gt;
&lt;br /&gt;
==Synthese Digitaler Schaltungen, Electronic Design Automatisation (EDA)==&lt;br /&gt;
&lt;br /&gt;
* [[FPGA/CPLD Toolchain | Allgemeine Beschreibung der Arbeitsweise von Synthesewerkzeugen]]&lt;br /&gt;
* [http://www.xilinx.com/ise/logic_design_prod/webpack.htm Xilinx ISE Webpack]&lt;br /&gt;
** es wird empfohlen, ISE Classic 6.3 mit dem Service Pack 3 zu nutzen (nur Windows, keine Linux-Unterstützung), spart Downloadzeit und Nerven, da die Nachfolgeversionen 7..9 riesig und relativ fehlerträchtig sind (Stand 01/2008)&lt;br /&gt;
** [[Xilinx_ISE|Fehler einkreisen]]&lt;br /&gt;
** [[Xilinx ISE: Hinweise zu Versionen|Bugs &amp;amp; Features der einzelnen ISE-Versionen]]&lt;br /&gt;
** [[Xilinx_ISE_Linux|ISE unter Linux]]&lt;br /&gt;
** [[Xilinx_ISE_Tutorial|ISE Tutorial]]&lt;br /&gt;
* [http://www.altera.com/products/software/products/quartus2/qts-index.html Altera Quartus II]&lt;br /&gt;
** [http://www.mikrocontroller.net/forum/read-9-387954.html Timing mit Quartus II:]&lt;br /&gt;
* [http://www.latticesemi.com/products/designsoftware/isplever/index.cfm Lattice ispLEVER]&lt;br /&gt;
* [http://www.actel.com/products/software/default.aspx Actel Libero]&lt;br /&gt;
&lt;br /&gt;
==Beschaltung/Inbetriebnahme/Konfiguration FPGAs==&lt;br /&gt;
&lt;br /&gt;
===Konfiguration allgemein===&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-293892.html Kopierschutz des FPGA Konfigurationsspeichers]&lt;br /&gt;
&lt;br /&gt;
===Konfiguration (Download) Xilinx===&lt;br /&gt;
&lt;br /&gt;
* [[Impact_mask|Fehler bei Konfiguration: &amp;quot;*.mask not found&amp;quot;]]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-395732.html Spannung ROM/FPGA Spartan3]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-385079.html USB Programmierkabel unter Linux]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-360045.html Spartan2 Konfiguration per JTAG beschalten]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-286219.html Selbstbau Programmierkabel]&lt;br /&gt;
* [http://www.geocities.com/jacquesmartini/digital/schematic/Parallel_Cable_III.png Parallel Cable III, verbesserte Version, für alle Xilinxbausteine]&lt;br /&gt;
&lt;br /&gt;
===Konfiguration Altera===&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-282738.html Selbstbau Programmierkabel]&lt;br /&gt;
&lt;br /&gt;
===Beschaltung allgemein===&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-330299.html Stromaufnahme von FPGAs]&lt;br /&gt;
&lt;br /&gt;
===Beschaltung Xilinx===&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-328386.html Spannungsregler für Spartan3]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-291474.html Unterschiede Spartan3/3E]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-306733.html XC95xxx CPLD: Beschaltung Quarz/Oszillator]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-294326.html Probleme beim Programmieren XC95xxx]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-285009.html Spartan2 Programmierfehler durch falsches PowerUp]&lt;br /&gt;
&lt;br /&gt;
== FPGA/CPLD Aufbau und Funktion ==&lt;br /&gt;
&lt;br /&gt;
* [[CPLD]]&lt;br /&gt;
* [[FPGA]]&lt;br /&gt;
&lt;br /&gt;
=== Xilinx-FPGA Designs ===&lt;br /&gt;
&lt;br /&gt;
*[[MicroBlaze Takt|MicroBlaze max. Taktfrequenz und Leistung]]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-393058.html MicroBlaze Timingprobleme]&lt;br /&gt;
&lt;br /&gt;
==Entwicklungsboards==&lt;br /&gt;
&lt;br /&gt;
*[[FPGA#Entwicklungsboards|FPGA-Evalboards verschiedener Hersteller]]&lt;br /&gt;
&lt;br /&gt;
*Kleines CPLD Experimentiersystem im Selbstbau [http://www.mikrocontroller.net/topic/116702]&lt;br /&gt;
&lt;br /&gt;
* [[Scalable FPGA Board]]&lt;br /&gt;
&lt;br /&gt;
==Bücher/Links==&lt;br /&gt;
&lt;br /&gt;
* [http://old.xess.com/ho03000.html Tutorials, Beispieldesigns, Makefiles -&amp;gt; eine Fundgrube! (alter Link)]&lt;br /&gt;
* [http://www.alse-fr.com/English/ips.html Beispielcores, Application Notes zu UART,LCD,PWM,Quiz zu VHDL]&lt;br /&gt;
* [http://www.doulos.com/knowhow/vhdl_designers_guide/ Nette Monthly VHDL Columne]&lt;br /&gt;
* [http://www.fpga4fun.com/ Nette kleine Projekte von RS232, I2C, 10BaseT, PCI, bis Oszilloskope]&lt;br /&gt;
*Dokumente über Verilog und System Verilog &lt;br /&gt;
** http://www.sunburst-design.com/papers/&lt;br /&gt;
** http://www.sutherland-hdl.com/papers.html&lt;br /&gt;
* [http://mikro.e-technik.uni-ulm.de/vhdl/vhdl_infos.html VHDL Kurzanleitung und Anleitung zur Synthese/Optimierung - Link geht nicht]&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
&lt;br /&gt;
Immer wieder wird hier nach einem guten VHDL Editor gefragt. Zu Empfehlen ist der Crimson Editor, wer etwas mehr Power mag (allerdings auch mehr Einarbeitungszeit) nimmt Emacs. Emacs gibt es für Linux, Unix, und auch für [http://www.gnu.org/software/emacs/windows/ntemacs.html Windows].&lt;br /&gt;
Sehr empfehlen kann ich noch die [http://ecb.sourceforge.net/ ECB Erweiterung]. Unter Debian GNU Linux ist Emacs und ECB enthalten! Emacs ist sehr mächtig, leider ist die Lernkurve anfangs sehr flach. Hier gibt es ein [http://book.chinaunix.net/special/ebook/oreilly/LearningGnuEmacs/ eBook] zu Emacs. &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/9 Bereich FPGA, VHDL &amp;amp; Co. auf mikrocontroller.net]&lt;br /&gt;
&lt;br /&gt;
== Artikel aus der Kategorie FPGA &amp;amp; Co. ==&lt;br /&gt;
&amp;lt;ncl style=compact maxdepth=2 headings=bullet headstart=2&lt;br /&gt;
      showcats=1 showarts=1&amp;gt;FPGA und Co&amp;lt;/ncl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA und Co]]&lt;br /&gt;
__NOTOC__&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Programmierbare_Logik&amp;diff=40209</id>
		<title>Programmierbare Logik</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Programmierbare_Logik&amp;diff=40209"/>
		<updated>2009-10-27T08:47:00Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Entwicklungsboards */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Programmierbare Logik ist eine Möglichkeit, digitale Schaltungen nahezu beliebiger Komplexität von der Digitaluhr über die eigene CPU bis zur Mobilfunk-Basisstation mit einzelnen, preiswerten, integrierten Schaltkreisen aufzubauen. &lt;br /&gt;
&lt;br /&gt;
Die Historie der programmierbaren digitalen Logik reicht von den starren ICs der 74***-Reihe über die schon programmierbaren &amp;quot;Urväter&amp;quot; [[GAL]] und [[PAL]] zu den heute oft eingesetzten [[CPLD]]s zu Hochleistungs-[[FPGA]]s mit intergrierter PowerPC-CPU. &lt;br /&gt;
Heute meint man mit Programmierbarer Logik Bausteine, die in einer Hochsprache wie [[VHDL]] oder [[Verilog]] beschrieben werden, also [[CPLD]]s oder [[FPGA]]s.&lt;br /&gt;
&lt;br /&gt;
Obwohl die Entwicklungsarbeit an einem FPGA der an einem Mikrocontroller ähnelt, sind FPGA- und Software-Entwicklung grundverschiedene Lösungsansätze.&lt;br /&gt;
&lt;br /&gt;
== Hardwarebeschreibungssprachen und Simulation allgemein ==&lt;br /&gt;
&lt;br /&gt;
* [[Hardwarebeschreibungssprachen|Übersicht zu VHDL, Verilog, ABEL etc.]]&lt;br /&gt;
* [http://www.symphonyeda.com/ Ein VHDL Simulator für Linux und Windows, auch mit kostenloser Lizenz] &lt;br /&gt;
* [http://ghdl.free.fr/ OpenSource VHDL Simulator unter GPL für Linux &amp;amp; Windows]&lt;br /&gt;
* [http://icarus.com/eda/verilog/ OpenSource Verilog Simulator unter GPL für Linux &amp;amp; Windows]&lt;br /&gt;
* [[ModelSim| Praxistipps zu ModelSim]]&lt;br /&gt;
* [http://home.nc.rr.com/gtkwave/ GTKWave] ist ein Program mit dem man .vcd Signal dumps ansehen kann. Es ist gerade interessant wenn man Simulatoren wie z.B. ghdl oder Icarus Verilog benutzt, die keine eigene GUI haben.&lt;br /&gt;
&lt;br /&gt;
==Synthese Digitaler Schaltungen, Electronic Design Automatisation (EDA)==&lt;br /&gt;
&lt;br /&gt;
* [[FPGA/CPLD Toolchain | Allgemeine Beschreibung der Arbeitsweise von Synthesewerkzeugen]]&lt;br /&gt;
* [http://www.xilinx.com/ise/logic_design_prod/webpack.htm Xilinx ISE Webpack]&lt;br /&gt;
** es wird empfohlen, ISE Classic 6.3 mit dem Service Pack 3 zu nutzen (nur Windows, keine Linux-Unterstützung), spart Downloadzeit und Nerven, da die Nachfolgeversionen 7..9 riesig und relativ fehlerträchtig sind (Stand 01/2008)&lt;br /&gt;
** [[Xilinx_ISE|Fehler einkreisen]]&lt;br /&gt;
** [[Xilinx ISE: Hinweise zu Versionen|Bugs &amp;amp; Features der einzelnen ISE-Versionen]]&lt;br /&gt;
** [[Xilinx_ISE_Linux|ISE unter Linux]]&lt;br /&gt;
** [[Xilinx_ISE_Tutorial|ISE Tutorial]]&lt;br /&gt;
* [http://www.altera.com/products/software/products/quartus2/qts-index.html Altera Quartus II]&lt;br /&gt;
** [http://www.mikrocontroller.net/forum/read-9-387954.html Timing mit Quartus II:]&lt;br /&gt;
* [http://www.latticesemi.com/products/designsoftware/isplever/index.cfm Lattice ispLEVER]&lt;br /&gt;
* [http://www.actel.com/products/software/default.aspx Actel Libero]&lt;br /&gt;
&lt;br /&gt;
==Beschaltung/Inbetriebnahme/Konfiguration FPGAs==&lt;br /&gt;
&lt;br /&gt;
===Konfiguration allgemein===&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-293892.html Kopierschutz des FPGA Konfigurationsspeichers]&lt;br /&gt;
&lt;br /&gt;
===Konfiguration (Download) Xilinx===&lt;br /&gt;
&lt;br /&gt;
* [[Impact_mask|Fehler bei Konfiguration: &amp;quot;*.mask not found&amp;quot;]]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-395732.html Spannung ROM/FPGA Spartan3]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-385079.html USB Programmierkabel unter Linux]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-360045.html Spartan2 Konfiguration per JTAG beschalten]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-286219.html Selbstbau Programmierkabel]&lt;br /&gt;
* [http://www.geocities.com/jacquesmartini/digital/schematic/Parallel_Cable_III.png Parallel Cable III, verbesserte Version, für alle Xilinxbausteine]&lt;br /&gt;
&lt;br /&gt;
===Konfiguration Altera===&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-282738.html Selbstbau Programmierkabel]&lt;br /&gt;
&lt;br /&gt;
===Beschaltung allgemein===&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-330299.html Stromaufnahme von FPGAs]&lt;br /&gt;
&lt;br /&gt;
===Beschaltung Xilinx===&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-328386.html Spannungsregler für Spartan3]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-291474.html Unterschiede Spartan3/3E]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-306733.html XC95xxx CPLD: Beschaltung Quarz/Oszillator]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-294326.html Probleme beim Programmieren XC95xxx]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-285009.html Spartan2 Programmierfehler durch falsches PowerUp]&lt;br /&gt;
&lt;br /&gt;
== FPGA/CPLD Aufbau und Funktion ==&lt;br /&gt;
&lt;br /&gt;
* [[CPLD]]&lt;br /&gt;
* [[FPGA]]&lt;br /&gt;
&lt;br /&gt;
=== Xilinx-FPGA Designs ===&lt;br /&gt;
&lt;br /&gt;
*[[MicroBlaze Takt|MicroBlaze max. Taktfrequenz und Leistung]]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-9-393058.html MicroBlaze Timingprobleme]&lt;br /&gt;
&lt;br /&gt;
==Entwicklungsboards==&lt;br /&gt;
&lt;br /&gt;
*[[FPGA#Entwicklungsboards|FPGA-Evalboards verschiedener Hersteller]]&lt;br /&gt;
&lt;br /&gt;
*Kleines CPLD Experimentiersystem im Selbstbau [http://www.mikrocontroller.net/topic/116702]&lt;br /&gt;
&lt;br /&gt;
* [[FPGA#BasisBoard|Scalable FPGA Board]]&lt;br /&gt;
&lt;br /&gt;
==Bücher/Links==&lt;br /&gt;
&lt;br /&gt;
* [http://old.xess.com/ho03000.html Tutorials, Beispieldesigns, Makefiles -&amp;gt; eine Fundgrube! (alter Link)]&lt;br /&gt;
* [http://www.alse-fr.com/English/ips.html Beispielcores, Application Notes zu UART,LCD,PWM,Quiz zu VHDL]&lt;br /&gt;
* [http://www.doulos.com/knowhow/vhdl_designers_guide/ Nette Monthly VHDL Columne]&lt;br /&gt;
* [http://www.fpga4fun.com/ Nette kleine Projekte von RS232, I2C, 10BaseT, PCI, bis Oszilloskope]&lt;br /&gt;
*Dokumente über Verilog und System Verilog &lt;br /&gt;
** http://www.sunburst-design.com/papers/&lt;br /&gt;
** http://www.sutherland-hdl.com/papers.html&lt;br /&gt;
* [http://mikro.e-technik.uni-ulm.de/vhdl/vhdl_infos.html VHDL Kurzanleitung und Anleitung zur Synthese/Optimierung - Link geht nicht]&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
&lt;br /&gt;
Immer wieder wird hier nach einem guten VHDL Editor gefragt. Zu Empfehlen ist der Crimson Editor, wer etwas mehr Power mag (allerdings auch mehr Einarbeitungszeit) nimmt Emacs. Emacs gibt es für Linux, Unix, und auch für [http://www.gnu.org/software/emacs/windows/ntemacs.html Windows].&lt;br /&gt;
Sehr empfehlen kann ich noch die [http://ecb.sourceforge.net/ ECB Erweiterung]. Unter Debian GNU Linux ist Emacs und ECB enthalten! Emacs ist sehr mächtig, leider ist die Lernkurve anfangs sehr flach. Hier gibt es ein [http://book.chinaunix.net/special/ebook/oreilly/LearningGnuEmacs/ eBook] zu Emacs. &lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/9 Bereich FPGA, VHDL &amp;amp; Co. auf mikrocontroller.net]&lt;br /&gt;
&lt;br /&gt;
== Artikel aus der Kategorie FPGA &amp;amp; Co. ==&lt;br /&gt;
&amp;lt;ncl style=compact maxdepth=2 headings=bullet headstart=2&lt;br /&gt;
      showcats=1 showarts=1&amp;gt;FPGA und Co&amp;lt;/ncl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA und Co]]&lt;br /&gt;
__NOTOC__&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29871</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29871"/>
		<updated>2008-08-09T13:04:49Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Wie es weiter geht */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display  mit At91SAM7S =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung sollen zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch Drehen zu Selectieren und durch Drücken auszuwählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG  bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatibel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt [[#Kontrastspannung_reparieren|Kontrastspannung reparieren]] beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Aus einer DSS (Doppelseitigen Europaplatine) bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabatten Gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Die flachen Bauteile  werden zuerst aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinendruck. Bei den großen Bauteilen ist es Praktisch mit dem ARM-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs muss der großflächige Anschluss (Kathode) innerhalb der LED auf der flachen Seite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linearregler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer Neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird.&lt;br /&gt;
&lt;br /&gt;
Unter dem USB Stecker sind unglücklicher Weise noch zwei Widerstände platziert worden. R11 kann ersatzlos entfallen. Aus Symmetriegründen kann auch R24 entfallen, sie ziehen den Eingang auf GND, wenn kein PC verbunden ist. Da ohne die USB Verbindung die Platine stromlos ist. R3 ist der Pull-UP mit dem der PC erkennt dass ein Highspeed gerät angeschlossen ist. Diesen Widerstand kann man nicht dauerhaft weglassen, so dass ich ihn sehr nah zur Platinen Mitte angelötet habe und ihn isoliert habe. &lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt auf gelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die Größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlitzen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anschneidend besitzt er einen winzigen Vorrat Lötzinn, der ausreicht um eine Verbindung zwischen Platine und Pin herzustellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zinn benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlitzen Methode die offensichtlichen Brücken entfernt und  mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine unerwünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet: Der Prozessor hat Spannung und die PINs befinden sich im Defaultzustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Mit diesem Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
Das Decodieren ist reigentlich recht einfach, wenn man davon ausgeht, dass keine Zustände übersprungen werden. Das Prellen ist dann nicht weiter als ein schnelles hin und her springen zwischen zwei Zuständen. Die Aufnahme des Logic Analyzers zeigt, dass niemals zwei Pins gleichzeitig prellen.&lt;br /&gt;
[[Bild:drehgeber_waveform.png]]&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe eines Zustands Automaten kann man sich vor Augen führen, in welcher Reihenfolge die Eingangswerte durchlaufen werden. Die De-Codierung besteht dann darin zu erkennen, aus welchem Vorgänger Zustand in welchen aktuellen Zustand gewechselt wird. Rot/Grün entspricht dann genau je einer Drehrichtung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotary_encoder.png]]&lt;br /&gt;
&lt;br /&gt;
Übrigens habe ich mir den Code angesehen und er ist meiner Meinung nach nicht verbesserbar, solange die Algorithmus Idee -- einen Zustandsautomaten zu verwenden weiter verfolgt wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrant Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
=== IR Impulse messen  ===&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. Nachdem ich inzwischen weitere Informationen zu USB gesammelt habe, habe ich nun die Idee gefasst das USB Device als Zwei geräte auf zu fassen. Der eine Zeil bleibt das Input/Output Device einer Seriellen Schnittstelle, die aber der unnötigen Attribute im dritten Endpoint beraupt wird. Die damit frei gewordenen Endpoint können dann dazu genutzt werden eine HID-KeyBoard device zu implementieren, so dass das Display auch ohne spezielle Treiber jede Anwendung steuern kann.&lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt. In dem hier bereit gestelltem Quelltext ist dies geschehen, so dass man das Display leicht in Betrieb nehmen kann und direkt mit MythTV benutzen kann.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Weitere Informationen und Quellen =&lt;br /&gt;
&lt;br /&gt;
 * [http://www.atmel.com/dyn/products/product_card.asp?part_id=3524  Der Verwendete Prozessor AT91SAM7S256. Datenblatt und Application Notes]&lt;br /&gt;
 * [http://www.lcd-module.de/deu/pdf/grafik/dogm132-5.pdf Datenblatt des Display DOGM132x-5]&lt;br /&gt;
 * [http://lcdproc.org/ LDCproc ]&lt;br /&gt;
 * [http://www.mythtv.org/  MythTV ]&lt;br /&gt;
 * [http://www.cadsoft.de/  Eagle Layout Programm]&lt;br /&gt;
 * [http://www.linuxjournal.com/article/4786 Anleitung zum Schreiben von USB Treibern]&lt;br /&gt;
 * [http://www.gnuarm.org/support.html  GCC Toolchain für ARM]&lt;br /&gt;
 * [http://chibios.sourceforge.net/  ChibiOS]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29870</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29870"/>
		<updated>2008-08-09T13:01:00Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Todo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display  mit At91SAM7S =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung sollen zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch Drehen zu Selectieren und durch Drücken auszuwählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG  bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatibel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt [[#Kontrastspannung_reparieren|Kontrastspannung reparieren]] beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Aus einer DSS (Doppelseitigen Europaplatine) bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabatten Gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Die flachen Bauteile  werden zuerst aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinendruck. Bei den großen Bauteilen ist es Praktisch mit dem ARM-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs muss der großflächige Anschluss (Kathode) innerhalb der LED auf der flachen Seite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linearregler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer Neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird.&lt;br /&gt;
&lt;br /&gt;
Unter dem USB Stecker sind unglücklicher Weise noch zwei Widerstände platziert worden. R11 kann ersatzlos entfallen. Aus Symmetriegründen kann auch R24 entfallen, sie ziehen den Eingang auf GND, wenn kein PC verbunden ist. Da ohne die USB Verbindung die Platine stromlos ist. R3 ist der Pull-UP mit dem der PC erkennt dass ein Highspeed gerät angeschlossen ist. Diesen Widerstand kann man nicht dauerhaft weglassen, so dass ich ihn sehr nah zur Platinen Mitte angelötet habe und ihn isoliert habe. &lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt auf gelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die Größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlitzen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anschneidend besitzt er einen winzigen Vorrat Lötzinn, der ausreicht um eine Verbindung zwischen Platine und Pin herzustellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zinn benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlitzen Methode die offensichtlichen Brücken entfernt und  mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine unerwünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet: Der Prozessor hat Spannung und die PINs befinden sich im Defaultzustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Mit diesem Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
Das Decodieren ist reigentlich recht einfach, wenn man davon ausgeht, dass keine Zustände übersprungen werden. Das Prellen ist dann nicht weiter als ein schnelles hin und her springen zwischen zwei Zuständen. Die Aufnahme des Logic Analyzers zeigt, dass niemals zwei Pins gleichzeitig prellen.&lt;br /&gt;
[[Bild:drehgeber_waveform.png]]&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe eines Zustands Automaten kann man sich vor Augen führen, in welcher Reihenfolge die Eingangswerte durchlaufen werden. Die De-Codierung besteht dann darin zu erkennen, aus welchem Vorgänger Zustand in welchen aktuellen Zustand gewechselt wird. Rot/Grün entspricht dann genau je einer Drehrichtung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotary_encoder.png]]&lt;br /&gt;
&lt;br /&gt;
Übrigens habe ich mir den Code angesehen und er ist meiner Meinung nach nicht verbesserbar, solange die Algorithmus Idee -- einen Zustandsautomaten zu verwenden weiter verfolgt wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrant Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
=== IR Impulse messen  ===&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Weitere Informationen und Quellen =&lt;br /&gt;
&lt;br /&gt;
 * [http://www.atmel.com/dyn/products/product_card.asp?part_id=3524  Der Verwendete Prozessor AT91SAM7S256. Datenblatt und Application Notes]&lt;br /&gt;
 * [http://www.lcd-module.de/deu/pdf/grafik/dogm132-5.pdf Datenblatt des Display DOGM132x-5]&lt;br /&gt;
 * [http://lcdproc.org/ LDCproc ]&lt;br /&gt;
 * [http://www.mythtv.org/  MythTV ]&lt;br /&gt;
 * [http://www.cadsoft.de/  Eagle Layout Programm]&lt;br /&gt;
 * [http://www.linuxjournal.com/article/4786 Anleitung zum Schreiben von USB Treibern]&lt;br /&gt;
 * [http://www.gnuarm.org/support.html  GCC Toolchain für ARM]&lt;br /&gt;
 * [http://chibios.sourceforge.net/  ChibiOS]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Drehgeber_waveform.png&amp;diff=29869</id>
		<title>Datei:Drehgeber waveform.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Drehgeber_waveform.png&amp;diff=29869"/>
		<updated>2008-08-09T12:47:12Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Das Bild zeigt den Typischen Verlauf der Signale des von mir verwendeten Drehgebers.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Bild zeigt den Typischen Verlauf der Signale des von mir verwendeten Drehgebers.&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29034</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29034"/>
		<updated>2008-07-15T19:53:06Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Drehimpulsgeber auslesen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs muss der großflächige Anschluss (Kathode) innerhalb der LED auf der flachen Seite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer Neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Unter dem USB Stecker sind unglücklicher Weise noch zwei Widerstände platziert worden. R11 kann ersatzlos entfallen. Aus Symetriegründen kann auch R24 entfallen, sie ziehen den Eingang auf GND, wenn kein PC verbunden ist. Da ohne die USB Verbindung die Platine stromlos ist, ist die Auswirkung recht gering -- in früheren Versionen waren hier sogar nur Kondensatoren vorgesehen, die auch eher Esoterische Verbesserungen bringen sollten. Sie könnten die Eingänge aber vor elektro statischer Aufladung in gewissen Grenzen schützen -- daher vorsicht mit der aufgebauten Platine! R3 ist der Pull-UP mit dem der PC erkennt dass ein Highspeed gerät angeschlossen ist. Diesen Widerstand kann man nicht dauerhaft weglassen, so dass ich ihn sehr nah zur Platinen Mitte angelötet habe und ihn isoliert habe. &lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt auf gelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die Größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlitzen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anschneidend besitzt er einen winzigen Vorrat Lötzinn, der ausreicht um eine Verbindung zwischen Platine und Pin herzustellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zinn benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlitzen Methode die offensichtlichen Brücken entfernt und  mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine unerwünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Defaultzustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Mit diesem Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
Das Decodieren ist reigentlich recht einfach, wenn man davon ausgeht, dass keine Zustände übersprungen werden. Das Prellen ist dann nicht weiter als ein schnelles hin und her springen zwischen zwei Zuständen. Die Aufnahme des Logic Analyzers zeigt, dass niemals zwei Pins gleichzeitig prellen.&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe eines Zustands Automaten kann man sich vor Augen führen, in welcher Reihenfolge die Eingangswerte durchlaufen werden. Die De-Codierung besteht dann darin zu erkennen, aus welchem Vorgänger Zustand in welchen aktuellen Zustand gewechselt wird. Rot/Grün entspricht dann genau je einer Drehrichtung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotary_encoder.png]]&lt;br /&gt;
&lt;br /&gt;
Übrigens habe ich mir den Code angesehen und er ist meiner Meinung nach nicht verbesserbar, solange die Algorithmus Idee -- einen Zustandsautomaten zu verwenden weiter verfolgt wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrant Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Rotary_encoder.png&amp;diff=29033</id>
		<title>Datei:Rotary encoder.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Rotary_encoder.png&amp;diff=29033"/>
		<updated>2008-07-15T19:47:00Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: hat eine neue Version von „Bild:Rotary encoder.png“ hochgeladen: Zustandsautomat zum Auslesen eines Drehimpulsgebers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Rotary_encoder.png&amp;diff=29032</id>
		<title>Datei:Rotary encoder.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Rotary_encoder.png&amp;diff=29032"/>
		<updated>2008-07-15T19:46:29Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29031</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29031"/>
		<updated>2008-07-15T19:46:15Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Drehimpulsgeber auslesen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs muss der großflächige Anschluss (Kathode) innerhalb der LED auf der flachen Seite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer Neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Unter dem USB Stecker sind unglücklicher Weise noch zwei Widerstände platziert worden. R11 kann ersatzlos entfallen. Aus Symetriegründen kann auch R24 entfallen, sie ziehen den Eingang auf GND, wenn kein PC verbunden ist. Da ohne die USB Verbindung die Platine stromlos ist, ist die Auswirkung recht gering -- in früheren Versionen waren hier sogar nur Kondensatoren vorgesehen, die auch eher Esoterische Verbesserungen bringen sollten. Sie könnten die Eingänge aber vor elektro statischer Aufladung in gewissen Grenzen schützen -- daher vorsicht mit der aufgebauten Platine! R3 ist der Pull-UP mit dem der PC erkennt dass ein Highspeed gerät angeschlossen ist. Diesen Widerstand kann man nicht dauerhaft weglassen, so dass ich ihn sehr nah zur Platinen Mitte angelötet habe und ihn isoliert habe. &lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt auf gelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die Größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlitzen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anschneidend besitzt er einen winzigen Vorrat Lötzinn, der ausreicht um eine Verbindung zwischen Platine und Pin herzustellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zinn benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlitzen Methode die offensichtlichen Brücken entfernt und  mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine unerwünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Defaultzustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Mit diesem Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
Das Decodieren ist reigentlich recht einfach, wenn man davon ausgeht, dass keine Zustände übersprungen werden. Das Prellen ist dann nicht weiter als ein schnelles hin und her springen zwischen zwei Zuständen. Die Aufnahme des Logic Analyzers zeigt, dass niemals zwei Pins gleichzeitig prellen.&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe eines Zustands Automaten kann man sich vor Augen führen, in welcher Reihenfolge die Eingangswerte durchlaufen werden. Die De-Codierung besteht dann darin zu erkennen, aus welchem Vorgänger Zustand in welchen aktuellen Zustand gewechselt wird. Rot/Grün entspricht dann genau je einer Drehrichtung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:rotary_encoder.png]]&lt;br /&gt;
&lt;br /&gt;
Übrigens habe ich mir den Code angesehen und er ist meiner Meinung nach nicht verbesserbar, solange die Algorithmus Idee -- einen Zustandsautomaten zu verwenden weiter verfolgt wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29028</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29028"/>
		<updated>2008-07-15T19:28:04Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Inbetriebnahme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs muss der großflächige Anschluss (Kathode) innerhalb der LED auf der flachen Seite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer Neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Unter dem USB Stecker sind unglücklicher Weise noch zwei Widerstände platziert worden. R11 kann ersatzlos entfallen. Aus Symetriegründen kann auch R24 entfallen, sie ziehen den Eingang auf GND, wenn kein PC verbunden ist. Da ohne die USB Verbindung die Platine stromlos ist, ist die Auswirkung recht gering -- in früheren Versionen waren hier sogar nur Kondensatoren vorgesehen, die auch eher Esoterische Verbesserungen bringen sollten. Sie könnten die Eingänge aber vor elektro statischer Aufladung in gewissen Grenzen schützen -- daher vorsicht mit der aufgebauten Platine! R3 ist der Pull-UP mit dem der PC erkennt dass ein Highspeed gerät angeschlossen ist. Diesen Widerstand kann man nicht dauerhaft weglassen, so dass ich ihn sehr nah zur Platinen Mitte angelötet habe und ihn isoliert habe. &lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt auf gelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die Größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlitzen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anschneidend besitzt er einen winzigen Vorrat Lötzinn, der ausreicht um eine Verbindung zwischen Platine und Pin herzustellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zinn benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlitzen Methode die offensichtlichen Brücken entfernt und  mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine unerwünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Defaultzustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Mit diesem Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29027</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29027"/>
		<updated>2008-07-15T19:27:07Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Aufbau der Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs muss der großflächige Anschluss (Kathode) innerhalb der LED auf der flachen Seite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer Neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Unter dem USB Stecker sind unglücklicher Weise noch zwei Widerstände platziert worden. R11 kann ersatzlos entfallen. Aus Symetriegründen kann auch R24 entfallen, sie ziehen den Eingang auf GND, wenn kein PC verbunden ist. Da ohne die USB Verbindung die Platine stromlos ist, ist die Auswirkung recht gering -- in früheren Versionen waren hier sogar nur Kondensatoren vorgesehen, die auch eher Esoterische Verbesserungen bringen sollten. Sie könnten die Eingänge aber vor elektro statischer Aufladung in gewissen Grenzen schützen -- daher vorsicht mit der aufgebauten Platine! R3 ist der Pull-UP mit dem der PC erkennt dass ein Highspeed gerät angeschlossen ist. Diesen Widerstand kann man nicht dauerhaft weglassen, so dass ich ihn sehr nah zur Platinen Mitte angelötet habe und ihn isoliert habe. &lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt auf gelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die Größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlitzen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anschneidend besitzt er einen winzigen Vorrat Lötzinn, der ausreicht um eine Verbindung zwischen Platine und Pin herzustellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zinn benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlitzen Methode die offensichtlichen Brücken entfernt und  mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine unerwünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Defaultzustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29026</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29026"/>
		<updated>2008-07-15T19:13:27Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Das Schaltungs Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29025</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29025"/>
		<updated>2008-07-15T19:11:18Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Das Schaltungs Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungsspannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungsspannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch hier entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper Feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Programmierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das falsche Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungsspannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem separatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Aus einer DSS Platine können vier Displays und eine Adapterplatine gewonnen werden.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29024</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29024"/>
		<updated>2008-07-15T19:06:57Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Das Schaltungs Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS64 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29023</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29023"/>
		<updated>2008-07-15T19:06:31Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Das Schaltungs Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Stand_jetzt.png&amp;diff=29022</id>
		<title>Datei:Stand jetzt.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Stand_jetzt.png&amp;diff=29022"/>
		<updated>2008-07-15T19:05:19Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Dieses Blockdiagram zeigt den Erreichten und hier dokumentierten Entwicklungsstand&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieses Blockdiagram zeigt den Erreichten und hier dokumentierten Entwicklungsstand&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29021</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29021"/>
		<updated>2008-07-15T19:03:53Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Einleitung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:stand_jetzt.png]]&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29018</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29018"/>
		<updated>2008-07-15T17:29:32Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Das Schaltungs Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Leider muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile je 8 Bit/Pixel. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29017</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29017"/>
		<updated>2008-07-15T17:26:05Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Inbetriebnahme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von an Code ist nicht viel interessantes passiert, so dass hier nur Code Auszüge gezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29016</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29016"/>
		<updated>2008-07-15T17:23:54Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: /* Dreh Impuls geber auslesen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Drehimpulsgeber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29002</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29002"/>
		<updated>2008-07-14T20:49:42Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: punkt abgehakt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insbesondere Datenblätter. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29001</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29001"/>
		<updated>2008-07-14T20:48:03Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Tippfehler korrigiert.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den Einen oder Anderen anregen die Ideen aufzugreifen oder weiterzuverfolgen.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphikdisplay sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Des weiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog Eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29000</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=29000"/>
		<updated>2008-07-14T20:45:39Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Bilder eingefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
[[Bild:USB_Display_Fix_Oberseite.png]] [[Bild:USB_Display_Fix_Unterseite.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:USB_Display_Fix_Unterseite.png&amp;diff=28999</id>
		<title>Datei:USB Display Fix Unterseite.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:USB_Display_Fix_Unterseite.png&amp;diff=28999"/>
		<updated>2008-07-14T20:45:09Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Der kleine Lila schnitt zeigt, wo man die Leiterbahn durchtrennen muss.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der kleine Lila schnitt zeigt, wo man die Leiterbahn durchtrennen muss.&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:USB_Display_Fix_Oberseite.png&amp;diff=28998</id>
		<title>Datei:USB Display Fix Oberseite.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:USB_Display_Fix_Oberseite.png&amp;diff=28998"/>
		<updated>2008-07-14T20:44:09Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Dies zeigt den Fix, den man auf der Operseite durchführen muss um die Kontrastspannung des Usbdisplay in der Version 5/08 zu reparieren.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dies zeigt den Fix, den man auf der Operseite durchführen muss um die Kontrastspannung des Usbdisplay in der Version 5/08 zu reparieren.&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28997</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28997"/>
		<updated>2008-07-14T20:38:47Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Software angepasst&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.bz2‎|Erste Software für die Platine, ohne LCDProc da die Source doch recht groß sind ]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Usb_display_0.1.tar.bz2&amp;diff=28996</id>
		<title>Datei:Usb display 0.1.tar.bz2</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Usb_display_0.1.tar.bz2&amp;diff=28996"/>
		<updated>2008-07-14T20:36:04Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Version ohne LCD-Proc. Um auf dem Display einnen Text aus zu geben, muss man ihn in /dev/twi_display0  schreiben. Sorry, lieber Admin, wenn Du die andere Datei löschen magst, bitte.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Version ohne LCD-Proc. Um auf dem Display einnen Text aus zu geben, muss man ihn in /dev/twi_display0  schreiben. Sorry, lieber Admin, wenn Du die andere Datei löschen magst, bitte.&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Usb_display_0.1.tar.gz&amp;diff=28995</id>
		<title>Datei:Usb display 0.1.tar.gz</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Usb_display_0.1.tar.gz&amp;diff=28995"/>
		<updated>2008-07-14T20:30:47Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: hat eine neue Version von „Bild:Usb display 0.1.tar.gz“ hochgeladen: Product ID tatsächlich entfernt. Die erste Version darf auf keinen Fall benutzt werden, wenn sie jemand physikalisch lösche kann, bitte!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Alles was  man braucht um die Hardware in Betrieb zu nehmen und mit MythTV via LCD-Proc ein drei Zeiliges LCD Display zu realisieren. Wie man an der Versionsnummer sehen kann, ist es noch weit vom Ziel entfernt. Das Niveau einer LTP-Prot zweit Zeilen Bastellösung hat es also schon überschritten.&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28994</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28994"/>
		<updated>2008-07-14T20:24:56Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Leerzeichen entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎|Erste Software für die Platine ]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28993</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28993"/>
		<updated>2008-07-14T20:24:38Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Dateinamen korrigiert.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:Usb_display_0.1.tar.gz‎| Erste Software für die Platine ]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Usb_display_0.1.tar.gz&amp;diff=28992</id>
		<title>Datei:Usb display 0.1.tar.gz</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Usb_display_0.1.tar.gz&amp;diff=28992"/>
		<updated>2008-07-14T20:24:15Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Alles was  man braucht um die Hardware in Betrieb zu nehmen und mit MythTV via LCD-Proc ein drei Zeiliges LCD Display zu realisieren. Wie man an der Versionsnummer sehen kann, ist es noch weit vom Ziel entfernt. Das Niveau einer LTP-Prot zweit Zeilen Bast&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Alles was  man braucht um die Hardware in Betrieb zu nehmen und mit MythTV via LCD-Proc ein drei Zeiliges LCD Display zu realisieren. Wie man an der Versionsnummer sehen kann, ist es noch weit vom Ziel entfernt. Das Niveau einer LTP-Prot zweit Zeilen Bastellösung hat es also schon überschritten.&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28991</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28991"/>
		<updated>2008-07-14T20:24:06Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Quelltexte verlinkt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
 *  [[Media:usb_display_0.1.tar.gz| Erste Software für die Platine ]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28988</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28988"/>
		<updated>2008-07-14T19:10:07Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: 8/08 Platine verlinkt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
 *  [[Media:Usb_dispay-8-08.zip|Usb-Display Eagle Dateien 8/08]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Usb_dispay-8-08.zip&amp;diff=28987</id>
		<title>Datei:Usb dispay-8-08.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Usb_dispay-8-08.zip&amp;diff=28987"/>
		<updated>2008-07-14T19:09:04Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Überarbeitete Version des USB-Displays Usb_dispay-5-08.zip. Die diese Datei enthält noch keine Massefälchen und eigenet sich daher noch nicht gut zum Fertigen. 

Ich werde diese Datei sicher noch überarbeiten, daher ist dies noch nicht die finale Vers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Überarbeitete Version des USB-Displays Usb_dispay-5-08.zip. Die diese Datei enthält noch keine Massefälchen und eigenet sich daher noch nicht gut zum Fertigen. &lt;br /&gt;
&lt;br /&gt;
Ich werde diese Datei sicher noch überarbeiten, daher ist dies noch nicht die finale Version!&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28986</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28986"/>
		<updated>2008-07-14T19:03:52Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: USB-Platine 5/08  zum Download bereit gestellt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontrastspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus Symmetriegründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor Strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hoch laden darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Download ===&lt;br /&gt;
 *  [[Media:Usb_dispay-5-08.zip|Usb-Display Eagle Dateien 5/08]]&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Usb_dispay-5-08.zip&amp;diff=28985</id>
		<title>Datei:Usb dispay-5-08.zip</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Usb_dispay-5-08.zip&amp;diff=28985"/>
		<updated>2008-07-14T18:59:59Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Dies ist die Version 5/08 meines USB-Displays. Ein AT91SAMS7 steuert per SPI ein DOGM132-5 an. Ein IR-Empfänger dient dazu IR-Signale auf zu fangen. Ein Drehimpulsgeber und ein paar tasten sollen der Menüführung dienen.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dies ist die Version 5/08 meines USB-Displays. Ein AT91SAMS7 steuert per SPI ein DOGM132-5 an. Ein IR-Empfänger dient dazu IR-Signale auf zu fangen. Ein Drehimpulsgeber und ein paar tasten sollen der Menüführung dienen.&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28984</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28984"/>
		<updated>2008-07-14T18:55:54Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Kleine Tippfehler korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe Funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetriebnahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die Richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontrastspannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
* Kontraspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
* Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
* R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
* R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus symetrie Gründen kann R24 ebenfalls entfallen.&lt;br /&gt;
* R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hochladen darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
* Grafiken hochladen&lt;br /&gt;
* Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
* Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
* Text korrektur lesen&lt;br /&gt;
* Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Danke! =&lt;br /&gt;
&lt;br /&gt;
Danke an Magnetus, der schon Fehler korrigiert hat, bevor ich es tun konnte.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28970</id>
		<title>UsbDisplay</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=UsbDisplay&amp;diff=28970"/>
		<updated>2008-07-13T20:28:32Z</updated>

		<summary type="html">&lt;p&gt;Thorstenw: Die Seite wurde neu angelegt: = Usb Display =  == Einleitung ==  Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben,...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Usb Display =&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Dies ist ein längeres Projekt, das sicher nicht bis zum 18.8 fertig gestellt ist. Dieser Artikel mag aber doch einen Einblick geben, was ich mir vorstelle und den einen oder anderen anregen die Ideen auf zu greifen oder weiter zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Ziel dieses Projektes ist es ein Multifuntkionales Display für MythTV zu bauen. Es soll über USB angeschlossen werden. Das Display soll ein Graphik display sein. Als Steuerung soll zwei Taster und ein Drehknopf mit Taskfunktion dienen. Dieser Drehknopf erlaubt es Menus durch drehen zu selectieren und durch drücken aus zu wählen. Desweiteren soll ein IR Empfänger vorhanden sein, so dass IR Signale dekodiert werden können. Als Prozessor soll ein Prozessor der AT91SAM7S Serie eingesetzt werden. Um Platz auf der Display Platine zu sparen soll es einen Konnektor geben, der eine Uart-Schnittstelle, DBG, JTAG und eine Analog eingangsleitung und eine Ausgangsleitung bereit hält. Die Adapter Platine wird über die Display Platine mit Spannung versorgt und soll auch in weiteren Projekten verwendet werden. &lt;br /&gt;
&lt;br /&gt;
== Das Schaltungs Design ==&lt;br /&gt;
&lt;br /&gt;
Die Versorgungs Spannung wird aus dem USB Bus mit einem Linearregler 317 D gewonnen. Die Widerstände  R21 und R22 wurden so gewählt, dass sich eine Ausgangsspannung von 3.3 V einstellt. Aufgrund der geringen Leiterbahnbreite, stellen sich etwa 3.1 V ein. Der Regler liefert höchstens 100mA. Dies ist für das Display 110µA und den Prozessor 50mA ausreichend. Der IR-Empfänger (5mA) und die LED der Hintergrund Beleuchtung (40mA) verbrauchen weniger als 50 mA, so dass keine Gesonderte Anmeldung beim Host erforderlich sind.&lt;br /&gt;
&lt;br /&gt;
Der Prozessor AT91SAM7S256 ist zu den anderen ICs der Serie kompatiebel. Wenn die Firmware fertig ist, kann evtl. auch ein kleiner Chip AT91SAMS56 ausreichen.&lt;br /&gt;
Der Prozessor ist entsprechend den Empfehlungen von Atmel beschaltet worden. Um die Spannung zu glätten sind für die 3.3V und 1.8V Versorgungs Spannung 2,2 µF Tantal Kondensatoren vorgesehen C1, C4. Alle weiteren Versorgungs Spannungspins sind mit 100nF Condensatoren abgeblockt worden  C2, C3, C5, C7, C8, C9, C10.&lt;br /&gt;
&lt;br /&gt;
Für die PLL-Filter und den Quarz wurden die Größen verwendet, die auch in anderen Beispielen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
Es wurde auch ein Reset Baustein vorgesehen, die Praxis zeigt aber, dass dieser Baustein nicht erforderlich ist. Auch ohne dieses teure Stück läuft der Prozessor zuverlässig an. Das Display wird durch den Prozessor zurück gesetzt, so dass er auch dafür entbehrlich ist.&lt;br /&gt;
&lt;br /&gt;
Es ist weiter ein Jumper feld zum Löschen und starten des SAM-BA vorgesehen. Leider wird für SAM-BA PA0 und PA1 auf GND gezogen, so dass SAM-BA nur dann verfügbar wäre, wenn keine Adapter Platine angeschlossen ist und R12 nicht bestückt ist. Einen Bootloader habe ich noch nicht geschrieben, so dass im Moment nur die Prorgammierung über JTAG bleibt.&lt;br /&gt;
&lt;br /&gt;
Der IR-Empfänger ist klassisch angeschlossen, um den Ausgangspin während eines Resets des Controllers (Verbindung per Pullup zu 3.3V) zu schonen ist ein Spannungsteiler vorgesehen, so dass der Ausgang auch in diesem Zustand nicht belastet wird. Er ist so eingestellt, dass ein High-Pegel etwa 3.3V liefert.&lt;br /&gt;
&lt;br /&gt;
Der Drehimpulsgeber  (STEC12E08) und die beiden Taster sind jeweils mit Pullups mit 3.3V verbunden. Diese Widerstände müssten eigentlich auch eingespart werden können, wenn die internen Pullups verwendet werden. Im Datenbaltt des Drehimpuls Gebers sind aber  für 5 V 10k empfohlen, aus denen ich die 6,2k für 3.3V hergeleitet habe. Die Kondensatoren habe ich schon eingespart -- die Platine ist ja schon eine Kondesator Senke. &lt;br /&gt;
&lt;br /&gt;
Beim Display habe ich mich für das EA DOGM132-5 entschieden. Es handelt sich um ein Grafik Display 132x32 Punkte, das Pinähnlich auch in anderen Varianten zu haben ist. Dieses Display kommt mit 3.3V Versorgungsspannung aus und kann direkt per SPI vom AT91SAM7S angesprochen werden. Im Internet Kursieren einige Bibliotheken, die ähnliche Displays zeigen. Leider habe ich zunächst das Verkehrte Pinning erwischt und schließlich das Symbol neu gezeichnet. Bei dieser Aktion haben sich die Netze für die Kontrastspannung und die Versorgungs spannung verbunden, was ich leider erst nach der Inbetriebnahme bemerkte. Die Lösung dieses Fehlers wird in einem seperatem Abschnitt beschrieben.&lt;br /&gt;
Die Reset Leitung ist mit einem I/O Pin verbunden, so dass das Display gezielt zurück gesetzt werden kann. &lt;br /&gt;
&lt;br /&gt;
Die CS-Leitung wird durch den SPI Teil des AT91SAM7S gesteuert. Ledier muss für die Unterscheidung von Display Daten und Kommandos die A0 Leitung gesteuert werden, so dass nicht direkt der Komplette Bildschirminhalt mit einem DMA (PDC) Transfer geschrieben werden kann, sondern immer nur eine Zeile. &lt;br /&gt;
&lt;br /&gt;
Das Display enthält mehrere Ladungspumpen um die Kontrast Spannung zu erzeugen, aus diesem Grund versammeln sich 8 Kondensatoren entlang des Displays.&lt;br /&gt;
&lt;br /&gt;
Die Adapter Platine verbindet die JTAG-Schnittstelle, USART2, DBGU, einen I/O-Pin und einen Analogen Eingang. Der I/O-Pin schaltet eine LED. Der Analog Pin soll dazu dienen zwei Tasten eingaben auf der Adapter Platine anhand der unterschiedlich abfallenden Spannung zu unterscheiden. LED und Analog-Pin sind noch nicht in Betrieb genommen worden. Da die LED aber bei einem Reset an ist und im normalen Betrieb ausgeschaltet ist, gehe ich davon aus, dass die Verbidnung zumindest zu irgend einem Pin besteht ;-)&lt;br /&gt;
&lt;br /&gt;
Die Display Platine entsprich den 8mil Anforderungen von Olimex, die Adapter Platine den 10mil Anforderungen. Die  8/08 Version hat noch keine Massefläche und ist noch völlig ungeprüft! Außerdem wäre eine Optimierung für eine bestimmte gängige Gehäusegröße und einige Bohrungen zur Befestigung sinnvoll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Aufbau der Hardware ==&lt;br /&gt;
&lt;br /&gt;
Die aufgeführten Bauteile kosten etwa 70 EUR bei Reichelt. Auf einer Doppelseitigen Bestellung bei Olimex können 4 Display-Platinen und eine Adapter Platine gewonnen werden. So dass eine Platine etwa 10 EUR kostet. Die Material Kosten können weiter gesenkt werden, wenn ein kleinerer Prozessor und sämtliche optionalen Widerstände und Kondensatoren weg gelassen werden und von Mengenrabaten gebrauch gemacht wird.&lt;br /&gt;
&lt;br /&gt;
Für die Maschinelle Herstellung eignet sich das Layout sicher nicht, die Kondensatoren in der ersten Version waren sehr eng angeordnet.&lt;br /&gt;
&lt;br /&gt;
Beim Aufbau bin ich wie folgt vorgegangen. Ich habe nur die Bauteile für eine Version bestellt. Zunächst habe ich die Adapter Platine aufgabaut. Zunächst habe ich die flachen Bauteile aufgelötet. Der Treiber Baustein ist ziemlich unempfindlich aus diesem Grund habe ich mit dieser Platine begonnen. Die Markierung des Chip entspricht dem Platinen druck. Bei den großen Bauteilen ist es Praktisch mit dem AMR-Jtag stecker zu beginnen. Ihn kann man in eine Unterlage stecken.   Bei den LEDs der großflächige Anschluss (Kathode) innerhalb der LED auf der Innenseite liegen. Die Kondensatoren sind aus Kostengründen keine SMD Bausteine die Markierung zeigt jeweils vom IC weg.&lt;br /&gt;
Die Ausrichtung des Miniatur Stiftleiste (MicroMatch MM FL 14G) ist egal. Ich habe sie wie den JTAG Adapter von oben eingesteckt. Mit den &amp;quot;richtigen&amp;quot; Kabeln kann man die Pins wieder in die richtige Richtung drehen. Ich gehe davon aus, dass er normal, d.h. von unten angelötet wird. Damit das Kabel von der Display Platine 5/08 weg zeigt, Müssen die Stecker des Kabels so angeordnet sein, dass sie an beiden Enden nicht gleich angesteckt sind. Die rote  Markierung sollte mit dem Pin 1 des JTAG adapters übereinstimmen -- wenn ich eine neue Version der Adapterplatine bauen würde, würde ich dringend eine 1 Markierung vorsehen!&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich die Display Platine aufgebaut. Angefangen mit dem Linear regler weiter mit den Widerständen und den uni-polaren Kondensatoren. Anschließend habe ich die Tantal Kondensatoren bestückt und jeweils die Polarität mit dem Platinen Layout verglichen. Eine Markierung im Bestückungsdruck fehlt leider. Auch dies sollte bei einer neuanfertigung korrigiert werden. Aber darauf achten, dass der Druck nicht auf die PADs reicht, da es sonst mit dem Löten schwierig wird. Bei einem der Tastern der Adapter Platine hatte ich dieses Problem...&lt;br /&gt;
&lt;br /&gt;
Die MicroMatch und den USB Stecker habe ich auch schon jetzt aufgelötet, weil ich in diesem Zustand die Schaltung prüfen möchte ob auf der Adapter Platine die Spannungsversorgungs LED leuchet. Dies hat gezeigt, dass bisher keine Brücke zwischen GND und 3.3V oder GND und 5V besteht. &lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich den AT91SAM7S eingelötet. Das Raster ist fein, aber die größe oder Feinheit des Lötkolben ist nicht entscheidend. Die Entlötlizen Methode beseitigt entstandene Brücken zuverlässig. Ich habe zunächst den Fehler gemacht und einen PIN verzinnt. Dieser Pin war dann auch recht bald schon verbogen, weil er an der Kuppe hängen geblieben ist. An den PIN habe ich aber eine Veränderung bemerkt, anscheindend besitzt er einen winzigen Vorrat Lötzin, der ausreicht um eine Verbindung zwischen Platine und Pin her zu stellen. Die Anderen Pins habe ich dann einfach nur noch erwärmt und mit einem mit Zin benetzten Lötspitze verlötet.&lt;br /&gt;
&lt;br /&gt;
Anschließend habe ich mit der Entlötlizen Methode die offensichtlichen Brücken entfernt und anschließend mit einer sehr starken Lupe die Löststellen kontrolliert. Nachdem ich mich versichert habe, dass es keine ungewünschten Verbindungen gibt, habe ich die Platine eingeschaltet und beobachtet, dass beide LEDs der Adapterplatine geleuchtet haben. Dies bedeutet, der Prozessort hat Strom und die PINs befinden sich im Default zustand. Anschließend habe ich mit dem Olimex JTAG interface die Prozessor angesprochen. Der Prozessor wurde auf Anhieb erkannt.&lt;br /&gt;
&lt;br /&gt;
Anschließend konnte ich mit den Beispielen zum AT91 USB und die Debug Schnittstelle testen. Die wie beschrieben, fehlenden Widerstände haben keinen negativen Einfluss auf diese Funktion.&lt;br /&gt;
&lt;br /&gt;
== In Betriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Während die Seriellen Beispiele von Atmel schon die grobe funktion gezeigt haben, konnten die anderen Funktionen nur durch eigene SW benutzt werden. Die Inbetrieb nahme dient dazu die Funktion der HW zu testen und sicher zu stellen, dass die notwendigen Verbindungen existieren und jede Teilkomponente für sich funktioniert. Als Basis Software habe ich eine GCC-Port eines USB/Seriell Wandlers verwendet, das im AT91.com Forum gepostet wurde. Von dem Code ist heute nicht mehr viel übrig, so dass ich hier nur Code auszüge zeigen werde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zunächst habe ich in einer Schleife die eingangs Ports abgefragt und ausgegeben.&lt;br /&gt;
Dies zeigt, dass die Verbindungen vorhanden sind. Das Auslesen des Drehimpulsgebers hat, per Polling leider nicht funktioniert.  Die Pins zeigen ein langes hochfrequentes Prellen. Ein weiterer Effekt mag sein, dass ich eine Reihe von Ausgaben gemacht habe. Deswegen habe ich den Interrupt on Change verwendet um den Zustand der Pins ab zu fragen und entsprechend einer Zustandsübergangstabelle in eine Drehrichtung umgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Dreh Impuls geber auslesen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static int dir=0; // Die richtung in die als letztes gedreht wurde&lt;br /&gt;
static int pos=0; // Die virtuelle Position. Pro Rastung wird 4 Schritte weiter gezählt.&lt;br /&gt;
&lt;br /&gt;
void  __attribute__((interrupt)) ISR_Button(void) {&lt;br /&gt;
&lt;br /&gt;
	int curState = 0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_GetInterruptStatus(LCD_PIO);&lt;br /&gt;
	unsigned int value = AT91F_PIO_GetInput(LCD_PIO);&lt;br /&gt;
&lt;br /&gt;
	int receiverState=value  &amp;amp; IR_IN;&lt;br /&gt;
	if(receiverState!=lastRecieverState)&lt;br /&gt;
	{&lt;br /&gt;
		lastRecieverState=receiverState;&lt;br /&gt;
		irToggled();&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	curState = 0;&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_A) {&lt;br /&gt;
		curState = 2;&lt;br /&gt;
	}&lt;br /&gt;
	if (value &amp;amp; BUTTON_ROT_B) {&lt;br /&gt;
		curState += 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (curState != lastState) {&lt;br /&gt;
&lt;br /&gt;
		switch (lastState &amp;lt;&amp;lt; 2 | curState) {&lt;br /&gt;
		case B8(1101):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1110):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0001):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0010):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0111):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(0100):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1000):&lt;br /&gt;
			dir = 1;&lt;br /&gt;
			break;&lt;br /&gt;
		case B8(1011):&lt;br /&gt;
			dir = -1;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			dir = 0;&lt;br /&gt;
		}&lt;br /&gt;
		pos += dir;&lt;br /&gt;
		if (pos &amp;lt; 0)&lt;br /&gt;
			pos = 99;&lt;br /&gt;
		if (pos &amp;gt; 99)&lt;br /&gt;
			pos = 0;&lt;br /&gt;
		lastState = curState;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
   AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Irgend wo in der Initialisierung&lt;br /&gt;
        AT91F_PIOA_CfgPMC();&lt;br /&gt;
  	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
   	AT91F_PIO_CfgPullupDisable(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInput(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
	AT91F_PIO_CfgInputFilter(LCD_PIO, BUTTON_E | BUTTON_D | BUTTON_ROT_A&lt;br /&gt;
			| BUTTON_ROT_B | BUTTON_ROT_C | IR_IN);&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_PIOA,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Button);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als  Interrupt Handler steht in der Intialisierung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        ldr     pc, [pc,#-0xF20]   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So wird direkt an die Addresse gesprungen, die im AIC konfiguriert ist. Da ich keine Reentrants Interrupts haben möchte, reicht mir diese Simple behandlung. &lt;br /&gt;
Die Magie geschieht über das Attribut  __attribute__((interrupt)) Laut GCC Manual ist dies genau für Interrupt Handler gedacht. Der Compiler speichert nur die Register auf dem Stack, die tatsächlich benötigt werden. Dies ist performanter als per se alle Register zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die nächste Herausforderung war Infrarot signale zu empfangen. Dieser Code ist noch nicht fertig, so dass ich einzelen Tasten empfangen kann, er wäre dazu aber leicht in der Lage. Da ich nicht solange auf einen Signal wechsel warten kann, brauche ich ein Mittel um zu messen, wie lang der letzte Signalwechsel her ist. Dazu verwende ich einen Timer (0). Die Clock wähle ich so dass er in 16 Bit locker eine Sekunde zählen kann. Ich wähle 48/1024 Mhz als Clock. Die Comperator stelle ich so ein, dass er genau nach einer Sekunde einen Interrupt auslöst. Im Interrupt wird auf den Globalen Tick-Zähler der comperator wert addiert. Aus der Summe des globalen Tick-Zählers und dem aktuellen Timerstandes, kann ein 32bit breiter monotoner zähler gweonnen werdenn, der mit 46,875 kHz getaktet ist. Dieser zähler wird etwa einmal am Tag ablaufen -- nur &lt;br /&gt;
in dieser Zeit ist dann keine IR-Messung möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Zeiten Messen ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int TICKS_PER_SECOND=46875;&lt;br /&gt;
int ticks  =0;&lt;br /&gt;
&lt;br /&gt;
void INTERRUPT ISR_Timer()&lt;br /&gt;
{&lt;br /&gt;
	int status=AT91C_BASE_TC0-&amp;gt;TC_SR;&lt;br /&gt;
	if(status&amp;amp; AT91C_TC_CPCS)&lt;br /&gt;
		dir=3;&lt;br /&gt;
&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
		dummy=dummy;&lt;br /&gt;
	access++;&lt;br /&gt;
	ticks+=TICKS_PER_SECOND;&lt;br /&gt;
&lt;br /&gt;
   END_INTERRUPT();&lt;br /&gt;
}&lt;br /&gt;
int lastRecieverState=0;&lt;br /&gt;
int lastMeasureTime=0;&lt;br /&gt;
int curMeasureTime=0;&lt;br /&gt;
int measured=0;&lt;br /&gt;
int lastDuration=0;&lt;br /&gt;
int measeureArray[40];&lt;br /&gt;
int measeureArrayL[40];&lt;br /&gt;
void irToggled()&lt;br /&gt;
{&lt;br /&gt;
	curMeasureTime=ticks+AT91C_BASE_TC0-&amp;gt;TC_CV;&lt;br /&gt;
	lastDuration=curMeasureTime-lastMeasureTime;&lt;br /&gt;
		lastMeasureTime=curMeasureTime;&lt;br /&gt;
&lt;br /&gt;
	if(measured&amp;lt;40)&lt;br /&gt;
	{&lt;br /&gt;
		if(lastDuration&amp;gt;255) lastDuration=0;&lt;br /&gt;
		measeureArray[measured]=lastDuration;&lt;br /&gt;
		measeureArrayL[measured]=lastRecieverState !=0 ? 1 : 0;&lt;br /&gt;
		measured++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// irgendwo in der Initialisierung&lt;br /&gt;
&lt;br /&gt;
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0,&lt;br /&gt;
			AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, //AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,&lt;br /&gt;
			ISR_Timer);&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BMR=0;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CMR=AT91C_TC_CLKS_TIMER_DIV5_CLOCK&lt;br /&gt;
	                   |   (AT91C_TC_CLKI*0)&lt;br /&gt;
	                   | AT91C_TC_BURST_NONE&lt;br /&gt;
	                   | AT91C_TC_WAVESEL_UP_AUTO&lt;br /&gt;
	                   | AT91C_TC_WAVE ;&lt;br /&gt;
&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RC=TICKS_PER_SECOND ;// TC0 Timer interval 1 second&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RA=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_RB=0xFFFF;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_IER=AT91C_TC_CPCS ; // Interrupt on RC&lt;br /&gt;
	AT91C_BASE_TCB-&amp;gt;TCB_BCR=1;&lt;br /&gt;
	int dummy=AT91C_BASE_TC0-&amp;gt;TC_IMR;&lt;br /&gt;
	AT91C_BASE_TC0-&amp;gt;TC_CCR=AT91C_TC_CLKEN&lt;br /&gt;
	                  | AT91C_TC_SWTRG;&lt;br /&gt;
	dummy=dummy;&lt;br /&gt;
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0 );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Display ansteuern ===&lt;br /&gt;
&lt;br /&gt;
Das Highlight ist natürlich, wenn das Display das Erste mal etwas ausgibt. Dies war zunächst ein Satz mit X, das Display blieb leer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also vergnügte ich mich zunächst mit der Hintergrund Beleuchtung, an ging sie schon doch leider nicht gedimmt. Dafür hatte ich ja extra einen PWM Pin vorgesehen. Also, wie macht man das?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, AT91C_PIO_PA1, 0); // Die Peripherie Konfiguration ist jeweils nur ein Beispiel!&lt;br /&gt;
	AT91F_PWMC_CfgPMC(); // Enable PWM&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0, 1, 0xFF, dutyCycle);&lt;br /&gt;
	AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID0,&lt;br /&gt;
						dutyCycle);  // Modified Version!!&lt;br /&gt;
&lt;br /&gt;
// Modified Functions:&lt;br /&gt;
//lib_PWM_SAM.h/1.3/Wed Dec  3 10:23:10 2003//&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_UpdateChannel&lt;br /&gt;
//* \brief Update Period or Duty Cycle&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_UpdateChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int update) // \arg  Channels IDs to be enabled&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CUPDR = update;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
//* \fn    AT91F_PWM_CfgChannel&lt;br /&gt;
//* \brief Test if PWM Interrupt is Set&lt;br /&gt;
//*----------------------------------------------------------------------------&lt;br /&gt;
__inline void AT91F_PWMC_CfgChannel(&lt;br /&gt;
        AT91PS_PWMC pPWM,   // \arg  pointer to a PWM controller&lt;br /&gt;
        unsigned int channelId, // \arg PWM channel ID&lt;br /&gt;
        unsigned int mode, // \arg  PWM mode&lt;br /&gt;
        unsigned int period, // \arg PWM period&lt;br /&gt;
        unsigned int duty) // \arg PWM duty cycle&lt;br /&gt;
{&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CMR = mode;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CPRDR = period;&lt;br /&gt;
	pPWM-&amp;gt;PWMC_CH[channelId-1].PWMC_CDTYR = duty;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind maximal 0xFF Ticks für die PWM vorgesehen -- so viel sieht man eh nicht... Nach einem Tasten Druck wird jeweils der dutyCycle verädnert, so dass  wenn UpdateChannel ausgeführt wird, die jweils neue Helligkeit  eingestellt werden kann. Die 1 sorgt auf magische Weise dafür, dass der richtige PWM-Modus gewählt wird, also 22/Mhz und der Duty Cycle bei einem Update aktualisiert wird. Durch ausprobieren habe ich gefunden, dass diese Frequenz brauchbar ist, so dass sich die Helligkeit ändert und das Licht nicht flackert.&lt;br /&gt;
&lt;br /&gt;
Achja, eine nettigkeit ist, dass StartChannel, CfgChannel und UpdateChannel die Kanal ID im Original unterschiedlich zählen, so dass die drei Funktionen nicht alle mit AT91C_PWMC_CHID0 benutzt werden können&lt;br /&gt;
&lt;br /&gt;
Ich habe darauf Atmel hingewiesen und sie wollen den Fehler weiter leiten. Ob sie allerdings ihre Bibliothek ändern bleibt fraglich, da die Änderung für mit dem original Funktionierendem Code falsch wird. Einzige Möglichkeit ist, den Namen zu ändern, so dass alter funktionierender Code nicht kaputt gemacht wird ... ich bin gespannt.&lt;br /&gt;
&lt;br /&gt;
=== Kontras Spannung reparieren ===&lt;br /&gt;
&lt;br /&gt;
Damit das Display etwas anzeigt, braucht es die korrekte Kontrast Spannung. Das Display habe ich vorsorglich gesockelt montiert. Mit einem Logic Analyzer habe ich die Signale und initialiserung konrolliert, keine Fehler. Dann habe ich die Spannungen gemessen, keine Fehler. Dann habe ich die Verbindungen zu den Kondensatoren und anderen Pins kontrolliert dabei ist mir die Verbindug zwischen 3,3V und dem VOUT des Displays aufgefallen.&lt;br /&gt;
&lt;br /&gt;
Anschlißend habe ich die Leiterbahnen, wie in den Bildern gezeigt durchtrennt. Der Kondensator C17 war eigentlich für die die Stabilisierung der Kontrastspannung gedacht. Den konnte ich nun nicht mehr verwenden, daher habe ich einen Bedrahteten 1µF zwischen VOUT und GND angelötet. Mit einem stück Draht habe ich dann den 3,3V Pin des Displays verbunden. Wenn man diesen Code ausgeführt  hat, hat man dann das folgende Bild gesehen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eOrientation curOrientation=ORIENTATION_TOP;&lt;br /&gt;
&lt;br /&gt;
void setLcdCmd(unsigned char value) {&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_A0);&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
void setLcdData(unsigned char value) {&lt;br /&gt;
	AT91F_SPI_PutChar(LCD_SPI, value, 0);&lt;br /&gt;
	while ((LCD_SPI-&amp;gt;SPI_SR &amp;amp; AT91C_SPI_TDRE) == 0)&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setDisplayOrientation(eOrientation orientation) {&lt;br /&gt;
	if (orientation == ORIENTATION_BOTTOM) {&lt;br /&gt;
		setLcdCmd(0xA1);&lt;br /&gt;
		setLcdCmd(0xC0);&lt;br /&gt;
	} else {&lt;br /&gt;
		setLcdCmd(0xA0);&lt;br /&gt;
		setLcdCmd(0xC8);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
   // irgend wo in der Initialisierung&lt;br /&gt;
	AT91F_SPI_CfgPMC();&lt;br /&gt;
	AT91F_PIOA_CfgPMC();&lt;br /&gt;
	AT91F_TC0_CfgPMC();&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgPullupDisable(LCD_PIO, (LCD_CSB | // Disable All Pullups&lt;br /&gt;
			LCD_RS | LCD_A0 | LCD_SCK | LCD_LED | LCD_MOSI));&lt;br /&gt;
&lt;br /&gt;
	AT91F_PIO_CfgOutput(LCD_PIO, LCD_RS | LCD_A0 | LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_LED);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	AT91F_PIO_CfgPeriph(LCD_PIO, LCD_PIO_A, LCD_PIO_B);&lt;br /&gt;
	AT91F_SPI_Reset(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Disable(LCD_SPI);&lt;br /&gt;
	AT91F_SPI_Enable(LCD_SPI);&lt;br /&gt;
	TRACE_INFO(&amp;quot;Habe SPI configuriert...\n&amp;quot;);&lt;br /&gt;
	AT91F_SPI_CfgMode(LCD_SPI, AT91C_SPI_MSTR | // Use Master&lt;br /&gt;
			AT91C_SPI_PS_FIXED | // Fixed CS&lt;br /&gt;
			~AT91C_SPI_PCSDEC | // Only plain CS lines&lt;br /&gt;
			AT91C_SPI_MODFDIS // No fault detection&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	AT91F_SPI_CfgPCS(LCD_SPI, 0);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(10);&lt;br /&gt;
	AT91F_PIO_ClearOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
	AT91F_PIO_SetOutput(LCD_PIO, LCD_RS);&lt;br /&gt;
	delay(100);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	setLcdCmd(0xE2); // Reset&lt;br /&gt;
	setLcdCmd(0x40);&lt;br /&gt;
	setDisplayOrientation(curOrientation);&lt;br /&gt;
	setLcdCmd(0xA6);&lt;br /&gt;
	setLcdCmd(0xA2);&lt;br /&gt;
	setLcdCmd(0x2F);&lt;br /&gt;
	setLcdCmd(0xF8);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0x23);&lt;br /&gt;
	setLcdCmd(0x81);&lt;br /&gt;
	setLcdCmd(0x1F);&lt;br /&gt;
	setLcdCmd(0xAC);&lt;br /&gt;
	setLcdCmd(0x00);&lt;br /&gt;
	setLcdCmd(0xAF);&lt;br /&gt;
&lt;br /&gt;
//Irgendwo im Header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_LED         AT91C_PIO_PA0&lt;br /&gt;
#define LCD_CSB         AT91C_PIO_PA11&lt;br /&gt;
#define LCD_RS          AT91C_PIO_PA12&lt;br /&gt;
#define LCD_A0          AT91C_PIO_PA24&lt;br /&gt;
#define LCD_SCK         AT91C_PIO_PA14&lt;br /&gt;
#define LCD_MOSI        AT91C_PIO_PA13&lt;br /&gt;
#define LCD_PIO         AT91C_BASE_PIOA&lt;br /&gt;
#define LCD_PIO_ID      AT91C_ID_PIOA&lt;br /&gt;
// Define which peripherial Port has to be used&lt;br /&gt;
#define LCD_PIO_A       LCD_MOSI |  LCD_SCK | LCD_CSB  | LCD_LED  | AT91C_PIO_PA1&lt;br /&gt;
#define LCD_PIO_B      0&lt;br /&gt;
&lt;br /&gt;
#define LCD_SPI         AT91C_BASE_SPI&lt;br /&gt;
&lt;br /&gt;
#define BUTTON_E        AT91C_PIO_PA17&lt;br /&gt;
#define BUTTON_D        AT91C_PIO_PA28&lt;br /&gt;
#define BUTTON_ROT_A        AT91C_PIO_PA31&lt;br /&gt;
#define BUTTON_ROT_B        AT91C_PIO_PA30&lt;br /&gt;
#define BUTTON_ROT_C        AT91C_PIO_PA29&lt;br /&gt;
&lt;br /&gt;
#define IR_IN       AT91C_PIO_PA5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Wie es weiter geht ===&lt;br /&gt;
&lt;br /&gt;
Als Betriebsystem habe ich mich für ChibiOS entscheiden. Die Nutzung ist aber noch nicht sehr weit gediehen. &lt;br /&gt;
&lt;br /&gt;
Als Treiber habe ich den usb-skeleton Treiber angepasst. &lt;br /&gt;
&lt;br /&gt;
Von lcdProc  lässt sich der text Treiber leicht modifzieren, so dass er die Zeilen in das bereit gestellte device schreibt.&lt;br /&gt;
&lt;br /&gt;
Da ich keine Vendor ID besitze und ich auch keinen Vendor-ID besitzer kenne, der mir eine Product ID überlässt, kann ich den Quelltext leider noch nicht in gänze bereit stellen, da ich die vorhanden IDs nicht verwenden darf. Jeder nutzer müsste dann erst seine eigene ID eintragen und dann alles neu compilieren.&lt;br /&gt;
&lt;br /&gt;
Nach nun mehr zwei drei Monaten der unregelmäßigen Wochenendarbeit, kann meine MythTV Installation nun ein dreizeiliges Display ansteuern. Die 4. Zeile ist noch der Debug Ausgabe gewittmet, in der man die Dasten stati, die aktuelle Position des Drehimpulsgebers und die Systemticks sehen kann. &lt;br /&gt;
&lt;br /&gt;
Ein Unschönheit ist, dass die Interrupt programmierung sehr fehler anfällig ist und das Target hin und wieder stehen blieb, wenn der Taskwechsel zum falschen Zeitpunkt kommt.&lt;br /&gt;
&lt;br /&gt;
Unschön ist auch, dass das Device noch keinen USB-Reconnect auslösen kann, so dass der Treiber neu initialisiert wird. Aus diesem Grund, funktioniert USB nur bei einem kalten neustart, bei einem Reset per Knof oder Jtag funktioniert der Reconnect nicht. Hinweise sind zu diesem Problem sind auch willkommen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hinweise zu den bereit gestellten Dateien ==&lt;br /&gt;
&lt;br /&gt;
Die evtl. hier herunter ladbaren Dateien spiegeln den jeweiligen Stand der Entwicklung wieder. Bisher wurde nur die Version 1 (5/08) der Platine tatsächlich aufgebaut und gefertigt. Um aber dem Interessierten Leser eine Chance zu geben nicht die gleichen Fehler zu machen, habe ich die Platine überarbeitet und als Version 3 (8/08) ebenfalls beigelegt. Die Software ist für diese Version noch nicht angepasst. Es muss vor allem PWM3 statt PWM1 verwendet werden. Da der jeweils andere Pin in den anderen Versionen nicht belegt ist, kann die Software beide PWMs gleichzeitig benutzen.&lt;br /&gt;
&lt;br /&gt;
Folgende Bugs sind in der Platine 5/08 bekannt:&lt;br /&gt;
 * Kontraspannung des Displays mit +3.3V kurz geschlossen. Lösung: Zwei Leiterbahnen trennen. Einen Kondensator einlöten und einen Fädeldraht entsprechend Anleitung ziehen.&lt;br /&gt;
 * Der Reset Baustein MAX809 hat kein brauchbares Footprint. Lösung: weglassen! Die Platine funktioniert auch ohne.&lt;br /&gt;
 * R3 Muss möglichst nahe zur Platinen innenseite Angelötet werden. Und mit geeignetem Material, z.B. Tesafilm isoliert werden&lt;br /&gt;
 * R11 Muss leider entfallen. Die Platine funktioniert aber auch ohne. Aus symetrie Gründen kann R24 ebenfalls entfallen.&lt;br /&gt;
 * R20 und R19 müssen nicht bestückt werden, weil wenn der Prozessor strom hat, liegt auch am Bus Spannung an.&lt;br /&gt;
&lt;br /&gt;
Ich lade nur Dateien hoch, in denen klar ist, dass ich sie hochladen darf. Weil sie unter der GPL stehen oder ich sie erstellt habe. Die Datei, die die Product-ID enthält kann ich nicht hochladen. Meine Prorgamm-Dateien dürfen entsprechend der GPL3  genutzt werden. Dieser Artikel darf entsprechend der Creative Commons verwendet werden. Das Eagle Layout darf für eigene Projekte verwendet werden. In der Dokumentation soll auf die Quelle hingewiesen werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Todo =&lt;br /&gt;
&lt;br /&gt;
 * Grafiken hochladen&lt;br /&gt;
 * Dateien mit zweifel losem Urhberrecht bzw. Lizenz hochladen&lt;br /&gt;
 * Text auf vollständigkeit und Verständnis prüfen&lt;br /&gt;
 * Text korrektur lesen&lt;br /&gt;
 * Links auf verwendete Literatur, insebsondere Datenblätter&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fragen und Anregungen sind willkommen. Insbesondere ein Hinweis zu einer Product ID würde helfen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Wettbewerb]]&lt;/div&gt;</summary>
		<author><name>Thorstenw</name></author>
	</entry>
</feed>