The XCtrl story

There's a brilliant document written by 'FK' that basically reverse-engineered the XCtrl protocol for when talking over a USB connection. I've been building on that work to speak to the desk over the network directly.

The main communication takes place on UDP port 10111, and uses the same messages as in the rest of the doc. What's most interesting though is that you can chain multiple messages into the same packet (size limiting of course). One of the limitations mentioned in that doc is that the meters can only be updated in turn, every ~1.2 seconds. But chaining 8 updates into the same packet, and they all update at once. This also applies to the other controls of the desk, so for getting feedback into the desk, you can pretty much spit an entire surface update at it as often as you like, without having to worry about individual changes.

For experimenting, I've been playing with a 'client' of sorts written in Ruby (what else). It's based around independent threads for sending and receiving, and a third worker thread to deal with things coming in.

@incoming_xctrl = Queue.new
@outgoing_xctrl = Queue.new
@xctrl = UDPSocket.new
@xctrl.bind('192.168.x.x', 10111)

# sender
Thread.new do
  loop do
    message = @outgoing_xctrl.pop(true) rescue next
    @xctrl.send([0xf0, *message, 0xf7].pack('C*'), 0, '192.168.x.x', 10111)
  end
end

# receiver
Thread.new do
  loop do
    message = @xctrl.recv(32) or next
    @incoming_xctrl.push(message)
  end
end

# processor
Thread.new do
  packet = @incoming_xctrl.pop(true) rescue nil
  next unless packet
  
  # do something fun
end

The X-Touch maintains a heartbeat, to make sure it won't 'disconnect' from our client. This is really plainly built at the moment:

HEARTBEAT = [0x00, 0x00, 0x66, 0x14, 0x00]

message = packet.to_hex_string
case message
when "f0 00 20 32 58 54 00 f7" then @outgoing_xctrl << HEARTBEAT
end

It seems to keep the X-Touch happy, and means we can play with everything else that the desk can spit out. Next up, VBAN.