Es kam hier zwar bestimmt schon ein paarmal vor, aber die Suche brachte kein Ergebnis. Wie ändere ich am einfachsten die Bitreihenfolge in C ? In Assembler ist es klar: Die Bits der Reihe nach nach rechts schieben, aber mit einem Linksshift wieder auffangen. Bei dem dummen BMP Format ist alles genau anderst rum: Es wird von unten nach oben gespeichert. Mikrocontroller ist ein M16C.
Wenn es schnell gehen soll und 256 Byte Platz vorhanden sind: konstantes byte-Array[256] anlegen mit den verdrehten Werten: msb_to_lsb[256] = {0x00,0x80,0x40,0xc0 ...}; Im Programmablauf dann den Wert, der gedreht werden soll, als Index der Tabelle verwenden: my_erg = msb_to_lsb[my_byte]; Beim M16C hast Du ja genügend Flash, dass die 256 nicht weh tun, und zur Laufzeit schneller geht es wohl kaum. Stefan
Habe die Tabelle, die ich mal benutzt habe, gefunden. Ist zwar in Assembler, aber nach C müuss nur wenig geändert werden: spiegeltab db 0,128, 64,192, 32,160, 96,224 db 16,144, 80,208, 48,176,112,240 db 8,136, 72,200, 40,168,104,232 db 24,152, 88,216, 56,184,120,248 db 4,132, 68,196, 36,164,100,228 db 20,148, 84,212, 52,180,116,244 db 12,140, 76,204, 44,172,108,236 db 28,156, 92,220, 60,188,124,252 db 2,130, 66,194, 34,162, 98,226 db 18,146, 82,210, 50,178,114,242 db 10,138, 74,202, 42,170,106,234 db 26,154, 90,218, 58,186,122,250 db 6,134, 70,198, 38,166,102,230 db 22,150, 86,214, 54,182,118,246 db 14,142, 78,206, 46,174,110,238 db 30,158, 94,222, 62,190,126,254 db 1,129, 65,193, 33,161, 97,225 db 17,145, 81,209, 49,177,113,241 db 9,137, 73,201, 41,169,105,233 db 25,153, 89,217, 57,185,121,249 db 5,133, 69,197, 37,165,101,229 db 21,149, 85,213, 53,181,117,245 db 13,141, 77,205, 45,173,109,237 db 29,157, 93,221, 61,189,125,253 db 3,131, 67,195, 35,163, 99,227 db 19,147, 83,211, 51,179,115,243 db 11,139, 75,203, 43,171,107,235 db 27,155, 91,219, 59,187,123,251 db 7,135, 71,199, 39,167,103,231 db 23,151, 87,215, 55,183,119,247 db 15,143, 79,207, 47,175,111,239 db 31,159, 95,223, 63,191,127,255 Stefan
Danke, die Idee ist gut. Ich hatte bisher die Idee das ganze Harwaremäßig über den Datenbus zu machen: Daten an eine bestimmte Adresse senden, dort befindet sich ein Latch, dessen Ausgang in umgedrehter Folge mit den den Eingängen verbunden ist. Liest man den Wert, hat er eine umgedrehte Bitfolge.
Mir ist das auch son passiert: PortB mit Eagle an 8 Solidstate-Relias, von da auf den Steckverbinder geroutet und nun war der PortB0 der 8te ausgang. Das Workaround sah dann ( in FastAVR ) so aus: Die Variablen sind vorab Global definiert. Function bitswap(b_in As Byte) As Byte wrong_in = b_in For xx= 8 To 1 Step -1 Shift(Left,1,wrong_in) Shift(Right,1,ok_out) k = wrong_in And &h0100 If k = &h0100 Then ok_out =ok_out + 128 End If k = 0 Next xx Return ok_out End Function Gruß Axel
Hatte mit ähnlichem Problem auch schon durch einen Layoutfehler zu kämpfen. Da war aber nur der halbe Datenbus verdreht. Das Workaround sah bei mir etwa so aus: neu = ((alt&&128)>>7)||((alt&&64)>>5)||((alt&&32)>>3)||((alt&&16)>>1)||((alt&& 8)<<1)||((alt&&4)<<3)||((alt&&2)<<5)||((alt&&1)<<7) Codesparend, aber natürlich langsamer. Gruß, Markus_8051
Es gibt dafür ein bekanntes Makro (u. a. beim Programm fortune dabei) mit logarithmischer Zeitkomplexität: // reverse (mirror) u32 number n #define mc_REVERSE(n) \ {\ n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); \ n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); \ n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); \ n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); \ n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); \ } Wie man das auf 8 Bit reduziert oder 128 Bit Zahlen ausbaut, ist offnsichtlich.
Allerdings bringt das Makro (so genial wie's auch ist) bei 8 Bit praktisch keinen Vorteil mehr gegenüber der expliziten Schleife. (Been there, done that. Das Thema kommt regelmäßig hoch.)
Markus_8051: sollte es nicht besser statt neu = ((alt&&128)>>7)||((alt&&64)>>5)||((alt&&32)>>3)||((alt&&16)>>1)||((alt&& 8)<<1)||((alt&&4)<<3)||((alt&&2)<<5)||((alt&&1)<<7) neu = ((alt&128)>>7)|((alt&64)>>5)|((alt&32)>>3)|((alt&16)>>1)|((alt&8)<<1)|(( alt&4)<<3)|((alt&2)<<5)|((alt&1)<<7) heißen? Hoch lebe der M16C und der M32C!
sieht hier einer durch?... muss bei dem ganze hin und hergeschiebe nicht die augangsvariable "alt" irgentwo gesichert werden? wenn die sagen ((alt&128>>7) dann schiebt er, so habe ich das jetzt nach langem mangala lesen erkannt, das höchste bit 7 mal nach rechts. was aber, wenn da schon ein bit steht? ganz hinten steht in der zeile: alt&1<<7rüber. da steht doch jeztzt das bit drinne, was eben noch gaanz links stand. Ich mein, wenn ich zwei sachen über Cut and Paste tauschen will, muss ich das "linke" Teil erstmal wo ablegen, dann das "rechte" Teil dahin packen, wo das "linke" stand, und erst jetzt kann ich das "linke" teil aus der Ablage nehmen und zum "rechten" packen. Das machte ihr hier alles so in einer Zeile auf einen Rutsch? Kein Wunder, wenn mein Windows sich ständig weghängt.hihi ;-))) Schönen Feierabend, bis morgen Axel
alt bleibt immer gleich, weil ihm ja nichts zugewiesen wird. neu wird über die 8 ORs bitweise zusammengebaut: (&128)>>7 alt-Bit 7 nach neu-Bit 0 (& 64)>>5 alt-Bit 6 nach neu-Bit 1 (& 32)>>3 alt-Bit 5 nach neu-Bit 2 (& 16)>>1 alt-Bit 4 nach neu-Bit 3 (& 8)<<1 alt-Bit 3 nach neu-Bit 4 (& 4)<<3 alt-Bit 2 nach neu-Bit 5 (& 2)<<5 alt-Bit 1 nach neu-Bit 6 (& 1)<<7 alt-Bit 0 nach neu-Bit 7 wenn ich zwei sachen über Cut and Paste tauschen will Hier wird ja nichts in-place getauscht. was aber, wenn da schon ein bit steht? Da steht nichts, weil nicht neu (und erst recht nicht alt) modifiziert wird (z.B. alt&=), sondern es wird ein neuer Wert zugewiesen, so wie bei neu=12+34. Ist es jetzt klarer?
@Profi: Gute Frage, das eine war das bitweise, das andere das logische UND. Hier muß natürlich das bitweise hin. Frag mich aber nicht, ob das jetzt & oder && war. Gleiches gilt natürlich auch für das ODER.
jetzt hab' ichs verstanden, vielen Dank. ich werde bei meinem "Compiler" auch mal probieren... Viele Grüße Axel
Noch eine Variante: Es empfiehlt sich, für alt und neu register-Variablen zu verwenden. register int alt,neu; neu = (alt&128) >>1 ; //alt-Bit 7 nach neu-Bit 6 neu |= (alt=<1) &128; //alt-Bit 6 nach neu-Bit 7 neu =>1; //neu-Bit 6&7 nach neu-Bit 5&6 neu |= (alt=<1) &128; //alt-Bit 5 nach neu-Bit 7 neu =>1; //neu-Bit 5-7 nach neu-Bit 4-6 neu |= (alt=<1) &128; //alt-Bit 4 nach neu-Bit 7 neu =>1; //neu-Bit 4-7 nach neu-Bit 3-6 neu |= (alt=<1) &128; //alt-Bit 3 nach neu-Bit 7 neu =>1; //neu-Bit 3-7 nach neu-Bit 2-6 neu |= (alt=<1) &128; //alt-Bit 2 nach neu-Bit 7 neu =>1; //neu-Bit 2-7 nach neu-Bit 1-6 neu |= (alt=<1) &128; //alt-Bit 1 nach neu-Bit 7 neu =>1; //neu-Bit 1-7 nach neu-Bit 0-6 neu |= (alt=<1) &128; //alt-Bit 0 nach neu-Bit 7 Vorteil ist hier, dass immer nur um EIN Bit geschoben wird, und das bei den meisten uC (außer sie haben einen Barrel-Shifter) schneller geht als Schieben um mehrere Bits. Da ich im Urlaub bin und hier keinen Compiler installiert hab, kann ich es nicht ausprobieren, vor allem ob alt=<1 nicht als kleiner gleich compiliert wird. Ich meine natürlich alt um eins nach links schieben. Hier wird eine Besonderheit von C ausgenutzt, nämlich dass eine Zuordung selbst als Wert verwendet werden kann. neu |= (alt=<1) &128; ist eine Kurzschreibweise für alt=<1; neu |= alt &128; Das ist auch der Grund, warum z.B. if (i=8) {....} syntaktisch richtig ist. Der Variablen i wird 8 zugewiesen und dann ist die if-Abfrage if (8) {....} natürlich immer true. In diese gemeine Falle ist wohl jeder schonmal getappt. Gute Compiler fragen natürlich, ob es nicht besser if (i==8) {....} heißen soll.
In Assembler wäre das simples "Loop-Unrolling", statt schleife also LSR Input ROL Output LSR Input ROL Output LSR Input ROL Output LSR Input ROL Output LSR Input ROL Output LSR Input ROL Output LSR Input ROL Output LSR Input ROL Output oder eben einfach LDI Counter, 8 Loop: LSR Input ROL Output DEC Counter BRNE Loop Gruß hagen
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.