<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
		<id>https://rn-wissen.de/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ofenrohr</id>
		<title>RN-Wissen.de - Benutzerbeiträge [de]</title>
		<link rel="self" type="application/atom+xml" href="https://rn-wissen.de/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ofenrohr"/>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Spezial:Beitr%C3%A4ge/Ofenrohr"/>
		<updated>2026-04-11T16:13:55Z</updated>
		<subtitle>Benutzerbeiträge</subtitle>
		<generator>MediaWiki 1.25.1</generator>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17107</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17107"/>
				<updated>2010-12-22T19:10:11Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Makefile */ Weitere Erklärung zum Makefile&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird. (In der Datei snes.h wird dieses Register snes_keys genannt)&lt;br /&gt;
&lt;br /&gt;
High Byte (snes_keys &amp;amp; 0xff00):&lt;br /&gt;
{{Registertabelle8Bit|n.c|n.c.|n.c.|n.c.|R|L|X|A}}&lt;br /&gt;
Low Byte (snes_keys &amp;amp; 0x00ff):&lt;br /&gt;
{{Registertabelle8Bit|B|Y|SELECT|START|RAUF|RUNTER|LINKS|RECHTS}}&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint8_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint8_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben. Dieses Makefile ist auf ein USB Arduino Board eingestellt. Bei anderen Boards sollten MMCU (AVR Typ) und PROGRAMMER im Makefile angepasst werden. Wenn weitere Header Dateien (*.h) hinzukommen sollten diese als Abhängigkeit in der folgenden Zeile hinzugefügt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Erklärung der einzelnen Befehle:&lt;br /&gt;
&lt;br /&gt;
make = Compilieren&lt;br /&gt;
&lt;br /&gt;
make clean = Aufräumen&lt;br /&gt;
&lt;br /&gt;
make upload = Programm auf Arduino laden&lt;br /&gt;
&lt;br /&gt;
make link = Nur notwendig auf Gentoo Systemen (einmal in jedem Projekt Ordner)&lt;br /&gt;
&lt;br /&gt;
make dump = Programm in Assembler ausgeben lassen&lt;br /&gt;
&lt;br /&gt;
make size = Speicherverbrauch des Programms anzeigen&lt;br /&gt;
&lt;br /&gt;
make screen = Verbindung mit Arduino herstellen (USART)&lt;br /&gt;
&lt;br /&gt;
make hexdump = USART Daten in Hex ausgeben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17106</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17106"/>
				<updated>2010-12-22T18:52:12Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* snes.h */ snes_key_pressed verbessert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird. (In der Datei snes.h wird dieses Register snes_keys genannt)&lt;br /&gt;
&lt;br /&gt;
High Byte (snes_keys &amp;amp; 0xff00):&lt;br /&gt;
{{Registertabelle8Bit|n.c|n.c.|n.c.|n.c.|R|L|X|A}}&lt;br /&gt;
Low Byte (snes_keys &amp;amp; 0x00ff):&lt;br /&gt;
{{Registertabelle8Bit|B|Y|SELECT|START|RAUF|RUNTER|LINKS|RECHTS}}&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint8_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint8_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben.&lt;br /&gt;
&lt;br /&gt;
Eine Erklärung der einzelnen Befehle:&lt;br /&gt;
&lt;br /&gt;
make = Compilieren&lt;br /&gt;
&lt;br /&gt;
make clean = Aufräumen&lt;br /&gt;
&lt;br /&gt;
make upload = Programm auf Arduino laden&lt;br /&gt;
&lt;br /&gt;
make link = Nur notwendig auf Gentoo Systemen (einmal in jedem Projekt Ordner)&lt;br /&gt;
&lt;br /&gt;
make dump = Programm in Assembler ausgeben lassen&lt;br /&gt;
&lt;br /&gt;
make size = Speicherverbrauch des Programms anzeigen&lt;br /&gt;
&lt;br /&gt;
make screen = Verbindung mit Arduino herstellen (USART)&lt;br /&gt;
&lt;br /&gt;
make hexdump = USART Daten in Hex ausgeben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Kategorie_Diskussion:Quellcode_C&amp;diff=17105</id>
		<title>Kategorie Diskussion:Quellcode C</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Kategorie_Diskussion:Quellcode_C&amp;diff=17105"/>
				<updated>2010-12-21T21:11:18Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Sortierung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Sortierung==&lt;br /&gt;
Hallo,&lt;br /&gt;
&lt;br /&gt;
wieso wird die von mir geschriebene, neue Seite [[SNES Controller]] nicht unter 'S' sondern unter '!' angezeigt?&lt;br /&gt;
&lt;br /&gt;
Und ist die Kategorie Quellcode C nicht eigentlich eine Art Code-Pool?&lt;br /&gt;
Auf AVRs braucht es meistens etwas mehr Erklärungen zum Code, wodurch sich die Form Seite = Erklärung + Schaltplan + C Code + Beispiel anbietet und hier auch in Artikeln verwendet wird.&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Ofenrohr|Ofenrohr]] 22:05, 21. Dez 2010 (CET)&lt;br /&gt;
&lt;br /&gt;
== Code-Pool==&lt;br /&gt;
Mehrfach wurde angeregt einen Code-Pool für avr-gcc C zu schaffen.&lt;br /&gt;
&lt;br /&gt;
Da der Artikel zu avr-gcc nicht der geeignete Ort dafür ist, bietet sich -- wenn überhaupt -- ein eigener Artikel an.&lt;br /&gt;
&lt;br /&gt;
Nun ist ein Code-Pool kein normaler Artikel, und bevor man damit anfängt, sollte diskutiert werden, wie weit sowas überhaupt sinnvoll ist und wenn ja, in welcher Form.&lt;br /&gt;
&lt;br /&gt;
Einfach nur ein copy &amp;amp;&amp;amp;amp; paste des Codes in den Artikel bringt keinem was.&lt;br /&gt;
&lt;br /&gt;
Zu bedenken gebe ich mal&lt;br /&gt;
&lt;br /&gt;
* welche Code-Convention sollten eingehalten werden?&lt;br /&gt;
** ANSI-C?&lt;br /&gt;
** Dokumentierung&lt;br /&gt;
** Kommentierung&lt;br /&gt;
** Indentation&lt;br /&gt;
** Naming Conventions für Makros, typedefs, Funktionen, etc&lt;br /&gt;
&lt;br /&gt;
* Was ist das für Code?&lt;br /&gt;
** Funktionsbeschreibung / Interfaces / Prototypen / Synopsis / Spezifikation...&lt;br /&gt;
** ein komplettes Modul&lt;br /&gt;
** eine Funktion&lt;br /&gt;
** nur ein Schnippsel&lt;br /&gt;
** pseudo-Code&lt;br /&gt;
** dient das als Vorlage oder soll es 'out of the box' funktionieren?&lt;br /&gt;
&lt;br /&gt;
* Wie weit reicht der Code?&lt;br /&gt;
** Stärken, Schwächen&lt;br /&gt;
** Unzulänglichkeiten und bekannte Fehler&lt;br /&gt;
&lt;br /&gt;
* Ist der Code getestet?&lt;br /&gt;
** Für welche Controller?&lt;br /&gt;
** Ist das halbwegs portierbar?&lt;br /&gt;
** Welche Änderungen wären dazu vorzunehmen?&lt;br /&gt;
** inwieweit ist das ganze maschinen(un)abhängig?&lt;br /&gt;
&lt;br /&gt;
* Kosten und Gewinn&lt;br /&gt;
** Was wird verbraucht?&lt;br /&gt;
*** flash&lt;br /&gt;
*** SRAM&lt;br /&gt;
*** EEPROM&lt;br /&gt;
*** Laufzeit&lt;br /&gt;
*** Hardware (Timer, I/O, Interrupt-Vektoren)&lt;br /&gt;
** warum steht der Code im Artikel?&lt;br /&gt;
** warum könn(t)en andere davon profitieren?&lt;br /&gt;
&lt;br /&gt;
* Wie könnten Versionierung / bugfixes / Erweiterungen /Diskussionen aussehen&lt;br /&gt;
&lt;br /&gt;
* Welche Nebeneffekte treten auf?&lt;br /&gt;
** müssen IRQs aktiv sein?&lt;br /&gt;
** was ändert sich, wenn ISRs (nicht mehr) kaskadieren dürfen/müssen?&lt;br /&gt;
** globale Variablen?&lt;br /&gt;
&lt;br /&gt;
* Ist der Code geeignet für eine Bibliothek?&lt;br /&gt;
** Was muss zur Compilezeit bekannt sein? Wann muss er neu generiert werden?&lt;br /&gt;
** was ist zu ändern, um den Code in eine Bibliothek aufnehmen zu können?&lt;br /&gt;
&lt;br /&gt;
* Wie wird der Code einsortiert?&lt;br /&gt;
** Nach Funktion (schwierig, da oft mehrere Dinge erledigt werden)&lt;br /&gt;
** nach Qualität&lt;br /&gt;
** komplettes, sauber implementiertes portierbares Modul oder nur Schnippsel?&lt;br /&gt;
&lt;br /&gt;
* Wie wird Überschaubarkeit gewahrt?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]] 17:14, 2. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
== Nicht gleich so komplexe Anforderungen? ==&lt;br /&gt;
&lt;br /&gt;
Ich würde nicht gleich so komplexe Maßstäbe an die Beispiele anlegen. Du musst bedenken das das Wiki auch Einsteigergerecht sein soll, mit zuvielen Richtlinien verschreckt man die Mitwirkkenden. Zudem programmieren im ROboternetz nur relativ wenige wirklich in C.&lt;br /&gt;
Ich denke man sollte Step bei Step vorgehen. Starte doch erst mal mit einem kleinen Beispiel so wie du es Dir denkt. Man kann immer noch editieren und umstellen wenn sich das Form als ungünstig erwiesen hat.&lt;br /&gt;
Wichtig ist es das es auch dem C-Einsteiger nützt und das es schnell verständlich ist.&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Frank|Frank]] 11:25, 3. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
Das wart eher als Brainstorm zu verstehen, nicht als Maximalforderung. &lt;br /&gt;
&lt;br /&gt;
Daß der Code verstanden und richtig eingesetzt wierden kann, setzt IMHO ein gewissen Mindestmaß an Beschreibung/Qualität voraus.&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]] 14:04, 3. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
== Feedback ==&lt;br /&gt;
&lt;br /&gt;
Vielleicht gebt ihr hier Rückmeldungen, ob ihr überhaupt was mit dem Code anfangen könnt.&lt;br /&gt;
z.B.&lt;br /&gt;
* Das ist der absolute Code, danke!&lt;br /&gt;
* Das Zeug ist unbrauchbar und Schrott&lt;br /&gt;
* Naja, netter Versuch, aber was soll der Schotter?&lt;br /&gt;
* Ist zu kompliziert und zu schwer zu verstehen, damit kann ich nix anfangen&lt;br /&gt;
* Was sollte hier für Code stehen?&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Kategorie_Diskussion:Quellcode_C&amp;diff=17104</id>
		<title>Kategorie Diskussion:Quellcode C</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Kategorie_Diskussion:Quellcode_C&amp;diff=17104"/>
				<updated>2010-12-21T21:05:26Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Sortierung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Sortierung==&lt;br /&gt;
Hallo,&lt;br /&gt;
&lt;br /&gt;
wieso wird die von mir geschriebene, neue Seite [[SNES Controller]] nicht unter 'S' sondern unter '!' angezeigt?&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Ofenrohr|Ofenrohr]] 22:05, 21. Dez 2010 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Code-Pool==&lt;br /&gt;
Mehrfach wurde angeregt einen Code-Pool für avr-gcc C zu schaffen.&lt;br /&gt;
&lt;br /&gt;
Da der Artikel zu avr-gcc nicht der geeignete Ort dafür ist, bietet sich -- wenn überhaupt -- ein eigener Artikel an.&lt;br /&gt;
&lt;br /&gt;
Nun ist ein Code-Pool kein normaler Artikel, und bevor man damit anfängt, sollte diskutiert werden, wie weit sowas überhaupt sinnvoll ist und wenn ja, in welcher Form.&lt;br /&gt;
&lt;br /&gt;
Einfach nur ein copy &amp;amp;&amp;amp;amp; paste des Codes in den Artikel bringt keinem was.&lt;br /&gt;
&lt;br /&gt;
Zu bedenken gebe ich mal&lt;br /&gt;
&lt;br /&gt;
* welche Code-Convention sollten eingehalten werden?&lt;br /&gt;
** ANSI-C?&lt;br /&gt;
** Dokumentierung&lt;br /&gt;
** Kommentierung&lt;br /&gt;
** Indentation&lt;br /&gt;
** Naming Conventions für Makros, typedefs, Funktionen, etc&lt;br /&gt;
&lt;br /&gt;
* Was ist das für Code?&lt;br /&gt;
** Funktionsbeschreibung / Interfaces / Prototypen / Synopsis / Spezifikation...&lt;br /&gt;
** ein komplettes Modul&lt;br /&gt;
** eine Funktion&lt;br /&gt;
** nur ein Schnippsel&lt;br /&gt;
** pseudo-Code&lt;br /&gt;
** dient das als Vorlage oder soll es 'out of the box' funktionieren?&lt;br /&gt;
&lt;br /&gt;
* Wie weit reicht der Code?&lt;br /&gt;
** Stärken, Schwächen&lt;br /&gt;
** Unzulänglichkeiten und bekannte Fehler&lt;br /&gt;
&lt;br /&gt;
* Ist der Code getestet?&lt;br /&gt;
** Für welche Controller?&lt;br /&gt;
** Ist das halbwegs portierbar?&lt;br /&gt;
** Welche Änderungen wären dazu vorzunehmen?&lt;br /&gt;
** inwieweit ist das ganze maschinen(un)abhängig?&lt;br /&gt;
&lt;br /&gt;
* Kosten und Gewinn&lt;br /&gt;
** Was wird verbraucht?&lt;br /&gt;
*** flash&lt;br /&gt;
*** SRAM&lt;br /&gt;
*** EEPROM&lt;br /&gt;
*** Laufzeit&lt;br /&gt;
*** Hardware (Timer, I/O, Interrupt-Vektoren)&lt;br /&gt;
** warum steht der Code im Artikel?&lt;br /&gt;
** warum könn(t)en andere davon profitieren?&lt;br /&gt;
&lt;br /&gt;
* Wie könnten Versionierung / bugfixes / Erweiterungen /Diskussionen aussehen&lt;br /&gt;
&lt;br /&gt;
* Welche Nebeneffekte treten auf?&lt;br /&gt;
** müssen IRQs aktiv sein?&lt;br /&gt;
** was ändert sich, wenn ISRs (nicht mehr) kaskadieren dürfen/müssen?&lt;br /&gt;
** globale Variablen?&lt;br /&gt;
&lt;br /&gt;
* Ist der Code geeignet für eine Bibliothek?&lt;br /&gt;
** Was muss zur Compilezeit bekannt sein? Wann muss er neu generiert werden?&lt;br /&gt;
** was ist zu ändern, um den Code in eine Bibliothek aufnehmen zu können?&lt;br /&gt;
&lt;br /&gt;
* Wie wird der Code einsortiert?&lt;br /&gt;
** Nach Funktion (schwierig, da oft mehrere Dinge erledigt werden)&lt;br /&gt;
** nach Qualität&lt;br /&gt;
** komplettes, sauber implementiertes portierbares Modul oder nur Schnippsel?&lt;br /&gt;
&lt;br /&gt;
* Wie wird Überschaubarkeit gewahrt?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]] 17:14, 2. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
== Nicht gleich so komplexe Anforderungen? ==&lt;br /&gt;
&lt;br /&gt;
Ich würde nicht gleich so komplexe Maßstäbe an die Beispiele anlegen. Du musst bedenken das das Wiki auch Einsteigergerecht sein soll, mit zuvielen Richtlinien verschreckt man die Mitwirkkenden. Zudem programmieren im ROboternetz nur relativ wenige wirklich in C.&lt;br /&gt;
Ich denke man sollte Step bei Step vorgehen. Starte doch erst mal mit einem kleinen Beispiel so wie du es Dir denkt. Man kann immer noch editieren und umstellen wenn sich das Form als ungünstig erwiesen hat.&lt;br /&gt;
Wichtig ist es das es auch dem C-Einsteiger nützt und das es schnell verständlich ist.&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Frank|Frank]] 11:25, 3. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
Das wart eher als Brainstorm zu verstehen, nicht als Maximalforderung. &lt;br /&gt;
&lt;br /&gt;
Daß der Code verstanden und richtig eingesetzt wierden kann, setzt IMHO ein gewissen Mindestmaß an Beschreibung/Qualität voraus.&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]] 14:04, 3. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
== Feedback ==&lt;br /&gt;
&lt;br /&gt;
Vielleicht gebt ihr hier Rückmeldungen, ob ihr überhaupt was mit dem Code anfangen könnt.&lt;br /&gt;
z.B.&lt;br /&gt;
* Das ist der absolute Code, danke!&lt;br /&gt;
* Das Zeug ist unbrauchbar und Schrott&lt;br /&gt;
* Naja, netter Versuch, aber was soll der Schotter?&lt;br /&gt;
* Ist zu kompliziert und zu schwer zu verstehen, damit kann ich nix anfangen&lt;br /&gt;
* Was sollte hier für Code stehen?&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17103</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17103"/>
				<updated>2010-12-21T20:55:11Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Elektronik */ Registerbeschreibung hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird. (In der Datei snes.h wird dieses Register snes_keys genannt)&lt;br /&gt;
&lt;br /&gt;
High Byte (snes_keys &amp;amp; 0xff00):&lt;br /&gt;
{{Registertabelle8Bit|n.c|n.c.|n.c.|n.c.|R|L|X|A}}&lt;br /&gt;
Low Byte (snes_keys &amp;amp; 0x00ff):&lt;br /&gt;
{{Registertabelle8Bit|B|Y|SELECT|START|RAUF|RUNTER|LINKS|RECHTS}}&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben.&lt;br /&gt;
&lt;br /&gt;
Eine Erklärung der einzelnen Befehle:&lt;br /&gt;
&lt;br /&gt;
make = Compilieren&lt;br /&gt;
&lt;br /&gt;
make clean = Aufräumen&lt;br /&gt;
&lt;br /&gt;
make upload = Programm auf Arduino laden&lt;br /&gt;
&lt;br /&gt;
make link = Nur notwendig auf Gentoo Systemen (einmal in jedem Projekt Ordner)&lt;br /&gt;
&lt;br /&gt;
make dump = Programm in Assembler ausgeben lassen&lt;br /&gt;
&lt;br /&gt;
make size = Speicherverbrauch des Programms anzeigen&lt;br /&gt;
&lt;br /&gt;
make screen = Verbindung mit Arduino herstellen (USART)&lt;br /&gt;
&lt;br /&gt;
make hexdump = USART Daten in Hex ausgeben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17102</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17102"/>
				<updated>2010-12-21T20:44:21Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* snes.h */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird. (In der Datei snes.h wird dieses Register snes_keys genannt)&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben.&lt;br /&gt;
&lt;br /&gt;
Eine Erklärung der einzelnen Befehle:&lt;br /&gt;
&lt;br /&gt;
make = Compilieren&lt;br /&gt;
&lt;br /&gt;
make clean = Aufräumen&lt;br /&gt;
&lt;br /&gt;
make upload = Programm auf Arduino laden&lt;br /&gt;
&lt;br /&gt;
make link = Nur notwendig auf Gentoo Systemen (einmal in jedem Projekt Ordner)&lt;br /&gt;
&lt;br /&gt;
make dump = Programm in Assembler ausgeben lassen&lt;br /&gt;
&lt;br /&gt;
make size = Speicherverbrauch des Programms anzeigen&lt;br /&gt;
&lt;br /&gt;
make screen = Verbindung mit Arduino herstellen (USART)&lt;br /&gt;
&lt;br /&gt;
make hexdump = USART Daten in Hex ausgeben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17101</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17101"/>
				<updated>2010-12-21T20:41:00Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* snes.h */ volatile bei snes_keys entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird. (In der Datei snes.h wird dieses Register snes_keys genannt)&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben.&lt;br /&gt;
&lt;br /&gt;
Eine Erklärung der einzelnen Befehle:&lt;br /&gt;
&lt;br /&gt;
make = Compilieren&lt;br /&gt;
&lt;br /&gt;
make clean = Aufräumen&lt;br /&gt;
&lt;br /&gt;
make upload = Programm auf Arduino laden&lt;br /&gt;
&lt;br /&gt;
make link = Nur notwendig auf Gentoo Systemen (einmal in jedem Projekt Ordner)&lt;br /&gt;
&lt;br /&gt;
make dump = Programm in Assembler ausgeben lassen&lt;br /&gt;
&lt;br /&gt;
make size = Speicherverbrauch des Programms anzeigen&lt;br /&gt;
&lt;br /&gt;
make screen = Verbindung mit Arduino herstellen (USART)&lt;br /&gt;
&lt;br /&gt;
make hexdump = USART Daten in Hex ausgeben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17100</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17100"/>
				<updated>2010-12-21T20:39:21Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Elektronik */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird. (In der Datei snes.h wird dieses Register snes_keys genannt)&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static volatile uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben.&lt;br /&gt;
&lt;br /&gt;
Eine Erklärung der einzelnen Befehle:&lt;br /&gt;
&lt;br /&gt;
make = Compilieren&lt;br /&gt;
&lt;br /&gt;
make clean = Aufräumen&lt;br /&gt;
&lt;br /&gt;
make upload = Programm auf Arduino laden&lt;br /&gt;
&lt;br /&gt;
make link = Nur notwendig auf Gentoo Systemen (einmal in jedem Projekt Ordner)&lt;br /&gt;
&lt;br /&gt;
make dump = Programm in Assembler ausgeben lassen&lt;br /&gt;
&lt;br /&gt;
make size = Speicherverbrauch des Programms anzeigen&lt;br /&gt;
&lt;br /&gt;
make screen = Verbindung mit Arduino herstellen (USART)&lt;br /&gt;
&lt;br /&gt;
make hexdump = USART Daten in Hex ausgeben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17099</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17099"/>
				<updated>2010-12-21T20:25:31Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Makefile */ Befehlserklärungen hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird.&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static volatile uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben.&lt;br /&gt;
&lt;br /&gt;
Eine Erklärung der einzelnen Befehle:&lt;br /&gt;
&lt;br /&gt;
make = Compilieren&lt;br /&gt;
&lt;br /&gt;
make clean = Aufräumen&lt;br /&gt;
&lt;br /&gt;
make upload = Programm auf Arduino laden&lt;br /&gt;
&lt;br /&gt;
make link = Nur notwendig auf Gentoo Systemen (einmal in jedem Projekt Ordner)&lt;br /&gt;
&lt;br /&gt;
make dump = Programm in Assembler ausgeben lassen&lt;br /&gt;
&lt;br /&gt;
make size = Speicherverbrauch des Programms anzeigen&lt;br /&gt;
&lt;br /&gt;
make screen = Verbindung mit Arduino herstellen (USART)&lt;br /&gt;
&lt;br /&gt;
make hexdump = USART Daten in Hex ausgeben&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17097</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17097"/>
				<updated>2010-12-21T20:16:51Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Software */ Makefile für Linuxuser&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird.&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static volatile uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
Da ich auf Linuxumgebungen programmiere, habe ich mir ein Makefile für oft verwendete Befehle geschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CC	= avr-gcc&lt;br /&gt;
OCP	= avr-objcopy&lt;br /&gt;
MMCU	= atmega168&lt;br /&gt;
CFLAGS	= -Os -g -mmcu=$(MMCU)&lt;br /&gt;
PORT	= /dev/ttyUSB0&lt;br /&gt;
BAUD = 19200&lt;br /&gt;
PROGRAMMER = stk500v1&lt;br /&gt;
TARGET 	= m168&lt;br /&gt;
SRC	= main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$(SRC).hex : $(SRC).elf&lt;br /&gt;
	$(OCP) -j .text -O ihex $(SRC).elf $(SRC).hex&lt;br /&gt;
&lt;br /&gt;
$(SRC).elf : $(SRC).o&lt;br /&gt;
	$(CC) $(SRC).o -o $(SRC).elf -mmcu=$(MMCU)&lt;br /&gt;
&lt;br /&gt;
$(SRC).o : $(SRC).c snes.h&lt;br /&gt;
	$(CC) $(SRC).c $(CFLAGS) -c -o $(SRC).o&lt;br /&gt;
&lt;br /&gt;
clean :&lt;br /&gt;
	rm *.o *.elf *.hex&lt;br /&gt;
&lt;br /&gt;
upload : $(SRC).hex&lt;br /&gt;
	avrdude -C /etc/avrdude.conf -p$(TARGET) -c$(PROGRAMMER) -P$(PORT) -b$(BAUD) -D -Uflash:w:$(SRC).hex -F&lt;br /&gt;
&lt;br /&gt;
link :&lt;br /&gt;
	ln -s /usr/lib/binutils/avr/2.19.1/ldscripts/ ldscripts&lt;br /&gt;
&lt;br /&gt;
dump : $(SRC).elf&lt;br /&gt;
	avr-objdump -S -d -j .text -j .data $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
size : $(SRC).o&lt;br /&gt;
	avr-size -x -A --target=ihex $(SRC).o&lt;br /&gt;
	avr-nm --size-sort -S  $(SRC).elf&lt;br /&gt;
&lt;br /&gt;
screen :&lt;br /&gt;
	screen /dev/ttyUSB0 9600&lt;br /&gt;
&lt;br /&gt;
hexdump :&lt;br /&gt;
	cat /dev/ttyUSB0 | hexdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17096</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17096"/>
				<updated>2010-12-21T20:14:08Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Software */ Unterkategorien&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird.&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
===snes.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static volatile uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===main.c===&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17095</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17095"/>
				<updated>2010-12-21T20:13:08Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Software */ Beispiel (main.c) hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird.&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
snes.h&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_REPEAT_DELAY 0x0fff;&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static volatile uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=SNES_REPEAT_DELAY;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel wechselt den Zustand der LED (an / aus) bei Tastendruck auf A oder B des SNES Controllers. Taste B ist verlangsamt, während bei A das Register (snes_keys) direkt ausgelesen wird.&lt;br /&gt;
&lt;br /&gt;
main.c&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define F_CPU 16000000L&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;quot;snes.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Arduino Belegung:&lt;br /&gt;
 *  0-7: PORTD&lt;br /&gt;
 *  8-13: PORTB (LED auf 13)&lt;br /&gt;
 *  Analog: PORTC&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/* LED an- bzw. ausschalten */&lt;br /&gt;
void toggle_led() {&lt;br /&gt;
	if (PORTB &amp;amp; 0x20) {&lt;br /&gt;
		PORTB &amp;amp;= ~(0x20);&lt;br /&gt;
	} else {&lt;br /&gt;
		PORTB |= 0x20;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	/* init led */&lt;br /&gt;
	DDRB = 0x20;&lt;br /&gt;
	/* init snes gamepad */&lt;br /&gt;
	snes_init();&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* Register auslesen */&lt;br /&gt;
		snes_update();&lt;br /&gt;
		/* Register (snes_keys) auswerten */&lt;br /&gt;
		/* Tastendruck mit Verzoegerung */&lt;br /&gt;
		if (snes_key_pressed(SNES_KEY_B)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
		/* Tastendruck ohne Verzoegerung */&lt;br /&gt;
		if (snes_keys &amp;amp; _BV(SNES_KEY_A)) {&lt;br /&gt;
			toggle_led();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17094</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17094"/>
				<updated>2010-12-21T19:44:05Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: /* Software */ Kommentar zu Anschlüssen hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird.&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
snes.h&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* snes Gamepad Einstellungen */&lt;br /&gt;
/* arduino: analog: 0:Clock, 1:Latch, 2:Data */&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
/* snes Tasten */&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;	&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;	&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
		&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=50;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17045</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17045"/>
				<updated>2010-12-07T20:53:22Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird.&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließen und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
snes.h&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;	&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;	&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
		&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=50;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17044</id>
		<title>SNES Controller</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=SNES_Controller&amp;diff=17044"/>
				<updated>2010-12-07T20:52:52Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: Erste Version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:SNES_Controller.jpg|thumb|Ein Supernintendo Controller]]&lt;br /&gt;
&lt;br /&gt;
'''SNES''' bedeutet Super Nintendo Entertainment System. Dieser Artikel erklärt die Verwendung (Schaltung und Programmierung in C) eines Supernintendo Controllers mit einem AVR.&lt;br /&gt;
&lt;br /&gt;
==Elektronik==&lt;br /&gt;
Der Controller beherbergt ein 16 Bit Schieberegister. Jede Taste entspricht einem Bit in diesem Register. Wird eine Taste gedrückt, wechselt das entsprechende Bit von 0 auf 1 und bleibt so lange auf 1, bis die Taste losgelassen wird.&lt;br /&gt;
&lt;br /&gt;
===Anschluss===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Snes controller pinout.jpg]]&lt;br /&gt;
&lt;br /&gt;
{|border=1&lt;br /&gt;
 |1&lt;br /&gt;
 | +5v&lt;br /&gt;
 |-&lt;br /&gt;
 |2&lt;br /&gt;
 |Clock&lt;br /&gt;
 |-&lt;br /&gt;
 |3&lt;br /&gt;
 |Latch&lt;br /&gt;
 |-&lt;br /&gt;
 |4&lt;br /&gt;
 |Data&lt;br /&gt;
 |-&lt;br /&gt;
 |5&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |6&lt;br /&gt;
 |nicht angeschlossen&lt;br /&gt;
 |-&lt;br /&gt;
 |7&lt;br /&gt;
 |Masse&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Stromversorgung anschließe und Clock, Latch und Data mit dem AVR verbinden.&lt;br /&gt;
Um möglichst unkompliziert eine sichere Verbindung mit den einzelnen Leitungen herzustellen, empfehle ich, den originalen Anschluss aus einem defekten SNES zu verwenden. Defekte Supernintendos gibts es bei Ebay günstig zu ersteigern.&lt;br /&gt;
&lt;br /&gt;
===Auslesen des Registers===&lt;br /&gt;
Um das Register auszulesen muss der SNES Controller zunächst initialisiert werden:&lt;br /&gt;
* Clock und Latch müssen am AVR als Output konfiguriert werden&lt;br /&gt;
* Data als Input mit Pullup Widerstand (Bit in DDRx auf 0, Bit in PORTx auf 1)&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die Datenübertragung initialisiert werden. Dieser Schritt muss bei jedem Auslesen des Registers durchgeführt werden.&lt;br /&gt;
* Latch auf 1&lt;br /&gt;
* 12 Mikrosekunden (im Folgenden &amp;quot;us&amp;quot;) warten&lt;br /&gt;
* Latch auf 0&lt;br /&gt;
&lt;br /&gt;
Nun können die 16 Bit des Registers wie folgt ausgelesen werden (folgendes also 16 Mal wiederholen):&lt;br /&gt;
* 6 us warten&lt;br /&gt;
* Clock auf 0&lt;br /&gt;
* Data auslesen und zwischenspeichern&lt;br /&gt;
* 6us warten&lt;br /&gt;
* Clock auf 1&lt;br /&gt;
&lt;br /&gt;
==Software==&lt;br /&gt;
Ich habe einen SNES Controller erfolgreich an einen Arduino (Mega168) angeschlossen und in C (avr-gcc, auf Linux) programmiert. Neben der Ansteuerung enthält mein Code auch eine Routine, welche die Tasten &amp;quot;verlangsamt&amp;quot;, damit die Verwendung in Programmen einfacher wird. Soll zum Beispiel die rote A Taste eine LED an- und ausschalten, würde diese ohne Verlangsamung mehrfach ein- und ausgeschaltet werden, bevor ein Mensch die Taste loslassen kann.&lt;br /&gt;
&lt;br /&gt;
snes.h&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright (C) 2009 by Tom Vincent Peters&lt;br /&gt;
 * code@ofenrohr.net&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software; you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program; if not, write to the&lt;br /&gt;
 * Free Software Foundation, Inc.,&lt;br /&gt;
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_DDR	DDRC&lt;br /&gt;
#define SNES_LATCH_PORT	PORTC&lt;br /&gt;
#define SNES_LATCH_BIT	0x02&lt;br /&gt;
&lt;br /&gt;
#define SNES_CLOCK_DDR	DDRC&lt;br /&gt;
#define SNES_CLOCK_PORT	PORTC&lt;br /&gt;
#define SNES_CLOCK_BIT  0x01&lt;br /&gt;
&lt;br /&gt;
#define SNES_DATA_PORT	PORTC&lt;br /&gt;
#define SNES_DATA_DDR	DDRC&lt;br /&gt;
#define SNES_DATA_PIN	PINC&lt;br /&gt;
#define SNES_DATA_BIT   0x04&lt;br /&gt;
&lt;br /&gt;
#define SNES_KEY_CNT	12&lt;br /&gt;
#define SNES_KEY_A	8&lt;br /&gt;
#define SNES_KEY_B	7&lt;br /&gt;
#define SNES_KEY_X	9&lt;br /&gt;
#define SNES_KEY_Y	6&lt;br /&gt;
#define SNES_KEY_L	10&lt;br /&gt;
#define SNES_KEY_R	11&lt;br /&gt;
#define SNES_KEY_UP	3&lt;br /&gt;
#define SNES_KEY_DOWN	2&lt;br /&gt;
#define SNES_KEY_LEFT	1&lt;br /&gt;
#define SNES_KEY_RIGHT	0&lt;br /&gt;
#define SNES_KEY_START	4&lt;br /&gt;
#define SNES_KEY_SELECT	5&lt;br /&gt;
&lt;br /&gt;
#define SNES_LATCH_LOW()	{ SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_BIT); }&lt;br /&gt;
#define SNES_LATCH_HIGH()	{ SNES_LATCH_PORT |= SNES_LATCH_BIT; }&lt;br /&gt;
#define SNES_CLOCK_LOW()	{ SNES_CLOCK_PORT &amp;amp;= ~(SNES_CLOCK_BIT); }&lt;br /&gt;
#define SNES_CLOCK_HIGH()	{ SNES_CLOCK_PORT |= SNES_CLOCK_BIT; }&lt;br /&gt;
&lt;br /&gt;
#define SNES_GET_DATA()	(SNES_DATA_PIN &amp;amp; SNES_DATA_BIT)&lt;br /&gt;
&lt;br /&gt;
static uint16_t snes_keys;&lt;br /&gt;
static uint16_t snes_key_repeat_delay[SNES_KEY_CNT];&lt;br /&gt;
&lt;br /&gt;
void snes_init(void);&lt;br /&gt;
void snes_update(void);&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void snes_init(void) {&lt;br /&gt;
	SNES_LATCH_DDR |= SNES_LATCH_BIT;&lt;br /&gt;
	SNES_CLOCK_DDR |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_DATA_DDR &amp;amp;= ~(SNES_DATA_BIT);&lt;br /&gt;
	SNES_DATA_PORT |= SNES_DATA_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_CLOCK_PORT |= SNES_CLOCK_BIT;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_PORT &amp;amp;= ~(SNES_LATCH_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void snes_update(void) {&lt;br /&gt;
	uint8_t i;&lt;br /&gt;
	uint8_t tmp=0;&lt;br /&gt;
	uint16_t ret=0;&lt;br /&gt;
&lt;br /&gt;
	SNES_LATCH_HIGH();&lt;br /&gt;
	_delay_us(12);&lt;br /&gt;
	SNES_LATCH_LOW();&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;lt;&amp;lt;= 1;	&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=1; }&lt;br /&gt;
&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys = tmp;&lt;br /&gt;
	for (i=0;i&amp;lt;8;i++) {&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_LOW();&lt;br /&gt;
&lt;br /&gt;
		tmp &amp;gt;&amp;gt;= 1;	&lt;br /&gt;
		if (!SNES_GET_DATA()) { tmp|=0x80; }&lt;br /&gt;
		&lt;br /&gt;
		_delay_us(6);&lt;br /&gt;
		SNES_CLOCK_HIGH();&lt;br /&gt;
	}&lt;br /&gt;
	snes_keys |= tmp&amp;lt;&amp;lt;8;&lt;br /&gt;
&lt;br /&gt;
	for (i=0;i&amp;lt;SNES_KEY_CNT;i++) {&lt;br /&gt;
		if (snes_key_repeat_delay[i]&amp;gt;0)&lt;br /&gt;
			snes_key_repeat_delay[i]--;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t snes_key_pressed(uint16_t key) {&lt;br /&gt;
	if (key&amp;gt;SNES_KEY_CNT) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (snes_keys&amp;amp;_BV(key)) {&lt;br /&gt;
		if (snes_key_repeat_delay[key]==0) {&lt;br /&gt;
			snes_key_repeat_delay[key]=50;&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		snes_key_repeat_delay[key]=0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Snes_controller_pinout.jpg&amp;diff=17043</id>
		<title>Datei:Snes controller pinout.jpg</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Snes_controller_pinout.jpg&amp;diff=17043"/>
				<updated>2010-12-07T19:53:29Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: Der Anschluss eines Supernintendo Controllers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der Anschluss eines Supernintendo Controllers&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:SNES_Controller.jpg&amp;diff=17042</id>
		<title>Datei:SNES Controller.jpg</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:SNES_Controller.jpg&amp;diff=17042"/>
				<updated>2010-12-07T19:41:10Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: Ein Supernintendo Controller&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein Supernintendo Controller&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Benutzer:Ofenrohr&amp;diff=17041</id>
		<title>Benutzer:Ofenrohr</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Benutzer:Ofenrohr&amp;diff=17041"/>
				<updated>2010-12-07T19:27:04Z</updated>
		
		<summary type="html">&lt;p&gt;Ofenrohr: Über mich / Intention&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ich programmiere in meiner Freizeit gelegentlich mit AVRs (Arduino, Pollin board).&lt;br /&gt;
Da ich einen beachtlichen Teil meines Wissens auf RN-Wissen erlangt habe, möchte ich nun etwas zurückgeben und ein paar Artikel über meine Erkenntnisse in avr-gcc, Linux und mit dem Arduino schreiben.&lt;/div&gt;</summary>
		<author><name>Ofenrohr</name></author>	</entry>

	</feed>