Sida 1 av 1

PIC MikroC: Hur rotera bitar smidigast? (jfr RLF, RRF i ASM)

Postat: 24 juli 2005, 16:38:32
av Schnegelwerfer
Har letat runt lite, och insett att ANSI C inte har någon färdig funktion för att rotera bitar inuti en byte (RLF, RRF i assembler).

Jag antar att detta "problem" ständigt dyker upp, så jag undrar om någon på forumet har en bra, smart standardmetod som man kan använda?

Postat: 24 juli 2005, 16:47:53
av cyr
Har faktiskt aldrig behövt rotera i C, men om jag skulle göra det antar jag att jag skulle skriva något i stil med:

Kod: Markera allt

unsigned char i;

...

i = i>>1 | i<<7;
Om kompilatorn är smart nog att göra om det till RRF istället för en hel hög instruktioner vete tusan...

Postat: 24 juli 2005, 17:03:22
av Schnegelwerfer
Ok, jag kanske ta och specifiera mitt problem istället, det kanske går att lösa på ett smart sätt utan roteing av bitar.

Jag håller alltså på att skriva om mitt IR-fjärrkontrollmottagarprogram i C, och jag behöver detektera inkommande 1:or och 0:or samt lagra dessa för att sedan jämföra med en 48-bitssekvens.

Det enklaste är kanske att lagra de inkommande 1 och 0 i en sträng med 48 platser, typ:

char code[47];

Det går då åt mer minne, men det har jag råd med... några synpunkter?

Postat: 24 juli 2005, 17:06:23
av cyr
Fast behöver du då rotera eller bara skifta?

Postat: 24 juli 2005, 17:13:46
av Schnegelwerfer
Egentligen behöver jag ju bara skifta in bitarna, det har du ju rätt i!
Då blir ju det hela bra mycket enklare.

Ex:

Kod: Markera allt

unsigned char i ;

i = i << 1 | 1 ;
Detta borde väl skifta in en 1a?

(mina C-kunskaper är minst sagt ringrostiga! :cry: )

Postat: 24 juli 2005, 17:53:59
av cyr
Precis.

Eller

Kod: Markera allt

i = i >> 1 | 0x80;
Beroende på vilket håll man vill skifta (LSB först eller MSB först).

Postat: 24 juli 2005, 19:36:22
av Icecap
Jag håller mig till ett "standart" sätt som fungerar bra:
Jag försöker att se till att datan kommer in med MSB först, sedan är det bara:
skifta till vänster (värde <<= 1;)
kolla om data är 1 (if(data) värde++;)

Det går såklart att köra andra hållet också men då fär man OR:a med ett lagom värde beroende på storleken på variablem man roterar.

48 bits kan sammanställas av en 16 bitars (unsigned int) och en 32 bitars (unsigned long), när man ska "överföra" bits sinsemellan kollar man om MSB:n på de lägsta bitsen är satt och skifter in den i högsta variablen, därefter skifter man den lägsta variabeln.

Kod: Markera allt

struct
  {
  int                 Bitcounter;
  union
    {
    struct
      {
      unsigned int   Highest;
      unsigned long Lowest;
      } Shift;
    unsigned char Bytes[5];
    } Value;
  } Alla_Bits;

void Start_Mottagning(void)
  {
  Alla_Bits.Bitcounter = 0;
  Alla_Bits.Shift.Lowest = 0;
  }

void Shift_In_Bit(bool Bitvalue)
  {
  Alla_Bits.Value.Shift.Highest <<= 1;
  if(Alla_Bits.Value.Shift.Lowest & 0x80000000) Alla_Bits.Value.Shift.Highest++;
  Alla_Bits.Value.Shift.Lowest <<= 1;
  if(Bitvalue) Alla_Bits.Value.Shift.Lowest++;
  Alla_Bits.Bitcounter++;
  if(Alla_Bits.Bitcounter >= 48)
    {
    // Här kan man sedan jämnföra de 5 bytes
    if((Alla_Bits.Value.Bytes[0] == 0x??) && (Alla_Bits.Value.Bytes[1] == 0x??) && (Alla_Bits.Value.Bytes[2] == 0x??) && (Alla_Bits.Value.Bytes[3] == 0x??) && (Alla_Bits.Value.Bytes[4] == 0x??))
      {
      // Jämnförd och lika, gör vad som ska göras.
      }
    }
  }
Kastat ihop lite snabbt men idéen finns där i alla fall.

Postat: 24 juli 2005, 22:43:32
av macgyver
alla har olika lösningar, så här hade nog jag gjort:
i detta fall för LSB först

unsigned char bits[6], i, j;

for(i=0; i != 6; i++) {
for(j=1; j != 8; j++) {

bits >>= 1;
bits += GET_IR_BIT() ? 0x80 : 0;

}
}

Postat: 25 juli 2005, 08:08:41
av Icecap
Får jag fråga varför din for-to-next loop använder '!='?
Enligt min erfarenhet är det vida bättre att använda '<', anledningen är att om någon jävla glitch i programmet spöker till det (och det har ju händ!) kommer din version enbart att stoppa när i/j är hhv. 6 och 8, på "mitt" sätt kommer de att stoppa när endera värde är lika med eller över deras respektiva referenser.

Samtidig är det iblant snabbare att kolla för "mindre än" i den slutgiltiga koden.

Postat: 25 juli 2005, 12:59:15
av macgyver
brukar skriva != av gammal vana från programering av 8051 cpu:er
med kompilatorn jag använde sparade jag in på 1 ASM instruktion genom att använda != istället för < :)