Forum: Mikrocontroller und Digitale Elektronik Bits bestrafen


von Unwissender69 (Gast)


Lesenswert?

Hallo,
ich habe ein Byte (hier Var) und möchte aufgrund der gesetzten Bits eine 
Zahl (hier Zahl) "bestrafen".

Hier z.B. ein Byte
1
unsigned char Var=0b101000;
2
//      Var=10|10|00


Und hier nun die Logik:

Zahl=0;

1. Paket (Bits 1&2 ):
Wenn die ersten beiden Bits 00, dann Zahl=Zahl+1;
Wenn die ersten beiden Bits 10, dann Zahl=Zahl+2;

2. Paket (Bits 3&4):
Wenn die zweiten beiden Bits 00, dann Zahl=Zahl+1;
Wenn die zweiten beiden Bits 10, dann Zahl=Zahl+2;

usw.

Bei dem Beispiel müsste die "Zahl" dann den Wert 5 aufweisen.
Wie kann man so etwas auf einem uController am effektivsten realisieren, 
ohne große If abfragen?


Grüße

von Sam .. (sam1994)


Lesenswert?

Unwissender69 schrieb:
> Wenn die ersten beiden Bits 00, dann Zahl=Zahl+1;
> Wenn die ersten beiden Bits 10, dann Zahl=Zahl+2;

uint8_t result = 0;
if(var & (1 << 6))
  result |= ((var >> 1) + (1 << 6)) & ((1 << 6) | (1 << 7));

Unwissender69 schrieb:
> Wenn die zweiten beiden Bits 00, dann Zahl=Zahl+1;
> Wenn die zweiten beiden Bits 10, dann Zahl=Zahl+2;

if(var & (1 << 4))
  result |= ((var >> 1) + (1 << 4)) & ((1 << 4) | (1 << 5));

Unwissender69 schrieb:
> Bei dem Beispiel müsste die "Zahl" dann den Wert 5 aufweisen.
> Wie kann man so etwas auf einem uController am effektivsten realisieren,
> ohne große If abfragen?

Ganz ohne würde ich es nicht machen. Aber eine pro Paket ist ja nicht so 
schlimm.

von Stefan (Gast)


Lesenswert?

Hat dein Byte nur 6 Bit?
Können die Bitkombinationen 01 und 11 nicht auftreten?

von Unwissender69 (Gast)


Lesenswert?

Dankeschön Samuel,
das dauert mir zu lange bei 20 Variablen. Der uC ist ja nur mit schieben 
beschäftigt.
Werde es in den Speicher legen und geeignet darauf zugreifen.


Viele Grüße

von Sam .. (sam1994)


Lesenswert?

Unwissender69 schrieb:
> Dankeschön Samuel,
> das dauert mir zu lange bei 20 Variablen. Der uC ist ja nur mit schieben
> beschäftigt.
Warum denn? Nur einmal pro Rechnung. Und wenn man diese Var >> 1 
temporär speichert ist es nur einmal schieben.
Die (1 << 4) werden vom Compiler ersetzt.

> Werde es in den Speicher legen und geeignet darauf zugreifen.
Oder meinst du das damit?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Sollen wie im Beispiel immer nur 3 Bitpaare (also die Bits 0 bis 5)
betrachtet werden?

Oder was soll bspw. mit Var=0b10101000 passieren?

Nur aus Neugier: Warum bezeichnest du das Addieren von 1 oder 2 als
"bestrafen"?

Was meinst du mit am "effektivsten"?

Unabhängig davon: Eine sehr schnelle Methode wäre eine Tabelle (Array)
mit 256 Einträgen, von denen jeder das gesamte "Strafmaß" für das
entsprechende Byte enthält.

von Sam .. (sam1994)


Lesenswert?

Ich merke gerade, dass man die if-Abfrage negieren muss.

Und wenn ich schon dabei bin. Ein bisschen optimierter:

uint8_t result = 0, x = (1 << 6), y = (1 << 6) | (1 << 7);
uint8_t varl1 = var >> 1;

do
{

  if(!(var & x))
    result |= (varl1 + x) & y;
  x = x >> 2;
  y = y >> 2;
}
while(x);


Oder in einer Anweisung:

#define mask 0b01010101
var = !(var & mask) * ((var >> 1) & mask + 1);

Ich gebe aber keine Garantie, dass das funktioniert.



Mir fällt gerade auf: Deine Idee funktioniert gar nicht: 0b10 + 2 ergibt 
einen überlauf.

von Unwissender69 (Gast)


Lesenswert?

Stefan schrieb:
> Hat dein Byte nur 6 Bit?

Ja, die restlichen Bits werden nicht betrachtet.

Stefan schrieb:
> Können die Bitkombinationen 01 und 11 nicht auftreten?

01 kann auftreten, ist aber ein don't care und 11 tritt nicht auf.

Yalu X. schrieb:
> Sollen wie im Beispiel immer nur 3 Bitpaare (also die Bits 0 bis 5)
> betrachtet werden?

Ja, es sollen nur 3 Bit-Paare verglichen werden.

Yalu X. schrieb:
> soll bspw. mit Var=0b10101000 passieren?

don't care! Nur die ersten 6 bits, und auch da nur paarweise.

Yalu X. schrieb:
> Nur aus Neugier: Warum bezeichnest du das Addieren von 1 oder 2 als
> "bestrafen"?

Weil damit bestimmte Zustände in einem Algorithmus "bestraft" werden 
sollen. Dies bedeutet, je höher die Zahl ist umso unwahrscheinlicher 
wird dieser Zustand. Die Zustände sind einschrittig Kodiert.

Yalu X. schrieb:
> Eine sehr schnelle Methode wäre eine Tabelle (Array)
> mit 256 Einträgen, von denen jeder das gesamte "Strafmaß" für das
> entsprechende Byte enthält.

So hatte ich es vor. Da einige Berechnungen durchgeführt werden, möchte 
ich den Overhead, z.B. für Bitoperationen, so klein als möglich halten.

Yalu X. schrieb:
> Was meinst du mit am "effektivsten"?

Schnelle Abarbeitungszeit.

von Sam .. (sam1994)


Lesenswert?

Korrigiert:
1
#define mask 0b01010101
2
var = (~(var & mask)) * ((var >> 1) & mask + mask);

Ich lerne zwar noch Asm, aber ich komme auf 8 Takte für bis zu 4 Pakete 
in einem Byte (ldi nicht mitgerechnet, mul braucht 2 Takte):
1
.def var r16
2
.def var2 r17
3
.def mask r18
4
5
ldi mask, 0b01010101
6
7
mov var, var2
8
and var, mask
9
com var
10
11
lsr var2
12
and var2, mask
13
add var2, mask
14
15
mul var, var2

Das Ergebnis wäre dann in r0.

Würde der Asm funktionieren (ist mein erster Versuch asm zu schreiben)?

von Sam .. (sam1994)


Lesenswert?

Ohne ldi
1
.def var r16
2
.def var2 r17
3
.def mask 0b01010101
4
5
mov var, var2
6
andi var, mask
7
com var
8
9
lsr var2
10
addi var2, mask
11
subi var2, 255-mask
12
13
mul var, var2

von Jobst M. (jobstens-de)


Lesenswert?

Samuel K. schrieb:
>
1
> .def var r16
2
> .def var2 r17        ; var2 ist vermutlich Dein Eingangsregister
3
                       ; im Beispiel des TO wird dies auf 0b101000 = 40 gesetzt
4
> .def mask 0b01010101 ; = 85
5
> 
6
7
    ; Nach der Operation:   var    var2 (dezimal)
8
> mov var, var2        ;    40     40
9
> andi var, mask       ;    0      40
10
> com var              ;    255    40
11
>                      ; 
12
> lsr var2             ;    255    20
13
> addi var2, mask      ;    255    105
14
> subi var2, 255-mask  ;    255    191(-65)
15
>                      ; 
16
> mul var, var2        ;    R0:R1 = 48705 = High 190 ; Low 65
17
>

... und wo kommt da nun 5 heraus?


Wenn es wirklich schnell gehen soll, dann eine Tabelle mit 64 Einträgen.


Gruß

Jobst

von Michael Giertz (Gast)


Lesenswert?

Das geht am besten mit einer BIT-Peitsche im BIT-SM-Studio!!!

SCNR ;-)

von Sam .. (sam1994)


Lesenswert?

Jobst M. schrieb:
> ... und wo kommt da nun 5 heraus?

sry, ich habe es falsch verstanden. Ich dachte die Zahl soll dem PAket 
dazugerechnet werden.
Ok noch mal überlegen.
1
.def var r16
2
.def res r17
3
4
ldi res, 0
5
6
sbrc var, 6
7
rjmp next1
8
inc res
9
sbrc var, 7
10
inc res
11
next1:
12
sbrc var, 4
13
rjmp next2
14
inc res
15
sbrc var, 5
16
inc res
17
next2:
18
sbrc var, 2
19
rjmp next3
20
inc res
21
sbrc var, 3
22
inc res
23
next3:

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
Noch kein Account? Hier anmelden.