
|
INFO - FAQ - CC2-Forum - CCPro-Forum |
|
||
|
Hallo, ein super Beitrag, mir ist nur noch nicht klar ob man mehrere Ports gleichzeitig als PWM verwenden kann (möchte 5 conrad Dimmer ansteuern) oder gibt es dann timing probleme > Auch wenn der Thread schon etwas älter ist, möchte ich hier noch einmal darauf eingehen. > Mit dem Dimmer hat Conrad ein fragliches Teil auf den Markt geworfen, dessen Ansteuerung > sich zum Bleistift mit einem DA-Port weit einfacher hätte machen lassen. > Der Dimmer könnte das auch, der Nutzer einer CControl-Station sucht jedoch vergebens > nach einem D/A-Port an seiner Kiste :-( > Das ist mal wieder Conrad live: Der geneigte Kunde hat das Nachsehen und diejenigen, > die mit der Programmierung wenig am Hut haben, verzweifeln an Fragen wie: > > 1. Warum, muss ich krampfhaft ein und die selbe feste Variable für den > auszugebenden Wert verwenden? > 2. Wieso, geht das Ding nur am Digitalport 3? > 3. Warum stottert die BEEP-Ausgabe? > 4. Geht das denn überhaupt anders zu machen? > > Antworten wir mal :-) ...... zuerst mit dem Original-Dimmer-Treiber in BASIC-Worten > > 0101 lda #6 ' Sorge dafür, dass alles > 0103 sta $52 ' ab Adresse 0106 automatisch alle 20 ms runtergerasselt wird > 0105 rts ' und kehre zurück zu BASIC > > 0106 lda $a1 ' akku = "BASIC"-Variable 1 (byte[1]) > 0108 bset 2,1 ' Port3 (des Byteport 1) = on > 010a deca ' akku = akku - 1 > 010b bne $010a ' if akku > 0 then goto 010a > 010d bclr 2,1 ' Port3 (des Byteport 1) = off > 010f lda #1 ' akku = 1 > 0111 rts ' return > > binär (hexdump) sieht das so aus: > a606 b752 81 b6a1 1401 4a 26fd 1501 a601 81 > bzw kennt der Dimmer-Neueinsteiger das so: > a6 06 b7 52 81 b6 a1 14 01 4a 26 fd 15 01 a6 01 81 > > Jetzt hat sicher jeder verstanden, was die merkwürdigen Zahlen hinter dem > syscode-Befehl im Beispielprogramm bedeuten. > > zu 1. ...Variablenfrage... > Wer aufmerksam mitzählt, weiß nun sicher schon, was er ändern müsste, um > die Nummer der Basic-Variable zu ändern. Diese liegt im System an Adresse > a1 und wird bei jedem Aufruf der Routine ab Adresse 0106 geladen. > Das 7. Byte also im syscode nennt die Adresse der Varable. Hexadezimal > weitergerechnet könnte man so die nächsten 23 möglichen Adressen verwenden. > Der Ladebefehl lda a3 an Adresse 6 (0106 b6a3) würde also zum Bleistift > byte[3] in Basic meinen. > Die "sys-Bytes" entsprechend neu in den Kontroller übertragen - und schon könnte > man sein Basic-Programm diesbezüglich anpassen. > (nicht machen! der Treiber ist so falsch und hier nur als Beispiel gezeigt) > > zu 2. ...Digitalportfrage... > Genau in den Quelltext gesehen? die Maschinenbefehle bset und bclr > bedienen den (Bit-)Port. die Parameter hinter den Befehlen geben an, welches Bit an > welchem Byteport gemeint ist. Bits werden im System von 0...7 gezählt, Basic macht > daraus 1...8. Da der Kontroller als 8-Bit-Rechner nicht wirklich mit Words im Sinne > von Basic rechnet, gilt in Maschinenprogrammen für den Byteport 2, zu dem > in Basic die Ports 9...16 gehören: ebenfalls Bits 0...7, aber port 2. > Um zum Bleistift Port 15 einzuschalten, muss bset 6,2 benutzt werden. > Auf die Richtungsregister möchte ich nicht eingehen, die haben keine Bedeutung für > den Dimmer, wenn man den Dimmerport bei Start des Basic-Programms off setzt. > Das sollte man auch tunlichst, sonst ist der Port ein "Eingang" und nichts geht. > > zu 3. ...BEEP-Stotter-Frage... > Basic-Benutzern ist der freilaufende 20-ms-Timer sicher schon genug geläufig. > Er wird in diesem Takt (also alle 20 ms, 50 mal pro Sekunde) um 1 erhöht - > völlig egal, was man tut. Somit ist er gut für Zeitmessungen einsetzbar. > Seine Existenz ist aber nur die halbe Wahrheit, in Wirklichkeit ist er von einem system- > internen Timer, der 10.000 mal schneller läuft und andere Timingfunktionen sowie > die Echtzeituhr bedient, mathematisch abgeleitet. Die Mathematik bewirkt einen > Interrupt, der alle 20 ms ausgelöst wird und eben genannte Systemfunktionen bedient. > Der Dimmertreiber läßt sich von diesem Interrupt anschubsen, macht sein kurzes Ding > und gibt ans System zurück. Dies dauert selbst im Höchstfall nicht einmal 1 ms! > Trotzdem kommt ihm da Wer in die Quere: der BEEPer. > Ich will es nicht genauer erklären - es reicht zu wissen, daß der Beep > von dem selben Interrupt abgekoppelt wird. > Da die Herunterzählschleife des Dimmertreibers eine Echtzeitanwendung ist und, > wenn auch nur sehr kurz, so aber voll den Prozessor in Anspruch nimmt, überlagert > sie den BEEP stroboskop-artig. Das heißt, nicht immer und nicht permanent, aber spürbar. > Hinzu kommt, dass ein Design-Fehler im Betriebssystem (es ist nicht Microsoft! *g*) > die Interrupt-Behandlung in falscher Weise erledigt und den Effekt so verdoppelt. > Dies hat der Programierer des Dimmertreibers nicht beachtet. > Deshalb wird der Dimmer durch den mitgelieferten Treiber auch nicht 50 mal pro > Sekunde "bepulst", sondern 57,7 mal. Warum? Der BEEP-Timer löst alle 131,07 s > (7,7 mal pro s) einen Roundtrip-Interrupt aus, den der Dimmertreiber eigentlich > ignorieren müsste. Deshalb wird der BEEP ärger als ohnehin unterbrochen. > > zu 4. ...geht's besser... > Klare Antwort: JA! Und zwar auf verschiednen Wegen. > Einen möchte ich hier vorstellen. Er entstand als Resultat meiner "Forschungen" > zur Funktionsweise der ganzen Sache und der Mithilfe bei der Programmierung > einer Steuerung von Terrarien. Das Ziel des Dimmers: Zeitgesteuert Sonnenauf- > und Untergang simulieren und bei Überhitzung der Becken die Lichtflut reduzieren. > Da die Kennlinie des Dimmers mit der Digiport-Pulserei alles andere als auch nur > ansatzweise eine Gerade ist, war diese zunächst "geradezubiegen". > Ein weiterer Dorn in meinen Augen war, dass das Byte[1] in Basic als Variable > für den Dimmer "festgenagelt" war. Die falsche Interruptbehandlung war auch zu > lösen und der störende Einfluss des Dimmertreibers auf des BEEP zu minimieren. > herausgekommen ist dabei dies: > > portnr equ 5 > byteport equ $01 > > org $101 > lda #$08 > sta $52 > clr $dc > rts > > brclr 6,$13,_handleST > jsr $ee9 > clra > rts > > _handleST jsr $e70 > lda $dc > cmp #20 > bhs _endTOCIRQon > tax > lda _dimtab,x > beq _endTOCIRQoff > bset portnr,byteport > _deca deca > bne _deca > _endTOCIRQoff bclr portnr,byteport > clra > rts > _endTOCIRQon bset portnr,byteport > clra > rts > > lda $92 > sta $dc > rts > > _dimtab fcb 0, 4, 5, 6, 7, 8, 8, 10, 11, 12 > fcb 13, 14, 15, 17, 19, 21, 23, 27, 40, 50 > > Das funktioniert folgendermaßen: > > Mit sys &h101 startet man in BASIC das erste Stück, womit das Ding > loszulaufen beginnt. Setzt man davor oder dahinter den (im Moment) Port 6 off, > so fällt der Dimmer ab. > Um dem Dimmer einen neuen Ausgabewert zuzuweisen, wird mit sys &h12c,wert > dieser ans Maschinenprogramm gegeben, welches den Wert in den Weiten des Systems > verbuddelt. Damit ist man von der zwanghaften Verwendung einer festen Variable befreit. > Der Hauptteil des Treibers holt sich den zwischengespeicherten Wert, der jetzt auch nur > noch 0...20 (dezimal) betragen darf, und prüft diesen: > wenn 0, dann schalte ganz aus, wenn 20, dann schalte ganz an. > Damit ist man von unnützen Schleifen befreit, die den Prozessor bremsen und nur mühseelig > eine Vollaussteuerung des Dimmers erreichen. > Liegt der Wert im bereich 1<= x <= 19, so wird aus der fcb-Tabelle ein Wert für den > Schleifenzähler geholt, und die bekannte Prozedur abgewickelt. > Zu den fcb's sei gesagt, dass die Werte experimentell an der CC1-Station eines Bekannten > ermittelt wurden. Die Digitalports an dieser erzeugen ein recht rundes Signal. Main-Unit'ler > müssen die vereinfachte, berichtigte Routine weiter unten verwenden (nicht den original-Treiber!!!), > um sich die für sie passenden Werte zu ermitteln. Diese liegen deutlich unterhalb der obigen. > Somit wäre auch die Frage der Linearität des Dimmers geklärt. Je nach Situation kann der > Beep zwar auch künftig stottern, jedoch kann man mit der Tonhöhe experiemntieren, um > einen Ton zu finden, der störungsfrei wiedergegeben wird, wenn der Dimmer nicht gerade > auf 0 oder 20 läuft - dann stört eh nichts mehr. > Ich hoffe, künftigen Dimmer-Benutzern damit einen Einblick und Hilfe gegeben zu haben. > > Zum Schluß die einfache, aber berichtigte Standard-Routine, welche byte[1] > und Port 3 benutzt. Zum Testen, Spielen und Ausgabewerte ermitteln ist sie OK: > > org $101 > lda #6 > sta $52 > rts > > brclr 6,$13,_handleST > jsr $ee9 > bra _ready > > _handleST jsr $e70 > > lda $a1 > beq _ready > bset 2,1 > _deca deca > bne _deca > bclr 2,1 > _ready clra > rts > > Wer das nicht erst übersetzen möchte, nimmt einen ASCII-Editor, übernimmt den > folgenden Inhalt und speichert die Daten als wasweißichwas.s19 > > S1200101A606B752810D1305CD0EE9200ECD0E70B6A1270714014A26FD15014F8158 > S5030001FB > > viel spaß beim dimmen :-) |
| Antwort schreiben |