The codebase to run the *spark d-fuser controller www.sparkav.co.uk/dvimixer
Dependencies: SPK-TVOne DMX DmxArtNet NetServicesMin OSC PinDetect mRotaryEncoder iniparser mbed spk_oled_ssd1305 filter
Revision 5:f8b285ca41ba, committed 2012-07-19
- Comitter:
- tobyspark
- Date:
- Thu Jul 19 10:46:53 2012 +0000
- Parent:
- 4:d5ff91b66357
- Child:
- 6:aca7c9e6894d
- Commit message:
- v18 - DMX
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DMX.lib Thu Jul 19 10:46:53 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/okini3939/code/DMX/#f0d988e15810
--- a/DmxArtNet.lib Mon Apr 23 09:30:50 2012 +0000 +++ b/DmxArtNet.lib Thu Jul 19 10:46:53 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/okini3939/libraries/DmxArtNet/ly98qu \ No newline at end of file +http://mbed.org/users/okini3939/code/DmxArtNet/#c59dc374fc64
--- a/NetServicesMin.lib Mon Apr 23 09:30:50 2012 +0000 +++ b/NetServicesMin.lib Thu Jul 19 10:46:53 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/hlipka/libraries/NetServicesMin/lkscxf \ No newline at end of file +http://mbed.org/users/hlipka/code/NetServicesMin/#9d93f4dc2f46
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OSC.lib Thu Jul 19 10:46:53 2012 +0000 @@ -0,0 +1,1 @@ +OSC#2b9d407f0e7b
--- a/OSC/.lib Mon Apr 23 09:30:50 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/tobyspark/libraries/OSC/m8izgx \ No newline at end of file
--- a/OSC/example-processing.h Mon Apr 23 09:30:50 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* 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 - 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, - // 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. - myRemoteLocation = new NetAddress("10.0.0.2",10000); -} - - -void draw() { - background(0); -} - -void mousePressed() { - // 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 - - // send the message - oscP5.send(myMessage, myRemoteLocation); -} - - -// 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("### received an osc message."); - print(" addrpattern: "+theOscMessage.addrPattern()); - println(" typetag: "+theOscMessage.typetag()); -}
--- a/OSC/example.h Mon Apr 23 09:30:50 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -#include "mbed.h" -#include "mbedOSC.h" - -//// ETHERNET - -// 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 -); -#endif - -//// 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; - -// 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; - -//// 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); - } -} - -//// 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); - - // 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()). - } -} \ No newline at end of file
--- a/OSC/mbedOSC.cpp Mon Apr 23 09:30:50 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,401 +0,0 @@ -/* - mbedOSC.cpp -*/ - -#include "mbed.h" -#include "mbedOSC.h" -#include "stdarg.h" - -OSCMessage::OSCMessage() { - // Initialize host address and port by default (as if this where the receiver message): - // host=new Host(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL); -} - -void OSCMessage::setPort(uint16_t _port){ - host.setPort(_port); -} - - -void OSCMessage::setIp(uint8_t *_ip){ - host.setIp(IpAddr(_ip[0], _ip[1], _ip[2], _ip[3])); -} - - - -void OSCMessage::setIp( uint8_t _ip1, - uint8_t _ip2, - uint8_t _ip3, - uint8_t _ip4 ){ - - host.setIp(IpAddr(_ip1, _ip2, _ip3, _ip4)); -} - -const IpAddr& OSCMessage::getIp(){ - return host.getIp(); -} - - - const int& OSCMessage::getPort(){ - return host.getPort(); -} - - - -uint8_t OSCMessage::getAddressNum(){ - - return addressNum; -} - - -uint8_t OSCMessage::getArgNum(){ - - return argNum; -} - - - -char * OSCMessage::getAddress(uint8_t _index){ - if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1; - return address[_index]; - -} - - - -char * OSCMessage::getTopAddress(){ - - return getAddress(0); - -} - - -char * OSCMessage::getSubAddress(){ - - return getAddress(1); - -} - - -char OSCMessage::getTypeTag(uint8_t _index){ - if(_index>MAX_ARG) _index=MAX_ARG-1; - return typeTag[_index]; -} - - -int32_t OSCMessage::getArgInt(uint8_t _index){ - int32_t *value; - if(_index > argNum) _index=argNum; - value = (int32_t *)arg[_index]; // cast to int32_t - return *value; -} - - -double OSCMessage::getArgFloat(uint8_t _index){ - double *value; - if(_index > argNum) _index=argNum; - value = (double *)arg[_index]; - return *value; -} - - -void OSCMessage::setTopAddress(char *_address){ - address[0]=_address; - address[1]=0; - addressNum=1; // Note: this "erases" the subaddress! (is this a good idea?) -} - - -void OSCMessage::setSubAddress(char *_address){ - address[1]=_address; - addressNum=2; // Note: this assumes the top address was already set! -} - - - -void OSCMessage::setAddress(char *_topAddress,char *_subAddress){ - setTopAddress(_topAddress); - setSubAddress(_subAddress); - addressNum=2; // (unnecessary...) -} - - -void OSCMessage::setAddress(uint8_t _index, char *_address){ - if(_index>MAX_ADDRESS) _index=MAX_ADDRESS-1; - address[_index]=_address; - addressNum=_index+1; -} - - - -void OSCMessage::setArgs(char *types,...){ - - va_list argList; - - argNum = strlen(types); - if(argNum>MAX_ARG) argNum=MAX_ARG-1; - - va_start( argList, types ); - for(uint8_t i=0 ; i < argNum ; i++){ - - typeTag[i]=types[i]; - - switch(types[i]) { - case 'i': - arg[i]=(uint32_t *)va_arg(argList, uint32_t *); - break; - case 'f': - arg[i]=va_arg(argList, double *); - break; - } - - } - -} - -// ================================================================================================================================================ -// ==================================== OSCClass for sending and receiving OSC messages using UDP protocol ======================================= -// ================================================================================================================================================ -//The class define an object wrapping the UDP functions to send and receive OSC messages - -OSCClass::OSCClass(){ - udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent); - newMessage=false; -} - -OSCClass::OSCClass(OSCMessage *_mes){ - udpRec.setOnEvent(this, &OSCClass::onUDPSocketEvent); - receiverMessage = _mes; // note: receiverMessage MUST be a pointer to the message, because we will modify things in it - newMessage=false; -} - -void OSCClass::begin() -{ - // setup receiver udp socket: - udpRec.bind(receiverMessage->host); -} - - -void OSCClass::begin(uint16_t _recievePort) -{ - receiverMessage->host.setPort(_recievePort); - // setup receiver udp socket: - udpRec.bind(receiverMessage->host); -} - - -void OSCClass::setReceiveMessage(OSCMessage *_mes){ - receiverMessage = _mes; -} - -void OSCClass::onUDPSocketEvent(UDPSocketEvent e) -{ - switch(e) - { - case UDPSOCKET_READABLE: //The only event for now - //char buf[256] = {0}; - Host auxhost; - buflength = udpRec.recvfrom( rcvBuff, 256, &auxhost ); // QUESTION: auxhost should be equal to the receiver host I guess... - if ( buflength > 0 ) { - //printf("\r\nFrom %d.%d.%d.%d:\r\n", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]); - decodePacket(receiverMessage); // convert to OSC message, and save it in receiverMessage - newMessage=true; - - messageReceivedCallback.call(); - } - break; - } -} - -/* - Decode UDP packet and save it in the OSCMessage structure - */ -void OSCClass::decodePacket( OSCMessage *_mes) { - - //uint16_t lenBuff; - uint8_t d; - uint8_t messagePos=0; - uint8_t adrCount=0; - uint8_t adrMesPos=0; - uint8_t packetCount=0; - uint8_t packetPos=4; - - - //W5100.writeSn(socketNo, SnIR, SnIR::RECV); - //lenBuff=recvfrom(socketNo, rcvBuff, 1, receiverMessage->ip, &receiverMessage->port); - - receiverMessage->address[0]=tempAddress[0]; - - //(1) address process start ========================================= - do{ - d=rcvBuff[messagePos]; - - - if( (d=='/') && (messagePos>0) ){ - - if(adrCount<MAX_ADDRESS){ - tempAddress[adrCount][adrMesPos]=0; - - adrCount++; - adrMesPos=0; - - receiverMessage->address[adrCount]=tempAddress[adrCount]; - } - - } - - if(adrCount<MAX_ADDRESS){ - //Added this in to remove the slashes out of final output - if(d!='/'){ - tempAddress[adrCount][adrMesPos]=d; - - if(packetCount>3) { - packetCount=0; - packetPos+=4; - } - - adrMesPos++; - } - } - messagePos++; - packetCount++; - - }while(d!=0); - - - if(adrCount<MAX_ADDRESS) adrCount++; - receiverMessage->addressNum=adrCount; - - messagePos=packetPos; - - //(2) type tag process starts ========================================= - packetCount=0; - packetPos+=4; - - uint8_t typeTagPos=0; - uint8_t tempArgNum=0; - - while(rcvBuff[messagePos]!=0 ){ - - if(rcvBuff[messagePos] != ',') { - - if(typeTagPos<MAX_ARG){ - receiverMessage->typeTag[tempArgNum]=rcvBuff[messagePos]; - tempArgNum++; - } - typeTagPos++; - - } - - packetCount++; - - if(packetCount>3) { - packetCount=0; - packetPos+=4; - } - - messagePos++; - } - - receiverMessage->argNum=tempArgNum; - - messagePos=packetPos; - - //(3) tempArg process starts ========================================= - for(int i=0;i<tempArgNum;i++){ - - adrMesPos=3; - - receiverMessage->arg[i]=tempArg[i]; - - for(int j=0;j<4;j++){ - - tempArg[i][adrMesPos]=rcvBuff[messagePos]; - - messagePos++; - adrMesPos--; - } - - } -} - - - -OSCMessage * OSCClass::getMessage(){ - newMessage=false; // this indicate the user READ the message - return receiverMessage; -} - - -void OSCClass::sendOsc( OSCMessage *_mes ) -{ - uint8_t lengthEnd; - uint8_t lengthStart; - char buff[128]; - - sendContainer = _mes; - - //バッファ初期値 - buff[0]=0; - - //1) Add name spaces: - for(int i=0;i<sendContainer->addressNum;i++){ - - strcat(buff,sendContainer->address[i]); // note: an address is for instance: "/test" (including the "/") - - } - - // pad with 0s to align in multiples of 4: - lengthStart=strlen(buff); - lengthEnd=lengthStart+(4-(lengthStart%4)); - for(int i=lengthStart ; i<lengthEnd; i++){ - buff[i]=0; - } - - lengthStart=lengthEnd; - - //2) Add TypeTag: - buff[lengthEnd++]=','; // Note: type tag is for instance: ",if" - for(int i=0;i<sendContainer->argNum;i++){ - buff[lengthEnd++]=sendContainer->typeTag[i]; - } - - // pad with 0s to align in multiples of 4: - lengthStart=lengthEnd; - lengthEnd=lengthStart+(4-(lengthStart%4)); - for(int i=lengthStart ; i<lengthEnd; i++){ - buff[i]=0; - } - - //3) add argument values (Note: here only big endian): - uint8_t *v; - for(int i=0;i<sendContainer->argNum;i++){ - uint8_t valuePos=3; - v=(uint8_t *)sendContainer->arg[i]; - - buff[lengthEnd++]=v[valuePos--]; - buff[lengthEnd++]=v[valuePos--]; - buff[lengthEnd++]=v[valuePos--]; - buff[lengthEnd++]=v[valuePos]; - - } - - //4) Send udp packet: - //sendto( socketNo, (uint8_t *)buff, lengthEnd, sendContainer->ip, sendContainer->port ); - udpSend.sendto(buff , lengthEnd, &(sendContainer->host)); -} - - -/* - flush a receive buffer -void OSCClass::flush() { - while ( available() ){} -} -*/ - - -void OSCClass::stop() { - //close( socketNo ); - udpSend.resetOnEvent(); // disables callback -} - -
--- a/OSC/mbedOSC.h Mon Apr 23 09:30:50 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -/* 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. 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 -#define mbedOSC_h - -#include "mbed.h" -#include "EthernetNetIf.h" -#include "UDPSocket.h" - -// setup IP of destination (computer): -#define DEFAULT_SEND_PORT 12000 -//Host sendHost(IpAddr(10, 0, 0, 1), DEFAULT_SEND_PORT, NULL); // Send Port -// set IP of origin of UDP packets - the mbed acts as a SERVER here, and needs to bind the socket to the "client" (the computer) -#define DEFAULT_RECEIVE_PORT 57130 -//Host recHost(IpAddr(10, 0, 0, 1), DEFAULT_RECEIVE_PORT, NULL); // Receive Port -//UDPSocket udpRec,udpSend; - - -#define MAX_ADDRESS 2 -#define MAX_ARG 2 - -#define TYPE_INT 1 -#define TYPE_FLOAT 2 - - -/** Container class for OSC messages (receiving or sending) - @note mbedOSC version 0.1 Specification (similar to Recotana's OSCClass library) - Example of an OSC message: "/mbed/test1, if 50 32.4" - ie. "Address TypeTag Args" - Address : max 2 - "/ard" - "/ard/output" - --address[0]="/ard" :max 15character - --address[1]="/output" :max 15character - TypeTag : max 2 - "i" - long or unsigned long - "f" - double - arg : max 2 - (Note: The byte string as seen here is not sent as UDP packet directly - there are no spaces, and arguments are in binary, BIG ENDIAN) -*/ -class OSCMessage{ - - private: - - char *address[MAX_ADDRESS]; // these are strings (as char*) - uint8_t addressNum; // current number of addresses in the message (ex: "/ard/test" --> the number of the addresses is 2) - - char typeTag[MAX_ARG]; - - void *arg[MAX_ARG]; - uint8_t argNum; - - // Information about the connection: - //uint8_t ip[4]; - //uint16_t port; - Host host; - - public: - /** Create a container for an OSC message to be received or sent */ - OSCMessage(); - - /** Return the IpAddr object */ - const IpAddr& getIp(); - /** Return the port */ - const int& getPort(); - -/** Gets the address string of the OSC message - * - * @param[in] _index The index of the address string (byte) - * @return pointer of the address string (char *) - * @note ex. "/ard/test"<br> - * getAddress(0) = "/ard"<br> - * getAddress(1) = "/test" - * @attention It is maximum number of the addresses is 2<br> - * In this case "/ard/test1/test2"<br> - * ignore it after "/test2" - */ - char *getAddress(uint8_t _index); //retturn address - -/** Gets the TopAddress string of the OSC message (this is just the address with index 0) - @return pointer of the TopAddress string (char *), i.e. address[0] - Example: In the case "/ard/test", getTopAddress() = "/ard" (WITH the slash "/") - */ - char *getTopAddress(); //return address[0] :"/ard" - -/** - Gets the "SubAddress" string of the OSC message (this is just the address with index 1) - @return pointer of the SubAddress string (char *), i.e. address[1] - Example: in the case "/ard/test", getSubAddress() = "/test" (WITH the slash "/") - */ - char *getSubAddress(); //return address[1] :"/test" - -/** - Gets the number of the OSC message address - @return number of the OSC message address (byte) - Examples: "/ard" --> the number of the addresses is 1 - "/ard/test" --> the number of the addresses is 2 - Attention: the maximum number of addresses is 2 (MAX_ADDRESS) -*/ - uint8_t getAddressNum(); //return 2 - -/** - Gets the TypeTag string (with index) of the OSC message - @param[in] _index The index of the TypeTag string (byte) - @return: TypeTag char (char) - Example: in the case of a total typetag string equal to "if", getTypeTag(0) = 'i' and getTypeTag(1) = 'f' - Attention: MAX_ARG is maximum number of the args, if the index argument is larger, it will be constrained to this max. - */ - char getTypeTag(uint8_t _index); //_index=0 ->'i' - //_index=1 ->'f' - -/** - Gets the number of the OSC message args - @return number of the args (byte) - Example: "i" 123 --> number of the OSC message args is 1 - "if" 123 54.24 --> number of the OSC message args is 2 - Attention: the maximum number of args is 2 (MAX_ARG) - */ - uint8_t getArgNum(); //return 2 - -/** - Get the args of the OSC message with an integer value - @param[in] _index An int or uint8_t corresponding to the index of the args (byte) - @return: integer value (long, or int32_t) - Example: in the case "if" 123 54.24, getArgInt(0) = 123 - Noe: "i" is integer, but the return type is "long" - Note: When a index is bigger than the number of the args, it is set to the number of the args - */ - int32_t getArgInt(uint8_t _index); //_index=0 -> 123 - -/** - Get the args of the OSC message with a float value - @param[in] _index The index of the args - @return: float value (double) - note: In this case "if" 123 54.24, getArgFloat(1) = 54.24 - attention: arg declared as float, but return value cast as "double" - attention: When index is bigger than the number of the args, it is set to the number of the args - */ - double getArgFloat(uint8_t _index); //_index=1 -> 54.21 - - -/** - Set TopAddress string of OSC Message - @param[in] _address A string pointer for the TopAddress String (char *). NOTE: is this a good idea? why not pass as const, and do allocation here? - Example: if the complete address string is "/ard/test", we set the topaddress as follows: char top[]="/ard" (allocation done here!), then setTopAddress(top) - */ - void setTopAddress(char *_address); //set address[0] - -/** - Set SubAddress string of the OSC Message - @param[in] _address A string pointer for the SubAddress String (char *) - Example: if the complete address string is "/ard/test", we set the subaddress as follows: char sub[]="/test" (allocation done here!), then setSubAddress(sub) - Attention: we should call first setTopAddress, and then setSubAddress. The order is important. This does not seems like a good idea... - */ - void setSubAddress(char *_address); //set address[1] - -/** - Set the complete Address string of the OSC Message (top and sub addresses) - @param[in] _topAddress, _subAddress The string pointers to top and sub addresses (char *) - Example: in the case "/ard/test", we need to do: char top[]="/ard", char sub[]="/test", and then setAddress(top,sub) - Reminder: in this implementation, the maximum number of addresses is MAX_ADDRESS=2 - */ - void setAddress(char *_topAddress, - char *_subAddress); - -/** - Set address string using index (here 0 or 1) - Example: "/ard/test", char adr[]="/ard", setAddress(0,adr), char adr2[]="/test", setAddress(1,adr) - */ - void setAddress(uint8_t _index, //set 0,address[0] - char *_address); - //set 1,address[1] - -/** - Set IP Address of the OSC Message (for SENDING messages - for receiving this will be done when receiving something ) - @param[in] _ip Pointer of IP Address array (byte *) - Example: IP=192.168.0.99, then we have to do: ip[]={192,168,0,1}, then setIp(ip) - */ - void setIp( uint8_t *_ip ); //set ip - -/** - Set IP Address to the OSC Message container (not through pointer) - Example: IP=192.168.0.99 => setIp(192,168,0,99) - */ - void setIp(uint8_t _ip1, //set(192, - uint8_t _ip2, // 168, - uint8_t _ip3, // 0, - uint8_t _ip4); // 100) - - /* - Set PortNo for the OSC Message - @param[in] _port PortNo (unsigned int) - @return None - */ - void setPort( uint16_t _port ); - -/** - Set TypeTag and args to the OSC Message container - @param[in] types TypeTag string "i"(integer) or"f"(float) (char *) - @param[in] ... Pointer of the Args(variable argument) .. - @Example: - (1) integer 123: (NOTE: integers are LONG) - long v1=123; sendMes.setArgs("i",&v1) - (2)integer:123 and float:52.14 - long v1=123; double v2=52.14; sendMes.setArgs("if",&v1,&v2) - Attention: in this implementation, the maximum number of the args is 2 - (if setArgs("iff",&v1,&v2,&v3), data is ignored after &v3) - */ - void setArgs( char *types , ... ); //set ("if",&v1,&v2) - - friend class OSCClass; - -}; - - - -/* ==================================== OSCClass for sending and receiving OSC messages using UDP protocol ===================================== */ - -#include "UDPSocket.h" - -/** Wraps the UDP functions to send and receive OSC messages */ -class OSCClass { - -private: - - UDPSocket udpRec,udpSend; - char rcvBuff[256]; // raw buffer for UDP packets (udpRec.recvfrom( buf, 256, &host ) )) - int buflength; - - OSCMessage *receiverMessage; - OSCMessage *sendContainer; - - 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(); - -/** - This sets "binds" the received message to the receiver container of the communication object - @param[in] _mes A pointer to the "receiveing" OSC message (OSCMessage *) - */ - OSCClass(OSCMessage *_mes); // set the receiver message container - -/** - This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT) - */ - void begin(); - -/** - Initialize an OSC object with arbitrary listening port - @param[in] _recievePort The listening ("receiving") Port No (unsigned int) - */ - void begin(uint16_t _recievePort); - -/** - Stop OSC communication (in fact, only the receiver - the server side) - */ - void stop(); - -/** - Returns whether there is new OSC data in the receiver message container. - */ - bool newMessage; - -/** - Set a OSC receive message container - @param[in] _mes Pointer to the OSC receive message container (OSCMessage *) - */ - void setReceiveMessage( OSCMessage *_mes ); //set receive OSCmessage container (note: the message has a "host" object from which we get the upd packets) - -/** - Get the received OSC message (note: this is another way to access the message directly from the OSCClass object). - The advantage is that we will signal that we read the message, and will be able to query if a NEW message arrived - (Alternatively, one could have a function pointer to pass to the OSC object, that will be called each time a new packet is received: TO DO) - */ - OSCMessage *getMessage(); //return received OSCmessage - -/** - Send an OSC Message (message contain the host ip and port where the message data has to be sent) - @param[in] _mes Pointer to the OSC message container (OSCMessage *) - */ - void sendOsc( OSCMessage *_mes ); //set&send OSCmessage (note: it will be sent to the host defined in the message container) - -/** - A function pointer to be set by host program that will be called on receipt of an OSC message - @code - osc.messageReceivedCallback.attach(&processOSC); - @endcode - */ - FunctionPointer messageReceivedCallback; -}; - -#endif
--- a/PinDetect.lib Mon Apr 23 09:30:50 2012 +0000 +++ b/PinDetect.lib Thu Jul 19 10:46:53 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/AjK/libraries/PinDetect/lkyxpw \ No newline at end of file +http://mbed.org/users/AjK/code/PinDetect/#cb3afc45028b
--- a/SPK-TVOne.lib Mon Apr 23 09:30:50 2012 +0000 +++ b/SPK-TVOne.lib Thu Jul 19 10:46:53 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/tobyspark/libraries/SPK-TVOne/m8i0mo \ No newline at end of file +http://mbed.org/users/tobyspark/code/SPK-TVOne/#533cfae24a1b
--- a/mRotaryEncoder.lib Mon Apr 23 09:30:50 2012 +0000 +++ b/mRotaryEncoder.lib Thu Jul 19 10:46:53 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/charly/libraries/mRotaryEncoder/lmcj2u \ No newline at end of file +http://mbed.org/users/charly/code/mRotaryEncoder/#75ddffaf3721
--- a/main.cpp Mon Apr 23 09:30:50 2012 +0000 +++ b/main.cpp Thu Jul 19 10:46:53 2012 +0000 @@ -12,7 +12,9 @@ // v13 - Menu system for Resolution + Keying implemented, it writing to debug, it sending TVOne commands - Apr'11 // v14 - Fixes for new PCB - Oct'11 // v15 - TBZ PCB, OLED - Mar'12 -// v16 - Comms menu, OSC. There in theory: lots of trouble from EthernetNetIf. NetServices better. But still silently crashes on creation of EthernetNetIf, despite (now) ample memory and code tested elsewhere (inc OSC + spkOLED). +// v16 - Comms menu, OSC, ArtNet - April'12 +// v17 - RJ45 - May'12 +// v18 - DMX - July'12 // vxx - TODO: EDID upload from USB mass storage // vxx - TODO: EDID creation from resolution @@ -26,14 +28,43 @@ #include "EthernetNetIf.h" #include "mbedOSC.h" #include "DmxArtNet.h" +#include "DMX.h" #include <sstream> +// MBED PINS + +#define kMBED_AIN_XFADE p20 +#define kMBED_AIN_FADEUP p19 +#define kMBED_DIN_TAP_L p24 +#define kMBED_DIN_TAP_R p23 +#define kMBED_ENC_SW p15 +#define kMBED_ENC_A p16 +#define kMBED_ENC_B p17 + +#define kMBED_RS232_TTLTX p13 +#define kMBED_RS232_TTLRX p14 + +#define kMBED_OLED_MOSI p5 +#define kMBED_OLED_SCK p7 +#define kMBED_OLED_CS p8 +#define kMBED_OLED_RES p9 +#define kMBED_OLED_DC p10 + +#define kMBED_DIN_ETHLO_DMXHI p30 +#define kMBED_DOUT_RS485_TXHI_RXLO p29 +#define kMBED_RS485_TTLTX p28 +#define kMBED_RS485_TTLRX p27 + +// DISPLAY + #define kMenuLine1 3 #define kMenuLine2 4 #define kCommsStatusLine 6 #define kTVOneStatusLine 7 +// NETWORKING + #define kOSCMbedPort 10000 #define kOSCMbedIPAddress 10,0,0,2 #define kOSCMbedSubnetMask 255,255,255,0 @@ -43,46 +74,61 @@ #define kArtNetBindIPAddress 2,0,0,100 #define kArtNetBroadcastAddress 2,255,255,255 +#define kDMXInChannelXFade 0 +#define kDMXInChannelFadeUp 1 +#define kDMXOutChannelXFade 0 +#define kDMXOutChannelFadeUp 1 + //// DEBUG // Comment out one or the other... -Serial *debug = new Serial(USBTX, USBRX); // For debugging via USB serial -// Serial *debug = NULL; // For release (no debugging) +//Serial *debug = new Serial(USBTX, USBRX); // For debugging via USB serial +Serial *debug = NULL; // For release (no debugging) //// mBED PIN ASSIGNMENTS // Inputs -AnalogIn xFadeAIN(p20); -AnalogIn fadeUpAIN(p19); -DigitalIn tapLeftDIN(p24); -DigitalIn tapRightDIN(p23); +AnalogIn xFadeAIN(kMBED_AIN_XFADE); +AnalogIn fadeUpAIN(kMBED_AIN_FADEUP); +DigitalIn tapLeftDIN(kMBED_DIN_TAP_L); +DigitalIn tapRightDIN(kMBED_DIN_TAP_R); -SPKRotaryEncoder menuEnc(p17, p16, p15); +SPKRotaryEncoder menuEnc(kMBED_ENC_A, kMBED_ENC_B, kMBED_ENC_SW); + +DigitalIn rj45ModeDIN(kMBED_DIN_ETHLO_DMXHI); // Outputs PwmOut fadeAPO(LED1); PwmOut fadeBPO(LED2); +DigitalOut dmxDirectionDOUT(kMBED_DOUT_RS485_TXHI_RXLO); + // SPKTVOne(PinName txPin, PinName rxPin, PinName signWritePin, PinName signErrorPin, Serial *debugSerial) -SPKTVOne tvOne(p13, p14, LED3, LED4, debug); +SPKTVOne tvOne(kMBED_RS232_TTLTX, kMBED_RS232_TTLRX, LED3, LED4, debug); // SPKDisplay(PinName mosi, PinName clk, PinName cs, PinName dc, PinName res, Serial *debugSerial = NULL); -SPKDisplay screen(p5, p7, p8, p10, p9, debug); +SPKDisplay screen(kMBED_OLED_MOSI, kMBED_OLED_SCK, kMBED_OLED_CS, kMBED_OLED_DC, kMBED_OLED_RES, debug); // Menu - SPKMenu *selectedMenu; SPKMenu *lastSelectedMenu; SPKMenuOfMenus mainMenu; SPKMenuPayload resolutionMenu; SPKMenuPayload mixModeMenu; +enum { blend, additive, lumaKey, chromaKey1, chromaKey2, chromaKey3 }; // additive will require custom TVOne firmware. +int mixMode = blend; SPKMenuPayload commsMenu; +enum { commsNone, commsOSC, commsArtNet, commsDMXIn, commsDMXOut}; +int commsMode = commsNone; -// Comms Objects +// RJ45 Comms +enum { rj45Ethernet = 0, rj45DMX = 1}; // These values from circuit +int rj45Mode = -1; EthernetNetIf *ethernet = NULL; OSCClass *osc = NULL; OSCMessage recMessage; DmxArtNet *artNet = NULL; +DMX *dmx = NULL; // Fade logic constants const float xFadeTolerance = 0.05; @@ -93,8 +139,7 @@ int fadeBPercent = 0; // Tap button states -bool tapLeftPrevious = false; -bool tapRightPrevious = false; +bool tapLeftWasFirstPressed = false; // Key mode parameters int keyerParamsSet = -1; // last keyParams index uploaded to unit @@ -147,13 +192,45 @@ void processArtNet(float &xFade, float &fadeUp) { - screen.clearBufferRow(kCommsStatusLine); screen.textToBuffer("ArtNet activity", kCommsStatusLine); screen.sendBuffer(); if (debug) debug->printf("ArtNet activity"); } +void processDMXIn(float &xFade, float &fadeUp) { + + std::stringstream statusMessage; + + int xFadeDMX = dmx->get(kDMXInChannelXFade); + int fadeUpDMX = dmx->get(kDMXInChannelXFade); + + xFade = (float)xFadeDMX/255; + fadeUp = (float)fadeUpDMX/255; + + screen.clearBufferRow(kCommsStatusLine); + statusMessage << "DMX In: xF " << xFadeDMX << " fUp " << fadeUpDMX; + screen.textToBuffer(statusMessage.str(), kCommsStatusLine); + screen.sendBuffer(); + if (debug) debug->printf(statusMessage.str().c_str()); +} + +void processDMXOut(float &xFade, float &fadeUp) { + + std::stringstream statusMessage; + + int xFadeDMX = xFade*255; + int fadeUpDMX = fadeUp*255; + + dmx->put(kDMXOutChannelXFade, xFadeDMX); + dmx->put(kDMXOutChannelFadeUp, fadeUpDMX); + + screen.clearBufferRow(kCommsStatusLine); + statusMessage << "DMX Out: xF " << xFadeDMX << " fUp " << fadeUpDMX; + screen.textToBuffer(statusMessage.str(), kCommsStatusLine); + screen.sendBuffer(); + if (debug) debug->printf(statusMessage.str().c_str()); +} inline float fadeCalc (const float AIN, const float tolerance) { float pos ; @@ -202,11 +279,11 @@ // Splash screen screen.imageToBuffer(spkDisplayLogo); screen.textToBuffer("SPK:D-Fuser",0); - screen.textToBuffer("SW beta.15",1); + screen.textToBuffer("SW beta.18",1); + screen.sendBuffer(); // Set menu structure mixModeMenu.title = "Mix Mode"; - enum { blend, additive, lumaKey, chromaKey1, chromaKey2, chromaKey3 }; // additive will require custom TVOne firmware. mixModeMenu.addMenuItem("Blend", blend, 0); mixModeMenu.addMenuItem("LumaKey", lumaKey, 0); mixModeMenu.addMenuItem("ChromaKey - Blue", chromaKey1, 0); @@ -223,12 +300,12 @@ resolutionMenu.addMenuItem(kTV1ResolutionDescriptionDualHeadXGAp60, kTV1ResolutionDualHeadXGAp60, 0); resolutionMenu.addMenuItem(kTV1ResolutionDescriptionTripleHeadVGAp60, kTV1ResolutionTripleHeadVGAp60, 0); - commsMenu.title = "Network Mode"; - enum { commsNone, commsOSC, commsArtNet, commsDMX}; + commsMenu.title = "Network Mode"; commsMenu.addMenuItem("None", commsNone, 0); commsMenu.addMenuItem("OSC", commsOSC, 0); commsMenu.addMenuItem("ArtNet", commsArtNet, 0); - commsMenu.addMenuItem("DMX", commsDMX, 0); + commsMenu.addMenuItem("DMX In", commsDMXIn, 0); + commsMenu.addMenuItem("DMX Out", commsDMXOut, 0); mainMenu.title = "Main Menu"; mainMenu.addMenuItem(&mixModeMenu); @@ -278,9 +355,29 @@ while (1) { //// Task background things - if (commsMenu.selectedPayload1() == commsOSC || commsMenu.selectedPayload1() == commsArtNet) + if (ethernet && rj45Mode == rj45Ethernet) + { + if (debug) debug->printf("net poll"); + Net::poll(); + } + + //// RJ45 SWITCH + + if (rj45ModeDIN != rj45Mode) { - Net::poll(); + // update state + rj45Mode = rj45ModeDIN; + if (rj45Mode == rj45Ethernet) commsMenu.title = "Network Mode [Ethernet]"; + if (rj45Mode == rj45DMX) commsMenu.title = "Network Mode [DMX]"; + + // cancel old comms + commsMode = commsNone; + commsMenu = commsMode; + + // refresh display + if (selectedMenu == &commsMenu) screen.textToBuffer(selectedMenu->title, kMenuLine1); + if (rj45Mode == rj45Ethernet) screen.textToBuffer("RJ45: Ethernet Engaged", kCommsStatusLine); + if (rj45Mode == rj45DMX) screen.textToBuffer("RJ45: DMX Engaged", kCommsStatusLine); } //// MENU @@ -299,7 +396,6 @@ screen.textToBuffer(selectedMenu->selectedString(), kMenuLine2); if (debug) debug->printf("%s \r\n", selectedMenu->selectedString().c_str()); - } // Action menu item @@ -352,6 +448,8 @@ // With that out of the way, we should be actioning a specific menu's payload? else if (selectedMenu == &mixModeMenu) { + mixMode = mixModeMenu.selectedPayload1(); + bool ok = false; std::string sentOK; std::stringstream sentMSG; @@ -414,19 +512,31 @@ } else if (selectedMenu == &commsMenu) { - std::string commsType = "Network: --"; + std::string commsTypeString = "Network: --"; std::stringstream commsStatus; // Tear down any existing comms // This is the action of commsNone // And also clears the way for other comms actions - if (osc) {delete osc; osc = NULL;} - if (ethernet) {delete ethernet; ethernet = NULL;} - if (artNet) {delete artNet; artNet = NULL;} - - if (commsMenu.selectedPayload1() == commsOSC) + if (osc) {delete osc; osc = NULL;} + if (ethernet) {delete ethernet; ethernet = NULL;} + if (artNet) {delete artNet; artNet = NULL;} + if (dmx) {delete dmx; dmx = NULL;} + + // Ensure we can't change to comms modes the hardware isn't switched to + if (rj45Mode == rj45DMX && (commsMenu.selectedPayload1() == commsOSC || commsMenu.selectedPayload1() == commsArtNet)) { - commsType = "OSC: "; + commsTypeString = "RJ45 not in Ethernet mode"; + } + else if (rj45Mode == rj45Ethernet && (commsMenu.selectedPayload1() == commsDMXIn || commsMenu.selectedPayload1() == commsDMXOut)) + { + commsTypeString = "RJ45 not in DMX mode"; + } + // Action! + else if (commsMenu.selectedPayload1() == commsOSC) + { + commsMode = commsOSC; + commsTypeString = "OSC: "; ethernet = new EthernetNetIf( IpAddr(kOSCMbedIPAddress), @@ -440,7 +550,7 @@ { if (debug) debug->printf("Ethernet setup error, %d", ethError); commsStatus << "Ethernet setup failed"; - // commsMenu = commsNone; //FIXME: this should set the selected menu item to none, but errors. wtf? + commsMenu = commsNone; // break out of here. this setup should be a function that returns a boolean } @@ -452,7 +562,8 @@ } else if (commsMenu.selectedPayload1() == commsArtNet) { - commsType = "ArtNet: "; + commsMode = commsArtNet; + commsTypeString = "ArtNet: "; artNet = new DmxArtNet(); @@ -470,13 +581,27 @@ commsStatus << "Listening"; } - else if (commsMenu.selectedPayload1() == commsDMX) + else if (commsMenu.selectedPayload1() == commsDMXIn) { + commsMode = commsDMXIn; + commsTypeString = "DMX In: "; + dmxDirectionDOUT = 0; + + dmx = new DMX(kMBED_RS485_TTLTX, kMBED_RS485_TTLRX); } - + else if (commsMenu.selectedPayload1() == commsDMXOut) + { + commsMode = commsDMXOut; + commsTypeString = "DMX Out: "; + + dmxDirectionDOUT = 1; + + dmx = new DMX(kMBED_RS485_TTLTX, kMBED_RS485_TTLRX); + } + screen.clearBufferRow(kCommsStatusLine); - screen.textToBuffer(commsType + commsStatus.str(), kCommsStatusLine); + screen.textToBuffer(commsTypeString + commsStatus.str(), kCommsStatusLine); } else { @@ -486,9 +611,9 @@ // Send any updates to the display screen.sendBuffer(); - + - //// MIX MIX MIX MIX MIX MIX MIX MIX MIXMIX MIX MIXMIX MIX MIXMIX MIX MIXMIX MIX MIXMIX MIX MIX + //// MIX MIX MIX MIX MIX MIX MIX MIX MIX MIX MIX MIXMIX MIX MIXMIX MIX MIX MIX MIX MIXMIX MIX MIX bool updateFade = false; float xFade = 0; @@ -497,32 +622,39 @@ //// TASK: Process control surface // Get new states of tap buttons, remembering at end of loop() assign these current values to the previous variables - const bool tapLeft = (tapLeftDIN) ? false : true; - const bool tapRight = (tapRightDIN) ? false : true; + const bool tapLeft = !tapLeftDIN; + const bool tapRight = !tapRightDIN; // We're going to cache the analog in reads, as have seen wierdness otherwise - const float xFadeAINCached = xFadeAIN.read(); + const float xFadeAINCached = 1-xFadeAIN.read(); const float fadeUpAINCached = fadeUpAIN.read(); // When a tap is depressed, we can ignore any move of the crossfader but not fade to black if (tapLeft || tapRight) { - // If both are pressed, which was not pressed in the last loop? + // If both are pressed, take to the one that is new, ie. not the first pressed. if (tapLeft && tapRight) { - if (!tapLeftPrevious) xFade = 0; - if (!tapRightPrevious) xFade = 1; + xFade = tapLeftWasFirstPressed ? 1 : 0; } - // If just one is pressed, is this it going high or the other going low? - else if (tapLeft && (!tapLeftPrevious || tapRightPrevious)) xFade = 0; - else if (tapRight && (!tapRightPrevious || tapLeftPrevious)) xFade = 1; - } + // If just one is pressed, take to that and remember which is pressed + else if (tapLeft) + { + xFade = 0; + tapLeftWasFirstPressed = 1; + } + else if (tapRight) + { + xFade = 1; + tapLeftWasFirstPressed = 0; + } + } else xFade = fadeCalc(xFadeAINCached, xFadeTolerance); fadeUp = 1.0 - fadeCalc(fadeUpAINCached, fadeUpTolerance); //// TASK: Process Network Comms - if (commsMenu.selectedPayload1() == commsOSC) + if (commsMode == commsOSC) { if (osc->newMessage) { @@ -531,11 +663,21 @@ } } - if (commsMenu.selectedPayload1() == commsArtNet) + if (commsMode == commsArtNet) { if (artNet->Work()) processArtNet(xFade, fadeUp); } + if (commsMode == commsDMXIn) + { + processDMXIn(xFade, fadeUp); + } + + if (commsMode == commsDMXOut) + { + processDMXOut(xFade, fadeUp); + } + // WISH: Really, we should have B at 100% and A fading in over that, with fade to black implemented as a fade in black layer on top of that correct mix. // There is no way to implement that though, and the alphas get messy, so this is the only way (afaik). @@ -543,7 +685,7 @@ int newFadeAPercent = 0; int newFadeBPercent = 0; - switch (mixModeMenu.selectedPayload1()) { + switch (mixMode) { case blend: case additive: newFadeAPercent = (1.0-xFade) * fadeUp * 100.0; @@ -581,9 +723,6 @@ debug->printf("xFade = %3f fadeUp = %3f \r\n", xFadeAINCached, fadeUpAINCached); debug->printf("xFade = %3f fadeUp = %3f fadeA% = %i fadeB% = %i \r\n", xFade, fadeUp, fadeAPercent, fadeBPercent); } - - // END OF LOOP - Reset - tapLeftPrevious = tapLeft; - tapRightPrevious = tapRight; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Jul 19 10:46:53 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/10b9abbe79a6 \ No newline at end of file
--- a/mbed.lib Mon Apr 23 09:30:50 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/projects/libraries/svn/mbed/trunk@43 \ No newline at end of file
--- a/spk_oled_ssd1305.lib Mon Apr 23 09:30:50 2012 +0000 +++ b/spk_oled_ssd1305.lib Thu Jul 19 10:46:53 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/tobyspark/libraries/spk_oled_ssd1305/m8i8mv \ No newline at end of file +http://mbed.org/users/tobyspark/code/spk_oled_ssd1305/#8187d69071f8
--- a/spk_utils.h Mon Apr 23 09:30:50 2012 +0000 +++ b/spk_utils.h Thu Jul 19 10:46:53 2012 +0000 @@ -67,8 +67,10 @@ std::string title; - void operator = (int newIndex) { + // not carried into subclass... whats the c++ way of doing this? + SPKMenu& operator = (const int &newIndex) { selected = newIndex; + return *this; } void operator ++ () { @@ -143,7 +145,13 @@ int32_t selectedPayload2() { return payload2[selected.index()]; } - + + SPKMenuPayload& operator = (const int &newIndex) { + selected = newIndex; + return *this; + } + + private: vector<int32_t> payload1; vector<int32_t> payload2;