ArduinoNative

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

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