commit 093cb30102089aafdf117c2e957cd1fcc9a4d571
parent 988ef87faf5abe37843d89e09ef5785e4596b2e2
Author: Samdal <samdal@protonmail.com>
Date: Wed, 23 Jun 2021 20:05:36 +0200
code cleanup, added interrupts (with example)
Diffstat:
M | ArduinoNative.hpp | | | 285 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
M | README.org | | | 57 | ++++++++++++++++++++++++++++++++++++++++++++++++++------- |
2 files changed, 199 insertions(+), 143 deletions(-)
diff --git a/ArduinoNative.hpp b/ArduinoNative.hpp
@@ -14,6 +14,7 @@
#include <stdint.h>
#include <string>
#include <thread>
+#include <unordered_map>
/* CONSTANTS */
#define String std::string
@@ -23,14 +24,18 @@ typedef enum {
INPUT,
OUTPUT,
INPUT_PULLUP
-} an_pin_mode;
+} an_pin_mode_t;
typedef enum {
BIN,
OCT,
DEC,
HEX
} an_print_format_t;
-
+typedef enum : uint64_t {
+ CHANGE,
+ RISING,
+ FALLING
+} an_int_mode_t;
#define byte uint8_t
#define word uint16_t
@@ -44,64 +49,69 @@ typedef enum {
#endif
/* BOARD DEFINITIONS */
-
#ifdef AN_BOARD_PRO_MINI
#define AN_BOARD_PRO
#endif
+/* ↓ Arduino PRO / Pro Mini and Arduino NANO ↓ */
#if defined(AN_BOARD_NANO) || defined(AN_BOARD_PRO)
-#define MAX_PINS 21
-
-#define LED_BUILTIN 13
-#define A0 14
-#define A1 15
-#define A2 16
-#define A3 17
-#define A4 18
-#define A5 19
-#define A6 20
-#define A7 21
-
+#define AN_MAX_PINS 21
+
+enum {
+ LED_BUILTIN = 13,
+ A0 = 14,
+ A1 = 15,
+ A2 = 16,
+ A3 = 17,
+ A4 = 18,
+ A5 = 19,
+ A6 = 20,
+ A7 = 21,
+} an_pins;
+
+/* ↑ Arduino PRO / Pro Mini and Arduino NANO ↑ */
#else // Default is Arduino Uno
+/* ↓ Arduino UNO ↓ */
-#define MAX_PINS 19
+#define AN_MAX_PINS 19
-#define LED_BUILTIN 13
-#define A0 14
-#define A1 15
-#define A2 16
-#define A3 17
-#define A4 18
-#define A5 19
+enum {
+ LED_BUILTIN = 13,
+ A0 = 14,
+ A1 = 15,
+ A2 = 16,
+ A3 = 17,
+ A4 = 18,
+ A5 = 19,
+} an_pins;
+/* ↑ Arduino UNO ↑ */
#endif
-uint8_t an_pin_cycle[MAX_PINS] = {0};
-float an_pin_voltage[MAX_PINS] = {0};
+// pin voltages
+float an_pin_voltage[AN_MAX_PINS] = {0};
/* FUNCTION DEFINITIONS */
+// non-arduino functions
+void an_set_voltage(const uint8_t pin, const float voltage);
+
// Digital I/O
-bool digitalRead(uint8_t pin);
-void digitalWrite(uint8_t pin, bool value);
-void pinMode(uint8_t pin, an_pin_mode mode);
+bool digitalRead(const uint8_t pin);
+void digitalWrite(const uint8_t pin, const bool value);
+void pinMode(const uint8_t pin, const an_pin_mode_t mode);
// Analog I/O
-uint16_t analogRead(uint8_t pin);
+uint16_t analogRead(const uint8_t pin);
// void analogReference();
-void analogWrite(uint8_t pin, uint8_t value);
-void an_set_voltage(uint8_t pin, float voltage);
+void analogWrite(const uint8_t pin, const uint8_t value);
// Advanced I/O
-// void noTone(uint8_t pin);
-// unsigned long pulseIn(uint8_t pin, bool value);
-// unsigned long pulseInLong(uint8_t pin, bool value);
-// unsigned long tone(uint8_t pin, unsigned frequenzy);
//Time
-inline void delay(unsigned long milliseconds);
-inline void delayMicroseconds(unsigned long microseconds);
+inline void delay(const unsigned long milliseconds);
+inline void delayMicroseconds(const unsigned long microseconds);
unsigned long micros(void);
unsigned long millis(void);
@@ -111,23 +121,21 @@ unsigned long millis(void);
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define sq(x) (x*x)
-// the rest are included in math.h
-// the same with all of the trigonomitry functions
// Characthers
-inline bool isAlpha(char thisChar);
-inline bool isAlphaNumeric(char thisChar);
-inline bool isAscii(char thisChar);
-inline bool isControl(char thisChar);
-inline bool isDigit(char thisChar);
-inline bool isGraph(char thisChar);
-inline bool isHexadecimalDigit(char thisChar);
-inline bool isLowerCase(char thisChar);
-inline bool isPrintable(char thisChar);
-inline bool isPunct(char thisChar);
-inline bool isSpace(char thisChar);
-inline bool isUpperCase(char thisChar);
-inline bool isWhitespace(char thisChar);
+#define isAlpha(thisChar) (isalpha(thisChar))
+#define isAlphaNumeric(thisChar) (isalnum(thisChar))
+#define isAscii(thisChar) (true)
+#define isControl(thisChar) (iscntrl(thisChar))
+#define isDigit(thisChar) (isdigit(thisChar))
+#define isGraph(thisChar) (isgraph(thisChar))
+#define isHexadecimalDigit(thisChar) (isxdigit(thisChar))
+#define isLowerCase(thisChar) (islower(thisChar))
+#define isPrintable(thisChar) (isprint(thisChar))
+#define isPunct(thisChar) (ispunct(thisChar))
+#define isSpace(thisChar) (isspace(thisChar))
+#define isUpperCase(thisChar) (isupper(thisChar))
+#define isWhitespace(thisChar) (isspace(thisChar))
// Random Numbers
inline long random(long max);
@@ -143,25 +151,39 @@ inline void randomSeed(unsigned long seed);
#define highByte(x) ((uint8_t) ((x) >> 8))
#define lowByte(x) ((uint8_t) ((x) & 0xff))
-// External Interrupts
-
// Interrupts
+#define digitalPinToInterrupt(pin) (pin)
+void attachInterrupt(const uint8_t pin, void (*intpointer), const an_int_mode_t mode);
+void detachInterrupt(const uint8_t pin);
+inline void interrupts(void);
+inline void noInterrupts(void);
// Implimentation
#ifdef AN_IMPL
-// Communication
+unsigned long an_start_time_ms;
+unsigned long an_start_time_µs;
+typedef enum {
+ an_analog,
+ an_digital,
+ an_pwm,
+ an_int_pin,
+} an_pin_types_t;
+typedef struct an_int {
+ void (*intpointer)();
+ an_int_mode_t mode;
+} an_int_t;
+std::unordered_map<uint8_t, an_int_t> an_ints;
+bool an_interrupts_enabled = true;
+
+void setup();
+void loop();
+void an_is_pin_defined(const uint8_t pin, const an_pin_types_t = an_digital);
+
class an_serial
{
-private:
std::string buffer;
public:
- void an_take_input()
- {
- std::cout << "ArduinoNative is requesting Serial input: ";
- std::cin >> buffer;
- }
-
inline size_t available() {return buffer.length();}
inline size_t availableForWrite() {return SIZE_MAX;}
inline void begin(unsigned speed) {}
@@ -169,6 +191,11 @@ public:
inline void end() {}
inline void flush() {}
inline void setTimeout(long new_time) {}
+ void an_take_input()
+ {
+ std::cout << "ArduinoNative is requesting Serial input: ";
+ std::cin >> buffer;
+ }
int peek()
{
std::string buffrev = buffer;
@@ -207,7 +234,6 @@ public:
std::strcpy(readbuffer, buff.str().c_str());
return buff.str().length();
}
- //float parseFloat() {}
template <typename T>
size_t print(T val)
{
@@ -217,7 +243,7 @@ public:
return s.str().length();
}
template <typename T>
- size_t print(T val, an_print_format_t format)
+ size_t print(const T val, an_print_format_t format)
{
std::stringstream s;
switch (format) {
@@ -244,7 +270,7 @@ public:
}}
return 0;
}
- size_t print(float val, uint8_t decimals)
+ size_t print(const float val, const uint8_t decimals)
{
std::cout << std::fixed << std::setprecision(decimals) << val;
std::stringstream s;
@@ -252,20 +278,20 @@ public:
return s.str().length();
}
template <typename T>
- size_t println(T val)
+ size_t println(const T val)
{
size_t byteswritten = this->print(val);
std::cout << "\n";
return byteswritten + 1;
}
template <typename T>
- size_t println(T val, an_print_format_t format)
+ size_t println(const T val, const an_print_format_t format)
{
size_t byteswritten = this->print(val, format);
std::cout << "\n";
return byteswritten + 1;
}
- size_t println(float val, uint8_t format)
+ size_t println(const float val, const uint8_t format)
{
size_t byteswritten = this->print(val, format);
std::cout << "\n";
@@ -274,125 +300,112 @@ public:
size_t println() {std::cout << std::endl; return 1;}
};
-void setup();
-void loop();
-
-unsigned long an_start_time_ms;
-unsigned long an_start_time_µs;
an_serial Serial;
// start program
int main()
{
- // Initialize
an_start_time_ms = millis();
an_start_time_µs = micros();
- // run setup() and loop()
setup();
for (;;) loop();
}
-// Digital I/O
-bool digitalRead(uint8_t pin)
+void an_is_pin_defined(uint8_t pin, an_pin_types_t type)
{
- if (pin > MAX_PINS) {
+ if (pin > AN_MAX_PINS) {
std::cout << "ERROR: PIN " << std::to_string(pin) << " IS NOT DEFINED\n";
exit(1);
}
+}
+
+// Digital I/O
+bool digitalRead(uint8_t pin)
+{
+ bool res = an_pin_voltage[pin] > 3;
#ifdef AN_DEBUG_DIGITALREAD
#ifdef AN_DEBUG_TIMESTAMP
std::cout << millis() << "ms | ";
#endif
- std::cout << "Read pin: " << std::to_string(pin) << " is "
- << (an_pin_voltage[pin] > 3 ? "HIGH" : "LOW") << "\n";
+ std::cout << "Read pin: " << pin << " is " << res ? "HIGH\n" : "LOW\n";
#endif
- return an_pin_voltage[pin] > 3;
+ return res;
}
void digitalWrite(uint8_t pin, bool val)
{
- if (pin > MAX_PINS) {
- std::cout << "ERROR: PIN " << std::to_string(pin) << " IS NOT DEFINED\n";
- exit(1);
- }
- an_pin_cycle[pin] = val * 255;
- an_pin_voltage[pin] = val * 5.0;
+ an_set_voltage(pin, val * 5.0);
#ifdef AN_DEBUG_DIGITALWRITE
#ifdef AN_DEBUG_TIMESTAMP
std::cout << millis() << "ms | ";
#endif
- std::cout << "Pin: " << std::to_string(pin) << " is now "
- << (an_pin_voltage[pin] > 3 ? "HIGH" : "LOW") << "\n";
+ std::cout << "Pin: " << pin << " is now " << val ? "HIGH\n" : "LOW\n";
#endif
}
-void pinMode(uint8_t pin, an_pin_mode mode)
+
+void pinMode(uint8_t pin, an_pin_mode_t mode)
{
- if (pin > MAX_PINS) {
- std::cout << "ERROR: PIN " << std::to_string(pin) << " IS NOT DEFINED\n";
- exit(1);
- }
- if (mode == INPUT_PULLUP) {
+ if (mode == INPUT_PULLUP)
an_pin_voltage[pin] == 5.0;
- an_pin_cycle[pin] == 255;
- }
-
}
// Analog I/O
uint16_t analogRead(uint8_t pin)
{
- if (pin > MAX_PINS) {
- std::cout << "ERROR: PIN " << pin << " IS NOT DEFINED\n";
- exit(1);
- }
+ an_is_pin_defined(pin);
uint16_t val = map(an_pin_voltage[pin], 0.0, 5.0, 0, 1023);
val = constrain(val, 0, 1023);
#ifdef AN_DEBUG_ANALOGREAD
#ifdef AN_DEBUG_TIMESTAMP
std::cout << millis() << "ms | ";
#endif
- std::cout << "Analog pin: " << std::to_string(pin) << " is "
- << std::to_string(val) << "\n";
+ std::cout << "Analog pin: " << pin << " is " << val << "\n";
#endif
return val;
}
void analogWrite(uint8_t pin, uint8_t val)
{
- if (pin > MAX_PINS) {
- std::cout << "ERROR: PIN " << pin << " IS NOT DEFINED\n";
- exit(1);
- }
val = constrain(val, 0, 255);
- an_pin_cycle[pin] = val;
- an_pin_voltage[pin] = map(val, 0, 255, 0.0, 5.0);
+ an_set_voltage(pin, map(val, 0, 255, 0.0, 5.0));
#ifdef AN_DEBUG_ANALOGWRITE
#ifdef AN_DEBUG_TIMESTAMP
std::cout << millis() << "ms | ";
#endif
- std::cout << "Duty cycle on pin: " << std::to_string(pin) << " is now "
- << std::to_string(an_pin_cycle[pin]) << "\n";
+ std::cout << "Duty cycle on pin: " << pin << " is now " << val << "\n";
#endif
}
void an_set_voltage(uint8_t pin, float voltage)
{
- if (pin > MAX_PINS) {
- std::cout << "ERROR: PIN " << std::to_string(pin) << " IS NOT DEFINED\n";
- exit(1);
- }
+ an_is_pin_defined(pin);
+ bool is_on = an_pin_voltage[pin] > 3;
+ bool turn_on = voltage > 3;
+ if (an_interrupts_enabled && an_ints.find(pin) != an_ints.end())
+ switch(an_ints[pin].mode) {
+ case CHANGE:
+ if (is_on != turn_on)
+ an_ints[pin].intpointer();
+ break;
+ case RISING:
+ if (!is_on && turn_on)
+ an_ints[pin].intpointer();
+ break;
+ case FALLING:
+ if (is_on && !turn_on)
+ an_ints[pin].intpointer();
+ break;
+ }
an_pin_voltage[pin] = voltage;
}
void an_request_voltage(uint8_t pin)
{
- if (pin > MAX_PINS) {
- std::cout << "ERROR: PIN " << std::to_string(pin) << " IS NOT DEFINED\n";
- exit(1);
- }
std::cout << "set voltage of pin " << std::to_string(pin) << " to: ";
- std::cin >> an_pin_voltage[pin];
+ float voltage;
+ std::cin >> voltage;
+ an_set_voltage(pin, voltage);
}
// Time
@@ -416,26 +429,26 @@ unsigned long millis()
return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() - an_start_time_ms;
}
-// Characters
-bool isAlpha(char thisChar) {return isalpha(thisChar);}
-bool isAlphaNumeric(char thisChar) {return isalnum(thisChar);}
-bool isAscii(char thisChar) {return true;}
-bool isControl(char thisChar) {return iscntrl(thisChar);}
-bool isDigit(char thisChar) {return isdigit(thisChar);}
-bool isGraph(char thisChar) {return isgraph(thisChar);}
-bool isHexadecimalDigit(char thisChar) {return isxdigit(thisChar);}
-bool isLowerCase(char thisChar) {return islower(thisChar);}
-bool isPrintable(char thisChar) {return isprint(thisChar);}
-bool isPunct(char thisChar) {return ispunct(thisChar);}
-bool isSpace(char thisChar) {return isspace(thisChar);}
-bool isUpperCase(char thisChar) {return isupper(thisChar);}
-bool isWhitespace(char thisChar) {return isspace(thisChar);}
-
// Random Numbers
long random(long max) {return rand() % max;}
long random(long min, long max) {return min + rand() % (max - min);}
void randomSeed(long seed) {srand(seed);}
+// External Interrupts
+void attachInterrupt(uint8_t pin, void (*intpointer)(), an_int_mode_t mode)
+{
+ an_is_pin_defined(pin, an_int_pin);
+ an_ints[pin] = (an_int_t){.intpointer = intpointer, .mode = mode,};
+}
+void detachInterrupt(const uint8_t pin)
+{
+ auto int_pos = an_ints.find(pin);
+ if (int_pos != an_ints.end())
+ an_ints.erase(int_pos);
+}
+void interrupts() {an_interrupts_enabled = true;}
+void noInterrupts() {an_interrupts_enabled = false;}
+
#undef AN_IMPL
#endif // AN_IMPL
diff --git a/README.org b/README.org
@@ -101,12 +101,12 @@ Note that less important functions haven't been tested that much.
+ [X] bitWrite()
+ [X] highByte()
+ [X] lowByte()
-- [ ] External Interrupts
- + [ ] attachInterrupt()
- + [ ] detachInterrupt()
-- [ ] Interrupts
- + [ ] interrupts()
- + [ ] noInterrupts()
+- [X] External Interrupts
+ + [X] attachInterrupt()
+ + [X] detachInterrupt()
+- [X] Interrupts
+ + [X] interrupts()
+ + [X] noInterrupts()
- [-] Serial
+ [X] available()
+ [X] availableForWrite()
@@ -222,7 +222,7 @@ l
l
o
#+END_SRC
-** millis()
+** millis() and specific debug modes
#+BEGIN_SRC C++
#define AN_DEBUG_DIGITALWRITE
#define AN_DEBUG_TIMESTAMP
@@ -273,3 +273,46 @@ Output:
4000ms | Pin: 5 is now LOW
4000ms | Pin: 6 is now LOW
#+END_SRC
+** Interrupts
+HIGH and LOW interrupt modes don't work, only CHANGE, RISING and FALLING
+#+BEGIN_SRC C++
+#define AN_IMPL
+#include "ArduinoNative.hpp"
+
+unsigned long switchdelay;
+unsigned short count;
+
+void interrupt()
+{
+ Serial.print("INTERRUPT");
+ Serial.println(count);
+}
+
+void setup() {
+ Serial.begin(9600);
+ attachInterrupt(digitalPinToInterrupt(2), interrupt, CHANGE);
+}
+
+// count 5 times, each time toggling pin 2
+// after 5 times detach interrupt
+void loop() {
+ unsigned long t = millis();
+ if (t - switchdelay >= 1000) {
+#ifdef ArduinoNative
+ an_set_voltage(2, !digitalRead(2) * 5.0);
+#endif
+ switchdelay = t;
+ count++;
+ if (count == 5)
+ detachInterrupt(digitalPinToInterrupt(2));
+ }
+}
+#+END_SRC
+Output:
+#+BEGIN_SRC
+INTERRUPT0
+INTERRUPT1
+INTERRUPT2
+INTERRUPT3
+INTERRUPT4
+#+END_SRC