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.

412 lines
11KB

  1. #include <OSCBundle.h>
  2. #include <OSCBoards.h>
  3. // tested on Fubarino with MpIDE 0023-macosx-20130514-test
  4. // analalogRead() has a strange interpretation of its arguments
  5. // they think you are supposed to pass digital pin numbers???
  6. #ifdef BOARD_HAS_USB_SERIAL
  7. #include <SLIPEncodedUSBSerial.h>
  8. SLIPEncodedUSBSerial SLIPSerial( thisBoardsSerialUSB );
  9. #else
  10. #include <SLIPEncodedSerial.h>
  11. SLIPEncodedSerial SLIPSerial(Serial);
  12. #endif
  13. OSCBundle bundleOUT;
  14. //converts the pin to an osc address
  15. char * numToOSCAddress( int pin){
  16. static char s[10];
  17. int i = 9;
  18. s[i--]= '\0';
  19. do
  20. {
  21. s[i] = "0123456789"[pin % 10];
  22. --i;
  23. pin /= 10;
  24. }
  25. while(pin && i);
  26. s[i] = '/';
  27. return &s[i];
  28. }
  29. /**
  30. * ROUTES
  31. *
  32. * these are where the routing functions go
  33. *
  34. */
  35. /**
  36. * DIGITAL
  37. *
  38. * called when address matched "/d"
  39. * expected format:
  40. * /d/(pin)
  41. * /u = digitalRead with pullup
  42. * (no value) = digitalRead without pullup
  43. * (value) = digital write on that pin
  44. *
  45. */
  46. void routeDigital(OSCMessage &msg, int addrOffset ){
  47. //match input or output
  48. for(byte pin = 0; pin < NUM_DIGITAL_PINS; pin++){
  49. //match against the pin number strings
  50. int pinMatched = msg.match(numToOSCAddress(pin), addrOffset);
  51. if(pinMatched){
  52. switch(pin)
  53. {
  54. // fubarino MINI
  55. // these are used for clocks and USB and Program switch and shouldn't be written to
  56. // unless you know what you are doing
  57. case 3: case 14: case 15: case 23: case 16: case 31:case 32: goto out;
  58. }
  59. //if it has an int, then it's a digital write
  60. if (msg.isInt(0)){
  61. pinMode(pin, OUTPUT);
  62. digitalWrite(pin, (msg.getInt(0)>0) ? HIGH:LOW);
  63. } //otherwise it's an digital read
  64. //with a pullup?
  65. else if (msg.fullMatch("/u", pinMatched+addrOffset)){
  66. //set the pullup
  67. pinMode(pin, INPUT_PULLUP);
  68. //setup the output address which should be /d/(pin)/u
  69. char outputAddress[9];
  70. strcpy(outputAddress, "/d");
  71. strcat(outputAddress, numToOSCAddress(pin));
  72. strcat(outputAddress,"/u");
  73. //do the digital read and send the results
  74. {
  75. OSCMessage msgOut(outputAddress); msgOut.add(digitalRead(pin));
  76. SLIPSerial.beginPacket(); msgOut.send(SLIPSerial); SLIPSerial.endPacket();
  77. }
  78. } //else without a pullup
  79. else {
  80. //set the pinmode
  81. pinMode(pin, INPUT);
  82. //setup the output address which should be /d/(pin)
  83. char outputAddress[6];
  84. strcpy(outputAddress, "/d");
  85. strcat(outputAddress, numToOSCAddress(pin));
  86. //do the digital read and send the results
  87. {
  88. OSCMessage msgOut(outputAddress); msgOut.add(digitalRead(pin));
  89. SLIPSerial.beginPacket(); msgOut.send(SLIPSerial); SLIPSerial.endPacket();
  90. }
  91. }
  92. }
  93. out: ;
  94. }
  95. }
  96. /**
  97. * ANALOG
  98. *
  99. * called when the address matches "/a"
  100. *
  101. * format:
  102. * /a/(pin)
  103. * /u = analogRead with pullup
  104. * (no value) = analogRead without pullup
  105. * (digital value) = digital write on that pin
  106. * (float value) = analogWrite on that pin
  107. *
  108. **/
  109. void routeAnalog(OSCMessage &msg, int addrOffset ){
  110. //iterate through all the analog pins
  111. for(byte pin = 0; pin < NUM_ANALOG_INPUTS; pin++){
  112. //match against the pin number strings
  113. int pinMatched = msg.match(numToOSCAddress(pin), addrOffset);
  114. if(pinMatched){
  115. //if it has an int, then it's a digital write
  116. if (msg.isInt(0)){
  117. pinMode(analogInputToDigitalPin(pin), OUTPUT);
  118. digitalWrite(analogInputToDigitalPin(pin), (msg.getInt(0) > 0)? HIGH: LOW);
  119. } //otherwise it's an analog read
  120. else if(msg.isFloat(0)){
  121. analogWrite(pin, (int)(msg.getFloat(0)*255.0f));
  122. }
  123. #ifdef BOARD_HAS_ANALOG_PULLUP
  124. //with a pullup?
  125. else if (msg.fullMatch("/u", pinMatched+addrOffset)){
  126. //set the pullup
  127. pinMode(analogInputToDigitalPin(pin), INPUT_PULLUP);
  128. //setup the output address which should be /a/(pin)/u
  129. char outputAddress[9];
  130. strcpy(outputAddress, "/a");
  131. strcat(outputAddress, numToOSCAddress(pin));
  132. strcat(outputAddress,"/u");
  133. //do the analog read and send the results
  134. {
  135. OSCMessage msgOut(outputAddress); msgOut.add((int32_t)analogRead(pin));
  136. SLIPSerial.beginPacket();msgOut.send(SLIPSerial); SLIPSerial.endPacket();
  137. }
  138. } //else without a pullup
  139. #endif
  140. else {
  141. //set the pinmode
  142. // This fails on Arduino 1.04 on Leanardo, I added this to fix it: #define analogInputToDigitalPin(p) (p+18)
  143. pinMode(analogInputToDigitalPin(pin), INPUT);
  144. //setup the output address which should be /a/(pin)
  145. char outputAddress[6];
  146. strcpy(outputAddress, "/a");
  147. strcat(outputAddress, numToOSCAddress(pin));
  148. //do the analog read and send the results
  149. {
  150. OSCMessage msgOut(outputAddress); msgOut.add((int32_t)analogRead(pin));
  151. SLIPSerial.beginPacket(); msgOut.send(SLIPSerial); SLIPSerial.endPacket();
  152. }
  153. }
  154. }
  155. }
  156. }
  157. #ifdef BOARD_HAS_TONE
  158. /**
  159. * TONE
  160. *
  161. * square wave output "/tone"
  162. *
  163. * format:
  164. * /tone/pin
  165. *
  166. * (digital value) (float value) = freqency in Hz
  167. * (no value) disable tone
  168. *
  169. **/
  170. void routeTone(OSCMessage &msg, int addrOffset ){
  171. //iterate through all the analog pins
  172. for(byte pin = 0; pin < NUM_DIGITAL_PINS; pin++){
  173. //match against the pin number strings
  174. int pinMatched = msg.match(numToOSCAddress(pin), addrOffset);
  175. if(pinMatched){
  176. unsigned int frequency = 0;
  177. //if it has an int, then it's an integers frequency in Hz
  178. if (msg.isInt(0)){
  179. frequency = msg.getInt(0);
  180. } //otherwise it's a floating point frequency in Hz
  181. else if(msg.isFloat(0)){
  182. frequency = msg.getFloat(0);
  183. }
  184. else
  185. noTone(pin);
  186. if(frequency>0)
  187. {
  188. if(msg.isInt(1))
  189. tone(pin, frequency, msg.getInt(1));
  190. else
  191. tone(pin, frequency);
  192. }
  193. }
  194. }
  195. }
  196. #endif
  197. #ifdef BOARD_HAS_CAPACITANCE_SENSING
  198. #define NTPINS 12
  199. const int cpins[NTPINS] = {22,23,19,18,17,16,15,0,1,25,32, 33 };
  200. void routeTouch(OSCMessage &msg, int addrOffset )
  201. {
  202. for(int i=0;i<NTPINS;++i)
  203. {
  204. const char *name = numToOSCAddress(cpins[i]);
  205. int pinMatched = msg.match(name, addrOffset);
  206. if(pinMatched)
  207. {
  208. char outputAddress[9];
  209. strcpy(outputAddress, "/c");
  210. strcat(outputAddress, name);
  211. {
  212. OSCMessage msgOut(outputAddress); msgOut.add(touchRead(cpins[i]));
  213. SLIPSerial.beginPacket(); msgOut.send(SLIPSerial); SLIPSerial.endPacket();
  214. }
  215. }
  216. }
  217. }
  218. #endif
  219. #ifdef BOARD_HAS_DIE_POWER_SUPPLY_MEASUREMENT
  220. #if defined(__MK20DX128__)
  221. float getSupplyVoltage()
  222. {
  223. int val = analogRead(39);
  224. return val>0? (1.20f*1023/val):0.0f;
  225. }
  226. #else
  227. // power supply measurement on some Arduinos
  228. float getSupplyVoltage(){
  229. // powersupply
  230. int result;
  231. // Read 1.1V reference against AVcc
  232. #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  233. ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  234. #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  235. ADMUX = _BV(MUX5) | _BV(MUX0);
  236. #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  237. ADMUX = _BV(MUX3) | _BV(MUX2);
  238. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega1280__)
  239. ADMUX = 0x40| _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) ;
  240. ADCSRB = 0;
  241. #else
  242. ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  243. #endif
  244. delayMicroseconds(300); // wait for Vref to settle
  245. ADCSRA |= _BV(ADSC); // Convert
  246. while (bit_is_set(ADCSRA,ADSC));
  247. result = ADCL;
  248. result |= ADCH<<8;
  249. float supplyvoltage = 1.1264f *1023 / result;
  250. return supplyvoltage;
  251. }
  252. #endif
  253. #endif
  254. #ifdef BOARD_HAS_DIE_TEMPERATURE_SENSOR
  255. #if defined(__MK20DX128__)
  256. float getTemperature()
  257. {
  258. analogReference(INTERNAL);
  259. delay(1);
  260. int val = analogRead(38); // seems to be flakey
  261. analogReference(DEFAULT);
  262. return val; //need to compute something here to get to degrees C
  263. }
  264. #else
  265. // temperature
  266. float getTemperature(){
  267. int result;
  268. #if defined(__AVR_ATmega32U4__)
  269. ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0);
  270. ADCSRB = _BV(MUX5);
  271. #else
  272. ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
  273. #endif
  274. delayMicroseconds(200); // wait for Vref to settle
  275. ADCSRA |= _BV(ADSC); // Convert
  276. while (bit_is_set(ADCSRA,ADSC));
  277. result = ADCL;
  278. result |= ADCH<<8;
  279. analogReference(DEFAULT);
  280. return result/1023.0f;
  281. }
  282. #endif
  283. #endif
  284. /**
  285. * SYSTEM MESSAGES
  286. *
  287. * expected format:
  288. * /s
  289. * /m = microseconds
  290. * /d = number of digital pins
  291. * /a = number of analog pins
  292. * /l integer = set the led
  293. * /t = temperature
  294. * /s = power supply voltage
  295. */
  296. //
  297. void routeSystem(OSCMessage &msg, int addrOffset ){
  298. #ifdef BOARD_HAS_DIE_TEMPERATURE_SENSOR
  299. if (msg.fullMatch("/t", addrOffset)){
  300. { OSCMessage msgOut("/s/t"); msgOut.add(getTemperature()); SLIPSerial.beginPacket();msgOut.send(SLIPSerial); SLIPSerial.endPacket(); }
  301. }
  302. #endif
  303. #ifdef BOARD_HAS_DIE_POWER_SUPPLY_MEASUREMENT
  304. if (msg.fullMatch("/s", addrOffset)){
  305. { OSCMessage msgOut("/s/s"); msgOut.add(getSupplyVoltage()); SLIPSerial.beginPacket();msgOut.send(SLIPSerial); SLIPSerial.endPacket(); }
  306. }
  307. #endif
  308. if (msg.fullMatch("/m", addrOffset)){
  309. { OSCMessage msgOut("/s/m"); msgOut.add((int32_t)micros()); SLIPSerial.beginPacket();msgOut.send(SLIPSerial); SLIPSerial.endPacket(); }
  310. }
  311. if (msg.fullMatch("/d", addrOffset)){
  312. { OSCMessage msgOut("/s/d"); msgOut.add(NUM_DIGITAL_PINS); SLIPSerial.beginPacket();msgOut.send(SLIPSerial); SLIPSerial.endPacket(); }
  313. }
  314. if (msg.fullMatch("/a", addrOffset)){
  315. { OSCMessage msgOut("/s/a"); msgOut.add(NUM_ANALOG_INPUTS); SLIPSerial.beginPacket();msgOut.send(SLIPSerial); SLIPSerial.endPacket(); }
  316. }
  317. if (msg.fullMatch("/l", addrOffset)){
  318. if (msg.isInt(0)){
  319. pinMode(LED_BUILTIN, OUTPUT);
  320. int i = msg.getInt(0);
  321. pinMode(LED_BUILTIN, OUTPUT);
  322. digitalWrite(LED_BUILTIN, (i > 0)? HIGH: LOW);
  323. { OSCMessage msgOut("/s/l"); msgOut.add(i); SLIPSerial.beginPacket();msgOut.send(SLIPSerial); SLIPSerial.endPacket(); }
  324. }
  325. }
  326. }
  327. /**
  328. * MAIN METHODS
  329. *
  330. * setup and loop, bundle receiving/sending, initial routing
  331. */
  332. void setup() {
  333. SLIPSerial.begin(9600); // set this as high as you can reliably run on your platform
  334. #if ARDUINO >= 100
  335. while(!Serial)
  336. ; // Leonardo bug
  337. #endif
  338. }
  339. //reads and routes the incoming messages
  340. void loop(){
  341. OSCBundle bundleIN;
  342. int size;
  343. while(!SLIPSerial.endofPacket())
  344. if ((size =SLIPSerial.available()) > 0)
  345. {
  346. while(size--)
  347. bundleIN.fill(SLIPSerial.read());
  348. }
  349. if(!bundleIN.hasError())
  350. {
  351. bundleIN.route("/s", routeSystem);
  352. bundleIN.route("/a", routeAnalog);
  353. bundleIN.route("/d", routeDigital);
  354. #ifdef BOARD_HAS_TONE
  355. bundleIN.route("/tone", routeTone);
  356. #endif
  357. #ifdef BOARD_HAS_CAPACITANCE_SENSING
  358. bundleIN.route("/c", routeTouch);
  359. #endif
  360. }
  361. }