Das Problem ist daß (1<<X) letztendlich im Controller 'ne Konstante ist, nämlich 2
X, bzw 'ne binäre Zahl wo alle Bits 0 sind, nur eben das X-Bit (von hinten) ist 1. Genau das ist ja der Sinn. Um hier bei den PORTs zu bleiben - das PORT-Register eines Ports legt mit seinen 8 Bits die Pegel der 8 Beine fest. dabei fängt man allerdings von rechts an, und mit 0. Das PORTA-Register ist also:
PORTA7|PORTA6|PORTA5|PORTA4|PORTA3|PORTA2|PORTA1|PORTA0
Die IDE kennt die Werte dieser Bits (auch unter den PAn-Namen die Du verwendest). PA7=7, PA6=6,...,PA0=0
Aus (1<<PA2) wird also bei der Compilierung die Konstante 2
3=8=0b00000100.
'Ne Konstante kann aber zur Laufzeit nicht variabel sein.
Wenn die Spalten an einem PORT liegen, kann man einfach das PORT-Register lesen, den Inhalt eins nach links schieben (verdoppeln), prüfen ob dabei ein Überlauf stattfand (bzw elegant das Carry addieren), und auf den Port zurückschreiben.
Wenn Die Spalten sich zwar auf mehrere PORTs verteilen, aber immerhin noch entsprechend der Zweierpotenzen sortiert sind (also die Bits 0,1,2,3,4,5,6,7) bleiben, nur eben auf unterschiedliche Ports verteilt sind, könnte es so trotzdem noch Sinn machen - stell Dir bei Deinem Code die Zuordnung der Bits im C-PORT mal genau andersrum vor, dann könntest Du das trotzdem erstmal in einem Byte (Variable) so berechnen, und dann den einen Teil (maskiert) dem einen Port zuweisen, und den anderen dem anderen.
Sonst bleibt eigentlich nur noch der Weg, das Fallweise mit case..of, oder switch oder wie das jetzt in C heißt, zu machen (letztendlich vom erzeugten Code her 8 IF..Then..).
Das andere Problem war, von der Nummer des zu setzenden Bits auf den Wert zu kommen - bei PA2 da oben eben von 3 auf 8.
Erstmal ist es sinniger, col von 0 bis 7 laufen zu lassen, das entspricht der Bitnummern. Die Variable, die dem Port (bzw den Ports) zugewiesen wird, muß also aus Col=3 8 erhalten. Wie? Steht eigentlich oben: 2
3, genauer 2
col. Ob C potenzieren kann, weiß ich nicht. Und ob C dann das Potenzieren von 2 effizient umsetzt, weiß ich auch nicht. Ich würde also (um die ISR schnell zu halten) quasi einen 2ten Zähler (Variable) verwenden, der aber nicht inkrementiert, sondern sich verdoppelt. (Wo dann wieder die Frage steht, ob man in C logisch schieben kann (LSL))
Also einen inkrementierenden Zähler für die Adressen im VRAM, und einen potenzierenden (schiebenden) für die Bitnummern im Ausgabeport. Klar kann man auch aus einem den anderen berechnen, aber meiner Meinung nach sind 2 getrennte Zähler schneller als die Rechnung. Der 2te Zähler ist ja dann immer das, was Du in den (ggf kombinierten) Port schreiben mußt. An welchen der beiden Zähler Du jetzt die Kontrolle "achte Spalte fertig?" nagelst, ist egal. Wäre jetzt also folgender Pseudocode in der ISR:
Code:
alle Spalten aus
col inkrementieren
Potenzzähler verdoppeln (in ASM linksschieben, in C ?)
wenn der dabei Überläuft, col und Potenzzähler zurücksetzen
VRAM[col] auf die Zeilen
Potenzzähler auf den Spaltenport
Bei kombinierten Ports halt 2 Zuweisungen mit den je Maskierten Anteilen des Potenzzählers.
Die untersten 3 nach PortB, die obersten 5 nach PortC. In C wären das dann zwei Einzeiler, in etwa so:
PortB wird zugewiesen ((Maske mit B2, B1, B0) bitweises AND (Potenzzähler))
PortC analog...
"wird zugewiesen" ist wegen der restlichen Bits der Ports eine RMW-Zuweisung, aus dem scheinbar kurzen Einzeiler wird also in Wirklichkeit etwas in der Art:
Potenzzähler in ein Rechenregister laden
Port in ein anderes
Im Port die Bits der Maske löschen (ANDI PortRechenregister, ~Maske)
Potenzzähler und Maske verANDen (ANDI Potenzzählerregister, Maske)
Beide verANDen (AND Portrechenregister, Potenzzählerregister)
Ergebnis dem Port zuweisen.
Das siehst Du in C natürlich nicht,in ASM würde man das aber selbst schreiben, und könnte im konkreten Fall hier und da optimieren (konkret weiß ich, daß die Bits im Portregister (Maske) bereits gelöscht sind, das war ja der erste Schritt in der ISR, zum verdoppeln (potenzieren) des Potenzzählers wurde selbiger natürlich auch schon in ein Rechenregister geladen, und hinterher zurückgeschrieben - In ASM könnte ich da das nochmalige laden sparen. )