ArduinoNative.hpp (25038B)
1 #ifndef ArduinoNative 2 #define ArduinoNative 3 4 #include <algorithm> 5 #include <bitset> 6 #include <cstring> 7 #include <ctype.h> 8 #include <cmath> 9 #include <chrono> 10 #include <iostream> 11 #include <stdio.h> 12 #include <iomanip> 13 #include <sstream> 14 #include <string> 15 #include <thread> 16 #include <unordered_map> 17 18 /* CONSTANTS */ 19 #define LOW 0 20 #define HIGH 1 21 #define MSBFIRST 0 22 #define LSBFIRST 1 23 typedef enum { 24 INPUT, 25 OUTPUT, 26 INPUT_PULLUP 27 } an_pin_mode_t; 28 typedef enum { 29 BIN, 30 OCT, 31 DEC, 32 HEX 33 } an_num_fmt_t; 34 typedef enum : uint64_t { 35 CHANGE, 36 RISING, 37 FALLING 38 } an_int_mode_t; 39 typedef enum { 40 SKIP_NONE, 41 SKIP_WHITESPACE, 42 SKIP_ALL, 43 } LookaheadMode; 44 typedef enum { 45 DEFAULT, 46 INTERNAL, 47 INTERNAL1V1, 48 INTERNAL2V56, 49 EXTERNAL, 50 } an_reference_t; 51 #define byte uint8_t 52 #define word uint16_t 53 54 /* DEBUG MESSAGES */ 55 #ifdef AN_DEBUG_ALL 56 #define AN_DEBUG_DIGITALREAD 57 #define AN_DEBUG_DIGITALWRITE 58 #define AN_DEBUG_ANALOGREAD 59 #define AN_DEBUG_ANALOGWRITE 60 #endif 61 62 /* BOARD DEFINITIONS */ 63 #ifdef AN_BOARD_PRO_MINI 64 #define AN_BOARD_PRO 65 #endif 66 67 /* ↓ Arduino PRO / Pro Mini and Arduino NANO ↓ */ 68 #if defined(AN_BOARD_NANO) || defined(AN_BOARD_PRO) 69 70 #define AN_MAX_PINS 21 71 72 enum { 73 LED_BUILTIN = 13, 74 A0 = 14, 75 A1 = 15, 76 A2 = 16, 77 A3 = 17, 78 A4 = 18, 79 A5 = 19, 80 A6 = 20, 81 A7 = 21, 82 }; 83 84 /* ↑ Arduino PRO / Pro Mini and Arduino NANO ↑ */ 85 #else // Default is Arduino Uno 86 /* ↓ Arduino UNO ↓ */ 87 88 #define AN_MAX_PINS 19 89 90 enum { 91 LED_BUILTIN = 13, 92 A0 = 14, 93 A1 = 15, 94 A2 = 16, 95 A3 = 17, 96 A4 = 18, 97 A5 = 19, 98 }; 99 100 /* ↑ Arduino UNO ↑ */ 101 #endif 102 103 #define AREF 255 104 float an_pin_voltage[AN_MAX_PINS] = {0}; 105 106 107 /* FUNCTION DEFINITIONS */ 108 109 // non-arduino functions 110 void an_set_voltage(const uint8_t pin, const float voltage); 111 void an_request_voltage(const uint8_t pin); 112 inline void an_print_timestamp(); 113 void an_attach_sine(const uint8_t pin, const unsigned hz = 1, const float amp = 2.5, const float dc = 2.5, const bool abs = false); 114 void an_remove_sine(const uint8_t pin); 115 void an_attach_square(const uint8_t pin, const unsigned hz = 1, const float duty = 0.5); 116 void an_remove_square(const uint8_t pin); 117 118 // Digital I/O 119 bool digitalRead(const uint8_t pin); 120 void digitalWrite(const uint8_t pin, const bool value); 121 void pinMode(const uint8_t pin, const an_pin_mode_t mode); 122 123 // Analog I/O 124 uint16_t analogRead(const uint8_t pin); 125 void analogReference(an_reference_t type); 126 void analogWrite(const uint8_t pin, const uint8_t value); 127 128 // Advanced I/O 129 void noTone(const uint8_t pin); 130 unsigned long pulseIn(const uint8_t pin, const bool val, const unsigned long timeout); 131 unsigned long pulseInLong(const uint8_t pin, const bool val, const unsigned long timeout); 132 uint8_t shiftIn(const uint8_t data_pin, const uint8_t clock_pin, const bool bit_order); 133 void shiftOut(const uint8_t data_pin, const uint8_t clock_pin, const bool bit_order, const byte value); 134 void tone(const uint8_t pin, unsigned hz, unsigned long dur = 0); 135 136 //Time 137 inline void delay(const unsigned long milliseconds); 138 inline void delayMicroseconds(const unsigned long microseconds); 139 unsigned long micros(void); 140 unsigned long millis(void); 141 142 // Math 143 #define constrain(x, a, b) ({x = x < a ? a : x; x = x > b ? b : x;}) 144 #define map(x, fL, fH, tL, tH) ((x - fL) * (tH - tL) / (fH - fL) + tL) 145 #define min(a,b) ((a)<(b)?(a):(b)) 146 #define max(a,b) ((a)>(b)?(a):(b)) 147 #define sq(x) ((x)*(x)) 148 #define PI 3.14159265 149 150 // Characthers 151 #define isAlpha(thisChar) (isalpha(thisChar)) 152 #define isAlphaNumeric(thisChar) (isalnum(thisChar)) 153 #define isAscii(thisChar) (true) 154 #define isControl(thisChar) (iscntrl(thisChar)) 155 #define isDigit(thisChar) (isdigit(thisChar)) 156 #define isGraph(thisChar) (isgraph(thisChar)) 157 #define isHexadecimalDigit(thisChar) (isxdigit(thisChar)) 158 #define isLowerCase(thisChar) (islower(thisChar)) 159 #define isPrintable(thisChar) (isprint(thisChar)) 160 #define isPunct(thisChar) (ispunct(thisChar)) 161 #define isSpace(thisChar) (isspace(thisChar)) 162 #define isUpperCase(thisChar) (isupper(thisChar)) 163 #define isWhitespace(thisChar) (isspace(thisChar)) 164 165 // Random Numbers 166 inline long random(long max); 167 inline long random(long min, long max); 168 inline void randomSeed(unsigned long seed); 169 170 // Bits and Bytes 171 #define bit(b) (1UL << (b)) 172 #define bitRead(value, bit) (((value) >> (bit)) & 0x01) 173 #define bitSet(value, bit) ((value) |= (1UL << (bit))) 174 #define bitClear(value, bit) ((value) &= ~(1UL << (bit))) 175 #define bitToggle(value, bit) ((value) ^= (1UL << (bit))) 176 #define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit)) 177 #define highByte(w) ((uint8_t) ((w) >> 8)) 178 #define lowByte(w) ((uint8_t) ((w) & 0xff)) 179 180 // Interrupts 181 #define digitalPinToInterrupt(pin) (pin) 182 void attachInterrupt(const uint8_t pin, void(*intpointer)(void), const an_int_mode_t mode); 183 void detachInterrupt(const uint8_t pin); 184 inline void interrupts(void); 185 inline void noInterrupts(void); 186 187 class String : public std::string { 188 public: 189 String() {}; 190 template<typename T> 191 String(const T val) 192 { 193 std::stringstream s; 194 s << val; 195 append(s.str()); 196 } 197 template <typename T> 198 String(const T val, const an_num_fmt_t fmt) 199 { 200 std::stringstream s = {}; 201 switch (fmt) { 202 case BIN: { 203 std::bitset<sizeof(val) * 8> bits(val); 204 s << bits; 205 append(s.str()); 206 return; 207 } case DEC: { 208 break; 209 } case HEX: { 210 s << std::hex; 211 break; 212 } case OCT: { 213 s << std::oct; 214 break; 215 }} 216 s << (long)val; 217 append(s.str()); 218 } 219 String(const char* buff, const an_num_fmt_t fmt) 220 { 221 for (unsigned int i = 0; i < strlen(buff); i++) 222 append(String((uint8_t)buff[i], fmt)); 223 } 224 String(const double val, const uint8_t decimals) 225 { 226 std::stringstream s; 227 s << std::fixed << std::setprecision(decimals) << val; 228 append(s.str()); 229 } 230 inline float toFloat() {return std::stof(c_str());} 231 inline int toInt() {return (int)toFloat();} 232 inline double toDouble() {return std::atof(c_str());} 233 234 inline void getBytes(byte* buf, unsigned len) {strncpy((char*)buf, substr(0, len).c_str(), len);} 235 inline void toCharArray(unsigned char* buf, const unsigned len) {getBytes((byte*)buf, len); buf[len] = '\0';} 236 inline String substring(size_t pos = 0, size_t len = npos) {return substr(pos, len);} 237 inline void toLowerCase() 238 { 239 std::transform(begin(), end(), begin(), 240 [](char c){return std::tolower(c);}); 241 } 242 inline void toUpperCase() 243 { 244 std::transform(begin(), end(), begin(), 245 [](char c){return std::toupper(c);}); 246 } 247 inline char charAt(const unsigned int n) {return at(n);} 248 inline int compareTo(const String str2) {return compare(str2);} 249 template <typename T> 250 inline bool concat(const T val) {append(String(val)); return true;} 251 inline bool startsWith(const String substr) {return rfind(substr, 0) == 0;} 252 inline bool endsWith(const String str) {return compare(length() - str.length(), str.length(), str) == 0;} 253 inline bool equals(const String str2) {return compare(str2) == 0;} 254 bool equalsIgnoreCase(const String str2) 255 { 256 String strlwr = String(c_str()); 257 String str2lwr = String(str2.c_str()); 258 strlwr.toLowerCase(); 259 str2lwr.toLowerCase(); 260 return strlwr.compare(str2lwr) == 0; 261 } 262 inline size_t indexOf(const char* val, const size_t from = 0) {return find(val, from);} 263 inline size_t lastIndexOf(const char* val, const size_t from = 0) {return rfind(val, from);} 264 inline void remove(const size_t index, const size_t count = 1) {erase(index, count);} 265 void replace(const String from, const String to) 266 { 267 size_t start_pos = 0; 268 while ((start_pos = find(from, start_pos)) != npos) { 269 std::string::replace(start_pos, from.length(), to); 270 start_pos += to.length(); 271 } 272 } 273 inline void setCharAt(const size_t index, const char c) {at(index) = c;} 274 void trim() 275 { 276 erase(begin(), std::find_if(begin(), end(), [](char ch) { 277 return !std::isspace(ch); 278 })); 279 erase(std::find_if(rbegin(), rend(), [](char ch) { 280 return !std::isspace(ch); 281 }).base(), end()); 282 } 283 }; 284 285 286 // Implimentation 287 #ifdef AN_IMPL 288 289 unsigned long an_start_time_ms; 290 unsigned long an_start_time_µs; 291 typedef enum { 292 an_analog, 293 an_digital, 294 an_pwm, 295 an_int_pin, 296 } an_pin_types_t; 297 typedef struct an_int { 298 void (*intpointer)(void); 299 an_int_mode_t mode; 300 } an_int_t; 301 std::unordered_map<uint8_t, an_int_t> an_ints; 302 std::unordered_map<uint8_t, std::thread> an_sines; 303 std::unordered_map<uint8_t, bool> an_sines_terminate; 304 std::unordered_map<uint8_t, std::thread> an_squares; 305 std::unordered_map<uint8_t, bool> an_squares_terminate; 306 bool an_interrupts_enabled = true; 307 float an_reference_v = 5.0; 308 309 void setup(void); 310 void loop(void); 311 void an_is_pin_defined(const uint8_t pin, const an_pin_types_t = an_digital); 312 #ifndef _WIN32 313 void serialEvent() __attribute__((weak)); 314 #endif 315 316 class an_serial 317 { 318 private: 319 String buffer; 320 inline bool skip_alpha(LookaheadMode lookahead, bool is_float, char ignore) 321 { 322 while(available()) { 323 char c = peek(); 324 if (c == ignore){ 325 buffer.erase(buffer.begin()); 326 continue; 327 } 328 if ((c == '-') || (c >= '0' && c <= '9') || 329 (is_float && c == '.')) 330 return true; 331 switch (lookahead) { 332 case SKIP_ALL: 333 buffer.erase(buffer.begin()); 334 break; 335 case SKIP_NONE: 336 case SKIP_WHITESPACE: 337 return true; 338 } 339 } 340 return false; 341 } 342 inline void remove_digit(bool is_float) 343 { 344 while(available()) { 345 char c = peek(); 346 if ((c == '-') || (c >= '0' && c <= '9') || 347 (is_float && c == '.')) 348 buffer.erase(buffer.begin()); 349 else 350 return; 351 } 352 } 353 public: 354 inline size_t available() {return buffer.length();} 355 inline size_t availableForWrite() {return SIZE_MAX;} 356 inline void begin(unsigned speed) {} 357 inline void begin(unsigned speed, int config) {} 358 inline void end() {} 359 inline void flush() {std::cout << std::flush;} 360 inline void setTimeout(const long new_time) {} 361 inline String readString() {String str = buffer; buffer.clear(); return str;} 362 inline String readStringUntil(const char terminator) 363 { 364 size_t t_pos = buffer.find(terminator); 365 if (t_pos == std::string::npos) 366 return readString(); 367 368 std::string str = buffer; 369 buffer.erase(0, t_pos); 370 str.erase(str.begin() + t_pos, str.end()); 371 return str; 372 } 373 void an_take_input() 374 { 375 std::cout << "ArduinoNative is requesting Serial input: "; 376 std::cin >> buffer; 377 #ifndef _WIN32 378 if (serialEvent) 379 serialEvent(); 380 #endif 381 } 382 uint8_t peek() {return buffer.length() > 0 ? uint8_t(buffer.c_str()[0]) : 0;} 383 inline uint8_t read() 384 { 385 uint8_t read_byte = peek(); 386 buffer.erase(buffer.begin()); 387 return read_byte; 388 } 389 size_t readBytes(byte* buffer, const unsigned length, const bool is_until = false, const char terminator = '\0') 390 { 391 size_t count = 0; 392 for(; count < length; count++) { 393 uint8_t c = read(); 394 if (c < 0 || (is_until && c == terminator)) 395 break; 396 *buffer++ = c; 397 } 398 return count; 399 } 400 inline size_t readBytesUntil(const char terminator, byte* buffer, const unsigned length) 401 { 402 return readBytes(buffer, length, true, terminator); 403 } 404 bool find(const char* target, const size_t len = 1) 405 { 406 size_t t_pos = buffer.find(target); 407 if (t_pos == std::string::npos) { 408 buffer.clear(); 409 return false; 410 } 411 buffer.erase(0, t_pos); 412 return true; 413 } 414 bool findUntil(const char* target, const char* terminal) 415 { 416 bool res = find(target); 417 if (res) 418 find(terminal); 419 return res; 420 } 421 int parseInt(const LookaheadMode lookahead = SKIP_ALL, const char ignore = '\n') 422 { 423 if (!skip_alpha(lookahead, false, ignore)) 424 return 0; 425 int res = buffer.toInt(); 426 remove_digit(false); 427 return res; 428 } 429 float parseFloat(const LookaheadMode lookahead = SKIP_ALL, const char ignore = '\n') 430 { 431 if (!skip_alpha(lookahead, true, ignore)) 432 return 0.0f; 433 float res = buffer.toFloat(); 434 remove_digit(true); 435 return res; 436 } 437 template <typename T> inline size_t print(const T val) 438 { 439 String s = val; 440 std::cout << s; 441 return s.length(); 442 } 443 template <typename V, typename F> 444 inline size_t print(const V val, const F fmt) {return print(String(val, fmt));} 445 446 template <typename T> 447 inline size_t write(const T val) {return print(val, HEX) / 2;} 448 449 template <typename V, typename F> 450 inline size_t println(const V val, const F fmt) {return print(val, fmt) + println();} 451 template <typename T> 452 inline size_t println(const T val) {return print(val) + println();} 453 inline size_t println() {std::cout << "\n"; return 1;} 454 }; 455 456 an_serial Serial; 457 458 // start program 459 int main() 460 { 461 an_start_time_ms = millis(); 462 an_start_time_µs = micros(); 463 464 setup(); 465 for (;;) loop(); 466 } 467 468 /* ArduinoNative reused functions */ 469 void an_is_pin_defined(uint8_t pin, an_pin_types_t type) 470 { 471 if (pin > AN_MAX_PINS && pin != AREF) { 472 std::cout << "ERROR: PIN " << std::to_string(pin) << " IS NOT DEFINED\n"; 473 exit(1); 474 } 475 } 476 void an_print_timestamp() 477 { 478 #ifdef AN_DEBUG_TIMESTAMP 479 std::cout << millis() << "ms | "; 480 #endif 481 } 482 483 // Digital I/O 484 bool digitalRead(uint8_t pin) 485 { 486 bool res = an_pin_voltage[pin] > 3; 487 #ifdef AN_DEBUG_DIGITALREAD 488 an_print_timestamp(); 489 std::cout << "Read pin: " << std::to_string(pin) << " is " << (res ? "HIGH\n" : "LOW\n"); 490 #endif 491 return res; 492 } 493 494 void digitalWrite(uint8_t pin, bool val) 495 { 496 an_set_voltage(pin, val * 5.0f); 497 #ifdef AN_DEBUG_DIGITALWRITE 498 an_print_timestamp(); 499 std::cout << "Pin: " << std::to_string(pin) << " is now " << (val ? "HIGH\n" : "LOW\n"); 500 #endif 501 } 502 503 void pinMode(uint8_t pin, an_pin_mode_t mode) 504 { 505 if (mode == INPUT_PULLUP) 506 an_pin_voltage[pin] = 5.0f; 507 } 508 509 // Analog I/O 510 uint16_t analogRead(uint8_t pin) 511 { 512 an_is_pin_defined(pin); 513 uint16_t val = (uint16_t)lround(map(an_pin_voltage[pin], 0.0f, an_reference_v, 0, 1023)); 514 val = constrain(val, 0, 1023); 515 #ifdef AN_DEBUG_ANALOGREAD 516 an_print_timestamp(); 517 std::cout << "Analog pin: " << std::to_string(pin) << " is " << val << "\n"; 518 #endif 519 return val; 520 } 521 522 void analogWrite(uint8_t pin, uint8_t val) 523 { 524 val = constrain(val, 0, 255); 525 an_set_voltage(pin, map(val, 0, 255, 0.0f, 5.0f)); 526 #ifdef AN_DEBUG_ANALOGWRITE 527 an_print_timestamp(); 528 std::cout << "Duty cycle on pin: " << std::to_string(pin) << " is now " << val << "\n"; 529 #endif 530 } 531 532 void analogReference(an_reference_t type) 533 { 534 switch(type) { 535 case DEFAULT: 536 an_reference_v = 5.0; 537 break; 538 case INTERNAL: 539 an_reference_v = 1.1; 540 break; 541 case INTERNAL1V1: 542 an_reference_v = 1.1; 543 break; 544 case INTERNAL2V56: 545 an_reference_v = 2.56; 546 break; 547 case EXTERNAL: 548 break; 549 } 550 } 551 552 void an_set_voltage(uint8_t pin, float voltage) 553 { 554 an_is_pin_defined(pin); 555 bool is_on = an_pin_voltage[pin] > 3; 556 bool turn_on = voltage > 3; 557 if (pin == AREF) { 558 an_reference_v = voltage; 559 return; 560 } 561 562 563 /* If pin has interrupt attached */ 564 if (an_interrupts_enabled && an_ints.find(pin) != an_ints.end()) 565 switch(an_ints[pin].mode) { 566 case CHANGE: 567 if (is_on != turn_on) 568 an_ints[pin].intpointer(); 569 break; 570 case RISING: 571 if (!is_on && turn_on) 572 an_ints[pin].intpointer(); 573 break; 574 case FALLING: 575 if (is_on && !turn_on) 576 an_ints[pin].intpointer(); 577 break; 578 } 579 580 an_pin_voltage[pin] = voltage; 581 } 582 583 void an_request_voltage(uint8_t pin) 584 { 585 std::cout << "set voltage of pin " << std::to_string(pin) << " to: "; 586 float voltage; 587 std::cin >> voltage; 588 an_set_voltage(pin, voltage); 589 } 590 591 // Time 592 void delay(unsigned long ms) 593 { 594 std::this_thread::sleep_for(std::chrono::milliseconds(ms)); 595 } 596 void delayMicroseconds(unsigned long µs) 597 { 598 std::this_thread::sleep_for(std::chrono::microseconds(µs)); 599 } 600 601 unsigned long micros() 602 { 603 auto duration = std::chrono::system_clock::now().time_since_epoch(); 604 return (unsigned long)std::chrono::duration_cast<std::chrono::microseconds>(duration).count() - an_start_time_µs; 605 } 606 unsigned long millis() 607 { 608 auto duration = std::chrono::system_clock::now().time_since_epoch(); 609 return (unsigned long)std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() - an_start_time_ms; 610 } 611 612 // Random Numbers 613 long random(long max) {return rand() % max;} 614 long random(long min, long max) {return min + rand() % (max - min);} 615 void randomSeed(long seed) {srand(seed);} 616 617 // External Interrupts 618 void attachInterrupt(uint8_t pin, void (*intpointer)(), an_int_mode_t mode) 619 { 620 detachInterrupt(pin); 621 an_ints[pin] = {intpointer, mode}; 622 } 623 void detachInterrupt(const uint8_t pin) 624 { 625 an_is_pin_defined(pin, an_int_pin); 626 auto int_pos = an_ints.find(pin); 627 if (int_pos != an_ints.end()) 628 an_ints.erase(int_pos); 629 } 630 void interrupts() {an_interrupts_enabled = true;} 631 void noInterrupts() {an_interrupts_enabled = false;} 632 633 // Advanced I/O 634 inline void noTone(const uint8_t pin) 635 { 636 an_is_pin_defined(pin); 637 #ifndef _WIN32 638 system("killall \"ffplay\" -q"); 639 #endif 640 } 641 unsigned long pulseIn(const uint8_t pin, const bool val, const unsigned long timeout) 642 { 643 an_is_pin_defined(pin); 644 while (digitalRead(pin) != val); 645 unsigned long before = micros(); 646 while (digitalRead(pin) == val && (!timeout && micros() - before >= timeout)); 647 unsigned long after = micros(); 648 return after - before; 649 } 650 inline unsigned long pulseInLong(const uint8_t pin, const bool val, const unsigned long timeout) 651 { 652 return pulseIn(pin, val, timeout); 653 } 654 uint8_t shiftIn(const uint8_t data_pin, const uint8_t clock_pin, const uint8_t bit_order) 655 { 656 an_is_pin_defined(data_pin); 657 an_is_pin_defined(clock_pin); 658 659 uint8_t value = 0; 660 uint8_t i; 661 662 for (i = 0; i < 8; ++i) { 663 digitalWrite(clock_pin, HIGH); 664 if (bit_order == LSBFIRST) 665 value |= digitalRead(data_pin) << i; 666 else 667 value |= digitalRead(data_pin) << (7 - i); 668 digitalWrite(clock_pin, LOW); 669 } 670 return value; 671 } 672 void shiftOut(const uint8_t data_pin, const uint8_t clock_pin, const bool bit_order, byte val) 673 { 674 an_is_pin_defined(data_pin); 675 an_is_pin_defined(clock_pin); 676 677 uint8_t i; 678 679 for (i = 0; i < 8; i++) { 680 if (bit_order == LSBFIRST) { 681 digitalWrite(data_pin, val & 1); 682 val >>= 1; 683 } else { 684 digitalWrite(data_pin, (val & 128) != 0); 685 val <<= 1; 686 } 687 688 digitalWrite(clock_pin, HIGH); 689 digitalWrite(clock_pin, LOW); 690 } 691 } 692 void tone(const uint8_t pin, unsigned hz, unsigned long dur) 693 { 694 noTone(pin); 695 #ifndef _WIN32 696 hz = constrain(hz, 0, 20000); 697 char ffplay[70]; 698 snprintf(ffplay, sizeof(ffplay), "ffplay -f lavfi -i \"sine=frequency=%d\" -nodisp -loglevel quiet &", hz); 699 system(ffplay); 700 #endif 701 } 702 void an_play_sine(const uint8_t pin, const unsigned hz, const float amp, const float dc) 703 { 704 for (;;) { 705 if (an_sines_terminate[pin]) 706 return; 707 an_set_voltage(pin, sin(((float)millis() / (1000.0f / (2.0f * PI))) * hz) * amp + dc); 708 } 709 } 710 void an_play_sine_abs(const uint8_t pin, const unsigned hz, const float amp, const float dc) 711 { 712 for (;;) { 713 if (an_sines_terminate[pin]) 714 return; 715 an_set_voltage(pin, fabs(sin(((float)millis() / (1000.0f / (2.0f * PI))) * hz) * amp + dc)); 716 } 717 } 718 719 void an_attach_sine(const uint8_t pin, const unsigned hz, const float amp, const float dc, const bool is_abs) 720 { 721 an_remove_sine(pin); 722 an_sines_terminate[pin] = false; 723 if (is_abs) { 724 std::thread sine(an_play_sine_abs, pin, hz, amp, dc); 725 an_sines[pin] = move(sine); 726 } else { 727 std::thread sine(an_play_sine, pin, hz, amp, dc); 728 an_sines[pin] = move(sine); 729 } 730 } 731 void an_remove_sine(const uint8_t pin) 732 { 733 an_is_pin_defined(pin); 734 auto sine_pos = an_sines.find(pin); 735 if (sine_pos != an_sines.end()) { 736 an_sines_terminate[pin] = true; 737 an_sines[pin].join(); 738 an_sines.erase(sine_pos); 739 } 740 } 741 742 void an_play_square(const uint8_t pin, const unsigned hz, const float duty) 743 { 744 bool top = true; 745 for (;;) { 746 if (an_sines_terminate[pin]) 747 return; 748 float sine = sin((millis() / (1000.0f / (2.0f * PI))) * hz); 749 float triangle = 1.0f-acos(sine)/PI; 750 751 float new_top = triangle <= duty; 752 if (new_top != top) { 753 an_set_voltage(pin, new_top * 5.0f); 754 top = new_top; 755 } 756 } 757 } 758 759 void an_attach_square(const uint8_t pin, const unsigned hz, const float duty) 760 { 761 an_remove_square(pin); 762 an_squares_terminate[pin] = false; 763 std::thread square(an_play_square, pin, hz, duty); 764 an_squares[pin] = move(square); 765 } 766 void an_remove_square(const uint8_t pin) 767 { 768 an_is_pin_defined(pin); 769 auto square_pos = an_squares.find(pin); 770 if (square_pos != an_squares.end()) { 771 an_squares_terminate[pin] = true; 772 an_squares[pin].join(); 773 an_squares.erase(square_pos); 774 } 775 } 776 #undef AN_IMPL 777 #endif // AN_IMPL 778 779 #endif // ArduinoNative