Entschlüsseln eines ganz komischen Datenformates

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Hallo,
ich lese im Rahmen einer Diplomarbeit ein Logikanalysator aus.
Dieser liefert ein extrem komisches Format, das ich entschlüsselt brauche.

Ich erkläre erst mal das Format.

Es gibt eine Tabelle mit folgenden Werten drin:
M P1 P2 P3
---------------------
0 64 36 36
1 64 18 18
2 64 9 9
3 64 4 4
4 64 36 36
5 64 32 4
6 64 36 9
7 64 36 18
8 64 36 36
9 64 36 18
10 64 36 12
11 64 36 9
12 64 36 6
13 64 36 4
14 64 36 2
15 64 36 1
16 64 36 36
17 64 36 18
18 64 36 12
19 64 36 9
20 64 36 6
21 64 36 4
22 64 36 2
23 64 36 1
Dabei steht "M" für Mode

Das Format ist also so aufgebaut:

Ein "Frame" hat immer P1 Bits (also hier in diesem Fall 64Bit)
die Frames sind immer aneinandergereiht.
davon werden P2 Bits verwendet - die restlichen Bits sind immer 0
Ein Abtastung hat P3 Kanäle. Pro Messung entsteht eine Abtastung, die hintereinander angereiht werden.
aber nur bis zu P2 Bits. Dann geht es wieder weiter in dem nächsten "Frame"

Blöd ist auch, dass wenn eine Abtastung z.B. 9 Kanäle hat, dann verschiebt sich die Position in den Bytes.
Außerdem kommt das niedrigste Byte, dann die höheren. Die Kanläle sind in den Bytes auch so angeordnet...
Niedrigste Bit = niedrigste Kanal. Aber das ist ja genau die andere richtig? Zumindest für uns Menschen?

Kann man das mit meiner Erklärung verstehen?

die Daten haben 16MB. Ist das überhaupt mit Python vernünftig zu bewerkstelligen?

Und wenn ja wie?

ich vermute mal, man muss sowas wie eine Maske erstellen und dann Bitweise verUNDen? Ich steh auf den Schlauch, wie man aus dem Datenvormat was vernünftiges heraus bekommt.

Da bräuchte ich mal eure Erfahrung.

Vielen Dank für eure Hilfe.

Grüße
Torsten
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Der Hex-Editor spuckt folgendes aus (9 Kanäle)
Kanal 0 ist immer "1" (habe da eine Spannung drauf gegeben)
P1 = 64
P2 = 36
P3 = 9


010204080000000001020408000000000102040800000000010204080000000001020408000000000102040800000000

noch mal deutlicher:

01 02 04 08 00 00 00 00
01 02 04 08 00 00 00 00
01 02 04 08 00 00 00 00
01 02 04 08 00 00 00 00

vermutlich wäre es sinnvoll nicht die einzelnen Byte sich anzuschauen, sondern gleich 8 Bytes
also ein ctypes.c_longlong
Wie bekomme ich denn das aus mein Array aus Bytes?
Zuletzt geändert von Torsten2000 am Montag 18. April 2011, 15:09, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Und wo ist nun das Problem? Du kennst anscheinend das Dateiformat und musst es nun nur noch umsetzen. Ein wenig Lesen hier, ein wenig umwandeln dort und dann noch ein wenig schubsen von Bits.

Sebastian
Das Leben ist wie ein Tennisball.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Hallo Sebastian,

Ich steh auf dem Schlauch...
ein Tip würde mir Sicherlich weiter helfen.
Und vor allem muss es schnell sein.
BlackJack

@Torsten2000: Zerleg es in Teilprobleme. Daten in Frames zerlegen. Frames in Folgen von 1en und 0en umwandeln. Die Anzahl von Bits mit Bedeutung davon nehmen. Und das dann noch aufteilen in entsprechend viele Päckchen. Also bei dem Beispieldaten sind es ja vier pro Frame.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Hallo BlackJack,
das mit dem Umwandeln in 1-en und 0-en habe ich auch schon mal probiert. Jedoch ist das viel zu langsam.

Außerdem ist das mit dem Big-Endian ein bisschen blöd.
Kann ich je 8 Bytes auch in ein c_longlong packen, so dass die Reihenfolge sich umdreht?
das würde mir glaube ich schon sehr weiter helfen.
BlackJack

@Torsten2000: Wenn Du es nicht in 0en und 1en umwandeln willst, solltest Du vielleicht mal erklären wie das Ergebnis überhaupt aussehen soll!?

Und falls Du da irgend etwas mit `ctypes` machen möchtest, dann mit `ctypes.c_uint64`. Du möchtest ja dass es 8 Bytes sind. Die Länge von `c_longlong` hängt vom System/Compiler ab.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Ich denke das beste Format wäre, wenn man die Abtastungen einzeln aneinander reiht.
Aber das letzte Byte immer mit 0en auffüllt

Also bei dem Beispiel:
00 01
00 01
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Ich probier mal was aus:

ich lege nicht ein Array von Bytes an sondern eins mit "ctypes.c_uint64"
dann kann ich hoffe ich auf die 8 Bytes direkt drauf zugreifen.

Anschließend verUNDde ich das ergebnis mit einer Maske: hier bei dem Beispiel 9 1-en
anschließend verschiebe ich das uint64 um 9 bit nach rechts
und so weiter
BlackJack

@Torsten2000: Mir ist das Zielformat immer noch nicht ganz klar. Willst Du eine Zahl `int`, oder eine Zeichenkette mit den Bytewerten? Wie soll denn ein dekodiertes Beispielpaket ganz konkret in Python aussehen?
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

@BlackJack:
ich weiß nicht genau ob ich dich 100%-ig verstanden habe.
ich denke das beste Zielformat ist eine Zeichenkette mit Bytes oder uint64
also so dass pro Variable eine Abtastung passt.
und von den Abtastungen dann ein Array.

Verbesser mich bitte, wenn das nicht das beste Zielformat ist.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Wie lese ich denn aus einem Array von Bytes ein uint64 raus?

dreht sich dann die Reihenfolge von den Bytes um?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Da hilft dir das struct-Modul weiter.
Das Leben ist wie ein Tennisball.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Danke Sebastian,
dann schau ich mir das mal an
BlackJack

@Torsten2000: Was das beste Zielformat ist, hängt doch massgeblich davon ab was Du mit den Werten machen willst.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

@BlackJack
Mmm... ja da hast du recht...
Ich habe mir gedacht, dass wäre schön, wenn das Format einheitlich wäre. Allerdings müsste man dann entweder wieder mit 0-en auffüllen, was viel Speicher verbracht, oder wieder eine "Entschlüsselungstabelle" einführen...

Man könnte auch für jeden Kanal die Samples hintereinander abspeichern. Das ist vielleicht das beste.


Also das mit den Verschiedenen Programmiersprachen ist furchtbar... Da war es schöner nur in C oder nur in Python zu Programieren. Da waren die Fronten noch klar... Aber dieses Mischmasch ist furchtbar (Oder meine Unkenntnis). :-| Ich glaub ich habe für heute die Nase voll ...
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

ich glaube das bringt mich weiter

Damit packe ich die vier Bytes in eine 64Bit Variable -Reihenfolge wählbar durch umstellen der test-variablen

Code: Alles auswählen

L = (c_uint64)()
pack_into('BBBB',L,0,test[0],test[1],test[2],test[3])
BlackJack

@Torsten2000: Du hast ja immer noch nicht gesagt wie das Ergebnis überhaupt aussehen soll, aber Dir ist klar, dass sie Reihenfolge der Bytes zumindest auf Intel-Systemen (Little-Endian) zum Beispiel "richtig" ist? Wenn Du jeden Frame in eine ganze 64-Bit-Zahl umwandeln willst, bei der Bit 0, 9, 18, und 27 gesetzt sind, dann liegen die Bytes schon in der richtigen Reihenfolge vor. Da musst Du überhaupt nichts machen.

Vielleicht wäre auch `numpy` einen Blick Wert, bevor Du anfängst `struct` und `ctypes` zu mischen. `numpy`-Arrays haben zum Beispiel eine `byteswap()`-Methode.
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

So. Jetzt habe ich 8 Bytes in ein c_uint64 gepackt.

Code: Alles auswählen

      L = (c_uint64)()
      pack_into('BBBBBBBB',L,0,Wave[i+0], Wave[i+1], Wave[i+2], Wave[i+3], Wave[i+4], Wave[i+5], Wave[i+6], Wave[i+7])
dann erstelle ich eine Maske

Code: Alles auswählen

   Channel = 0
   Maske = 1 << Channel
und möchte die beiden miteinander verUNDen

Code: Alles auswählen

   print L & Maske
Jedoch geht das nicht
print L & Maske
TypeError: unsupported operand type(s) for &: 'c_ulonglong' and 'int'
wie kann ich denn jetzt wieder das c_uint64 in eine normale Python-Zahl umwandeln?
Torsten2000
User
Beiträge: 40
Registriert: Montag 27. Dezember 2010, 17:26

Ich habe jetzt noch eine andere Möglichkeit gefunden

ich glaube langsam komm ich hinter.
Entschluldigt immer meine Fragerei

Code: Alles auswählen

      temp = Wave[i+0]<<(0*8) | Wave[i+1]<<(1*8) | Wave[i+2]<<(2*8) | Wave[i+3]<<(3*8) | Wave[i+4]<<(4*8) | Wave[i+5]<<(5*8) | Wave[i+6]<<(6*8) | Wave[i+7]<<(7*8) 

Antworten