Forum: Mikrocontroller und Digitale Elektronik 8x8 Matrix Laufschrift


von Jan H. (janiiix3)


Lesenswert?

Halli Hallo,

habe irgendwie einen kompletten "Blackout" was das "scrollen" eines 
Textes betrifft.

Habe eine 8x8 Matrix aufgebaut. Nun möchte ich gerne von rechts nach 
links einen Text rein scrollen lassen und diesen links ausrollen lassen.

Meine Zeichen stelle ich wie folgt ( mittig ) auf die Anzeige dar..
1
for( uint8_t i = 0 ; i < 8 ; i++ )
2
{
3
 VRAM[i] &= pgm_read_byte(&charMap[ZEICHEN][i])
4
}

Nun habe ich irgendwie mega Probleme mich in den Ablauf des scrollens 
rein zu denken & wie ich das am besten nachbilden kann..

Kann mir jemand evtl. mit einem Kodebeispiel weiter helfen? Darf auch 
gerne Pseudokode sein.. Würde mich über Hilfe riesig freuen.

Angenehmen, siegreichen Sonntag noch ;)

P.S
Die Anzeige wird schon gemultiplext.

: Bearbeitet durch User
von Dergute W. (derguteweka)


Lesenswert?

Moin,

Hab's nicht getestet - und warum nimmst du "&=" bei der Zuweisung ans 
VRAM?
1
for( uint8_t j = 0 ; j < 8 ; j++ )
2
  for( uint8_t i = 0 ; i < 8 ; i++ )
3
  {
4
   z1 = pgm_read_byte(&charMap[ZEICHEN][i]);
5
   z2 = pgm_read_byte(&charMap[NAECHSTES_ZEICHEN][i]);
6
   VRAM[i] = (z1 << j) | (z2 >> (8-j));
7
  }

Gruss
WK
edit: z1 und z2 sollten unsigned sein, sonst stoert das Vorzeichen beim 
rechtsschieben.

: Bearbeitet durch User
von Thomas S. (thomas_s72)


Lesenswert?

Hallo,
vorausgesetzt dass die Ausgabe ohne Scrollen so funktioniert (verstehe 
das &= auch nicht, aber egal) stellt sich mir die Frage:
Wie sind die Bytes angeordnet?

Horizontal oder vertikal?

Anders ausgedrückt: Die Laufvariable i, ist das die Zeile von oben nach 
unten oder die Spalte von links nach rechts? Danach richtet sich es, ob 
man die Spalten versetzt ausgeben muss, oder die einzelnen Zeilen 
bitweise nach links schieben.


Wenn das klar ist kann man sinnvolle Ansätze erarbeiten.
Gruß
Thomas

von Thomas S. (thomas_s72)


Lesenswert?

Hab sowas schonmal gemacht, siehe hier:

https://www.youtube.com/watch?v=dVLfzm9piLw

Da sind die Bytes zeilenweise angeordnet, muss man aber nicht so machen.

von georg (Gast)


Lesenswert?

Jan H. schrieb:
> Habe eine 8x8 Matrix aufgebaut. Nun möchte ich gerne von rechts nach
> links einen Text rein scrollen lassen

Einen Text in 8 Spalten? Ist dir klar dass man da nur ein einziges 
Zeichen sieht oder 2 halbe? Wer soll das lesen können?

Georg

von Karl M. (Gast)


Lesenswert?

Hallo Georg,

das geht schon mit einer Matrix Lauftext anzusehen, Zielführend war bei 
mir die für mich passende Scrollgeschwindigkeit zu wählen.
Do kann ich einfach 5 Zeichen + 1 Leerzeichen anzeigen.

georg schrieb:
> Jan H. schrieb:
>> Habe eine 8x8 Matrix aufgebaut. Nun möchte ich gerne von rechts nach
>> links einen Text rein scrollen lassen
>
> Einen Text in 8 Spalten? Ist dir klar dass man da nur ein einziges
> Zeichen sieht oder 2 halbe? Wer soll das lesen können?
>
> Georg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Die Anzeige wird schon gemultiplext.
Bau dein Programm so um, dass du dein Zeichen aus dem RAM darstellen 
kannst.  Und dann speicherst du die gesamte Meldung mitsamt Abstand 
hintereinander in das RAM und fährst mit einem "Anfangszeiger" durch das 
RAM. Diesen Anfangszeiger inkremenierst du nach jeweils ca. 100ms und 
fängst somit immer eine Pixelreihe "weiter hinten" an.

von MaWin (Gast)


Lesenswert?

Jan H. schrieb:
> Nun habe ich irgendwie mega Probleme mich in den Ablauf des scrollens
> rein zu denken

Tja, wenn man nicht weiss, ob deine Bytes eine senkrechte Spalte oder 
waagerechte Zeile darstellen, wird das auch nichts.

Man braucht jedenfalls das aktuelle Zeichen und das nächste Zeichen, du 
hast nur ZEICHEN, also 1.

Man muss dann entweder eine Anzahl von Spalten aus dem ersten und die 
Restanzahl aus dem nächsten Zeichen holen,

oder eben aus 2 byzes 1 16 bit Wort machen und so schirben dass die 
benötigten Bildpunkte z.B. im lower byte stehen, welches dann auf die 
Matrix kommt

von Jan H. (janiiix3)


Lesenswert?

Dergute W. schrieb:
> Hab's nicht getestet - und warum nimmst du "&=" bei der Zuweisung ans
> VRAM?
Das habe ich gemacht, damit alle anderen LED´s aus sind. Habe die LED´s 
"active low" angeschlossen.
Ohne würden die anderen nicht ausgehen. Hängt auch mit dem Zeichensatz 
zusammen.

von Dergute W. (derguteweka)


Lesenswert?

Jan H. schrieb:
> Das habe ich gemacht, damit alle anderen LED´s aus sind. Habe die LED´s
> "active low" angeschlossen.
> Ohne würden die anderen nicht ausgehen. Hängt auch mit dem Zeichensatz
> zusammen.

Da staunt der Fachmann und der Wunde leiert sich...

Gruss
WK

von Jim M. (turboj)


Lesenswert?

Jan H. schrieb:
> Dergute W. schrieb:
>> Hab's nicht getestet - und warum nimmst du "&=" bei der Zuweisung ans
>> VRAM?
> Das habe ich gemacht, damit alle anderen LED´s aus sind. Habe die LED´s
> "active low" angeschlossen.
> Ohne würden die anderen nicht ausgehen. Hängt auch mit dem Zeichensatz
> zusammen.

Das möchtest Du Dir nochmal an Hand von Beispiel Werten durchrechen. In 
meinen Augen funktioniert das nämlich nur genau ein Mal - es sei denn Du 
hast irgendwo ein
1
memset(VRAM, 0xFF, sizeof(VRAM));

versteckt.

von Jan H. (janiiix3)


Lesenswert?

Dergute W. schrieb:
> Jan H. schrieb:
>> Das habe ich gemacht, damit alle anderen LED´s aus sind. Habe die LED´s
>> "active low" angeschlossen.
>> Ohne würden die anderen nicht ausgehen. Hängt auch mit dem Zeichensatz
>> zusammen.
>
> Da staunt der Fachmann und der Wunde leiert sich...
>
> Gruss
> WK

So ganz funktioniert das noch nicht. Die Schrift soll von rechts rein 
kommen und nach links raus rollen. Hier mal ein Video..

https://www.dropbox.com/s/m1xoapgqulvenrj/IMG_1795.MOV?dl=0

von Stefan F. (Gast)


Lesenswert?

Ja dann sage doch endlich mal, wie die Matrix aufgebaut und ausgerichtet 
ist! Und wie sind die Zeichensätze im Speicher aufgebaut? Ein kleiner 
Schaltplan + die relevanten Codeschnipsel wären angemessen.

von Jan H. (janiiix3)


Lesenswert?

Die Anzeige ist "horizontal" aufgebaut.
1
0 1  2  3  4  5  6  7  
2
3
1 VRAM[0]   ..    VRAM[7]
4
5
2 ..
6
7
3 ..
8
9
4 ..
10
11
5 ..
12
13
6 ..
14
15
7

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Das sind doch immer noch halbe Informationen. Ich dichte mal dazu, dass 
jedes Byte im VRAM eine vertikale Reihe von LED's ansteuert, und zwar 
Low=An. Ich dichte auch dazu, dass diese Darstellung der physischen 
Zuordnung entspricht, also keine Pins vertauscht werden müssen und keine 
Drehung um 90° nötig ist.

Stimmt das soweit?

Wie sind denn deine Daten im Zeichensatz angeordnet. Genau so? Könnte 
man also 8 Byte direkt vom Zeichensatz 1:1 ins VRAM Kopieren, um ein 
einzelnes stehendes Zeichen darzustellen?

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Das sind doch immer noch halbe Informationen. Ich dichte mal dazu, dass
> jedes Byte im VRAM eine vertikale Reihe von LED's ansteuert, und zwar
> Low=An. Ich dichte auch dazu, dass diese Darstellung der physischen
> Zuordnung entspricht, also keine Pins vertauscht werden müssen und keine
> Drehung um 90° nötig ist.
>
> Stimmt das soweit?
>
> Wie sind denn deine Daten im Zeichensatz angeordnet. Genau so? Könnte
> man also 8 Byte direkt vom Zeichensatz 1:1 ins VRAM Kopieren, um ein
> einzelnes stehendes Zeichen darzustellen?

Genau das kann man.
Mit..
1
for( uint8_t x = 0 ; x < 8 ; x++ )
2
{
3
 VRAM[x] = ~(pgm_read_byte(&charMap[u1][x]));
4
}
Kopier ich das Zeichen "u1" in den VRAM und es wird auf dem Display 
angezeigt.

von Stefan F. (Gast)


Lesenswert?

Um ein neues Zeichen schrittweise von rechts herein zu schieben, musst 
du eine Schleife mit 8 Schritten programmieren. Bei jedem Schritt 
verschiebt sie den Inhalt des ganzen VRAM um eine Position nach links, 
um danach rechts eine Spalte des nächsten Zeichens einzufügen.

Angenommen, das VRAM Enthält zunächst die acht Spalten von dem 
Buchstaben "A" und dann soll der Buchstabe "B" von rechts herein 
geschoben werden, dann sieht das im VRAM so aus:

A0 A1 A2 A3 A4 A5 A6 A7
A1 A2 A3 A4 A5 A6 A7 B0
A2 A3 A4 A5 A6 A7 B0 B1
A3 A4 A5 A6 A7 B0 B1 B2
A4 A5 A6 A7 B0 B1 B2 B3
A5 A6 A7 B0 B1 B2 B3 B4
A6 A7 B0 B1 B2 B3 B4 B5
A7 B0 B1 B2 B3 B4 B5 B6
B0 B1 B2 B3 B4 B5 B6 B7
1
for( uint8_t step = 0 ; step < 8 ; step++ )
2
{
3
    // Schieben
4
    for( uint8_t spalte = 0 ; spalte < 7 ; spalte++ )
5
    {
6
       VRAM[spalte] = VRAM[spalte+1];
7
    }
8
9
    // neues Byte rechts einfügen
10
    VRAM[7] = ~(pgm_read_byte(&charMap[u1][step]));
11
12
   delay_ms(100);
13
}

Verständlich?

von Jan H. (janiiix3)


Lesenswert?

Habe ich soweit verstanden. Das Zeichen fängt aber auch hier wieder im 
Display an. Es wird nicht komplett von unten nach oben rein geschoben.

Hier mal ein Video..
https://www.dropbox.com/s/yy4ftcy1y3v6rw4/IMG_1796.MOV?dl=0

von mIstA (Gast)


Lesenswert?

Jan H. schrieb:
> Habe ich soweit verstanden. Das Zeichen fängt aber auch hier wieder im
> Display an.


Meinst Du konkret das erste Zeichen Deines Textes? Dann stell ihm ein 
Leerzeichen voran, dann fällt das nicht auf.


Jan H. schrieb:
> Es wird nicht komplett von unten nach oben rein geschoben.

Jan H. schrieb:
> Nun möchte ich gerne von rechts nach links einen Text rein scrollen lassen


Magst Du Dich vielleicht mal entscheiden? Von wo nach wohin soll der 
Text scrollen?

von Jan H. (janiiix3)


Lesenswert?

> Magst Du Dich vielleicht mal entscheiden? Von wo nach wohin soll der
> Text scrollen?

Der Text sollte von links nach rechts rein scrollen. Die Funktion 
@Stefanus F. geschrieben hat, funktioniert auch wunderbar aber da 
scrollt der Text von unten rein und nach oben raus..

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Dann wirds wohl auf so ein Schiebekonstrukt rauslaufen, wie ich schon um 
11:11h mutmasste.

Gruss
WK

von Jan H. (janiiix3)


Lesenswert?

Dergute W. schrieb:
> Moin,
>
> Dann wirds wohl auf so ein Schiebekonstrukt rauslaufen, wie ich schon um
> 11:11h mutmasste.
>
> Gruss
> WK

Bei dem fehlt nur noch was. Die Zeichen sind direkt in der Mitte vom 
Display gewesen und nicht von rechts reingekommen.. Das müsste ich noch 
hinbekommen..

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Lass' mal die for schleife mit dem j weg, und setze j einfach mal auf 
einen festen Wert z.b. 3,4, oder 5.
Vielleicht faellt ja dann der Groschen?

Gruss
WK

von Jan H. (janiiix3)


Lesenswert?

Dergute W. schrieb:
> Moin,
>
> Lass' mal die for schleife mit dem j weg, und setze j einfach mal auf
> einen festen Wert z.b. 3,4, oder 5.
> Vielleicht faellt ja dann der Groschen?
>
> Gruss
> WK
1
void scrollMessage( char *msg )
2
{
3
  char z1 = 0 , z2 = 0;
4
  while ( *msg )
5
  {
6
7
      for( uint8_t i = 0 ; i < 8 ; i++ )
8
      {
9
        z1 = ~pgm_read_byte(&charMap[ GetCharacterIndex( *msg )  ] [ i ] );
10
        z2 = ~pgm_read_byte(&charMap[ GetCharacterIndex( *msg++ )] [ i ] );
11
        VRAM[i] = ( z1 << 6 ) | (z2 >> ( 8 - 6 ) );
12
      }  
13
      _delay_ms(250);    
14
15
16
    
17
//     for( uint8_t step = 0 ; step < 8 ; step++ )
18
//     {
19
//       // Schieben
20
//       for( uint8_t spalte = 0 ; spalte < 8 ; spalte++ )
21
//       {
22
//         VRAM[spalte] = VRAM[spalte+1];
23
//       }
24
// 
25
//       // neues Byte rechts einfügen
26
//       VRAM[7] = ~(pgm_read_byte(&charMap[ GetCharacterIndex( *msg )][step]));
27
// 
28
//       _delay_ms(150);
29
//     }  
30
//     msg++;  
31
  }
32
}

Wenn ich die Funktion so einsetze, passiert folgendes..
https://www.dropbox.com/s/ln6vh99z0joixu3/IMG_1799.MOV?dl=0

von MaWin (Gast)


Lesenswert?

Jan H. schrieb:
> Der Text sollte von links nach rechts rein scrollen. Die Funktion
> @Stefanus F. geschrieben hat, funktioniert auch wunderbar aber da
> scrollt der Text von unten rein und nach oben raus

Tja, dann ist deine Matrix falsch verdrahtet.
Dreh sie und die font definition um 90 Grad.

von Stefan F. (Gast)


Lesenswert?

Offensichtlich ist die Schaltung und die Ausrichtung der Daten im 
Speicher immer noch völlig unklar. Meine Zusammenfassung wurde erst 
bestätigt und dann ein Problem (von unten nach oben) geschildert, dass 
nur bei einer völlig anderen Struktur möglich sein kann.
Ich werde much erst weiter beteiligen, wenn der TO Schaltplan, 
Speicherstruktur und Quelltext offen legt.

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Sorry war die ganze Zeit unterwegs und hatte leider nur mein Handy dabei 
und keinen Zugriff auf die Daten.

Und anbei der Zeichensatz.

von Stefan F. (Gast)


Lesenswert?

Der Test von Code fehlt, der die eigentliche Ausgabe macht. Auf jeden 
Fall ist der Zeichensatz schnmal ganz anders aufgebaut als hier 
abgestimmt wurde. Ich sehe 8 Bytes pro Zeichen. Jedes Byte repräsentiert 
eine Zeile.

Das macht den Scrill Effekt aufwändigwr denn du musst in jeder Zeile 
alle Bits um eins nach links schieben und dann rechts in jeder Zeile ein 
Bit aus dem Zeichensatz rein schieben.

Bitmanipulation ist dein Thema.

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Der Test von Code fehlt, der die eigentliche Ausgabe macht.

Du meinst die Ausgabe mit deinem Kode von 11:11 Uhr?

von Michael K. (tschoeatsch)


Lesenswert?

Hi, ehrlich gesagt, ich hab nicht alles gelesen, aber ich würde das so 
machen:
Einen Bildspeicher anlegen, vertikal ein byte, horizontal Anzahl der 
Spalten deiner Matrix.
Eine Routine schreiben, die den Bildspeicher auf der Matrix anzeigt.
Einen font verwenden, der spaltenorinetiert ist.
Eine Routine schreiben, die jetzt nacheinander Buchstabe für Buchstabe 
aus dem Text nimmt und eine Spalte von Buchstaben in die rechteste 
Spalte vom Bildspeicher schreibt, den Bildspeicher anzeigen lässt, nach 
kurzer Zeit den Bildspeicher spaltenweise nach links umkopiert(linkeste 
Spalte fällt weg, 2. Spalte wird 1....rechteste Spalte wird die 2. von 
rechts). Jetzt nächste Spalte vom Buchstaben in die rechteste Stelle vom 
Bildspeicher schreiben, anzeigen lassen, warten, Bildspeicher nach links 
shiften, nächste Spalte vom Buchstaben in die rechteste Spalte des 
Bildspeichers...

von Stefan F. (Gast)


Lesenswert?

Ich meinte dass der TEXT von deinem Quelltext fehlt, der die Ausgabe vom 
VRAM zum Display macht.

von Stefan F. (Gast)


Lesenswert?

Michael, so weit waren wir schon. Nun ist sein Zeichensatz aber 
Zeilenorientiert, wie sich herausgestellt hat.

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Ich meinte dass der TEXT von deinem Quelltext fehlt, der die Ausgabe vom
> VRAM zum Display macht.
1
 
2
/* Multiplexen der Anzeige */
3
ISR(TIMER0_COMP_vect)
4
{
5
  
6
    static volatile uint8_t spalte = 0;
7
8
    PORTC &= ~((1<<PC7) | (1<<PC6) | (1<<PC5) | (1<<PC4) | (1<<PC3));
9
    PORTB &= ~((1<<PB2) | (1<<PB1) | (1<<PB0));
10
    
11
    // neue Zeilendaten ausgeben
12
    
13
  PORTA = ~(VRAM)[spalte];
14
    
15
    // Spalte aktivieren  
16
    switch (spalte) {
17
      case 0: PORTC |= (1<<PC3);
18
      break;
19
      case 1: PORTC |= (1<<PC4);
20
      break;
21
      case 2: PORTC |= (1<<PC5);
22
      break;
23
      case 3: PORTC |= (1<<PC6);
24
      break;
25
      case 4: PORTC |= (1<<PC7);
26
      break;
27
      case 5: PORTB |= (1<<PB2);
28
      break;
29
      case 6: PORTB |= (1<<PB1);
30
      break;
31
      case 7: PORTB |= (1<<PB0);
32
      break;
33
      default: break;
34
    }
35
36
    spalte++; // nächste Spalte
37
    if (spalte >= 8) spalte = 0; // Spalten 0.

von Michael K. (tschoeatsch)


Lesenswert?

Stefanus F. schrieb:
> Michael, so weit waren wir schon. Nun ist sein Zeichensatz aber
> Zeilenorientiert, wie sich herausgestellt hat.

Dann macht man den Bildspeicher einfach nach rechts breiter und zeigt 
halt nur den linken Teil an. Der Buchstabe wird rechts in den 
Bildspeicher geschrieben, man shiftet und zeigt den Bildspeicher an, 
nachdem man das 8x gemacht hat, wird wieder ein kompletter Buchstabe in 
den Speicher geladen...

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Oioioi, ich glaub', da laeuft's noch an so vielen verschiedenen Stellen 
schief...
In dem Filmchen siehts so aus, als wuerde da wer weiss wer an den LEDs 
rumfummeln. Die muessten doch zumindest regelmaessig ihr Muster aendern; 
tun sie aber nicht. Da sind manchmal kurze und manchmal laengere Pausen 
dabei.

Die Bedeutung von Tilde (~) und die Gesetze von De Morgan sitzen auch 
noch lange nicht so, wie man das braucht, um Bitpopeleien vernuenftig 
auszufuehren:

Jan H. schrieb:
> z1 = ~pgm_read_byte(&charMap[ GetCharacterIndex( *msg )  ] [ i ] );
>         z2 = ~pgm_read_byte(&charMap[ GetCharacterIndex( *msg++ )] [ i ]
> );
>         VRAM[i] = ( z1 << 6 ) | (z2 >> ( 8 - 6 ) );


Gruss
WK

von Jan H. (janiiix3)


Lesenswert?

Dergute W. schrieb:
> Die Bedeutung von Tilde (~) und die Gesetze von De Morgan sitzen auch
> noch lange nicht so, wie man das braucht, um Bitpopeleien vernuenftig
> auszufuehren:

Da es sich um "invertierte Logik" handelt, musste ich das so machen, 
sonst hätte ich den ganzen Font umschreiben müssen.

Wenn ich wüsste wie ich jetzt weiter machen sollte, würde ich mich wohl 
kaum hier zu Wort melden..

von Thomas S. (thomas_s72)


Lesenswert?

Hier mal eine Funktion, so ähnlich habe ich das in meiner Uhr gelöst.
scroll ist hier die Verschiebung nach links (0 ist nicht verschoben)
.
Das Zeichen wird in die 8x8 hineingeschrieben, bei jedem Aufruf mit 
scroll einen größer wird es nach links herausgeschoben.
Will man es von rechts hereinschieben lassen muss man V8bit[1] ausgeben.

void ScrollPrint (unsigned char ZEICHEN, unsigned char scroll)
{
  union
  {
    unsigned int V16Bit;
    unsigned char V8Bit[2];
  } tmp;

  for( uint8_t i = 0 ; i < 8 ; i++ )
  {
    tmp.V16Bit = pgm_read_byte(&charMap[ZEICHEN][i]);
    tmp.V16Bit = V16Bit << scroll;//nach lins schieben
    VRAM[i] &= tmp.V8Bit[0];//die rechte Seite ausgeben
  }
}
Hilft das weiter?

von Jan H. (janiiix3)


Lesenswert?

Thomas S. schrieb:
> Hier mal eine Funktion, so ähnlich habe ich das in meiner Uhr gelöst.
> scroll ist hier die Verschiebung nach links (0 ist nicht verschoben)
> .
> Das Zeichen wird in die 8x8 hineingeschrieben, bei jedem Aufruf mit
> scroll einen größer wird es nach links herausgeschoben.
> Will man es von rechts hereinschieben lassen muss man V8bit[1] ausgeben.
>
> void ScrollPrint (unsigned char ZEICHEN, unsigned char scroll)
> {
>   union
>   {
>     unsigned int V16Bit;
>     unsigned char V8Bit[2];
>   } tmp;
>
>   for( uint8_t i = 0 ; i < 8 ; i++ )
>   {
>     tmp.V16Bit = pgm_read_byte(&charMap[ZEICHEN][i]);
>     tmp.V16Bit = V16Bit << scroll;//nach lins schieben
>     VRAM[i] &= tmp.V8Bit[0];//die rechte Seite ausgeben
>   }
> }
> Hilft das weiter?

Hallo,

ich danke dir erstmal für deine Antwort. Kann es gerade leider nicht 
testen. Werde mich später dazu noch mal melden.

von Jan H. (janiiix3)


Lesenswert?

Thomas S. schrieb:
> void ScrollPrint (unsigned char ZEICHEN, unsigned char scroll)
> {
>   union
>   {
>     unsigned int V16Bit;
>     unsigned char V8Bit[2];
>   } tmp;
>
>   for( uint8_t i = 0 ; i < 8 ; i++ )
>   {
>     tmp.V16Bit = pgm_read_byte(&charMap[ZEICHEN][i]);
>     tmp.V16Bit = V16Bit << scroll;//nach lins schieben
>     VRAM[i] &= tmp.V8Bit[0];//die rechte Seite ausgeben
>   }
> }
> Hilft das weiter?

Wenn ich es von rechts reinrollen lassen möchte, meinst du muss es so 
aussehen? Ist das richtig?
1
void ScrollPrint (unsigned char ZEICHEN, unsigned char scroll)
2
{
3
  union
4
  {
5
    unsigned int V16Bit;
6
    unsigned char V8Bit[2];
7
  } tmp;
8
9
  for( uint8_t i = 0 ; i < 8 ; i++ )
10
  {
11
    tmp.V16Bit = pgm_read_byte(&charMap[ZEICHEN][i]);
12
    tmp.V16Bit = V16Bit << scroll;//nach lins schieben
13
    VRAM[i] &= tmp.V8Bit[1];//die rechte Seite ausgeben
14
  }
15
}

von Thomas S. (thomas_s72)


Lesenswert?

Genau so.
Mit jeder Vergrößerung des Parameters scroll rutscht die Ausgabe einen 
Pixel nach links.
tmp.V8Bit[0] ist dabei die rechte Hälfte, tmp.V8Bit[1] die linke.
Wenn man einen schiebt so sind wir einen Pixel in er linken Hälfte, wenn 
man die ausgibt sieht es so aus als käme das Zeichen von rechts.
Beim Schieben von 8 ist man genau drin, schiebt man weiter verschwindet 
es wieder links raus.

von Äxl (geloescht) (Gast)


Lesenswert?

ich hatte auch ein 8x8 Gitter mit kleinen Glühlampen+Dioden gebastelt 
und dieses dann jahre später auf 16x10, mit LEDs, erweitert / 
modernisiert.
ab jenem Zeitpunkt musste die Anzeige dann Quer aufgehangen werden 
(16:10 Format quasi) und ich stand genau vor dem gleichen Problem. 
Konnte ich anfangs die Bytes aus dem Flash einfach so auf die Anzeige 
tröpfeln lassen und mitm Zeiger den Flash durchfahren, musste ich nun 
das anfangs geladene Byte(paar)[16bit] per Bitshift und hirnschmalz auf 
die Anzeige bringen, weil das Display ja nun 90° gedreht war. Ich such 
das gern mal raus - hab ich zu Hause.
(Hing damals am Balkon: "Merry Xmas ,Happy new Year" usw.)

von Jan H. (janiiix3)


Lesenswert?

Äxl (geloescht) schrieb:
> ich hatte auch ein 8x8 Gitter mit kleinen Glühlampen+Dioden gebastelt
> die Anzeige bringen, weil das Display ja nun 90° gedreht war. Ich such
> das gern mal raus - hab ich zu Hause.
> (Hing damals am Balkon: "Merry Xmas ,Happy new Year" usw.)
Sehr gerne würde ich mich drüber freuen.

von Michael K. (tschoeatsch)


Lesenswert?

Wenn du eine 'inverse' Ansteuerung der Led hast, dann invertiere halt 
beim Lesen des fonts gleich alle bits der bytes und fülle damit den 
Bildspeicher. Wenn du den Bildspeicher aus 8 words aufbaust, ein word 
ist eine Zeile, dann kannst du doch 8 bits von dem word auf den Leds 
ausgeben und in den anderen 8bits eine Zeile des Buchstabens 
reinkopieren. Wenn du jetzt alle words shiftest, dann wandern die bits 
des Buchstabens in den dargestellten Bereich der words. Jetzt musst du 
halt das word entsprechend dem font anlegen. Wenn bit7 aus einem byte 
des fonts die linke Kante des Buchstabens ist, dann wäre bit15 des words 
die linke Kante deiner Ledmatrix, die dann bis bit8 den Inhalt des words 
darstellt. Bit7 bis bit0 wäre eine Zeile des Buchstabens.
Ein word ist bei mir eine 16bit-Variable.

von Stefan F. (Gast)


Lesenswert?

Habe ich einen Knick in der Optik oder sehe ich doppelte Invertierung?

> Mit..
1
for( uint8_t x = 0 ; x < 8 ; x++ )
2
{
3
 VRAM[x] = ~(pgm_read_byte(&charMap[u1][x]));
4
}
> Kopier ich das Zeichen "u1" in den VRAM und es wird auf
> dem Display angezeigt.

Und:
1
ISR(TIMER0_COMP_vect)
2
{
3
    ...    
4
    // neue Zeilendaten ausgeben
5
    PORTA = ~(VRAM)[spalte];
6
    ...
7
}

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
>
1
> ISR(TIMER0_COMP_vect)
2
> {
3
>     ...
4
>     // neue Zeilendaten ausgeben
5
>     PORTA = ~(VRAM)[spalte];
6
>     ...
7
> }
8
>
Das musste ich eben wegen der Invertierten Logik machen. Sonst sind 
dauerthaft alle LED´s beim Plexen an.

von Jan H. (janiiix3)


Lesenswert?

Vielen Dank! Das klappt echt super. Was mir jetzt noch nicht so ganz 
gefällt ist der Font. Ich habe zwischen den einzelnen Zeichen immer 
mindestens 6 x "Leerzeichen".. Das sieht echt kacka aus bei dem 
scrollen.
Wie löse ich das am besten? Font anpassen und mit jeweils der Breite 
eines Zeichens versehen?

von Michael K. (tschoeatsch)


Lesenswert?

Ist nicht ein 8x8 font so aufgebaut, dass das Zeichen und eine leere 
Spalte in eine 8x8 Matrix passt? Wenn du 6 Spalten dazwischen hast, dann 
kommen 5 Spalten von deinem Programm. Das gilt jetzt für ein 'H', wenn 
du ein (schmales) 'I' hast, dann sind mehr Spalten zwischen den 
Buchstaben, ist halt kein proportional font.

von Jan H. (janiiix3)


Lesenswert?

Michael K. schrieb:
> Ist nicht ein 8x8 font so aufgebaut, dass das Zeichen und eine leere
> Spalte in eine 8x8 Matrix passt? Wenn du 6 Spalten dazwischen hast, dann
> kommen 5 Spalten von deinem Programm. Das gilt jetzt für ein 'H', wenn
> du ein (schmales) 'I' hast, dann sind mehr Spalten zwischen den
> Buchstaben, ist halt kein proportional font.
Es sieht eben beim scrollen sehr doof aus. Es ist halt eine Menge Platz 
dazwischen.. Den muss ich irgendwie eliminieren..

von Michael K. (tschoeatsch)


Lesenswert?

Tja, dann wird es das einfachste sein, im font bei jedem Zeichen ein 
'Breite'-byte einzufügen. Wenn der font zeilenorientiert ist, ist es 
schon aufwändig die Breite zu errechnen, könnte aber gehen.

Aber wenn du schreibs 'mindestens' 6 Leerspalten, dann ist was anderes 
faul. Was passiert, wenn du 'HHHH' als Text ausgibst? Da sollte nur 1 
Spalte als Platzhalter zwischen den Buchstaben sein.

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Michael K. schrieb:
> Aber wenn du schreibs 'mindestens' 6 Leerspalten, dann ist was anderes
> faul. Was passiert, wenn du 'HHHH' als Text ausgibst? Da sollte nur 1
> Spalte als Platzhalter zwischen den Buchstaben sein.

Da ist immer ein ganzer "Bildschirm" (8 Bytes) zwischen jedem 'H'...
1
uint8_t ScrollPrint ( char *msg )
2
{
3
  union
4
  {
5
    unsigned int V16Bit;
6
    unsigned char V8Bit[2];
7
  } tmp;
8
9
  uint8_t scrollPos;
10
  uint8_t leng;
11
  for ( leng = 0 ; *msg != '\0' ; leng++ )
12
  {
13
    for ( scrollPos = 0 ; scrollPos < 8 ; scrollPos++ )
14
    {
15
      for( uint8_t i = 0 ; i < 8 ; i++ )
16
      {
17
        tmp.V16Bit  =  0xFF & ~pgm_read_byte(&charMap[ GetCharacterIndex( *msg ) ][i]);
18
        tmp.V16Bit  = tmp.V16Bit << scrollPos; // nach links verschieben
19
        VRAM[i]    = tmp.V8Bit[1]; // rechte Seite ausgeben
20
      }
21
      _delay_ms(250);    
22
    }
23
    msg++;    
24
  }
25
  
26
  return leng;
27
}

: Bearbeitet durch User
von Thomas S. (thomas_s72)


Lesenswert?

Breite berechnet diese Funktion:
//###########returns the length of a char in pixels####################
unsigned char SignLength (unsigned char A)      //returns length of A in 
pixels
{
  unsigned char max=1,tmp;
  register unsigned char i, j;

  if (A == ' ')  return 3;  //SPACE
  if (!A)  return 4;    //NULL
  if (A == ',')  return 2;  //comma

  for (i = 0; i < 8; i++)              //8 lines with 6 dots max each
  {
  tmp = (pgm_read_byte (&font6x8[A][i]));  //maximum char is 0x1F, 5 
bits right adjusted
  for (j = 32; j > 1; j/=2)
    {
    if ((tmp&j)&&(j > max))
      {
    max = j;              //max value in this line, next line...
        break;
    }
   }
  }
  j = 1;
  while (max)
  {
    max/=2;
    j++;
  }
  return j;
}

So geht es in meiner Uhr. Die Zeichen müssen dafür rechtsbündig 
definiert sein, also immer in Bit0 der rechteste Pixel.

von Jan H. (janiiix3)


Lesenswert?

Thomas S. schrieb:
> So geht es in meiner Uhr. Die Zeichen müssen dafür rechtsbündig
> definiert sein, also immer in Bit0 der rechteste Pixel.

Wo baust du die Länge bei deinem "ScrollPrint" ein? Du musst ja 
irgendwie um 'x' schieben ?!

von Stefan F. (Gast)


Lesenswert?

> Das musste ich eben wegen der Invertierten Logik machen.

Aber doppelt invertiert ist am Ende doch nicht invertiert.

von Michael K. (tschoeatsch)


Lesenswert?

Stefanus F. schrieb:
>> Das musste ich eben wegen der Invertierten Logik machen.
>
> Aber doppelt invertiert ist am Ende doch nicht invertiert.

Eben, der font ist nicht invertiert, dann wird er invertiert und durch 
die Ausgabe wieder invertiert. Dann passt die Ansicht wieder.

von Michael K. (tschoeatsch)


Lesenswert?

Ich verwende nicht C, aber wenn ich mich nicht irre (was dadurch leicht 
sein kann), shiftest du deine 16bit Variable und liest gleichzeitig die 
bytes des nächsten Buchstabens ein?. Wenn du den Buchstaben komplett in 
die eine Hälfte der 16bitVariablen einliest, dann diese 8x um 1bit 
shiftest und dann wieder komplett den nächsten Buchstaben lädst, dann 
muss alles passen.

von Jan H. (janiiix3)


Lesenswert?

Michael K. schrieb:
> Ich verwende nicht C, aber wenn ich mich nicht irre (was dadurch leicht
> sein kann), shiftest du deine 16bit Variable und liest gleichzeitig die
> bytes des nächsten Buchstabens ein?. Wenn du den Buchstaben komplett in
> die eine Hälfte der 16bitVariablen einliest, dann diese 8x um 1bit
> shiftest und dann wieder komplett den nächsten Buchstaben lädst, dann
> muss alles passen.

Das "scrollen" ist nicht das Problem. Es geht jetzt nur noch darum das 
immer ein Zeichen ( 8 Byte ) durch geschoben wird und dahinter erstmal 
weiter nichts kommt, bis eben das nächste Zeichen anfängt. Das sieht aus 
als würde er erst nach jedem Zeichen noch ein ' ' durch schieben.

Wie stelle ich das jetzt am besten an, die Zeichen aneinander zu reihen 
mit max. 2 Leerstellen dazwischen?

von Thomas S. (thomas_s72)


Lesenswert?

Hallo,
mit einer einzelnen 8x8 habe ich da auch noch nie gemacht, aber ich 
würde so ansetzen:

1. String definieren mit den Zeichen die ausgegeben werden müssen. z.B. 
"Das ist mein Scrolltext"

2. einen Zeiger drauf definieren der das erste Zeichen adressiert.
3. Breite B des Zeichens berechnen, siehe Funktion oben
4. PrintFunktion mit scroll = 8-B fürs Zeichen beim Zeiger
5. scroll++
6. wenn scroll == 8 ist, dann ist das erste Zeichen voll zu sehen
7. dann das zweite Zeichen dazu drucken (8-B), Zeiger incrementieren
8. wenn scroll des ersten Zeichens gleich 16 ist, dann ist das erste 
draußen
9. drittes Zeichen dazu drucken, usw...

Eventuell muss man mit zwei Zeigern und zwei scrolls arbeiten, einer für 
das erste, dritte, fünfte Zeichen, einer fürs zweite, vierte und so 
weiter. Zeiger dann immer um 2 erhöhen.

Es gibt da bestimmt verschiedene Ansätze, testen und überlegen. Soll ja 
nur eine Hilfe sein hier, keine Komplettlösung.

Zur Frage
>Wo baust du die Länge bei deinem "ScrollPrint" ein? Du musst ja
>irgendwie um 'x' schieben ?!

Wenn ich ein schmales Zeichen (z.B. 'i" drucken will (Breite x), so 
drucke ich es nicht an scroll = 0, sodern an scroll = 8-x, je schmaler 
desto linkser sozusagen. Ein breites Zeichen (8 breit sogar) wird dann 
an scroll=0 gedruckt. Simple Mathematik, keine "Rocket science" wie man 
im Englischen sagt.

Gruß
Thomas

von Thomas S. (thomas_s72)


Lesenswert?

Ach nochwas:
Die Breitenfunktion erwartet leuchtende Punkte als 1, wenn ich es 
richtig verstehe ist das bei Dir invertiert. Muss ggf. angepasst werden.
Nr dass keine Fragen kommen wieso es nicht funzt..

von Michael K. (tschoeatsch)


Lesenswert?

Jan H. schrieb:
> VRAM[i]    = tmp.V8Bit[1]; // rechte Seite ausgeben

Wäre es nicht richtig, die linke Seite auszugeben?

Jan H. schrieb:
> tmp.V16Bit  = tmp.V16Bit << scrollPos; // nach links verschieben

Hier schiebst du die Daten des Buchstabens nach links. Er wird so 
spaltenweise in's Sichtfeld geschoben. Wenn der voll zu sehen ist, muss 
der nächste Buchstabe in die 16bit Variablen kopiert werden. Dazu darf 
aber der alte Wert der 16bitVariablen nicht gelöscht werden, die müssen 
also global sein.

von Thomas S. (thomas_s72)


Lesenswert?

Sehe ich etwas anders.
Es ist sicherlich richtig die linke Seite auszugeben. Dann kann man 
schön von rechts reinscrollen und links wieder raus. Passt.

Global sollten nur die Speicherzellen sein, die am Ende das zu sichtbare 
Zeichen enthalten. Die temporäre Variable wird ja achtmal wieder 
verwendet. Interessant ist nur das Endergebnis. Das wird global 
gespeichert (8 Bytes).

von Michael K. (tschoeatsch)


Lesenswert?

Thomas S. schrieb:
> Global sollten nur die Speicherzellen sein, die am Ende das zu sichtbare
> Zeichen enthalten. Die temporäre Variable wird ja achtmal wieder
> verwendet. Interessant ist nur das Endergebnis. Das wird global
> gespeichert (8 Bytes).

Global sollten die 8 16bitVariablen ein. Die enthalten doch im Prinzip 2 
Buchstaben, wovon der linke Teil, der linke Buchstabe, angezeigt wird. 
Zum scrollen werden diese Variablen geshiftet, der linke Buchstabe 
verschwindet spaltenweise aus der Bildfläche, der rechte rück nach. Nach 
8x shiften sieht man nur den rechten Buchstaben. Jetzt wäre die Prozedur 
fertig. Ist der Text aber noch nicht komplett angezeigt, muss man in den 
rechten Teil der Variablen den nächsten Buchstaben kopieren, wobei der 
linke Teil der Variablen erhalten bleiben muss. Wenn in der Prozedur 
eben nur der nächste Buchstabe auf den rechten Platz kopiert wird und 
dann 8x geshiftet wird, dann lässt man doch geschickterweise die 
16bitVariablen global.

von Thomas S. (thomas_s72)


Lesenswert?

Nee, stimmt nicht.
Die 16bit Variable gibt es nur einmal in der Funktion (und nicht 
statisch oder global), und NICHT achtmal.
Sie wird achtmal genutzt und am Ende verworfen. Zwischendurch wird 
achtmal ein Teil ausgelesen, der ist interessant und wird in ein 
globales Array geschrieben (sollte es zumindest).
So wird ein Schuh draus.

So kann man die Funktion mehrfach nutzen und die Ergebnisse in einem 
globalen Array miteinander "verodern" so dass die geschobenen Zeichen 
gemischt werden.

von Jan H. (janiiix3)


Lesenswert?

Thomas S. schrieb:
> 1. String definieren mit den Zeichen die ausgegeben werden müssen. z.B.
> "Das ist mein Scrolltext"
>
> 2. einen Zeiger drauf definieren der das erste Zeichen adressiert.
Das müsste dann ja in der Funktion passieren? Die Zeichenkette übergebe 
ich ja schon der Funktion. Da bekommt die Funktion ja schon die Adresse 
vom ersten Buchstaben

> 3. Breite B des Zeichens berechnen, siehe Funktion oben
Das würde ich jetzt in der Font Datei hinterlegen so das ich da nichts 
mehr berechnen muss.

> 4. PrintFunktion mit scroll = 8-B fürs Zeichen beim Zeiger
Meinst du die Anzahl der Schleifendurchläufe damit?
for( scroll = ZEICHEN_BREITE - B ; scroll > 0 ; scroll--)?
> 5. scroll++

von Thomas S. (thomas_s72)


Lesenswert?

Meine Ausführungen bezogen sich auf die von mir oben gepostete Funktion

void ScrollPrint (unsigned char ZEICHEN, unsigned char scroll)

Die druckt ein Zeichen in den Bildschirmspeicher der dann anderswo 
ausgegeben wird.
Erstes Zeichen Z1 mehrfach drucken mit scroll1 laufend von 0 bis 15. Das 
läuft dann von rechts nach links durch.
Wenn scroll1 8 erreicht das zweite Zeichen Z2, wieder mit scroll2=0 bis 
15 dazu drucken. Wenn scroll1 16 wird wieder auf 0 setzen und Zeichen3 
ausgeben.


scroll = 8-B ist der Anfangswert um Lücken zu vermeiden wobei B die 
Zeichenbreite in Pixeln ist. Kann man für jedes Zeichen hinterlegen, ist 
aber aufwändig, hab ich nicht so realisiert.

Im Code den du oben gepostet hast wird immer nur ein Zeichen von rechts 
hereingeschoben, wenn es voll drin steht wird das nächste in gleicher 
Weise behandelt.
Denke nicht dass das schön läuft. Um den Srolleffekt zu haben muss man 
zwei Zeichen hintereinander drucken die beide durchschieben.

von Thomas S. (thomas_s72)


Lesenswert?

Hab deine Funktion mal angesehen, versuch mal das. String sollt emit 
einem Leerzeichen anfangen, das erste Zeichen wird erstmal voll 
gedruckt:

uint8_t ScrollPrint ( char *msg )
{
  union
  {
    unsigned int V16Bit;
    unsigned char V8Bit[2];
  } tmp;

  uint8_t scrollPos;
  uint8_t leng;
  for ( leng = 0 ; *msg != '\0' ; leng++ )
  {
    for ( scrollPos = 8 ; scrollPos < 16 ; scrollPos++ )
    {
      for( uint8_t i = 0 ; i < 8 ; i++ )
      {
        //Zeichen n
        tmp.V16Bit  =  0xFF & ~pgm_read_byte(&charMap[ 
GetCharacterIndex( *msg ) ][i]);
        tmp.V16Bit  = tmp.V16Bit << scrollPos; // nach links verschieben
        VRAM[i]    = tmp.V8Bit[1]; // linke Seite ausgeben

        //Zeichen n+1
        tmp.V16Bit  =  0xFF & ~pgm_read_byte(&charMap[ 
GetCharacterIndex( *(msg +1)) ][i]);
        tmp.V16Bit  = tmp.V16Bit << scrollPos-8; // nach links 
verschieben
        VRAM[i]    &= tmp.V8Bit[1]; // linke Seite ausgeben

      }
      _delay_ms(250);
    }
    msg++;
  }

  return leng;
}

von Jan H. (janiiix3)


Lesenswert?

Thomas S. schrieb:
> Hab deine Funktion mal angesehen, versuch mal das. String sollt emit
> einem Leerzeichen anfangen, das erste Zeichen wird erstmal voll
> gedruckt:

So wird der ganze Text nur bis in die Mitte geschoben und hört dann 
auf..

von Jan H. (janiiix3)


Lesenswert?

Thomas S. schrieb:
> VRAM[i]    &= tmp.V8Bit[1]; // linke Seite ausgeben

Hast du diese verODERUNG eingebaut oder war die noch von mir?

von Thomas S. (thomas_s72)


Lesenswert?

Das habe ich eingebaut. Die zwei Zeichen werden ja "gemischt".
Also funktioniert das erst mal, aber nur bis zur Mitte des Textes?

Also "Hallo das ist mein Text" wird nur als "Hallo das ist" angezeigt?

Oder wie verstehe ich das?

von Thomas S. (thomas_s72)


Lesenswert?

Und die Schleife würde ich eher so definieren:

for (leng = 0; leng < strlen(msg); leng++)

damit läuft man bis zum vorletzten Zeichen und nimmt dann mit msg+1 das 
letzte noch mit.

von Thomas S. (thomas_s72)


Lesenswert?

muss wohl doch eher einer weniger sein..

for (leng = 0; leng < strlen(msg)-1; leng++)

von Jan H. (janiiix3)


Lesenswert?

Also wenn ich das letzte Zeichen "verODER" klappt nichts. Wird also 
nichts angezeigt.
Ohne das "ODER" klappt es.

Das Zeichen wird direkt in der Mitte vom Display gedruckt und nach links 
herraus geschoben.
Es kommt nichts von rechts rein. Am besten muss ich noch mal ein Video 
davon machen.
1
  
2
uint8_t ScrollPrint ( char *msg )
3
{
4
  union
5
  {
6
    unsigned int V16Bit;
7
    unsigned char V8Bit[2];
8
  } tmp;
9
10
  uint8_t scrollPos;
11
  uint8_t leng;
12
  for ( leng = 0 ; *msg != '\0' ; leng++ )
13
  {
14
    for ( scrollPos = 8 ; scrollPos < 16 ; scrollPos++ )
15
    {
16
      for( uint8_t i = 0 ; i < 8 ; i++ )
17
      {
18
        //Zeichen n
19
        tmp.V16Bit =  0xFF & ~pgm_read_byte(&charMap[GetCharacterIndex( *msg ) ][i]);
20
        tmp.V16Bit = tmp.V16Bit << scrollPos; // nach links verschieben
21
        VRAM[i]    = tmp.V8Bit[0]; // linke Seite ausgeben
22
23
         //Zeichen n+1
24
         tmp.V16Bit =  0xFF & ~pgm_read_byte(&charMap[GetCharacterIndex( *(msg +1)) ][i]);
25
         tmp.V16Bit = tmp.V16Bit << (scrollPos-8); // nach links verschieben
26
         VRAM[i]    = tmp.V8Bit[0]; // linke Seite ausgeben
27
      }
28
      _delay_ms(150);
29
    }
30
    msg++;
31
  }
32
33
  return leng;
34
}

von Michael K. (tschoeatsch)


Lesenswert?

Ich verstehe eure ganzen Aktionen nicht. Nehmt halt für die Ausgabe beim 
Multiplexen einfach 8 16bit Variablen (global) und gebt die linken bits 
an die Leds aus. Jetzt muss man zum scrollen doch nur die 8 Variablen 
nach link shiften. Und wenn ein Buchstabe in das Sichtbare rein scrollen 
soll, dann wird der vor dem scrollen in den rechten Teil der 8 Variablen 
reinkopiert. Nach 8x shiften ist jetzt der sichtbar und das Vorherige 
ist links aus dem Sichtbaren heraus getickert. Jetzt wird in den rechten 
Teil der nächste Buchstabe rein kopier und so weiter. Ist doch simpel.

: Bearbeitet durch User
von georg (Gast)


Lesenswert?

Michael K. schrieb:
> und so weiter. Ist doch simpel.

Das ist nicht nur simpel sondern sogar verständlich. Aber nach dem 
bisherigen Verlauf des Threads ist das für die Beteiligten definitiv ZU 
simpel.

Georg

von Jan H. (janiiix3)


Lesenswert?

georg schrieb:
> Michael K. schrieb:
>> und so weiter. Ist doch simpel.
>
> Das ist nicht nur simpel sondern sogar verständlich. Aber nach dem
> bisherigen Verlauf des Threads ist das für die Beteiligten definitiv ZU
> simpel.
>
> Georg

In Sachen Kreativität bist du definitiv nicht zurückgeblieben!

von georg (Gast)


Lesenswert?

Jan H. schrieb:
> In Sachen Kreativität bist du definitiv nicht zurückgeblieben!

Doch, für mich gilt immer noch KISS. Kreativ im Sinne von möglichst 
komplizierten Lösungen für einfache Probleme will ich garnicht sein, ich 
finde gute Ingenieurskunst besteht gerade aus dem Gegenteil. Aber jeder 
nach seinem Geschmack.

Georg

von Jan H. (janiiix3)


Lesenswert?

Wenn ich wüsste wie ich es lösen könnte, würde ich hier nicht weiter 
fragen.
Bekomme es aktuell noch nicht hin.

von Michael K. (tschoeatsch)


Lesenswert?

War mein Vorschlag so unverständlich? Erweitere deine Ledmatrix virtuell 
um 8 Spalten nach rechts. Ein byte ist doch bei dir 8 Leds in einer 
Zeile. Jetzt häng rechts an das byte noch eins drann, dann wäre die 
Zeile 16 Leds breit. Diese 2 bytes fasst du zu einer 16bitVariable 
zusammen. Deine Multiplexroutine verwendet aber nur die linken bits, um 
8 Led in einer Zeile anzusteuern. Jetzt kopierst du in die rechten 8bit 
das byte einer Zeile des Buchstabens. Und das für alle 8 Zeilen. Als 
nächster Schritt werden die 16bitVariablen nach links und schon wird 
Spalte für Spalte des Buchstabens sichtbar. Sieht man den komplett, wird 
der nächste Buchstabe rechts hin kopiert und weiter nach links 
geshiftet...

von Stefan F. (Gast)


Lesenswert?

Ich glaube das bringt nichts. Diese Aufgabe überfordert den TO.

von Michael K. (tschoeatsch)


Lesenswert?

Ich kann halt kein C und basic wird nicht groß weiter helfen. Im basic 
gibt's halt mit overlay eine einfache Möglichkeit, 16bit auf 
2x8bit-Variablen zu verteilen (eine Speicherzelle im ram hat 2 Namen), 
dann könnte man ein byte zum Multiplexen verwenden und ins ander kommt 
eine Zeile vom Buchstaben. Zum shiften nimmt man dann die 16bit, weil's 
einfacher ist. Aber sowas muss es doch bei C auch geben.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> und basic wird nicht groß weiter helfen

Wieso? Es gibt doch Bascom.

> Aber sowas muss es doch bei C auch geben.

Sicher, auch in C kannst du hin und her schieben. Und auch in C kann man 
zwei Bytes wahlweise als 2x8bit oder 1x16bit ansprechen. DU musst halt 
mal die Grundlagen der Programmiersprache lernen. Am Besten auf dem PC, 
nicht auf einem Mikrocontroller.

Aber wenn du besser Basic kannst, dann bleibe doch dabei!

von Michael K. (tschoeatsch)


Lesenswert?

Ich hab' ja auch nicht vor zu wechseln, ich bin mit bascom sehr 
zufrieden. Nur, wenn ich Jan ein bascom-Beispiel zeige, wird's nicht 
viel nützen. Deswegen versuche ich es mit Prosa.

von Stefan F. (Gast)


Lesenswert?

Ach so, ich hatte dich mit Jan verwechselt.

von Jan H. (janiiix3)


Lesenswert?

Stefanus F. schrieb:
> Ach so, ich hatte dich mit Jan verwechselt.

Das hat doch überhaupt nichts mit den Grundlagen zu tun. Mir fehlt 
lediglich die genaue Vorgehensweise wie ich das bewältigen muss. Die 
Logik erschließt sich mir noch nicht so 100% ig.

von Michael K. (tschoeatsch)


Lesenswert?

Mit bascom kriegt man schöne scrolleffekte hin
https://youtu.be/hZpoGnXdOWM (ok, hier verwende ich Matrixmodule mit 
max7219, aber das betrifft ja nur das Multiplexen)
das wird mit C genauso gehen.

von Jan H. (janiiix3)


Lesenswert?

Inzwischen klappt es schon einigermaßen.
1
void DisplayString( const char *s)
2
{
3
  uint16_t len;
4
  uint8_t i, d, u1, u2;
5
  
6
  len = strlen(s)*8;
7
  
8
  for (uint16_t x = 0 ; x < len ; x++ )
9
  {
10
    i = x >> 3; // Index vom ersten Zeichen
11
    u1 = GetCharacterIndex(s[i++]); // erstes Zeichen
12
    u2 = GetCharacterIndex(s[i]);  // zweites Zeichen
13
    for (d=0 ; d<16 ; d++)
14
    {
15
      VRAM[d] = 0xFFFF;
16
      VRAM[d] &= ~(pgm_read_byte(&charMap[u1][d]) << (( x & 7 )) ); // erstes Zeichen verschoben nach links
17
      VRAM[d] &= ~(pgm_read_byte(&charMap[u2][d]) >> ( 8 - ( x & 7 )) );  // zweites Zeichen verschoben nach rechts
18
    }  
19
    _delay_ms(80);  
20
  }
21
}

Was jetzt noch fehlt ist der Abstand zwischen den einzelnen Zeichen. 
Weiß absolut nicht wie ich das mit berechnen soll.

von Michael K. (tschoeatsch)


Lesenswert?

Jan H. schrieb:
> Mir fehlt lediglich die genaue Vorgehensweise wie ich das bewältigen
> muss. Die Logik erschließt sich mir noch nicht so 100% ig.

Neuer Versuch:
8 16bitVariablen, denke sie dir binär und untereinander angeordnet. 
Jetzt hast du einen bit-Raster, 8bit hoch und 16 bit breit. Jetzt 
gestaltest du dein Multiplexing so, dass du die linke Hälfte von dem 
Raster an deine Leds ausgibst. Jetzt kopierst du in die rechte Hälfte 
die Daten des Buchstabens rein. Wenn du jetzt diese 8 16bitVariablen 
nach links shiftest, dann werden nach und nach die rechten bits in den 
Bereich wandern, die auf den Leds sichtbar sind. Wenn du 8x shiftest 
sind alle bits der rechten Hälfte nach links gewandert, der Buchstabe 
jetzt voll sichtbar. Jetzt ist der Zeitpunkt da, in die nunmehr leere 
rechte Hälfte die Daten des nächsten Buchstabens zu kopieren und das 
shiften geht weiter.
Was ich so von deinem Programm verstanden hab', du packst zuviel in eine 
Schleife. Das rein kopieren des Buchstabens ist eine Schleife und da 
passiert nix weiter. Das 8malige shiften ist eine weitere Schleife und 
da passiert außer dem Multiplexen auch nix weiter.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.