Dieses Projekt beschreibt sowohl die Kommunikation zwischen einem Arduino Mega und einem UPNP fähigen Router, als auch die serielle Kommunikation zwischen Gameboy und Arduino. Es handelt sich hierbei um einen Beitrag für den "Pimp your Fritz!"-Wettbewerb der Maker Faire 2015 in Berlin. Die Teilnahmebedingungen befinden sich hier. Die finalisten befinden sich auf der Seite von AVM. Die Gewinner bei Heise.
Foto (c) AVM
In der CT Make 1/2016 gibt es einen kurzen Artikel über den FritzBoy.
# | Bezeichnung | ~Preis |
1 | Gameboy (DMG) oder Gameboy Color | 30 € |
1 | USB 64m Smart card (z.B. von hier) | 50 € |
1 | Gameboy Link Kabel | 5 € |
1 | Arduino Mega | 15 € |
1 | Arduino Ethernet Shield | 10 € |
1 | Gehäuse (Optional) | 5 € |
~100 € |
Nachdem der Arduino Mega Mikrocontroller eine IP-Adresse von der Fritz!Box erhalten hat, sendet er einen SOAP-Request an sein Default-Gateway. In dieser Anfrage erfragt er die Eigenschaften des WAN-Interfaces und erhält die maximale Up- und Downloadbandbreite („NewLayer1UpstreamMaxBitRate“ und „NewLayer1DownstreamMaxBitRate“) zurück. Als nächstes fragt er periodisch, alle drei Sekunden, die aktuelle Bandbreitenauslastung ab („NewByteReceiveRate“ und „NewByteSendRate“). Die gesammelten Werte werden in Megabit umgerechnet und jede Sekunde über die serielle Schnittstelle an den Gameboy übertragen. Auf der Cartridge des Gameboys läuft ein Programm, welches auf der seriellen Schnittstelle lauscht und die letzten 50 empfangenen Werte auf einer Skala anzeigt.
Abgesehen vom Anlöten des Link-Kabels muss keine zusätzliche Hardware gebaut werden. Der Aufbau sieht wie folgt aus:
Hier noch ein Foto des Arduino Megas mit dem Ethernet Shield:
Nach dem Start des Gameboys kommt als Erstes der Splash-Screen:
Der Gameboy wartet dann auf serielle Signale:
Wenn diese empfangen werden, werden sie in einem Graphen angezeigt:
Hier der Code für den Gameboy. Das Übertragungsprotokoll sieht folgendermaßen aus:
Es werden immer 7 Byte übertragen, das ist zwar ineffizient, aber simpel:
Byte | Bedeutung | Gültige Werte | Beispiel |
0 | Aktueller relativer Downstream auf einer Skala von 0-50 | 0-50 | 30 / 50 |
1 | Aktueller relativer Upstream auf einer Skala von 0-50 | 0-50 | 3 / 50 |
2 | Absoluter aktueller Downstream | 0-254 | 44 Mbit/s |
3 | Absoluter aktueller Upstream | 0-254 | 5 Mbit/s |
4 | Maximaler Downstream | 0-254 | 50 Mbit/s |
5 | Maximaler Upstream | 0-254 | 10 Mbit/s |
6 | [End of Stream] | 255 | 255 |
Hinweis: Es handelt sich um unsignierte Bytes (UBYTE). Das sechste Byte gibt an, dass die Übertragung abgeschlossen wurde.
#include <gb/gb.h> #include <stdio.h> #include <gb/drawing.h> #include <rand.h> unsigned char tile_fritzbox[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x11, 0x10, 0x23, 0x20, 0x47, 0x40, 0x6E, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x10, 0x10, 0x20, 0x20, 0x40, 0x41, 0x8C, 0x80, 0x1E, 0x00, 0x3F, 0x00, 0x7F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xBF, 0x40, 0x7F, 0x80, 0xEF, 0x10, 0x3D, 0x32, 0x1F, 0x18, 0x0F, 0x0C, 0x07, 0x06, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0x20, 0xBB, 0x44, 0x77, 0x88, 0xEE, 0x11, 0xDD, 0x22, 0xFB, 0x84, 0xF7, 0xC8, 0x7E, 0x60, 0x3C, 0x30, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x90, 0x08, 0x08, 0x04, 0x24, 0x82, 0x12, 0xC1, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0xF8, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x50, 0x70, 0x50, 0x70, 0x50, 0x70, 0x50, 0x70, 0x50, 0x70, 0x50, 0x70, 0x50, 0x70, 0xD0, 0xF0, 0x50, 0x70, 0x30, 0x30, 0x10, 0x10, 0xFC, 0x00, 0xF8, 0x00, 0xF0, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0x81, 0x01, 0x03, 0x02, 0x07, 0x04, 0x0F, 0x09, 0x1F, 0x13, 0x3E, 0x26, 0x7C, 0x4C, 0xF8, 0x98, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x1C, 0x1C, 0x3C, 0x24, 0x7C, 0x4C, 0xF8, 0x98, 0xF0, 0x30, 0xE0, 0x60, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x70, 0x0F, 0x70, 0x08, 0x70, 0x08, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x70, 0x0F, 0x70, 0x08, 0x70, 0x08, 0x70, 0x08, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1C, 0x80, 0x7F, 0x80, 0x73, 0x08, 0x73, 0x08, 0x73, 0x08, 0x7F, 0x80, 0x7E, 0x81, 0x7C, 0x82, 0x7C, 0x00, 0x76, 0x08, 0x77, 0x08, 0x77, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x08, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x18, 0x00, 0x38, 0x04, 0x3B, 0x04, 0x3B, 0x04, 0xBB, 0x04, 0xB8, 0x45, 0xB8, 0x44, 0x38, 0x84, 0x38, 0x04, 0x38, 0x04, 0x38, 0x04, 0x38, 0x04, 0x00, 0x9C, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0x70, 0x8F, 0x70, 0x08, 0x70, 0x08, 0x70, 0x08, 0x70, 0x08, 0x70, 0x08, 0x70, 0x08, 0x70, 0x08, 0x70, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0E, 0x01, 0x1C, 0x03, 0x3F, 0x00, 0x7F, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0xF8, 0x00, 0xF0, 0x0C, 0xE0, 0x18, 0xC0, 0x30, 0x80, 0x60, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0xFC, 0x00, 0xFC, 0x02, 0xFC, 0x02, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE3, 0x42, 0xA2, 0x42, 0xA2, 0x42, 0xA2, 0x42, 0xA2, 0x43, 0xA3, 0x42, 0xA2, 0x02, 0xE2, 0x02, 0x02, 0x02, 0x42, 0x42, 0xA2, 0x03, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xC1, 0x22, 0x22, 0x24, 0x24, 0x24, 0x24, 0x44, 0x44, 0xF4, 0xF4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x22, 0x22, 0xC1, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xC4, 0x22, 0x22, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0xA0, 0xA0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0xA8, 0xA8, 0xF8, 0xF8, 0xD8, 0xD8, 0x00, 0x00, 0x18, 0x18, 0x20, 0x20, 0x20, 0x20, 0x79, 0x79, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x47, 0x89, 0x89, 0x09, 0x09, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x09, 0x09, 0x09, 0x09, 0x87, 0x87, 0x01, 0x01, 0x0F, 0x0F, 0x19, 0x19, 0x13, 0x13, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x12, 0x12, 0x72, 0x72, 0x92, 0x92, 0x92, 0x92, 0x71, 0x71, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x41, 0x41, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x89, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xC3, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x23, 0x23, 0x78, 0x78, 0x44, 0x44, 0x04, 0x04, 0x18, 0x18, 0x20, 0x20, 0x60, 0x60, 0x42, 0x42, 0x7C, 0x7C, 0x3C, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x3C, 0x08, 0x08, 0x18, 0x18, 0x28, 0x28, 0x48, 0x48, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7E, 0x7E, 0x40, 0x40, 0x40, 0x40, 0x3C, 0x3C, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x78, 0x78, 0x66, 0x66, 0x7E, 0x7E, 0x5A, 0x5A, 0x5A, 0x5A, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x64, 0x64, 0x44, 0x44, 0x44, 0x44, 0x43, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x44, 0x44, 0x7C, 0x7C, 0x40, 0x40, 0x3C, 0x3C, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x92, 0x92, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x46, 0x46, 0x49, 0x49, 0x49, 0x49, 0x47, 0x47, 0x01, 0x01, 0x0F, 0x0F, 0x19, 0x19, 0x13, 0x13, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x87, 0x87, 0x89, 0x89, 0x89, 0x89, 0x27, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x48, 0x48, 0x70, 0x70, 0x40, 0x40, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0xA8, 0xA8, 0xF8, 0xF8, 0xD9, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char map_fritzbox[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x12, 0x18, 0x1A, 0x20, 0x22, 0x28, 0x2A, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x13, 0x19, 0x1B, 0x21, 0x23, 0x29, 0x2B, 0x31, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x1C, 0x1E, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x09, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x0C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x07, 0x0D, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x3E, 0x3F, 0x40, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x4B, 0x35, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3C, 0x49, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int main () { UINT8 DEBUG = 0; UINT8 YPOSITION = 72; UINT8 GRAPHWIDTHFULL = 100; UINT8 GRAPHWIDTHHALF = 50; UBYTE max_downstream = 0; UBYTE max_upstream = 0; UBYTE current_downstream = 0; UBYTE current_upstream = 0; UINT8 XOFFSET = 30; UBYTE array_downstream[50]; // array for downstream values UBYTE array_upstream[50]; // array for upstream values UBYTE buffer[7]; // buffer for incoming transfer UBYTE i, n = 0; UBYTE random; UBYTE *s; UINT8 c; // For UINT8 position; UINT8 TMP = 2; UINT8 demomode = 0; UINT8 packetreceived = 0; // Show welcome screen set_bkg_data(0, 127, tile_fritzbox); set_bkg_tiles(0, 0, 20, 18, map_fritzbox); SHOW_BKG; DISPLAY_ON; for (c = 0; c != 100; c++) { delay(40); if (joypad() != 0) break; } // Initialize arrays for (c = 0; c < GRAPHWIDTHHALF; c++) { array_downstream[c] = 0; array_upstream[c] = 0; } for (c = 0; c < 8; c++) { buffer[c] = 0; } // Initialize random initarand(0x5F); // Draw a box color(LTGREY, WHITE, SOLID); box(XOFFSET - 1, YPOSITION - 52, XOFFSET + GRAPHWIDTHFULL - 1, YPOSITION + 52, M_NOFILL); // Draw a line in the middle color(BLACK, WHITE, SOLID); line(XOFFSET, YPOSITION, XOFFSET + GRAPHWIDTHFULL - 1, YPOSITION); // Write text gotogxy(1, 1); gprintf("Down:"); gotogxy(1, 16); gprintf("Up:"); while (1) { // Plot the values position = 1; for (c = 1; c < GRAPHWIDTHHALF; c++) { // Generate downstream values if (c == 0 || array_downstream[c] == array_downstream[c - 1]) { // Do nothing ; } else if (array_downstream[c] > array_downstream[c - 1]) { // New value is higher than the old one --> generate line color(DKGREY, WHITE, SOLID); line(XOFFSET + position, YPOSITION - 1, XOFFSET + position, (YPOSITION - 1) - array_downstream[c]); } else { // Erase the rest of the line for downstream color(WHITE, WHITE, SOLID); line(XOFFSET + position, (YPOSITION - 1) - array_downstream[c], XOFFSET + position, YPOSITION - 51); } // Generate upstream values if (c == 0 || array_upstream[c] > array_upstream[c - 1]) { // New value is higher than the old one --> generate line color(LTGREY, WHITE, SOLID); line(XOFFSET + position, YPOSITION + 1, XOFFSET + position, (YPOSITION + 1) + array_upstream[c]); } else { // Erase the rest of the line for upstream color(WHITE, WHITE, SOLID); line(XOFFSET + position, YPOSITION + 1 + array_upstream[c], XOFFSET + position, YPOSITION + 51); } // Generate point color(BLACK, WHITE, SOLID); plot_point(XOFFSET + position, YPOSITION - 1 - array_downstream[c]); plot_point(XOFFSET + position, YPOSITION + 1 + array_upstream[c]); position += 2; } // Set color to black for text color(BLACK, WHITE, SOLID); // Shift complete array to the left for (c = 0; c < GRAPHWIDTHHALF - 1; c++) { array_downstream[c] = array_downstream[c + 1]; array_upstream[c] = array_upstream[c + 1]; } // print current text-values downstream... if(packetreceived == 1){ gotogxy(6, 1); if (current_downstream == 0) gprintf("<1 ", current_downstream); else gprintf("%u ", current_downstream); gprintf("/ %u Mbit ", max_downstream); // ... and upstream gotogxy(6, 16); if (current_upstream == 0) gprintf("<1 ", current_upstream); else gprintf("%u ", current_upstream); gprintf("/ %u Mbit ", max_upstream); } else { color(DKGREY, WHITE, SOLID); gotogxy(5, 4); gprintf("connecting"); gotogxy(9, 5); gprintf("to"); gotogxy(5, 6); gprintf("Fritz!Boy"); gotogxy(9, 7); color(LTGREY, WHITE, SOLID); gotogxy(8, 11); gprintf("hold"); gotogxy(6, 12); gprintf("\"SELECT\""); gotogxy(6, 13); gprintf("for demo"); } // Receive new values from gotogxy(16, 16); s = buffer; if (DEBUG == 1) { // Debug the incoming values gotogxy(1, TMP); TMP++; TMP = TMP % 14; gprintf("IN:"); } while (1) { receive_byte(); /* Wait for IO completion... */ while (_io_status == IO_RECEIVING) { if(joypad() == J_SELECT) { demomode = 1; break; } } // Break the outer loop if(demomode == 1) break; if (_io_status != IO_IDLE) { // Error if (DEBUG == 1){ gotogxy(1, 5); gprintf("IO:%u", _io_status); } break; } if (DEBUG == 1) gprintf("%u", _io_in); *s = _io_in; if (*s == 255) { //if (_io_in == 255){ // gprintf("X"); break; } s++; } if (_io_status == IO_IDLE || demomode) { if(packetreceived == 0){ // First packet received // Clear the text color(WHITE, WHITE, SOLID); box(XOFFSET + 3, YPOSITION - 49, XOFFSET + GRAPHWIDTHFULL - 5, YPOSITION - 2, M_FILL); box(XOFFSET + 3, YPOSITION + 49, XOFFSET + GRAPHWIDTHFULL - 5, YPOSITION + 2, M_FILL); packetreceived = 1; // Hide the text } // current graph if(demomode){ // Demo = random random = rand(); random = random % 50; // current downstream percent 0-49 buffer[0] = random; random = rand(); random = random % 50; // current downstream percent 0-49 buffer[1] = random; buffer[2] = buffer[0]; buffer[3] = buffer[1] / 10; buffer[4] = 100; buffer[5] = 10; demomode = 0; } array_downstream[GRAPHWIDTHHALF - 1] = buffer[0]; array_upstream[GRAPHWIDTHHALF - 1] = buffer[1]; current_downstream = buffer[2]; current_upstream = buffer[3]; max_downstream = buffer[4]; max_upstream = buffer[5]; if(DEBUG == 1){ gotogxy(1, 5); gprintf("cDp%u", buffer[0]); gotogxy(1, 6); gprintf("cUp%u", buffer[1]); gotogxy(1, 7); gprintf("cDa%u", buffer[2]); gotogxy(1, 8); gprintf("cUa%u", buffer[3]); gotogxy(1, 9); gprintf("U%u", max_upstream); gotogxy(1, 10); gprintf("D%u", max_downstream); } } } return 0; }
Er kann mit GBDK kompilliert werden. Das bekommt ihr hier. Die Tiles können mit dem Gameboy Tile Designer und dem Gameboy Map Builder bearbeitet werden. Auch wenn es seit 16 Jahren kein Update mehr gab, läuft die Software noch problemlos unter Windows 10. Herunterladen könnt ihr sie hier. Falls ihr keine Lust habt, das ROM selber zu kompillieren, könnt ihr euch die fritzboy.gb Datei hier herunterladen. Sie muss einfach mittels des GB-USB Programms auf die programmierbare Cartridge übertragen werden.
Für die Kommunikation mit dem Gameboy sind die Funktionen in der "_gameboy.ino" zuständig (Quelle tomvdb):
/* * FritzBoy Request-Client * Send messages to Gameboy */ boolean pushValues() { // Send current values to gameboy if (maximum_downstream_short != UNDEFINED && maximum_upstream_short != UNDEFINED && rate_receive_percent != UNDEFINED && rate_send_percent != UNDEFINED) { Serial.print("Sending maximum and current bandwidth curDown%/CurUp% | curDownA/curUpA | maxDown/maxUp: "); Serial.print(rate_receive_percent); Serial.print("/"); Serial.print(rate_send_percent); Serial.print(" | "); temp_a = rate_receive_abs / 1000000; Serial.print(temp_a); Serial.print("/"); temp_b = rate_send_abs / 1000000; Serial.print(temp_b); Serial.print(" | "); Serial.print(maximum_downstream_short); Serial.print("/"); Serial.println(maximum_upstream_short); sendValuesToGB(rate_receive_percent, rate_send_percent, temp_a, temp_b, maximum_downstream_short, maximum_upstream_short); return true; } return false; } // Format: [DOWNSTREAM-GRAPH][UPSTREAM-GRAPH][DOWNSTREAM-ABSOLUTE][UPSTREAM-ABSOLUTE][DOWNSTREAM-MAXIMUM][UPSTREAM-MAXIMUM] void sendValuesToGB(byte downstream_percent, byte upstream_percent, byte downstream_absolute, byte upstream_absolute, byte maximum_downstream_short, byte maximum_upstream_short) { // i.e. "123456"; outbuffer[0] = downstream_percent; outbuffer[1] = upstream_percent; outbuffer[2] = downstream_absolute; outbuffer[3] = upstream_absolute; outbuffer[4] = maximum_downstream_short; outbuffer[5] = maximum_upstream_short; sendBytesToGB(outbuffer, 6); delay(400); } // Converts the values to a bytestream and sends it void sendBytesToGB(byte* out, int out_length) { Serial.print("Sending:"); for (int i = 0; i < out_length; i++) { Serial.print(out[i]); Serial.print('-'); byte dataToSend = out[i]; if (dataToSend == 255) // End-byte! dataToSend = 254; sendByte(dataToSend); delay(DELAYBETWEENBITS); } // Send end-byte sendByte(255); Serial.println("E"); delay(DELAYBETWEENBITS); digitalWrite(PIN_LED, LOW); } // Send a single byte void sendByte(byte out) { for (byte counter = 0; counter < 8; counter++ ) { if ( out & 0x80 ) { // Logical 1 digitalWrite(PIN_LED, HIGH); digitalWrite(PIN_SO, HIGH ); digitalWrite(PIN_CLOCK, LOW ); delayMicroseconds(DELAYBETWEENBITS); digitalWrite(PIN_CLOCK, HIGH ); delayMicroseconds(DELAYBETWEENBITS); } else { // Logical 0 digitalWrite(PIN_LED, LOW); digitalWrite(PIN_SO, LOW ); digitalWrite(PIN_CLOCK, LOW ); delayMicroseconds(DELAYBETWEENBITS); digitalWrite( PIN_CLOCK, HIGH ); delayMicroseconds(DELAYBETWEENBITS); } out = out << 1; // Next bit } }
In der "_sender.ino" wird die UPNP Abfrage (ein HTTP Soap request) erstellt und an das default Gateway (= der Router) verschickt:
/* * FritzBoy Request-Client * Sender: Sends SOAP-requests to the router */ // Maximum bandwidth usage const String soapAction_GetCommonLinkProperties = "SoapAction:urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1#GetCommonLinkProperties"; const String soapU_GetCommonLinkProperties = "<u:GetCommonLinkProperties xmlns:u=urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 />"; // Current bandwidth usage const String soapAction_GetAddonInfos = "SoapAction:urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1#GetAddonInfos"; const String soapU_GetAddonInfos = "<u:GetAddonInfos xmlns:u=urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 />"; boolean sendRequest_maximumbandwidth() { return sendRequest(soapAction_GetCommonLinkProperties, soapU_GetCommonLinkProperties); } boolean sendRequest_bandwidthusage() { return sendRequest(soapAction_GetAddonInfos, soapU_GetAddonInfos); } boolean sendRequest(String soapAction, String soapU) { Serial.println("Sending request to router"); rate_receive_abs = UNDEFINED; rate_send_abs = UNDEFINED; // if you get a connection, report back via serial: if (client.connect(Ethernet.gatewayIP(), 49000)) { Serial.println("Sending POST request"); request = "POST /igdupnp/control/WANCommonIFC1 HTTP/1.1\r\n"; request += "HOST: "; request += router_ip; request += ":49000\r\n"; //client.print(Ethernet.gatewayIP()); request += "User-Agent: fritzboy\r\n"; request += "Accept: */*\r\n"; request += "Content-Type: text/xml; charset=utf-8\r\n"; request += soapAction; request += "\r\n"; // Serial.print(request); client.print(request); delay(SENDING_DELAY); request = "Content-Length: "; String xmldata1 = "<?xml version='1.0' encoding='utf-8'?> <s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>\r\n<s:Body> "; // ... soapU ... String xmldata3 = " </s:Body> </s:Envelope>\r\n\r\n"; int contentlength = xmldata1.length() + soapU.length() + xmldata3.length(); request += contentlength; request += "\r\n\r\n"; // Serial.print(request); client.print(request); delay(SENDING_DELAY); // Serial.print(xmldata1); client.print(xmldata1); delay(SENDING_DELAY); // Serial.print(soapU); client.print(soapU); delay(SENDING_DELAY); // Serial.print(xmldata3); client.print(xmldata3); delay(SENDING_DELAY); client.flush(); delay(SENDING_DELAY); Serial.println("Post request sent"); return true; } else { Serial.println("connection failed"); return false; } }
Die Antwort wird dann in den Funktionen der "_handler.ino" geparsed:
/* * FritzBoy Request-Client * Handler: Handles resonses from the router */ boolean handle_response() { // Parse response for maximum upstream rate if (maximum_upstream_long == UNDEFINED) { if (strstr(response, "</NewLayer1UpstreamMaxBitRate") != NULL) { Serial.print("//Found maximum upstream//"); pch = strrchr(response, '<'); lastIntegerPosition = pch - response - 1; pch = strrchr(response, '>'); firstIntegerPosition = pch - response + 1; if (lastIntegerPosition - firstIntegerPosition == 0) rate_receive_abs = 0; else { char subbuff[lastIntegerPosition - firstIntegerPosition + 2]; memcpy(subbuff, &response[firstIntegerPosition], lastIntegerPosition - firstIntegerPosition + 1); subbuff[lastIntegerPosition - firstIntegerPosition + 1] = '\0'; maximum_upstream_long = atol(subbuff); if (maximum_upstream_long == UNDEFINED) // Unsigned long maximum_upstream_long++; maximum_upstream_short = maximum_upstream_long / 1000000; Serial.print("Maximum upstream:"); Serial.println(maximum_upstream_short); } } } // Parse response for maximum upstream rate if (maximum_downstream_long == UNDEFINED) { if (strstr(response, "</NewLayer1DownstreamMaxBitRate") != NULL) { Serial.print("//Found maximum downstream//"); pch = strrchr(response, '<'); lastIntegerPosition = pch - response - 1; pch = strrchr(response, '>'); firstIntegerPosition = pch - response + 1; if (lastIntegerPosition - firstIntegerPosition == 0) rate_receive_abs = 0; else { char subbuff[lastIntegerPosition - firstIntegerPosition + 2]; memcpy(subbuff, &response[firstIntegerPosition], lastIntegerPosition - firstIntegerPosition + 1); subbuff[lastIntegerPosition - firstIntegerPosition + 1] = '\0'; maximum_downstream_long = atol(subbuff); if (maximum_downstream_long == UNDEFINED) // Unsigned long maximum_downstream_long++; maximum_downstream_short = maximum_downstream_long / 1000000; Serial.print("Maximum downstream:"); Serial.println(maximum_downstream_short); } } } // Parse response for receive rate if (!response_found_downstream) { if (strstr(response, "</NewByteReceiveRate") != NULL) { Serial.print("//Found current receive//"); pch = strrchr(response, '<'); lastIntegerPosition = pch - response - 1; pch = strrchr(response, '>'); firstIntegerPosition = pch - response + 1; if (lastIntegerPosition - firstIntegerPosition == 0) rate_receive_abs = 0; else { char subbuff[lastIntegerPosition - firstIntegerPosition + 2]; memcpy(subbuff, &response[firstIntegerPosition], lastIntegerPosition - firstIntegerPosition + 1); subbuff[lastIntegerPosition - firstIntegerPosition + 1] = '\0'; rate_receive_abs = atol(subbuff); if (rate_receive_abs == UNDEFINED) // Unsigned long rate_receive_abs++; rate_receive_abs = rate_receive_abs; Serial.print("rate_receive_abs (byte/bits):"); Serial.print(rate_receive_abs); Serial.print('/'); rate_receive_abs = rate_receive_abs * 8; // Convert byte to bit Serial.println(rate_receive_abs); temp = (unsigned long) rate_receive_abs * (unsigned long) 50; rate_receive_percent = temp / maximum_downstream_long; if (rate_receive_percent > 49) // catch Maximum rate_receive_percent = 49; Serial.print("receiverate abs/percent:"); Serial.print(rate_receive_abs); Serial.print('/'); Serial.println(rate_receive_percent); } response_found_downstream = true; } } // Parse response for send rate if (!response_found_upstream) { if (strstr(response, "</NewByteSendRate") != NULL) { Serial.print("//Found current send//"); pch = strrchr(response, '<'); lastIntegerPosition = pch - response - 1; pch = strrchr(response, '>'); firstIntegerPosition = pch - response + 1; if (lastIntegerPosition - firstIntegerPosition == 0) rate_send_abs = 0; else { char subbuff[lastIntegerPosition - firstIntegerPosition + 2]; memcpy(subbuff, &response[firstIntegerPosition], lastIntegerPosition - firstIntegerPosition + 1); subbuff[lastIntegerPosition - firstIntegerPosition + 1] = '\0'; // Serial.print("Delta:"); // Serial.println(subbuff); rate_send_abs = atol(subbuff); if (rate_send_abs == UNDEFINED) // Unsigned long rate_send_abs++; rate_send_abs = rate_send_abs; Serial.print("rate_send_abs (byte/bits):"); Serial.print(rate_send_abs); Serial.print('/'); rate_send_abs = rate_send_abs * 8; // Convert byte to bit Serial.println(rate_send_abs); // highest_downstream = max(highest_downstream, rate_receive_abs); // Serial.print("highest_downstream:"); // Serial.println(highest_downstream); // unsigned long temp = (long) rate_receive_abs * (long) 50; // rate_receive_percent = temp / highest_downstream; temp = (unsigned long) rate_send_abs * (unsigned long) 50; rate_send_percent = temp / maximum_upstream_long; if (rate_send_percent > 49) // catch Maximum rate_send_percent = 49; Serial.print("sendrate abs/percent:"); Serial.print(rate_send_abs); Serial.print('/'); Serial.println(rate_send_percent); } response_found_upstream = true; } } if (response_found_downstream && response_found_upstream) return true; else return false; }
Das gesamte Repository gibt es hier.
Letzlich muss nur noch das Link-Kabel durchtrennt und folgendermaßen angeschlossen werden (Die Abbildung stellt das Kabel dar!):
SOUT (Rot) --> Arduino PIN 36
SCK (Grün) --> Arduino PIN 38
GND (Schwarz) --> Masse
SIN wird nicht benötigt, da keine Kommunikation vom Gameboy zum Arduino stattfindet.
Kommentare
das Projekt ist echt super und es hat mich animiert das ganze nachzubauen (allerdings ohne Gameboy). Wenn ich das Skript laufen lasse kommt bei mir über den seriellen Monitor allerdings ein Fehler? (Eingesetzt in das Skript habe ich meine RouterIP, ansonsten ist es so wie es hier steht belassen, in der fritzbox 7330 ist "Statusinformat ion über UpnP übertragen" an):
Fritz!Boy 1.0 starting, waiting for DHCP
IP: 192.168.1.63
GW: 192.168.1.1
Sending request to router
Sending POST request
Post request sent
HTTP/1.1 404 Not Found
Connection: close
Content-Length: 174
Content-Type: text/html
404 Not Found (ERR_NOT_FOUND) 404 Not FoundERR_NOT_FO UNDWebserver Tue, 01 Dec 2015 07:02:11 GMT
Sending request to router
connection failed
Fehler 404 lässt darauf schließen, dass die entsprechende Website nicht erreichbar ist. Ich vermute daher, dass sich deine Firmware von meiner unterscheidet.
Bitte stelle sicher, dass du die aktuellste Firmware auf der Fritzbox hast. Falls das nicht klappt, vermute ich, dass die URLs bei deiner Box andere sind.
grüße
Marcel