This example is for Wiring version 0023+. If you have a previous version, use the examples included with your software. If you see any errors or have comments, please let us know.
WIRING_OSC 0004
Firmware to send OSC messages from a Wiring board to a PC and to receive OSC messages sent from the PC.
Right now, only messages with a single integer argument are supported in either direction.
Uses the following serial OSC format: 0xBE MSG_LENGTH OSC_MESSAGE CHECKSUM ---- ---------- ---/.../-- -------- 1b 1byte 4*n bytes 1byte
PROTOCOL DETAILS Digital pins 0..39, analog inputs 0..7 are supported. PWM output on PWM pins 0..5 is supported as well. Below, the notation [0..39] means: any number from 0 to 39. The notation [0|1] means: either 0 or 1. Pin numbers are always part of the OSC address. The single integer argument for each OSC message represents either HIGH/LOW, or an 8bit analog value.
PC->WIRING MESSAGE FORMAT /pinmode/[0..39] [0|1] - set a pin to input or output mode
/report/adc [0|1] - turn all analog pin reporting on/off (Default: off) /report/adc/[0..7] [0|1] - set analog pin reporting for one pin on/off /report/in [0|1] - turn digital pin reporting on/off (default: on)
/out/[0..39] [0|1] - set a digital pin to [low|high] /pwm/[0..5] [0..1023] - set duty on a pwm-enabled pin
ARDUINO->PC PROTOCOL /in/[0..39] [0|1] - a digital input pin changed to [high|low] /adc/[0..7] [0..255] - analog input value changed to [0..255] NOTE: input pins use pull-up resistors and are HIGH by default. Therefore, 0 means HIGH, 1 means LOW (pulled to ground).
EXAMPLES: PC->ARDUINO /pinmode/5 0 - set pin 5 to INPUT /pinmode/9 1 - set pin 9 to OUTPUT /out/9 0 - set pin 9 to LOW /out/12 1 - set pin 12 to HIGH /pwm/4 512 - set PWM duty on PWM pin 4 to 512 (50%) /report/in 1 - turn digital input pin reporting on /report/adc/4 0 - turn reporting of analog input 4 off
EXAMPLES: WIRING->PC /in/4 1 - digital input pin 4 pulled to ground /adc/2 512 - analog input pin2 read 512 (=2.5V)
DEFAULT STARTUP CONFIGURATION - Pins 0-39 are all set to input, digital reporting enabled (change variable reportDigital to False to disable by default) - Analog reporting is disabled (change variable reportAnalog to 0xFF to enable by default)
NOTES: - Pins 32,33 cannot be used (needed for Rx/Tx) - Resolution on analog in and out is 10 bit. - So far, not much error checking for bounds done - In testing with pd and [serialIO], message bytes tend to get "stuck" in a buffer either on PC or on Wiring board side when sending to hardware, with the effect that an OSC message doesn't get processed on the board until the *next* message arrives, or until a few 0x00 characters are sent. This does not appear to happen wir Arduino_Osc. - On the tested board, pin Analog In 0 corresponds to analogRead(7) and pins 1..7 correspond to analogRead(0)..analogRead(6).
MIT License: Copyright (c) 2008 Bjoern Hartmann, Stanford HCI Group Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bjoern@cs.stanford.edu 11/23/2008
Firmware to send OSC messages from a Wiring board to a PC and to receive OSC messages sent from the PC.
Right now, only messages with a single integer argument are supported in either direction.
Uses the following serial OSC format: 0xBE MSG_LENGTH OSC_MESSAGE CHECKSUM ---- ---------- ---/.../-- -------- 1b 1byte 4*n bytes 1byte
PROTOCOL DETAILS Digital pins 0..39, analog inputs 0..7 are supported. PWM output on PWM pins 0..5 is supported as well. Below, the notation [0..39] means: any number from 0 to 39. The notation [0|1] means: either 0 or 1. Pin numbers are always part of the OSC address. The single integer argument for each OSC message represents either HIGH/LOW, or an 8bit analog value.
PC->WIRING MESSAGE FORMAT /pinmode/[0..39] [0|1] - set a pin to input or output mode
/report/adc [0|1] - turn all analog pin reporting on/off (Default: off) /report/adc/[0..7] [0|1] - set analog pin reporting for one pin on/off /report/in [0|1] - turn digital pin reporting on/off (default: on)
/out/[0..39] [0|1] - set a digital pin to [low|high] /pwm/[0..5] [0..1023] - set duty on a pwm-enabled pin
ARDUINO->PC PROTOCOL /in/[0..39] [0|1] - a digital input pin changed to [high|low] /adc/[0..7] [0..255] - analog input value changed to [0..255] NOTE: input pins use pull-up resistors and are HIGH by default. Therefore, 0 means HIGH, 1 means LOW (pulled to ground).
EXAMPLES: PC->ARDUINO /pinmode/5 0 - set pin 5 to INPUT /pinmode/9 1 - set pin 9 to OUTPUT /out/9 0 - set pin 9 to LOW /out/12 1 - set pin 12 to HIGH /pwm/4 512 - set PWM duty on PWM pin 4 to 512 (50%) /report/in 1 - turn digital input pin reporting on /report/adc/4 0 - turn reporting of analog input 4 off
EXAMPLES: WIRING->PC /in/4 1 - digital input pin 4 pulled to ground /adc/2 512 - analog input pin2 read 512 (=2.5V)
DEFAULT STARTUP CONFIGURATION - Pins 0-39 are all set to input, digital reporting enabled (change variable reportDigital to False to disable by default) - Analog reporting is disabled (change variable reportAnalog to 0xFF to enable by default)
NOTES: - Pins 32,33 cannot be used (needed for Rx/Tx) - Resolution on analog in and out is 10 bit. - So far, not much error checking for bounds done - In testing with pd and [serialIO], message bytes tend to get "stuck" in a buffer either on PC or on Wiring board side when sending to hardware, with the effect that an OSC message doesn't get processed on the board until the *next* message arrives, or until a few 0x00 characters are sent. This does not appear to happen wir Arduino_Osc. - On the tested board, pin Analog In 0 corresponds to analogRead(7) and pins 1..7 correspond to analogRead(0)..analogRead(6).
MIT License: Copyright (c) 2008 Bjoern Hartmann, Stanford HCI Group Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bjoern@cs.stanford.edu 11/23/2008
#define VERSION 4
#define MIN_A2D_DIFF 4 // threshold for reporting a2d changes
#define MAX_LENGTH 24 // size of buffer for building OSC msgs
#define SERIAL_SPEED 38400
#define FIRST_DIGITAL_PIN 0
#define LAST_DIGITAL_PIN 39
#define NUM_DIGITAL_PINS 40
#define NUM_PORTS 5
#define FIRST_ANALOG_PIN 0
#define LAST_ANALOG_PIN 7
#define NUM_ANALOG_PINS 8
#define RX_PIN 32
#define TX_PIN 33
// define state constants for parsing FSM
#define OSC_RXOP_WAITFORSTART 0
#define OSC_RXOP_READSIZE 1
#define OSC_RXOP_READADDR 2
#define OSC_RXOP_READTAG 3
#define OSC_RXOP_READARG 4
#define OSC_RXOP_READCHECKSUM 5
//removed READMSG
#define OSC_RXOP_SKIPMSG 7
#define OSC_RXOP_READARG1BYTE1 8
#define OSC_RXOP_READARG1BYTE2 9
#define OSC_RXOP_READARG1BYTE3 10
#define OSC_RXOP_READARG1BYTE4 11
#define OSC_RXOP_READTAGBYTE1 12
#define OSC_RXOP_READTAGBYTE2 13
#define OSC_RXOP_READTAGBYTE3 14
#define OSC_RXOP_READTAGBYTE4 15
#define OSC_MAX_RX_MSG_SIZE 32
int incomingByte = 0; // for incoming serial data
int k = FIRST_ANALOG_PIN;
byte inputBuffer[NUM_PORTS] = {0xFF}; // holds previous values of PORTB and PORTD (pins 0..7); start all high because of pull-ups
int a2dBuffer[NUM_ANALOG_PINS] = {0x00}; // holds previous A2D conversion values
char oscBuffer[MAX_LENGTH]={0x00}; // holds outgoing OSC message
byte pinDir[NUM_PORTS] = {0x00}; //buffer that saves pin directions 0=input; 1=output; default: all in
char prefixReport[] = "/report/";
char prefixPinmode[] = "/pinmode/";
char prefixOut[] = "/out/";
char prefixPwm[] = "/pwm/";
char prefixIn[]="/in/";
char prefixA2d[]="/adc/";
char prefixReset[]="/reset"; //TODO: implement
char oscOutAddress[10]={0x00}; //string that holds outgoing osc message address
char* numbers[] = {"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16",
"17","18","19","20","21","22","23","24","25","26","27","28","29","30",
"31","32","33","34","35","36","37","38","39"};
byte pwmPinMap[6] = {37, 36, 35, 31, 30, 29};
// which values should be reported?
byte reportAnalog = 0x00; //bitmask - 0=off, 1=on - default:all off
boolean reportDigital = true; //no per-pin reporting for analog
//////parser variables////////
static byte oscRxNextOp = OSC_RXOP_WAITFORSTART; //keeps track of current state
// space for buffer in RAM
static char oscRxData[OSC_MAX_RX_MSG_SIZE];
byte oscRxMsgSize; // size of incoming msg
byte oscRxReadBytes; //number of bytes read
byte *oscRxAddr;
unsigned long oscRxIntArg1; //int argument of message
byte oscRxChecksum;
/***********************************************
* SETUP - open serial comm and initialize pins
***********************************************/
void setup() {
int i;
reportAnalog=0x00;
reportDigital=true;
// set all pins as inputs
for(i=FIRST_DIGITAL_PIN; i<=LAST_DIGITAL_PIN; i++) {
if((i!=RX_PIN) && (i != TX_PIN)) {
pinMode(i,INPUT);
digitalWrite(i,HIGH); // use pull-ups
}
}
Serial.begin(SERIAL_SPEED);
}
/***********************************************
* LOOP - poll pin values and read incoming
* serial communication
***********************************************/
void loop() {
// check all digital inputs
if(reportDigital) {
checkDiscreteInputs();
}
// check one analog input per loop
if(reportAnalog & (1<<k)) {
checkAnalogInput(k);
}
k=(k+1)%NUM_ANALOG_PINS;
// handle all received serial bytes
while (Serial.available() > 0) {
incomingByte = Serial.read() & 0xFF;// read byte - truncate to 8bits to be safe
oscRxHandler(incomingByte); // hand to message parser
}
}
/***********************************************
* Check all digital inputs and call
* oscSendMessageInt() if values has changed
***********************************************/
void checkDiscreteInputs() {
int i;
byte state[NUM_PORTS] = {0x00};
//WIRING: read all ports into buffer
for(i=0; i<NUM_PORTS; i++) {
state[i]= portRead(i);
}
// if the state of a pin has changed since last time,
// and that pin is an input pin, send a message
for(i=FIRST_DIGITAL_PIN;i<=LAST_DIGITAL_PIN;i++) {
if(!(pinDir[i/8] & (1<<(i%8))) && (i!=RX_PIN) && (i!=TX_PIN)) { //if pin is input and not RX/TX
if ((state[i/8] & (1<<(i%8))) != (inputBuffer[i/8] &(1<<(i%8)))) { //does this shift work?
strcpy(oscOutAddress,prefixIn);
strcat(oscOutAddress,numbers[i]);
oscSendMessageInt(oscOutAddress, !(state[i/8] & (1<<(i%8))));
}
}
}
//save current state to buffer
for(i=0; i<NUM_PORTS; i++) {
inputBuffer[i]=state[i];
}
}
/***********************************************
* Check one analog input channel and call
* oscSendMessageInt() if its value has changed
***********************************************/
void checkAnalogInput(byte channel) {
int result;
int diff;
// read a2d
result = analogRead(channel); // >>2 on arduino
// compare to last reading - if delta big enough,
// send message
//diff = result - a2dBuffer[channel];
//if(diff>MIN_A2D_DIFF || diff<(int)((-1)*MIN_A2D_DIFF)) {
if(result!=a2dBuffer[channel]) {
a2dBuffer[channel]=result;
strcpy(oscOutAddress,prefixA2d);
strcat(oscOutAddress,numbers[channel]);
oscSendMessageInt(oscOutAddress, result);
}
}
/***********************************************
* Send an OSC message with the passed in
* address and a single integer argument
***********************************************/
void oscSendMessageInt(char * address, unsigned long value){
byte offset=0;
byte i=0;
// clear buffer
for(i=0; i<MAX_LENGTH; i++) {
oscBuffer[i]=0x00;
}
//write packet header
oscBuffer[offset++]=0xBE;
//compute message length
//first compute address string length and padd if necessary
byte addrlen = strlen(address);
if(addrlen&0x03)
addrlen += 4-(addrlen&0x03);
//then add type-tag length and arg length (both 4 for a simple int message)
byte typetaglen=4;
byte arglen = 4;
//final length is sum of the three
byte len = addrlen+typetaglen+arglen;
//write message length
oscBuffer[offset++]=(unsigned char)len;
//write address
strcpy(oscBuffer+offset,address);
offset+=addrlen;
//write typetag
oscBuffer[offset++]=',';
oscBuffer[offset++]='i';
oscBuffer[offset++]=0x00;
oscBuffer[offset++]=0x00;
//write argument
oscBuffer[offset++]=*(((unsigned char *)(&value))+3);
oscBuffer[offset++]=*(((unsigned char *)(&value))+2);
oscBuffer[offset++]=*(((unsigned char *)(&value))+1);
oscBuffer[offset++]=*(((unsigned char *)(&value))+0);
//compute + write checksum
byte checksum=0;
for(i=2; i<offset; i++) {
checksum+=oscBuffer[i];
}
oscBuffer[offset++]=checksum;
//send message byte-by-byte
for(i=0;i<offset;i++) {
Serial.print(oscBuffer[i],BYTE);
}
}
/***********************************************
* Handle a received OSC message
***********************************************/
void oscReceiveMessageInt(char * msg, unsigned long value)
{
int i;
int outPin;
//uncomment to echo message back for debugging
oscSendMessageInt(msg,value);
// check if this is an output message, i.e., starts with "/out/"
if(strncmp(msg,prefixOut,strlen(prefixOut))==0) {
//if so, find which pin
outPin = atoi(msg+strlen(prefixOut));
if(outPin>=FIRST_DIGITAL_PIN && outPin<=LAST_DIGITAL_PIN && outPin!=RX_PIN && outPin!=TX_PIN) { //sanity check
//change its value
//note: pin can be set to input - this enables/disables pullups
digitalWrite(outPin,(byte)(value & 0x01));
}
return;
}
// check if this is a pwm message, i.e., starts with "/pwm/"
if(strncmp(msg,prefixPwm,strlen(prefixPwm))==0) {
outPin = atoi(msg+strlen(prefixPwm));
if(outPin>=FIRST_DIGITAL_PIN && outPin<=LAST_DIGITAL_PIN && outPin!=RX_PIN && outPin!=TX_PIN) { //sanity check
//make sure we turn pin into output in our pinDir first
//so we don't generate lots of extraneous messages
//may need to map from 0..5 to 29..37 range as well
if(0<=outPin && 5 >= outPin) {
pinDir[pwmPinMap[outPin]/8] =
pinDir[pwmPinMap[outPin]/8] | (1<<(pwmPinMap[outPin]%8));
} else {
pinDir[outPin/8] = pinDir[outPin/8] | (1<<(outPin%8));
}
//set pwm
analogWrite(outPin,value&1023);
}
return;
}
// check if this is a "report" message which starts with "/report/"
// changes which pins get reported
if(strncmp(msg,prefixReport,strlen(prefixReport))==0) {
//if it continues with "/in"
if(strncmp(msg+strlen(prefixReport)-1,prefixIn,strlen(prefixIn)-1)==0) {
reportDigital = (value!=0);
return;
}
//else if it continues with "/adc/"
else if(strncmp(msg+strlen(prefixReport)-1,prefixA2d,strlen(prefixA2d))==0) {
//extract which analog pin we're talking about
outPin = atoi(msg+strlen(prefixReport)-1+strlen(prefixA2d));
//flip the bit in reportAnalog:
if(outPin>=FIRST_ANALOG_PIN && outPin<=LAST_ANALOG_PIN) { //sanity check
if(value==0) {
reportAnalog = reportAnalog & ~(1<<outPin);
}
else {
reportAnalog = reportAnalog | (1<<outPin);
}
}
return;
}
//else if it continues with "/adc" (no final slash)
else if(strncmp(msg+strlen(prefixReport)-1,prefixA2d,strlen(prefixA2d)-1)==0) {
//turn reporting for all analog pins on or off
if(value==0) {
reportAnalog=0x00;
}
else {
reportAnalog=0xFF;
}
return;
}
}
//finally, this could be a "/pinmode/ message"
if(strncmp(msg,prefixPinmode,strlen(prefixPinmode))==0) {
outPin = atoi(msg+strlen(prefixPinmode));
if(outPin>=FIRST_DIGITAL_PIN && outPin<=LAST_DIGITAL_PIN) { //sanity check
if(value==0) {
pinDir[outPin/8] = pinDir[outPin/8] & ~(1<<(outPin%8)); //turn bit in our own direction buffer to off = input
pinMode(outPin,INPUT); //set DDR register bit to input
digitalWrite(outPin,HIGH); //reenable pull-up
}
else {
pinDir[outPin/8] = pinDir[outPin/8] | (1<<(outPin%8)); //turn bit on
pinMode(outPin,OUTPUT); // turn DDR bit to output
}
}
return;
}
//is this a reset message? if so, reinitialize.
if(strncmp(msg,prefixReset,strlen(prefixReset))==0) {
oscRxNextOp = OSC_RXOP_WAITFORSTART;
setup();
}
}
/***********************************
* PARSING OF MESSAGES BELOW
***********************************/
/***********************************
* PARSER
***********************************/
void oscRxHandler(unsigned char c) {
byte i;
switch(oscRxNextOp) {
case OSC_RXOP_WAITFORSTART:
if(c==0xBE) { //0xBE is the magic start byte
oscRxNextOp = OSC_RXOP_READSIZE;
}
break;
case OSC_RXOP_READSIZE:
oscRxMsgSize = c; // read message size
oscRxReadBytes = 0; //reset index into message buffer
if(oscRxMsgSize < (OSC_MAX_RX_MSG_SIZE-1)) {
oscRxNextOp = OSC_RXOP_READADDR;
}
else {
oscRxNextOp = OSC_RXOP_SKIPMSG; //Msg is too long
}
break;
case OSC_RXOP_READADDR:
if(c!=0 && c!=',') {
oscRxData[oscRxReadBytes++] = c; //copy normal addr byte
}
else if (c==',') {
//if we went straight from addr to to tag string, convert "," of tag string to 0x00
// so our address string is properly zero-terminated
//and jump ahead in the state machine to read second tag byte next
oscRxData[oscRxReadBytes++]=0x00;
oscRxNextOp = OSC_RXOP_READTAGBYTE2;
}
else {
oscRxData[oscRxReadBytes++] = 0;
if(!((oscRxReadBytes)&0x03)) { //skip 0s until we hit byte boundary
oscRxNextOp = OSC_RXOP_READTAGBYTE1;
}
}
break;
// read type tag string bytes 1-4
case OSC_RXOP_READTAGBYTE1:
oscRxData[oscRxReadBytes++] = c;
if(c==',') {
// valid type tag start character found
oscRxNextOp = OSC_RXOP_READTAGBYTE2;
}
else {
// no type tag start char present
// assume one int arg and read its first byte
oscRxIntArg1 = 0;
oscRxIntArg1 |= ((unsigned long)(c) << 0x18);
oscRxNextOp = OSC_RXOP_READARG1BYTE2;
}
break;
case OSC_RXOP_READTAGBYTE2:
oscRxData[oscRxReadBytes++] = c;
switch (c) {
case 'i': //int32 argument
oscRxNextOp = OSC_RXOP_READTAGBYTE3;
break;
// all other types besides int are not supported yet
// so skip remainder of message
case 'f': //float arg
case 's': //string arg
default:
oscRxNextOp = OSC_RXOP_SKIPMSG;
}
break;
case OSC_RXOP_READTAGBYTE3:
oscRxData[oscRxReadBytes++] = c;
switch (c) {
// null - message has only one arg - we're ok
case 0:
oscRxNextOp = OSC_RXOP_READTAGBYTE4;
break;
// all others: not yet supported; skip rest of message
default:
oscRxNextOp = OSC_RXOP_SKIPMSG;
break;
}
break;
case OSC_RXOP_READTAGBYTE4:
oscRxData[oscRxReadBytes++] = c;
switch (c) {
// null - message has only one arg - we're ok
case 0:
oscRxNextOp = OSC_RXOP_READARG1BYTE1;
break;
// all others: not yet supported; skip rest of message
default:
oscRxNextOp = OSC_RXOP_SKIPMSG;
break;
}
break;
// read argument bytes 1-4
case OSC_RXOP_READARG1BYTE1:
oscRxData[oscRxReadBytes++] = c;
oscRxIntArg1 = 0;
oscRxIntArg1 |= ((unsigned long)(c) << 0x18);
oscRxNextOp = OSC_RXOP_READARG1BYTE2;
break;
case OSC_RXOP_READARG1BYTE2:
oscRxData[oscRxReadBytes++] = c;
oscRxIntArg1 |= ((unsigned long)(c) << 0x10);
oscRxNextOp = OSC_RXOP_READARG1BYTE3;
break;
case OSC_RXOP_READARG1BYTE3:
oscRxData[oscRxReadBytes++] = c;
oscRxIntArg1 |= ((unsigned long)(c) << 0x08);
oscRxNextOp = OSC_RXOP_READARG1BYTE4;
break;
case OSC_RXOP_READARG1BYTE4:
oscRxData[oscRxReadBytes++] = c;
oscRxIntArg1 |= (unsigned long)(c);
oscRxNextOp = OSC_RXOP_READCHECKSUM;
break;
// read checksum byte; check msg integrity; fire off user function
case OSC_RXOP_READCHECKSUM:
// check that we read the right number of bytes
if (oscRxReadBytes != oscRxMsgSize) {
oscSendMessageInt("/error/msgsize/",oscRxReadBytes);
}
else {
oscRxChecksum = 0;
for (i=0; i<oscRxMsgSize; i++) {
oscRxChecksum+=oscRxData[i];
}
if(oscRxChecksum == c) {
// checksum matched and we're done with this msg
// -> fire off user function
oscReceiveMessageInt(oscRxData,oscRxIntArg1);
}
else {
// mismatch - throw this message away
oscSendMessageInt("/error/checksum",oscRxChecksum);
}
}
// wait for next message header
oscRxNextOp = OSC_RXOP_WAITFORSTART;
break;
//skip rest of message - called if an error was detected in the current
//incoming message
case OSC_RXOP_SKIPMSG:
if(++oscRxReadBytes == (oscRxMsgSize+1)) {
oscRxNextOp = OSC_RXOP_WAITFORSTART;
}
break;
default:
oscRxNextOp = OSC_RXOP_WAITFORSTART;
}
}


