Hi
Nebenschauplatz - ich bin noch an meinem Dot-Display am Schrauben.
Das Display besteht aus 4 Stk 8x8 DOT-Matrix-LED-Elementen (fertig verlötet vom freundlichen China-Mann, bin damit auch zufrieden).
Aktuell möchte ich die Bits meines 5x5-Zeichensatz 'umdrehen', da ich die Zeichen 'falsch herum' rein schieben muß, damit ich die nicht sichtbaren LED-Elemente 'rechts' vom Feld habe.
In C scheint es dafür keine Funktion zu geben - in Assembler ist's dagegen ein Klacks. (die Bits aus dem einen Register nach links raus- und in eine anderes Register von links rein-schieben)
11000000 -> 00000011
Etwas eingelesen und ein Beispiel zu Inline-Assembler gefunden:
Thread im Arduinoforum.de
Weiter brauchte ich noch Pointer (da die Variablen für Funktionen kopiert werden ... ich aber die Variable selber ändern will).
Dafür fand ich dieses PDF, recht lehrreich:
Pointers_in_Arduino
Beides zusammen geworfen, etwas Abgekupfert, heraus kam:
//...
void serialbin(unsigned int var, byte stellen); //gibt Zahl in BIN aus
void mirrorbits(byte &zeichenbyte); //spiegelt die Bits eines Byte-Wert, der Pointer auf die Variable wird übergeben (das & muß beim Aufruf mit übergeben werden)
byte mirrorwert; //global, da örtlich MIT Assembler nicht klappt
//...
void setup() {
Serial.begin(9600);
//***********************************
//Testen der Assembler-Mirror-Funktion
byte x = 0;
byte save = 0;
while (1) {
Serial.print("X=");
serialbin(x,8);
//Serial.print(x, BIN);
save = x;
mirrorbits(&save);
Serial.print("<->");
//Serial.println(save, BIN);
serialbin(save,8);
Serial.println();
x++;
}
}
void loop(){
}
void mirrorbits(byte *zeichenbyte) { //spiegelt die Bits eines Byte-Wert
// byte wert; //erstellen die Variable global, da sonst das Rückschreiben nicht funktioniert (die Variable gibt es nach dem STS nicht mehr ?!?)
mirrorwert = *zeichenbyte;
//hier Inline-ASM zum Byte spiegeln
//Serial.print (" ");
//Serial.print (mirrorwert);
asm volatile ("push r30 \n\t"
"push r31 \n\t"
"lds r30,(mirrorwert) \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
"rol r30 \n\t"
"ror r31 \n\t"
//"clr r30 \n\t"
"sts (mirrorwert),r31 \n\t"
"pop r31 \n\t"
"pop r30 \n\t"
);
Serial.print ("->");
//Serial.print (mirrorwert);
// Serial.print (" ");
*zeichenbyte = mirrorwert;
}
void serialbin(unsigned int var, byte stellen) {
int vartest = pow(2, stellen - 1) + 1; //2 ^ (stellen - 1); //128;
/*
Serial.print("Stellen ");
Serial.print(stellen);
Serial.print("Grenze:");
Serial.print(vartest);
Serial.print(" Wert:");
Serial.print(var);
Serial.println();
*/
while (vartest > var and vartest > 1) {
Serial.print ("0");
vartest = vartest >> 1;
}
// Serial.println();
Serial.print (var, BIN);
}
Die Funktion mirrorbits nimmt einen Pointer entgegen, liest den Inhalt aus, übergibt Diesen an die Assembler-Routiene (Diese liest den Wert aus dem SRam), Diese schiebt die Bits nach links raus (ins Carry-Flag) und schiebt Dieses (Carry-Flag) in das 2.te Register von Links wieder rein.
Die Register werden dabei zerstört (da die Bits vom Ziel-Register ebenso in das Quell-Register geschoben werden), was aber Nichts macht, da das Quell-Register nicht weiter benötigt wird.
Das Ziel-Register wird dann zurück ins SRam kopiert.
Vor der ganzen Arbeit werden die Register 30 und 31 gesichert, danach wieder zurück geholt.
Eigentlich müsste nun Alles top sein, ohne die Serial.print-Zeile bleibt aber mein geändertes Byte im Original-Zustand.
Zur Not kann ich damit leben - ist aber unschön und ich hätte gerne gewusst, was mir hier 'in die Suppe spuckt'.
Das 'clr r30' kam rein, da ich Mal ein umgedrehtes Byte bekam und Mal nicht - also noch während der Debug-Phase.
Die Register 30 und 31 nutze ich, da Diese als Z-Pointer vom µC benutzt werden und es sehr unwahrscheinlich ist, daß genau dort meine Variable liegt - wie ich heraus bekomme, welche Register 'frei' sind, fand ich noch nicht heraus.
Mit r24/r25 hatte ich teilweise seltsames Verhalten ![]()
Leider bekam ich auch keine Schleife hin - PC (program counter) kennt der Compiler nicht, wollte einen relativen Sprung 'brne PC-3' machen - wobei Labels habe ich gar nicht versucht, müsste schauen, wie ein Label beim Inline-Assembler auszusehen hat - gibt's dazu ein halbwegs bezahlbares Buch? (aus Papier, ein eBook wollte ich eigentlich nicht)
Die Funktion serialbin gibt mit ein Byte als 8-Zeichen BIN-Zahl aus, dort bekomme ich noch eine Warnung, daß ich unsigned und signed Variablen miteinander vergleiche - wird wohl dauern, bis ich Das, der Optik wegen, ausmerze.
Wer kann helfen?
Ich könnte ein Array mit einem Element erstellen, da Dieses selber den Pointer repräsentiert - muß ich Morgen Mal probieren, ob's damit besser geht - zumindest hätte ich dort nicht das Problem, daß ich erst umständlich den Pointer nutzen muß und sollte direkt auf den Inhalt zugreifen können.
MfG