Receiving double digit numbers from Pure Data to Arduino over OSC

Status
Not open for further replies.

TrueBlue

Member
Hi, I'm trying to trying to control an led matrix from pure data over osc. I'm able to control 10 leds (ie.'/led/1' - '/led/9'. However I'm not able to receive osc messages with double digit numbers.

I believe the problem has to do with the following lines of code which I did not write and as a result don't fully understand. Could someone give me a better understanding of what's going on here so I might be able to adjust the code?
Code:
char whatLED[] = {'/','1',0};
      for(int i=0; i<16;i++){
        whatLED[1] = char (i | 0x30);


Code:
#include "Tlc5940.h"

#include <OSCBoards.h>
#include <OSCMessage.h>

#ifdef BOARD_HAS_USB_SERIAL
#include <SLIPEncodedUSBSerial.h>
SLIPEncodedUSBSerial SLIPSerial( thisBoardsSerialUSB );
#else
#include <SLIPEncodedSerial.h>
 SLIPEncodedSerial SLIPSerial(Serial1);
#endif


byte outPins[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};    //for tlc pins
int brightness;
int i;


void setup() {
    SLIPSerial.begin(9600);   // set this as high as you can reliably run on your platform
    Tlc.init();               
}


void routeSystem(OSCMessage &msg, int matched ){
      char whatLED[] = {'/','1',0};
      for(int i=0; i<16;i++){
        whatLED[1] = char (i | 0x30);
        if(msg.match(whatLED,matched)){
            if(msg.getInt(0));
            int brightness = msg.getInt(0);
            Tlc.set(outPins[i],brightness);    // addressing tlcs
            Tlc.update();
            
        }
    }
}

//reads and routes the incoming messages
void loop(){ 
    OSCMessage messageIN;
    int size;
    while(!SLIPSerial.endofPacket())
        if ((size =SLIPSerial.available()) > 0)
        {
           while(size--)
              messageIN.fill(SLIPSerial.read());
        }

    if(!messageIN.hasError())
    {
        messageIN.route("/led", routeSystem);
       
    }
}
 
If you do a logical OR (or an addition) of the numbers 0...9 with 0x30, you'll get 0x30, 0x31, .... 0x39. These happen to be the ASCII codes for the characters '0', '1', ....'9'.
So, the code is building a set of null-terminated c-strings: "/0", "/1", .... "/9".

It doesn't work when you go beyond 9 because 10 (decimal) + 0x30 = 0x3A which is the ASCII code for the character ":".
 
Thanks for the response! I understand what you're saying about the character codes, though I feel I'm a bit at a loss about how to proceed.
Is there a simple way around this? Or is it simply not possible given the format of osc?

I was able to double up the code as seen below, but this approach is messy and time consuming for number of leds that im working with.

Code:
#include "Tlc5940.h"

#include <OSCBoards.h>
#include <OSCMessage.h>

#ifdef BOARD_HAS_USB_SERIAL
#include <SLIPEncodedUSBSerial.h>
SLIPEncodedUSBSerial SLIPSerial( thisBoardsSerialUSB );
#else
#include <SLIPEncodedSerial.h>
 SLIPEncodedSerial SLIPSerial(Serial1);
#endif


//byte outPins[] = {9,10};      //for analogwrite pins standard leds w/o tlc
byte outPins1[] = {0,1,2,3,4,5,6,7,8,9};    //for tlc pins
byte outPins2[] = {10,11,12,13,14,15};    //for tlc pins

int brightness;
int i;


void setup() {
    SLIPSerial.begin(9600);   // set this as high as you can reliably run on your platform
    Tlc.init();               
}


void led1(OSCMessage &msg, int matched ){
      char whatLED[] = {'/','1',0};
      for(int i=0; i<16;i++){
        whatLED[1] = char (i | 0x30);
        if(msg.match(whatLED,matched)){
            if(msg.getInt(0));
            int brightness = msg.getInt(0);
            //analogWrite(outPins[i],brightness);  // addressing standard leds w/o tlc
            Tlc.set(outPins1[i],brightness);    // addressing tlcs
            //Tlc.setAll(4000);                  //address all tlcs with set value of 4000
            Tlc.update();
            
        }
    }
}

void led2(OSCMessage &msg, int matched ){
      char whatLED[] = {'/','1',0};
      for(int i=0; i<16;i++){
        whatLED[1] = char (i | 0x30);
        if(msg.match(whatLED,matched)){
            if(msg.getInt(0));
            int brightness = msg.getInt(0);
            //analogWrite(outPins[i],brightness);  // addressing standard leds w/o tlc
            Tlc.set(outPins2[i],brightness);    // addressing tlcs
            //Tlc.setAll(4000);                  //address all tlcs with set value of 4000
            Tlc.update();
            
        }
    }
}

//reads and routes the incoming messages
void loop(){ 
    OSCMessage messageIN;
    int size;
    while(!SLIPSerial.endofPacket())
        if ((size =SLIPSerial.available()) > 0)
        {
           while(size--)
              messageIN.fill(SLIPSerial.read());
        }

    if(!messageIN.hasError())
    {
        messageIN.route("/led", led1);
        messageIN.route("/led2", led2);
       
    }
}
 
I came up with this function for extracting an index from an OSC path:
Code:
int getAddresPartAsIndex(char* addres, int position){
  int number=0;   // function will return -1 if the position doesn't exist or doesn't contain an integer
  char* addresRest=addres;
  char* path=strtok_r(addresRest,"/",&addresRest);
  for (int i=1;i<position;i++){
    path=strtok_r(addresRest,"/",&addresRest);
  }
  number=atoi(path);
  return number-1;
}

It's essentially a tokenise '/' function to get a specific part in the OSC address
I use it to get the track or other number from the path like this:
Code:
    char adresStr[48];    
    msg.getAddress(adresStr);
    int index = getAddresPartAsIndex(adresStr,2);
    if (msg.match("/fxparam/*/name")){
      msg.getString(0,reaper.insertParameter[index].name,NAME_LENGTH); 
      if (index==reaper.selectedParameter) addToQueue(4);
      return;
    }

Beware that the function returns -1 if the requested message part index does not exist or does not contain an integer.
 
Status
Not open for further replies.
Back
Top