PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Library für Bascom: Array anlegen und beschreiben



Mitch64
08.11.2009, 19:50
Hallo zusammen,

ich habe ein paar Routinen in Bascom geschrieben, die ich nach und nach in eine Lib übertragen will. Hier ein Beispiel:


Sub OSDClear()
'[OSDClear]
_OSDClear:
lds xl,{_Screen_Start} ' Startadresse Bildbuffer laden
lds xh,{_Screen_Start+1}
ldi yl,lbyte(BufferSize) ' BufferZize nach Y
ldi yh,hbyte(BufferSize)
clr r24
_OSDClearScreen:
st x+,r24
sbiw yl,1
breq _OSDClearScreenExit
rjmp _OSDClearScreen
_OSDClearScreenExit:
End Sub


Nun greife ich über diese Routinen auf ein ByteArray zu, was in Bascom auch funktioniert. Das Array brauche ich aber später in der Lib und nicht im Hauptprogramm.

Nun die Frage:
Wie definiere ich in einer Library ein Array über beispielsweise 512 Byte. Muss das in einer Routine gemacht werden oder wird das ganz am Anfang gemacht?

Das ganze soll ähnlich funktionieren wie der Befehl

Config Serialin=Buffered

Der Buffer wird erst angelegt, wenn die Initialisierung aufgerufen wird.

Wie wird also das Array angelegt und wie kann ich innerhalb der Lib z.B. auf den ersten Index des Arrays zugreifen?

Ich verwende aktuell die Vollversion BascomAVR 1.11.9.5

Vielen Dank schon mal für eure Hilfe!

Mitch.

PicNick
09.11.2009, 09:03
Nun, das definieren von Speicherplatz findet ja beim compilieren statt und nicht zu laufzeit.
Beim DIM-en werden ja label-adressen festgelegt, die dann als HIGH() und LOW() in die Befehle eingebaut werden.
"COnfig serialin=buffered" wird daher schon zur Compile-Time ausgewertet.

Du kannst aber z.b. deiner LIB die Grösse deines Arrays als
CONST ArrSize = 512
festelegen und dieses Symbol "ArrSize" in der LIB verwenden ( um es in die Assembler-befehle einzubauen, s.o)

EIn bisschen was über Libraries hab ich da geschrieben:
http://www.rn-wissen.de/index.php/Bascom_Libraries

Mitch64
09.11.2009, 16:24
Das klingt aus deinem Munde ja simpel.
Leider stellen sich mir trotzdem eine menge Fragen.

Vielleicht kannst du das mit einem kurzen Code-Schnipsel verdeutlichen.

Ich Frage mich gerade, wenn ich die ArraySize in einer Constante ablege und in Bascom werden ja auch Variablen gedimt. Woher weis dann Bascom, dass die nächste Variable erst im Anschluss kommt und nicht in den Array-Bereich gerät?

Nehmen wir an ich schreibe folgendes:

zunächst Bascomcode:


Dim Variable1 as Byte
Dim Variable2 as Word

$Lib "MyLib.lib"

Dim Variable3 as Word


und in der Lib wird ein Array definiert mit Namen MyArray in dieser Art:

Code in der Lib


MyArray:
.equ MyArraySize = 512


Ich glaube der Code ist so nicht ganz korrekt, zeigt aber, wie ich deine Erklärung verstanden habe.

Irgendwie tappe ich da noch im Dunkeln.

Und da die Lib zwischen Variable2 und Variable3 eingefügt ist. Wird die Variable3 nicht in diesem Array-Bereich dimensioniert?

Ich verstehe das nicht.

kurzes Codebeispiel wäre klasse.[/code]

PicNick
10.11.2009, 09:24
Moin ! (spät, aber doch)
Also: Speicherplatz definieren bzw reservieren muss man im Bascom-Code mit den "DIM's".
In den Libraries ist sowas nicht vorgesehen und eigentlich auch nicht möglich. Nur von den Stack's kann man sich zur Laufzeit was abzwicken.

Diese Abhängigkeit der Library von den Bascom-Dims hat aber den Vorteil, dass man die Library-Funktionen nicht angreifen muss, wenn man z.B auf einen grösseren/kleineren µC wechselt.

Ich definiere also im Bascom


Const ArrSize = 512
DIM MyArray(ArrSize) as Byte

Dadurch ist der Platz belegt und wird von Bascom nicht mehr angegriffen

Damit die Library-Funktion dies Definition auch mitkriegt, habe ich mehrere Möglichkeiten,
eine davon ist die, dass die Namen der Variablen fix vereinbart sind
d.h. die Library geht davon aus, das im Bascom-Teil immer
"MyArray" und "ArrSize" verwendet werden.

Um Dir ganz konkreten Code vorzuschlagen, würde es mir helfen zu wissen, was die Library-Routinen in Etwa können sollen.
Daraus ergeben sich nämlich unterschiedliche empfehlenswerte Vorgangsweisen.

Mitch64
10.11.2009, 16:13
Hallo

Ich versuche mich daran, einen OSD (On Screen Display) zu realisieren.
Das ganze mit einem ATmega aufgebaut und mit I2C-Schnittstelle versehen.

Das OSD verwendet einen Buffer als Bildspeicher, der z.B. in 16 Spalten (Zeichen) und 16 Zeilen aufgeteilt ist. Also ein 16x16 Bildspeicher.

Die Routinen, die eventuell in einer Lib untergebracht werden sollen, haben die Aufgabe, Textstring in diesen Buffer zu schreiben.

Eine Routine OSDSetCursor(Spalte,Zeile) setzt den Bildzeiger auf die Zeile und Spalte, wo der Text später eingeblendet werden soll.

Eine weitere Roitune OSDWriteText(text) schreibt dann den Text an die entsprechende Stelle im Bildspeicher.

Eine Dritte Routine OSDClear() löscht den Buffer wieder.

Es gibt noch ein paar zusätzliche Routinen, um OSD einzuschalten OSDOn() und auschhalten OSDOff().

Soviel zur Erklärung der Routinen.

Die Lib habe ich derzeit so aufgeteilt.

Die Header-Datei, die die Constanten und Dimensionierungen enthält. Unter anderem auch den Screen_Buffer(). Das sieht so aus:



' Projekt: OSD (On Screen Display)
' Modul: Screen.h
' erstellt: 08.11.2009
' letzte Änderung: 09.11.2009
' Beschreibung:
' Headerdatei zu Modul Screen.bas



Declare Sub OSDInit()
Declare Sub OSDClear()
Declare Sub OSDOn()
Declare Sub OSDOff()
Declare Sub OSDSetCursor(byval Zeile as Byte , byval Spalte as Byte)
Declare Sub OSDWriteString(Byval Text as String)

Dim _Screen_Buffer(BufferSize) as Byte ' Bild-Speicher
Dim _Screen_Offset as Word ' Offset Bildbuffer für Schreibzugriffe
Dim _Screen_Start as Word ' Startadresse Bildbuffer

Dim OSD_Char as Byte


Die eigentlichen Routinen habe ich in einem 2. Modul untergebracht und sieht so aus:


' Projekt: OSD (On Screen Display)
' Modul:
' erstellt: 08.11.2009
' letzte Änderung: 08.11.2009
' Beschreibung:
' Routinen zum Bearbeiten des OSD-Screen-Buffer

$nocompile

' ----------------------------------------------
' OSD initialisieren
' ----------------------------------------------

Sub OSDInit()
'[OSDInit]
_OSDInit:
loadadr _Screen_Buffer(1) , x ' Start-Adresse Bildspeicher berechnen
sts {_Screen_Start},xl ' und in _Screen_Start speichern
sts {_Screen_Start+1},xh

clr r24 ' _Screen_Offset zücksetzen
sts {_Screen_Offset},r24
sts {_Screen_Offset+1},r24
rcall _OSDClear ' Bildschirm löschen
'[END]
End Sub

' ----------------------------------------------
' Bildschirm löschen
' ----------------------------------------------

Sub OSDClear()
'[OSDClear]
_OSDClear:
lds xl,{_Screen_Start} ' Startadresse Bildbuffer laden
lds xh,{_Screen_Start+1}
ldi yl,lbyte(BufferSize) ' BufferZize nach Y
ldi yh,hbyte(BufferSize)
clr r24
_OSDClearScreen:
st x+,r24
sbiw yl,1
breq _OSDClearScreenExit
rjmp _OSDClearScreen
_OSDClearScreenExit:
'[END]
End Sub

' ----------------------------------------------
' Cursor-Position setzen
' Zeile: Werte 0 bis 23
' Spalte: Werte 0 bis CharPerLine (Zeichen pro Zeile)
' ----------------------------------------------

Sub OSDSetCursor(byval Zeile as Byte , byval Spalte as Byte)
'[OSDSetCursor]
_OSDSetCursor:
ldd xl,y+2 ' Zeiger auf Zeile
ldd xh,y+3
ld r24,x ' Zeile nach r24
ldi r25,CharPerLine
mul r24 , r25

ldd xl,y+0 ' Zeiger auf Spalte
ldd xh,y+1
ld r25,x ' Spalte nach r25

add r0,r25 ' Spalte addieren
clr r25
adc r1,r25
sts {_Screen_Offset},r0
sts {_Screen_Offset+1},r1
'[END]
End Sub

' ----------------------------------------------
' Text in Buffer schreiben
' SetCursor sollte zuvor aufgerufen werden!
' ----------------------------------------------

Sub OSDWriteString(byval Text as String)
'[OSDWriteString]
_OSDWriteString:
local Offset as Word
Offset = _Screen_Start + _Screen_Offset ' Adresse berechnen
ldd zl,y+0 ' Adresse auf lokale Variable Offset nach Z
ldd zh,y+1
ld xl,z+ ' Wert lokaler Variable Offset nach X
ld xh,z
loadadr Text , z ' Zeiger auf Text nach Z

_WriteStringNextChar:
ld r24,z+
cpi r24,0 ' letztes Zeichen?
breq _WriteStringExit
st x+,r24
rjmp _WriteStringNextChar
_WriteStringExit:
'[END]
End Sub

' ----------------------------------------------
' OSD einschalten
' ----------------------------------------------

Sub OSDOn()
'[OSDOn]
_OSDOn:
nop
'[END]
End Sub

' ----------------------------------------------
' OSD ausschalten
' ----------------------------------------------

Sub OSDOff()
'[OSDOff]
_OSDOFF:
nop
'[END]
End Sub


Die Routinen funktionieren soweit und sind auch schon andeutungsweise für Lib vorbereitet.

In der Lib hätte ich gerne das Modul 1 (Header) + Modul 1 (Routinen) gehabt. Schließlich soll der Benutzer der Library nicht noch von Hand irgendwelche Konstanten oder Buffer dimensionieren müssen.

Schön wäre natürlich auch ein Configurations-Befehl ala Bascom zur Initialisierung des Buffers und des PortPin für die Ausgabe des OSD.

In Etwa so:
Config OSD=Zeichen,Zeilen

und
Config OSDPin=PortB.1

Allerdings weiß ich nicht, ob das mit Config möglich ist.

Weist du Rat?

Gruß Mitch.

[/b]

PicNick
10.11.2009, 16:25
Ich schau mir deine Routinen noch genauer an.

Das mit "Config" wird aber wohl nix, das spielt Bascom nicht mit.
aber, nur als Beispiel:


Const OSDZeichen = 16
Const OSDZeilen = 16
Const OSDPort = PortB
Const OSDPin = 1

kommt mir eigentlich auch nicht so schlimm vor

Mitch64
10.11.2009, 16:36
Hallo Robert,

da fehlt noch der Screenbuffer, der Zeiger für den Bildspeicher, der Offset dazu und dann wird es unübersichtlich. Es muss auch noch jede Routine deklariert werden und noch ein $External je Routine eingefügt werden.

Das wird immer mehr. Da ist man fast einfacher bedient, eine Bas zu inkluden, die diese Declares, usw ethält. In dieser steckt dann auch der $Lib Befehl.

Eigentlich wollte ich das alles etwas vereinfachen deswegen auch die Lib.

Mitch

PicNick
10.11.2009, 18:41
Nun, ich persönlich verwende Libraries recht umfangreich, dabei mache ich auch genau das:
Ein Bascom-Include, das auf diese Art die Schnittstelle zu der Library bildet.
Dabei verwende ich immer einen Art Kontroll-Block, der von Bascom und der Library gemeinschaftlich verwendet wird.

Im Bascom musst du nur die Routinen deklarieren u. $external definieren, die du vom Bascom aus aufrufen willst. Das musst du aber so wie so.
Das wäre in deinem Fall offenbar
OSDSetCursor(Spalte,Zeile)
OSDWriteText(text)
OSDClear()
OSDOn()
OSDOff().
Das scheint mir nicht unzumutbar.

aaaaaaber eins muss klar sein:

Diese ganze Planung und Vorgangsweise ist sinnvoll, wenn man dann diese Libraries in mehreren Projekten braucht.

Für eine einzige Anwendung / Programm

kann man auch überlegen, bei Bascom zu bleiben und nur trickreichen Dinge mit Inline-Assembler zu lösen.

Mitch64
10.11.2009, 19:50
OK Robert,

ich danke dir fürs erste für deine Ausführungen.
Ich hoffe doch, ich kann mich nochmal an dich wenden wenn Bedarf beseht?

Mitch.

PicNick
11.11.2009, 08:26
Ich bittte sogar darum :-)

Mitch64
11.11.2009, 16:00
Oki!

Gruß Mitch.

Mitch64
15.12.2009, 19:23
Hallo PicNick,

habe Neuigkeiten für dich.
Check doch mal dein Postfach.

Gruß Mitch.