Bascom: Library Verständnisschwierigkeiten

Dirk

Administrator
Teammitglied
28. Jan. 2007
4.328
166
63
Mittelhessen, Giessen
Sprachen
  1. ANSI C
  2. C++
  3. C#
  4. Java
  5. Kotlin
  6. Pascal
  7. Assembler
  8. PHP
Hallo zusammen,

ich möchte für Bascom eine Library erstellen, habe aber anscheinend noch einige Verständnisschwierigkeiten. Vielleicht kann mir ja hier jemand helfen. Die Parameterübergabe über den SoftStack ist mir soweit klar, es gibt jedoch beim Compilieren noch Fehlermeldungen.


Einen Ausschnitt aus meiner Library
Code:
.equ XVCMD_ScreenFillRGB = 0x1B 

.equ XV_CNTRLPORT = PORTB
.equ XV_CNTRLCS = PB0
.equ XV_CNTRLPORTPIN = PINB
.equ XV_CNTRLBUSY = PB4

[B][_ScreenFillRGB][/B]
_ScreenFillRGB:

  rcall _XV_WaitWhileBusy

  cbi XV_CNTRLPORT, XV_CNTRLCS

  rcall _XV_Wait5us

  ldi r16, XVCMD_ScreenFillRGB
  rcall _XV_SendSPI

  rcall _XV_WaitWhileNotBusy

  ldd    xl, y + 0  ; Red
  ldd    xh, y + 1
  ld     r16, x
  rcall _XV_SendSPI
  ldd    xl, y + 2  ; Green
  ldd    xh, y + 3
  ld     r16, x
  rcall _XV_SendSPI
  ldd    xl, y + 4  ; Blue
  ldd    xh, y + 5
  ld     r16, x
  rcall _XV_SendSPI

  rcall _XV_WaitWhileBusy

  sbi XV_CNTRLPORT, XV_CNTRLCS
  rcall _XV_Wait5us

ret
[B][END][/B]

[B][_XV_SendSPI][/B]
_XV_SendSPI:
  out SPDR, r16
_xv_spisend_loop:
  in r16, SPSR
  sbrs r16, SPIF  ; if SPIF (Bit7) set, then skip
  rjmp _xv_spisend_loop
  in r16, SPDR
ret
[B][END][/B]
Zu Begin der Library gibt es einige Definitionen. Die Definitionen, welche sich auf Port-Zugriff beziehen, sollen später außerhalb der Lib im Bascom-Programm festgelegt werden.

In der Lib sind mehrere Routinen, ich habe oben nur zwei aufgelistet, damit es übersichtlich bleibt. Im Moment sind es folgende:
  • _ScreenFillRGB (wird vom Bascom-Programm aufgerufen)
  • _XV_SendSPI (wird innerhalb der Lib benötigt und von _ScreenFillRGB aufgerufen)
  • _XV_WaitWhileBusy (wird innerhalb der Lib benötigt und von _ScreenFillRGB aufgerufen)
  • _XV_WaitWhileNotBusy (wird innerhalb der Lib benötigt und von _ScreenFillRGB aufgerufen)
  • _XV_Wait5us (wird innerhalb der Lib benötigt und von _ScreenFillRGB aufgerufen)
Ein Ausschnitt aus dem Bascom-Programm:
Code:
$lib "MeineLibrary.lib"

$external _Screenfillrgb

Declare Sub _Screenfillrgb(Red As Byte , Green As Byte , Blue As Byte)
Nun zu meinen Problemen:

Beim Compilieren gibt es noch mehrere Fehler.
Die Routine _ScreenFillRGB kennt zum Beispiel die in ihr aufgerufenen Routinen nicht, auch die .def Definitionen zu Begin der Lib kennt die Routine nicht.
Ich habe mir auch Libs angesehen, die im Lib Verzeichnis von Bascom sind und auch einige Sachen probiert, leider habe ich noch keinen Erfolg gehabt.

Kann mir vielleicht jemand Helfen, meinen "Knoten aufzubekommen".

Gruß,
Dirk
 
Hallo Dirk!

Hast du dir zum Verständnis mal die "mylib.lib" im BASCM/LIB Verzeichnis durchgelesen?

Da stehen einige Hinweise drin, wie eine eigene LIB aufgebaut sein muss.

Code:
; How To Create Your Own Asm Libs And Put In Your Own Statements

; First Determine The Used Parameters And Their Type.
; Also Consider If They Are Passed By Reference Or By Value

; For Example The Sub Test Has Two Parameters:
; X Which Is Passed By Value (copy Of The Variable)
; Y Which Is Passed By Reference(address Of The Variable)

; In Both Cases The Addres Of The Variable Is Put On The Soft Stack Which Is
; Indexed By Y

; The First Parameter (or A Copy) Is Put On The Softstack First
; To Refer To The Address You Must Use:
;    Ldd R26 , Y + 0
;    Ldd R27 , Y + 1
; This Loads The Address Into Pointer X


; The Second Parameter Will Also Be Put On The Softstack So
; The Reference For The X Variable Will Be Changed :

; To Refer To The Address Of X You Must Use:
;   Ldd R26 , Y + 2
;   Ldd R27 , Y + 3


; To Refer To The Last Parameter Y You Must Use
;   Ldd R26 , Y + 0
;   Ldd R27 , Y + 1


; Write The Sub Routine As You Are Used Too
; But Include The Name Within Brackets

[TEST]
Test:
  ldd r26,y+2 ; load address of X
  ldd r27,y+3
  ld r24,x    ; get value into r24
  Inc r24     ; value + 1
  St x,r24    ; put back
  ldd r26,y+0 ; address pf Y
  ldd r27,y+1
  st x,r24    ; store
  ret         ; ready
[END]

[testconst]
testconst:
.equ myconst = 10 + 20
  ldi r24,myconst
  ldi r24,10 + 20
#IF vartest("myconstz>10")
  #if myconstz=10
    .equ klm=11
  #else
    .equ klm=12
  #endif
#ELSE
  .equ abc=13
#ENDIF
[end]

; To Write A Function Goes The Same Way
; A Function Return A Result So A Function Has One Additional Parameter
; It Is Generated Automatic And It Has The Name Of The Function
; This Way You Can Assign The Result To The Function Name
; For Example:
; Declare Function Test(byval X As Byte , Y As Byte) As Byte
; A Virtual Variable Will Be Created With The Name Of The Function In This Case Test
; It Will Be Pushed On The Softstack With The Y Pointer
; To Reference To The Result Or Name Of The Function (test) The Address Will Be
; Y + 0 And Y + 1
; The First Variable X Will Bring That To Y + 2 And Y + 3
; And The Third Variable Will Cause That 3 Params Are Saved On The Soft Stack
; So To Reference To Test You Must Use
;   Ldd R26 , Y + 4
;   Ldd R27 , Y + 5

; To Reference To X Ldd R26 , Y + 2
;   Ldd R27 , Y + 3
; And To Reference Y Ldd R26 , Y + 0
;   Ldd R27 , Y + 1


; When You Use Exit Sub Or Exit Function You Also Need To Provide An Additional Lable
; It Starts With Sub_ And Must Be Completed With The Function / Sub Routine Name
; In Our Example:
; Sub_test:


; When You Use Local Variables Thing Become More Complicated.
; Each Local Variable Address Will Be Put On The Soft Stack Too
; When You Use 1 Local Variable Its address will become
;   LDD r26,  y+0
;   Ldd R27 , Y + 1
; All Other Parameters Must Be Increaded With 2 So The Reference To Y Variable Changes
; From Ldd R26 , Y + 0 To Ldd R26 , Y + 2
;      Ldd R27 , Y + 1 To Ldd R27 , Y + 3
; And Of Course Also For The Other Variables.

; WHen You Have More Local Vars Just Add 2 For Each
; Finally You Save The File As A .lib File
; Use The Library Manager To Compile It
; The Declare Sub / Function Must Be In The Program Whre You Use The Sub / Function


Leider habe ich davon zu wenig Ahnung! ;)
Eventuell kann dir Dino oder Markus da besser weiter helfen.

Gruß,
Cassio
 
Hallo Cassio,

ja die Lib habe ich mir auch angesehen, die Erklärungen stehen auch in dieser riesen PDF-Dokumentation von Bascom.

Ich hatte auch mehrere Sachen probiert, unter anderem auch jede Menge Routinen wieder aus der Lib geschmissen, so dass sie einfacher wurde. Leider hatte ich immer noch Fehlermeldungen, es scheint als hätte ich hier irgendwie einen "Knoten", den ich nicht aufbekomme :rolleyes:

Gruß,
Dirk
 
Hallo Dirk,

grundsätzlich will ich als Assembler-Programmierer "Modular" arbeiten. Das heisst, ich erstellen ein "Haupt" Programm und dazu gehören dann "Inklude" Dateien für die "Primitiven" (das sind Hardwarenahe Funktionen). Wie das in BASIC funktionieren soll, weis ich leider niht, aber, habe sofort das Programm an dem ich jetzt dabei bin (LCD-Steuerung) in ein Hauptprogramm und eine "Include Datei" getrennt.. und assambliert....es funktioniert.
--- Im Assembler, kann eine Include-Datei, fehlerfrei assambliert werden, aber ---nicht alleinstehend---. Das heisst, es muss ein Hauptprogramm existieren das die Include Datei aufruft... (auch noch -bedingt- für den Assembler im AVR-Studio) -- der Assembler im AVR-Studio ist kein "Makroassembler"-- er kennt die Direktiven: - PUBLIC, EXTERN, GLOBAL, scheinbar nicht....

Wolfgang

über die von mir, oben genannten Directiven, kommuniziert ein "Makroassembler" mit den dazugehörigen Files...
- Eine "Include"-Datei erklärt ihre Variabeln, Namen, als "Public" oder "Global", und die Routinen des Assembler-Linkers erkennen daran, was sie zu tun haben..Im Hauptprogramm werden, die dort "nicht existierenden" Deklarationen" dann in den entsprechenden Files gesucht, die als "Include" angegeben sind......

-- Wie das im "AVR-Studio", genau funktionieren soll, darüber muss auch ich mir noch den Kopf zerbrechen.-- vor allem, zwischen den unterschiedlichen Programmiersprachen.. "C" scheint da in Bezug auf Assembler-Programmierung, einen Vorteil zu haben.

Wolfgang
 
Hallo Wolfgang,

Assembler ist hier nicht das Problem, sondern lediglich die Library-Struktur von Bascom, mit der ich noch ein bisschen auf Kriegsfuß stehe, und die werde ich mir am Wochenende nochmal vornehmen.

Gruß,
Dirk
 
Da wünsch ich Dir "viel Erfolg" und wenn mir "altem Indiviidum" nichts dazwischne kommt, werde ich mich in naher Zukunft, auch mit "Bascom" auseinandersezten müssen...(wollen).
Wolfgang
 
Hallo Dirk,

ich weiß nicht, ob das Thema noch aktuell ist. Ich habe mich auch mit dem Thema beschäftigt, da ich diese Woche ein Display bei euch bestellt habe und dafür eine Lib schreiben will. Nach einigem rumprobieren bin ich doch schon ein Stück weiter gekommen. Die Übergabe der Parameter über den Softstack erfolgt anders herum, mit deiner Version wird erst Blau, dann Grün und dann Rot übertragen. Das hier dürfte funktionieren:
Code:
  ldd    xl, y + 4  ; Red
  ldd    xh, y + 5
  ld     r16, x
  rcall _XV_SendSPI
  ldd    xl, y + 2  ; Green
  ldd    xh, y + 3
  ld     r16, x
  rcall _XV_SendSPI
  ldd    xl, y + 0  ; Blue
  ldd    xh, y + 1
  ld     r16, x
  rcall _XV_SendSPI
Das Problem mit den Unterprogrammen bekommt man in den Griff indem man die mit reinschreibt:
Code:
[_ScreenFillRGB]
$external _XV_SendSPI, _XV_Wait5us, XV_DEF
_ScreenFillRGB:

Hier siehst du dann auch gleich die Lösung für die Konstanten. Mach einfach vor die Konstanten noch ein
Code:
[XV_DEF]
und dann meckert Bascom auch nicht mehr.

Könntest du mir eventuell deinen bisherigen Assemblercode zukommen lassen, da meine Assemblerkenntnisse nicht besonders gut sind und mit das bei der Erstellung der LIB helfen würde?
 
Hallo Stefan,

ich wollte damals für das OLED Displaymodul XV-OLED302 eine Library schreiben, hatte es dann aber weit weit nach hinten geschoben, da mir die Zeit gefehlt hat und Cassio auch schon eine Bascom-Lösung für das Display hatte, wenn auch nicht mit einer Lib, aber das muss auch nicht unbedingt sein. Ich wollte ursprünglich erst einmal die Lib mit einem einfachen Kommando realisieren, bevor ich den ganzen Befehlssatz "einbauen" wollte. Ich bin leider nicht weiter gekommen, da ich bei der Konfiguration der SPI-Schnittstelle hängen geblieben bin. Ich wollte hier einmal das SPI-Modul verwenden und dann auch noch SoftwareSPI realisieren. Ich habe also leider noch keinen Assemblercode. Probleme hatte ich nicht mit der Parameterübergabe über den Softwarestack, sondern ich wusste nicht, wie man den SPI-Rountinen in der Lib beibringt, dass bei SoftwareSPI bestimmte IO-Pins verwendet werden sollen und bei HardwareSPI welche Register dafür genutzt werden sollen.

Jetzt weiß ich nicht welches Display du bestellt hast. Der Befehlssatz des OLED Displays ist nicht kompatibel zu den neueren Displaymodulen der Familien XV-TFT2428T und TFT-60D (Hier musste ein Schnitt gemacht werden, da bei den neuen Displaymodulen weitere Funktionen hinzukommen sollen, zum Beispiel visuelle Komponenten).

Du könntest mir entweder sagen, welche Assemblerroutinen du genau brauchst, also was die machen sollen, dann würde ich den Source schreiben oder du sendest mir deinen bisherigen Bascomcode und ich versuche da erst mal eine einfache Routine einzubauen. Ich muss mich in Bascom allerdings erst mal wieder reinfinden. Wenn erst mal der Knoten bei mir geplatzt ist, wird es sicherlich recht schnell fertig.

Grüße,
Dirk
 
Hallo Dirk,

das OLED-Display habe ich schon eine Weile in Benutzung. Die Bascom-Ansteuerung habe ich ähnlich wie Cassio gemacht. Momentan bin ich am Code für das 2,8"-TFT mit Touch.

Dass da die Ansteuerung verschieden ist, habe ich schon aus dem Datenblatt und den C-Files rauslesen können.
Ich werde zunächst mal die Ansteuerung komplett in Bascom machen und dann Stück für Stück die Routinen mit Inline-ASM ersetzen. Das hat den Vorteil, dass man da im Simulator debuggen kann. Danach kann das dann in die LIB übernommen werden. Wenn ich irgendwo hänge, melde ich mich. Ich muss jetzt erst mal das Paket auspacken und das Display zum Laufen bringen.
 
Hallo Stafan,

ja ok, kannst dich ja melden, wenn ich etwas in Assembler übernemen soll :)

Den ersten Befehl, den du senden musst ist der SetBacklightIntensity mit dem Parameter 0 bis 255 (Byte), wobei 255 für volle Helligkeit steht. Erst dann wird der Schaltregler für die LED-Spannung aktiviert. Also ähnlich wie bei dem OLED.

(Noch ein Hinweis: Die Pausezeiten ta und tb für das Signal CS_ beachten (mind. 100ns, bei einem AVR etwa 2 nop), besonders tb ist bei schnell getaktetem Mikrcocontroller wichtig, da ja hier das SPI mit CS_ high deaktiviert wird. Bei tb=0 könnte der letzte Takt (das letzte Bit) sonst nicht mehr zum Display rüberkommen.

Dann mal viel Erfolg :)

Dirk
 
Hallo Dirk,

jetzt könnte ich wirklich Hilfe gebrauchen. Ich habe die meisten Subs in Bascom umgesetzt. Funktioniert auch problemlos. Einen Teil der Subs habe ich auch schon in Assembler umgesetzt und in die Library eingebunden. Das Senden per SPI ist kein Problem mehr. Jetzt hänge ich aber an der Umsetzung von
Code:
Sub Touchpanel_readdown()
   Sendcommand Cmd_touchpanel_readdown
   Spiin Xwert , 2
   Swap Xwert
   Spiin Ywert , 2
   Swap Ywert
   Waitus 1
   Set Display_cs
   Bitwait Display_busy , Set
End Sub
XWert und YWert sind im Bascom-Programm als Word definiert. Die Umsetzung von Sendcommand zum Senden ist schon umgesetzt. Wie aber bekomme ich in Assembler die Werte vom Display eingelesen?
 
Ich habe die meisten Subs in Bascom umgesetzt. Funktioniert auch problemlos.


Hallo Stefan!

Och mensch.... wofür mache ich mir hier die ganze Arbeit, mit meinem 4,3" Touch-TFT, wenn du schon alle Subroutinen fertig hast. :hmmmm: ;)

Ich habe eigentlich auch fast alle Routinen fertig und werde dir hier bald einstellen.
Vielleicht kannst du mir dann ja "zur Hand" gehen bzw. mich etwas unterstützen.

Grüße,
Cassio
 
Hallo,

nachdem ich noch ein paar Probleme beim SPI-Empfang hatte, funktionieren nun alle Routinen auch in der Assembler-Variante. Ich habe mal die BASCOM-Routinen in den Disassembler geworfen und mir da das nötige abgeschaut. In der Lib sind bis jetzt etwa 80% aller Funktionen umgesetzt, den Rest sollte ich heute Abend noch hinbekommen. Dann werde ich die LIB hier veröffentlichen. Soweit ich dem Datenblatt entnehmen konnten, sind die Routinen ja wohl auch für die größeren TFT-Module verwendbar.
 
Hallo Stefan!

In BASCOM habe ich die Routinen auch alle fertig! :cool:
Allerdings sehe ich mich nicht in der Lage, das in ASM umzsetzen.
Die Idee, das Ganze aber über einen Disassembler zu machen, ist natürlich eine Nette. ;)

Nun bin ich aber mal gespannt, was du da schönes gezaubert hast.
Ich stelle mich zumindest mit meinem 4,3" TTFT gern als "Testobjekt" zur Verfügung. :cool:

Grüße,
Cassio


PS: Mensch Kerl, hättest du am Samstag nicht zum Stammtisch kommen können?
Das wäre doch ein super Thema gewesen. :)
 
Hallo,

ich habe noch Schwierigkeiten bei den 32bit und 64bit Zahlen mit der Umsetzung in ASM. Da muss ich noch etwas probieren. Bis morgen sollte das aber alles klappen. Ansonsten scheint es jetzt alles richtig zu laufen.
Die Umsetzung in ASM ist gar nicht so schwierig, wenn man sich erst mal etwas damit beschäftigt hat.

Wäre schon ein gutes Thema gewesen. Aber der Anfahrtsweg von knapp 700 km war mir dann doch etwas zu weit.
 
Hallo Stefan!

Ich kann ja mal ein neues Thema eröffnen, in dem wir dann "gemeinsam" die Routinen einstellen.
Sowohl in BASCOM, als auch in ASM!

Stimmt schon... wenn man sich einige Zeit mit ASM in den LIBs befasst, dann kommt man recht schnell dahinter.
Ging mir ja beim Umstellen der Andersson-LCD-LIB auf das Arduino-LCD auch so. ;)


Momentan frage ich mich aber gerade, warum du 32bit oder gar 64bit Variablen hast? :hmmmm:
Senden kannst du per SPI doch sowieso immer nur 8bit...... und die breitesten Werte für das Display (z.B. die Koordinaten) sind doch höchstens 16bit!
Hast du da mehrere Werte zusammen gefasst, oder geht es dir um den Text mit 99 Zeichen?


Ich kann dann ja mal mit dem "Veröffentlichen" anfangen....
Wollte das sowieso die Tage machen. :)

Grüße,
Cassio
 
Hallo Cassio,

Es gibt da z. B. "DisplayHex64" oder "DisplayDecimalSigned32". Wenn ich da einen Wert als Double oder Long übergebe, muss ich diesen vom Stack holen und dann per SPI ans Display schicken. Klar, es werden immer nur einzelne Bytes geschickt. Aber die muss ich ja in der Richtigen Reihenfolge übergeben. Die 32bit-Werte funktionieren mittlerweile auch. Nur wenn ich einen 64bit-Wert übergeben, passt das Ergebnis nicht. Ich muss vermutlich mal den Logic-Analyzer anstecken und mir anschauen, was tatsächlich übertragen wird.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)