Hallo Leute,
ich habe eine Funktion geschrieben, der ich ein unsigned char feld, ein
Startbit, eine Länge und ein Zielpointer übergebe. Diese Funktion soll
nun aus dem unsigned char Feld, ab dem Startbit für die übergebene
Länge, alle Bits an die Adresse des Zielpointers kopieren.
Der Funktionsheader sieht wie folgt aus:
Folgende Fälle habe ich schon abgedeckt:
1.) W_len <= 8 und die Bits sind in einem Byte in W_sourcefield
2.) W_len <= 8 und die Bits sind über zwei Bytes in W_sourcefield
verteilt
3.) W_len > 8 und die Bits sind über zwei Bytes in W_sourcefield
verteilt
Nun fehlt mir also noch der vierte Fall! Wenn W_len nun Länger als 8 ist
und die Bits die ich auslesen möchte zum Beispiel über 3 Bytes verteilt
sind.
Dazu folgendes Beispiel:
Byte: 1 2 3 4
Bit: 0000 1 010 | 1010 0000 | 1 111 0001 | 0000 0000
W_start_bit = 6,
W_len = 12
In dem Fett markierten Bereich steckt nun also meine Information. Diese
möchte ich nun an meinen Zielpointer W_destination schreiben, wobei
W_destination immer die Adresse des niederwertigsten Bytes enthält.
Der Inhalt von W_destination sollte dann so aussehen:
W_destination[0] = 0100 0001
W_destination[1] = 0000 0101
Ich komme mit meinen Überlegungen einfach nicht so recht weiter. Hat
jemand eine Idee von euch, wie man das realisieren kann?
MfG BlueMorph
@Benny Nestler (bluemorph)
>Ich komme mit meinen Überlegungen einfach nicht so recht weiter. Hat>jemand eine Idee von euch, wie man das realisieren kann?
Ja. Man muss eigentlich keine deiner Fallunterscheidungen machen, das
geht auch mit einem allgemeinen Ablauf, IMO sogar besser.
Hallo Falk,
danke für deine schnelle Antwort!
Leider habe ich bedenken, dass deine Funktion, so wie sie ist
funktioniert.
Folgendes Beispiel:
Byte: 0 1
W_sourcefield = 0000 0011 | 0101 0011
W_start_bit = 4 und W_len = 4.
@Benny Nestler (bluemorph)
>Leider habe ich bedenken, dass deine Funktion, so wie sie ist>funktioniert.
Kann schon sein, ist NICHT getestet, sollte im Wesentlichen nur das
Prinzip darstellen.
OK, hier die debuggte Version, auch wenn das pädagogisch unklug ist.
Okay, du hast natürlich recht, der pädagogische Effekt ist jetzt weg.
Aber sag mal, wie bist du denn vorgegangen, um die Formeln für mask_in
und cnt_in zu erstellen?
Ich glaube das Prinzip ist mir soweit klar. Mit cnt_in zählst du die
übrigen, noch nicht geschriebenen Bits im aktuellen W_sourcefield -
Byte. Ist das richtig? Wenn dann alle Bits geschrieben sind,
dekrementierst du den Zeiger und er zeigt auf das vorhergende Byte des
W_sourcefields. Diesmal kann die mask_in bei 1 beginnen, da ja das
niederwertigste Bit auch das LSB des aktuellen Bytes ist.
Wenn mask_out soweit fortgeschritten ist, dass die 1 aus dem unsigned
char herausgeschoben wird und damit mask_out wieder 0 ist, muss an das
nächste W_destination Byte geschrieben werden.
Übergeordnet wird bei jedem Schleifendurchlauf W_len dekrementiert, so
dass die Schleife entsprechend abgebrochen wird, wenn das Ende der zu
extrahierende Information erreicht ist. usw.
Vielen Dank dir schonmal!
@ Benny Nestler (bluemorph)
Deine Erkläsrung stimmt. Jetzt wo ich das alles nochmal sehe, kann man
cnt_in auch weglassen und die Abfrage wie bei mask_out machen. Macht es
einen Tick schneller.
MFG
Falk
W_sourcefield+=(W_start_bit+W_len-1)/8;//Setze Zeiger auf das Byte wo das LSB drin steht steht
8
V_data_in=*W_sourcefield;//Kopiere das Byte in eine temp Variable
9
V_mask_in=1<<(7-((W_start_bit+W_len-1)%8));//Maskiere das LSB des niederwertigsten Bytes
10
11
for(;W_len>0;W_len--){
12
if(V_data_in&V_mask_in)V_data_out|=V_mask_out;
13
V_mask_in<<=1;
14
V_mask_out<<=1;
15
if(V_mask_in==0){//aktuelles Byte hat keine Bits mehr die geschrieben werden müssen
16
V_mask_in=1;//Maskiere das LSB des nächsten Bytes, diesmal ist es auch das tatsächliche LSB
17
W_sourcefield--;//dekrementiere den W_Sourcefield - Pointer
18
V_data_in=*W_sourcefield;//Kopiere das neue Byte in die temp - Variable
19
}
20
if(V_mask_out==0){//Die temporäre Variable V_data_out ist voll mit Bits
21
V_mask_out=1;//Setzte die Ausgangsmaske wieder an den Anfang
22
*W_destination=V_data_out;//Kopiere V_data_out an den destination Pointer
23
W_destination++;//Inkrementiere den Destination - Pointer
24
V_data_out=0;//V_data muss nun wieder mit 0 anfangen
25
}
26
}
27
if(V_mask_out!=1)*W_destination=V_data_out;//Für den Fall, dass nur wenige Bits in einem Byte geschrieben werden, muss V_data_out noch an die W_destination Speicherstelle geschrieben werden
28
}
Verrätst du mir noch, wie du auf die Formeln für die Maske gekommen
bist???
War das so eine Überlegung ... von wegen "Ich kenne das Ziel" und "ich
probiere jetzt aus, wie ich rechnen muss, damit ich mein Ziel erreiche"?
Das Ziel war ja im niederwertigsten Byte das LSB zu markieren. Das war
auch mein Ziel, allerdings bin ich ganz anders herangegangen und habe
versucht verschiedene Fälle, die auftreten können zu unterscheiden ...
bis ich mich verrannt habe und nicht mehr weiter wusst ;-) .
Du wirst lachen, aber ich kann dir ja mal meine Funktion zeigen, die ich
angefangen habe zu schreiben:
@ Benny Nestler (bluemorph)
>Meinst du das so:
Ja. Noch ein Tip. Verwende die standardisierten Datentypen aus stdint
und nichts selbstgestricktes. Macht die u.a. Sache leichter lesbar. UN
Zeilenlänge auf 80...100 Zeichen begrenzen.
>Verrätst du mir noch, wie du auf die Formeln für die Maske gekommen>bist???
Brain 2.0 ;-)
>War das so eine Überlegung ... von wegen "Ich kenne das Ziel" und "ich>probiere jetzt aus, wie ich rechnen muss, damit ich mein Ziel erreiche"?
Eigentlich ist es nichts weiter als Bitmanipulation plus ein paar
Schleifen.
Erste Idee. Ich maskiere die Bits im Quell- und Zielbereich mit einer
Maske.
Zweite Idee. Ich berechne aus den Parametern eben diese Masken sowie die
Offsets im Array.
Drittens. Die Daten werden rückwärts gelesen.
Der Rest ergibt sich daraus. Der "Trick" mit Division und Modulo setze
ich mal als bekannt vorraus, siehe Festkommaarithmetik.
>Du wirst lachen, aber ich kann dir ja mal meine Funktion zeigen, die ich>angefangen habe zu schreiben:
Naja, dein Ansatz ist erstmal OK, wenn gleich du dich verrannt hast.
Bitmaske erzeugen, Bits maskieren und schieben, eben halt
Bitmanipulation.
MfG
Falk