ich schrieb:> PORTx.OUTTGL = 0xFF; (alle Bits im Ausgangsregister toggeln)Christian W. schrieb:> Werden immer die selben Bits invertiert?> Dann z.B. mit einer Bitmaske!Stephan schrieb:> CPL
An alle drei: Thema verfehlt.
Lest mal, was
hugo schrieb:> Also aus 11101010 mach 01010111
Lothar Miller schrieb:> Lest mal, was> hugo schrieb:>> Also aus 11101010 mach 01010111
hugo schrieb aber auch:
> Wie kann man am besten so "mal eben" ein Bit invertieren, um es so an> einem Port auszugeben?!
Offensichtlich weiß er selbst nicht was er will und weiß auch nicht was
ein Bit und was ein Byte ist.
J.-u. G. schrieb:> Offensichtlich weiß er selbst nicht was er will und weiß auch nicht was> ein Bit und was ein Byte ist.
Das geht offenbar vielen so, die das nicht wissen... ;-)
Nochmal der Link zur Suche, da sind auch ein paar solcher Kandidaten:
> Lothar Miller schrieb:>> Die Suche wird dir helfen...>> http://www.mikrocontroller.net/search?query=Byte+spiegeln
Und weil er es selbst nicht weiß, was er will, es aber beschreiben kann,
gilt die Regel:
1
Es gibt 2 Arten von Menschen:
2
1. die, die auf der Basis unzureichender Information extrapolieren können
Okay, Ihr habt Recht, ich wusste nicht genau was ich wollte :D.
Also ich will das Byte natürlich Spiegeln. Und das am besten in C.
Es war gestern glaub einfach schon zu spät xD
Michael Dierken schrieb:> Warum schiebst du vor "lop" eine 1 in r16 rein?
R16 ist solange <>0 bis die 1 im Carry ist. Solange springt dann brne.
Man spart so den Schleifenzähler und ein paar Zyklen..
Sascha Weber schrieb:> Klaus schrieb:>> IMHO ist in C eine Tabelle das Schnellste.> wenn man soviel Speicher übrig hat
16 Byte reichen dafür. Die Nibbles kann man swappen.
Peter schrieb:> Folgender Code auch recht effizient compiliert...
Stimmt! Obwohl er recht lang aussieht, sind es nur 178 Byte erzeugter
Code beim avr-gcc - inkl. leerer main-Funktion:
Program: 178 bytes (1.1% Full)
Data: 0 bytes (0.0% Full)
Da habe ich das mal eben mit einer Tabelle ausprobiert:
Ergebnis:
Program: 266 bytes (1.6% Full)
Data: 16 bytes (1.6% Full)
Das Programm "sieht" zwar kürzer aus, kostet aber doch einiges mehr an
Speicherplatz...
Zuallerletzt habe ich Volkers Version getestet (mit kleinen
Modifikationen, z.B. int -> uint8_t):
1
uint8_t
2
bitsreverse(uint8_tin)
3
{
4
uint8_tout=0;
5
uint8_tloop;
6
7
for(loop=0;loop<8;loop++)
8
{
9
if(in&0x01)
10
{
11
out|=0x01;
12
}
13
in=in>>1;
14
out=out<<1;
15
}
16
return(out);
17
}
Ergebnis:
Program: 162 bytes (1.0% Full)
Data: 0 bytes (0.0% Full)
Damit liegt Volkers Version derzeit an der Spitze, was die Sparsamkeit
an Speicherplatz angeht.
Volkers Version ist etwas kürzer, dafür etwas langsamer bei der
Ausführung. Bleibt beim Anwender zu entscheiden was für ihn wichtiger
ist, Code-Size oder Code-Speed! ;o)
Lothar Miller schrieb:> Lest mal, was> hugo schrieb:>> Also aus 11101010 mach 01010111
Es geht doch nichts über einen passenden Titel. Warum sagt er dann nicht
gleich "Byte spiegeln" oder Bitfolge invertieren.
Invertieren bezogen auf ein Bit ist immer noch der Not-Operator.
Hier mal ein Zwischenstand. Der Speicherbedarf wurde ermittelt, indem
vorneweg alles mit mirror auskommentiert wurde, und danach der
Speicherplatzzuwachs festgestellt wurde (Atmega32, -Os, avr-gcc 4.3.2):
Komisch schrieb:> Es geht doch nichts über einen passenden Titel. Warum sagt er dann nicht> gleich "Byte spiegeln" oder Bitfolge invertieren.
Vielleicht, weil ihm der Begriff nicht geläufig war...
Stimmt, die habe ich hier auf µC.net auch schon öfters rumschwirren
sehen.
Ergebnis:
Program: 180 bytes (1.1% Full)
Data: 0 bytes (0.0% Full)
Das ist dann der 3. Platz... aber knapp :-)
Lothar Miller schrieb:> Hier mal ein Zwischenstand. Der Speicherbedarf wurde ermittelt, indem> vorneweg alles mit mirror auskommentiert wurde, und danach der> Speicherplatzzuwachs festgestellt wurde (Atmega32, -Os, avr-gcc 4.3.2):
Erstaunlich, was bei Dir an relativen(!) Unterschieden rauskommt. Bei
mir ist es ATmega168, -Os, avr-gcc 4.3.3.
Lothar Miller schrieb:> Lothar Miller schrieb:>> uint8_t mirror (uint8_t val) // 208 Bytes> Frank M. schrieb:>> Program: 180 bytes (1.1% Full)> Ich muß mal meinen Compiler updaten... ;-)
Da ist ein leeres main() auch mit drin. Das halte ich für legitim, da
der Compiler auch bei Nicht-Aufruf die Funktionen NICHT wegoptimieren
kann, da sie nicht als static deklariert sind. Wie ist das bei Dir?
Zählst Du Deine (aufwendigere) main-Funktion mit?
EDIT: Bei mir frisst die leere main-Funktion 138 Byte, die müsste man
also von meinen Werten abziehen. Dann sieht der 4.3.3er Compiler um
einiges besser aus als Dein 4.3.2er.
Ich glaube wir haben Hugo (TO) etwas überfordert. Er meldet sich gar
nicht mehr!
Hallo Huuuugooooo.
Konten wir dir helfen oder haben wir dich nur verwirrt?
volker
Das ist ja echt der Wahnsinn xD
Ihr ward echt seeehr krass...
Naja das ganze ist so: Ich hab ein Display und das hängt direkt an einem
Port. Aus Layout technischen Gründen müsste ich ALLE Leitungen kreuzen,
was natürlich ziemlich dumm ist. Jetzt habe ich überlegt einfach immer
das Byte zu spiegeln, damit ich es so übertragen kann. Ich denke aber
bei einem Grafik LCD ist das totaler Quatsch, da der AVR ja 2/3 seiner
Zeit nur damit verbringt Daten zu spiegeln. Da er später noch andere
Dinger erledigen soll wäre das also dumm.
Nun bin ich am Überlegen einen SMD-Stecker zu nehmen, dann kann ich die
Leiterbahnen von oben anfahren (kann Zuhause nur einseitige Platinen mit
min. 8mil Leiterbahnen).
Aber ich finde diesen Thread echt klasse! Wenn wir nun vielleicht alles
zusammenstellen und irgendwo festhalten wär das schonmal toll!
Danke euch!
Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen
für die Verarbeitung (Function Call bis Return)
Bei mirror4() habe ich den Array auf static gesetzt, dann werden dessen
Werte nur einmal im StartUpCode initialisiert und nicht bei jedem
Funktions-Aufruf. (Codesize und CPU-Zyklen für diese Initialisierung
sind nicht dabei)
Peter schrieb:> Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen> für die Verarbeitung (Function Call bis Return)
Welche avr-gcc-Version? Welche Optimierungsstufe? Wie wir gestern
gesehen haben, gibt es allein bei der Version erhebliche Unterschiede im
Ergebnis.
> Bei mirror4() habe ich den Array auf static gesetzt, dann werden dessen> Werte nur einmal im StartUpCode initialisiert und nicht bei jedem> Funktions-Aufruf.
Ohja, das hatte ich doch glatt übersehen. Damit liegt mirror4 mit der
Ausführungszeit an erster Stelle und vom Speicherplatz immerhin noch an
2. Stelle.
Interessant, dass mirror3() als kleinste Funktion auch die langsamste
ist.
Danke für die Aufstellung.
Gruß,
Frank
hugo schrieb:> Also ich will das Byte natürlich Spiegeln. Und das am besten in C.
Na, wenn nicht ausschließlich C, dann hat auch noch 'ne Bascom-Version
Platz ;D
MWS schrieb:> dann hat auch noch 'ne Bascom-Version Platz ;D> !LDS R16, {Var_In}> !BST R16, 0
Naja. Ich würde sagen, das fällt fast schon unter "Assembler-Doping"...
> 40Bytes, 20 Cycles.
Das ist jetzt aber noch keine richtige Unterroutine...
>> Peter schrieb:>>> Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen>>> für die Verarbeitung (Function Call bis Return)
hugo schrieb:> Das ist ja echt der Wahnsinn xD> Ihr ward echt seeehr krass...> Naja das ganze ist so: Ich hab ein Display und das hängt direkt an einem> Port. Aus Layout technischen Gründen müsste ich ALLE Leitungen kreuzen,> was natürlich ziemlich dumm ist. Jetzt habe ich überlegt einfach immer> das Byte zu spiegeln, damit ich es so übertragen kann. Ich denke aber> bei einem Grafik LCD ist das totaler Quatsch, da der AVR ja 2/3 seiner> Zeit nur damit verbringt Daten zu spiegeln. Da er später noch andere> Dinger erledigen soll wäre das also dumm.
Bei der Initialisierung des GLCD kann man auch entsprechende Konstante
nehmen (und das kommentieren), die Fonts zur Textausgabe lassen sich
auch vorher spiegeln/passend generieren und die Routinen zum
Pixel-Setzen/Linien-Zeichnen kann man auch passend schreiben...
Lothar Miller schrieb:> Naja. Ich würde sagen, das fällt fast schon unter "Assembler-Doping"...
Da hast Du natürlich recht, da sich aber Assembler bei Bascom äußerst
problemlos in Basic-Code einbetten lässt, so ist das legitim.
> Das ist jetzt aber noch keine richtige Unterroutine...
Das sind sie im C-Beispiel auch nicht. Nur mirror2 wird über einen CALL
aufgerufen, alles andere wird vom Compiler Inline eingebaut (mit -Os).
Und zwar wiederholt, zweimal mirror1 aufgerufen wird auch zweimal als
Inline compiliert. Wahrscheinlich weil bei der kleinen Codegröße der
Funktion der Overhead unrentabel ist.
>>>> Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen>>>> für die Verarbeitung (Function Call bis Return)
Eine Bascom-Sub, die auch tatsächlich als Sub eingebunden ist, benötigt
dann 39 Cycles, liegt daran, daß die Variablenzeiger auf den Frame
gehen/von dort geholt werden müssen.
Also die Bascom Variante von MWS (Gast) gefällt mir doch sehr.
Wie könnte ich das auf C übertragen?
Geht das in C überhaupt, Werte an Assembler zu übergeben und
zurückzubekommen?
Räuber Hotzenplotz schrieb:> Wie könnte ich das auf C übertragen?
Sollte per Inline Assembler gehen, ist aber im Vergleich zu dem
Gezeigten relativ kompliziert, der C-Compiler hat's nicht gern, wenn man
sich einmischt.
Vorteil meiner Version ist die völlig freie Bitzuweisung, somit lassen
sich einfach die Anschlüsse intern "umverdrahten".
So entstand dieser Codeteil auch, wurde in ein Lib eingebunden um
entsprechend einem anderes Platinenlayout für ein Display mit einem
I2C-Expander PCF8574 die Pins frei zuweisen zu können.
MWS schrieb:> Das sind sie im C-Beispiel auch nicht. Nur mirror2 wird über einen CALL> aufgerufen, alles andere wird vom Compiler Inline eingebaut (mit -Os).
Das schon. Aber die Aufrufparameter sind frei wählbar.
> Eine Bascom-Sub, die auch tatsächlich als Sub eingebunden ist, benötigt> dann 39 Cycles
Liegt damit annähernd gleichauf zur Lösung mirror2, wo ja auch beliebige
Bits zugeordnet werden könnten.
Lothar Miller schrieb:> Das schon. Aber die Aufrufparameter sind frei wählbar.
Wenn man Speed braucht, dann ist's egal, ob die Aufrufparameter frei
wählbar sind. Speziell für den Fall eine Pinbelegung "umzubiegen" wird
dieser Codeblock in die ausgebende Funktion eingebaut, da brauch' ich
keinen Call auf eine Funktion machen, und dann sind wir wieder bei 20
Takten. Da beißt die Maus keinen Faden ab.
Lothar Miller schrieb:> Es ging ja nicht um den Faden der Maus, sondern um die> Vergleichbarkeit... ;-)
Ja, und mir ging's um die Verwendbarkeit im Sinnes des TEs :D
Um auch das noch zu beantworten:
Räuber Hotzenplotz schrieb:> Wie könnte ich das auf C übertragen?> Geht das in C überhaupt, Werte an Assembler zu übergeben und> zurückzubekommen?
@MWS (Gast):
Ganz vielen Dank für die Mühe! :-)
: [out_reg] "=&r" (out), [in_reg] "+r" (in)
verstehe ich nicht so ganz (bin Anfänger in C )
Werde es am Montag testen, wenn ich wieder in der "Firma" bin ;-)
Hoffentlich geht das mit AVRStudio4 und WINAVR...
Ich wär so froh :-)
Räuber Hotzenplotz schrieb:> : [out_reg] "=&r" (out), [in_reg] "+r" (in)> verstehe ich nicht so ganz
Nennt sich "clobber list". Ich fand's interessant wie's dem Compiler
beizubringen ist, mach' normalerweise nichts in C-asm. Du kannst
übrigens auch mirror2 nehmen, da wird sehr schöner und kurzer Code
erzeugt. Funktional ist's gleich.