Hallo zusammen, stehe ein wenig auf dem Schlauch, vlt. kann mir jemand helfen. Ich möchte ein Bit-Datenstream zusammenbauen von 148 Bit, dessen Daten nur Byte- /Nibbleweise vorliegen. Beispiel: Ein Byte hat im rechten Nibble die Einsen als Daten, welche in den Stream sollen. (0011_0011) Hier ist jetzt klar 11... Bei den Nullen wird es schwierig, deswegen ist im linken Nibble immer gekennzeichnet, welche Bits für den Stream genommen werden sollen z.B (0111 0000) heißst dann drei Nullen (Bit 0,1,2) in den Stream. Dieser wächst dann -> 11000. Noch ein Beispiel (1111 1111), hier ist im linken Nibble klar, das alle Bits aus dem rechten Nibble auch in den Stream sollen ->110001111. So geht das weiter bis zum Schluss. Also in dem rechten Teil der Bytes sind die eigentlichen Daten für den Stream mit wechselnden Längen von 1 bis 4 Bit. In dem linken Teil ist die Kennung, welche/wieviele Bits es sind im rechten Teil. Jetzt fehlen mir die Ideen, wie man das elegant angeht. Einfach kopieren geht nicht, das sich immer die Längen ändern. Mal 1 Bit, mal 2,3 oder 4 Bit. Mehr nicht. Ich bin momentan herkömmlich dabei mit If / If else ... verrenne mich aber immer irgendwie. Also ausmaskieren des linken Teils und den rechten dann entsprechend kopieren, dann jede volle neue 8Bit Information in des Stream einbauen. Dabei den Überlauf beachten, weil die Längen sich ja ändern. Ein Bit Array kann der Compiler nicht (C - MikroE für PIC) Kann mir mal jemand Hilfestellung geben? Hoffe, das ist einigermassen klar geworden. Gruß CL
Beitrag #5036497 wurde von einem Moderator gelöscht.
Beitrag #5036513 wurde von einem Moderator gelöscht.
Können im linken Teil auch Lücken wie 0101_xxxx vorkommen?
Versuchs mal so (keine Garantie auf Funktion, ungetestet). Kann man bestimmt auch noch etwas optimieren.
1 | void setData(unsigned char cData){ |
2 | static unsigned char cBuffer = 0; //Ausgabepuffer |
3 | static unsigned char cPos = 0; //Aktuell zu befüllende Stelle bzw. Anzahl bereits gefüllter Stellen |
4 | |
5 | /*JETZT FÜLLEN WIR DEN BUFFER*/
|
6 | for(unsigned char x = 0; x < 4; x++){ |
7 | if(cData & 16){ |
8 | cBuffer |= (cData & 1) << cPos; //BUffer schreiben |
9 | |
10 | if(++cPos > 7){ //Buffer voll |
11 | cPos = 0; //Position auf 0 setzen |
12 | //Daten verschicken.... usw.
|
13 | cBuffer = 0; //Buffer leeren |
14 | }
|
15 | }
|
16 | cData >>= 1; |
17 | }
|
18 | }
|
Tom schrieb: > Können im linken Teil auch Lücken wie 0101_xxxx vorkommen? Nein. Entweder nur 1111, 0111, 0011 oder 0001 @ nils Schaue ich mir nachher mal näher an. Gruss cl Schwerenöter schrieb im Beitrag #5036513: > Es ist kaum auszuhalten Verständnisschwierigkeiten ?
Bei meiner Lösung kann im linken Teil irgendwas stehen. 1101, 1011, 1000, 1010,....
C. L. schrieb: > nur 1111, 0111, 0011 oder 0001 Also nur genau 2 Mal 4 Werte... Da ist ein Switch case schon gut genug, mehr optimieren nur mit ausmessen. Also 16 bit-wert füllen per shift, Shift zählen, Nach mehr als 7 shifts die oberen 8 Bit rauskopieren und shift-=8 (eigener case, kann nur 8..11 sein...) Was ist denn dein Ansatz?
1 | typedef unsigned char BYTE; |
2 | |
3 | extern BYTE ReadNibbleDibble(void); |
4 | extern void PutStream(BYTE data); |
5 | |
6 | void doit_once(void) |
7 | {
|
8 | unsigned short r; /* no need to clear */ |
9 | int byte_cnt = 0; |
10 | int bit_cnt = 0; |
11 | |
12 | while(byte_cnt < 148) |
13 | {
|
14 | BYTE B = ReadNibbleDibble(); |
15 | |
16 | switch(B) |
17 | {
|
18 | case 0x11: bit_cnt+=1; r<<=1; r|=0x01; break; |
19 | case 0x33: bit_cnt+=2; r<<=2; r|=0x03; break; |
20 | case 0x77: bit_cnt+=3; r<<=3; r|=0x07; break; |
21 | case 0xff: bit_cnt+=4; r<<=4; r|=0x0f; break; |
22 | |
23 | case 0x10: bit_cnt+=1; r<<=1; break; |
24 | case 0x30: bit_cnt+=2; r<<=2; break; |
25 | case 0x70: bit_cnt+=3; r<<=3; break; |
26 | case 0xf0: bit_cnt+=4; r<<=4; break; |
27 | |
28 | default: no_default_neccessary_as_we_collapse_immideately(); return; |
29 | }
|
30 | switch(bit_cnt) |
31 | {
|
32 | case 8: bit_cnt-=8; byte_cnt++; PutStream((BYTE) (r>>0)); break; |
33 | case 9: bit_cnt-=8; byte_cnt++; PutStream((BYTE) (r>>1)); break; |
34 | case 10: bit_cnt-=8; byte_cnt++; PutStream((BYTE) (r>>2)); break; |
35 | case 11: bit_cnt-=8; byte_cnt++; PutStream((BYTE) (r>>3)); break; |
36 | }
|
37 | }
|
38 | }
|
Hey Leute... erstmal vielen Dank für die vielen Ansätze. Evtl. komme ich erst Sonntag dazu was umzusetzen weil ich morgen nicht da bin. Ich melde mich dazu auf jeden Fall noch! Achim S. schrieb: > Also nur genau 2 Mal 4 Werte... Hä? Warum 2 mal 4 Werte??? Du meinst die 4 Werte pro Nibble? OK! Deine Lösung sieht auch gut aus... (dito Nils) Um das sauber zu verstehen, möchte ich das schon durcharbeiten, bin aber momentan zeitlich etwas gebunden. Achim S. schrieb: > Was ist denn dein Ansatz? Ich bin gerne noch herkömmlich unterwegs. Poiner usw. habe ich auch schon gemacht aber versuche es gerne ohne, auch wenn es etwas mehr Code braucht. Hier mal ein Ausschnitt, wie ich das Datenbyte zusammensetze. Es geht ja um einen Datenstrom am Empfangspin eines Funkmoduls. Hier messe ich die Puls/Pausenbreite und die binären Zustände zu diesen Zeiten, speichere diese in Arrays. Dann durchlaufe ich die Arrays, prüfe die Breiten ab und fülle die Bytes, von denen ich oben gesprochen habe. Ich war bis gestern Abend dann mit IF (Kennung_Bits[k] & 0x10) usw. unterwegs um dann anhand der linken Nibbles die rechten zu kopieren. Bin dann aber an dem Füllen des Stream gescheitert, weil ich es nicht hinbekommen habe, die unterschiedlichen Zustände in den Stream zu schieben. Den Codeansätze habe ich dann gestern wieder gelöscht und beschlossen hier zu fragen.
1 | if ((PulsPausenWerte[k] > 142) & (PulsPausenWerte[k] < 162)) |
2 | {
|
3 | Kennung_Bits[k] = PulsPausenBinaerWerte[k]; // Bitstelle 0 |
4 | |
5 | temp = PulsPausenBinaerWerte[k] * 2; // Bitstelle 1 |
6 | Kennung_Bits[k] |= temp; |
7 | |
8 | temp = PulsPausenBinaerWerte[k] * 4; // Bitstelle 2 |
9 | Kennung_Bits[k] |= temp; |
10 | |
11 | temp = PulsPausenBinaerWerte[k] * 8; // Bitstelle 3 |
12 | Kennung_Bits[k] |= temp; |
13 | Kennung_Bits[k] |= 0b11110000; // Kennung welche Bits zum Datenstrom gehören |
14 | }
|
Nach diesem Prinzip war ich das angegangen. CL
In asm ist das pillepalle, aber in C muss man da auch nicht
verzweifeln:
In-Byte = XXXXYYYY
Ctrl-Byte = In-Byte
Ctrl-Byte >>= 4 ; Ctrl-Byte = Hi-Nibble von In-Byte
n = 4
while ( Ctrl-Byte & 0x01 && n)
{ STREAM <<= 1
if (In-Byte & 0x01)
STREAM += 1
In-Byte >>= 1
Ctrl-Byte >>= 1
n -= 1
}
Wenn die Bits andersrum einsortiert werden sollen:
In-Byte = XXXXYYYY
Ctrl-Byte = In-Byte
Ctrl-Byte >>= 4 ; Ctrl-Byte = Hi-Nibble von In-Byte
n = 4
while ( Ctrl-Byte & 0x01 && n)
{ STREAM <<= 1
if (In-Byte & 0x08)
STREAM += 1
In-Byte <<= 1
Ctrl-Byte >>= 1
n -= 1
}
Hallo, ich habe das gestern umgesetzt und für die Nachwelt möchte ich meine Lösung hier (noch unkommentiert) mitteilen. Orcans Ansatz habe ich dann schließlich verwendet und auf das System umgemünzt. Die übergebenen Bytebreiten Infos/Daten werden hier in max. acht 32Bit Wörtern umgeschrieben. Dann kann man den Stream weiterverwenden. Danke an alle, die mir weitergeholfen haben... In diesem Sinne, wieder was gelernt... CL
1 | Stream_cnt = 0; |
2 | |
3 | for(l=0; l<=180; l++) |
4 | {
|
5 | In_Byte = Kennung_Bits[l]; |
6 | |
7 | Ctrl_Byte = In_Byte; |
8 | Ctrl_Byte >>= 4; // Ctrl-Byte = Hi-Nibble von In-Byte |
9 | |
10 | x = 4; |
11 | while ( Ctrl_Byte & 0x01 && x) |
12 | {
|
13 | Stream_cnt +=1; |
14 | |
15 | if ((Stream_cnt >= 1) &(Stream_cnt <= 32)) |
16 | {
|
17 | STREAM_1 <<= 1; |
18 | if (In_Byte & 0x01){STREAM_1 += 1;} |
19 | }
|
20 | if ((Stream_cnt >= 33) &(Stream_cnt <= 64)) |
21 | {
|
22 | STREAM_2 <<= 1; |
23 | if (In_Byte & 0x01){STREAM_2 += 1;} |
24 | }
|
25 | if ((Stream_cnt >= 65) &(Stream_cnt <= 96)) |
26 | {
|
27 | STREAM_3 <<= 1; |
28 | if (In_Byte & 0x01){STREAM_3 += 1;} |
29 | }
|
30 | if ((Stream_cnt >= 97) &(Stream_cnt <= 128)) |
31 | {
|
32 | STREAM_4 <<= 1; |
33 | if (In_Byte & 0x01){STREAM_4 += 1;} |
34 | }
|
35 | if ((Stream_cnt >= 129) &(Stream_cnt <= 160)) |
36 | {
|
37 | STREAM_5 <<= 1; |
38 | if (In_Byte & 0x01){STREAM_5 += 1;} |
39 | }
|
40 | if ((Stream_cnt >= 161) &(Stream_cnt <= 192)) |
41 | {
|
42 | STREAM_6 <<= 1; |
43 | if (In_Byte & 0x01){STREAM_6 += 1;} |
44 | }
|
45 | if ((Stream_cnt >= 193) &(Stream_cnt <= 224)) |
46 | {
|
47 | STREAM_7 <<= 1; |
48 | if (In_Byte & 0x01){STREAM_7 += 1;} |
49 | }
|
50 | if ((Stream_cnt >= 225) &(Stream_cnt <= 256)) |
51 | {
|
52 | STREAM_8 <<= 1; |
53 | if (In_Byte & 0x01){STREAM_8 += 1;} |
54 | }
|
55 | In_Byte >>= 1; |
56 | Ctrl_Byte >>= 1; |
57 | x -= 1; |
58 | }
|
59 | }
|
Moin, Kann man denn nicht den Zaehler x einfach weglassen? Wenn Ctrl_Byte 0 ist, ist der Drops doch eh' fertig gelutscht. Gruss WK
Dergute W. schrieb: > Kann man denn nicht den Zaehler x einfach weglassen? Da kann man soviel weglassen. Der UP hat wohl Orcans Version genommen, da war es schon drin. Da Orcan das eigentliche Problem (die Bytegrenzen) garnicht berücksichtigt hat, ist es so groß geworden. Normal straight (und komplett) wäre sowas
1 | typedef unsigned char BYTE; |
2 | BYTE STREAM[32]; /* wo immer diese Werte auch herkommen */ |
3 | BYTE Kennung_Bits[181];/* so sind sie momentan im UP-Code */ |
4 | |
5 | void doit(void) |
6 | {
|
7 | unsigned int l; |
8 | unsigned int bit_cnt = 0; |
9 | |
10 | for(l=0; l<=180; l++) |
11 | {
|
12 | BYTE In_Byte = Kennung_Bits[l]; |
13 | |
14 | while(In_Byte & 0x10) |
15 | {
|
16 | STREAM[bit_cnt/8]<<1; |
17 | STREAM[bit_cnt/8]+=B&1; |
18 | In_Byte>>=1; |
19 | if(++bit_cnt>255) {/* errorhandling hier */ return;} |
20 | }
|
21 | }
|
22 | }
|
achim.s schrieb: > STREAM[bit_cnt/8]<<1; STREAM[bit_cnt/8]<<=1; und vermutlich noch mehr Flüchtigkeitsfehler....
Hi! achim.s schrieb: > Der UP hat wohl Orcans Version genommen, > da war es schon drin. Da Orcan das eigentliche Problem (die Bytegrenzen) > garnicht berücksichtigt hat, ist es so groß geworden. Richtig, das fehlte, deswegen habe ich es mit den IF´s gemacht. Was heisst denn UP? habe ich auf die schnelle nicht gefunden. Kenne wohl TO oder TE... Und was ist das mit dem B? Wo ist das denn initialisiert? achim.s schrieb: > STREAM[bit_cnt/8]+=B&1; achim.s schrieb: > BYTE STREAM[32]; /* wo immer diese Werte auch herkommen */ das ist der fertige "zusammengesetzte" Stream. Hatte oben ja geschrieben das der Compiler ein BIT Array nicht hinbekommt, oder ich bin zu d**f. 32*8 Bit ist quasi ein Container. Ich finde es trotzdem erstaunlich, wie kompakt Ihr das dann oft macht. Dazu fehlt mir noch die Erfahrung, scheinbar. Ich werde auch diese Routine mal antesten, mache momentan aber erstmal mit dem Code weiter um erste Ergebnisse zu erzielen. Dafür nochmal Thx!!!
Wenn man nach verquast-überfrachteten Vorschlägen einen praktikablen Lösungs-ANSATZ (!) bietet, wagen sich natürlich wieder die Klugsch... aus der Deckung. Hauptsache, der TO kam dem Ziel näher! Freut mich.
Orcan schrieb: > wagen sich natürlich wieder die Klugsch... aus der Deckung Du siehst aber schon, dass mein neuer Code meinem Alten entspricht? Halt auf Deine Benamung umgestellt (weil der TO diese übernommen hat) und durch bitweise Verarbeitung halt kleiner. Ich dachte er wollte ein In_Byte auf einmal zu verarbeiten, darum hatte ich das ausgerollt. Du hast Deinen Beitrag ja auch erst nach der Konkretisierung des TO gepostet. C. L. schrieb: > Und was ist das mit dem B? sorry, "B" ist "In_Byte". STREAM[bit_cnt/8]+=In_Byte&1; Orcans Version ist hier aber besser (lesbarer, wartbarer): if (In_Byte & 0x01) {STREAM[bit_cnt/8]++;} Thread-Owner (TO) und Urposter(UP) meinen (bei mir) das gleiche.
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.