Sending messages to Pure Data using fudi
/Isn’t this exciting? I’m just on the brink of sending useful messages between my PICO powered controller (which has buttons and a display) and a Pure Data patch running on a Raspberry Pi. Last time I got the comport working now that I can send raw data bytes between the devices. Now I want to see about sending packets of useful data.
The man behind Pure Data (Miller Puckette) has thought of this. He’s invented the FUDI protocol for sending messages. It’s a very simple text based protocol which means that it will be very easy to make the PICO assemble FUDI messages for the Pure Data patch to read.
Lets take a look at the kind of message that I might want to send from the controller to a Pure Data patch:
encoder 97 5;
The controller generates messages like this when an encoder is turned. The word encoder tells the receiver that a new encoder value is coming The first number (97) is the new encoder value. The second number (5) is the number of the encoder. The encoder message is generated by Circuit Python running inside a PICO which is connected to the encoders and sends messages out over the serial port. The Python code that sends these messages is:
b1 = int(self.active_config.serial_channel)
b2 = int(self.active_config.controller_value)
message = "encoder " + str(b1) + " " + str(b2) + ";\n"
send_buffer = bytes(message,"ascii")
print("Sending to serial:", send_buffer)
self.client.serial_port.write(send_buffer)
This code takes the two values and puts them into the variables b1 and b2. Then it creates the message string. Next it makes a byte array containing the message in ASCII. Finally it uses the serial_port_write method provided by the serial port to send the entire string out to the Pure Data patch. Now lets take a look at how this serial data stream is received.
My blog post here shows how to get a Pure Data patch to receive data from a com port. At the bottom of the patch you can see a data flow coming out of the comport object and ending in a rather enigmatic way. The patch decodes the input message and routes it to the required destination. It uses a Pure Data loop to assemble the message (which is a line of text) and then uses FUDI (Fast Universal Digital Interface) to parse the text and extract a message which is then routed to the appropriate destination.
Remember that what is happening is that individual bytes are arriving, one at a time, and need to be assembled into a line of text. The text is terminated by a newline character (10) or a return (13).
The sel object at the top of the patch takes the input stream and feeds it to one of three outputs. If the input value is 10 or 13 (the characters that mark the end of the list) the list is triggered to push its contents into the fudiparse object. If the input value is anything else (this is what the right hand output from sel is for) the newly received character is added to the start of the list, building up the line of text.
The fudiparse block takes the buffer containing the incoming message (in our case “encoder 97 5” and uses it to generate a Pure Data message that contains the values “encoder”, 97 and 5. This message is then sent into a route object. This looks at the first item in the message and then sends the rest of the message (the values 97 and 5) to the output that matches that name. In the case of the patch above, this means that the two encoder value are sent to a message endpoint called “encoderReceived”. Patches in other parts of the of the application can receive these messages and act on them.
You should be able to work out that the decoder above can also respond to an incoming message called button, which tells the Pure Data application when a button was pressed.