Angepinnt DIY-RGB-Controller mit IR-Fernbedienung und DMX - modular erweiterbar

    das ist in dem Sinn Geschmackssache ;)

    die Warte-Routine wird nur da verwendet, wo die LEDs beim Speichern blinken, und die Status-LED im "Sleep"-Modus immer wieder kurz aufblitzt, das war mir wohl zu langsam, habe das also da geändert...

    ich weiß, das ist unsauber programmiert, dass die Routine immer noch "wait_200ms" heisst, obwohl sie nun kürzer läuft, aber da war ich einfach zu faul, das überall umzubenennen... :P - das ist auch nirgends verwendet, wo es zeitkritisch ist, nur für dieses Blinken/Blitzen...

    Empirelord schrieb:

    Es gibt aber natürlich einen einfachen Workaround: Ein Register zum Zählen abstellen und nur jeden 2^8=256 Takt die Routine wirklich durchlaufen.

    ja, im Prinzip so - einfach in der bereits vorhandenen Timer0-ISR ein Byte runterzählen und dann ein Flag setzen für das durchlaufen der Taster-Routine, Byte neu laden mit nem Wert, so dass die Geschwindigkeit für Dich 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!
    so, hab nochmal einen controller mit 2313 gebaut...der sohnemann will auch einen "infinity" haben.
    was mir dabei einfiel, wenn noch platz im attiny ist...
    wäre es möglich eine von der umgebungshelligkeit abhängige dimmung z.b. auf programmplatz 7 zu legen?
    könnte man die helligkeitswerte direkt über den infrarotempfänger ermitteln, oder bräuchte man einen extra sensor?
    hintergrund ist der, wenn es am tage hell ist sollte auch die helligkeit der led´s erhöht sein.
    abends hingegen wenn es dunkelt, sollte es dunkler sein...weil dann krachen die led´s in voller helligkeit ganz schön rein.
    jaaaaaaaaa, ich weiss man kann das ja alles von hand regeln - aber für manche sachen wäre "vollautomatik" ne feine sache.

    nur mal als idee.
    das kann bislang kein chinacontroller :)

    vlg
    hermann
    Der IR-Empfänger ist dazu da, die digital codierten FB-Kommandos zu empfangen und zu decodieren, ein Einlesen analoger Helligkeitswerte ist daher unmöglich.
    Auch besitzt der ATTiny 2313 / 4313 keinen A/D-Wandler, so dass es schwierig bis unmöglich wird, die von Dir gewünschte Helligkeitsregelung mit geringem Aufwand zu implementieren.
    Am Speicherplatz liegt's nicht, denn es gibt ja schließlich den 4313 mit 4k Programmspeicher.

    BTW, ab und zu mal die Shifttaste benutzen, schon wird Dein Text besser lesbar ... :thumbup:
    Hallo (nochmal), :)

    ich bin gerade dabei die Software um einen unabhängigen PWM-Kanal zu erweitern. Dieser soll über eine eigene Helligkeit verfügen, also unabhängig vom Master-Dimmer sein.

    Was habe ich bisher gemacht:

    Settings.inc:
    Tasten für Helligkeit rauf & runter hinzugefügt

    Key_Command:
    Die gleiche Abfrage wie für den Master-Dimmer kopiert und umbenannt, damit das ganze für den zweiten Dimmer auch klappt. Das _Dimmer_out Label auch kopiert und umbenannt.

    Definitions.inc:
    Einen Port und Pin definiert für den PWM Ausgang definiert. (Die RGB Leds hängen an PortD und der neue PWM Port liegt auf PortB, nur zur Info).
    Am Ende (unter Lightning_Speed) folgendes eingefügt:

    Quellcode

    1. Dimmer_indirekt: .byte 1 ; Dimmer indirkete Beleuchtung



    So jetzt zu meinen Problemen:

    Wie muss ich die Data.inc abändern? Reicht es aus für die Daten im EEPROM einfach den Wert für den neuen Dimmer unten in der Tabelle einzufügen, in etwa so?

    Quellcode

    1. .db 31, 0 ; Dimmer-indirket ; Dummy


    Ich komme momentan auch nicht so wirklich dahinter, wie die Dimmerkorrektur funktioniert bzw. wie ich meinen "neuen" Dimmer da rein bekomme. Die Dimmerkorrektur ist ja eigentlich so gemacht, dass eben die Werte in der Tabelle gesetzt werden, wenn man die Helligkeit und "1" erhöht und die Helligkeit nicht immer nur +1 gerechnet wird.

    Ich habe bisher noch nicht entdeckt wie bzw. wo die Helligkeit verrechnet wird und wie ich dann das ganze in der SW_PWM.inc einarbeiten muss.


    Also insgesamt bin ich da noch nicht wirklich weit gekommen, aber evtl. kann mir hier ja jemand helfen!
    Danke euch.
    Ja, genau, wenn weitere Parameter dazu kommen (also auch für andere Programme etc., dann sowohl bei den Definitions wie bei Data.inc eintragen - das wird einfach hin- und her kopiert, muss also die selbe Anzahl Bytes an den selben Positionen sein.

    Die Dimmerkorrektur ist eine Funktion, die schaut einfach in ner Tabelle nach, Du übergibst einen Wert von 0-31 (in temp1), rufst die Funktion auf, und dann kommt der tatsächliche Wert raus (wieder in temp1).

    Da wird aber noch nix gedimmt, das macht die Funktion _Dimmer, die verrechnet den Eingangs-Wert (die von den Programmen erzeugten Farben) mit der Dimm-Stufe.

    Wenn ich das richtig sehe, willst Du nur einen weiteren Kanal, den Du völlig unabhängig von den anderen Programmen rauf- und runter dimmen kannst...?

    da brauchst Du die eigentliche Dimmer-Funktion (das verrechnen der Werte) dann gar nicht, einfach so:

    - in der Key_Command den Wert aus Dimmer_indirekt holen (gleich in temp1), je nach Tastendruck rauf oder runter (Bereich von 0-31 eingrenzen), dann wieder zurück speichern in Dimmer_indirekt (damit der Wert auch bleibt)
    - aktueller Wert ist dann eh' schon in temp1, also rufst Du die Dimmerkorrektur auf, die macht Dir aus dem Wert 0-31 einen Wert 0-255 (wieder in temp1)
    - diesen speicherst Du in den PWM-Buffer, an die Position PWM_Buffer+3 (die 3 Byte davor sind ja für den RGB-Ausgang)
    - in der SW_PWM.inc fügst Du noch einen Block ein für den 4. Kanal - einfacher wäre es, wenn der auch an PortD hängt, wenn er unbedingt an B sein muss, dann schau' Dir mal an, wie das gemacht ist, genauso für Port B machen

    nicht vergessen:

    - Du musst den Pin in der Configuration.inc auch auf Ausgang schalten, diese Angaben in Definitons.inc sind nur "Merkhilfen" (also dass man dann z.B. "PWM_Port" schreiben kann statt "PortD" etc.), da wird nichts irgendwie tatsächlich gemacht
    - im PWM-Buffer ein weiteres Byte reservieren, also dann

    Quellcode

    1. PWM_Buffer: .byte 4 ; RAM-Puffer für PWM-Ausgabedaten
    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!
    Hallo Pesi,

    danke für deine schnelle Antwort.
    Habe mich heute Abend mal dran gesetzt. Muss vllt. noch dazu sagen, dass ich mich zur Zeit noch in Assembler einarbeite, komme eher aus dem C Lager, aber bei mir hat dein Plan (vorerst) gefruchtet, mich mal mit Assembler zu befassen. ;)

    Mit der Configuration.inc war mir klar. Habe auf dem Controller z.B. noch andere Ausgänge die Halogen-Spots (ja Schande über mich) ein- und ausschalten per FB. Der zusätzliche PWM-Kanal soll nun eine Warmweiße indirkete Beleuchtung steuern.

    In der Data.inc habe ich noch eine weitere Variable gesetzt, wieso kommt gleich:

    Quellcode

    1. .db 30, 0 ; Dimmer-indirket ; Dimmer-indirket_korr


    Das ganze wird dann erstmalig in der Configuration.inc korrigiert:

    Brainfuck-Quellcode

    1. ; ================================================================================================
    2. ; Konfiguration aus EEPROM holen & indirekten Dimmer erstmalig korrigieren
    3. ; ------------------------------------------------------------------------------------------------
    4. rcall _Load_Config
    5. lds temp1, Dimmer_indirekt ; Dimmer_indirekt holen
    6. rcall _Dimmerkorrektur ; und von 0-31 auf 0-255 mit Kurve umrechnen
    7. sts Dimmer_indirekt_korr, temp1 ; und speichern


    Das erschein mir notwendig, da ich die Dimmerkorrektur nur aufrufe wenn auch eine entsprechende Taste, für heller oder dunkler, gedrückt wurde.

    Brainfuck-Quellcode

    1. _key_select_15:
    2. lds temp1, Dimmer_indirekt ; Dimmer_indirekt holen
    3. ; ------------------------------------------------------------------------------------------------
    4. cpi temp2, BRI_UP_indirekt ; Taste heller_indirekt gedrückt?
    5. brne _key_select_16 ; nein, nächste Abfrage
    6. cpi temp1, BRI_MAX ; Maximalwert schon erreicht...?
    7. brlo _set_bright_up_ind ; nein, erhöhen
    8. rjmp _key_command_ende ; ja, nicht ändern
    9. _set_bright_up_ind:
    10. inc temp1 ; Helligkeit erhöhen
    11. rjmp _dimmer_out_ind ; und Speichern
    12. ; ------------------------------------------------------------------------------------------------
    13. _key_select_16:
    14. cpi temp2, BRI_DOWN_indirekt ; Taste dunkler_indirekt gedrückt?
    15. brne _key_select_end ; nein, nächste Abfrage
    16. tst temp1 ; Minimalwert schon erreicht...?
    17. rjmp _key_command_ende ; ja, nicht ändern
    18. _set_bright_down_ind:
    19. dec temp1 ; Helligkeit verringern
    20. rjmp _dimmer_out_ind ; und Speichern

    Quellcode

    1. _dimmer_out_ind:
    2. sts Dimmer_indirekt,temp1 ; indirekten Dimmer speichern
    3. rcall _Dimmerkorrektur ; und von 0-31 auf 0-255 mit Kurve umrechnen
    4. sts Dimmer_indirekt_korr,temp1 ; korriegierten Wert speichern
    5. rjmp _key_command_ende ; und Ende


    In der Hauptdatei habe ich im Label "RGB_Output" nichts geändert, sondern das Label "RGB_Copy_Loop" geändert.

    Quellcode

    1. _rgb_copy_loop:
    2. ld temp0, Y+ ; Wert aus Puffer holen
    3. rcall _Dimmer ; dimmen
    4. st Z+, temp0 ; und speichern
    5. dec temp2
    6. brne _rgb_copy_loop
    7. lds temp1, Dimmer_indirekt_korr ; Dimmer_indirket-Wert holen
    8. st Z+, temp1 ; Speichern
    9. rjmp _main ; Hauptschleife von vorne


    Um es dann doch für den Anfang etwas einfacherer zu gestalten, habe ich RGB und den neuen PWM Kanal auf einen Port gelegt, d.hh. in der SW_PWM.inc einfach copy&paste einen Kanal hinzu gefügt und angepasst.

    Momentan kann ich allerdings noch nicht die Helligkeit ändern. Schalte ich den Strom an ist der PWM Kanal auf voller Helligkeit. Dimmen klappt leider nicht.

    Werde mich morgen mal erneut dran setzen und wollte einen kleinen Zwischenstand hier lassen. Vielleicht fällt dir ja irgendwas auf die Schnelle auf.
    Hallo zusammen,

    hab es nun zum laufen gebracht. Anscheinend gab es ein Problem mit folgender Zeile:

    Quellcode

    1. tst temp1 ; Minimalwert schon erreicht...?


    Das dimmen müsste funktioniert haben, da allerdings als Startwert bereits der Maximalwert eingestellt war und ich nicht runter dimmen konnte, hatte ich den Eindruck es würde nicht funktionieren. Mit geändertem Startwert klappte dann das hoch- nicht aber das runterdimmen.
    Also wurde obenstehendes durch folgendes ersetzt:

    Quellcode

    1. cpi temp1, 1 ; Minimalwert schon erreicht...?
    2. brsh _set_bright_down_ind ; nein, verringern


    Dauert jetzt zwar einen halben Takt länger aber das sollte zu verkraften sein.

    Des Weiteren habe ich die SW_PWM.inc nochmal überarbeitet, so dass jetzt die RGB Leds und der weitere PWM Kanal auf verschiedenen Ports laufen können.

    Nochmal vielen Dank an Pesi für den tollen Controller.

    Grüße
    Hallo,
    mittlerweile bin ich auf ein Problem beim Anschluss von DMX gestoßen.
    Und zwar, so funktioniert alles, stecke ich erst den Strom ein, später das dmx Kabel, ist alles gut. Liegt aber ein dmx Signal an, und ich schalte erst dann den Strom ein funktioniert nichts mehr richtig, alles blinkt, oder macht sonstigen Unsinn. Wieder alles aus gemacht, dmx raus, Strom dran, dann funktionierte die Lampe so, aber beim Anschluss von dmx reagierte nichts, teilweise waren dann auch nur die roten an, ohne Reaktion auf Änderungen vom dmx. Daraufhin flashe ich den Tiny neu und alles geht wieder.
    Hat jemand eine Idee wo das Problem ist, in anderen Schaltungen sind vor dem dmx Eingang 10 Ohm wiederstände, das einfügen hiervon hat das Problem nicht behoben.
    Gruß Andreas
    Huch, schon lange nicht mehr hier rein geschaut...

    Flixus: Könntest Du Deine SW-Version mit dem extra Kanal auch noch hier rein stellen..? - das wäre super! :thumbup:

    Andreas: Hm, das ist komisch! - kann ich mir jetzt auf die Schnelle nicht vorstellen, woran das liegen könnte...

    zur Eingrenzung: spinnt das Teil denn dann komplett, also gehen auch die Standalone-Programme nicht mehr, wenn Du erst DMX und dann den Strom dran machst, oder funktioniert nur der DMX-Empfang nicht richtig...?

    also kannst Du mal ein Standalone-Programm einstellen (und speichern, damit das beim nächsten Einschalten kommt), und dann noch mal so, erst DMX an, dann Strom...? - läuft das Programm dann einfach, oder spinnt er da auch rum..?

    welche SW-Version hast Du denn...? - in der ganz alten mit dem Display war noch ein Fehler in der DMX-Empfangsroutine, der ist glaubich immer noch nicht behoben :whistling: , da die dann weiter nicht mehr so interessant war (das Display ist ja unnötig, war nur zum testen dran...)
    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!
    Aufgrund mangelnder Zeit melde ich mich auch erst jetzt wieder.

    Software benutze ich die vom 12.11.2012, ohne Display.
    Ist Dmx eingesteckt funktionieren auch die stand Alone Programme nicht, z.B. blinkt alles sehr schnell rot, man kann nichts umstellen oder ändern, dann Strom ausschalten, dmx aus, Strom wieder ein, anschließend dmx an und es funktioniert.
    Allerdings kommt es auch mal vor das die Software dabei einen Schaden bekommt, wenn dmx eingeschaltet war, sodas die festen Farben endlos durchzuschalten sind und es auch ganz andere, viel mehr Farben sind.
    Nach dem ausschalten warte ich ebenfalls immer eine gewisse zeit, zu schnelles wiedereinschalten ist nicht gut.
    Ich habe das Gefühl es liegt an dem anliegenden dmx Signal beim einschalten, wenn man aufpasst und immer erst den Strom einsteckt gab es noch keine probleme, ist aber komisch.
    Gruß
    Sorry, jetzt hat's bei mir auch etwas länger gedauert...

    leider kann ich das Problem hier nicht nachvollziehen, also ich meine damit nicht, dass ich Dir nicht glauben würde, sondern es tritt bei mir nicht auf...

    da kann ich schlecht was debuggen, wenn der Fehler bei mir nicht passiert, weil ich ja nicht sehe, woran es liegen könnte...

    das Einzige, was mir jetzt noch einfällt: wie sieht es denn bei Dir mit den Fusebits aus...? - ich habe die immer so eingestellt, dass der µC maximal lange wartet (Startup-Time 16K CK + 65 ms) bis er tatsächlich losläuft.

    Könnte mir schon vorstellen, wenn die Startup-Time kürzer eingestellt ist, und der µC dann schon mit "wackeligem" Takt losläuft und dann noch zusätzlich Signale anliegen (das DMX eben), dass er dann durcheinander kommt und rumspinnt...

    sonst würde mir jetzt nix mehr einfallen, in der SW habe ich jedenfalls nix gefunden, was dieses Verhalten erklären könnte...

    wenn zufällig jemand mitliest, der das Teil ebenfalls mit DMX betreibt: Ist das bei anderen auch so, also hat sonst noch jemand dieses Problem mit seltsamen Verhalten, wenn erst DMX und dann Strom angelegt wird...?
    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!
    Hallo Pesi

    Ich habe die gleichen Bugs was ich auch schonmal im anderen Thread geschrieben habe.

    Vielleicht etwas anders beschrieben...

    Ich habe auch das Problem, das die Schaltungen das ein und ausgeschalte von Dau's an der Sicherung nicht mögen, mit wirklich seltsamen Erscheinungen. 8|
    Ausserdem habe ich 2 Platinen hier, die den Fehler des Flackerns dauerhaft haben, die ich Dir gerne zusende.

    Was sich zumal auch zeigt ist die Tatsache, das der Controller bei mir nicht damit klar kommt wenn man schon DMX am laufen hat, bevor die Platine mit Strom versorgt wurde. ||
    Das habe ich mit mehreren DMX-sendern getestet. Monacor DMX-510, DMX-PlayerM von DMX4all, und 2 DMX-Pulte. Ich würde Dir auch ne funktionierende Platine zur Verfügung stellen, wenns hilft, damit Du das Ganze direkt nachvollziehen kannst. :rolleyes:

    Flo

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „bfbs“ ()

    Hallo zusammen,

    ich plane (als µC-Anfänger!), den Controller mit einem ATtiny4313 umzusetzen.
    Es gab ja mal die Idee, die Software um die NEC Funktionalität zu erweitern. Gibt's dazu schon was neues?
    Wenn man sich evtl an der IRMP etwas anlehnt??

    Hätte den netten Vorteil, dass die gängigen China-Remotes verwendet werden könnten :)

    Viele Grüße!!
    Hm, das ist C, damit kenne ich mich nicht aus, auch k.A., wie ich das mit meinem asm-Programm zusammen bringe...

    aber kannst Du gerne probieren, Quelltext ist ja drin, letztlich nur die RC5-Routine durch eine ersetzen, die NEC empfängt...

    Ich hab' da leider keine Zeit dazu, seit ich wieder fest angestellter Held der Arbeiterklasse bin, komm ich zu gar nix mehr...
    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 Antwort.
    Ja ich lese mich mal etwas ein.

    in aber noch nicht so optimistisch, da ich werder asm noch C programmieren kann.
    Das Programm auf andere RC5 Befehle anpassen bzw evtl die festeingestellten Farbe zu erweitern, bekomm ich hin, denk ich; komplette routinen austauschen muss ich mir mal anschauen!..

    NEC Protokoll in ASM

    Hallo zusammen,

    Pesi, ich hab jetzt mal ein bisschen mit ASM rumgespielt und deinen Controller um einige Programme erweitert. Ich habe das Display reingepackt, und das Programm soweit angegepasst, dass es für den NEC Empfang (insb die China Remotes) vorbereitet ist.

    Bevor ich die Version aber mit euch teilen kann, fehlt noch das i-Tüpfelchen....
    Jetzt bin ich gerade in den letzten Zügen, das NEC Protokoll zu integrieren. Leider sind Vorlagen dafür in AMS sehr sehr rar. Bin dann in einem russichen Forum fündig geworden und habe den Code, soweit angepasst, dass er in den Controller reinpasst.
    Die Grundfunktionalität der NEC Routine läuft über den Timer1 und INT0 (der IR Empfänger ist für den Zweck zumindest Testweise an PD2), der die NEC Intervalle anhand steigender und fallender Flanken erkennt und gegenüber Timer1 vergleicht.
    Hier ist allerdings auch schon der Hund begraben. Diese Timerfunktionalität scheint nicht so ganz funtionieren wie sie soll, so dass kein korrektes NEC format ankommt... Ich komme mit meinen Anfänger ASM Kenntnissen aber einfach nicht weiter...
    Daher die Frage an euch, ob jemand auf die schnelle einen groben Schnitzer sieht und woran es hängen könnte??

    Hier die relevanten Code Teile...

    In der "Haupt"-asm.Datei wird INT0 und Timer1 konfiguriert.

    Quellcode

    1. _reset:
    2. .include "Configuration.inc" ; Ports setzen, Timer konfigurieren etc.
    3. ; ***** FÜR NEC ****
    4. ldi tmp,low(ramend) ;
    5. out spl,tmp ;
    6. cli
    7. clr zero ; Hilfsregister für NEC Empfang auf 0 setzen
    8. ; NEC Routine
    9. ; auslagern??? :
    10. ;************************;
    11. ;**** INIT T1 & INT0 ****;
    12. ; INT0 falling mode ;
    13. ldi tmp,(1<<ISC01)|(0<<ISC00) ; (1<<ISC01)|(0<<ISC00)
    14. out MCUCR,tmp ;
    15. ldi tmp,(1<<INT0) ;
    16. out GIMSK,tmp ;
    17. ; TIMER_1 ;
    18. ; ; 0-STOP, 1-/1, 2-/8, 3-/64, 4-/256, 5-/1024. OVF mode
    19. ldi tmp,(1<<CS11) ; ICNC1, ICES1, –, WGM13, WGM12, CS12, CS11, CS10.
    20. out TCCR1B,tmp ;
    21. clr tmp ; clear TIMER1 registers
    22. out TCCR1A,tmp ;
    23. out TCNT1H,tmp ;
    24. out TCNT1L,tmp ;
    25. out OCR1AH,tmp ;
    26. out OCR1AL,tmp ;
    27. out OCR1BH,tmp ;
    28. out OCR1BL,tmp ;
    29. out ICR1H,tmp ;
    30. out ICR1L,tmp ;
    31. out TIFR,tmp ;
    32. in tmp,TIMSK ; OCIE2, TOIE2, TICIE1, OCIE1A, OCIE1B, TOIE1, –, TOIE0.
    33. ori tmp,(1<<TOIE1) ;
    34. out TIMSK,tmp ; ;out TIMSK1,tmp
    35. sei ; Interrupts aktivieren
    36. ; **** NEC ENDE *****


    Die Interrupts sind wie folgt definiert:

    Quellcode

    1. .org 0x0000 rjmp _reset ; RESET
    2. ;.org 0x0001 reti ; External Interrupt Request 0
    3. .org 0x0001 rjmp IR_read ; für NEC ; External Interrupt Request 0
    4. .org 0x0002 reti ; External Interrupt Request 1
    5. .org 0x0003 reti ; Timer/Counter1 Capture Event
    6. .org 0x0004 reti ; Timer/Counter1 Compare Match A
    7. ;.org 0x0005 reti ; Timer/Counter1 Overflow
    8. .org 0x0005 rjmp T1_ovf ; für NEC ; Timer/Counter1 Overflow
    9. .org 0x0006 rjmp _ISR_Timer0OVF ; Timer/Counter0 Overflow
    10. .org 0x0007 rjmp _DMX_Receiver ; Rx Complete
    11. .org 0x0008 reti ; Data Register Empty
    12. .org 0x0009 reti ; Tx Complete
    13. .org 0x000A reti ; Analog Comparator
    14. .org 0x000B reti ; Pin Change Interrupt
    15. .org 0x000C reti ; Timer/Counter1 Compare Match B
    16. .org 0x000D reti ; Timer/Counter0 Compare Match A
    17. .org 0x000E reti ; Timer/Counter0 Compare Match B
    18. .org 0x000F reti ; USI Start Condition
    19. .org 0x0010 reti ; USI Overflow
    20. .org 0x0011 reti ; EEPROM Ready
    21. .org 0x0012 reti ; Watchdog Timer Overflow
    22. .org 0x0013 reti ; PCINT1 Pin Change Interrupt Request 1
    23. .org 0x0014 reti ; PCINT2 Pin Change Interrupt Request 2
    und hier dann der Teil des NEC receivers (nicht wundern, die Kommentare
    sind per google translate aus dem kyrillischen übersetzt....)
    Spoiler anzeigen

    Quellcode

    1. ; http://monitor.net.ru/forum/nec-ir-decoder-attiny2313-lcd1110i-info-537446.html;
    2. ; grob übersetzt aus russisch
    3. ; Module für den Einsatz mit NEC IR -Fernbedienungen
    4. ; Das Ergebnis der Beendigung des Empfangs in
    5. ; vier Register Adresse L, H -Adresse , Daten Non-Inverted, Daten Inverted !
    6. ; Während die Taste , werden die Daten in den Registern gespeichert !
    7. ; wird über Interrupt ausgelöst, daher Anschluss von IR Pin an PD2!!!
    8. ; NEC DATA registers
    9. .def bytei = R11 ; Inverted command byte
    10. .def byten = R12 ; Normal command byte
    11. .def adrh = R13 ; High Address
    12. .def adrl = R14 ; Low Address
    13. .def zero = R15 ; always = 0 !
    14. .def tmp = R23 ; RON
    15. .def flags_nec = R21 ; flags register
    16. .def cnt = R22 ;
    17. ; all constants are true ms values !
    18. .equ FCLK = XTAL ; global definierte Taktfrequenz, 16000000
    19. .equ pre = 8 ; Preskaler Timer 1
    20. .equ const = (FCLK / 10000) / pre ; 125 (1,25 real) 1 Timer-Tick 1,25 ms
    21. .equ starth = (9000 * const) / 100 ; Die erste Prämisse 9,0ms
    22. .equ startl = (4500 * const) / 100 ; zweite Prämisse 4,5ms
    23. .equ log1 = (2250 * const) / 100 ; Empfang einer logischen 1 (2,250ms)
    24. .equ restart = log1 ; Senden 4,5ms + 2.250ms = Wiederholungs
    25. .equ log0 = (1125 * const) / 100 ; Empfangen einer logischen 0 (1,125ms)
    26. .equ IRcL = (100 * const) / 100 ; Constant Fehler 100uS
    27. .equ IRcH = (500 * const) / 100 ; Constant Fehler 200uS
    28. .equ repeat = 65535 - ((110000 * const / / 100); Nach über 110 ms sendet die empfangenen Daten neu zu starten
    29. ;***********************************************************************************
    30. IR_read: ; Register cnt,tmp,X,Z !
    31. push tmp ; save tmp in STACK
    32. in tmp,SREG ; Lesen Inhalt SREG in tmp
    33. push tmp ; save tmp at STACK
    34. push xl ; save XL at STACK
    35. push xh ; save XH at STACK
    36. push zl ; save ZL at STACK
    37. push zh ; save ZH at STACK
    38. cli ; disable interrupts
    39. inc cnt ; INT0 counter + 1
    40. cpi cnt,1 ; IF cnt = 1 -> goto IR_9ms
    41. breq IR_9ms ; Reset T1, start counting , interrupt edge , catch 9ms !
    42. cpi cnt,2 ; IF cnt = 2 -> goto IR_start
    43. breq IR_start ; We accept Start 9 ms (+ - 200us) !
    44. cpi cnt,3 ; IF cnt = 3 -> goto IR_repeat_OR_normal start !
    45. breq IR_repeat ; Check the replay team! Or send the transmission data !
    46. cpi cnt,4 ; IF cnt >= 4 -> goto IR_data
    47. brsh GET_data ; that receives data
    48. rjmp IR_error ; if 0 - interrupt exit
    49. GET_data: ; escape transition
    50. rjmp GET_IR_data ; receiving data 32 bits ! LSB first
    51. IR_9ms: ;
    52. in tmp,MCUCR ; MCUCR ist internes Register
    53. ldi tmp,(1<<ISC01)|(1<<ISC00) ; INT0 - rising (0x03) (1<<ISC01)|(1<<ISC00)
    54. ;ori tmp,0x03 ;
    55. out MCUCR,tmp ;
    56. ldi flags_nec,0x01 ; Flags = 1
    57. rcall read_T1 ; Z = TCNT1
    58. rjmp IR_ok ; interrupt exit WAIT High level on INT0 !
    59. IR_start: ; 9.136 ms NORMAL ! INT0 - rising cnt=1 !
    60. in tmp,MCUCR ;
    61. ldi tmp,(1<<ISC01)|(0<<ISC00) ; INT0 - falling (1<<ISC01)|(0<<ISC00)
    62. ;andi tmp,0xFC ;
    63. ;ori tmp,0x02 ;
    64. out MCUCR,tmp ;
    65. rcall read_T1 ; Z = TCNT1
    66. ldi xl,byte1(starth-IRcH) ; load 9.000 ms - 200us
    67. ldi xh,byte2(starth-IRcH) ;
    68. cp zl,xl ; comparing TCNT1 with starth constant !
    69. cpc zh,xh ;
    70. brlo IR_error ; if it is less than 8.8 ms, then the error is not our protocol !
    71. ldi xl,byte1(starth+IRcH) ; load 9.000 ms + 200us
    72. ldi xh,byte2(starth+IRcH) ;
    73. cp zl,xl ; comparing TCNT1 with starth constant !
    74. cpc zh,xh ;
    75. brsh IR_error ; if more than 9.25 ms, the error is not our protocol !
    76. ldi flags_nec,0x02 ; Flags = 2
    77. rjmp IR_ok ;
    78. IR_repeat: ;
    79. rcall read_T1 ; Z = TCNT1
    80. ldi xl,byte1(restart-IRcL) ; 2.250 ms - 100us
    81. ldi xh,byte2(restart-IRcL) ;
    82. cp zl,xl ; comparing TCNT1 with starth constant !
    83. cpc zh,xh ;
    84. brlo IR_error ; if it is less than 8.8 ms, then the error is not our protocol !
    85. ldi xl,byte1(restart+IRcL) ; 2.250 ms + 100us
    86. ldi xh,byte2(restart+IRcL) ;
    87. cp zl,xl ; comparing TCNT1 with starth constant !
    88. cpc zh,xh ;
    89. brsh IR_N_start ; If more than 2.375 ms then check the normal start
    90. ldi flags_nec,0x03 ; Flags = 3 (REPEAT command)
    91. rcall write_T1 ; T1 = f.osc / 64
    92. rjmp IR_check ;
    93. IR_N_start: ; NEC normal start 9 ms + 4.5 ms ! FLAGS = 3 !
    94. ldi xl,byte1(startl-IRcH) ; load 4.500 ms - 200us
    95. ldi xh,byte2(startl-IRcH) ;
    96. cp zl,xl ; comparing TCNT1 with starth constant !
    97. cpc zh,xh ;
    98. brlo IR_error ; if it is less than 4.3 ms, then the error is not our protocol !
    99. ldi xl,byte1(startl+IRcH) ; load 4.500 ms + 200us
    100. ldi xh,byte2(startl+IRcH) ;
    101. cp zl,xl ; comparing TCNT1 with starth constant !
    102. cpc zh,xh ;
    103. brsh IR_error ; if more than 4.7 ms, then the error is not our protocol !
    104. ldi flags_nec,0x04 ; Flags = 4
    105. IR_ok: ; Successful Reception
    106. cpi cnt,35 ; the maximum number of interrupts sending remote = 35 ! Then, repeat 2 interrupt
    107. brsh IR_check ; >= 35 - check the replay flag !
    108. ; IR ADDRESS CHECK !
    109. ldi zl,low (IR_adr*2) ; IR address pointer
    110. ldi zh,high(IR_adr*2) ;
    111. lpm xl,z+ ; X = NEC IR ADR
    112. lpm xh,z ; xl <-- ADRL, xh <-- ADRH
    113. cp adrl,xl ;
    114. cpc adrh,xh ;
    115. brne IR_adr_err ; If it does not match with the specified at the program , the team at writing 255
    116. Exit: ; marker label of interruption
    117. pop zh ; extract ZH from STACK
    118. pop zl ; extract ZL from STACK
    119. pop xh ; extract XH from STACK
    120. pop xl ; extract XL from STACK
    121. pop tmp ; extract tmp from STACK
    122. out SREG,tmp ; reestablish SREG
    123. pop tmp ; extract tmp from STACK
    124. ; TEST NEC:
    125. ; Zwischenspeichern für LCD:
    126. sts nec_adrl,adrl
    127. sts nec_adrh,adrh
    128. sts nec_flag_status,flags_nec
    129. rcall _Update_LCD ; Ausgabe auf LCD
    130. ; Test ende
    131. reti ; output from an external interrupt INT0
    132. IR_adr_err: ; Error received address from the remote IR
    133. ;ser tmp ;
    134. ldi tmp, 249 ; als debug
    135. sts nec,tmp ; keep the operation at 255
    136. rjmp Exit ; the output from the interrupt
    137. IR_error: ; Not our protocol , a reception error !
    138. clr cnt ; counter interrupt = 0
    139. ;ser tmp ;
    140. ldi tmp, 111 ; als debug
    141. mov bytei,tmp ; NEC IR Command_INV = FFH
    142. mov byten,tmp ; NEC IR Command_Nor = FFH
    143. mov adrh,tmp ; NEC IR Address High = FFH
    144. mov adrl,tmp ; NEC IR Address Low = FFH
    145. in tmp,MCUCR ;
    146. ldi tmp,(1<<ISC01)|(0<<ISC00) ; INT0 - falling (1<<ISC01)|(0<<ISC00)
    147. ;andi tmp,0xFC ;
    148. ;ori tmp,0x02 ;
    149. out MCUCR,tmp ;
    150. ldi flags_nec,0b01000000 ; ERROR - 0x40, 0d64
    151. out TCCR1B,zero ; STOP Timer1
    152. out TCNT1H,zero ;
    153. out TCNT1L,zero ; TCNT1=0
    154. in tmp,TIFR ; tmp = TIFR
    155. andi tmp,0xFD ; TOV1 --> 2 bit (FD)
    156. out TIFR,tmp ; reset the overflow flag T1
    157. rjmp Exit ; to the exit
    158. IR_check: ; Checking the status of the console and addresses !!!
    159. sts nec,byten ; retain command byte !
    160. clr cnt ; ITNT0 counter = 0
    161. cpi flags_nec,0x03 ; If the status = 0x03 then the received data
    162. breq IR_ok ; got to OK
    163. cpi flags_nec,0x05 ; If the status = 0x05 then the received data
    164. breq IR_ok ; go to OK!
    165. rjmp IR_error ; If checked , you will not erase the data
    166. GET_IR_data: ; GET data
    167. rcall read_T1 ; Z = TCNT1
    168. IR_data_0: ; Receiving bit 0 (1.125ms)
    169. ldi xl,byte1(log0-IRcL) ; load 1.125 ms - 100us
    170. ldi xh,byte2(log0-IRcL) ;
    171. cp zl,xl ; comparing TCNT1 with log0 constant !
    172. cpc zh,xh ;
    173. brlo IR_error ; if less than 1,025 is not our protocol error
    174. ldi xl,byte1(log0+IRcL) ; load 1.125 ms + 100us
    175. ldi xh,byte2(log0+IRcL) ;
    176. cp zl,xl ; comparing TCNT1 with log0 constant !
    177. cpc zh,xh ;
    178. brsh IR_data_1 ; if more than 1,225 take the log 1
    179. clc ;
    180. lsr bytei ; DATA 32 bits = >> 1 LSB first
    181. ror byten ;
    182. ror adrh ;
    183. ror adrl ;
    184. ldi flags_nec,5 ; received bit 0 Flags = 5
    185. rjmp IR_ok ; return
    186. IR_data_1: ; Reception bit 1 (2,25ms)
    187. ldi xl,byte1(log1-IRcL) ; load 2.25 ms - 100us
    188. ldi xh,byte2(log1-IRcL) ;
    189. cp zl,xl ; comparing TCNT1 with log0 constant !
    190. cpc zh,xh ;
    191. brlo IR_error ; if less than 2.15ms is not our protocol error
    192. ldi xl,byte1(log1+IRcL) ; load 2.25 ms + 100us
    193. ldi xh,byte2(log1+IRcL) ;
    194. cp zl,xl ; comparing TCNT1 with log0 constant !
    195. cpc zh,xh ;
    196. brsh IR_error ; if more than 2.35ms is not our protocol error
    197. ldi tmp,0b10000000 ; setting bit 7 at registers
    198. clc ;
    199. lsr bytei ; DATA 32 bits = >> 1 LSB first !
    200. ror byten ;
    201. ror adrh ;
    202. ror adrl ;
    203. or bytei,tmp ; DATA = | 1
    204. ldi flags_nec,5 ; received bit 1 Flags = 5
    205. rjmp IR_ok ; return
    206. read_T1: ; We read the data and set Timer1 counter preskaler 8 !
    207. in zl,TCNT1L ; Z = TCNT1
    208. in zh,TCNT1H ; Low counter must be read FIRST !
    209. out TCCR1B,zero ; STOP Timer1
    210. out TCNT1H,zero ;
    211. out TCNT1L,zero ; TCNT1=0
    212. in tmp,TIFR ; tmp = TIFR
    213. andi tmp,0xFD ; TOV1 --> 2 bit (FD)
    214. out TIFR,tmp ; reset the overflow flag T1
    215. ldi tmp,(1<<CS11) ; f.osc / 8
    216. out TCCR1B,tmp ;
    217. ret ; return
    218. write_T1: ; Timer1 overflow through 110ms!
    219. out TCCR1B,zero ; STOP Timer1
    220. ldi zl,low (repeat) ;
    221. ldi zh,high(repeat) ; Z = repeat ~(110ms)
    222. out TCNT1H,zh ;
    223. out TCNT1L,zl ; TCNT1=repeat
    224. in tmp,TIFR ; tmp = TIFR
    225. andi tmp,0xFD ; TOV1 --> 2 bit (FD)
    226. out TIFR,tmp ; reset the overflow flag T1
    227. ldi tmp,0x03 ; f.osc / 64
    228. out TCCR1B,tmp ;
    229. ret ; return
    230. ;************************;
    231. ; TIMER 1 Overflow ;
    232. T1_ovf:
    233. push tmp ; save tmp at STACK
    234. in tmp,SREG ; read the contents of the SREG at tmp
    235. push tmp ; save SREG at STACK
    236. cli ; turn off interrupts
    237. clr cnt ; CNT = 0
    238. clr flags_nec ; FLAGS = 0
    239. out TCCR1B,zero ; STOP Timer1
    240. out TCNT1H,zero ;
    241. out TCNT1L,zero ; TCNT1=0
    242. in tmp,TIFR ; tmp = TIFR
    243. andi tmp,0xFD ; TOV1 --> 2 bit (FD)
    244. out TIFR,tmp ; reset the overflow flag T1
    245. ser tmp ;
    246. sts nec,tmp ; RAM NEC IR Command_Nor = FFH
    247. mov bytei,tmp ; NEC IR Command_INV = FFH
    248. mov byten,tmp ; NEC IR Command_Nor = FFH
    249. mov adrh,tmp ; NEC IR Address High = FFH
    250. mov adrl,tmp ; NEC IR Address Low = FFH
    251. pop tmp ; extract tmp from STACK
    252. out SREG,tmp ; restore SREG
    253. pop tmp ; extract tmp from STACK
    254. reti ; output from the interrupt T1_ovf
    255. ; END of NEC IR_receiver code
    256. ; NEC IR Address L H ;
    257. IR_adr: .db 0x0A,0xF1 ; Remote Address first byte , second byte