Wie ist es möglich aus 2 Bytes ein Byte zu gewinnen, indem jedes zweite Bit ausgelassen wird. Als Controller habe ich den ATTiny2313. Kennt jemand einen schnellen Algorithmus? Byte 0 Byte 2 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 Neues Byte 7 5 3 1 7 5 3 1
Möglicherweise wäre ein Beispiel, mit zwei signifikant unterschiedlichen Bytes, nicht verkehrt.
Wenn 256 Bytes Platz im Flash ist, kann man eine Tabelle verwenden: neues_byte = (table[byte0] << 4) + table[byte2]; Das Schieben könnte man auch noch einsparen, wenn man nochmal 256 Bytes Flash spendiert.
Uwe B. schrieb: > (byte0 & 0xcc) | (byte1 & 0x66) Das ist falsch, die Bits werden abwechselnd geschoben, oder hab ich da was übersehen?
bst Byte2, 7 bld Byte0, 7 bst Byte2, 5 bld Byte0, 6 bst Byte2, 3 bld Byte0, 5 bst Byte2, 1 bld Byte0, 4 bst Byte1, 7 bld Byte0, 3 bst Byte1, 5 bld Byte0, 2 bst Byte1, 3 bld Byte0, 1 bst Byte1, 1 bld Byte0, 0
Fridel schrieb: > Byte 0 Byte 2 > 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 > > Neues Byte > 7 5 3 1 7 5 3 1 Byte A a7 a6 a5 a4 a3 a2 a1 a0 Byte B b7 b6 b5 b4 b3 b2 b1 b0 Neues Byte a7 a5 a4 a3 a1 b7 b5 b3 b1 Das geht nicht einfach, da must du jedes Bit manuell an die richtige Stelle schieben: Wolfgang R. schrieb: > neues_byte = byte0&0x80 + ((byte0&0x20)<<2) + ((byte0&0x08)<<4) + ...
Karl M. schrieb: > Naja, > > Neues Byte > a7 a5 a4 a3 a1 b7 b5 b3 b1 > > sind neu Bits... lass a4 weg, dann passt es :-)
@ Wolfgang Das Prinzip funktioniert. Verschlingt allerdings 50 Bytes.
1 | nb = (b0 & 0x80) |
2 | + ((b0 & 0x20) << 1) |
3 | + ((b0 & 0x08) << 2) |
4 | + ((b0 & 0x02) << 3) |
5 | + ((b1 & 0x80) >> 4) |
6 | + ((b1 & 0x20) >> 3) |
7 | + ((b1 & 0x08) >> 2) |
8 | + ((b1 & 0x02) >> 1); |
Der Lookup-Table verschlingt vermutlich mehr... ;-) Dafür ist er deutlich schneller.
Wolfgang R. schrieb: > Der Lookup-Table verschlingt vermutlich mehr... ;-) Dafür ist er > deutlich schneller. Man könnte ja noch auf Assembler umsteigen. Das obige Beispiel von Knut werde ich mir auch noch ausprobieren.
die bst/bld-Lösung ist schön. Da lohnt die Tabelle höchstens noch, wenn's wirklich auf jeden Takt ankommt.
Keine Ahnung :-)
1 | ; result in R0, byte 1 in R1, byte 2 in R2 |
2 | ; destroys R1 and R2 ! 22 CLKs! |
3 | |
4 | rol R1 ; bit to carry |
5 | rol R0 ; carry to result |
6 | |
7 | rol R1 ; skip one bit |
8 | rol R1 ; bit to carry |
9 | rol R0 ; carry to result |
10 | |
11 | rol R1 ; skip one bit |
12 | rol R1 ; bit to carry |
13 | rol R0 ; carry to result |
14 | |
15 | rol R1 ; skip one bit |
16 | rol R1 ; bit to carry |
17 | rol R0 ; carry to result |
18 | |
19 | rol R2 ; bit to carry |
20 | rol R0 ; carry to result |
21 | |
22 | rol R2 ; skip one bit |
23 | rol R2 ; bit to carry |
24 | rol R0 , carry to result |
25 | |
26 | rol R2 ; skip one bit |
27 | rol R2 ; bit to carry |
28 | rol R0 ; carry to result |
29 | |
30 | rol R2 ; skip one bit |
31 | rol R2 ; bit to carry |
32 | rol R0 ; carry to result |
beric schrieb: > Keine Ahnung :-) Stimmt, hast du nicht. > 22 CLKs! Und was soll daran besser sein als die 16 Ticks der bld/bst-Lösung?
Hallo, ernsthafte Frage (ganz ohne Ironie): Fridel, wofür soll das gut sein? Was kommt da heraus ausser das ein Byte verschwindet - steckt da irgendeine clevere Logik dahinter? mfg C-Beginner
In C (mit AVR-Builtin __builtin_avr_insert_bits):
1 | #include <stdint.h> |
2 | |
3 | uint8_t oddbits(uint8_t byte0, uint8_t byte2) { |
4 | byte0 = __builtin_avr_insert_bits (0x7531ffff, byte0, byte0); |
5 | byte0 = __builtin_avr_insert_bits (0xffff7531, byte2, byte0); |
6 | return byte0; |
7 | }
|
Das ergibt:
1 | oddbits: |
2 | mov r0,r24 |
3 | bst r0,1 |
4 | bld r24,4 |
5 | bst r0,3 |
6 | bld r24,5 |
7 | bst r0,5 |
8 | bld r24,6 |
9 | bst r22,1 |
10 | bld r24,0 |
11 | bst r22,3 |
12 | bld r24,1 |
13 | bst r22,5 |
14 | bld r24,2 |
15 | bst r22,7 |
16 | bld r24,3 |
17 | ret |
Yalu X. schrieb: > In C (mit AVR-Builtin __builtin_avr_insert_bits): [...] D.h.: Mit der doch recht speziellen Kenntnis einer einzigartigen Besonderheit des AVR-GCC kann man in C immerhin (nicht ganz) die Performance erreichen, die in Assembler möglich ist, wenn man einfach nur die rund hundert simplen Instruktionen des AVR kennt und beherrscht (statt der hunderte Seiten füllenden Details von C an sich und der weitere hunderte Seiten füllenden Beschreibungen eines speziellen Compilers bezogen auf ein spezielles Target-System)? Außerdem: Sollten die angeblich doch so hocheffizent optimierenden C-Compiler nicht einfach alleine herausfinden können, wann der Einsatz der spezialisierten Macros sinnvoll wäre? Algorithmisch sehe ich da jedenfalls kein Problem. Es muß also wohl daran liegen, dass die Compiler doch nicht so gut sind, wie die C-Apologeten immer behaupten, dass sie es wären...
> D.h.: Mit der doch recht speziellen Kenntnis einer einzigartigen > Besonderheit des AVR-GCC kann man in C immerhin (nicht ganz) die > Performance erreichen, ... Deinem Beitrag entnehme ich, dass es in Assembler noch besser umzusetzen ist (kürzer?, schneller?). Kannst du ein Programm posten?
Das von Knut Ballhause. Wenn man wie Yalu X. ein Quellbyte mit dem Zielbyte überschreibt, dann kann man Byte0 durch Byte2 ersetzen, die ersten beiden Zeilen weglassen, und ist bei 14 Takten.
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.