www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Parity rechnen mit AVR


Autor: Seph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie rechnet man am Effizientesten die Parity eines Bytes ? Das Ziel ist 
zu wissen ob die Anzahl gesetzter Bits gerade oder ungerade ist. Leider 
kann der AVR das nicht in Hardware. Eine For Schleife mit compare leider 
ist zuviel Aufwand.

Autor: DO (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier wird dir geholfen:

http://www.nongnu.org/avr-libc/user-manual/group__...

Gruß,
Dirk

Autor: Marius S. (lupin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
par = 0;
while(byte>0) {
par ^= (byte&1);
byte >>= 1;
}

denke ich...

Autor: Marius S. (lupin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirks lösung ist natürlich viel besser, jetzt würde ich nur noch gerne 
den code im listing verstehen... :)

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir ist da grad ne lustige Lösung in asm eingefallen, frisst allerdings 
etwa 600 bytes:

Etwa so:
clr r17
;(parity byte mit 2 multiplizieren, wegen 2byte langem opcode)
lsl r16 ;low byte vo zu bestimmenden parity byte
rol r17 ;carry U.u in r17 reinrollen;
ldi r30 low(IP_vor_ijmp)
ldi r31 high(IP_vor_ijmp)
add r30,r16
adc r31,r17
IP_vor_ijmp:
ijmp
rjmp even parity;(0 hat gerade parität)
rjmp odd parity;(1 hat ungerade parität)
rjmp even parity;(2 hat gerade parität)
rjmp odd parity;(3 hat ungerade parität)
.
.
.
.
rjmp odd parity;(255 hat ungerade parität)
rjmp even parity;(256 hat gerade parität)

odd parity:
....
even parity:
......

11 CPU Cycles, who's faster, C is es sicher nicht :)

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noch eine kleiner fehler in programm:
2 hat ungerade parität
3 hat gerade parität
255 ungerade
Sorry kurz falsch gedacht

Autor: Seph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick's code sollte noch einige symmetrien ausnutzen und etwas 
kompakter werden.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/pgmspace.h>
#include <stdint.h>

#define PARITY_ODD 0
#define PARITY_EVEN 1

const uint8_t PROGMEM ParityTable[256] = 
{
    PARITY_EVEN,
    PARITY_ODD,
    PARITY_ODD,
    PARITY_EVEN,
    ...
};

main()
{
    uint8_t parity = pgm_read_byte(&ParityTable[133]); //Parity von 133
    
    if (parity == PARITY_EVEN)
    {
        ...
    }else
    {
        ...
    }
}

Da kommt sicher keiner dran ;) Sowohl von der Code-menge als auch von 
der Ausführungsgeschwindigkeit.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick wrote:
> Mir ist da grad ne lustige Lösung in asm eingefallen, frisst allerdings
> etwa 600 bytes:
> ...
> 11 CPU Cycles, who's faster, C is es sicher nicht :)

Du irrst, in C dauerts nur 10 Zyklen und braucht auch nur 20 Bytes.

Ist nämlich ein Assemblermacro in der "parity.h".


Peter

Autor: Seph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie schaut der ASM code denn aus ? Ich hab's nicht geschafft.

(__extension__({                                        \
        unsigned char __t;                              \
        _asm_ (                                       \
                "mov _tmp_reg_,%0" "\n\t"             \
                "swap %0" "\n\t"                        \
                "eor %0,__tmp_reg__" "\n\t"             \
                "mov _tmp_reg_,%0" "\n\t"             \
                "lsr %0" "\n\t"                         \
                "lsr %0" "\n\t"                         \
                "eor %0,__tmp_reg__"                    \
                : "=r" (__t)                            \
                : "0" ((unsigned char)(val))            \
                : "r0"                                  \
        );                                              \
        (((__t + 1) >> 1) & 1);                         \
 }))

macht :

 mov  R16, %0
 swap %0
 eor %0, R16
 mov R16, %0
 lsr %0
 lsr %0
 eor %0, R16

und weiter ?

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das spuckt der GCC für nen einfachen Aufruf des parity_even_bit Macros 
aus:
       mov __tmp_reg__,r24
        swap r24
        eor r24,__tmp_reg__
        mov __tmp_reg__,r24
        lsr r24
        lsr r24
        eor r24,__tmp_reg__

        subi r24,lo8(-(1))
        lsr r24
        andi r24,lo8(1)

C Code:
  unsigned char x;
  x=PINB;
  x=parity_even_bit(x);
  PORTB=x;

(Die PINB/PORTB Zugriffe verhindern nur, daß der Optimierer das ganze 
komplett verwirft...)

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf so ein Makro muss man erst mal kommen. Falls jemand Schwierigkeiten 
hat, den Assembler-Code nachzuvollziehen:

Seien a bis h die Bits des untersuchenden Werts. a ist das MSB (oberstes 
Bit, Bit 7), h das LSB (unterstes Bit, Bit 0). R24 ist also zu Anfang 
abcdefgh.

Durch SWAP, EOR(=XOR), 2xLSR, EOR stehen schließlich in den untersten 
beiden Bits von R24 (die restlichen sind nicht relevant, "x"):
Bit 1: a XOR c XOR e XOR g = Parity von aceg
Bit 0: b XOR d XOR f XOR h = Parity von bdfh

Damit die Parity des Bytes gerade ist, müssen die Teil-Parities entweder 
beide gerade oder beide ungerade sein, d.h.
R24 = xxxxxx00 oder R24 = xxxxxx11.
Nach Addition von 1 (SUBI), gilt dann also
R24 = xxxxxx01 oder R24 = xxxxxx00. Durch ein weiteres LSR und die 
Maskierung mit AND wird selektiv das Bit 1 ausgewertet, was im Falle 
einer geraden Parity 0 ist und im Falle einer ungeraden Parity 1.

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
8 Bit hat ein Byte, wir teilen in 2 Hälfen und xor'en 4 Bit, das 
Resultat in 2 Hälften und xor'en 2 Bits und das dann nochmal.

Gruß Hagen

Autor: AVRFan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>8 Bit hat ein Byte

Dachte immer, ein Byte hat 8 Bit ;-)

>wir teilen in 2 Hälfen und [...]

Jepp, das ist das Prinzip.  In diesem Code kann man es besser erkennen:
    mov   t, a    ; a = Input der Routine
    lsr   a
    lsr   a
    lsr   a
    lsr   a
    eor   a, t

    mov   t, a
    lsr   a
    lsr   a
    eor   a, t

    mov   t, a
    lsr   a
    eor   a, t

    andi  a, 1    ; Ergebnis: a = 0[1] wenn Parität even[odd]

Zuerst wird um 8/2 = 4 Stellen rechtsgeschoben, danach um 2 Stellen, und 
am Schluss um eine.  Dann enthält Bit 0 von a das Ergebnis.

Den "lsr"-Viererblock kann man durch ein "swap a" ersetzen, außerdem 
(wie man sich leicht klarmachen kann) die letzten vier Instruktionen 
durch diese drei:
    inc   a
    lsr   a
    andi  a, 1

Tut man dies, hat man genau Dirks Code reproduziert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.