PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

291 lines
11KB

  1. /*
  2. Bidirectional Esplora OSC communications
  3. using SLIP
  4. Adrian Freed, Jeff Lubow 2013
  5. Includes some examples of common "best practices" for OSC name space and parameter
  6. mapping design.
  7. */
  8. #include <Esplora.h>
  9. #include <OSCBundle.h>
  10. //Teensy and Leonardo variants have special USB serial
  11. #include <SLIPEncodedUSBSerial.h>
  12. #if !defined(__AVR_ATmega32U4__)
  13. #error select Arduino Esplora in board menu
  14. #endif
  15. // temperature
  16. float getTemperature(){
  17. int result;
  18. ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0);
  19. ADCSRB = _BV(MUX5);
  20. delayMicroseconds(200); // wait for Vref to settle
  21. ADCSRA |= _BV(ADSC); // Convert
  22. while (bit_is_set(ADCSRA,ADSC));
  23. result = ADCL;
  24. result |= ADCH<<8;
  25. analogReference(DEFAULT);
  26. return result/1023.0f;
  27. }
  28. float getSupplyVoltage(){
  29. // powersupply
  30. int result;
  31. // Read 1.1V reference against AVcc
  32. ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  33. delayMicroseconds(300); // wait for Vref to settle
  34. ADCSRA |= _BV(ADSC); // Convert
  35. while (bit_is_set(ADCSRA,ADSC));
  36. result = ADCL;
  37. result |= ADCH<<8;
  38. float supplyvoltage = 1.1264f *1023 / result;
  39. return supplyvoltage;
  40. }
  41. // Esplora has a dinky green led at the top left and a big RGB led at the bottom right
  42. void routeLed(OSCMessage &msg, int addrOffset ){
  43. if(msg.match("/red", addrOffset)) {
  44. if (msg.isInt(0)) Esplora.writeRed( (byte)msg.getInt(0));
  45. }
  46. else
  47. if(msg.match("/green", addrOffset)) {
  48. if (msg.isInt(0)) Esplora.writeGreen( (byte)msg.getInt(0));
  49. }
  50. else
  51. if(msg.match("/blue", addrOffset)) {
  52. if (msg.isInt(0)) Esplora.writeBlue( (byte)msg.getInt(0));
  53. }
  54. else
  55. if(msg.match("/rgb", addrOffset)) {
  56. if (msg.isInt(0)&&msg.isInt(1)&&msg.isInt(2))
  57. {
  58. Esplora.writeRGB((byte)msg.getInt(0),(byte)msg.getInt(1),(byte)msg.getInt(2));
  59. }
  60. }
  61. else
  62. {
  63. if (msg.isInt(0))
  64. {
  65. digitalWrite(13, msg.getInt(0)>0?HIGH:LOW);
  66. }
  67. }
  68. }
  69. // Esplora has a dinky green led at the top left and a big RGB led at the bottom right
  70. void routeOut(OSCMessage &msg, int addrOffset ){
  71. if(msg.match("/B", addrOffset) || msg.match("/b", addrOffset)) {
  72. if (msg.isInt(0)) {
  73. pinMode(11,OUTPUT);
  74. digitalWrite(11, msg.getInt(0)>0?HIGH:LOW);
  75. }
  76. else
  77. pinMode(11,INPUT); // add pull up logic some day
  78. }
  79. else
  80. if(msg.match("/A", addrOffset) ||msg.match("/a", addrOffset)) {
  81. if (msg.isInt(0)) {
  82. pinMode(3,OUTPUT);
  83. digitalWrite(3, msg.getInt(0)>0?HIGH:LOW);
  84. }
  85. else
  86. pinMode(3,INPUT); // add pull up logic some day
  87. }
  88. }
  89. /**
  90. * TONE
  91. *
  92. * square wave output "/tone"
  93. *
  94. * format:
  95. * /tone
  96. * (no value) = notome
  97. * float or int = frequency
  98. * optional length of time as an integer in milliseconds afterwards
  99. *
  100. **/
  101. void routeTone(OSCMessage &msg, int addrOffset ){
  102. unsigned int frequency = 0;
  103. if (msg.isInt(0)){
  104. frequency = msg.getInt(0);
  105. }
  106. else if(msg.isFloat(0)){
  107. frequency = msg.getFloat(0); // this doesn't work due to problems with double to float conversion?
  108. }
  109. else
  110. Esplora.noTone();
  111. if(frequency>0)
  112. {
  113. if(msg.isInt(1))
  114. Esplora.tone(frequency, msg.getInt(1));
  115. else
  116. Esplora.tone( frequency);
  117. }
  118. }
  119. const char *released = "released";
  120. const char *pressed = "pressed";
  121. SLIPEncodedUSBSerial SLIPSerial(Serial);
  122. const byte MUX_ADDR_PINS[] = {
  123. A0, A1, A2, A3 };
  124. const byte MUX_COM_PIN = A4;
  125. unsigned int myReadChannel(byte channel) {
  126. digitalWrite(MUX_ADDR_PINS[0], (channel & 1) ? HIGH : LOW);
  127. digitalWrite(MUX_ADDR_PINS[1], (channel & 2) ? HIGH : LOW);
  128. digitalWrite(MUX_ADDR_PINS[2], (channel & 4) ? HIGH : LOW);
  129. digitalWrite(MUX_ADDR_PINS[3], (channel & 8) ? HIGH : LOW);
  130. return analogRead(MUX_COM_PIN);
  131. }
  132. void setup() {
  133. //begin SLIPSerial just like Serial
  134. SLIPSerial.begin(115200); // set this as high as you can reliably run on your platform
  135. while(!Serial)
  136. ; //Leonardo "feature" (also needed on Esplora?)
  137. }
  138. int32_t counter = 0;
  139. int32_t serialnumber = 2; //hard coded; beware
  140. int32_t num_components = 3; //currently break the bundle up into 3 components
  141. void loop(){
  142. OSCBundle bndl;
  143. int32_t manifest_count = 1;
  144. if(!SLIPSerial.available())
  145. {
  146. // The RAW OSC address space and parameter mappngs try to capture
  147. // the data at lowest level without calibration or scaling
  148. // The names are chosen to match what is on the silkscreen of the board where it is found
  149. #define RAW
  150. #ifdef RAW
  151. SLIPSerial.beginPacket();
  152. bndl.add("/mic").add((int32_t)Esplora.readMicrophone());
  153. bndl.add("/temp/sensor/celsius").add((int32_t)Esplora.readTemperature(DEGREES_C));
  154. bndl.add("/temp/sensor/fahrenheit").add((int32_t)Esplora.readTemperature(DEGREES_F));
  155. bndl.add("/linear/potentiometer").add((int32_t)Esplora.readSlider());
  156. bndl.add("/light/sensor").add((int32_t)Esplora.readLightSensor());
  157. bndl.add("/switch/1").add((int32_t)Esplora.readButton(SWITCH_1));
  158. bndl.add("/switch/2").add((int32_t)Esplora.readButton(SWITCH_2));
  159. bndl.add("/switch/3").add((int32_t)Esplora.readButton(SWITCH_3));
  160. bndl.add("/switch/4").add((int32_t)Esplora.readButton(SWITCH_4));
  161. bndl.add("/joystick/X").add((int32_t)Esplora.readJoystickX());
  162. bndl.add("/joystick/Y").add((int32_t)Esplora.readJoystickY());
  163. bndl.add("/joystick/switch").add((int32_t)Esplora.readJoystickSwitch());
  164. bndl.add("/joystick/switch/1").add((int32_t)Esplora.readButton(JOYSTICK_DOWN));
  165. bndl.add("/joystick/switch/2").add((int32_t)Esplora.readButton(JOYSTICK_LEFT));
  166. bndl.add("/joystick/switch/3").add((int32_t)Esplora.readButton(JOYSTICK_UP));
  167. bndl.add("/joystick/switch/4").add((int32_t)Esplora.readButton(JOYSTICK_RIGHT));
  168. bndl.add("/accelerometer/x").add(Esplora.readAccelerometer(X_AXIS));
  169. bndl.add("/accelerometer/y").add(Esplora.readAccelerometer(Y_AXIS));
  170. bndl.add("/accelerometer/z").add(Esplora.readAccelerometer(Z_AXIS));
  171. bndl.send(SLIPSerial); // send the bytes to the SLIP stream
  172. SLIPSerial.endPacket(); // mark the end of the OSC Packet
  173. bndl.empty();
  174. #endif //RAW
  175. // The COOKED OSC address space and parameter mappings
  176. // encode data for ease of use and legibility at the host. Unit intervals replace integers
  177. // The names are chosen to clarify usage rather than adherance to the silkscreen
  178. // also values are acquired as close together as reasonably possible to increase
  179. // their usability in sensor fusion contexts, i.e. in this case with the accelerometer
  180. SLIPSerial.beginPacket(); // mark the beginning of the OSC Packet
  181. //bundle 1
  182. bndl.add("/acceleration/x").add(Esplora.readAccelerometer(X_AXIS)/512.0f);
  183. bndl.add("/acceleration/y").add(Esplora.readAccelerometer(Y_AXIS)/512.0f);
  184. bndl.add("/acceleration/z").add(Esplora.readAccelerometer(Z_AXIS)/512.0f);
  185. bndl.add("/photoresistor").add(Esplora.readLightSensor()/1023.0f);
  186. bndl.add("/joystick/horizontal").add(-1.0 * (int32_t)Esplora.readJoystickX()/512.0f);
  187. bndl.add("/joystick/vertical").add(-1.0 * (int32_t)Esplora.readJoystickY()/512.0f);
  188. bndl.add("/joystick/button").add(Esplora.readJoystickSwitch()>0? released:pressed);
  189. bndl.add("/joystick/backward").add((int32_t)Esplora.readButton(JOYSTICK_DOWN)?released:pressed);
  190. bndl.add("/joystick/left").add((int32_t)Esplora.readButton(JOYSTICK_LEFT)?released:pressed);
  191. bndl.add("/joystick/forward").add((int32_t)Esplora.readButton(JOYSTICK_UP)?released:pressed);
  192. bndl.add("/joystick/right").add((int32_t)Esplora.readButton(JOYSTICK_RIGHT)?released:pressed);
  193. bndl.add("/serialnumber").add(serialnumber);
  194. //bndl.add("/manifest").add(manifest_count++).add(num_components).add(counter);
  195. bndl.send(SLIPSerial); // send the bytes to the SLIP stream
  196. SLIPSerial.endPacket(); // mark the end of the OSC Packet
  197. bndl.empty(); //bundle ending early due to current memory limitations
  198. //bundle 2
  199. bndl.add("/diamond/backward").add((int32_t)Esplora.readButton(SWITCH_1)?released:pressed);
  200. bndl.add("/diamond/left").add((int32_t)Esplora.readButton(SWITCH_2)?released:pressed);
  201. bndl.add("/diamond/forward").add((int32_t)Esplora.readButton(SWITCH_3)?released:pressed);
  202. bndl.add("/diamond/right").add((int32_t)Esplora.readButton(SWITCH_4)?released:pressed);
  203. bndl.add("/microphone/loudness").add(Esplora.readMicrophone()/1023.0f);
  204. bndl.add("/temperature/fahrenheit").add((float)Esplora.readTemperature(DEGREES_F));
  205. bndl.add("/temperature/celsius").add((float)Esplora.readTemperature(DEGREES_C));
  206. bndl.add("/slider/horizontal").add(1.0f - ((float)Esplora.readSlider()/1023.0f));
  207. bndl.add("/serialnumber").add(serialnumber);
  208. //bndl.add("/manifest").add(manifest_count++).add(num_components).add(counter);
  209. bndl.send(SLIPSerial); // send the bytes to the SLIP stream
  210. SLIPSerial.endPacket(); // mark the end of the OSC Packet
  211. bndl.empty(); //bundle ending early due to current memory limitations
  212. //bundle 3
  213. bndl.add("/connector/white/left").add(myReadChannel(CH_MIC +1)/1023.0);
  214. bndl.add("/connector/white/right").add(myReadChannel(CH_MIC +2)/1023.0);
  215. bndl.add("/led/red").add((int32_t)Esplora.readRed());
  216. bndl.add("/led/green").add((int32_t)Esplora.readGreen());
  217. bndl.add("/led/blue").add((int32_t)Esplora.readBlue());
  218. bndl.add("/led/rgb").add((int32_t)Esplora.readRed()).add((int32_t)Esplora.readGreen()).add((int32_t)Esplora.readBlue());
  219. bndl.add("/connector/orange/right").add((digitalRead(3)==HIGH)?1:0);
  220. bndl.add("/connector/orange/left").add((digitalRead(11)==HIGH)?1:0);
  221. bndl.add("/vendor").add("Arduino");
  222. bndl.add("/productname").add("Esplora");
  223. bndl.add("/serialnumber").add(serialnumber);
  224. //bndl.add("/manifest").add(manifest_count++).add(num_components).add(counter);
  225. bndl.send(SLIPSerial); // send the bytes to the SLIP stream
  226. SLIPSerial.endPacket(); // mark the end of the OSC Packet
  227. bndl.empty();
  228. counter += 1;
  229. // bndl.add("/32u4/supplyVoltage").add(getSupplyVoltage());
  230. // bndl.add("/32u4/temperature").add(getTemperature());
  231. }
  232. else
  233. {
  234. OSCBundle bundleIN;
  235. int size;
  236. while(!SLIPSerial.endofPacket())
  237. if ((size =SLIPSerial.available()) > 0)
  238. {
  239. while(size--)
  240. bundleIN.fill(SLIPSerial.read());
  241. }
  242. {
  243. if(!bundleIN.hasError())
  244. {
  245. bundleIN.route("/led", routeLed);
  246. bundleIN.route("/L", routeLed); // this is how it is marked on the silkscreen
  247. bundleIN.route("/out", routeOut); // for the TinkerIt output connectors
  248. bundleIN.route("/tone", routeTone);
  249. bundleIN.route("/squarewave", routeTone);
  250. bundleIN.route("/notone", routeTone);
  251. }
  252. }
  253. }
  254. }