An Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige written by: Alvaro Cassinelli, October 2011 tweaked by: Toby Harris / *spark audio-visual, March 2012

Dependencies:   NetServices mbed

Revision:
11:853a9e887023
Parent:
1:ab7dc9550de6
--- a/main.cpp	Sun Apr 15 13:26:47 2012 +0000
+++ b/main.cpp	Sun Apr 15 15:05:19 2012 +0000
@@ -1,125 +1,143 @@
 #include "mbed.h"
 #include "mbedOSC.h"
 
-DigitalOut myled(LED1);
+//// ETHERNET
 
-// mbed IP address (server):
+// Ethernet can be created with *either* an address assigned by DHCP or a static IP address. Uncomment the define line for DHCP
+//#define DHCP
 #ifdef DHCP
 EthernetNetIf eth;
 #else
 EthernetNetIf eth(
-  IpAddr(10,0,0,2), //IP Address
-  IpAddr(255,255,255,0), //Network Mask
-  IpAddr(10,0,0,1), //Gateway
-  IpAddr(10,0,0,1)  //DNS
+    IpAddr(10,0,0,2), //IP Address
+    IpAddr(255,255,255,0), //Network Mask
+    IpAddr(10,0,0,1), //Gateway
+    IpAddr(10,0,0,1)  //DNS
 );
 #endif
 
-uint8_t serverIp[]  = { 10, 0, 0, 2 }; // not needed perhaps!
-int  serverPort  = 10000;
-  
-uint8_t destIp[]  = { 10, 0, 0, 1};
-int  destPort = 12000;
-  
-char *topAddress="/mbed";
-char *subAddress[3]={ "/test1" , "/test2" , "/test3" };
-  
+//// OSC
+
+// The object to do the work of sending and receiving
+OSCClass osc;
+
+// The message objects to send and receive with
 OSCMessage recMes;
 OSCMessage sendMes;
-  
-OSCClass osc;    
-//OSCClass osc(&recMes);  // instantiate OSC communication object, and set the receiver container from the OSC packets  
- 
-Serial pc(USBTX, USBRX); 
- 
-void processOSC(); 
- 
-int main() {
-    
-  // make debug port:
-  pc.baud(115200);
+
+// Setting - The port we're listening to on the mbed for OSC messages
+int  mbedListenPort  = 10000;
+
+// Setting - The address and port we're going to send to, from the mbed
+uint8_t destIp[]  = { 10, 0, 0, 1};
+int  destPort = 12000;
+
+//// mbed input
+
+DigitalIn button(p21);
+bool buttonLastState;
 
-  // Set the Ethernet port: 
-  printf("Setting up...\r\n");
-  EthernetErr ethErr = eth.setup();
-  if(ethErr)
-  {
-    printf("Error %d in setup.\r\n", ethErr);
-    return -1;
-  }
-  printf("Setup OK\r\n");
-    
-  
-   //(1) Sending message:
-   // Set IP and Port: 
-   sendMes.setIp( destIp );
-   sendMes.setPort( destPort );
-   // Set data: 
-   // sendMes.setTopAddress(topAddress);
-   
-   //setting osc functionnality:
-   //(2) Receiving: 
-  // recMes.setIp( serverIp ); // not needed?
-   osc.setReceiveMessage(&recMes); // this sets the receiver container for the OSC packets (we can avoid doing this if we use osc.getMessage() to get messages)
-   osc.begin(serverPort); // binds the upd (osc) messages to an arbitrary listening port ("server" port), and callback function
-   osc.messageReceivedCallback.attach(&processOSC);
-   
-   //==========================================   INFINITE LOOP (in USER PROGRAM CONTEXT) ===================================================================
-    while(true) {
-        Net::poll();
-        
-        // ... Do whatever needs to be done (note: the osc processing is done in the processOSC function. 
-        // BUT DO NOT FORGET to call osc.onUDPSocketEvent(e). This is messy... should find a better way to do it. 
-    
+//// Our messageReceivedCallback function
+void processOSC() {
+
+    // If this function has been called, the OSC message just received will have been parsed into our recMes OSCMessage object
+    // Note we can access recMes here, outside of the main loop, as we created it as a global variable.
+
+    // TASK: If this message one we want, do something about it.
+    // In this example we're listening for messages with a top address of "mbed".
+    // Note the strcmp function returns 0 if identical, so !strcmp is true if the two strings are the same
+    if ( !strcmp( recMes.getAddress(0) , "mbed" ) ) {
+        printf("OSC Message received addressed to mbed \r\n");
+        if ( !strcmp( recMes.getAddress(1) , "test1" ) )
+            printf("Received subAddress= test1 \r\n");
+
+        // Send some osc message:
+        sendMes.setTopAddress("/working...");
+        osc.sendOsc(&sendMes);
     }
 }
 
-void processOSC() {
+////  M A I N
+int main() {
+
+    //// TASK: Set up the Ethernet port
+    printf("Setting up ethernet...\r\n");
+    EthernetErr ethErr = eth.setup();
+    if (ethErr) {
+        printf("Ethernet Failed to setup. Error: %d\r\n", ethErr);
+        return -1;
+    }
+    printf("Ethernet OK\r\n");
+
+    //// TASK: Set up OSC message sending
+
+    // In the OSC message container we've made for send messages, set where we want it to go:
+    sendMes.setIp( destIp );
+    sendMes.setPort( destPort );
+
+    //// TASK: Set up OSC message receiving
+
+    // In the OSC send/receive object...
+    // Set the OSC message container for it to parse received messages into
+    osc.setReceiveMessage(&recMes);
+
+    // Tell it to begin listening for OSC messages at the port specified (the IP address we know already, it's the mbed's!).
+    osc.begin(mbedListenPort);
 
-    if (osc.newMessage) { // in fact, there is no need to check this if using the method of a global callback function - it is clear this is a new packet... however, it may be 
-                          // interesting to use a timer, and process data (answers, etc) only after a certain amount of time, so as to avoid blocking the program in IRQ context...
-        
-             //pc.printf("we received top address %s\n", recMes.getAddress(0) );
-             
-            osc.newMessage=false; // note: if using: message=osc.getMessage(), then we don't need to do this explicitly. 
-        
-            // Test: 
-            if( !strcmp( recMes.getAddress(0) , "mbed" ) ) {
-                pc.printf("we received topAddress= mbed \n");
-                if( !strcmp( recMes.getAddress(1) , "test1" ) )
-                      pc.printf("we received subAddress= test1 \n");
-                      
-                      // Send some osc message:
-                      sendMes.setTopAddress("/working...");
-                      osc.sendOsc(&sendMes);
-            }
+    // Rather than constantly checking to see whether there are new messages waiting, the object can call some code of ours to run when a message is received.
+    // This line does that, attaching a callback function we've written before getting to this point, in this case it's called processOSC
+    // For more info how this works, see http://mbed.org/cookbook/FunctionPointer
+    osc.messageReceivedCallback.attach(&processOSC);
+
+    //// TASK: Prime button change detection
+    buttonLastState = button;
+
+    //// TASK: GO!
+
+    // We've finished setting up, now loop this forever...
+    while (true) {
+        // This polls the network connection for new activity, without keeping on calling this you won't receive any OSC!
+        Net::poll();
+
+        // Has the button changed?
+        if (button != buttonLastState) {
+            // If so, lets update the lastState variable and then send an OSC message
+            buttonLastState = button;
+            
+            sendMes.setTopAddress("/mbed");
+            sendMes.setSubAddress("/button");
+            sendMes.setArgs("i", (long)button); // The payload will be the button state as an integer, ie. 0 or 1. We need to cast to 'long' for ints (and 'double' for floats).// The payload will be the button state as an integer, ie. 0 or 1. We need to cast to 'long' for ints (and 'double' for floats).
+            osc.sendOsc(&sendMes);
+            
+            printf("Sent OSC message /mbed/button \r\n");
         }
-       
+
+        // ... Do whatever needs to be done by your mbed otherwise. If an OSC message is received, your messageReceivedCallback will run (in this case, processOSC()).
+    }
 }
 
-
 /* EXAMPLE SEND/RECEIVE on PROCESSING:
 
 // oscP5sendreceive by andreas schlegel
 // example shows how to send and receive osc messages.
 // oscP5 website at http://www.sojamo.de/oscP5
 
- 
+
 import oscP5.*;
 import netP5.*;
-  
+
 OscP5 oscP5;
 NetAddress myRemoteLocation;
 
 void setup() {
   size(400,400);
   frameRate(25);
-  // start oscP5, listening for incoming messages at port 12000 
+  // start oscP5, listening for incoming messages at port 12000
   oscP5 = new OscP5(this,12000);
-  
+
   // myRemoteLocation is a NetAddress. a NetAddress takes 2 parameters,
   // an ip address and a port number. myRemoteLocation is used as parameter in
-  // oscP5.send() when sending osc packets to another computer, device, 
+  // oscP5.send() when sending osc packets to another computer, device,
   // application. usage see below. for testing purposes the listening port
   // and the port of the remote location address are the same, hence you will
   // send messages back to this sketch.
@@ -128,23 +146,23 @@
 
 
 void draw() {
-  background(0);  
+  background(0);
 }
 
 void mousePressed() {
-  // in the following different ways of creating osc messages are shown by example 
+  // in the following different ways of creating osc messages are shown by example
   OscMessage myMessage = new OscMessage("/mbed/test1");
-  
-  myMessage.add(123); // add an int to the osc message 
+
+  myMessage.add(123); // add an int to the osc message
 
-  // send the message 
-  oscP5.send(myMessage, myRemoteLocation); 
+  // send the message
+  oscP5.send(myMessage, myRemoteLocation);
 }
 
 
-// incoming osc message are forwarded to the oscEvent method. 
+// incoming osc message are forwarded to the oscEvent method.
 void oscEvent(OscMessage theOscMessage) {
-  // print the address pattern and the typetag of the received OscMessage 
+  // print the address pattern and the typetag of the received OscMessage
   print("### received an osc message.");
   print(" addrpattern: "+theOscMessage.addrPattern());
   println(" typetag: "+theOscMessage.typetag());