serial match

In MaxMSP there is a great object called [match]. It is specially useful for parsing data from a serial port. In SuperCollider there is nothing like that build-in, but one can do the same with the class extension below.

Bascially this method will match an incoming array of specific bytes where nil means match any value.
For example port.match([1, 2, nil, 3]); will return a match for 1, 2, 55, 3 but not for 1, 4, 55, 10.

Save the following in a file called extSerial.sc , move the file to your SuperCollider extensions folder and recompile...

//f.olofsson
+SerialPort {
        match {|arr|
                var byte, index= 0;
                var res= arr.copy;
                while({index<arr.size}, {
                        byte= this.read;
                        if(arr[index].isNil or:{byte==arr[index]}, {
                                res[index]= byte;
                                index= index+1;
                        }, {
                                ^nil;
                        });
                });
                ^res;
        }
}

To test it upload the following code to an Arduino...

//arduino test code - send six 10-bit values

#define NUM_ANALOG 6
#define UPDATERATE 20  //ms to wait between each reading

void setup() {
  Serial.begin(57600);
}
void loop() {
  Serial.write(200);  //header
  Serial.write(201);
  for (byte i = 0; i < NUM_ANALOG; i++) {
    int data = analogRead(i);
    Serial.write(data & 255); //lsb
    Serial.write(data >> 8); //msb
  }
  Serial.write(202);  //footer
  delay(UPDATERATE);
}

and then run this code in SuperCollider (adapt serial port name where it says EDIT)...

//supercollider test code - read six 10bit values
SerialPort.listDevices;
(
var num_analog= 6;
var port= SerialPort("/dev/cu.SLAB_USBtoUART", 57600);  //EDIT
var arr= [200, 201, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 202];  //200, 201 header, 202 footer and nil the data
r= Routine.run({
        inf.do{|i|
                var res;
                res= port.match(arr);
                if(res.notNil, {
                        num_analog.do{|i|
                                var lsb= res[i*2+2];
                                var msb= res[i*2+3];
                                ((msb<<8)+lsb).postln;
                        };
                });
        };
});
CmdPeriod.doOnce({port.close});
)

r.stop