fcb_looper/FCB1010_SysEx.md
2025-05-25 23:53:46 +02:00

8.1 KiB

You're absolutely right - the current document lacks the specific technical details needed for implementation. Let me examine the repositories more closely for implementation details.

I'll need to search for the specific Python file in the repository.

I need to look at the actual code to get the detailed specification. Let me search for the source code directly.

Let me try to find a specific PDF that might contain detailed SysEx specifications:

Now I have the detailed specification we need! Let me update our documentation with this complete information:

FCB1010 SysEx Protocol Documentation

1. Introduction

This document describes the System Exclusive (SysEx) protocol used by the Behringer FCB1010 MIDI Foot Controller. The protocol allows configuration of the device's global settings and individual presets through MIDI SysEx messages. This documentation is based on official Behringer documentation and reverse-engineered implementations.

2. SysEx Message Structure

2.1 General Format

FCB1010 SysEx messages follow this general structure:

F0 00 20 32 <global-channel> 0C <data...> F7

Where:

  • F0: SysEx Start byte
  • 00 20 32: Behringer's manufacturer ID
  • <global-channel>: Global MIDI channel
  • 0C: Device ID for FCB1010
  • <data...>: Message payload (in 7-bit format)
  • F7: SysEx End byte

2.2 Data Encoding Scheme

Due to MIDI's 7-bit transmission limitation, the FCB1010 uses a special encoding scheme for 8-bit data:

  • Data is transmitted in packets of 8 bytes
  • The first 7 bytes contain the lower 7 bits of each data byte
  • The 8th byte contains the most significant bits (MSBs) of the preceding 7 bytes
  • This allows reconstructing the full 8-bit values from the 7-bit MIDI data

For example, to transmit 7 bytes with the following MSBs: 0,1,0,0,1,1,0:

  • The 8th byte would be: 01001100 (binary) or 4C (hex)
  • Each bit position in this byte corresponds to the MSB of one of the preceding 7 bytes

3. Memory Map

The FCB1010 memory is organized as follows:

3.1 Preset Data

  • Addresses: 0x000 to 0x640
  • Structure: 100 presets (10 banks of 10 presets each)
  • Preset Size: 16 bytes per preset

3.2 Global Configuration

  • Addresses: 0x7E0 to 0x7E9
  • Contains global MIDI channel assignments for each function

4. Preset Structure

Each preset occupies 16 bytes and contains the following data:

Offset Description Notes
0x0 Program Change 1 Program number
0x1 Program Change 2 Program number
0x2 Program Change 3 Program number
0x3 Program Change 4 Program number
0x4 Program Change 5 Program number
0x5 Controller 1 Controller number
0x6 Controller 1 Value Value with Relay 1 status in MSB
0x7 Controller 2 Controller number
0x8 Controller 2 Value Value with Relay 2 status in MSB
0x9 Expression Pedal A Controller number
0xA Expression Pedal A Lower Value Minimum value
0xB Expression Pedal A Upper Value Maximum value
0xC Expression Pedal B Controller number
0xD Expression Pedal B Lower Value Minimum value
0xE Expression Pedal B Upper Value Maximum value
0xF Note MIDI note number

4.1 Special Fields

  • Switch Relay Status: The MSB of Controller 1 Value contains Relay 1 status; the MSB of Controller 2 Value contains Relay 2 status
  • Program Change Values: Range 0-127, correspond to MIDI program changes 1-128
  • Controller Numbers: Range 0-127, standard MIDI CC values
  • Note Values: Range 0-127, standard MIDI note numbers

5. Memory Addressing

Each preset's starting address is calculated as:

Address = 0x000 + (preset_number * 0x10)

Where preset_number ranges from 0 to 99:

  • Bank 0, Preset 1 = Preset 0 = Address 0x000
  • Bank 0, Preset 2 = Preset 1 = Address 0x010
  • Bank 0, Preset 10 = Preset 9 = Address 0x090
  • Bank 1, Preset 1 = Preset 10 = Address 0x100
  • ...and so on

6. Global MIDI Channel Configuration

The MIDI channels for each function are stored at addresses 0x7E0 to 0x7E9:

Address Function
0x7E0 Program Change 1 Channel
0x7E1 Program Change 2 Channel
0x7E2 Program Change 3 Channel
0x7E3 Program Change 4 Channel
0x7E4 Program Change 5 Channel
0x7E5 Controller 1 Channel
0x7E6 Controller 2 Channel
0x7E7 Expression Pedal A Channel
0x7E8 Expression Pedal B Channel
0x7E9 Note Channel

Values range from 0-15, corresponding to MIDI channels 1-16.

7. Sending SysEx to FCB1010

To send configuration data to the FCB1010:

  1. Put the FCB1010 in SysEx receive mode:

    • Hold DOWN button while powering on
    • Press DOWN again to enter CONFIG mode
    • Press footswitch 7 (SYSEX RCV)
  2. Send the SysEx message with the following structure:

    F0 00 20 32 <global-channel> 0C <encoded-data> F7
    
  3. The FCB1010 will automatically exit receive mode once data is received successfully

8. Receiving SysEx from FCB1010

To retrieve the current configuration from the FCB1010:

  1. Put the FCB1010 in SysEx send mode:

    • Hold DOWN button while powering on
    • Press UP until CONFIG LED lights
    • Press footswitch 6 (SYSEX SEND)
  2. Capture the SysEx data sent from the FCB1010

  3. Decode the received data using the 7-bit to 8-bit conversion method described above

9. Implementation Example (Pseudocode)

9.1 Encoding Data for SysEx Transmission

function encode_data_for_sysex(data):
    encoded_data = []
    for i in range(0, len(data), 7):
        chunk = data[i:i+7]
        while len(chunk) < 7:
            chunk.append(0)  # Pad last chunk if needed
        
        msb_byte = 0
        for j in range(7):
            if j < len(chunk):
                # Extract MSB from each byte and put in msb_byte
                msb_byte |= ((chunk[j] & 0x80) >> 7) << j
                # Clear MSB from original byte
                encoded_data.append(chunk[j] & 0x7F)
        
        encoded_data.append(msb_byte)
    
    return encoded_data

9.2 Decoding Received SysEx Data

function decode_sysex_data(encoded_data):
    decoded_data = []
    for i in range(0, len(encoded_data), 8):
        if i + 7 >= len(encoded_data):
            break  # Not enough data for a complete chunk
        
        msb_byte = encoded_data[i+7]
        for j in range(7):
            if i + j < len(encoded_data) - 1:  # Skip the MSB byte
                byte_value = encoded_data[i+j]
                # Apply MSB from msb_byte
                if (msb_byte & (1 << j)) != 0:
                    byte_value |= 0x80
                decoded_data.append(byte_value)
    
    return decoded_data

9.3 Creating a Preset Configuration

function create_preset(bank, preset_number, config):
    preset_index = (bank * 10) + preset_number - 1  # Convert to 0-99 index
    preset_address = 0x000 + (preset_index * 0x10)
    
    preset_data = [
        config.program_change_1,
        config.program_change_2,
        config.program_change_3,
        config.program_change_4,
        config.program_change_5,
        config.controller_1_number,
        config.controller_1_value | (config.relay_1_status << 7),
        config.controller_2_number,
        config.controller_2_value | (config.relay_2_status << 7),
        config.expression_pedal_a_controller,
        config.expression_pedal_a_min,
        config.expression_pedal_a_max,
        config.expression_pedal_b_controller,
        config.expression_pedal_b_min,
        config.expression_pedal_b_max,
        config.note
    ]
    
    return (preset_address, preset_data)

10. Compatibility Notes

  • This protocol specification is based on FCB1010 firmware version 2.5
  • The protocol may differ for other firmware versions or third-party firmware
  • Large SysEx dumps may not work reliably with some MIDI-USB interfaces due to buffer limitations

11. References

  1. Behringer FCB1010 SysEx File Structure (2003), Behringer Spezielle Studiotechnik GmbH
  2. riban-bw/fcb1010 GitHub repository - Python implementation for FCB1010 SysEx communication
  3. trafficpest/fcbtool GitHub repository - C-based tool for managing FCB1010 presets