Alternative zu ws2801 lpd6803 tm.... u.s.w gesucht!

  • 8 Bit DMX rein in den Controller, der guckt in der Tabelle nach und setzt das auf 16 Bit Werte um...


    in meiner Kugelmatrix habe ich auch ne Gammakorrektur drin, weil ich festgestellt habe, dass die Werte vom Bildschirm (die das Matrix-Steuer-Programm erzeugt) auf den LEDs viel zu hell, und die Farben dadurch auch zu blass rüberkommen.


    bei mir wird halt von 8 Bit auf 8 Bit umgesetzt, wodurch ein paar Stufen verloren gehen - da wäre ne Umsetzung von 8 auf 12 oder 16 Bit eben besser...


    siehe dazu auch hier...


    und Zeit dafür haettest

    Das ist das Problem, die habe ich i.M. leider überhaupt nicht - wird schon knapp, dass mein Zeug alles rechtzeitig fertig wird... diese Matrix soll am 13.1. auf ner Party hängen, und es sind gerade mal 2 Ketten fertig, 1/2 von 4 Controllern, und die SW zu 70%...

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • huh, da gibt es ja schon auch ein code für 12bit gamma von nenni ;)


    bis am 13.1 kriegst DU doch die kette locker hin :)


    Na gut, ich werd mal demnaechst gucken wie ich die DMX routine an die TLC einbinden kann. Wird ein laaaanger Weg dahin sein. Kann ja hier nach tipps fragen wenns kompliziert für mich wird ;) (heisst: alle 5 minuten poste ich dann ne frage für jede zeile code ;P )

  • Also hab mal ein bisschen assembler studiert ;)


    Wie ich das so sehe, müsste ich mit deinem tlc5947ram ausgabe code folgendes tun:
    (Haut das alles eigentlich mit nem Mega16 und 16mhz hin?)


    1- Register & Konstante Definieren für die TLC's in deinem code
    2- ISR für DMX und die Konfiguration dafür sollte kein problem sein
    3- Ram puffer daten vom DMX in die ARR_TLC_Out reinschreiben lassen
    3- Wenn ich das richtig verstehe, müsste dann TLC_Out_Loop auch daten vom Ram bekommen statt von der Tabelle oder?


    Für die Ausgabepins hab ich mal sowas festgelegt:


    Code
    .equ TLC_Data			= 6				; Ausgabepin TLC5947 Data
    .equ TLC_Clk			= 7				; Ausgabepin TLC5947 Clock
    .equ TLC_Blank			= 21				; Ausgabepin TLC5947 Blank
    .equ TLC_Lat				= 22				; Ausgabepin TLC5947 Latch
    .equ TLC_Out			= 23				; Ausgabepin TLC5947 Out


    Meint ihr ich bin auf dem richtigen Weg ? ;)

  • Fast.... ;)


    bei den Pins ist nicht die Nummer am IC-Gehäuse gemeint, sondern die vom Port.


    Der Port muss auch definiert werden, bei "TLC_Port" - also z.B. bei


    .equ TLC_Port = PortC
    .equ TLC_Data = 0
    .equ TLC_Clk = 1


    kommen die Daten dann an PortC0 raus und Clock an PortC1, usw.


    das ist noch ne alte Routine, sorry, bei meinen neuen stehen oben im Header diese ganzen Definitionen drin zum rauskopieren...


    genau, die DMX-Empfangsroutine muss dann die Daten in's RAM schreiben ab Adresse ARR_TLC_Out (diese muss eben auch definiert werden, bei nem Mega16 z.B. .equ ARR_TLC_Out = 0x0060)


    und die Patchtabelle ist dann dazu da, die Daten bei der Ausgae umzusortieren, also wenn Du die LEDs in ner bestimmten Reihenfolge, so wie's vom Layout her passt, an den TLC5947 angeschlossen hast, dass dann jede DMX-Adresse zur richtigen LED passt..

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Danke für die Tipps.


    Du benutzt hier SW SPI oder? Man kann also die Data & Clk von irgendeinem Pin rausgeben?


    Wegen der Patchtabelle:
    Zeigen die Zahlen die DMX kanaele oder bedeutet jeder Zahl 1 RGB led?
    zb.:
    .db 8, 7, 6, 11, 10, 9, 23, 22
    .db 21, 20, 19, 18, 17, 16, 15, 14
    .db 13, 12, 2, 1, 0, 5, 4, 3


    ist also 5,4,3 ein RGB Led oder 3 RGB Leds?




    Edit 1: Braucht der TLC überhaupt auch so ne Warteschleife wie bei den 2801's?
    Edit 2: TLC_kanaele definieren sollte doch .equ TLC_kanaele = 24 sein oder nicht?


    ;)

  • genau, wenn Du einen TLC hast, dann sind das 24 Kanäle - Du kannst mit dieser Routine auch mehrere kaskadierte TLC ansteuern, dann halt die Zahl der Kanäle entsprechend erhöhen (und die Patchtabelle vergrößern).


    Warten ist hier nicht nötig, da gibt's ja ein extra Latch-Signal, das geht hier nicht über eine Pause - Du kannst also in der Hauptschleife einfach immer die Daten aus dem RAM ausgeben.


    Hier beachten: der TLC hat ja 12 Bit, also ist der Puffer dort auf 16 Bit ausgelegt, also 2 Byte pro Ausgang (erst LSB, dann MSB). Du kannst also nicht direkt (bzw. hängt halt von Deiner Empfangsroutine ab) die empfangenen Bytes da rein schreiben.


    ich würde das so machen: Du schreibst die empfangenen Kanäle mit der DMX-ISR in nen extra RAM-Bereich. In der ISR setzt Du ein Flag, wenn ein kompletter Frame empfangen wurde. In der Hauptschleife wartest Du immer drauf, dass dieses Flag gesetzt ist, dann lscht Du das Flag, kopierst Du die Daten in den Ausgabepuffer und rechnest sie dabei auf 12 Bit um. Dann ausgeben, und wieder auf das Flag warten.


    Dann läuft das Ganze synchron, und es kann auch kein Flackern geben, weil sich Empfangs- und Sende-Routine gerade irgendwo überschneiden...


    das umrechnen beim Kopieren kann dann eben nachsehen in ner Tabelle sein (für Gammakorrektur), oder im einfachsten Fall das empfangene Byte 4 Bit nach links schieben, um nen Pseudo-12-Bit-Wert (letzte 4 Bits immer 0) draus zu machen...


    Weißt Du wie das geht mit der Bitschieberei und Flags setzen/abfragen...?


    Die Zahlen in der Tabelle sind die DMX-Kanäle, richtig - mit einer Änderung: es geht bei 0 los, nicht bei 1... also 1 Zahl ist ein Pin am TLC, für ne RGB-LED also 3 Zahlen


    wie dort steht, das ist in umgekehrter Reihenfolge, weil der TLC praktisch ein normales Schieberegister ist, d.h., was Du als erstes rein schiebst, kommt am letzten Pin an... wenn also z.B. die *letzten* 3 Ausgänge des TLC auf Kanal 22, 23 und 24 reagieren sollen, dann *beginnt* die Tabelle mit 24, 23, 22...


    und, ja, es ist SW-SPI, Du kannst also die Daten irgendwo raus schicken - nur nicht vergessen, die Pins auch auf Ausgang zu stellen... ;) hier sind's nicht nur Data und Clock, sondern eben auch noch Latch und Blank, also insg. 4 Signale...

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Leider Nein ;( Mit dem Bits und Flags wirds mir dann schon wie du geahnt hast zu viel. Hab keine Ahnung wie ich das umsetzen soll.


    EDIT:
    Bin mal beim rumstöbern auf ein thread aufmerksam geworden bzgl. 5947 und BLANK flackern. Da schreibt TI support dass 5947 eher für bilder statt videos designed wurde und dass der 5940 besser dafür ist. Was soll das denn heissen?


    http://e2e.ti.com/support/powe…_bias/f/192/t/120587.aspx

  • k.A. - kann die Seite nicht ansehen, da haut's bei mir total den Text durcheinander...


    war hier auch schon mal im Gespräch, dieses Problem mit dem Flackern bei der Datenübernahme, tritt aber mit meiner Routine nicht auf, da dort eben der Blank benutzt wird...


    das mit den Bits etc. ist ganz einfach - erst mal zu den Flags:


    ein Flag ist einfach ein Bit in einem Register, das Du setzt oder löscht, um nen bestimmten Zustand anzuzeigen/zu merken - wie eben hier, dass ein kompletter Frame empfangen wurde...


    am Besten lädst Du Dir mal bei Atmel.com die AVR-Befehlsübersicht runter, da ist zu jedem Befehl erklärt, was der macht, da kannst Du das leichter nachvollziehen...


    Du definierst also ein Register, das Du für die Flags benutzt, z.B.:


    .def Flags = R24 ; Diverse Flags (oder was halt noch frei ist, muss aber größer 15 sein)


    und Dein Flag mit z.B.:


    .equ DMX_FRAME_COMPLETE = 0


    das sind letztlich nur Merkhilfen für Dich, der Assembler ersetzt intern also überall "Flags" durch R24, und "DMX_FRAME_COMPLETE" durch 0, für ihn ist es also das selbe, egal ob Du


    sbrs Flags, DMX_FRAME_COMPLETE oder


    sbrs R24, 0


    schreibst - wichtig: für Register muss man .def nhemen, für alles andere .equ - Gross- und Kleinschreibung ist egal, es ist aber so ne Konvention, dass man Konstanten in Grossbuchstaben schreibt.


    Du kannst also nun mit:


    sbr Flags, (1<<DMX_FRAME_COMPLETE) das Flag auf "1" setzen (in der DMX-Routine, wenn der Frame durch ist), und mit
    cbr Flags, (1<<DMX_FRAME_COMPLETE) das Flag auf 0 setzen (nachdem Du es abgefragt hast)


    warum es einmal (beim setzen/löschen) "(1<<DMX_FRAME_COMPLETE)" heisst, und einmal nur "DMX_FRAME_COMPLETE" (beim abfragen), dazu siehe eben die Befehlsübersicht... ;)


    in der Hauptschleife oben machst Du einfach die Abfrage rein:


    _main:
    sbrs Flags, DMX_FRAME_COMPLETE ; nächsten Befehl überspringen, wenn das Flag gesetzt ist
    rjmp _main ; Flag nicht gesetzt, weiter abfragen
    cbr Flags, (1<<DMX_FRAME_COMPLETE)


    das heisst also, so lange das Flag nicht gesetzt ist, springt er wieder zu _main zurück, wenn's dann gesetzt wurde (durch die DMX-ISR), macht er weiter, lscht das Flag wieder - danach dann die Kopier-Routine und Ausgabe, dann wieder zu _main, also wieder drauf warten, dass das Flag gesetzt wird.


    zum Kopieren erst mal zwei Pointer setzen:


    ldi YL, low(DMX_Buffer) ; Y auf DMX-Buffer
    ldi YH, high(DMX_Buffer)


    ldi ZL, low(Arr_TLC_Out) ; Z auf Ausgabepuffer
    ldi ZH, high(Arr_TLC_Out)


    dann in einer Schleife die Werte kopieren - immer erst den Wert aus dem DMX-Buffer holen mit Post-Increment (bedeutet, der Zeiger zeigt nach dem holen auf das nächste Byte):


    ld temp0, Y+


    ein Register löschen:


    clr temp1


    um in diesen beiden Registern den 12-Bit-Wert zusammenzubasteln - dazu muss eben der 8-Bit-Wert in temp0 um 4 nach links geschoben werden:


    rol temp0
    rol temp1
    rol temp0
    rol temp1
    rol temp0
    rol temp1
    rol temp0
    rol temp1


    es werden also die 8 Bit in temp0 um eins nach links geschoben, das höchste Bit dabei in's Carry - dann das selbe mit temp1, wobei das unterste Bit aus dem Carry kommt - das Ganze eben 4 mal.


    dann diese beiden Bytes in den Ausgabepuffer schreiben:


    st Z+, temp0 ; Low-Byte speichern
    st Z+, temp1 ; High-Byte speichern


    auch hier wird wieder der Pointer automatisch erhöht, um eben immer nach dem Speichern auf das nächste Byte zu zeigen


    das war's dann auch schon, da drum rum halt ne Schleife basteln, die 510x durch läuft, wie man das macht, da kannst Du nun mal selbst gucken (Mikrocontroller.net o.ä.) ;)

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Hi Pesi,


    Wow, noch nie gesehen, dass da jemand wirklich Zeit nimmt und alles bis ins letzte Detail schreibt! Hast mich echt überrascht. Respekt!!! :thumbup:


    Ich habe es mir mal ein bisschen einfacher gemacht und als Vorlage dein Code für den 2801 genommen. Alle veraenderungen mache ich auf diesem Code. Wenn Du oder andere in den Code (was ich hoffentlich noch zu ende bringen werde) mal was editieren wollen, dann habt ihr das ajf einfacher. Sonst waers echt n mischmasch und unmöglich für mich das hier zu Realisieren ;) Ich finde halt das System wie du programmierst sehr hilfreich, und ist besonders mit den einzelnen .inc dateien sehr Übersichtlich.


    So nun mal wieder ein paar Fragen:


    .def Flags = R24
    .equ DMX_FRAME_COMPLETE = 0


    und


    push YL
    push HL


    habe ich Definiert.


    Ist der "Dmx_Buffer" bei YL und HL der gleiche wie "DMX_Data" in der ISR_Byte_received.inc? Also kann ich wieder statt "Dmx_Buffer" den "DMX_Data" nehmen, weil die ja im gleichen Ram Bereich liegen? Oder muss ich trotzdem zusaetzlich mit ".equ DMX_Buffer = 0x0060" den Ram Bereich festlegen.
    Wozu brauchen wir YL und YH wenn in der DMX/ISR die "DMX_Data" ZL und ZH ist? Vielleicht echt ne bescheuerte Frage, aber nur so kann ich ein bisschen was verstehen :P

    Ist da von dir vielleicht ein Tippfehler drin?
    Weil im ersten Paragraph heisst es "sbr" und unten "sbrs".


    Wieder im ersten Paragraphhast du 1<<DMX_FRAME_COMPLETE in klammern, weiter unten sind aber die klammern weg und der 1<< ist auch nicht mehr da. Welche ist denn nun richtig?


    Ist die Hauptschleife so ok?
    (DMX-zu-TLC5947.asm)


    Und in der Datenausgabe aus RAM an TLC5947 ( das ist ja nun SUB_TLC5947_Out.inc geworden) habe ich es jetzt so umgesetzt (Kopiert habe ich hier nur den Teil mit dem Registern und dem Loop Bereich):


    Das wars erstmal...


    To be continued ;)
    Eddie


    PS: Vielleicht lachen die Profis mich jetzt bestimmt aus, aber ich lache echt mit Euch waehrend ich die Fragen hier tippe. Trozdem ist es mir nicht peinlich, weil es mir einfach spass macht ein bisschen zu lernen ;)

  • Ja, wenn Du (und evtl. andere auch noch) was dabei lernst, dann hat sich's ja auch rentiert.


    push YL
    push HL


    habe ich Definiert.

    Da gibt es aber nix zu "definieren" - "push" ist ein Befehl, und bedeutet, dass das Register auf den Stapel gelegt wird...


    Ist der "Dmx_Buffer" bei YL und HL der gleiche wie "DMX_Data" in der ISR_Byte_received.inc? Also kann ich wieder statt "Dmx_Buffer" den "DMX_Data" nehmen, weil die ja im gleichen Ram Bereich liegen? Oder muss ich trotzdem zusaetzlich mit ".equ DMX_Buffer = 0x0060" den Ram Bereich festlegen.

    Das kommt daher, dass die eine Routine halt 2, 3 Jahre älter ist als die andere, da habe ich halt mal so, mal so geschrieben... aber wie gesagt, das sind ja nur Namen für Konstanten, Du kannst also nun entweder überall "Dmx_Buffer" durch "DMX_Data" ersetzen, oder du definierst für "Dmx_Buffer" eben die selbe Zahl (0x0060)...


    Wozu brauchen wir YL und YH wenn in der DMX/ISR die "DMX_Data" ZL und ZH ist? Vielleicht echt ne bescheuerte Frage, aber nur so kann ich ein bisschen was verstehen :P

    Hier ebenso: ein mal habe ich halt den Y-Pointer benutzt, ein mal den Z-Pointer - das ist völlig egal... evtl. ist's halt damals so besser ausgegangen, bei kleinen Projekten, wo man nicht viele Register braucht, reserviert man manchmal die Pointer fest, also z.B. Y für die Empfangsroutine und Z für die Ausgaberoutine...


    Ist da von dir vielleicht ein Tippfehler drin?
    Weil im ersten Paragraph heisst es "sbr" und unten "sbrs".


    Wieder im ersten Paragraphhast du 1<<DMX_FRAME_COMPLETE in klammern, weiter unten sind aber die klammern weg und der 1<< ist auch nicht mehr da. Welche ist denn nun richtig?

    siehe hier, es ist beides richtig:

    warum es einmal (beim setzen/löschen) "(1<<DMX_FRAME_COMPLETE)" heisst, und einmal nur "DMX_FRAME_COMPLETE" (beim abfragen), dazu siehe eben die Befehlsübersicht... ;)

    das ist kein Tippfehler, "sbr" heisst "set bit(s) in register" und dient zum setzen der Bits, "sbrs" heisst "skip if Bit in Register is set", eben, den nächsten Befehl überspringen, wenn das Bit gesetzt ist (zur Abfrage)...


    der Mechanismus ist da unterschiedlich, setzen kann man mehrere Bits auf einmal, deswegen das 1<< - abfragen kann man aber nur eins, deswegen da dirket die Bit-Nummer...


    wie schon gesagt, am Besten schaust Du Dir erst mal die Befehlsübersicht an, was die Befehle überhaupt bedeuten und was sie machen - ausserdem das Tutorial bei Mikrocontroller.net - weil mit reinem Copy&Paste funktioniert das nicht, wenn man nicht mal weiß, was der µC nun macht, wenn man "sbrs" hin schreibt... ;)

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Habe gestern Tutorial von MC und AVR Befehlsübersicht schon runtergeladen. War wohl zu schnell mit der Antwort. Haette erstmal die Dokumente checken müssen....Ich werde versuchen ab Mitternacht keine codes mehr zu schreiben (copy&paste), wird wohl nur noch schlimmer ;)


    Über die Hauptschleife und TLC_Out_Loop Codes hast du nichts geschrieben. Ich geh mal davon aus dass die total falsch sind?


    BB & Danke nochmal

  • Da war's mir dann doch zu spät, da auch noch was dazu zu schreiben... aber, ja es ist falsch... ;)


    Grundsätzlich: Du baust Dir hier ja ne SW zusammen unter Verwendung bereits bestehender Routinen - das ist ja auch ganz üblich, keiner erfindet immer wieder das Rad neu...


    nur, da gibt es zwei Möglichkeiten: entweder man nimmt ne Routine, so wie die geschrieben ist, und benutzt sie als Programmteil - oder man nimmt Codeschnipsel und modifiziert sich die nach seinen Anforderungen - dazu muss man dann aber genau wissen, was man da macht... und dazu erst mal nachvollziehen, was der Code überhaupt bewirkt... sollte bei meinem recht einfach sein, da gut kommentiert...


    zur Augaberoutine, wo Du diese Umrechnung mit rein geflickt hast: Die setzt ja erst mal nen Zeiger auf die Patchtabelle, der dann in der Schleife erhöht wird - ein Zeiger ist praktisch ne Adresse im RAM oder Flash... der zeigt also zuerst auf den ersten Wert in der Patchtable und holt den, beim nächsten Durchlauf den 2., usw.


    dieser Wert wird dann zur Basisadresse des Ausgabepuffers dazu addiert - dadurch geschieht das umsortieren. Eben wieder mit nem Zeiger, der erst auf die Startadresse des Puffers gesetzt wird, und dann der Wert aus der Patchtabelle dazu addiert wird.


    Und der Teil fehlt hier nun, Du holst einfach der Reihe nach Bytes aus dem DMX-Puffer, verschiebst die, und speicherst die dann an ne komplett falsche Adresse, weil der Z-Pointer ja eigentlich auf's Flash gesetzt ist (wo die Patchtabelle drin ist)... ;)


    Das ist nun für nen Anfänger evtl. nicht so leicht nachvollziehbar, was da in der Routine genau passiert - deswegen ist es eben besser, die einfach so zu benutzen, *wie sie ist*, *da* nix dran zu ändern!


    Genauso, wie Du in Bascom o.ä. z.B. For...next schreibst, ohne dass es Dich groß interessiert, was der Compiler draus macht...


    Beim Programmieren generell (egal welche Sprache), empfiehlt es sich, ein größeres Problem erst mal in mehrere kleinere zu zerlegen - wie sieht das hier aus..?


    Programm insgesamt läuft so:


    - in einer ISR werden per DMX empfangene Bytes in's RAM geschrieben - diese ISR hast Du ja schon fertig, da musst Du (ausser der Sache mit dem Flag) nix dran machen, die kannst Du einfach benutzen


    - in der Hauptschleife wird drauf gewartet, dass das Flag gesetzt wird, das sind die 4 Zeilen oben, das ist nur der *Beginn* der Hauptschleife...


    - dann werden die Daten "umgerechnet", so wie oben erklärt


    - dann werden sie ausgegeben - dazu gibt's ja eben die fertige Routine von mir, die Du einfach so verwenden kannst, wie nen Befehl "Daten ausgeben"


    - dann wieder nach oben, warten auf Flag gesetzt


    und so größere Programmteile (eben die Ausgaberoutine, auch die zum Bits verschieben) macht man eben in ne Subroutine, dann ist das Ganze übersichtlich und leicht änderbar - willst Du z.B. doch mal die Gammakorrektur rein machen, musst Du nur die Bitschieberoutine durch eine ersetzen, die die Gamma-Umrechnung macht, ohne am Code sonst was zu ändern - was aber eben nicht mehr geht, wenn die Bitschieberei bereits in der Ausgaberoutine mit drin ist... ;)


    die Hauptschleife, das "eigentliche Programm" sieht dann also so aus:



    so macht man sich das Ganze eben übersichtlich, ist dann fast wie ne Hochsprache, das Programm in der Hauptschleife besteht eben nur aus 3 Anweisungen: Warten auf Flag gesetzt, dann Daten umkopieren mit Bitschieberei, dann Daten ausgeben, das ist alles...


    und diese Routine "Change_8Bit_to_12Bit" eben auch in ne extra Datei, die Routine an sich habe ich Dir oben ja schon erklärt, ist einfach der Code ohne die Erklärungen dazwischen:



    die Schleife fehlt hier noch, wie gesagt, die kannst Du mal selbst machen - entweder zwei extra Register zum zählen benutzen, wie oft das Ganze schon durchlaufen wurde, man kann ja aber auch z.B. den Y-Pointer nehmen, der ja eh' imer um eins erhöht wird - Anfangs hat er den Wert DMX_Buffer, nach 510 übertragenen Werten eben (DMX_Buffer+510), also kann man einfach immer wieder nach oben springen, so lange Y kleiner ist als (DMX_Buffer+510)...


    EDIT: Du machst das Ganze j ain AVR Studio, oder..? - wenn'smal nahe an fertig ist, ist's dann besser, mal das komplette Projekt rein zu stellen, als nur Ausschnitte aus Quelltexten, damit man sieht, ob das überhaupt alles zusammen passt (z.B. eben auch die Definitionen, INterrupt-Vektor-Tabelle, etc.)

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

    Einmal editiert, zuletzt von Pesi ()

  • Hi Pesi,

    Du machst das Ganze j ain AVR Studio, oder..?

    Genau. AVR Studio 4. Oft nehme ich aber auch das Programm "Programmer's Notepad". Ist ziemlich fix.


    Ja, ich depp hab also die flags zwischen die SUB_TLC_Out schleife rein getackert :rolleyes:
    Die Pointer wie Y, Z usw verstehe ich jetzt besser.


    Die Idee die 8bit-12bit Routine in die SUB_TLC5947_Out einzubauen war dann auch doof. So ne sub Routine sieht schon ordentlicher aus. Vor allem wenn du schon alles vorgegeben hast. Bin noch nicht mal in der Lage korrekt zu Copy&Pasten :D


    Ne im ernst, wenn ich irgendwann mal ein DMX-zu-XXXXX Code basteln sollte, wirds definitiv einfacher gehen. Man lernt eben einiges durch diese Trial & Error Geschichten.


    Habe jetzt Stundenlang die AVR Befehle gelesen und bin dabei hoffentlich fündig geworden.
    Mal sehen ob das ok ist. War mir nur nicht so sicher ob ich temp3 und temp4 benutzen durfte.


    Habe übrigens schon alle .inc dateien entsprechend für TLC editiert. Beim Kompilieren kommen auch keine Errors.


    Hier der Code mit meinem Schleifchen ;)


  • So ne sub Routine sieht schon ordentlicher aus. (...)
    Ne im ernst, wenn ich irgendwann mal ein DMX-zu-XXXXX Code basteln sollte, wirds definitiv einfacher gehen.

    Genau - das musste ich auch erst lernen, anfangs waren meine Programme auch einfach alles in eine meterlange Datei geschrieben - so ist das eben übersichtlicher, man weiß bei jeder Routine, was sie macht, und muss ggfs. nur noch Routinen austauschen - also hier eben die mit der Bitschieberei gegen eine, die Gamma-Korrektur macht, wenn man das will, oder eben ne andere Ausgaberoutine statt TLC für andere Chips - der Rest vom Code ist davon eben unberührt...


    War mir nur nicht so sicher ob ich temp3 und temp4 benutzen durfte.

    Du darfst benutzen, was Du willst :D - musst nur den Überblick behalten.... ;)


    Hier z.B., in der Hauptschleife passiert weiter nix, da werden sonst keine Register gebraucht, also kann auch keins überschrieben werden - normal macht man das so, dass man zu Beginn einer Subroutine alle verwendeten Register auf den Stapel sichert, und nachher wiederherstellt, dann kann nix passieren in der Art, dass es seltsame Fehler gibt, weil in irgendeinem Register was drin steht, was da nicht soll...


    also eben oben z.B.:


    push temp0
    push temp1
    push temp2 usw. - damit werden die Inhalte der Register auf den Stack gelegt... und unten dann:


    pop temp2
    pop temp1
    pop temp0 - damit werden sie dann wieder vom Stapel geholt, die Inhalte dieser Register sind also nach dem Aufruf der Subroutine exakt so wie vorher, egal was diese mit den Registern gemacht hat...


    ich habe es mir schon länger angewöhnt, in die Routinen oben rein zu schreiben, was die eigentlich wie machen, welche Register sie benutzen und ggfs. Konstanten brauchen - so in der Art z.B.:



    da hat man dann alles auf einen Blick, und weiß auch nach 2 Jahren sofort wieder, wie man die Routine einbauen muss...


    das mit den Pointern hast Du anscheinend noch nicht ganz verstanden: Ein Pointer ist eben ein Zeiger auf eine Speicherzelle im RAM, der enthält eine Adresse - Du kannst Dir das so vorstellen, das RAM ist ein Kasten mit lauter Schubladen, in jeder liegt ein Zettel mit einer Zahl drauf. Der Pointer enthält dann eben die Nummer der Schublade, also wenn Y z.B. 15 ist, dann holst Du mit ld temp0, Y+ den Wert aus der 15. Schublade in temp0, anschließend ist Y dann 16.


    Jetzt schau Dir mal Deine Schleife an: Du holst da also nen Wert aus dem RAM, und vergleichst *den* (der kann irgendwas sein) mit DMX_Channels - so kannst Du ja nicht feststellen, wie viele Schubladen Du schon geöffnet hast... ;)


    Du musst also die Nummer der Schublade (= der Y-Pointer) überprüfen, ob Du schon alle durch hast - also z.B. die erste Schublade hat die Nummer 0x0060 (dezimal 96 = DMX_Buffer), und Du musst 512 Schubladen öffnen (512 DMX-Kanäle = DMX_Channels), dann bist Du also fertig, wenn Du bei Schublade Nr. 608 (= 96+512 = DMX_Buffer+DMX_Channels) angelangt bist.


    also musst Du eben die *Nummer* der Schublade (= Y) mit DMX_Buffer+DMX_Channels vergleichen, *nicht* das, was da drin ist...


    wundert mich, dass sich das assemblieren lassen hat, wenn DMX_Channels größer als 255 ist, muss ldi temp4, DMX_Channels nen Fehler ergeben, weil temp4 ja nur Zahlen von 0 bis 255 enthalten kann (8 Bit)...


    deswegen muss der Vergleich mit dem Y-Pointer auch in 16 Bit gemacht werden - "Y" ist auch nur ein Name, das bedeutet praktisch "das 16-Bit-Register, das aus ZL und ZH zusammengesetzt ist" - daher muss man die auch einzeln benutzen beim laden und vergleichen etc., so wie oben eben auch:


    Code
    ldi YL, low(DMX_Buffer) 	; Y auf DMX-Buffer
    ldi YH, high(DMX_Buffer)


    da kann man eben nicht ldi Y, DMX_Buffer schreiben... ;) (leider, wenn der Assembler "schlau" wäre, wüsste er schon, dass damit eben gemeint ist, low-Byte von "DMX_Buffer" nach YL und High-Byte nach YH...)


    um nun Y mit der Nummer der letzten Schublade zu vergleichen, muss man auch Low- und High-Byte getrennt vergleichen - so wie das in der DMX-Empfangsroutine ja auch gemacht wird (hier halt mit dem Z-Pointer, Prinzip ist das selbe):


    Code
    cpi	ZL, low(DMX_Data+DMX_Channels)
    brne 	dmx_finish
    cpi	ZH, high(DMX_Data+DMX_Channels)
    brne 	dmx_finish


    bau' das doch mal ein, überlege Dir dabei, wann was passiert, und wo er bei welchem Vergleichsergebnis hin springt, dann bekommst Du die Schleife schon zusammen... ;)

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Hi,


    So! Haben ja noch kein Mitternacht, also kann ich jetzt mal meine Hausaufgabe posten ;)


    Danke nochmal für die ganzen Tipps und Tricks, wobei ja das, was du alles da schreibst schon viel mehr sind als nur einfache Tipps u. Tricks u.s.w.
    Ich muss zugeben: ich lerne jedes mal viel mehr über die Sprache und vor allem was die leds vom uc brauchen und was der uc den leds geben muss damit sie Leuchten ;)

    wundert mich, dass sich das assemblieren lassen hat, wenn DMX_Channels größer als 255 ist, muss ldi temp4, DMX_Channels nen Fehler ergeben, weil temp4 ja nur Zahlen von 0 bis 255 enthalten kann (8 Bit)...

    Ja, sorry habe es vorher nicht erwaehnt, aber ich habe erstmal 24 DMX kanaele eingestellt, weil ich die Patch Tabelle ja noch nicht auf 512 erweitert habe. Werde ich natürlich demnaechst auch machen. Im moment laeufts halt noch mit 24. Lieber klein Anfangen wie Du auch schon vor kurzem über Sachen zerkleinern u.s.w. geschrieben hast. Dieser Vorschlag von Dir passt jetzt natürlich nicht so richtig rein :P Vielleicht ist es sogar besser wenn mann sofort 512 einstellt und erst die Patch Tabelle macht, statt da dann spaeter temp4 wieder zu aendern oder erstmal stundenlang suchen wo es nun hakt ;) Siehst du, ich lern wirklich was von dir :)) Ich möchte damit eigentlich nur sagen, dass Logik hier und da eine sehr grosse Rolle spielt. Die Logik, um vom Baecker 2 stck. semmel zu besorgen, klappt schon von alleine im Alltag. Für die Mikrokontroller Geschichte aber, braucht man halt einfach vieeel mehr Logik. Genau das glaube ich, ist der grösster Fehler was viele machen, die vor haben eigene codes zu Basteln. Die jetzt mal auch vielleicht was kleines Programmieren wollen und noch nicht mit der ganzen Logik umgehen können, weil halt entweder keine Erfahrung oder Lehre, oder einfach zu dumm dafür ;). Ohne Plan einfach alles reinschreiben und dann wieder alles schön löschen ;)


    Na ja, nun zum code. Ich werde jetzt dazu nicht viel schreiben da ja eh die comments existieren, kann manschön vom code lesen was ich da alles gemacht habe. Bin jetzt nur noch gespannt ob ich nach so vielen infos von dir immer noch fehler habe oder nicht. Aber von der ordnung im code her finde ich mich als ein gehorsamer Schüler gegenüber seinen Lehrer. (wenigestens dass ;))



    EDIT: Hab nur mein Text da oben bissl korrigiert weil viele Schreibfehler u.s.w. Bzw immer noch;)

  • Ganz kurz noch:


    Eine Stelle wo ich mir immer noch nicht so sicher bin:


    Obwohl du eigentlich den platz von der

    Code
    ;Start Kopf der Schleife


    angegeben hast, habe ich die "Bit_Loop", über die beiden Pointer:

    Code
    ldi YL, low(DMX_Buffer) ; Y auf DMX-Buffer
    ldi YH, high(DMX_Buffer)
    
    
    ldi ZL, low(Arr_TLC_Out) ; Z auf Ausgabepuffer
    ldi ZH, high(Arr_TLC_Out)


    reingeschrieben, weil ich gedacht habe, warum soll der Pointer jetzt zweimal in die schublade nachschauen. Guckt er doch oben schon rein ;)


    EDIT:
    Deshalb habe ich in der Schleife nicht schon wieder den Code hier Wiederholt...

    Code
    ldi YL, low(DMX_Buffer) 	; Y auf DMX-Buffer
    ldi YH, high(DMX_Buffer)
  • passt fast... ;)


    nur, das Label "Bit_Loop:" muss nach diesen 4 Zeilen mit "ldi" hin - so wie jetzt, setzt Du den Zeiger ja immer wieder auf Anfang, d.h. Du schaust ständig immer wieder in der ersten Schublade nach, da kannst Du ja nie fertig werden...


    Und die Pop-Befehle müssen in der umgekehrten Reihenfolge kommen wie die Push-Befehle - warum, dazu mal bei Wikipedia o.ä. gucken, was ein "Stack"/"Stapel" in einem µC/Prozessor eigentlich ist.... ;)


    EDIT: Ach, sorry, der Vergleich mit high und low ist auch falsch - das kannst Du Dir so vorstellen, wie zwei Stellen einer Zahl - also z.B. Du vergleichst "xy" mit "27" - gleich ist es dann, wenn x = 2 *und* y = 7


    im Moment beendest Du ja die Schleife, wenn auch nur *eine* Bedingung erfüllt ist - also, in diesem Beispiel, Du zählst xy hoch, und vergleichst die letzte Stelle ("y") zuerst - wenn Du also 7 erreicht hast, ist die Bedingung y = 7 erfüllt, und die Schleife also schon bei 7 beendet, obwohl sie erst bei 27 aufhören sollte...


    also musst Du das "andersrum" machen - so lange x *nicht* 2 ist *und/oder* y *nicht* 7, geht es weiter mit der Schleife... brauchst also den Befehl "brne", und wie das genau geht, kannst Du jetzt mal als Denksportaufgabe machen.... ;)


    in obigem Beispiel so, wenn x nicht 2 ist, und/oder y nicht 7, dann kann ja xy nicht 27 sein... d.h. an einer Stelle (egal ob low oder high), wenn das Byte nicht gleich ist, kann auch die ganze 16-Bit-Zahl nicht gleich sein...

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

    2 Mal editiert, zuletzt von Pesi ()

  • Ok.


    reicht es dann also wenn ich einfach sowas machen würde?

    Code
    Bit_Loop:
    
    
    		cpi	YL, low(DMX_Buffer+DMX_Channels)	; Low Wert vergleichen, ob dies den Wert vom angegebenen DMX_Channels erreicht hat. 
    		brne   Bit_Ende 									; 
    		cpi	YH, high(DMX_Buffer+DMX_Channels)	; High Wert vergleichen.
    		brne   Bit_Ende


    oder müsste ich sowas in der Art machen?

    Code
    Bit_Loop:
    
    
    		cpi	YL, low(DMX_Buffer+DMX_Channels)	; Low Wert vergleichen, ob dies den Wert vom angegebenen DMX_Channels erreicht hat. 
    		brne 	Bit_Loop									; 
    		cpi	YH, high(DMX_Buffer+DMX_Channels)	; High Wert vergleichen.
    		brne 	Bit_Loop	
    		rjmp Bit_Ende


    ?(