Mackie Showbox Reverse Engineering

  • Ersteller 6stringtheory
  • Erstellt am
6
6stringtheory
Registrierter Benutzer
Zuletzt hier
16.09.24
Registriert
24.05.20
Beiträge
172
Kekse
2.196
In diesem Thread werde ich meine Erkenntnisse über die Mackie Showbox teilen, die über die offizielle Dokumentation hinausgehen. Jeder der sich anschließen möchte ist herzlich willkommen.
Ziel ist es erstmal die Möglichkeit zu schaffen zusätzliche Hardware für die Mackie Showbox selber zu bauen, die sich den RJ-45 Anschluss zu Nutze macht. Beispielsweise ein Fußschalter, der den Looper mit mehr als nur einem Fußschalter steuern kann. (Ich bevorzuge es beim Loopen einen separaten Stop Schalter zu haben.) Aber auch Fußschalter um Presets zu wechseln sind denkbar.
Ich fange erstmal an mit einem Foto von der Platine des Breakaway Mixers:
breakaway-mixer-pcb-back-small.jpg
chips.jpg

Im Anhang liegt auch noch ein Bild von der Vorderseite, aber diese ist relativ uninteressant für den Rahmen des Projektes.

Weitere Erkenntnisse folgen morgen. Ich kann aber schonmal soviel verraten: Die RJ-45 Buchse ist nicht Ethernet-konform.





Durchgangsprüfung
Wenn ich hier von Orange, Orange-White, Green, Green-White, Blue, Blue-White, Brown und Brown-White rede, dann beziehe ich mich auf die Drähte im Cat 5 Kabel nach T568B:
1719476462661.png

Wenn ich von Pin X (mixer) rede, meine ich die Pogo-Pin Kontakte am Breakaway Mixer.
Wenn ich von Pin X (base) rede, meine ich die Pogo-Pins an der Box selbst (Mackie nennt sie oft einfach "Base Unit").
X -> Y, Z bedeutet, dass ein Durchgan von X nach Y, sowie ein Durchgang von X nach Z gemessen wurde.

Breakaway Mixer:
Code:
RJ-45:
Cat5 Shield -> Pin 4 (mixer), Pin 7 (mixer), USB Shield (mixer), USB Gnd (mixer), Orange-White, Orange
Orange-White -> Pin 4 (mixer), Pin 7 (mixer), USB Shield, USB Gnd (mixer), Orange, Cat5 Shield
Orange -> Pin 4 (mixer), Pin 7 (mixer), USB Shield (mixer), USB Gnd (mixer), Cat5 Shield, Orange-White
Blue-White -> Pin 3 (mixer)
Blue -> Pin 5 (mixer)
Green-White -> Pin 6 (mixer)
Green -> Pin 2 (mixer)
Brown-White -> Brown
Brown -> Brown-White

Pogo-Pin Interface:
Pin 1 -> ---
Pin 2 -> Green
Pin 3 -> Blue-White
Pin 4 -> Pin 7 (mixer), Cat5 Shield, USB Shield (mixer), USB Gnd (mixer)
Pin 5 -> Blue
Pin 6 -> Green-White
Pin 7 -> Pin 4 (mixer), Cat5 Shield, USB Shield (mixer), USB Gnd (mixer)

USB:
Shield -> Pin 4 (mixer), Pin 7 (mixer), Cat5 Shield, Orange, Orange-White
VCC -> ---
Gnd -> Pin 4 (mixer), Pin 7 (mixer), Cat5 Shield, Orange, Orange-White
D+ -> ---
D- -> ---

Box (Base Unit):
Code:
RJ-45:
Cat5 Shield -> Pin 7 (base), Orange-White, Orange
Orange-White -> Pin 7 (base), Cat5 Shield, Orange
Orange -> Pin 7 (base), Cat5 Shield, Orange-White
Green-White -> Pin 6 (base)
Blue -> Pin 5 (base)
Blue-White -> Pin 3 (base), Pin 7 (base), Cat5 Shield, Orange, Orange-White, Brown, Brown-White
Green -> Pin 2 (base)
Brown-White -> Pin 7 (base), Cat5 Shield, Orange, Orange-White, Brown
Brown -> Pin 7 (base), Cat5 Shield, Orange, Orange-White, Brown-White

Pogo-Pins:
Pin 1 -> ---
Pin 2 -> Green
Pin 3 -> Pin 7 (base), Cat5 Shield, Orange, Orange-White, Green-White, Brown, Brown-White, USB Gnd, USB Shield
Pin 4 -> ---
Pin 5 -> Blue
Pin 6 -> Green-White
Pin 7 -> Cat5 Shield, Orange, Orange-White

USB:
Shield -> Pin 7 (base)
VCC -> ---
Gnd -> Pin 7 (base)
D+ -> ---
D- -> ---





Spannungsmessung

Alle Messungen werden in folgendem Zustand durchgeführt:
- Showbox ist eingeschaltet
- Breakaway Mixer ist über Cat 5 Kabel mit der Box (Base Unit) verbunden
Für die Messungen der Verbindung der beiden RJ-45 Anschlüsse wird ein einfaches Breakout Board benutzt, welches nichts tut außer die einzelnen Pins/Drähte zugänglich zu machen:
1719477068758.png


Pogo-Pins (am Breakaway Mixer):
Code:
Gnd -> Pin 1: 11.4V
Gnd -> Pin 2: 3.27V
Gnd -> Pin 3: 3.27
Gnd -> Pin 4: 0V
Gnd -> Pin 5: 3.3V
Gnd -> Pin 6: 3.3V

RJ-45 / Cat5 Verbindung:
Code:
Gnd -> Orange: 0V
Gnd -> Orange-White: 0V
Gnd -> Blue: 3.30V
Gnd -> Blue-White: 3.26V
Gnd -> Green: 3.26V
Gnd -> Green-White: 3.30V
Gnd -> Brown: 11.84V
Gnd -> Brown-White: 11.84V





Erkenntnisse

Es wird sofort klar, dass das keinem Ethernet Standard folgt, wenn die Ladebuchse am Breakaway Mixer erlaubt eine Versorgung mit bis zu 10W. Das wäre mit Ethernet nur über dem PoE-Standard möglich und dieser arbeitet mit wesentlich höheren Spannungen:
1719477643057.png


Was wir uns aber denken können ist:
- Orange, Orange-White, sowie die Cat 5 Abschirmung sind GND
- Brown und Brown-White übertragen zusammen ~12V welche im Breakaway Mixer dann für den USB Port in 5V gewandelt wird.
- Green, Green-White, Blue, Blue-White haben alle ungefähr 3,3V (was ist eine typische logic-level Spannung, die gerne für die Datenübertragung genutzt wird). Es ist also davon auszugehen, dass die Daten über diese Leitungen fließen.





Signal-Analyse
Nun nehme ich mir einen Logic-Analyzer (die sind für unter 10€ auf ebay und aliexpress zu haben und haben gleich 8 Kanäle, hier Z. B.):
1719478462599.png

Ich verbinde GND der RJ-45 Verbindung mit GND vom Logic-Analyzer. Und Green, Blue, Green-White, sowie Blue-White mit den ersten 4 Kanälen.

Am Rechner nehme ich mir dann den fx2lafw Treiber, welcher sich wunderbar eignet um mit der freien Software PipeView die Signale eines solchen Logic-Analyzers einzufangen und auszuwerten.
Wie ihr nun auf folgendem Screenshot seht, findet eine Datenübertragung lediglich auf den ersten beiden Kanälen statt (Das sind Green und Blue des Cat 5 Kabels (technisch gesehen Pin 6 und 4 des RJ45-Anschluss).
1719478794836.png





Protokoll-Analyse (Erste Schicht)
Da wir nur 2 Datenpins haben, können wir durch ein einfaches Ausschlussverfahren schon hunderte Protokolle ausschließen.
Zwei Protokolle, die naheliegend erscheinen, weil sie vom verwendeten MIMXRT1010 Mikrocontroller unterstützt werden, weit verbreitet sind und nur 2 Datenpins benötigen sind I²C und UART.
I²C benutzt eine Datenleitung allerdings nur für ein Taktsignal. Seht ihr auf dem Screenshot eins? Ich nicht und damit bleibt nur noch UART.
Aber welche Baudrate könnte es sein? Probieren wir doch einfach mal ein paar typische Baudraten aus. 9600 und 115200 sind wahrscheinlich die am weitesten verbreitetsten...
Siehe da 115200 passt PERFEKT. Wer genauer hingeschaut hat, dem wird schon aufgefallen sein, dass ich den Protokoll-Decoder für UART ganz unten schon entsprechend eingerichtet habe.





Protokoll-Analyse (Zweite Schicht)
Wenn man noch genauer hinschaut, fällt auf, dass die verdächtig oft mit 1011111011101111 (das entspricht den Bytes 0xBE 0xEF) anfangen und mit 1110111110111110 aufhören (das entspricht den Bytes 0xEF 0xBE). Auch nach längerer Analyze größerer Datenmengen, war dieses Muster ganz klar zu sehen.
Daraus lässt sich schließen, dass der Anfang jedes Daten-Packets mit 0xBE 0xEF gekennzeichnet ist und das Ende mit 0xEF 0xBE.





Protokoll-Analyse (Dritte Schicht)
Da mir kein auf UART basierendes Protokoll bekannt ist, welches seine Pakete mit BEEF ... EFBE kennzeichnet, gehe ich davon aus, dass es sich hierbei um ein proprietäres Protokoll handelt.
Da wir nun aber schonmal wissen, dass es sich um UART handelt, wechsle ich mal vom Logic-Analyzer auf einen einfachen USB UART Adapter (die gibt es für unter 5€ auf ebay und aliexpress). Dieser wird nun auf 3.3V gestellt. (Genaugenommen brauchen wir zwei Stück, weil Green und Blue für uns beide RX sind.) Aber gut, erstmal nur eine Leitung.

Nun schreiben wir ein kurzes Python-Script, welches den Inhalt der Datenpakete Zeile für Zeile ausgibt:

Python:
import serial

# Define the markers
START_MARKER = bytes([0xBE, 0xEF])
END_MARKER = bytes([0xEF, 0xBE])

# Open serial port
ser = serial.Serial('/dev/ttyUSB0', baudrate=115200)

# Buffer to store received bytes
buffer = bytearray()

while True:
    # Read one byte from serial port
    byte = ser.read()
  
    # Append byte to buffer
    buffer.append(byte[0])
  
    # Check if buffer contains start and end markers
    if buffer[-len(END_MARKER):] == END_MARKER:
        start_idx = buffer.find(START_MARKER)
        if start_idx != -1:
            # Extract the packet (excluding markers)
            packet = buffer[start_idx+len(START_MARKER):-len(END_MARKER)]
          
            # Print packet in hexadecimal format
            print('Packet:', packet.hex())
          
            # Remove processed bytes from buffer
            del buffer[:start_idx+len(START_MARKER)+len(packet)+len(END_MARKER)]

# Close serial port
ser.close()

Der Output ist ein regelrechtes gespamme dieser beiden Pakete:
00ff00
010100ff

Aber jedes mal wenn ich die Showbox über den Mute-Button stumm schalte, taucht plötzlich dieses Datenpaket in der Leitung auf:
0503005900000001

und immer wenn ich wieder un-mute, dann wird dieses Paket geschickt:
0503005900000000

Ich weiß jetzt nicht, ob das das Signal vom Mixer an die Box war oder ob das die Bestätigung bzw das Status-Update der Box an den Mixer war, aber es ist klar, dass wir nun mit Leichtigkeit mitschneiden können, wann die Box stummgeschaltet wird.

Der nächste Schritt wäre mal eine Tabelle mit allen Datenpaketen und deren Bedeutung anzulegen und zu schauen was wohl passiert, wenn man diese Pakete in die Datenleitungen einschleust ohne, dass der Mute Button gedrückt wurde.
 

Anhänge

  • breakaway-mixer-pcb-front-small.jpg
    breakaway-mixer-pcb-front-small.jpg
    413,6 KB · Aufrufe: 46
Zuletzt bearbeitet:
  • Gefällt mir
  • Interessant
Reaktionen: 5 Benutzer
Ich habe nun glaube ich fast alle Datenpakete dekodiert und kann nun alles mitschneiden, was der Mixer bzw die Box tut:
1719663011071.png


Diese Benamung wie USER_INPUT1_MUTE usw. habe ich mir übrigens nicht ausgedacht. Diese habe ich beim Analysieren der Firmware gefunden. Das geht in Ghirda mit diesen Einstellungen ganz gut:
1719663327536.png


Um überhaupt an die Firmware zu kommen, muss man sich den Firmwareupdater herunterladen (ShowBoxUpdater_v1.1.x_Win.zip) diese ZIP-Datei extrahiert man ganz normal, dann nimmt man sich UniExtract zur Hand und extrahiert die eben entpackte ShowBoxUpdater_v1.1.x.msi, wodurch man unter anderem eine Datei namens disk1.cab erhält, welche man dann mit 7z entpackt, welche die binären Firmware-Images enthält:
  • ivt_performer_ui_extracted_unsigned_nopadding.bin
  • ivt_performer_dcd_unsigned_nopadding.bin
  • ivt_flashloader.bin
  • unsigned_MIMXRT1010_flashloader_nopadding.bin
Die Mackie Showbox hat zwei Firmwares (eine in der Box, die andere im Breakaway Mixer) und diese Firmwares sind wiederum aufgeteilt in einen sogenannten Flashloader und die Application Firmware, welche dann im Endeffekt auf die SPI Flash Chips geflasht werden. Den SPI Flash Chip des Breakaway Mixers hatte ich auch im zweiten Foto markiert.

Aber bevor ich weiter abschweife, hier ist mein überarbeitetes Python Script, welches die Kommunikation zwischen Box und Mixer dekodiert:
Python:
import serial
import threading
import signal
import sys
# Define the markers
START_MARKER = bytes([0xBE, 0xEF])
END_MARKER = bytes([0xEF, 0xBE])
# Define exclusion list for packets that are constantly sent without interaction
exclude_base_hex = [
    '00ff00',
    '010100ff'
]
exclude_mixer_hex = [
    '00ff00',
    '010100ff',
    '0803005b0000006227eec2',
    '0803005b0000000000f0c2',
    '08030057000000287652c2',
    '08030057000000ecc44ec2',
    '0803005b000000c54eecc2'
]
# Function to convert hex strings to byte sequences
def hex_list_to_bytes(hex_list):
    return {bytes.fromhex(hex_str) for hex_str in hex_list}
# Convert hex string lists to byte sequences sets
exclude_base = hex_list_to_bytes(exclude_base_hex)
exclude_mixer = hex_list_to_bytes(exclude_mixer_hex)
# Known packet patterns with descriptions
known_packet_patterns = {
    '05030000000000': 'USER_FRONT_LED {}',
    '05030001000000': 'USER_FEEDBACK_ELIM {}',
    '05030002000000': 'USER_AMP_PA_MODE {}',
    '05030003000000': 'USER_LOCATION_MODE {}',
    '05030004000000': 'USER_SELECTED_CHAN {}',
    '080300050000000': 'USER_INPUT1_GAIN {}',
    '08030006000000': 'USER_INPUT1_VOLUME {}',
    '05030007000000': 'USER_INPUT1_MUTE {}',
    '05030008000000': 'USER_INPUT1_CLIP_OL_PRE {}',
    '05030009000000': 'USER_INPUT1_CLIP_OL_POST {}',
    '0503000a000000': 'USER_INPUT1_EFFECT_1_MUTE {}',
    '0803000b000000': 'USER_INPUT1_EFFECT_1_AMOUNT {}',
    '0503000c000000': 'USER_INPUT1_EFFECT_2_MUTE {}',
    '0803000d000000': 'USER_INPUT1_EFFECT_2_AMOUNT {}',
    '0503000e000000': 'USER_INPUT1_EQ_ENABLE {}',
    '0803000f000000': 'USER_INPUT1_EQ_LOW_GAIN {}',
    '08030010000000': 'USER_INPUT1_EQ_MID_GAIN {}',
    '08030011000000': 'USER_INPUT1_EQ_HIGH_GAIN {}',
    '05030012000000': 'USER_INPUT1_COMPRESSOR_ENABLE {}',
    '08030013000000': 'USER_INPUT1_COMPRESSOR_AMOUNT {}',
    '05030014000000': 'USER_INPUT1_EXT_FX_MUTE {}',
    '08030015000000': 'USER_INPUT1_EXT_FX_SENDS {}',
    '080300160000000': 'USER_INPUT2_GAIN {}',
    '08030017000000': 'USER_INPUT2_VOLUME {}',
    '05030018000000': 'USER_INPUT2_MUTE {}',
    '05030019000000': 'USER_INPUT2_CLIP_OL_PRE {}',
    '0503001a000000': 'USER_INPUT2_CLIP_OL_POST {}',
    '0503001b000000': 'USER_INPUT2_EFFECT_1_MUTE {}',
    '0803001c000000': 'USER_INPUT2_EFFECT_1_AMOUNT {}',
    '0503001d000000': 'USER_INPUT2_EFFECT_2_MUTE {}',
    '0803001e000000': 'USER_INPUT2_EFFECT_2_AMOUNT {}',
    '0503001f000000': 'USER_INPUT2_EQ_ENABLE {}',
    '08030020000000': 'USER_INPUT2_EQ_LOW_GAIN {}',
    '08030021000000': 'USER_INPUT2_EQ_MID_GAIN {}',
    '08030022000000': 'USER_INPUT2_EQ_HIGH_GAIN {}',
    '05030023000000': 'USER_INPUT2_COMPRESSOR_ENABLE {}',
    '08030024000000': 'USER_INPUT2_COMPRESSOR_AMOUNT {}',
    '05030025000000': 'USER_INPUT2_EXT_FX_MUTE {}',
    '08030026000000': 'USER_INPUT2_EXT_FX_SENDS {}',
    '080300270000000': 'USER_INPUT3_GAIN {}',
    '08030028000000': 'USER_INPUT3_VOLUME {}',
    '05030029000000': 'USER_INPUT3_MUTE {}',
    '0503002a000000': 'USER_INPUT3_CLIP_OL_PRE {}',
    '0503002b000000': 'USER_INPUT3_CLIP_OL_POST {}',
    '0503002c000000': 'USER_INPUT3_EFFECT_1_MUTE {}',
    '0803002d000000': 'USER_INPUT3_EFFECT_1_AMOUNT {}',
    '0503002e000000': 'USER_INPUT3_EFFECT_2_MUTE {}',
    '0803002f000000': 'USER_INPUT3_EFFECT_2_AMOUNT {}',
    '05030030000000': 'USER_INPUT3_EQ_ENABLE {}',
    '08030031000000': 'USER_INPUT3_EQ_LOW_GAIN {}',
    '08030032000000': 'USER_INPUT3_EQ_MID_GAIN {}',
    '08030033000000': 'USER_INPUT3_EQ_HIGH_GAIN {}',
    '05030034000000': 'USER_INPUT3_COMPRESSOR_ENABLE {}',
    '08030035000000': 'USER_INPUT3_COMPRESSOR_AMOUNT {}',
    '05030036000000': 'USER_INPUT3_EXT_FX_MUTE {}',
    '08030037000000': 'USER_INPUT3_EXT_FX_SENDS {}',
    '080300380000000': 'USER_INPUT4_GAIN {}',
    '08030039000000': 'USER_INPUT4_VOLUME {}',
    '0503003a000000': 'USER_INPUT4_MUTE {}',
    '0503003b000000': 'USER_INPUT4_CLIP_OL_PRE {}',
    '0503003c000000': 'USER_INPUT4_CLIP_OL_POST {}',
    '0503003d000000': 'USER_INPUT4_EFFECT_1_MUTE {}',
    '0803003e000000': 'USER_INPUT4_EFFECT_1_AMOUNT {}',
    '0503003f000000': 'USER_INPUT4_EFFECT_2_MUTE {}',
    '08030040000000': 'USER_INPUT4_EFFECT_2_AMOUNT {}',
    '05030041000000': 'USER_INPUT4_EQ_ENABLE {}',
    '08030042000000': 'USER_INPUT4_EQ_LOW_GAIN {}',
    '08030043000000': 'USER_INPUT4_EQ_MID_GAIN {}',
    '08030044000000': 'USER_INPUT4_EQ_HIGH_GAIN {}',
    '05030045000000': 'USER_INPUT4_COMPRESSOR_ENABLE {}',
    '08030046000000': 'USER_INPUT4_COMPRESSOR_AMOUNT {}',
    '05030047000000': 'USER_INPUT4_EXT_FX_MUTE {}',
    '08030048000000': 'USER_INPUT4_EXT_FX_SENDS {}',
    '08030049000000': 'USER_STEREO_INPUT1_VOLUME {}',
    '0503004a000000': 'USER_STEREO_INPUT1_MUTE {}',
    '0503004b000000': 'USER_STEREO_INPUT1_CLIP_OL_PRE {}',
    '0503004c000000': 'USER_STEREO_INPUT1_CLIP_OL_POST {}',
    '0503004d000000': 'USER_STEREO_INPUT1_EQ_ENABLE {}',
    '0803004e000000': 'USER_STEREO_INPUT1_EQ_LOW_GAIN {}',
    '0803004f000000': 'USER_STEREO_INPUT1_EQ_MID_GAIN {}',
    '08030050000000': 'USER_STEREO_INPUT1_EQ_HIGH_GAIN {}',
    '05030051000000': 'USER_EFFECT11_TYPEID {}',
    '05030052000000': 'USER_EFFECT12_TYPEID {}',
    '05030053000000': 'USER_EFFECT13_TYPEID {}',
    '05030054000000': 'USER_EFFECT14_TYPEID {}',
    '05030055000000': 'USER_EFFECT21_TYPEID {}',
    '05030056000000': 'USER_EFFECT22_TYPEID {}',
    '08030057000000': 'USER_MAIN_HEADPHONE_GAIN {}',
    '08030058000000': 'USER_MAIN_MASTER_GAIN {}',
    '050300590000000': 'USER_MAIN_MUTE {}',
    '0503005a0000000': 'USER_MAIN_CLIP_OL {}',
    '0803005b000000': 'USER_LOOPER_LEVEL {}',
    '0503005c000000': 'USER_LOOPER_STATE {}',
    '0503005d000000': 'USER_FX_BYPASS {}',
    '001e02': 'SD_RECORD'
}
class PacketLogger:
    def __init__(self, known_patterns):
        self.known_patterns = known_patterns
    def add_packet(self, packet):
        key = packet.hex()
        if key not in self.known_patterns:
            self.known_patterns[key] = 'Unknown Packet'
     
    def get_packet_description(self, packet):
        packet_hex = packet.hex()
        for pattern, description in self.known_patterns.items():
            if packet_hex.startswith(pattern):
                # Extract the variable part
                variable_part = packet_hex[len(pattern):]
                if variable_part:
                    # Convert the variable part to an integer and format the description
                    variable_value = int(variable_part, 16)
                    return description.format(variable_value)
                return description
        return 'Unknown Packet'
    def print_packet(self, label, packet):
        description = self.get_packet_description(packet)
        print(f'{label}: {description} - Raw: {packet.hex()}')
# Initialize the packet logger with known packet patterns
packet_logger = PacketLogger(known_packet_patterns)
# Buffer to store received bytes
buffer0 = bytearray()
buffer1 = bytearray()
# Flag to indicate if the script should keep running
running = True
# Function to read from a serial port
def read_from_port(ser, buffer, label, exclude_list):
    global running
    while running:
        if ser.in_waiting > 0:
            # Read one byte from serial port
            byte = ser.read()
         
            # Append byte to buffer
            buffer.append(byte[0])
         
            # Check if buffer contains start and end markers
            if buffer[-len(END_MARKER):] == END_MARKER:
                start_idx = buffer.find(START_MARKER)
                if start_idx != -1:
                    # Extract the packet (excluding markers)
                    packet = buffer[start_idx+len(START_MARKER):-len(END_MARKER)]
                 
                    # Convert packet to bytes before checking for exclusion
                    packet_bytes = bytes(packet)
                 
                    # Check if the packet should be excluded
                    if packet_bytes not in exclude_list:
                        # Use the packet logger to print and log the packet
                        packet_logger.print_packet(label, packet_bytes)
                 
                    # Remove processed bytes from buffer
                    del buffer[:start_idx+len(START_MARKER)+len(packet)+len(END_MARKER)]
# Signal handler to cleanly exit the script
def signal_handler(sig, frame):
    global running
    running = False
    print('Exiting...')
    ser0.close()
    ser1.close()
    sys.exit(0)
# Register the signal handler for SIGINT (Ctrl+C)
signal.signal(signal.SIGINT, signal_handler)
# Open serial ports
ser0 = serial.Serial('/dev/ttyUSB0', baudrate=115200)
ser1 = serial.Serial('/dev/ttyUSB1', baudrate=115200)
# Start threads to read from each port
thread0 = threading.Thread(target=read_from_port, args=(ser0, buffer0, 'Base', exclude_base))
thread1 = threading.Thread(target=read_from_port, args=(ser1, buffer1, 'Mixer', exclude_mixer))
thread0.start()
thread1.start()
# Join threads to main thread to keep the program running
thread0.join()
thread1.join()
So sieht der Spaß übrigens aus. Zwischen Mixer und Box ein Breakout PCB und dann zwei USB UART Adapter.
USB-UART-Adapter 1: Gnd an Orange, RX an Blue (liest die Nachrichten vom Mixer an die Box mit)
USB-UART-Adapter 2: Gnd an Orange-White, RX an Green (liest die Nachrichten von der Box an den Mixer mit)
USB-UART.jpg
USB-UART close-up.jpg

(Das schwarze UGREEN-Gerät ist übrigens nur ein USB-Hub, weil der Laptop kein USB-A hat.)
 
  • Gefällt mir
Reaktionen: 3 Benutzer
Ich habe nun doch noch ein paar mehr Pakete gefunden. Z.B.
Code:
'011a01': 'SNAPSHOT_RECALL {}',
'0101001a': 'SNAPSHOT_RECALL_TRIGGERED',
'01180102': 'TUNER_ON',
'01180002': 'TUNER_OFF',
'01010018': 'TUNER_COMMAND_RECEIVED',
Aber es gibt momentan auch noch 10-20 Pakete, die ich bisher nicht zuordnen konnte.

Das ist allerdings nicht schlimm. Man kann auch so schon erkennen, dass das Protokoll so primitiv ist, dass ich da problemlos eigene Pakete einschleusen könnte.
Es gibt keine Verschlüsselung, keine Sequenznummern und auch keine Checksummen.

Die Box und der Mixer sagen sich für die meisten Pakete nicht einmal gegenseitig, ob es überhaupt angekommen ist.
Das wiederum hat allerdings Implikationen für das Injecten von Paketen. Wenn ich jetzt z.B. in die Datenleitung vom Mixer an die Box ein Paket einschleuse, welches die Box stumm schaltet, dann wird der Mute-Button am Mixer nicht rot aufleuchten, obwohl die Box nun stumm ist.

Ich habe mir daraufhin mal die Start-Sequenz angeschaut, also was senden sich Box und Mixer eigentlich zu, wenn sie angeschaltet werden. Dabei habe ich beobachtet, dass die Box beim Starten wartet, bis der Mixer ein Lebenszeichen von sich gibt und dem Mixer dann sämtliche Einstellungen, wie sie vor dem Neustart gesetzt waren einzeln zuschickt. Also wirklich alles (Lautstärke, Gain, EQ, Kompressor, Effekte, ... und das für jeden Kanal, ...).
Danach ist der Mixer auf sich alleine gestellt sich alle Änderungen an den Reglern zu merken.

Meine Hoffnung ist nun aber, dass ich nach dem Einschleusen eines Pakets an die Box, einfach ein zweites Paket einschleusen kann, welches an den Mixer geht und diesem gezielt mitteilt, welche Einstellung sich nun geändert hat. Beispielsweise könnte ich ein USER_MAIN_MUTE Paket erst an die Box und dann an den Mixer senden. So müsste die rote LED am Mute-Button dann auch am Mixer aufleuchten. Ich denke die Chancen stehen gut, dass das funktionieren würde.

Erstmal muss ich leider auf neue Hardware warten. Ich hatte mir überlegt ein kleines Gerät zu bauen, was dann so programmiert werden könnte, dass man über diverse Schnittstellen mit der Mackie Showbox reden kann. Midi, Midi über Wifi, Midi über Bluetooth, HUI, Mackie Control oder direkt per TRS Fußschalter:

1719919205590.png

Das wäre so für schätzungsweise 10€ realisierbar. Die wirkliche Arbeit wäre dann die programmatische Übersetzung der Pakete in HUI, Mackie Control und Midi und das ganze natürlich auch in die andere Richtung.
Ich muss mal schauen wie viel Motivation ich dafür habe. Mein Use-Case ist erstmal eigentlich nur mit einem Doppel-Fußschalter den Looper zu bedienen und mit einem weiteren zwischen Presets hin und her zu wechseln. Dafür würden mir einfache TRS-Fußschalter auch reichen.

Ich vermute übrigens, dass Green-White und Blue-White auch UART benutzen und dafür da sind neue Firmware auf den Mixer zu spielen. Müsste ich bei Gelegenheit mal testen.





Wo ich gerade genauer drüber nachdenke, will ich eigentlich weg davon so viele separate Fußschalter zu haben. Wenn ich jetzt neben meinem Page-Turner, noch einen Preset-Wechsler und einen Looper-Controller liegen habe, wären das schon 3 Geräte...
Falls ich mal günstig an einen Xsonic Airstep Smart Controller kommen sollte, werde ich probieren Bluetooth-Midi zu implementieren (eine Grundlage dafür existiert sogar schon). So könnte ich dann 2 Schalter dem Looper zuweisen, weitere 2 für das Umschalten der Presets und den letzten lass ich einfach mit dem Tablet verbinden - dieser fungiert dann als Page-Turner.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: 3 Benutzer
Mal ne Frage: sind die seriellen Signale auf dem grünen und blauen Paar single ended TTL mit Massebezug oder vielleicht doch RS422, das eine differentielle Signalführung hätte?

Ansonsten lese ich hier interessiert mit, aber würde selber den Aufwand nicht treiben, obwohl ich das könnte.
Bei mir wartet seit ewigen Zeiten ein Arduino Micro darauf, dass er Tastbefehle in entweder Blättern am Tablet oder Start/Stop/Record für die DAW am PC entgegen nimmt und als USB Tastatur bzw USB MIDI schickt. (je nachdem, wo er gerade dran steckt).
 
  • Gefällt mir
Reaktionen: 1 Benutzer
Mal ne Frage: sind die seriellen Signale auf dem grünen und blauen Paar single ended TTL mit Massebezug oder vielleicht doch RS422, das eine differentielle Signalführung hätte?
Da ich Ethernet ja schon recht früh ausschließen konnte und UART auf 2 Drähten identifiziert habe, hatte ich auf eine differentielle Signalführung noch gar nicht getestet, aber ich schaue nachher mal ob grün-weiß und blau-weiß vielleicht eine separate UART-Verbindung für das Flashen der Firmware ist, die erst was tut, wenn man in den Firmware Flash Modus wechselt. Falls dem nicht so sein sollte, könnte ich mir das vorstellen, dass es differentiell ist. Ich kann ja einfach mal blau und blau-weiß statt blau und Gnd verbinden und schauen was rauskommt.



Auf der Mixer-Platine war auch noch ein weiterer UART-Anschluss fällt mir gerade ein. Den hatte ich beim Öffnen auch mal testweise ausgelesen mit 115200 baud, aber da kam immer nur das raus:
Screenshot from 2024-06-22 18-24-23.png





An DIY Page-Turnern bin ich auch immer interessiert. Ein ESP32-S3 wäre dafür bestimmt auch sehr interessant, weil er USB und Bluetooth LE kann.





@chris_kah Ich glaube du hast Recht. Ich bekomme die Signale auch wenn ich zwischen green und green-white bzw blue und blue-white messe, ganz ohne Gnd. :)
 
Zuletzt bearbeitet:
Wenn's differentiell ist, müsstest du auch blau-weiß bzw grün-weiß Signale gegenüber Gnd sehen, aber invertiert.
Sonst könnte es ja auch sein, dass diese Adern einfach auch GND sind.
 
Ach so, ne dann ist das wohl nicht der Fall. In dem Screenshot vom Logic Analyzer hatte ich ja grün, blau, blau-weiß, sowie grün-weiß gegen Gnd getestet.
Und bei der Durchgangsprüfung kam ja auch raus, dass nur Orange, Orange-Weiß und die Abschirmung mit GND verbunden sind.
 
Zuletzt bearbeitet:
Ich hab eben nochmal durch die Doku vom MIMXRT1010 geblättert und direkt unterstützen tut er RS-422 nicht. Er kann lediglich ganz einfaches UART.
Screenshot from 2024-07-03 14-36-25.png

In der zugehörigen Doku bzgl. FlexIO und UART-Emulation wird zwar RS-422 erwähnt, aber mit dem Hinweis, dass ein externer Treiberschaltkreis dafür nötig ist.
Da aber auf der Platine kein entsprechender IC vorhanden ist, gehe ich davon aus, dass es wirklich ganz primitiv UART ohne differenzielle Signalübertragung ist.
Eigentlich schade. Das wirft irgendwie auch die Frage auf, wie lang das Cat-5-Kabel überhaupt sein dürfte, damit noch alles funktioniert.





Ich möchte an dieser Stelle auch einmal kurz erwähnen, dass das von Mackie beigelegte Cat-5-Kabel (Hersteller: UGREEN) zwar auf den ersten Blick robust wirkt, aber dann recht schnell auffällt, dass die Plastik-Clips an den RJ45-Steckern komplett ungeschützt sind. Bei einem Produkt, wo man diese ständig ein- und aussteckt ist es m.M.n. nur eine Frage der Zeit bis diese abgebrochen sind.





Ich habe die Schaltung noch einmal ein bisschen überarbeitet:

ShowboxInterceptor2.png


So dürfte das ein bisschen übersichtlicher sein. Da dieser Mikrocontroller nur 3 UARTs hat und einer davon eigentlich für das Flashen vorgesehen, wäre es wahrscheinlich schlauer, die Midi-Anschlüsse Softwaregesteuert über 2 andere GPIO Pins laufen zu lassen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: 1 Benutzer
Ne, da müssten entsprechende Treiber verbaut sein. Meist im SO8 Gehäuse zwischen Prozessor und dem RJ45 Stecker. Kann aber sein, die Übertragung wure tatsächlich einfach auf TTL LEvel gemacht.

Bei den CAT Kabeln kann man ja einfach eins nachkaufen, falls es kaputt geht. Die sind meist alle so mit dem einfachen Plastikriegel. Und halten trotzdem erstaunlich viele Steckzyklen. Wie oft ich beruflich meinen Laptop schon an- und abgestöpselt habe ...
 
  • Gefällt mir
Reaktionen: 1 Benutzer
Ne, da müssten entsprechende Treiber verbaut sein.
Warum? Wenn kein RS-422 verwendet wird, dann müsste auch kein entsprechender Treiber verbaut sein.
Meist im SO8 Gehäuse zwischen Prozessor und dem RJ45 Stecker.
Auf den Fotos kann man eigentlich recht gut erkennen, dass kein solcher IC vorhanden ist. Da sind nur Mikrokontroller, SPI Flash und ein Haufen Schiebegerister.
Bei den CAT Kabeln kann man ja einfach eins nachkaufen, falls es kaputt geht. Die sind meist alle so mit dem einfachen Plastikriegel. Und halten trotzdem erstaunlich viele Steckzyklen. Wie oft ich beruflich meinen Laptop schon an- und abgestöpselt habe ...
Glaub mir, es hat seine Gründe, dass wenn du heute auf Amazon nach einem Cat-5-Kabel suchst, du im Prinzip nur noch welche mit Riegelschutz findest. Deine persönliche Erfahrung ist da nicht besonders repräsentativ. Ich habe z.B. schätzungsweise 10 alte Kabel bei denen auf mindestens einer Seite der Clip abgebrochen ist. Beim ständigen Transport passiert so etwas einfach schnell mal.
Aber ich wollte auch nur erwähnen, dass mir dieses Kabel negativ aufgefallen ist, weil ich bisher niemand anderen darüber reden hören habe. In meinen Augen ist dieses Kabel schon zum Zeitpunkt der Produktion ein Wegwerfprodukt gewesen. Sehr schade eigentlich, weil ein vernünftiges Kabel nun wirklich nicht mehr als ein paar zusätzliche Cent gekostet hätte.




Ich habe jetzt mal was kleines zusammengebastelt:

IMG_20240704_005904.jpg

Der Mikrocontroller empfängt nun die Daten beider Geräte und leitet sie an das jeweils andere weiter. Funktioniert bisher noch nicht richtig zuverlässig, aber vielleicht liegt es am Software Serial. Der neue Mikrocontroller den ich bestellt hatte kann das direkt mit Hardware basiertem UART. Mal schauen ob es einen Unterschied machen wird.
 
Zuletzt bearbeitet:
Ein Lob muss ich aber eigentlich auch mal an Mackie aussprechen, denn das Öffnen des Breakaway Mixers war unglaublich einfach. Man braucht wirklich nur die Schrauben unten zu lösen, welche auch nicht abgeklebt sind und schon ist das Gehäuse offen. Keine Hebelwerkzeuge nötig, denn auf Plastikösen/clips wurde gänzlich verzichtet. Die Kappen auf den Drehgebern und Potis waren leicht festgeklebt, aber lassen sich trotzdem abziehen und halten dann auch ohne diesen Kleber wunderbar. Die Knöpfe muss man aber wirklich nur entfernen, wenn man an die Frontseite der Platine möchte und da hat Mackie mitgedacht, denn das wichtigste ist auf der Rückseite der Platine.
 
Ich hatte leider noch keine Zeit den neuen Mikrocontroller in Betrieb zu nehmen, aber ich habe mal angefangen die Datenpakete auf Muster zu analysieren, um die einzelnen bytes/bits zu benamen. Das wird später beim Programmieren einiges erleichtern und erlauben neue Pakete schneller zu verstehen.
Die meisten Pakete (diese, die Mackie in der Firmware auch mit dem USER_-Präfix versehen hat), lassen sich wie folgt unterteilen:
(In der Grafik habe ich als Beispiel das USER_MAIN_MUTE Paket genommen.)
1720530867734.png


Alle "USER"-Pakete beginnen entweder mit der Bytefolge 05 03 00 oder 08 03 00. Darauf folgt ein Byte welches bestimmt, um welche Entität es hier geht (also z.B. Channel 1 Gain, Looper Status, Main Volume, ...). Dann folgen drei 00-Bytes. (Ich nehme mal an diese sind reserviert für zukünftige Firmware-Updates, falls es mal mehr als 256 Entitäten geben sollte oder falls der Wert einer Entität eine höhere Auflösung als 3 Bytes benötigt.) Dann folgen 1-3 Bytes, die den Wert der Entity bestimmen. (Abhängig davon ob der Mixer der die Box das Paket senden, handelt es sich bei dem Wert um den IST-Zustand den die Box dem Mixer mitteilt oder den NEUEN Zustand den der Mixer der Box zum Setzen übermittelt. Für Entitäten, die einem Schalter zugewiesen sind (z.B. Mute, Feedback-Elimination, Looper, Outdoor-PA-Mode, etc) handelt es sich hier um ein Byte (Beim Looper z.B. wenn ich mich recht entsinne 00, 01, 02 oder 03, abhängig davon ob der Knopf kurz, lang, einmal oder zweimal gedrückt wird. Beim den Mute Schaltern einfach nur 00 oder 01). Im Falle von Entitäten, dessen Wert über ein Poti oder Drehgeber gesetzt wird, handelt es sich um 3 Bytes die übertragen werden. In dem Falle ist das Paket dann eben zwei Bytes länger.

Es gibt aber auch Pakete, die sich nur bis einschließlich dem gelben Teil in der Grafik einordnen lassen. Das ist z.B. der Fall bei dem Paket, welches geschickt wird, wenn man das eingebaute Stimmgerät aktiviert oder deaktiviert
TUNER_ON : BE EF 01 18 01 02 EF BE
TUNER_OFF: BE EF 01 18 00 02 EF BE
 
So, ich habe nun mal den neuen Mikrocontroller verkabelt und eine kleine Library geschrieben mit der man UART-Verbindungen belauschen und manipulieren kann.
Den Quellcode habe ich auf GitHub bereitgestellt: https://github.com/T-vK/UARTInterceptor

So sieht die Bastelei bisher aus (wie man sieht noch gänzlich ohne MIDI oder TRS-Buchse):
IMG_20240710_223653.jpg

Rechts unten ist das Cat 5 Kabel von der Box eingesteckt und gegenüber auf dem Breadboard der Breakaway Mixer. Bis auf die beiden UART-Leitungen sind die RJ45 Buchsen direkt miteinander verdrahtet über das Flachbandkabel unten.
Die 12V Leitung und GND habe ich aufs Breadboard geführt, sodass sie den Mikrocontroller mit Strom versorgen können (unter dem Mikrocontroller befindet sich noch ein Step-Down-Converter, der aus den 12V, 5V macht (aus denen der Mikrocontroller wiederum 3,3V macht).
Die UART-Leitungen habe ich auch auf dem Breadboard zugänglich gemacht und durch den Mikrocontroller geschleust.

Unter Einbindung meiner UARTInterceptor Library habe ich dann folgenden C++ Code geschrieben:

C++:
#include <UARTInterceptor.h>

// Define UART pins
const uint8_t MIXER_RX = 16; // Mixer RX (Blue) | GPIO16 = TX2
const uint8_t MIXER_TX = 17; // Mixer TX (Green) | GPIO17 = RX2
const uint8_t BASE_RX = 10; // Base RX (Green) | GPIO10 = RX1 = SD3
const uint8_t BASE_TX = 9; // Base TX (Blue) | GPIO09 = TX1 = SD2

const UARTInterceptor::Direction TO_MIXER = UARTInterceptor::Direction::TO_A;
const UARTInterceptor::Direction TO_BASE = UARTInterceptor::Direction::TO_B;

UARTInterceptor interceptor(MIXER_RX, MIXER_TX, BASE_RX, BASE_TX);

void handlePacket(uint8_t* packet, size_t& length, UARTInterceptor::Direction direction) {
    if (direction == TO_BASE) {
        Serial.print("From Mixer: ");
    } else if (direction == TO_MIXER) {
        Serial.print("From Base:  ");
    }

    // Print the incoming packet
    for (size_t i = 0; i < length; ++i) {
        Serial.printf("%02X ", packet[i]);
    }
    Serial.println();
  
    // Packet manipulation example (inverting with bitwise NOT)
    //for (size_t i = 0; i < length; ++i) {
    //    packet[i] ^= 0xFF;
    //}
}

void injectPacket(const uint8_t* packet, size_t length, UARTInterceptor::Direction direction) {
    interceptor.injectPacket(packet, length, direction);
}

void setup() {
    Serial.begin(115200);
    interceptor.begin(115200, 115200); // Baud rates for Base and Mixer
    interceptor.setStartBytes(0xBE, 0xEF);
    interceptor.setEndBytes(0xEF, 0xBE);
    interceptor.setPacketHandler(handlePacket);
    interceptor.setPacketInjector(injectPacket);
    Serial.println("UART Interceptor ready");
}

void loop() {
    interceptor.loop();
}

Dadurch hat der Mikrocontroller nun volle Kontrolle über die UART-Schnittstelle und kann sämtliche Pakete in beide Richtungen mitlesen, manipulieren und sogar eigene Pakete einschleusen (injecten).

Das Mitlesen sieht erstmal ganz unspektakulär aus:

1720644454626.png







Der nächste Schritt wird sein die TRS-Buchsen zu verkabeln und ihnen Funktionen zuzuweisen (sodass man entsprechende Fußschalter daran anschließen kann).
Als nächstes muss ich mal schauen, ob ich noch weiter die übrigen Pakete analysiere oder ob ich mich schon daran mache einen MIDI-Übersetzer zu programmieren.
Dafür muss ich mir allerdings erstmal einiges anlesen, weil ich insbesondere in Mackie Control und Bluetooth MIDI bisher so gar nicht drinstecke.





Ach ja, hier mal eine Liste der Hardware, falls jemand sich auch sowas basteln wollen sollte:
Im nächsten Teil kommen dann hinzu:




Ich habe eben nochmal ein wenig darüber nachgedacht, was ich für ein Gehäuse nehmen soll, da es durch die ganzen Anschlüsse und den Mikrocontroller doch recht sperrig wird und ich eigentlich nicht vorhabe eine eigene Platine zu entwickeln. Vieleicht versuche ich einfach mal das Gehäuse vom Breakaway Mixer nachzubauen, also natürlich ohne die Bedienoberfläche, aber dann vorne mit den TRS, MIDI und RJ45-Anschlüssen. Ich glaube es könnte durchaus machbar sein das 3D zu drucken.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: 2 Benutzer
Habe die Schaltung noch einmal ein bisschen überarbeitet und korrigiert:

InterceptorSchematics.png

Ich hoffe, ich habe nun auch die richtigen Widerstände für den Optokoppler gewählt. Ich bin mir nicht ganz sicher, ob ich da mit den richtigen Daten gerechnet habe.
Aber laut MIDI Dokumentation sollten zumindest die 33 und 10Ohm Widerstände für den MIDI Out bei 3.3V passen.





Die Liste mit TODOs ist noch lang, aber ein neuer Punkt ist abgehakt: Ich habe die Bytes, welche die Lautstärke repräsentieren dekodiert.
Roh sehen die Daten erstmal recht willkürlich aus:
Code:
Main Volume:
From Mixer: BE EF 08 03 00 58 00 00 00 00 00 C0 40 EF BE - 16/16 (Max Vol)
From Mixer: BE EF 08 03 00 58 00 00 00 16 98 83 40 EF BE - 15/16
From Mixer: BE EF 08 03 00 58 00 00 00 7B 6B 05 40 EF BE - 14/16
From Mixer: BE EF 08 03 00 58 00 00 00 40 B7 D7 BD EF BE - 13/16
From Mixer: BE EF 08 03 00 58 00 00 00 D9 1A 1F C0 EF BE - 12/16
From Mixer: BE EF 08 03 00 58 00 00 00 F6 FF A2 C0 EF BE - 11/16
From Mixer: BE EF 08 03 00 58 00 00 00 3E 3F FF C0 EF BE - 10/16
From Mixer: BE EF 08 03 00 58 00 00 00 6A 2F 33 C1 EF BE - 9/16
From Mixer: BE EF 08 03 00 58 00 00 00 20 A4 6D C1 EF BE - 8/16
From Mixer: BE EF 08 03 00 58 00 00 00 D1 8F 98 C1 EF BE - 7/16
From Mixer: BE EF 08 03 00 58 00 00 00 17 78 C0 C1 EF BE - 6/16
From Mixer: BE EF 08 03 00 58 00 00 00 CE 4F F1 C1 EF BE - 5/16
From Mixer: BE EF 08 03 00 58 00 00 00 F3 23 18 C2 EF BE - 4/16
From Mixer: BE EF 08 03 00 58 00 00 00 F4 83 44 C2 EF BE - 3/16
From Mixer: BE EF 08 03 00 58 00 00 00 FF 2F 88 C2 EF BE - 2/16
From Mixer: BE EF 08 03 00 58 00 00 00 00 00 F0 C2 EF BE - 1/16 (Min Vol)

Wer gut aufgepasst hat, dem wird aufgefallen sein, dass sich immer nur 4 Bytes verändern. Also fokussieren wir uns mal auf diese:
Code:
00 00 C0 40  # Max Volume (16/16)
16 98 83 40  # 15/16
7B 6B 05 40  # 14/16
40 B7 D7 BD  # 13/16
D9 1A 1F C0  # 12/16
F6 FF A2 C0  # 11/16
3E 3F FF C0  # 10/16
6A 2F 33 C1  # 9/16
20 A4 6D C1  # 8/16
D1 8F 98 C1  # 7/16
17 78 C0 C1  # 6/16
CE 4F F1 C1  # 5/16
F3 23 18 C2  # 4/16
F4 83 44 C2  # 3/16
FF 2F 88 C2  # 2/16
00 00 F0 C2  # Min Volume (1/16)

Aber wenn wir diese nun einfach ins Dezimalsystem übersetzen, dann erhalten wir:
Code:
49216   # Max Volume (16/16)
379093824  # 15/16
2070611264 # ...
1085790141
3642367936
4143948480
1044381632
1781478337
547646913
3515848897
393789633
3461345729
4079163586
4102243522 # ...
4281305282 # 2/16
61634 # Min Volume (1/16)

Also äußerst willkürliche Zahlen, die nicht wie erwartet aufeinanderfolgend absteigend sind.

Nun stellt sich die Frage wie die Zahlen richtig zu interpretieren sind und da gibt es eine große Menge an Möglichkeiten.
Wir benutzen also lieber mal einen kleinen Online Analyzer, der die meisten Optionen für uns abfrühstückt und befüttern ihn mal mit dem ersten und letzten Wert aus unserer Liste:

1720724238746.png


"Float - Little Endian" fällt direkt ins Auge mit "6" als Maximalwert und "-120" als Minimalwert. Und siehe da es geht auf:

Code:
6  # Max Volume (16/16)
4.112315  # 15/16
2.084685  # 14/16
-0.10532999 # 13/16
-2.48601365  # 12/16
-5.093745  # 11/16
-7.97647  # 10/16
-11.1990757  # 9/16
-14.85257  # 8/16
-19.0702229  # 7/16
-24.0586376  # 6/16
-30.1639671  # 5/16
-38.0351067  # 4/16
-49.12886  # 3/16
-68.09374  # 2/16
-120  # Min Volume (1/16)





Ich habe aber leider nicht herausfinden können, wie diese Werte errechnet wurden.
Ich denke es sollte einen Funktion geben, welcher man einen Wert von 1 bis 16 übergeben kann, die dann einen Wert von -120 bis 6 ausgibt, aber leider konnte ich nichts finden was exakt passt. Vielleicht gibt's ja unter euch ein Mathegenie, welches mir helfen kann.
 
Zuletzt bearbeitet:
Bei den MIDI Werten bin ich mir auch nicht ganz sicher. MIDI In bis zum Optokoppler ist nach Norm, aber der Rest ...
Du kennst sicher dieses Schaltbild nach Wikipedia, ist aber für 5V (Und Through kann man hier ignorieren, ist ja auch nichts anderes als Out aber eben beim In abgegriffen)
StandardMIDIInterface.gif

Ausgehend vom 5V Interface komme ich auf einen Strom von (5V - 1.6V) / (200+200+200) Ohm = 5.3 mA (Die 1.6V wäre der Spannungsabfall in der LED des Optokopplers)
Für den gleichen Strom darf der Kreis dann in Summe 320 Ohm haben. Abzüglich der 220 Om beim Eingang bleiben also noch 100 Ohm für die Summe aus R11 und R10. Daher kommen mir deine beiden Werte zu niedrig vor.
 
Danke für deinen Input, vielleicht habe ich es auch einfach gänzlich falsch verstanden, aber meine Rechnung beruhte auf folgenden Infos aus dem Datenblatt:
1720732836497.png

...
1720732862227.png

Daraus habe ich entnommen:

Code:
4N35 forward voltage: 1.2V
4N35 forward current: 0.005A (at 3.3V)

Also:
Code:
Voltage drop: 3.3V - 1.2V = 2.1V
Resistor value: 2.1V / 0.005A = 420Ω
Nearest E12: 430Ω

Oder hätte ich für 1.2V rechnen müssen? Das wären, wenn ich das im Graphen richtig erkenne 0.001A und somit käme ich auf 1.2V / 0.001A = 1.2K. Oder bin ich hier ganz falsch?


Das Schaltbild aus der Wikipedia kannte ich nicht. Als 5V Vorbild diente bei mir:
1720733862826.png
 
Zuletzt bearbeitet:
Ok, dann arbeitet der Optokoppler mit eine Infrarot LED mit nur 1.2 V
Den Strom habe ich so gerechnet (Strom fließt)
Aus 5V über 220 Ohm raus zur MIDI Buchse, dann wieder 220 Ohm, dann die LED im Optokoppler, dann wieder raus und beim Sender nochmals 220 Ohm. Den Strom habe ich ermittelt und dann geschaut, welchen Widerstand ich brauche für den gleichen Strom bei 3.3V
Mit 1.2V für die LED komme ich dann auf 6.3 mA und dann auf ein Summe von 333 Ohm. Abzüglich der 220 Ohm beim Optokoppler bleiben dann 113 Ohm für die beiden Widerstände beim Sender. Also muss die Summe aus R10 und R11 aus deinem Bild 113 Ohm sein und bei dir ist das nur 43 Ohm. Außer du hast dich vertippt und die 10 Ohm sollten eigentlich 100 Ohm sein.
Ob das jetzt 560 Ohm, 470 Ohm oder 420 Ohm als Arbeitswiderstand für den Ausgangstransistor sind ist relativ egal.
Aber die 10 Ohm (R12 in deinem Schaltbild) an der Basis des Treibertransistors sollten schon 10 kOhm sein, sonst kommt da gar nichts an. Oder hast du den als Emitterwiderstand drin (weil es den dann nicht bräuchte)?
 
Die Werte für R10 und R11 habe ich einfach aus der Tabelle entnommen:
signal-2024-07-12-08-31-54-157.jpg

Seite 2 - MIDI Spezifikation

Oder meinst du, das ist nicht richtig?





In der Zwischenzeit habe ich mal ein kleines Python Script geschrieben um per Bruteforce die Funktion zu finden, welche die Drehgeberposition in dB umrechnet, aber das nächste was ich finden konnte war
f(x) = -341.7109 * x + 1.3457^(-1) + 25.6786
Gerundet komme ich damit auf:
Code:
1 | -120
2 | -76
3 | -53
4 | -38
5 | -28
6 | -21
7 | -15
8 | -11
9 | -7
10 | -4
11 | -2
12 | 0
13 | 2
14 | 3
15 | 5
16 | 6

1720776315595.png

Ist zwar dicht dran, aber m.M.n. dennoch nicht zufriedenstellend.

Daher werde ich stattdessen nun einfach die 16 Werte hardcodieren. Es erscheint sowieso sicherer, nur die Werte zuzulassen, die der Breakaway Mixer auch von sich aus hätte setzen können.




Ich habe eben noch eine neue Erkenntnis über das Protokoll gewonnen: Das erste Byte nach den Start-Bytes gibt an wie groß der Teil vor den End-Bytes jedes Pakets ist.

Wir wissen nun also:
  • Alle Pakete...
    • ...beginnen mit einem Header, welcher mit den Start-Bytes BE EF beginnt.
    • ...dessen drittes Byte 00 ist, sind statisch, bestehen aus 7 Bytes und haben keinen Body.
    • ...dessen drittes Byte größer als 01 ist,
      • haben einen 5 Bytes großen Header
      • haben einen Typ (Byte #4) (Für die USER-Pakete ist dieser immer 03. Bei anderen Paketen habe ich 09, 04 und 05 beobachten können.)
      • haben ein Byte (Byte #5), dessen Funktion mir bisher nicht klar ist, welches während meiner Untersuchung bei allen USER-Paketen 00 war. Der einzige andere Wert, den ich dort für nicht-USER-Pakete beobachtet habe war 01 und in einem Fall 02.
      • haben einen dynamischen Body,
        • dessen Größe dem Byte #3 entspricht.
        • der mit einer ein Byte langen Entitäts-ID in Byte #6 beginnt (eine Entität ist bspw. Lautstärke eines Kanals, der Bass-EQ eines Kanals oder der Looper Zustand)
        • der mit drei 00-Bytes beginnt (Byte #7, #8 und #9), die bisher scheinbar keine Bedeutung haben, aber reserviert sind
        • der mit einem Wert endet, welcher aus den restlichen Bytes, abzüglich des Footers besteht. Dieser ist meiner Beobachtung nach entweder ein Byte lang oder vier Bytes. In letzterem Fall sind die Bytes als Little Endian Float zu interpretieren.
    • ...enden mit einem Footer, welcher einfach aus den zwei End-Bytes EF BE besteht.
Etwas visueller ausgedrückt also:
Pakete mit dynamischem Body (mit Beispiel):
Code:
[                  HEADER                ][           BODY           ][   FOOTER   ]
[START SEQUENCE][BODY SIZE][TYPE][UNKNOWN][ENTITY ID][RESERVED][VALUE][END SEQUENCE]
[   BE    EF   ][   05    ][ 03 ][  00   ][    59   ][00 00 00][  01 ][  EF    BE  ]

Pakete ohne Body (mit Beispiel):
Code:
[                   HEADER                    ][   FOOTER   ]
[START SEQUENCE][BODY SIZE = 00][TYPE][UNKNOWN][END SEQUENCE]
[   BE    EF   ][      00      ][ FF ][  00   ][  EF    BE  ]
 
Zuletzt bearbeitet:
Oder meinst du, das ist nicht richtig?
Dann ist dort vermutlich ein Tippfehler drin, denn die Widerstandswerte für 3.3V sind doch deutlich zu niedrig.
Ich vermute mal, der 10 Ohm sollte eigentlich 100 Ohm sein und dann passt das.
Ok mit 8mA wird der Optokoppler vermutlich eher nicht sterben, aber es ist schon ein Unterschied zu den sonst ca. 6mA.
Egal, wird schon irgendwie funktionieren.

Insgesamt finde ich dein Reverse Engineering schon sehr interessant, würde aber selber den Aufwand nicht betreiben wollen.
 
Verstehe, ja ich schaue mal. Vielleicht nehme ich sonst auch einfach einen anderen Optokoppler für den andere schon die Arbeit gemacht haben. Die MIDI-Spezifikation selbst nennt ja z.B. den PC-900V und den 6N138.

In der Zwischenzeit habe ich daran gearbeitet meine neuen Erkenntnisse über die Paketstruktur in C++ umzusetzen. Nun kann ich die Daten schon sehr viel besser einordnen:
1720901375393.png
 
Zuletzt bearbeitet:

Unser weiteres Online-Angebot:
Bassic.de · Deejayforum.de · Sequencer.de · Clavio.de · Guitarworld.de · Recording.de

Musiker-Board Logo
Zurück
Oben