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.

403 lines
10KB

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