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

Files at this revision

API Documentation at this revision

Comitter:
tobyspark
Date:
Sun Apr 15 15:05:19 2012 +0000
Parent:
10:b4cc0df203b7
Commit message:

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbedOSC.h Show annotated file Show diff for this revision Revisions of this file
diff -r b4cc0df203b7 -r 853a9e887023 main.cpp
--- 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());
diff -r b4cc0df203b7 -r 853a9e887023 mbedOSC.h
--- a/mbedOSC.h	Sun Apr 15 13:26:47 2012 +0000
+++ b/mbedOSC.h	Sun Apr 15 15:05:19 2012 +0000
@@ -1,15 +1,13 @@
 /* mbed OSC Library
  This is 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. I have also used parts of the OSC Transceiver(Sender/Receiver) code by xshige
- written by: Alvaro Cassinelli, 7.10.2011
- tweaked by: Toby Harris / *spark audio-visual, 13.4.2012
+ 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
 
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License version 2.1 as published by the Free Software Foundation.
  Open Sound Control  http://opensoundcontrol.org/
- 
- 
 */
 
 #ifndef mbedOSC_h
@@ -245,10 +243,14 @@
     char         tempAddress[MAX_ADDRESS][16];
     uint8_t      tempArg[MAX_ARG][4];    
     
+    void onUDPSocketEvent(UDPSocketEvent e);
+    
     void decodePacket( OSCMessage *_mes); // makes OSC message from packet
 
 public:
     
+    friend class UDPSocket;
+    
     /** Create an object to send and receive OSC messages */
     OSCClass();
     
@@ -257,11 +259,6 @@
  @param[in] _mes A pointer to the "receiveing" OSC message (OSCMessage *)
  */
     OSCClass(OSCMessage *_mes); // set the receiver message container
-
-/**
- Ignore: See messageReceivedCallback instead. This is called by the UDPSocket... and should be a protected function and we friend UDPSocket?
- */
-    void onUDPSocketEvent(UDPSocketEvent e);
         
 /**
  This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT) 
@@ -280,7 +277,7 @@
     void stop();
     
 /**
- Returns whether there is new OSC data in the receiver message container
+ Returns whether there is new OSC data in the receiver message container.
  */
     bool newMessage;