PIC MikroC: Hur rotera bitar smidigast? (jfr RLF, RRF i ASM)
- Schnegelwerfer
- Inlägg: 1863
- Blev medlem: 8 november 2004, 13:46:56
PIC MikroC: Hur rotera bitar smidigast? (jfr RLF, RRF i ASM)
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?
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?
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:
Om kompilatorn är smart nog att göra om det till RRF istället för en hel hög instruktioner vete tusan...
Kod: Markera allt
unsigned char i;
...
i = i>>1 | i<<7;
- Schnegelwerfer
- Inlägg: 1863
- Blev medlem: 8 november 2004, 13:46:56
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?
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?
- Schnegelwerfer
- Inlägg: 1863
- Blev medlem: 8 november 2004, 13:46:56
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:
Detta borde väl skifta in en 1a?
(mina C-kunskaper är minst sagt ringrostiga!
)
Då blir ju det hela bra mycket enklare.
Ex:
Kod: Markera allt
unsigned char i ;
i = i << 1 | 1 ;
(mina C-kunskaper är minst sagt ringrostiga!

Precis.
Eller
Beroende på vilket håll man vill skifta (LSB först eller MSB först).
Eller
Kod: Markera allt
i = i >> 1 | 0x80;
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.
Kastat ihop lite snabbt men idéen finns där i alla fall.
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.
}
}
}
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.
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.