c_byte swap endianess

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
HoWei
User
Beiträge: 12
Registriert: Freitag 28. Juni 2019, 10:18

Hallo,
ich habe ein "c_byte" bei dem ich die Endianess toggeln möchte.

Code: Alles auswählen

from ctypes import *
a = c_ubyte(0xC0)  #a=1100 0000
b = swap(a)        #b=0000 0011
Wie sollte "swap(a)" aussehen - b sollte auch c_ubyte sein?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist keine Endianess. Die bezieht sich nur auf die Reihenfolge von ganzen Bytes. Das was du da suchst ist bitweise Rotation. Also zb

Code: Alles auswählen

b = (a << 4 & 0xf0) | (a >> 4 & 0x0f)
Wobei ich jetzt aus dem Kopf nicht weiss, ob das auf c_ubyte-Ebene funktioniert, oder du das erstmal auf Python-Integer-Objekten machen musst, und *danach* erst c_ubyte(von_irgendwas) aufrufst.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Oh, jetzt sehe ich das erst. Du willst sogar die gesamte Bitreihenfolge umdrehen. Das geht entweder mit Spezialinstruktionen (der PROPELLER uC hat so etwas zB), oder sehr muehselig mit einer Schleife. Ggf. kannst du dir dafuer eine lookup-Tabelle schreiben.

Mit Endianess hat das aber immer noch nichts zu tun. Das bezieht sich darauf, ob das MSB (most significant bit) zuerst ist oder zuletzt.
HoWei
User
Beiträge: 12
Registriert: Freitag 28. Juni 2019, 10:18

Ja, ich möchte die Bitreihenfolge umdrehen, da ich dieses Byte via SPI senden muss, und die SPI implementierung das LSB zuerst schickt (und nicht das MSB wie so oft üblich).
Okay - stimmt - Endianess bezieht sich auf die Anordnung einzelner Bytes und nicht Bits innerhalb eines Bytes.
Jetzt hab ich auch die richtigen Beispiele gefunden. So gehts:

Code: Alles auswählen

c_data = c_ubyte(0x20)		#create c_byte
print(c_data, type(c_data))

i_data = c_data.value		#convert to int
print(i_data, type(i_data))

bin = bin(i_data) 			#get binary representation
print(bin)

rev_bin = bin[-1:1:-1] 	#swap 
print(rev_bin)

rev_bin = rev_bin + (8 - len(rev_bin))*'0'	#fill-up with zeros
print(rev_bin)

c_data = c_ubyte(int(rev_bin,2))	#back to c_ubyte
print(c_data, type(c_data))
Das Ergebniss sieht dann so aus:

c_ubyte(32) <class 'ctypes.c_ubyte'>
32 <class 'int'>
0b100000
000001
00000100
c_ubyte(4) <class 'ctypes.c_ubyte'>
Sirius3
User
Beiträge: 18217
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie die Bit-Reihenfolge gesendet wird, sollte aber Dein SPI-Treiber schon richtig machen.
Statt mit `bin` und Indexspielerei gibt es auch einfache Formatierungsbefehle:

Code: Alles auswählen

c_data = c_ubyte(int(f"{c_data.value:08b}"[::-1], 2))
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: da kommen wir aber schon gefaehrlich an perlige Einzeiler... waere mir zu obfuskiert.

@HoWei: Sirius3 hat schon gesagt, was das eigentliche Problem angeht solltest du das dem Treiber ueberlassen.

Code: Alles auswählen

spi = spidev.SpiDev()
spi.open(0, 0)
spi.lsbfirst = True
Antworten