Ledmatrix 32x64 RGB mit 12bit-Farben. Wie machen die das?

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Hm, der Brüller an Zeitersparnis wird das auch nicht. Bei mir färben sich (außer SREG): SREG, 0, 1, 10, 11, 16-24, 26, 27, 30 und 31 =18 Register.
      Laut Hilfe zu nosave, wenn ich das nosave weg lasse, dann
      SAVEThis is the default and is the same as when no parameter is provided. The most common used registers, SREG, and RAMPZ are saved and restored.
      Saved : SREG , R31 to R16 and R11 to R0 with exception of R6,R8 and R9.
      If RAMPZ exists, it will be saved as well.

      da zähle ich mit den Fingern 26 Register. 2x8 Takte gespart. Das nennt man wohl 'Kleinvieh'.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Ich denke, du glaubst, mit ein paar kleinen Änderungen kommst du auf deren Leistung. Das wird nichts werden. Da musst du dir schon mal genauer ansehen, was der Compiler so treibt und wie du es verbessern kannst.
      Incr Index_1
      sieht ja nett aus, benötigt bei Word Variablen aber 19 Takte.
      Index_1=Index_1 + 1
      nur 14. Mal eben 25% weniger.
      Oder das hier:

      BASCOM-Quellcode

      1. Incr Page_counter
      2. If Page_counter > 15 Then Page_counter = 0
      3. Index_1 = Page_counter * Bytes_in_row

      49 Takte und 11 Register, 10 alleine für die Multiplikation.
      Ginge auch so:

      BASCOM-Quellcode

      1. Incr Page_counter
      2. If Page_counter > 15 Then
      3. Page_counter = 0
      4. Index_1 = 0
      5. Else
      6. Index_1 = Index_1 + Bytes_in_row
      7. End If
      29 Takte und nur 4 Register. Macht mal eben 50% durch ein wenig nachdenken.
      Könnte ich endlos weitermachen.
      Und glaube mir, genau das haben die gemacht: An jeder Ecke optimiert.
      Und das innerhalb Bascom.
    • Hm, du kennst dich aus, im Gegensatz zu mir.
      Aber, wenn das incr zwar hübsch ausschaut, aber nur Zeit frisst, warum bietet man das an, zumal das var=var+1 vom schreiben nicht so unübersichtlich ist. Wenn das jetzt nur bei word so gravierend ist, dann könnte man das auch mal in der Hilfe erwähnen, statt es dem geneigten user zu überlassen, dass der das mal im Maschinencode oder Simulator überprüft.
      Bei der Multiplikation geb' ich dir Recht, hätte mir auch auffallen können/müssen. Um mich da ein bisschen rauszuwinden, im Hinterkopf habe ich noch im Sinn, dieses Durchzählen des page_counters nicht mit 1 zu machen, sondern mit 3, damit die Ausgabe nicht nacheinander die Zeilen im display ansteuert, sondern sprunghaft. So erhoffe ich mit eine Reduzierung der refreshrate. Ich hab's aber noch nicht probiert, ob man dadurch das Auge etwas überlisten kann.
      Des weiteren glaube ich nicht, dass ich mit meiner Bildspeicherorganisation groß die Leistung steigern kann. Da sind die Daten zu weit verteilt. Es war/ist halt für meinen Kleingeist übersichtlich zu bedienen.
      Danke auf jeden Fall mal, für deine Hinweise!
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Ach @tschoeatsch, meistens brauch‘ ich den ASM-Kram nicht. Nur wenn es eng wird im Speicher oder die Geschwindigkeit wirklich wichtig ist. Dann mach‘ ich es wie @Guenther, der Klasse recherchiert hat... Ist ein bissel sportliche Herausforderung.

      Wenn die ganze ISR in ASM läuft, dann nutzen die kleinen Einsparungen in Summe immer.

      Komme erst am Wochenende dazu mal eine Version zu schreiben...
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Guenther schrieb:

      Könnte ich endlos weitermachen.
      Ich bin beeindruckt.


      Bob, ich habe mal den ASM-Teil gestrafft, Du benutzt jetzt ja nur PortA.

      BASCOM-Quellcode

      1. Dout_port Alias Porta
      2. $asm
      3. LDI r17,8
      4. Loop_shift2out:
      5. in R16, dout_port
      6. BST r18,7
      7. BLD r16,Dout_pin_r1
      8. BST r19,7
      9. bld r16,Dout_pin_g1
      10. BST r20,7
      11. bld r16,Dout_pin_b1
      12. BST r21,7
      13. BLD r16,Dout_pin_r2
      14. BST r22,7
      15. bld r16,Dout_pin_g2
      16. BST r23,7
      17. bld r16,Dout_pin_b2
      18. lSl r18
      19. lSl r19
      20. lsl r20
      21. lsl r21
      22. lsl r22
      23. lsl r23
      24. Out Dout_port_b2 , R16
      25. SBI shift_clock_Port, shift_clock_Pin
      26. dec r17
      27. CBI shift_clock_Port, shift_clock_Pin
      28. BRnE loop_shift2out ; if = 0 exit
      29. $end Asm
      Alles anzeigen
    • tschoeatsch schrieb:

      Wenn das jetzt nur bei word so gravierend ist, dann könnte man das auch mal in der Hilfe erwähnen, statt es dem geneigten user zu überlassen, dass der das mal im Maschinencode oder Simulator überprüft.
      Dein Vergleich hinkt. Wenn es in der Hilfe steht, finden es viele auch nicht und es liegt auf der Hand, dass Word-Operationen mehr Ressourcen brauchen als Byte bei einem 8Bit Rechner.
      Bascom ist ein Basic-Dialekt.
      Zitat aus Wiki: BASIC“ steht für „Beginner’s All-purpose Symbolic Instruction Code“, was so viel bedeutet wie „symbolische Allzweck-Programmiersprache für Anfänger“
      Der Fokus liegt auf einfacher Bedienbarkeit, nicht auf Geschwindigkeit.
      Sollte man immer im Hinterkopf haben.
      Sei doch froh, dass du so gut Assembler einbinden kannst ;)
    • @Guenther dein Vorschlag, die Multiplikation so zu umgehen, passt so leider doch nicht. Für den index_1 brauche ich ja bei Beginn der isr bestimmte Startwerte. Dein Schnipsel baut auf vorhergende Werte von index_1 auf, die aber nicht brauchbar sind, weil ja index_1 während der isr verändert wird.
      @Michael das word mehr Aufwand braucht, ist mir schon klar, den braucht es ja auch bei var=var+1, aber da eben weniger als bei incr var.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • @Galahat nur mal so zu meinem Verständnis, brauche ich diese Zeile
      in R16, dout_port
      Reicht es nicht, die bits von R16 nacheinander mit bits von den anderen R18-R23 zu füllen und dann mit out an den port zu senden?

      Edit: ah, ist das zur Sicherung der noch freien bits im port, die man für anderes verwenden könnte?
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • @tschoeatsch,
      wenn du noch was rausholen willst, würde ich auf die ganze ISR verzichten.
      Das spart dir bei jedem Timerüberlauf mehr als 100 Takte.
      Wenn ich das richtig verstehe macht deine Main Loop doch eigentlich gar nichts, hauptsächlich waits.
      In der Main Loop würde ich nur TOV0 abfragen, dann die Display Routine (deine jetzige ISR) aufrufen und dann wieder auf das Bit warten.

      @Michael Das hat ja nichts mit BASIC oder Unterschied Word-Byte zu tun, wenn ein Incr länger dauert als v=v+1. Umgekehrt könnte ich das noch verstehen. Und bei den anderen Variablen Typen ist das ja auch nicht der Fall, nur bei Integer und Word. Da muss MCS irgendwas vermasselt haben.
    • Guenther schrieb:

      Wenn ich das richtig verstehe macht deine Main Loop doch eigentlich gar nichts, hauptsächlich waits.
      das stimmt schon, aber das ist ja auch nur ein Test. Die Anzeige soll universell werden, das heißt in der main soll alles mögliche drin sein können, ohne dass ich mich um den refresh kümmern muss.
      Den thread hier hab' ich ja nur angezettelt, weil mein Programm im Vergleich zu denen ihrem so jämmerlich ist. Ich dachte mir, da muss was zu optimieren sein, was ja nie schadet. Und da ist ja schon was zusammen gekommen.
      Ich kann ja immerhin mehrere displays koppeln, was die (noch) nicht können, die 4000 Farben brauche ich nicht, da ich ja nur Text darstellen will, oder 7-farbige Klotzgraphik.
      Immerhin brauche ich jetzt für die isr nur 0,1817ms im Vergleich zu den 0,2501ms aus dem Anfangsprogramm.
      Aber leider geht es noch nicht optimal.
      Bevor die pages umgeschaltet werden, muss die pwm=0 sein, damit keine Geisterpixel entstehen. Da pwm2=0 ja nur dann auch =0 wird, wenn der timer2 eben den pin bedient hat, war von mir das waitus 20 drin, damit der timer auch die Zeit hat. Das geht sehr gut. Will ich diese 20µs auch weg haben, dann muss ich die pwm vom pin abkoppeln und den entsprechend setzen, um das display auszuschalten (P_oe=1). Das Abkoppeln geht über die
      Bit 5:4 – COM21:0: Compare Match Output Mode
      These bits control the Output Compare pin (OC2) behavior. If one or both of the COM21:0 bits
      are set, the OC2 output overrides the normal port functionality of the I/O pin it is connected to.
      However, note that the Data Direction Register (DDR) bit corresponding to OC2 pin must be set
      in order to enable the output driver.
      Das klappt aber nicht, es flackern einzelne pixel auf, die im Bildspeicher gesetzt sind. Helligkeit=0 hat dadurch Störungen. Was hab' ich jetzt da wieder nicht beachtet?

      BASCOM-Quellcode

      1. 'Interrupt service
      2. Display_refresh: 'show the memory on the display
      3. Load Timer0 , Timer0reload
      4. Page_counter = Page_counter + 1
      5. If Page_counter > 15 Then Page_counter = 0
      6. Index_1 = Index_offset(page_counter)
      7. Index_2 = Index_1 + Channel_offset
      8. For D_2 = 1 To Dy_num_v
      9. For D_1 = 1 To Bytes_in_row
      10. R18 = Memory_red(index_1)
      11. R19 = Memory_green(index_1) : R20 = Memory_blue(index_1) : R21 = Memory_red(index_2) : R22 = Memory_green(index_2) : R23 = Memory_blue(index_2)
      12. 'MSB first
      13. $asm
      14. LDI r17,8
      15. Loop_shift2out:
      16. in R16, dout_port
      17. BST r18,7
      18. BLD r16,Dout_pin_r1
      19. BST r19,7
      20. bld r16,Dout_pin_g1
      21. BST r20,7
      22. bld r16,Dout_pin_b1
      23. BST r21,7
      24. BLD r16,Dout_pin_r2
      25. BST r22,7
      26. bld r16,Dout_pin_g2
      27. BST r23,7
      28. bld r16,Dout_pin_b2
      29. lSl r18
      30. lSl r19
      31. lsl r20
      32. lsl r21
      33. lsl r22
      34. lsl r23
      35. Out Dout_port , R16
      36. SBI shift_clock_Port, shift_clock_Pin
      37. dec r17
      38. CBI shift_clock_Port, shift_clock_Pin
      39. BRnE loop_shift2out ; if = 0 exit
      40. $end Asm
      41. Index_1 = Index_1 + 1 : Index_2 = Index_2 + 1
      42. Next D_1
      43. Index_1 = Index_1 + Dy_offset : Index_2 = Index_2 + Dy_offset
      44. Next D_2
      45. Pwm2 = 0
      46. Tccr2.5 = 0 : Tccr2.4 = 0
      47. 'Waitus 20
      48. P_oe = 1
      49. P_lat = 1 : P_lat = 0
      50. P_a = Page_counter.0
      51. P_b = Page_counter.1
      52. P_c = Page_counter.2
      53. P_d = Page_counter.3
      54. Tccr2.5 = 1 : Tccr2.4 = 1
      55. Pwm2 = Brightness 'display on
      56. Trigger = 1
      57. Return
      Alles anzeigen
      P_oe ist als output konfiguriert.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Die Geisterpixel sind weg, wenn man den timer2 ausschaltet und nach dem pages-Umschalten wieder einschaltet. Man braucht auch den Schmonzenz mit dem COM21/0 bits nicht.

      BASCOM-Quellcode

      1. 'Interrupt service
      2. Display_refresh: 'show the memory on the display
      3. Load Timer0 , Timer0reload
      4. Page_counter = Page_counter + 1
      5. If Page_counter > 15 Then Page_counter = 0
      6. Index_1 = Index_offset(page_counter)
      7. Index_2 = Index_1 + Channel_offset
      8. For D_2 = 1 To Dy_num_v
      9. For D_1 = 1 To Bytes_in_row
      10. R18 = Memory_red(index_1)
      11. R19 = Memory_green(index_1) : R20 = Memory_blue(index_1) : R21 = Memory_red(index_2) : R22 = Memory_green(index_2) : R23 = Memory_blue(index_2)
      12. 'MSB first
      13. $asm
      14. LDI r17,8
      15. Loop_shift2out:
      16. in R16, dout_port
      17. BST r18,7
      18. BLD r16,Dout_pin_r1
      19. BST r19,7
      20. bld r16,Dout_pin_g1
      21. BST r20,7
      22. bld r16,Dout_pin_b1
      23. BST r21,7
      24. BLD r16,Dout_pin_r2
      25. BST r22,7
      26. bld r16,Dout_pin_g2
      27. BST r23,7
      28. bld r16,Dout_pin_b2
      29. lSl r18
      30. lSl r19
      31. lsl r20
      32. lsl r21
      33. lsl r22
      34. lsl r23
      35. Out Dout_port , R16
      36. SBI shift_clock_Port, shift_clock_Pin
      37. dec r17
      38. CBI shift_clock_Port, shift_clock_Pin
      39. BRnE loop_shift2out ; if = 0 exit
      40. $end Asm
      41. Index_1 = Index_1 + 1 : Index_2 = Index_2 + 1
      42. Next D_1
      43. Index_1 = Index_1 + Dy_offset : Index_2 = Index_2 + Dy_offset
      44. Next D_2
      45. Pwm2 = 0
      46. Stop Timer2
      47. ' Tccr2.5 = 0 : Tccr2.4 = 0
      48. 'Waitus 20
      49. P_oe = 1
      50. P_lat = 1 : P_lat = 0
      51. P_a = Page_counter.0
      52. P_b = Page_counter.1
      53. P_c = Page_counter.2
      54. P_d = Page_counter.3
      55. ' Tccr2.5 = 1 : Tccr2.4 = 1
      56. Start Timer2
      57. Pwm2 = Brightness 'display on
      58. Trigger = 1
      59. Return
      Alles anzeigen
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • @monkye es scheint ja so zu sein, dass incr einen anderen code als var+1 erzeugt, und der dann noch komplizierter ist. Das ist halt, naja, verwunderlich, aber es wird größere Baustellen im bascom-Umfeld geben, als jetzt sowas zu optimieren. Es wäre einen Eintrag im Lexikon wert, und darin auf sowas hinzuweisen. Ich zumindest versuche es mir zu merken und schreibe in Zukunft +1, bzw -1 statt incr und decr (vielleich checke ich das decr auch mal im Simulator, wie sich das mit byte und word verhält).
      Hier sieht man wieder, was so ein Forum bringt, man stößt auf Dinge, an die man überhaupt nicht denkt.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Das Incr Word/Integer länger braucht als die Addition mit 1 liegt einfach daran, das man seiner Zeit die Funktion Incr für 16Bit eben als Funktion implementiert hat, was auch bedeutet, dass hier Aufruf und Rücksprung hinzukommen. Incr Byte wird erfreulicherweise Inline im Code eingebettet. Selbiges passiert mit 16Bit Additionen - Aber! Und (jetzt kommt's) : Die Addition mit 16Bit ist aber auch nur schneller, wenn die Optimierung eingeschaltet ist.
      Jedoch hat es nie je geheißen, Incr müsse schneller sein als die Addition mit 1.

      Denke aber, gäbe es Incr Inline, wäre das mit dem Word in 12 Takten erledigt....
      ...dafür noch was zum emulieren

      BASCOM-Quellcode

      1. macro incr_VARIABLENNAME
      2. loadadr VARIABLENNAME, x
      3. !LD R24,X+
      4. !LD R25,X
      5. !SUBI R24,0xFF
      6. !SBCI R25,0xFF
      7. !ST X,R25
      8. !ST -X,R24
      9. end macro
      Am Rande bemerkt sei auch, dass aus sicht des AVR der Befehl INC im Übrigen nicht gänzlich gleichbedeutend mit einer Addition/Subtraktion ist, was in der Assemblerprogrammierung von Belang ist.