eMail an MarcZum GästebuchKontakt per MSN-MessengerZum Messageboard

TAPs programmieren für den TF5000

Wer sich mit der Programmierung von TAPs beschäftigen will, sollte ein gewisses Grundwissen in C-Programmierung mitbringen: TAPs werden in C programmiert und können mit einer kostenlosen Entwicklungsumgebung am PC erstellt werden.

Ihr findet hier eine geniale Anleitung von Gerti zum Einrichten der Entwicklungsumgebung. Ich gehe aufgrund der Vollständigkeit von Gertis Anleitung hier nicht auf die Einrichtung ein, sondern setze voraus, daß das alles geklappt hat und ihr das dort beschriebene Testfile compiliert und getestet habt.

Wenn ihr euch in die Programmierung einarbeiten wollt, nehmt ihr euch sinnvollerweise einen dokumentierten Sourcecode vor und versucht ihn zuerst soweit zu verstehen, daß ihr kleine Änderungen vornehmen könnt. Dann experimentiert ihr ein wenig damit herum und versucht dann Stück für Stück auch größere Modifikationen vorzunehmen und letztendlich den gesamten Code zu verstehen.

Ich habe mir die Mühe gemacht, FreeSpaceBar 1.1 detailliert und in deutsch zu dokumentieren. Da die umfangreiche Dokumentation aber den Rahmen des Code-Files sprengen und es sehr unübersichtlich machen würden, habe ich den Code in der folgenden Liste dokumentiert.

Um Loszulegen, solltet ihr euch erstmal die zur Dokumentation passende Codefassung herunterladen:

FreeSpaceBar Sourcecode V1.1

Den Inhalt dieses Zipfiled entpackt ihr nach "c:\work\tap\fspacebar". Dann versucht ihr gleich mal, das File zu compilieren, indem ihr in der Kommandozeile BUILD.BAT ausführt. Hat alles geklappt (keine Fehlermeldungen des Compilers), übertragt ihr das .TAP-File auf den Topf und startet es dort. Beim Aufrufen des Festplattenmenüs sollte dann der Balken angezeigt werden.

Jetzt könnt ihr anfangen euch den Code anzuschauen - ich empfehle zuerstmal mittendrin anzufangen - und zwar beim Abschnitt "void DrawPie". Dieser Codeteil ist für das Erzeugen des Balkens zuständig und sollte weitestgehend verständlich sein. Versucht einfach mal, den Balken zu verschieben oder schmaler zu machen. Wenn das geklappt hat, könnt ihr mal mit der Höhe des Balkens experimentieren oder die Textanzeigen verändern - einfach probieren. Insbesondere der TAP_Event-Handler ist extrem unübersichtlich und schwer verständlich. Ich würde daher empfehlen, ihn erst ganz zum Schluß genauer anzuschauen.

Viel Spaß!

#include "tap.h"  
#define ID_FREESPACEPIE 0x807A10B4  
#define COLOR_CustomYellow RGB(28,28,7)  
TAP_ID (ID_FREESPACEPIE);  
TAP_PROGRAM_NAME ("FreeSpaceBar 1.1");  
TAP_AUTHOR_NAME ("Judy (modified by Marc)");  
TAP_DESCRIPTION ("Shows Free HD-Space as Bar");  
TAP_ETCINFO (__DATE__);  
static int exitMenuShow = FALSE; Speichert den Zustand, wenn innerhalb des Exit-Fensters
static TYPE_Window win; Speichert den win-handle des Exit-Fensters
static int rgn; Speichert den rgn-handle des Exit-Fensters
static int isPieDrawn = FALSE; Speichert das gezeichnet-Flag des Balkens
static int lastwf = -1; Speichert den letzten Übergangswert für die Neuzeichnen-Überprüfung
static int updatePie = FALSE; Speichert, ob die Grafik neu gezeichnet werden muß
static byte *savedBox; Speichert die letzte Bitmap
static dword nextTick = 0; Speichert den tick-wert für das nächste Update
#define COLOR_FRed RGB( 23, 0, 0 )
#define COLOR_BRed RGB( 15, 0, 0 )
#define COLOR_FGreen RGB( 0, 23, 0 )
#define COLOR_BGreen RGB( 0, 15, 0 )
#define COLOR_LGrey RGB(160,160,160)
#define COLOR_MGrey RGB(128,128,128)
#define COLOR_DGrey RGB( 90, 90, 90)
Farben für die Grafik und den Text (einige derzeit ungenutzt)
#define ABS(x) (((x)>0)?(x):(-(x))) Definition der ABS-Funktion (Diese Funktion entfernt das Vorzeichen bei negativen Zahlen)
   
void DrawLine( word rgn, int Ax, int Ay, int Bx, int By, int Color ) Diese Funktion zeichnet eine Linie in die angegebene rgn von Ax,Ay nach Bx,By in der Farbe Color
{  

int dX = ABS(Bx-Ax);

Horizontale Differenz in dX ablegen

int dY = ABS(By-Ay);

Vertikale Differenz in dY ablegen

int CurrentX = Ax;

Linienanfang als CurrentX...

int CurrentY = Ay;

...und CurrentY (aktuelle Position) speichern

int Xincr, Yincr;

Speichert die Schrittweite in X- und Y-Richtung

if (Ax > Bx) { Xincr=-1; } else { Xincr=1; }

Legt Xincr entsprechend der benötigten Richtung für X fest

if (Ay > By) { Yincr=-1; } else { Yincr=1; }

Legt Yincr entsprechend der benötigten Richtung für Y fest

if (dX >= dY)

Ist horizontal die größere Distanz zu überbrücken ?

{

 

int dPr = dY<<1;

Wert für das Hochzählen, wenn "rechts" gewählt wird

int dPru = dPr - (dX<<1);

Wert für das Hochzählen, wenn "hoch" gewählt wird

int P = dPr - dX;

Startwert für die Entscheidung

for (; dX>=0; dX--)

Jeden Punkt der Line auf Basis eines Zählers bis dX abarbeiten

{

 

TAP_Osd_PutPixel( rgn, CurrentX, CurrentY, Color);

Pixel an die aktuelle Position zeichnen

if (P > 0)

Geht's weiter mit "rechts" UND "hoch" ?

{

 

CurrentX+=Xincr;

aktuelle X- und...

CurrentY+=Yincr;

...Y-Positon hochzählen

P+=dPru;

Entscheidungswert hochzählen (für "hoch")

}

 

else

geht's weiter mit "rechts" ?

{

 

CurrentX+=Xincr;

aktuelle X-Position hochzählen

P+=dPr;

Entscheidungswert hochzählen (für "rechts")

}

 

}

 

}

 

else

Wenn vertikal die größere Distanz zu überbrücken ist:

{

 

int dPr = dX<<1;

Wert für das Hochzählen, wenn "rechts" gewählt wird

int dPru = dPr - (dY<<1);

Wert für das Hochzählen, wenn "hoch" gewählt wird

int P = dPr - dY;

Startwert für die Entscheidung

for (; dY>=0; dY--)

Jeden Punkt der Line auf Basis eines Zählers bis dY abarbeiten

{

 

TAP_Osd_PutPixel( rgn, CurrentX, CurrentY, Color);

Pixel an die aktuelle Position zeichnen

if (P > 0)

Geht's weiter mit "rechts" UND "hoch" ?

{

 

CurrentX+=Xincr;

aktuelle X- und...

CurrentY+=Yincr;

...Y-Positon hochzählen

P+=dPru;

Entscheidungswert hochzählen (für "hoch")

}

 

else

geht's weiter mit "hoch" ?

{

 

CurrentY+=Yincr;

aktuelle Y-Position hochzählen

P+=dPr;

Entscheidungswert hochzählen (für "rechts")

}

 

}

 

}

 
}  
   
void DrawPie (void) Hier wird der eigentliche Balken gezeichnet
{  

int w;

Speichert den Zähler für die Zeilen

int wf;

Speichert die relative Position für den Übergang von rot nach grün innerhalb des Balkens

int prc;

Speichert den Prozentwert für den freie Platz

int rst;

Speichert die verbleibende Aufzeichnungszeit in Sekunden

int mn;

Speichert die verbleibende Aufzeichnungszeit in Minuten (derzeit nicht verwendet)

int hr;

Speichert die verbleibende Aufzeichnungszeit in Stunden

int x;

Derzeit ungenutzt

int y;

Derzeit ungenutzt

int lpos;

Speichert die horizontale Startposition des Balkens

int sze;

Speichert die Breite des Balkens

char str[10];

Zwischenspeicher für die Textausgaben

rgn = 0;

rgn zurücksetzen

lpos=109;

horizontale Startposition und...

sze=305;

...Breite des Balkens festlegen

prc = TAP_Hdd_FreeSize()*100/TAP_Hdd_TotalSize();

Prozentwert für freien Speicher berechnen

rst = TAP_Hdd_FreeSize()/5*8;

Verbleibende Aufzeichnungsdauer in Sekunden bei 5MBit Datenrate berechnen

hr = rst/60/60;

Verbleibende Aufzeichnungsdauer auf Stunden umrechnen

wf = sze-TAP_Hdd_FreeSize()*sze / TAP_Hdd_TotalSize();

relative Position des Übergangs von rot nach grün bestimmen

if (wf != lastwf)

Prüfen, ob Neuzeichnen notwendig ist (Hat sich die Übergangsposition seit dem letzten Neuzeichnen verändert ?)

{

 

lastwf = wf;

aktuelle Übergangsposition für nächsten Neuzeichnen-Check zwischenspeichern

for ( w=0 ; w<20 ; w++ )

Schleife für die einzelnen Linien des Balkens starten und bis 20 Linien hochzählen

{

 

if (w<=9)

Wird die obere Hälfte des Balkens gezeichnet ?

{

 

DrawLine(rgn,lpos,458+w,lpos+wf,458+w,RGB(160+w*3,0,0));

roten Teil der aktuellen Linie zeichnen, Farbwert abhängig von der Linienposition heller werden lassen (obere Hälfte des Balkens) und...

DrawLine(rgn,lpos+wf,458+w,lpos+sze-1,458+w,RGB(0,160+w*3,0));

...den entsprechenden grünen Rest der Linie zeichnen.

}

 

else

untere Hälfte des Balkens:

{

 

DrawLine(rgn , lpos,458+w,lpos+wf,458+w,RGB(220-(w-11)*3,0,0));

roten Teil der aktuellen Linie zeichnen, Farbwert abhängig von der Linienposition dunkler werden lassen (untere Hälfte des Balkens) und...

DrawLine(rgn , lpos+wf,458+w,lpos+sze-1,458+w,RGB(0,220-(w-11)*3,0));

...den entsprechenden grünen Rest der Linie zeichnen.

}

 

}

 

TAP_Osd_Draw3dBox(rgn, lpos,458,sze,20,COLOR_LGrey,COLOR_DGrey);

3D-Rahmen um den Balken zeichnen

TAP_SPrint( str, "~ %02dh@5MBit", hr);

Text für verbleibende Aufzeichnungszeit formatieren

TAP_Osd_PutStringAf1419( rgn, lpos+210-1, 458, -1, str, COLOR_Black, COLOR_None );

verbleibende Aufzeichnungszeit ausgeben. Dabei zuerst zweimal...

TAP_Osd_PutStringAf1419( rgn, lpos+210+1, 458, -1, str, COLOR_Black, COLOR_None );

...den Text jeweils nach links und rechts versetzt in Schwarz ausgeben und...

TAP_Osd_PutStringAf1419( rgn, lpos+210, 458, -1, str, COLOR_White, COLOR_None );

...dann in der gewünschten Farbe drüber (so ist's besser lesbar)

TAP_SPrint( str, "Frei: %02d%%", prc);

Text für Prozentwert formatieren

TAP_Osd_PutStringAf1419( rgn, lpos-1, 458, -1, str, COLOR_Black, COLOR_None );

Prozentwert ausgeben. Dabei zuerst zweimal...

TAP_Osd_PutStringAf1419( rgn, lpos+1, 458, -1, str, COLOR_Black, COLOR_None );

...den Text jeweils nach links und rechts versetzt in Schwarz ausgeben und...

TAP_Osd_PutStringAf1419( rgn, lpos, 458, -1, str, COLOR_White, COLOR_None );

...dann in der gewünschten Farbe drüber (so ist's besser lesbar)

TAP_SPrint( str, "(%02dGB/%02dGB)",TAP_Hdd_FreeSize()/1024,TAP_Hdd_TotalSize()/1024);

Text für Frei/Gesamtplatz formatieren

TAP_Osd_PutStringAf1419( rgn, lpos+60-1, 458, -1, str, COLOR_White, COLOR_None );

Text für Frei/Gesamtplatz ausgeben. Dabei zuerst zweimal...

TAP_Osd_PutStringAf1419( rgn, lpos+60+1, 458, -1, str, COLOR_White, COLOR_None );

...den Text jeweils nach links und rechts versetzt in Schwarz ausgeben und...

TAP_Osd_PutStringAf1419( rgn, lpos+60, 458, -1, str, COLOR_White, COLOR_None );

...dann in der gewünschten Farbe drüber (so ist's besser lesbar)

savedBox = TAP_Osd_SaveBox( rgn, lpos, 458, sze, 20);

Den gesamten Balken für schnelles Neuzeichnen im Puffer ablegen

}

 

else

Werte haben sich seit den letzten Neuzeichnen nicht verändert:

TAP_Osd_RestoreBox( rgn, lpos, 458, sze, 20, savedBox);

Zuvor gespeicherte Grafik des Balkens aus dem Puffer ausgeben
}  
   
void ShowMessageWin (char* lpMessage) Nachrichtenfenster ausgeben
{  

int rgn;

Speichert den rgn-handle

dword w;

Speichert die Breite der Nachricht

rgn = TAP_Osd_Create( 0, 0, 720, 576, 0, FALSE );

rgn-Handle erzeugen

w = TAP_Osd_GetW( lpMessage, 0, FNT_Size_1926 ) + 10;

Breite der Nachricht berechnen

if (w > 720) w = 720;

Breite abschneiden, wenn Nachricht zu lang

TAP_Osd_FillBox(rgn, (720-w)/2-5, 265, w+10, 36,COLOR_User1 );

Hintergrundkasten für das Fenster zeichnen

TAP_Osd_PutS(rgn, (720-w)/2, 270, (720+w)/2, lpMessage,COLOR_User1, COLOR_CustomYellow, 0, FNT_Size_1926,FALSE, ALIGN_CENTER);

Nachricht ausgeben

TAP_Delay(150);

1,5 Sekunden anzeigen

TAP_Osd_Delete(rgn);

rgn-handle wieder freigeben (und damit Fenster entfernen)
}  
   
void ShowExitMenuWin (char* lpTitle) Fenster für Programmende anzeigen
{  

dword w;

Speichert die Breite des Titel-Textes

rgn = TAP_Osd_Create( 0, 0, 720, 576, 0, FALSE );

rgn-handle für Fenster erzeugen

TAP_Win_SetDefaultColor( &win );

Standardfarbe im Fenster verwenden

w = TAP_Osd_GetW( lpTitle, 0, FNT_Size_1622 ) + 15;

Breite des Fensters berechnen

TAP_Win_Create( &win, rgn, (720-w)/2, 253, w, 30,FALSE, FALSE );

Fenster erzeugen

TAP_Win_SetTitle( &win, lpTitle, 0, FNT_Size_1622 );

Fenstertitel setzen

TAP_Win_AddItem( &win, "Yes" );

Yes-Item erzeugen

TAP_Win_AddItem( &win, "No" );

No-Item erzeugen

TAP_Win_SetSelection( &win, 1 );

No-Item als Standard festlegen
}  
   
int IsAnythingShown (void) Stellt fest, ob etwas angezeigt wird
{  

TYPE_OsdBaseInfo osdBaseInfo;

Speichert OSD-BaseInfo

word *_vAddr[576];

Speichert die vertikale Adresse

dword i;

Speichert die Schleifenvariable für die Adresserzeugung

dword x;

Speichert die x-Position für Bildschirm-Scan

dword y;

Speicher die y-Position für Bildschirm-Scan

TAP_Osd_GetBaseInfo( &osdBaseInfo );

Basisadresse des Screenbuffers ermitteln.

for( i=0; i<576; i+=2 )

Schleife zum Speichern der vertikalen Adressen

{

 

_vAddr[i] = osdBaseInfo.eAddr + 720*i;

Vertikale Adressen auslesen für 1. und...

_vAddr[i+1] = osdBaseInfo.oAddr + 720*i;

... 2. Halbbild

}

 

for( y=0; y<576; y+=2 )

Schleife zum scannen der Zeilen des Screenbuffers

{

 

for ( x=0; x<720; x++ )

Schleife für die Spalten

{

 

if ((*(_vAddr[y]+x)) != 0) return TRUE

Wenn ein Wert zurückgemeldet wird, ist irgendetwas auf den Bildschirm gezeichnet - dann TRUE zurückmelden

}

 

}

 

return FALSE;

FALSE zurückmelden, da nichts gefunden wurde
}  
   
dword TAP_EventHandler (word wEvent, dword dwParam1, dword dwParam2) Event-Handler
{  

dword dwState, dwSubState;

Speichert die States der Firmware

if (wEvent == EVT_IDLE)

Wenn keine Taste gedrückt ist (d.h. Event "IDLE" wird zurückgemeldet):

{

 

TAP_GetState( &dwState, &dwSubState );

Firmware-States abfragen

if (isPieDrawn == TRUE)

Befindet sich der Balken auf dem Bildschirm ?

{

 

if (dwState != STATE_FileList)

Hat der Benutzer das Festplattenmenü verlassen ?

{

 

if (dwState == STATE_Normal)

Hat der Benutzer irgendein Menü verlassen ?

{

 

TAP_MemFree( savedBox );

Die gespeicherte Bitmap im Puffer freigeben, da Balken nicht mehr gebraucht wird.

isPieDrawn = FALSE;

Balken-gezeichnet-Flag zurücksetzen

}

 

}

 

ef (updatePie == TRUE)

Muß die Grafik neu gezeichnet werden ?

{

 

updatePie = FALSE;

Flag für Grafikneuzeichnung zurücksetzen

DrawPie();

Grafik neu zeichnen

}

 

ef (TAP_GetTick() >= nextTick)

Ist es Zeit, die Grafik neu zu zeichnen ?

{

 

DrawPie();

Grafik neu zeichnen

nextTick = TAP_GetTick() + 100;

Zeitpunkt für nächstes Zwangsneuzeichnen festlegen (1 Sekunde weiter)

}

 

}

 

else

Balken befindet sich nicht auf dem Bildschirm:

{

 

if (dwState == STATE_FileList)

Befinden wir uns im Festplattenmenü ?

{

 

isPieDrawn = TRUE;

Neuzeichnen-Flag setzen

DrawPie();

Grafik neu zeichnen

}

 

}

 

}

 

ef (wEvent == EVT_KEY)

Hat der Benutzer eine Taste gedrückt ?

{

 

TAP_GetState( &dwState, &dwSubState );

Firmware-State ermitteln

if (isPieDrawn == TRUE)

Befindet sich die Grafik auf dem Bildschirm ?

{

 

if (dwParam1 == RKEY_Ok || dwParam1 == RKEY_Rewind || dwParam1 == RKEY_Forward) updatePie = TRUE;

Hat der Benutzer OK, Zurückspulen oder Vorspulen gedrückt ? Dann Flag setzen, damit Grafik im nächsten Durchlauf neu gezeichnet wird

}

 

if (dwState != STATE_Normal)

Befinden wir uns in einem Menü ?

return dwParam1;

Keycode unverändert an die Firmware zurückliefern

if (dwSubState != SUBSTATE_Normal)

Befinden wir uns in einem Untermenü ?

return dwParam1;

Keycode unverändert an die Firmware zurückliefern

if (exitMenuShow == FALSE)

Wird das TAP-Exit-Menü nicht angezeigt ?

{

 

if (dwParam1 == RKEY_Exit &&IsAnythingShown() == FALSE)

Benutzer hat EXIT-Taste gedrückt und es befindet sich nichts auf dem Bildschirm:

{

 

exitMenuShow = TRUE;

Flag zum Anzeigen des Exit-Menüs setzen

ShowExitMenuWin( "Exit FreeSpaceBar");

Exit Menü anzeigen...

return 0;

...und raus hier

}

 

}

 

else

Exit Menü wird bereits angezeigt:

{

 

if (dwParam1 == RKEY_Ok)

Benutzer hat OK gedrückt

{

 

int selNum;

Speichert den gewählten Menüpunkt

selNum = TAP_Win_GetSelection( &win );

Gewählten Menüpunkt ermitteln

TAP_Win_Delete( &win );

Das Exit-Fenster entfernen

TAP_Osd_Delete( rgn );

rgn-Handle freigeben

exitMenuShow = FALSE;

Flag für Exit-Fenster zurücksetzen

if (selNum == 0)

Der Benutzer hat "Yes" gewählt:

{

 

TAP_Exit();

TAP beenden...

return 0;

...und raus hier

}

 

else

Der Benutzer hat "No" gewählt:

{

 

return RKEY_Exit;

Exit-Tastendruck an ggf. vorhandene andere TAP's weiterleiten und raus hier

}

 

}

 

ef (dwParam1 == RKEY_Exit)

Hat der Benutzer "Exit" gedrückt:

{

 

TAP_Win_Delete( &win );

Exit-Fenster entfernen

TAP_Osd_Delete( rgn );

rgn-Handle freigeben

exitMenuShow = FALSE;

Flag für Exit-Fenster zurücksetzen

return 0;

und raus hier

}

 

else

Der Benutzer hat irgendeine andere Taste gedrückt:

{

 

TAP_Win_Action( &win, dwParam1 );

Keycode an das Exit-Fenster senden...

return 0;

...und raus hier

}

 

}

 

}

 

return dwParam1;

unverändert an die Firmware weitergeben
}  
   
int TAP_Main (void) Hauptroutine für FreeSpaceBar
{  

ShowMessageWin( "FreeSpaceBar has started" );

Startbestätigung anzeigen...

return 1;

...und TSR-Modus vor verlassen festlegen
}  

Impressum

Hit Counter