Der Quelltext für die Software der WLAN-RGB Lampe kann über den Download-Link als freie Software bezogen werden. Er ist unter der GPL 2 oder wahlweise einer späteren Version der Lizenz verfügbar. Der Treiber für den ZG2100M wird derzeit von der Firma AyncLabs.com unter GPL2 vertrieben.
Die Ansteuerng der LED-Treiber erfolgt über Pulsweiten-Modulation (PWM). Dadurch sind pro LED 255 verschiedene Helligkeitsstufen möglich. Die Werte für die einzelnen Helligkeitsstufen werden über das WLAN mit dem UDP-Protokoll übertragen. Da mit dem ZG2100M kein Multicast eingesetzt werden kann, muss der WLAN-RGB Lampe eine IP-Adress zugewiesen werden. Die Software enthält eine Minimal-Implementierung des ARP Protokolles, um die Zuweisung der IP-Adresse zur MAC-Adresse des ZG2100M über das Netzwerk veröffentlichen zu können.
Die Verbindung mit dem WLAN wird von dem ZG2100M und dem Treiber der Firma AsyncLabs.com durchgeführt. Das ZG2100 kümmert sich dabei auch um die Verschlüsselung der Daten nach WEP oder WPA Standard. Der Treiber kommuniziert mit der übrigen Software über einen Buffer, welcher die in Ethernet-Frames eingebetteten Netzwerdaten enthält.
Die im Folgenden beschriebenen Auszüge aus dem C-Code enthalten Verweise auf die jeweiligen Quelltextdateien um das Navigieren durch den Sourcecode etwas zu vereinfachen.
Das Hauptprogramm in main.c initialisiert das Netzwerk, wartet die Verbindung zum WLAN ab und verarbeitet dann in einer Endlosschleife die ankommenden Netzwerkdaten:
/* Connect to WLAN
*/
unsigned char ok = 0;
do
{
ok = ConnectNetwork();
}
while( ok == 0);
log("\n\rConnected to WLAN.\n\r" );
/* Event loop
*/
for (;;)
{
HandleNetworkData();
}
Dabei wird zunächst der ZG2100M Treiber aufgerufen, um eventuell eingetroffene Netzwerkdaten zu verarbeiten (net.c) :
void HandleNetworkData()
{
/* Call network driver
*/
zg_drv_process();
Von empfangenen Daten wird zunächst einmal die Prüfsumme entfernt, bevor sie weiterverarbeitet werden:
/* Have we received some data?
*/
unsigned int len = zg_get_rx_status();
if ( len > 0 )
{
/* Strip off the checksum
*/
MyNetworkBuffer[len-4] = 0;
Wurde ein ARP-Request empfangen, so wird dieser bearbeitet und ggfs. eine ARP-Response verschickt ( arp.c ). Da die Addressierung der Ethernet-Frames über MAC-Adressen läuft, wird mit der ARP-Response die MAC-Adresse des ZG2100M im Netzwerk veröffentlicht, die der eigenen IP-Adresse entspricht.
if ( IsArpMessage ( MyNetworkBuffer ) )
{
ARP_Packet * arp = (ARP_Packet*) (MyNetworkBuffer + Ethernet_DataOffset);
if ( ProcessArpMessage( arp ) )
{
log("Sent ARP Response :\n\r");
DumpArpMessage( arp );
}
}
Falls es sich bei den empfangenen Daten nicht um einen ARP-Request handelt, wird auf den Empfang einer Nachricht zum Ansteuern der LEDs geprüft:
/* Check for ambient color message
*/
if ( IsAmbientColorMessage( MyAddress.IP , AMBICOLOR_PORT,
(char*) MyNetworkBuffer ) )
{
HandleAmbientColorMessage( (char*) MyNetworkBuffer );
}
Dabei wird ein UDP-Datagram verwendet, dessen Format hier kurz beschrieben ist. Die beiden Funktionen zur Auswertung IsAmbientColorMessage und HandleAmbientColorMessage sind in der Datei ambientcolor.c definiert. Sind die Daten an die WLAN-RGB Lample adressiert, so werden sie bei einer gültigen Nachricht zum Setzen der LED-Farbe verwendet:
void HandleAmbientColorMessage( char* msg )
{
if ( msg != NULL && strncmp( msg + UDP_DataOffset, "AmbientColor:",13) == 0 )
{
int red, green, blue, index = 0;
char * token;
char * context;
token = strtok_r ( msg + UDP_DataOffset,":",&context);
while (token != NULL)
{
switch( index )
{
case 1: red = atoi( token );
log("Setting RED to 0x%x\n\r", red);
break;
case 2: green = atoi(token);
log("Setting GREEN to 0x%x\n\r", green );
break;
case 3: blue = atoi(token);
log("Setting BLUE to 0x%x\n\r", blue );
break;
}
++index;
token = strtok_r (NULL,":",&context);
}
SetColors(red, green, blue);
log("\n\r" );
}
}
Die LED-Farbe wird wie oben schon erwähnt per PWM eingestellt. Die Funktion SetColors setzt dabei die Werte für die Pulsweitenmodulation, die von der Interrupt-Service-Routine des Timers 1 ausgewertet werden ( timer.c ):
ISR (TIMER1_COMPA_vect)
{
TIMER1_COMPA_INT_DISABLE;
if ( ++pwm == 0 )
{
if ( red > 0 ) {
LED_On ( RED );
}
if ( green > 0 ) {
LED_On ( GREEN );
}
if ( blue > 0) {
LED_On ( BLUE );
}
}
/* Pulse width modulation of LEDs
*/
if ( pwm > red ) {
LED_Off( RED );
}
if ( pwm > green ) {
LED_Off ( GREEN );
}
if ( pwm > blue ) {
LED_Off ( BLUE );
}
TIMER1_COMPA_INT_ENABLE;
}