Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // The sketch is auto-generated with XOD (https://xod.io).
- //
- // You can compile and upload it to an Arduino-compatible board with
- // Arduino IDE.
- //
- // Rough code overview:
- //
- // - Configuration section
- // - STL shim
- // - Immutable list classes and functions
- // - XOD runtime environment
- // - Native node implementation
- // - Program graph definition
- //
- // Search for comments fenced with '====' and '----' to navigate through
- // the major code blocks.
- #include <Arduino.h>
- #include <inttypes.h>
- /*=============================================================================
- *
- *
- * Configuration
- *
- *
- =============================================================================*/
- // Uncomment to turn on debug of the program
- //#define XOD_DEBUG
- // Uncomment to trace the program runtime in the Serial Monitor
- //#define XOD_DEBUG_ENABLE_TRACE
- // Uncomment to make possible simulation of the program
- //#define XOD_SIMULATION
- #ifdef XOD_SIMULATION
- #include <WasmSerial.h>
- #define XOD_DEBUG_SERIAL WasmSerial
- #else
- #define XOD_DEBUG_SERIAL DEBUG_SERIAL
- #endif
- /*=============================================================================
- *
- *
- * STL shim. Provides implementation for vital std::* constructs
- *
- *
- =============================================================================*/
- namespace xod {
- namespace std {
- template< class T > struct remove_reference {typedef T type;};
- template< class T > struct remove_reference<T&> {typedef T type;};
- template< class T > struct remove_reference<T&&> {typedef T type;};
- template <class T>
- typename remove_reference<T>::type&& move(T&& a) {
- return static_cast<typename remove_reference<T>::type&&>(a);
- }
- } // namespace std
- } // namespace xod
- /*=============================================================================
- *
- *
- * Basic XOD types
- *
- *
- =============================================================================*/
- namespace xod {
- #if __SIZEOF_FLOAT__ == 4
- typedef float Number;
- #else
- typedef double Number;
- #endif
- typedef bool Logic;
- typedef unsigned long TimeMs;
- typedef uint8_t ErrorFlags;
- struct Pulse {
- Pulse() {}
- Pulse(bool) {}
- Pulse(int) {}
- };
- struct XColor {
- uint8_t r, g, b;
- };
- } // namespace xod
- /*=============================================================================
- *
- *
- * XOD-specific list/array implementations
- *
- *
- =============================================================================*/
- #ifndef XOD_LIST_H
- #define XOD_LIST_H
- namespace xod {
- namespace detail {
- /*
- * Cursors are used internaly by iterators and list views. They are not exposed
- * directly to a list consumer.
- *
- * The base `Cursor` is an interface which provides the bare minimum of methods
- * to facilitate a single iteration pass.
- */
- template<typename T> class Cursor {
- public:
- virtual ~Cursor() { }
- virtual bool isValid() const = 0;
- virtual bool value(T* out) const = 0;
- virtual void next() = 0;
- };
- template<typename T> class NilCursor : public Cursor<T> {
- public:
- virtual bool isValid() const { return false; }
- virtual bool value(T*) const { return false; }
- virtual void next() { }
- };
- } // namespace detail
- /*
- * Iterator is an object used to iterate a list once.
- *
- * Users create new iterators by calling `someList.iterate()`.
- * Iterators are created on stack and are supposed to have a
- * short live, e.g. for a duration of `for` loop or node’s
- * `evaluate` function. Iterators can’t be copied.
- *
- * Implemented as a pimpl pattern wrapper over the cursor.
- * Once created for a cursor, an iterator owns that cursor
- * and will delete the cursor object once destroyed itself.
- */
- template<typename T>
- class Iterator {
- public:
- static Iterator<T> nil() {
- return Iterator<T>(new detail::NilCursor<T>());
- }
- Iterator(detail::Cursor<T>* cursor)
- : _cursor(cursor)
- { }
- ~Iterator() {
- if (_cursor)
- delete _cursor;
- }
- Iterator(const Iterator& that) = delete;
- Iterator& operator=(const Iterator& that) = delete;
- Iterator(Iterator&& it)
- : _cursor(it._cursor)
- {
- it._cursor = nullptr;
- }
- Iterator& operator=(Iterator&& it) {
- auto tmp = it._cursor;
- it._cursor = _cursor;
- _cursor = tmp;
- return *this;
- }
- operator bool() const { return _cursor->isValid(); }
- bool value(T* out) const {
- return _cursor->value(out);
- }
- T operator*() const {
- T out;
- _cursor->value(&out);
- return out;
- }
- Iterator& operator++() {
- _cursor->next();
- return *this;
- }
- private:
- detail::Cursor<T>* _cursor;
- };
- /*
- * An interface for a list view. A particular list view provides a new
- * kind of iteration over existing data. This way we can use list slices,
- * list concatenations, list rotations, etc without introducing new data
- * buffers. We just change the way already existing data is iterated.
- *
- * ListView is not exposed to a list user directly, it is used internally
- * by the List class. However, deriving a new ListView is necessary if you
- * make a new list/string processing node.
- */
- template<typename T> class ListView {
- public:
- virtual Iterator<T> iterate() const = 0;
- };
- /*
- * The list as it seen by data consumers. Have a single method `iterate`
- * to create a new iterator.
- *
- * Implemented as pimpl pattern wrapper over a list view. Takes pointer
- * to a list view in constructor and expects the view will be alive for
- * the whole life time of the list.
- */
- template<typename T> class List {
- public:
- constexpr List()
- : _view(nullptr)
- { }
- List(const ListView<T>* view)
- : _view(view)
- { }
- Iterator<T> iterate() const {
- return _view ? _view->iterate() : Iterator<T>::nil();
- }
- // pre 0.15.0 backward compatibility
- List* operator->() __attribute__ ((deprecated)) { return this; }
- const List* operator->() const __attribute__ ((deprecated)) { return this; }
- private:
- const ListView<T>* _view;
- };
- /*
- * A list view over an old good plain C array.
- *
- * Expects the array will be alive for the whole life time of the
- * view.
- */
- template<typename T> class PlainListView : public ListView<T> {
- public:
- class Cursor : public detail::Cursor<T> {
- public:
- Cursor(const PlainListView* owner)
- : _owner(owner)
- , _idx(0)
- { }
- bool isValid() const override {
- return _idx < _owner->_len;
- }
- bool value(T* out) const override {
- if (!isValid())
- return false;
- *out = _owner->_data[_idx];
- return true;
- }
- void next() override { ++_idx; }
- private:
- const PlainListView* _owner;
- size_t _idx;
- };
- public:
- PlainListView(const T* data, size_t len)
- : _data(data)
- , _len(len)
- { }
- virtual Iterator<T> iterate() const override {
- return Iterator<T>(new Cursor(this));
- }
- private:
- friend class Cursor;
- const T* _data;
- size_t _len;
- };
- /*
- * A list view over a null-terminated C-String.
- *
- * Expects the char buffer will be alive for the whole life time of the view.
- * You can use string literals as a buffer, since they are persistent for
- * the program execution time.
- */
- class CStringView : public ListView<char> {
- public:
- class Cursor : public detail::Cursor<char> {
- public:
- Cursor(const char* str)
- : _ptr(str)
- { }
- bool isValid() const override {
- return (bool)*_ptr;
- }
- bool value(char* out) const override {
- *out = *_ptr;
- return (bool)*_ptr;
- }
- void next() override { ++_ptr; }
- private:
- const char* _ptr;
- };
- public:
- CStringView(const char* str = nullptr)
- : _str(str)
- { }
- CStringView& operator=(const CStringView& rhs) {
- _str = rhs._str;
- return *this;
- }
- virtual Iterator<char> iterate() const override {
- return _str ? Iterator<char>(new Cursor(_str)) : Iterator<char>::nil();
- }
- private:
- friend class Cursor;
- const char* _str;
- };
- /*
- * A list view over two other lists (Left and Right) which first iterates the
- * left one, and when exhausted, iterates the right one.
- *
- * Expects both Left and Right to be alive for the whole view life time.
- */
- template<typename T> class ConcatListView : public ListView<T> {
- public:
- class Cursor : public detail::Cursor<T> {
- public:
- Cursor(Iterator<T>&& left, Iterator<T>&& right)
- : _left(std::move(left))
- , _right(std::move(right))
- { }
- bool isValid() const override {
- return _left || _right;
- }
- bool value(T* out) const override {
- return _left.value(out) || _right.value(out);
- }
- void next() override {
- _left ? ++_left : ++_right;
- }
- private:
- Iterator<T> _left;
- Iterator<T> _right;
- };
- public:
- ConcatListView() { }
- ConcatListView(List<T> left, List<T> right)
- : _left(left)
- , _right(right)
- { }
- ConcatListView& operator=(const ConcatListView& rhs) {
- _left = rhs._left;
- _right = rhs._right;
- return *this;
- }
- virtual Iterator<T> iterate() const override {
- return Iterator<T>(new Cursor(_left.iterate(), _right.iterate()));
- }
- private:
- friend class Cursor;
- List<T> _left;
- List<T> _right;
- };
- //----------------------------------------------------------------------------
- // Text string helpers
- //----------------------------------------------------------------------------
- using XString = List<char>;
- /*
- * List and list view in a single pack. An utility used to define constant
- * string literals in XOD.
- */
- class XStringCString : public XString {
- public:
- XStringCString(const char* str)
- : XString(&_view)
- , _view(str)
- { }
- private:
- CStringView _view;
- };
- } // namespace xod
- #endif
- /*=============================================================================
- *
- *
- * Functions to work with memory
- *
- *
- =============================================================================*/
- // Define the placement new operator for cores that do not provide their own.
- // Note, this definition takes precedence over the existing one (if any). We found no C++ way
- // to use the existing implementation _and_ this implementation if not yet defined.
- template<typename T>
- void* operator new(size_t, T* ptr) noexcept {
- return ptr;
- }
- /*=============================================================================
- *
- *
- * UART Classes, that wraps Serials
- *
- *
- =============================================================================*/
- class HardwareSerial;
- class SoftwareSerial;
- namespace xod {
- class Uart {
- private:
- long _baud;
- protected:
- bool _started = false;
- public:
- Uart(long baud) {
- _baud = baud;
- }
- virtual void begin() = 0;
- virtual void end() = 0;
- virtual void flush() = 0;
- virtual bool available() = 0;
- virtual bool writeByte(uint8_t) = 0;
- virtual bool readByte(uint8_t*) = 0;
- virtual SoftwareSerial* toSoftwareSerial() {
- return nullptr;
- }
- virtual HardwareSerial* toHardwareSerial() {
- return nullptr;
- }
- void changeBaudRate(long baud) {
- _baud = baud;
- if (_started) {
- end();
- begin();
- }
- }
- long getBaudRate() const {
- return _baud;
- }
- Stream* toStream() {
- Stream* stream = (Stream*) toHardwareSerial();
- if (stream) return stream;
- return (Stream*) toSoftwareSerial();
- }
- };
- class HardwareUart : public Uart {
- private:
- HardwareSerial* _serial;
- public:
- HardwareUart(HardwareSerial& hserial, uint32_t baud = 115200) : Uart(baud) {
- _serial = &hserial;
- }
- void begin();
- void end();
- void flush();
- bool available() {
- return (bool) _serial->available();
- }
- bool writeByte(uint8_t byte) {
- return (bool) _serial->write(byte);
- }
- bool readByte(uint8_t* out) {
- int data = _serial->read();
- if (data == -1) return false;
- *out = data;
- return true;
- }
- HardwareSerial* toHardwareSerial() {
- return _serial;
- }
- };
- void HardwareUart::begin() {
- _started = true;
- _serial->begin(getBaudRate());
- };
- void HardwareUart::end() {
- _started = false;
- _serial->end();
- };
- void HardwareUart::flush() {
- _serial->flush();
- };
- } // namespace xod
- /*=============================================================================
- *
- *
- * Basic algorithms for XOD lists
- *
- *
- =============================================================================*/
- #ifndef XOD_LIST_FUNCS_H
- #define XOD_LIST_FUNCS_H
- namespace xod {
- /*
- * Folds a list from left. Also known as "reduce".
- */
- template<typename T, typename TR>
- TR foldl(List<T> xs, TR (*func)(TR, T), TR acc) {
- for (auto it = xs.iterate(); it; ++it)
- acc = func(acc, *it);
- return acc;
- }
- template<typename T> size_t lengthReducer(size_t len, T) {
- return len + 1;
- }
- /*
- * Computes length of a list.
- */
- template<typename T> size_t length(List<T> xs) {
- return foldl(xs, lengthReducer<T>, (size_t)0);
- }
- template<typename T> T* dumpReducer(T* buff, T x) {
- *buff = x;
- return buff + 1;
- }
- /*
- * Copies a list content into a memory buffer.
- *
- * It is expected that `outBuff` has enough size to fit all the data.
- */
- template<typename T> size_t dump(List<T> xs, T* outBuff) {
- T* buffEnd = foldl(xs, dumpReducer, outBuff);
- return buffEnd - outBuff;
- }
- /*
- * Compares two lists.
- */
- template<typename T> bool equal(List<T> lhs, List<T> rhs) {
- auto lhsIt = lhs.iterate();
- auto rhsIt = rhs.iterate();
- for (; lhsIt && rhsIt; ++lhsIt, ++rhsIt) {
- if (*lhsIt != *rhsIt) return false;
- }
- return !lhsIt && !rhsIt;
- }
- template<typename T> bool operator == (List<T> lhs, List<T> rhs) {
- return equal(lhs, rhs);
- }
- } // namespace xod
- #endif
- /*=============================================================================
- *
- *
- * Format Numbers
- *
- *
- =============================================================================*/
- /**
- * Provide `formatNumber` cross-platform number to string converter function.
- *
- * Taken from here:
- * https://github.com/client9/stringencoders/blob/master/src/modp_numtoa.c
- * Original function name: `modp_dtoa2`.
- *
- * Modified:
- * - `isnan` instead of tricky comparing and return "NaN"
- * - handle Infinity values and return "Inf" or "-Inf"
- * - return `OVF` and `-OVF` for numbers bigger than max possible, instead of using `sprintf`
- * - use `Number` instead of double
- * - if negative number rounds to zero, return just "0" instead of "-0"
- *
- * This is a replacement of `dtostrf`.
- */
- #ifndef XOD_FORMAT_NUMBER_H
- #define XOD_FORMAT_NUMBER_H
- namespace xod {
- /**
- * Powers of 10
- * 10^0 to 10^9
- */
- static const Number powers_of_10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
- 10000000, 100000000, 1000000000 };
- static void strreverse(char* begin, char* end) {
- char aux;
- while (end > begin)
- aux = *end, *end-- = *begin, *begin++ = aux;
- };
- size_t formatNumber(Number value, int prec, char* str) {
- if (isnan(value)) {
- strcpy(str, "NaN");
- return (size_t)3;
- }
- if (isinf(value)) {
- bool isNegative = value < 0;
- strcpy(str, isNegative ? "-Inf" : "Inf");
- return (size_t)isNegative ? 4 : 3;
- }
- /* if input is larger than thres_max return "OVF" */
- const Number thres_max = (Number)(0x7FFFFFFF);
- Number diff = 0.0;
- char* wstr = str;
- if (prec < 0) {
- prec = 0;
- } else if (prec > 9) {
- /* precision of >= 10 can lead to overflow errors */
- prec = 9;
- }
- /* we'll work in positive values and deal with the
- negative sign issue later */
- int neg = 0;
- if (value < 0) {
- neg = 1;
- value = -value;
- }
- uint32_t whole = (uint32_t)value;
- Number tmp = (value - whole) * powers_of_10[prec];
- uint32_t frac = (uint32_t)(tmp);
- diff = tmp - frac;
- if (diff > 0.5) {
- ++frac;
- /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */
- if (frac >= powers_of_10[prec]) {
- frac = 0;
- ++whole;
- }
- } else if (diff == 0.5 && prec > 0 && (frac & 1)) {
- /* if halfway, round up if odd, OR
- if last digit is 0. That last part is strange */
- ++frac;
- if (frac >= powers_of_10[prec]) {
- frac = 0;
- ++whole;
- }
- } else if (diff == 0.5 && prec == 0 && (whole & 1)) {
- ++frac;
- if (frac >= powers_of_10[prec]) {
- frac = 0;
- ++whole;
- }
- }
- if (value > thres_max) {
- if (neg) {
- strcpy(str, "-OVF");
- return (size_t)4;
- }
- strcpy(str, "OVF");
- return (size_t)3;
- }
- int has_decimal = 0;
- int count = prec;
- bool notzero = frac > 0;
- while (count > 0) {
- --count;
- *wstr++ = (char)(48 + (frac % 10));
- frac /= 10;
- has_decimal = 1;
- }
- if (frac > 0) {
- ++whole;
- }
- /* add decimal */
- if (has_decimal) {
- *wstr++ = '.';
- }
- notzero = notzero || whole > 0;
- /* do whole part
- * Take care of sign conversion
- * Number is reversed.
- */
- do
- *wstr++ = (char)(48 + (whole % 10));
- while (whole /= 10);
- if (neg && notzero) {
- *wstr++ = '-';
- }
- *wstr = '\0';
- strreverse(str, wstr - 1);
- return (size_t)(wstr - str);
- }
- } // namespace xod
- #endif
- /*=============================================================================
- *
- *
- * Runtime
- *
- *
- =============================================================================*/
- //----------------------------------------------------------------------------
- // Debug routines
- //----------------------------------------------------------------------------
- // #ifndef DEBUG_SERIAL
- #if defined(XOD_DEBUG) && !defined(DEBUG_SERIAL)
- # define DEBUG_SERIAL Serial
- #endif
- #if defined(XOD_DEBUG) && defined(XOD_DEBUG_ENABLE_TRACE)
- # define XOD_TRACE(x) { DEBUG_SERIAL.print(x); DEBUG_SERIAL.flush(); }
- # define XOD_TRACE_LN(x) { DEBUG_SERIAL.println(x); DEBUG_SERIAL.flush(); }
- # define XOD_TRACE_F(x) XOD_TRACE(F(x))
- # define XOD_TRACE_FLN(x) XOD_TRACE_LN(F(x))
- #else
- # define XOD_TRACE(x)
- # define XOD_TRACE_LN(x)
- # define XOD_TRACE_F(x)
- # define XOD_TRACE_FLN(x)
- #endif
- //----------------------------------------------------------------------------
- // PGM space utilities
- //----------------------------------------------------------------------------
- #define pgm_read_nodeid(address) (pgm_read_word(address))
- /*
- * Workaround for bugs:
- * https://github.com/arduino/ArduinoCore-sam/pull/43
- * https://github.com/arduino/ArduinoCore-samd/pull/253
- * Remove after the PRs merge
- */
- #if !defined(ARDUINO_ARCH_AVR) && defined(pgm_read_ptr)
- # undef pgm_read_ptr
- # define pgm_read_ptr(addr) (*(const void **)(addr))
- #endif
- namespace xod {
- //----------------------------------------------------------------------------
- // Global variables
- //----------------------------------------------------------------------------
- TimeMs g_transactionTime;
- bool g_isSettingUp;
- bool g_isEarlyDeferPass;
- //----------------------------------------------------------------------------
- // Metaprogramming utilities
- //----------------------------------------------------------------------------
- template<typename T> struct always_false {
- enum { value = 0 };
- };
- //----------------------------------------------------------------------------
- // Forward declarations
- //----------------------------------------------------------------------------
- TimeMs transactionTime();
- void runTransaction();
- //----------------------------------------------------------------------------
- // Engine (private API)
- //----------------------------------------------------------------------------
- namespace detail {
- template<typename NodeT>
- bool isTimedOut(const NodeT* node) {
- TimeMs t = node->timeoutAt;
- // TODO: deal with uint32 overflow
- return t && t < transactionTime();
- }
- template<typename NodeT>
- void clearTimeout(NodeT* node) {
- node->timeoutAt = 0;
- }
- template<typename NodeT>
- void clearStaleTimeout(NodeT* node) {
- if (isTimedOut(node))
- clearTimeout(node);
- }
- void printErrorToDebugSerial(uint16_t nodeId, ErrorFlags errorFlags) {
- #if defined(XOD_DEBUG) || defined(XOD_SIMULATION)
- XOD_DEBUG_SERIAL.print(F("+XOD_ERR:"));
- XOD_DEBUG_SERIAL.print(g_transactionTime);
- XOD_DEBUG_SERIAL.print(':');
- XOD_DEBUG_SERIAL.print(nodeId);
- XOD_DEBUG_SERIAL.print(':');
- XOD_DEBUG_SERIAL.print(errorFlags, DEC);
- XOD_DEBUG_SERIAL.print('\r');
- XOD_DEBUG_SERIAL.print('\n');
- #endif
- }
- } // namespace detail
- //----------------------------------------------------------------------------
- // Public API (can be used by native nodes’ `evaluate` functions)
- //----------------------------------------------------------------------------
- TimeMs transactionTime() {
- return g_transactionTime;
- }
- bool isSettingUp() {
- return g_isSettingUp;
- }
- bool isEarlyDeferPass() {
- return g_isEarlyDeferPass;
- }
- template<typename ContextT>
- void setTimeout(ContextT* ctx, TimeMs timeout) {
- ctx->_node->timeoutAt = transactionTime() + timeout;
- }
- template<typename ContextT>
- void clearTimeout(ContextT* ctx) {
- detail::clearTimeout(ctx->_node);
- }
- template<typename ContextT>
- bool isTimedOut(const ContextT* ctx) {
- return detail::isTimedOut(ctx->_node);
- }
- bool isValidDigitalPort(uint8_t port) {
- #if defined(__AVR__) && defined(NUM_DIGITAL_PINS)
- return port < NUM_DIGITAL_PINS;
- #else
- return true;
- #endif
- }
- bool isValidAnalogPort(uint8_t port) {
- #if defined(__AVR__) && defined(NUM_ANALOG_INPUTS)
- return port >= A0 && port < A0 + NUM_ANALOG_INPUTS;
- #else
- return true;
- #endif
- }
- } // namespace xod
- //----------------------------------------------------------------------------
- // Entry point
- //----------------------------------------------------------------------------
- void setup() {
- // FIXME: looks like there is a rounding bug. Waiting for 100ms fights it
- delay(100);
- #if defined(XOD_DEBUG) || defined(XOD_SIMULATION)
- XOD_DEBUG_SERIAL.begin(115200);
- XOD_DEBUG_SERIAL.setTimeout(10);
- #endif
- XOD_TRACE_FLN("\n\nProgram started");
- xod::g_isSettingUp = true;
- xod::runTransaction();
- xod::g_isSettingUp = false;
- }
- void loop() {
- xod::runTransaction();
- }
- /*=============================================================================
- *
- *
- * Native node implementations
- *
- *
- =============================================================================*/
- namespace xod {
- //-----------------------------------------------------------------------------
- // xod-dev/servo/servo-device implementation
- //-----------------------------------------------------------------------------
- namespace xod_dev__servo__servo_device {
- //#pragma XOD error_raise enable
- // --- Enter global namespace ---
- }}
- #include <Servo.h>
- namespace xod {
- namespace xod_dev__servo__servo_device {
- // --- Back to local namespace ---
- /*
- A wrapper around the stock Servo object because we need to keep some details
- which the original object hides in private fields. This over-protection leads
- to increased RAM usage to duplicate the data. A pull request to the original
- library asking to add field read methods would be nice.
- */
- class XServo : public Servo {
- protected:
- // Here are the duplicates
- uint8_t port;
- int pulseMin;
- int pulseMax;
- public:
- // Set pulse duration according the given `value` and set pulseMin, pulseMax
- // The value is clipped to the [0; 1] range
- void write01(Number value) {
- ensureAttached();
- int pseudoAngle = constrain((int)(value * 180), 0, 180);
- this->write(pseudoAngle);
- }
- // Performs Servo::attach with the parameters set previously
- void ensureAttached() {
- if (this->attached())
- return;
- this->attach(port, pulseMin, pulseMax);
- }
- Number read01() {
- int us = this->readMicroseconds();
- return (Number)(us - pulseMin) / (Number)(pulseMax - pulseMin);
- }
- void reattach(uint8_t port, int pulseMin, int pulseMax) {
- this->port = port;
- this->pulseMin = pulseMin;
- this->pulseMax = pulseMax;
- if (this->attached())
- this->attach(port, pulseMin, pulseMax);
- }
- };
- using State = XServo;
- using Type = XServo*;
- union NodeErrors {
- struct {
- bool output_DEV : 1;
- };
- ErrorFlags flags;
- };
- struct Node {
- NodeErrors errors;
- xod_dev__servo__servo_device::Type output_DEV;
- State state;
- };
- struct input_PORT { };
- struct input_Pmin { };
- struct input_Pmax { };
- struct output_DEV { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_PORT> { using T = uint8_t; };
- template<> struct ValueType<input_Pmin> { using T = Number; };
- template<> struct ValueType<input_Pmax> { using T = Number; };
- template<> struct ValueType<output_DEV> { using T = xod_dev__servo__servo_device::Type; };
- struct ContextObject {
- Node* _node;
- uint8_t _input_PORT;
- Number _input_Pmin;
- Number _input_Pmax;
- bool _isOutputDirty_DEV : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_PORT input_Pmin input_Pmax" \
- " output_DEV");
- }
- template<> uint8_t getValue<input_PORT>(Context ctx) {
- return ctx->_input_PORT;
- }
- template<> Number getValue<input_Pmin>(Context ctx) {
- return ctx->_input_Pmin;
- }
- template<> Number getValue<input_Pmax>(Context ctx) {
- return ctx->_input_Pmax;
- }
- template<> xod_dev__servo__servo_device::Type getValue<output_DEV>(Context ctx) {
- return ctx->_node->output_DEV;
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_DEV");
- }
- template<> void emitValue<output_DEV>(Context ctx, xod_dev__servo__servo_device::Type val) {
- ctx->_node->output_DEV = val;
- ctx->_isOutputDirty_DEV = true;
- ctx->_node->errors.output_DEV = false;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- template<typename OutputT> void raiseError(Context ctx) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_DEV");
- }
- template<> void raiseError<output_DEV>(Context ctx) {
- ctx->_node->errors.output_DEV = true;
- ctx->_isOutputDirty_DEV = true;
- }
- void raiseError(Context ctx) {
- ctx->_node->errors.output_DEV = true;
- ctx->_isOutputDirty_DEV = true;
- }
- void evaluate(Context ctx) {
- State* servo = getState(ctx);
- auto port = getValue<input_PORT>(ctx);
- if (!isValidDigitalPort(port)) {
- raiseError(ctx);
- return;
- }
- servo->reattach(
- port,
- getValue<input_Pmin>(ctx),
- getValue<input_Pmax>(ctx)
- );
- emitValue<output_DEV>(ctx, servo);
- }
- } // namespace xod_dev__servo__servo_device
- //-----------------------------------------------------------------------------
- // xod/core/continuously implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__continuously {
- struct State {
- };
- struct Node {
- TimeMs timeoutAt;
- State state;
- };
- struct output_TICK { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<output_TICK> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- bool _isOutputDirty_TICK : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- "" \
- " output_TICK");
- }
- template<> Pulse getValue<output_TICK>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_TICK");
- }
- template<> void emitValue<output_TICK>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_TICK = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- emitValue<output_TICK>(ctx, 1);
- setTimeout(ctx, 0);
- }
- } // namespace xod__core__continuously
- //-----------------------------------------------------------------------------
- // xod/core/boot implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__boot {
- struct State {
- };
- struct Node {
- State state;
- };
- struct output_BOOT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<output_BOOT> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- bool _isOutputDirty_BOOT : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- "" \
- " output_BOOT");
- }
- template<> Pulse getValue<output_BOOT>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_BOOT");
- }
- template<> void emitValue<output_BOOT>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_BOOT = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- emitValue<output_BOOT>(ctx, 1);
- }
- } // namespace xod__core__boot
- //-----------------------------------------------------------------------------
- // xod/core/pulse-on-change(number) implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__pulse_on_change__number {
- struct State {
- Number sample = NAN;
- };
- struct Node {
- State state;
- };
- struct input_IN { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_IN> { using T = Number; };
- template<> struct ValueType<output_OUT> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- Number _input_IN;
- bool _isOutputDirty_OUT : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_IN" \
- " output_OUT");
- }
- template<> Number getValue<input_IN>(Context ctx) {
- return ctx->_input_IN;
- }
- template<> Pulse getValue<output_OUT>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_OUT = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- State* state = getState(ctx);
- auto newValue = getValue<input_IN>(ctx);
- if (!isSettingUp() && newValue != state->sample)
- emitValue<output_OUT>(ctx, 1);
- state->sample = newValue;
- }
- } // namespace xod__core__pulse_on_change__number
- //-----------------------------------------------------------------------------
- // xod/core/cast-to-pulse(boolean) implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__cast_to_pulse__boolean {
- struct State {
- bool state = false;
- };
- struct Node {
- State state;
- };
- struct input_IN { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_IN> { using T = Logic; };
- template<> struct ValueType<output_OUT> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- Logic _input_IN;
- bool _isOutputDirty_OUT : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_IN" \
- " output_OUT");
- }
- template<> Logic getValue<input_IN>(Context ctx) {
- return ctx->_input_IN;
- }
- template<> Pulse getValue<output_OUT>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_OUT = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- State* state = getState(ctx);
- auto newValue = getValue<input_IN>(ctx);
- if (newValue == true && state->state == false)
- emitValue<output_OUT>(ctx, 1);
- state->state = newValue;
- }
- } // namespace xod__core__cast_to_pulse__boolean
- //-----------------------------------------------------------------------------
- // xod/gpio/digital-read-pullup implementation
- //-----------------------------------------------------------------------------
- namespace xod__gpio__digital_read_pullup {
- //#pragma XOD evaluate_on_pin disable
- //#pragma XOD evaluate_on_pin enable input_UPD
- //#pragma XOD error_raise enable
- struct State {
- };
- union NodeErrors {
- struct {
- bool output_SIG : 1;
- bool output_DONE : 1;
- };
- ErrorFlags flags;
- };
- struct Node {
- NodeErrors errors;
- Logic output_SIG;
- State state;
- };
- struct input_PORT { };
- struct input_UPD { };
- struct output_SIG { };
- struct output_DONE { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_PORT> { using T = uint8_t; };
- template<> struct ValueType<input_UPD> { using T = Pulse; };
- template<> struct ValueType<output_SIG> { using T = Logic; };
- template<> struct ValueType<output_DONE> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- uint8_t _input_PORT;
- bool _isInputDirty_UPD;
- bool _isOutputDirty_SIG : 1;
- bool _isOutputDirty_DONE : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_PORT input_UPD" \
- " output_SIG output_DONE");
- }
- template<> uint8_t getValue<input_PORT>(Context ctx) {
- return ctx->_input_PORT;
- }
- template<> Pulse getValue<input_UPD>(Context ctx) {
- return Pulse();
- }
- template<> Logic getValue<output_SIG>(Context ctx) {
- return ctx->_node->output_SIG;
- }
- template<> Pulse getValue<output_DONE>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- " input_UPD");
- return false;
- }
- template<> bool isInputDirty<input_UPD>(Context ctx) {
- return ctx->_isInputDirty_UPD;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_SIG output_DONE");
- }
- template<> void emitValue<output_SIG>(Context ctx, Logic val) {
- ctx->_node->output_SIG = val;
- ctx->_isOutputDirty_SIG = true;
- ctx->_node->errors.output_SIG = false;
- }
- template<> void emitValue<output_DONE>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_DONE = true;
- ctx->_node->errors.output_DONE = false;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- template<typename OutputT> void raiseError(Context ctx) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_SIG output_DONE");
- }
- template<> void raiseError<output_SIG>(Context ctx) {
- ctx->_node->errors.output_SIG = true;
- ctx->_isOutputDirty_SIG = true;
- }
- template<> void raiseError<output_DONE>(Context ctx) {
- ctx->_node->errors.output_DONE = true;
- ctx->_isOutputDirty_DONE = true;
- }
- void raiseError(Context ctx) {
- ctx->_node->errors.output_SIG = true;
- ctx->_isOutputDirty_SIG = true;
- ctx->_node->errors.output_DONE = true;
- ctx->_isOutputDirty_DONE = true;
- }
- void evaluate(Context ctx) {
- if (!isInputDirty<input_UPD>(ctx))
- return;
- const uint8_t port = getValue<input_PORT>(ctx);
- if (!isValidDigitalPort(port)) {
- raiseError(ctx);
- return;
- }
- ::pinMode(port, INPUT_PULLUP);
- emitValue<output_SIG>(ctx, ::digitalRead(port));
- emitValue<output_DONE>(ctx, 1);
- }
- } // namespace xod__gpio__digital_read_pullup
- //-----------------------------------------------------------------------------
- // xod/gpio/analog-read implementation
- //-----------------------------------------------------------------------------
- namespace xod__gpio__analog_read {
- //#pragma XOD evaluate_on_pin disable
- //#pragma XOD evaluate_on_pin enable input_UPD
- //#pragma XOD error_raise enable
- struct State {
- };
- union NodeErrors {
- struct {
- bool output_VAL : 1;
- bool output_DONE : 1;
- };
- ErrorFlags flags;
- };
- struct Node {
- NodeErrors errors;
- Number output_VAL;
- State state;
- };
- struct input_PORT { };
- struct input_UPD { };
- struct output_VAL { };
- struct output_DONE { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_PORT> { using T = uint8_t; };
- template<> struct ValueType<input_UPD> { using T = Pulse; };
- template<> struct ValueType<output_VAL> { using T = Number; };
- template<> struct ValueType<output_DONE> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- uint8_t _input_PORT;
- bool _isInputDirty_UPD;
- bool _isOutputDirty_VAL : 1;
- bool _isOutputDirty_DONE : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_PORT input_UPD" \
- " output_VAL output_DONE");
- }
- template<> uint8_t getValue<input_PORT>(Context ctx) {
- return ctx->_input_PORT;
- }
- template<> Pulse getValue<input_UPD>(Context ctx) {
- return Pulse();
- }
- template<> Number getValue<output_VAL>(Context ctx) {
- return ctx->_node->output_VAL;
- }
- template<> Pulse getValue<output_DONE>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- " input_UPD");
- return false;
- }
- template<> bool isInputDirty<input_UPD>(Context ctx) {
- return ctx->_isInputDirty_UPD;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_VAL output_DONE");
- }
- template<> void emitValue<output_VAL>(Context ctx, Number val) {
- ctx->_node->output_VAL = val;
- ctx->_isOutputDirty_VAL = true;
- ctx->_node->errors.output_VAL = false;
- }
- template<> void emitValue<output_DONE>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_DONE = true;
- ctx->_node->errors.output_DONE = false;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- template<typename OutputT> void raiseError(Context ctx) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_VAL output_DONE");
- }
- template<> void raiseError<output_VAL>(Context ctx) {
- ctx->_node->errors.output_VAL = true;
- ctx->_isOutputDirty_VAL = true;
- }
- template<> void raiseError<output_DONE>(Context ctx) {
- ctx->_node->errors.output_DONE = true;
- ctx->_isOutputDirty_DONE = true;
- }
- void raiseError(Context ctx) {
- ctx->_node->errors.output_VAL = true;
- ctx->_isOutputDirty_VAL = true;
- ctx->_node->errors.output_DONE = true;
- ctx->_isOutputDirty_DONE = true;
- }
- void evaluate(Context ctx) {
- if (!isInputDirty<input_UPD>(ctx))
- return;
- const uint8_t port = getValue<input_PORT>(ctx);
- if (!isValidAnalogPort(port)) {
- raiseError(ctx);
- return;
- }
- ::pinMode(port, INPUT);
- emitValue<output_VAL>(ctx, ::analogRead(port) / 1023.);
- emitValue<output_DONE>(ctx, 1);
- }
- } // namespace xod__gpio__analog_read
- //-----------------------------------------------------------------------------
- // xod/core/any implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__any {
- struct State {
- };
- struct Node {
- State state;
- };
- struct input_IN1 { };
- struct input_IN2 { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_IN1> { using T = Pulse; };
- template<> struct ValueType<input_IN2> { using T = Pulse; };
- template<> struct ValueType<output_OUT> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- bool _isInputDirty_IN1;
- bool _isInputDirty_IN2;
- bool _isOutputDirty_OUT : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_IN1 input_IN2" \
- " output_OUT");
- }
- template<> Pulse getValue<input_IN1>(Context ctx) {
- return Pulse();
- }
- template<> Pulse getValue<input_IN2>(Context ctx) {
- return Pulse();
- }
- template<> Pulse getValue<output_OUT>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- " input_IN1 input_IN2");
- return false;
- }
- template<> bool isInputDirty<input_IN1>(Context ctx) {
- return ctx->_isInputDirty_IN1;
- }
- template<> bool isInputDirty<input_IN2>(Context ctx) {
- return ctx->_isInputDirty_IN2;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_OUT = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- bool p1 = isInputDirty<input_IN1>(ctx);
- bool p2 = isInputDirty<input_IN2>(ctx);
- if (p1 || p2)
- emitValue<output_OUT>(ctx, true);
- }
- } // namespace xod__core__any
- //-----------------------------------------------------------------------------
- // xod/core/not implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__not {
- //#pragma XOD dirtieness disable
- struct State {
- };
- struct Node {
- Logic output_OUT;
- State state;
- };
- struct input_IN { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_IN> { using T = Logic; };
- template<> struct ValueType<output_OUT> { using T = Logic; };
- struct ContextObject {
- Node* _node;
- Logic _input_IN;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_IN" \
- " output_OUT");
- }
- template<> Logic getValue<input_IN>(Context ctx) {
- return ctx->_input_IN;
- }
- template<> Logic getValue<output_OUT>(Context ctx) {
- return ctx->_node->output_OUT;
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Logic val) {
- ctx->_node->output_OUT = val;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- auto x = getValue<input_IN>(ctx);
- emitValue<output_OUT>(ctx, !x);
- }
- } // namespace xod__core__not
- //-----------------------------------------------------------------------------
- // xod/math/map implementation
- //-----------------------------------------------------------------------------
- namespace xod__math__map {
- //#pragma XOD dirtieness disable
- struct State {
- };
- struct Node {
- Number output_OUT;
- State state;
- };
- struct input_X { };
- struct input_Smin { };
- struct input_Smax { };
- struct input_Tmin { };
- struct input_Tmax { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_X> { using T = Number; };
- template<> struct ValueType<input_Smin> { using T = Number; };
- template<> struct ValueType<input_Smax> { using T = Number; };
- template<> struct ValueType<input_Tmin> { using T = Number; };
- template<> struct ValueType<input_Tmax> { using T = Number; };
- template<> struct ValueType<output_OUT> { using T = Number; };
- struct ContextObject {
- Node* _node;
- Number _input_X;
- Number _input_Smin;
- Number _input_Smax;
- Number _input_Tmin;
- Number _input_Tmax;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_X input_Smin input_Smax input_Tmin input_Tmax" \
- " output_OUT");
- }
- template<> Number getValue<input_X>(Context ctx) {
- return ctx->_input_X;
- }
- template<> Number getValue<input_Smin>(Context ctx) {
- return ctx->_input_Smin;
- }
- template<> Number getValue<input_Smax>(Context ctx) {
- return ctx->_input_Smax;
- }
- template<> Number getValue<input_Tmin>(Context ctx) {
- return ctx->_input_Tmin;
- }
- template<> Number getValue<input_Tmax>(Context ctx) {
- return ctx->_input_Tmax;
- }
- template<> Number getValue<output_OUT>(Context ctx) {
- return ctx->_node->output_OUT;
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Number val) {
- ctx->_node->output_OUT = val;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- auto x = getValue<input_X>(ctx);
- auto sMin = getValue<input_Smin>(ctx);
- auto sMax = getValue<input_Smax>(ctx);
- auto tMin = getValue<input_Tmin>(ctx);
- auto tMax = getValue<input_Tmax>(ctx);
- auto k = (x - sMin) / (sMax - sMin);
- auto xm = isnan(x) ? x : tMin + k * (tMax - tMin);
- emitValue<output_OUT>(ctx, xm);
- }
- } // namespace xod__math__map
- //-----------------------------------------------------------------------------
- // xod/core/debounce(boolean) implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__debounce__boolean {
- struct State {
- bool state = false;
- };
- struct Node {
- TimeMs timeoutAt;
- Logic output_OUT;
- State state;
- };
- struct input_ST { };
- struct input_Ts { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_ST> { using T = Logic; };
- template<> struct ValueType<input_Ts> { using T = Number; };
- template<> struct ValueType<output_OUT> { using T = Logic; };
- struct ContextObject {
- Node* _node;
- Logic _input_ST;
- Number _input_Ts;
- bool _isOutputDirty_OUT : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_ST input_Ts" \
- " output_OUT");
- }
- template<> Logic getValue<input_ST>(Context ctx) {
- return ctx->_input_ST;
- }
- template<> Number getValue<input_Ts>(Context ctx) {
- return ctx->_input_Ts;
- }
- template<> Logic getValue<output_OUT>(Context ctx) {
- return ctx->_node->output_OUT;
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Logic val) {
- ctx->_node->output_OUT = val;
- ctx->_isOutputDirty_OUT = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- State* state = getState(ctx);
- bool x = getValue<input_ST>(ctx);
- if (x != state->state) {
- state->state = x;
- TimeMs dt = getValue<input_Ts>(ctx) * 1000;
- setTimeout(ctx, dt);
- }
- if (isTimedOut(ctx)) {
- emitValue<output_OUT>(ctx, x);
- }
- }
- } // namespace xod__core__debounce__boolean
- //-----------------------------------------------------------------------------
- // xod/core/greater implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__greater {
- //#pragma XOD dirtieness disable
- struct State {
- };
- struct Node {
- Logic output_OUT;
- State state;
- };
- struct input_IN1 { };
- struct input_IN2 { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_IN1> { using T = Number; };
- template<> struct ValueType<input_IN2> { using T = Number; };
- template<> struct ValueType<output_OUT> { using T = Logic; };
- struct ContextObject {
- Node* _node;
- Number _input_IN1;
- Number _input_IN2;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_IN1 input_IN2" \
- " output_OUT");
- }
- template<> Number getValue<input_IN1>(Context ctx) {
- return ctx->_input_IN1;
- }
- template<> Number getValue<input_IN2>(Context ctx) {
- return ctx->_input_IN2;
- }
- template<> Logic getValue<output_OUT>(Context ctx) {
- return ctx->_node->output_OUT;
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Logic val) {
- ctx->_node->output_OUT = val;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- auto lhs = getValue<input_IN1>(ctx);
- auto rhs = getValue<input_IN2>(ctx);
- emitValue<output_OUT>(ctx, lhs > rhs);
- }
- } // namespace xod__core__greater
- //-----------------------------------------------------------------------------
- // xod/core/pulse-on-change(boolean) implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__pulse_on_change__boolean {
- struct State {
- bool sample = false;
- };
- struct Node {
- State state;
- };
- struct input_IN { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_IN> { using T = Logic; };
- template<> struct ValueType<output_OUT> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- Logic _input_IN;
- bool _isOutputDirty_OUT : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_IN" \
- " output_OUT");
- }
- template<> Logic getValue<input_IN>(Context ctx) {
- return ctx->_input_IN;
- }
- template<> Pulse getValue<output_OUT>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- "");
- return false;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_OUT = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- State* state = getState(ctx);
- int8_t newValue = (int8_t) getValue<input_IN>(ctx);
- if (!isSettingUp() && newValue != state->sample)
- emitValue<output_OUT>(ctx, 1);
- state->sample = newValue;
- }
- } // namespace xod__core__pulse_on_change__boolean
- //-----------------------------------------------------------------------------
- // xod/core/gate(pulse) implementation
- //-----------------------------------------------------------------------------
- namespace xod__core__gate__pulse {
- struct State {
- };
- struct Node {
- State state;
- };
- struct input_IN { };
- struct input_EN { };
- struct output_OUT { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_IN> { using T = Pulse; };
- template<> struct ValueType<input_EN> { using T = Logic; };
- template<> struct ValueType<output_OUT> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- Logic _input_EN;
- bool _isInputDirty_IN;
- bool _isOutputDirty_OUT : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_IN input_EN" \
- " output_OUT");
- }
- template<> Pulse getValue<input_IN>(Context ctx) {
- return Pulse();
- }
- template<> Logic getValue<input_EN>(Context ctx) {
- return ctx->_input_EN;
- }
- template<> Pulse getValue<output_OUT>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- " input_IN");
- return false;
- }
- template<> bool isInputDirty<input_IN>(Context ctx) {
- return ctx->_isInputDirty_IN;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_OUT");
- }
- template<> void emitValue<output_OUT>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_OUT = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- if (getValue<input_EN>(ctx) && isInputDirty<input_IN>(ctx))
- emitValue<output_OUT>(ctx, true);
- }
- } // namespace xod__core__gate__pulse
- //-----------------------------------------------------------------------------
- // xod-dev/servo/rotate implementation
- //-----------------------------------------------------------------------------
- namespace xod_dev__servo__rotate {
- //#pragma XOD evaluate_on_pin disable
- //#pragma XOD evaluate_on_pin enable input_DO
- struct State { };
- struct Node {
- xod_dev__servo__servo_device::Type output_DEVU0027;
- State state;
- };
- struct input_VAL { };
- struct input_DEV { };
- struct input_DO { };
- struct output_ACK { };
- struct output_DEVU0027 { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_VAL> { using T = Number; };
- template<> struct ValueType<input_DEV> { using T = xod_dev__servo__servo_device::Type; };
- template<> struct ValueType<input_DO> { using T = Pulse; };
- template<> struct ValueType<output_ACK> { using T = Pulse; };
- template<> struct ValueType<output_DEVU0027> { using T = xod_dev__servo__servo_device::Type; };
- struct ContextObject {
- Node* _node;
- Number _input_VAL;
- xod_dev__servo__servo_device::Type _input_DEV;
- bool _isInputDirty_DO;
- bool _isOutputDirty_ACK : 1;
- bool _isOutputDirty_DEVU0027 : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_VAL input_DEV input_DO" \
- " output_ACK output_DEVU0027");
- }
- template<> Number getValue<input_VAL>(Context ctx) {
- return ctx->_input_VAL;
- }
- template<> xod_dev__servo__servo_device::Type getValue<input_DEV>(Context ctx) {
- return ctx->_input_DEV;
- }
- template<> Pulse getValue<input_DO>(Context ctx) {
- return Pulse();
- }
- template<> Pulse getValue<output_ACK>(Context ctx) {
- return Pulse();
- }
- template<> xod_dev__servo__servo_device::Type getValue<output_DEVU0027>(Context ctx) {
- return ctx->_node->output_DEVU0027;
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- " input_DO");
- return false;
- }
- template<> bool isInputDirty<input_DO>(Context ctx) {
- return ctx->_isInputDirty_DO;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_ACK output_DEVU0027");
- }
- template<> void emitValue<output_ACK>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_ACK = true;
- }
- template<> void emitValue<output_DEVU0027>(Context ctx, xod_dev__servo__servo_device::Type val) {
- ctx->_node->output_DEVU0027 = val;
- ctx->_isOutputDirty_DEVU0027 = true;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- void evaluate(Context ctx) {
- auto xservo = getValue<input_DEV>(ctx);
- if (isSettingUp()) {
- // Short-circuit DEV and DEV'
- emitValue<output_DEVU0027>(ctx, xservo);
- }
- if (!isInputDirty<input_DO>(ctx))
- return;
- auto angle = getValue<input_VAL>(ctx);
- xservo->write01(angle);
- emitValue<output_ACK>(ctx, 1);
- }
- } // namespace xod_dev__servo__rotate
- //-----------------------------------------------------------------------------
- // xod/gpio/digital-write implementation
- //-----------------------------------------------------------------------------
- namespace xod__gpio__digital_write {
- //#pragma XOD evaluate_on_pin disable
- //#pragma XOD evaluate_on_pin enable input_UPD
- //#pragma XOD error_raise enable
- struct State {
- };
- union NodeErrors {
- struct {
- bool output_DONE : 1;
- };
- ErrorFlags flags;
- };
- struct Node {
- NodeErrors errors;
- State state;
- };
- struct input_PORT { };
- struct input_SIG { };
- struct input_UPD { };
- struct output_DONE { };
- template<typename PinT> struct ValueType { using T = void; };
- template<> struct ValueType<input_PORT> { using T = uint8_t; };
- template<> struct ValueType<input_SIG> { using T = Logic; };
- template<> struct ValueType<input_UPD> { using T = Pulse; };
- template<> struct ValueType<output_DONE> { using T = Pulse; };
- struct ContextObject {
- Node* _node;
- uint8_t _input_PORT;
- Logic _input_SIG;
- bool _isInputDirty_UPD;
- bool _isOutputDirty_DONE : 1;
- };
- using Context = ContextObject*;
- template<typename PinT> typename ValueType<PinT>::T getValue(Context ctx) {
- static_assert(always_false<PinT>::value,
- "Invalid pin descriptor. Expected one of:" \
- " input_PORT input_SIG input_UPD" \
- " output_DONE");
- }
- template<> uint8_t getValue<input_PORT>(Context ctx) {
- return ctx->_input_PORT;
- }
- template<> Logic getValue<input_SIG>(Context ctx) {
- return ctx->_input_SIG;
- }
- template<> Pulse getValue<input_UPD>(Context ctx) {
- return Pulse();
- }
- template<> Pulse getValue<output_DONE>(Context ctx) {
- return Pulse();
- }
- template<typename InputT> bool isInputDirty(Context ctx) {
- static_assert(always_false<InputT>::value,
- "Invalid input descriptor. Expected one of:" \
- " input_UPD");
- return false;
- }
- template<> bool isInputDirty<input_UPD>(Context ctx) {
- return ctx->_isInputDirty_UPD;
- }
- template<typename OutputT> void emitValue(Context ctx, typename ValueType<OutputT>::T val) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_DONE");
- }
- template<> void emitValue<output_DONE>(Context ctx, Pulse val) {
- ctx->_isOutputDirty_DONE = true;
- ctx->_node->errors.output_DONE = false;
- }
- State* getState(Context ctx) {
- return &ctx->_node->state;
- }
- template<typename OutputT> void raiseError(Context ctx) {
- static_assert(always_false<OutputT>::value,
- "Invalid output descriptor. Expected one of:" \
- " output_DONE");
- }
- template<> void raiseError<output_DONE>(Context ctx) {
- ctx->_node->errors.output_DONE = true;
- ctx->_isOutputDirty_DONE = true;
- }
- void raiseError(Context ctx) {
- ctx->_node->errors.output_DONE = true;
- ctx->_isOutputDirty_DONE = true;
- }
- void evaluate(Context ctx) {
- if (!isInputDirty<input_UPD>(ctx))
- return;
- const uint8_t port = getValue<input_PORT>(ctx);
- if (!isValidDigitalPort(port)) {
- raiseError<output_DONE>(ctx);
- return;
- }
- ::pinMode(port, OUTPUT);
- const bool val = getValue<input_SIG>(ctx);
- ::digitalWrite(port, val);
- emitValue<output_DONE>(ctx, 1);
- }
- } // namespace xod__gpio__digital_write
- } // namespace xod
- /*=============================================================================
- *
- *
- * Main loop components
- *
- *
- =============================================================================*/
- namespace xod {
- // Define/allocate persistent storages (state, timeout, output data) for all nodes
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
- constexpr Number node_0_output_VAL = 0.25;
- constexpr Number node_1_output_VAL = 36;
- constexpr Number node_2_output_VAL = 0.02;
- constexpr uint8_t node_3_output_VAL = 52;
- constexpr Logic node_4_output_VAL = true;
- constexpr uint8_t node_5_output_VAL = 32;
- constexpr Logic node_6_output_VAL = true;
- constexpr uint8_t node_7_output_VAL = 0;
- constexpr Number node_8_output_VAL = 0.15;
- constexpr Number node_9_output_VAL = 0.35;
- constexpr Number node_10_output_VAL = 25;
- constexpr Number node_11_output_VAL = 125;
- constexpr uint8_t node_12_output_VAL = A0;
- constexpr uint8_t node_13_output_VAL = A5;
- constexpr Number node_14_output_VAL = 544;
- constexpr Number node_15_output_VAL = 2400;
- constexpr Logic node_16_output_VAL = true;
- constexpr Logic node_17_output_VAL = true;
- constexpr xod_dev__servo__servo_device::Type node_21_output_DEV = { /* xod-dev/servo/servo-device */ };
- constexpr Logic node_24_output_SIG = false;
- constexpr Number node_25_output_VAL = 0;
- constexpr Logic node_27_output_OUT = false;
- constexpr Number node_28_output_OUT = 0;
- constexpr Logic node_29_output_OUT = false;
- constexpr Logic node_30_output_OUT = false;
- constexpr xod_dev__servo__servo_device::Type node_42_output_DEVU0027 = { /* xod-dev/servo/servo-device */ };
- #pragma GCC diagnostic pop
- struct TransactionState {
- bool node_18_isNodeDirty : 1;
- bool node_18_isOutputDirty_TICK : 1;
- bool node_19_isNodeDirty : 1;
- bool node_19_isOutputDirty_BOOT : 1;
- bool node_20_isNodeDirty : 1;
- bool node_20_isOutputDirty_OUT : 1;
- bool node_21_isNodeDirty : 1;
- bool node_22_isNodeDirty : 1;
- bool node_22_isOutputDirty_OUT : 1;
- bool node_23_isNodeDirty : 1;
- bool node_23_isOutputDirty_OUT : 1;
- bool node_24_isNodeDirty : 1;
- bool node_24_isOutputDirty_SIG : 1;
- bool node_25_isNodeDirty : 1;
- bool node_25_isOutputDirty_VAL : 1;
- bool node_26_isNodeDirty : 1;
- bool node_26_isOutputDirty_OUT : 1;
- bool node_27_isNodeDirty : 1;
- bool node_27_isOutputDirty_OUT : 1;
- bool node_27_hasUpstreamError : 1;
- bool node_28_isNodeDirty : 1;
- bool node_28_isOutputDirty_OUT : 1;
- bool node_28_hasUpstreamError : 1;
- bool node_29_isNodeDirty : 1;
- bool node_29_isOutputDirty_OUT : 1;
- bool node_29_hasUpstreamError : 1;
- bool node_30_isNodeDirty : 1;
- bool node_30_isOutputDirty_OUT : 1;
- bool node_30_hasUpstreamError : 1;
- bool node_31_isNodeDirty : 1;
- bool node_31_isOutputDirty_OUT : 1;
- bool node_31_hasUpstreamError : 1;
- bool node_32_isNodeDirty : 1;
- bool node_32_isOutputDirty_OUT : 1;
- bool node_32_hasUpstreamError : 1;
- bool node_33_isNodeDirty : 1;
- bool node_33_isOutputDirty_OUT : 1;
- bool node_33_hasUpstreamError : 1;
- bool node_34_isNodeDirty : 1;
- bool node_34_isOutputDirty_OUT : 1;
- bool node_34_hasUpstreamError : 1;
- bool node_35_isNodeDirty : 1;
- bool node_35_isOutputDirty_OUT : 1;
- bool node_35_hasUpstreamError : 1;
- bool node_36_isNodeDirty : 1;
- bool node_36_isOutputDirty_OUT : 1;
- bool node_36_hasUpstreamError : 1;
- bool node_37_isNodeDirty : 1;
- bool node_37_isOutputDirty_OUT : 1;
- bool node_37_hasUpstreamError : 1;
- bool node_38_isNodeDirty : 1;
- bool node_38_isOutputDirty_OUT : 1;
- bool node_38_hasUpstreamError : 1;
- bool node_39_isNodeDirty : 1;
- bool node_39_isOutputDirty_OUT : 1;
- bool node_39_hasUpstreamError : 1;
- bool node_40_isNodeDirty : 1;
- bool node_40_isOutputDirty_OUT : 1;
- bool node_40_hasUpstreamError : 1;
- bool node_41_isNodeDirty : 1;
- bool node_41_isOutputDirty_OUT : 1;
- bool node_41_hasUpstreamError : 1;
- bool node_42_isNodeDirty : 1;
- bool node_42_hasUpstreamError : 1;
- bool node_43_isNodeDirty : 1;
- bool node_43_hasUpstreamError : 1;
- bool node_44_isNodeDirty : 1;
- bool node_44_hasUpstreamError : 1;
- TransactionState() {
- node_18_isNodeDirty = true;
- node_18_isOutputDirty_TICK = false;
- node_19_isNodeDirty = true;
- node_19_isOutputDirty_BOOT = false;
- node_20_isNodeDirty = true;
- node_20_isOutputDirty_OUT = false;
- node_21_isNodeDirty = true;
- node_22_isNodeDirty = true;
- node_22_isOutputDirty_OUT = false;
- node_23_isNodeDirty = true;
- node_23_isOutputDirty_OUT = false;
- node_24_isNodeDirty = true;
- node_24_isOutputDirty_SIG = true;
- node_25_isNodeDirty = true;
- node_25_isOutputDirty_VAL = true;
- node_26_isNodeDirty = true;
- node_26_isOutputDirty_OUT = false;
- node_27_isNodeDirty = true;
- node_28_isNodeDirty = true;
- node_29_isNodeDirty = true;
- node_29_isOutputDirty_OUT = true;
- node_30_isNodeDirty = true;
- node_31_isNodeDirty = true;
- node_31_isOutputDirty_OUT = false;
- node_32_isNodeDirty = true;
- node_32_isOutputDirty_OUT = false;
- node_33_isNodeDirty = true;
- node_33_isOutputDirty_OUT = false;
- node_34_isNodeDirty = true;
- node_34_isOutputDirty_OUT = false;
- node_35_isNodeDirty = true;
- node_35_isOutputDirty_OUT = false;
- node_36_isNodeDirty = true;
- node_36_isOutputDirty_OUT = false;
- node_37_isNodeDirty = true;
- node_37_isOutputDirty_OUT = false;
- node_38_isNodeDirty = true;
- node_38_isOutputDirty_OUT = false;
- node_39_isNodeDirty = true;
- node_39_isOutputDirty_OUT = false;
- node_40_isNodeDirty = true;
- node_40_isOutputDirty_OUT = false;
- node_41_isNodeDirty = true;
- node_41_isOutputDirty_OUT = false;
- node_42_isNodeDirty = true;
- node_43_isNodeDirty = true;
- node_44_isNodeDirty = true;
- }
- };
- TransactionState g_transaction;
- xod__core__continuously::Node node_18 = {
- 0, // timeoutAt
- xod__core__continuously::State() // state default
- };
- xod__core__boot::Node node_19 = {
- xod__core__boot::State() // state default
- };
- xod__core__pulse_on_change__number::Node node_20 = {
- xod__core__pulse_on_change__number::State() // state default
- };
- xod_dev__servo__servo_device::Node node_21 = {
- false, // DEV has no errors on start
- node_21_output_DEV, // output DEV default
- xod_dev__servo__servo_device::State() // state default
- };
- xod__core__cast_to_pulse__boolean::Node node_22 = {
- xod__core__cast_to_pulse__boolean::State() // state default
- };
- xod__core__cast_to_pulse__boolean::Node node_23 = {
- xod__core__cast_to_pulse__boolean::State() // state default
- };
- xod__gpio__digital_read_pullup::Node node_24 = {
- false, // SIG has no errors on start
- false, // DONE has no errors on start
- node_24_output_SIG, // output SIG default
- xod__gpio__digital_read_pullup::State() // state default
- };
- xod__gpio__analog_read::Node node_25 = {
- false, // VAL has no errors on start
- false, // DONE has no errors on start
- node_25_output_VAL, // output VAL default
- xod__gpio__analog_read::State() // state default
- };
- xod__core__any::Node node_26 = {
- xod__core__any::State() // state default
- };
- xod__core__not::Node node_27 = {
- node_27_output_OUT, // output OUT default
- xod__core__not::State() // state default
- };
- xod__math__map::Node node_28 = {
- node_28_output_OUT, // output OUT default
- xod__math__map::State() // state default
- };
- xod__core__debounce__boolean::Node node_29 = {
- 0, // timeoutAt
- node_29_output_OUT, // output OUT default
- xod__core__debounce__boolean::State() // state default
- };
- xod__core__greater::Node node_30 = {
- node_30_output_OUT, // output OUT default
- xod__core__greater::State() // state default
- };
- xod__core__pulse_on_change__boolean::Node node_31 = {
- xod__core__pulse_on_change__boolean::State() // state default
- };
- xod__core__pulse_on_change__boolean::Node node_32 = {
- xod__core__pulse_on_change__boolean::State() // state default
- };
- xod__core__cast_to_pulse__boolean::Node node_33 = {
- xod__core__cast_to_pulse__boolean::State() // state default
- };
- xod__core__any::Node node_34 = {
- xod__core__any::State() // state default
- };
- xod__core__any::Node node_35 = {
- xod__core__any::State() // state default
- };
- xod__core__any::Node node_36 = {
- xod__core__any::State() // state default
- };
- xod__core__any::Node node_37 = {
- xod__core__any::State() // state default
- };
- xod__core__any::Node node_38 = {
- xod__core__any::State() // state default
- };
- xod__core__gate__pulse::Node node_39 = {
- xod__core__gate__pulse::State() // state default
- };
- xod__core__gate__pulse::Node node_40 = {
- xod__core__gate__pulse::State() // state default
- };
- xod__core__gate__pulse::Node node_41 = {
- xod__core__gate__pulse::State() // state default
- };
- xod_dev__servo__rotate::Node node_42 = {
- node_42_output_DEVU0027, // output DEVU0027 default
- xod_dev__servo__rotate::State() // state default
- };
- xod__gpio__digital_write::Node node_43 = {
- false, // DONE has no errors on start
- xod__gpio__digital_write::State() // state default
- };
- xod__gpio__digital_write::Node node_44 = {
- false, // DONE has no errors on start
- xod__gpio__digital_write::State() // state default
- };
- #if defined(XOD_DEBUG) || defined(XOD_SIMULATION)
- namespace detail {
- void handleTweaks() {
- if (XOD_DEBUG_SERIAL.available() > 0 && XOD_DEBUG_SERIAL.find("+XOD:", 5)) {
- int tweakedNodeId = XOD_DEBUG_SERIAL.parseInt();
- switch (tweakedNodeId) {
- }
- XOD_DEBUG_SERIAL.find('\n');
- }
- }
- } // namespace detail
- #endif
- void handleDefers() {
- }
- void runTransaction() {
- g_transactionTime = millis();
- XOD_TRACE_F("Transaction started, t=");
- XOD_TRACE_LN(g_transactionTime);
- #if defined(XOD_DEBUG) || defined(XOD_SIMULATION)
- detail::handleTweaks();
- #endif
- // Check for timeouts
- g_transaction.node_18_isNodeDirty |= detail::isTimedOut(&node_18);
- g_transaction.node_29_isNodeDirty |= detail::isTimedOut(&node_29);
- // defer-* nodes are always at the very bottom of the graph, so no one will
- // recieve values emitted by them. We must evaluate them before everybody
- // else to give them a chance to emit values.
- //
- // If trigerred, keep only output dirty, not the node itself, so it will
- // evaluate on the regular pass only if it receives a new value again.
- if (!isSettingUp()) {
- g_isEarlyDeferPass = true;
- handleDefers();
- g_isEarlyDeferPass = false;
- }
- // Evaluate all dirty nodes
- { // xod__core__continuously #18
- if (g_transaction.node_18_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(18);
- xod__core__continuously::ContextObject ctxObj;
- ctxObj._node = &node_18;
- // copy data from upstream nodes into context
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_TICK = false;
- xod__core__continuously::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_18_isOutputDirty_TICK = ctxObj._isOutputDirty_TICK;
- // mark downstream nodes dirty
- g_transaction.node_24_isNodeDirty |= g_transaction.node_18_isOutputDirty_TICK;
- g_transaction.node_25_isNodeDirty |= g_transaction.node_18_isOutputDirty_TICK;
- }
- }
- { // xod__core__boot #19
- if (g_transaction.node_19_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(19);
- xod__core__boot::ContextObject ctxObj;
- ctxObj._node = &node_19;
- // copy data from upstream nodes into context
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_BOOT = false;
- xod__core__boot::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_19_isOutputDirty_BOOT = ctxObj._isOutputDirty_BOOT;
- // mark downstream nodes dirty
- g_transaction.node_26_isNodeDirty |= g_transaction.node_19_isOutputDirty_BOOT;
- g_transaction.node_34_isNodeDirty |= g_transaction.node_19_isOutputDirty_BOOT;
- g_transaction.node_35_isNodeDirty |= g_transaction.node_19_isOutputDirty_BOOT;
- }
- }
- { // xod__core__pulse_on_change__number #20
- if (g_transaction.node_20_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(20);
- xod__core__pulse_on_change__number::ContextObject ctxObj;
- ctxObj._node = &node_20;
- // copy data from upstream nodes into context
- ctxObj._input_IN = node_0_output_VAL;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__pulse_on_change__number::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_20_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_26_isNodeDirty |= g_transaction.node_20_isOutputDirty_OUT;
- }
- }
- { // xod_dev__servo__servo_device #21
- if (g_transaction.node_21_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(21);
- xod_dev__servo__servo_device::ContextObject ctxObj;
- ctxObj._node = &node_21;
- // copy data from upstream nodes into context
- ctxObj._input_PORT = node_13_output_VAL;
- ctxObj._input_Pmin = node_14_output_VAL;
- ctxObj._input_Pmax = node_15_output_VAL;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_DEV = false;
- xod_dev__servo__servo_device::NodeErrors previousErrors = node_21.errors;
- xod_dev__servo__servo_device::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- if (previousErrors.flags != node_21.errors.flags) {
- detail::printErrorToDebugSerial(21, node_21.errors.flags);
- // if an error was just raised or cleared from an output,
- // mark nearest downstream error catchers as dirty
- if (node_21.errors.output_DEV != previousErrors.output_DEV) {
- }
- // if a pulse output was cleared from error, mark downstream nodes as dirty
- // (no matter if a pulse was emitted or not)
- }
- // mark downstream nodes dirty
- }
- // propagate errors hold by the node outputs
- if (node_21.errors.flags) {
- if (node_21.errors.output_DEV) {
- g_transaction.node_42_hasUpstreamError = true;
- }
- }
- }
- { // xod__core__cast_to_pulse__boolean #22
- if (g_transaction.node_22_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(22);
- xod__core__cast_to_pulse__boolean::ContextObject ctxObj;
- ctxObj._node = &node_22;
- // copy data from upstream nodes into context
- ctxObj._input_IN = node_16_output_VAL;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__cast_to_pulse__boolean::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_22_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_37_isNodeDirty |= g_transaction.node_22_isOutputDirty_OUT;
- }
- }
- { // xod__core__cast_to_pulse__boolean #23
- if (g_transaction.node_23_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(23);
- xod__core__cast_to_pulse__boolean::ContextObject ctxObj;
- ctxObj._node = &node_23;
- // copy data from upstream nodes into context
- ctxObj._input_IN = node_17_output_VAL;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__cast_to_pulse__boolean::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_23_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_38_isNodeDirty |= g_transaction.node_23_isOutputDirty_OUT;
- }
- }
- { // xod__gpio__digital_read_pullup #24
- if (g_transaction.node_24_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(24);
- xod__gpio__digital_read_pullup::ContextObject ctxObj;
- ctxObj._node = &node_24;
- // copy data from upstream nodes into context
- ctxObj._input_PORT = node_3_output_VAL;
- ctxObj._isInputDirty_UPD = g_transaction.node_18_isOutputDirty_TICK;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_SIG = false;
- ctxObj._isOutputDirty_DONE = false;
- xod__gpio__digital_read_pullup::NodeErrors previousErrors = node_24.errors;
- node_24.errors.output_DONE = false;
- xod__gpio__digital_read_pullup::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_24_isOutputDirty_SIG = ctxObj._isOutputDirty_SIG;
- if (previousErrors.flags != node_24.errors.flags) {
- detail::printErrorToDebugSerial(24, node_24.errors.flags);
- // if an error was just raised or cleared from an output,
- // mark nearest downstream error catchers as dirty
- if (node_24.errors.output_SIG != previousErrors.output_SIG) {
- }
- if (node_24.errors.output_DONE != previousErrors.output_DONE) {
- }
- // if a pulse output was cleared from error, mark downstream nodes as dirty
- // (no matter if a pulse was emitted or not)
- if (previousErrors.output_DONE && !node_24.errors.output_DONE) {
- }
- }
- // mark downstream nodes dirty
- g_transaction.node_27_isNodeDirty |= g_transaction.node_24_isOutputDirty_SIG;
- }
- // propagate errors hold by the node outputs
- if (node_24.errors.flags) {
- if (node_24.errors.output_SIG) {
- g_transaction.node_27_hasUpstreamError = true;
- }
- if (node_24.errors.output_DONE) {
- }
- }
- }
- { // xod__gpio__analog_read #25
- if (g_transaction.node_25_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(25);
- xod__gpio__analog_read::ContextObject ctxObj;
- ctxObj._node = &node_25;
- // copy data from upstream nodes into context
- ctxObj._input_PORT = node_12_output_VAL;
- ctxObj._isInputDirty_UPD = g_transaction.node_18_isOutputDirty_TICK;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_VAL = false;
- ctxObj._isOutputDirty_DONE = false;
- xod__gpio__analog_read::NodeErrors previousErrors = node_25.errors;
- node_25.errors.output_DONE = false;
- xod__gpio__analog_read::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_25_isOutputDirty_VAL = ctxObj._isOutputDirty_VAL;
- if (previousErrors.flags != node_25.errors.flags) {
- detail::printErrorToDebugSerial(25, node_25.errors.flags);
- // if an error was just raised or cleared from an output,
- // mark nearest downstream error catchers as dirty
- if (node_25.errors.output_VAL != previousErrors.output_VAL) {
- }
- if (node_25.errors.output_DONE != previousErrors.output_DONE) {
- }
- // if a pulse output was cleared from error, mark downstream nodes as dirty
- // (no matter if a pulse was emitted or not)
- if (previousErrors.output_DONE && !node_25.errors.output_DONE) {
- }
- }
- // mark downstream nodes dirty
- g_transaction.node_28_isNodeDirty |= g_transaction.node_25_isOutputDirty_VAL;
- }
- // propagate errors hold by the node outputs
- if (node_25.errors.flags) {
- if (node_25.errors.output_VAL) {
- g_transaction.node_28_hasUpstreamError = true;
- }
- if (node_25.errors.output_DONE) {
- }
- }
- }
- { // xod__core__any #26
- if (g_transaction.node_26_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(26);
- xod__core__any::ContextObject ctxObj;
- ctxObj._node = &node_26;
- // copy data from upstream nodes into context
- ctxObj._isInputDirty_IN1 = g_transaction.node_20_isOutputDirty_OUT;
- ctxObj._isInputDirty_IN2 = g_transaction.node_19_isOutputDirty_BOOT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__any::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_26_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_36_isNodeDirty |= g_transaction.node_26_isOutputDirty_OUT;
- }
- }
- { // xod__core__not #27
- if (g_transaction.node_27_hasUpstreamError) {
- g_transaction.node_29_hasUpstreamError = true;
- } else if (g_transaction.node_27_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(27);
- xod__core__not::ContextObject ctxObj;
- ctxObj._node = &node_27;
- // copy data from upstream nodes into context
- ctxObj._input_IN = node_24.output_SIG;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- xod__core__not::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- // mark downstream nodes dirty
- g_transaction.node_29_isNodeDirty = true;
- }
- }
- { // xod__math__map #28
- if (g_transaction.node_28_hasUpstreamError) {
- g_transaction.node_30_hasUpstreamError = true;
- } else if (g_transaction.node_28_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(28);
- xod__math__map::ContextObject ctxObj;
- ctxObj._node = &node_28;
- // copy data from upstream nodes into context
- ctxObj._input_X = node_25.output_VAL;
- ctxObj._input_Smin = node_8_output_VAL;
- ctxObj._input_Smax = node_9_output_VAL;
- ctxObj._input_Tmin = node_10_output_VAL;
- ctxObj._input_Tmax = node_11_output_VAL;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- xod__math__map::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- // mark downstream nodes dirty
- g_transaction.node_30_isNodeDirty = true;
- }
- }
- { // xod__core__debounce__boolean #29
- if (g_transaction.node_29_hasUpstreamError) {
- g_transaction.node_31_hasUpstreamError = true;
- g_transaction.node_43_hasUpstreamError = true;
- } else if (g_transaction.node_29_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(29);
- xod__core__debounce__boolean::ContextObject ctxObj;
- ctxObj._node = &node_29;
- // copy data from upstream nodes into context
- ctxObj._input_ST = node_27.output_OUT;
- ctxObj._input_Ts = node_2_output_VAL;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__debounce__boolean::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_29_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_31_isNodeDirty |= g_transaction.node_29_isOutputDirty_OUT;
- }
- }
- { // xod__core__greater #30
- if (g_transaction.node_30_hasUpstreamError) {
- g_transaction.node_32_hasUpstreamError = true;
- g_transaction.node_33_hasUpstreamError = true;
- g_transaction.node_39_hasUpstreamError = true;
- g_transaction.node_44_hasUpstreamError = true;
- } else if (g_transaction.node_30_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(30);
- xod__core__greater::ContextObject ctxObj;
- ctxObj._node = &node_30;
- // copy data from upstream nodes into context
- ctxObj._input_IN1 = node_28.output_OUT;
- ctxObj._input_IN2 = node_1_output_VAL;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- xod__core__greater::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- // mark downstream nodes dirty
- g_transaction.node_32_isNodeDirty = true;
- g_transaction.node_33_isNodeDirty = true;
- g_transaction.node_39_isNodeDirty = true;
- }
- }
- { // xod__core__pulse_on_change__boolean #31
- if (g_transaction.node_31_hasUpstreamError) {
- g_transaction.node_34_hasUpstreamError = true;
- } else if (g_transaction.node_31_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(31);
- xod__core__pulse_on_change__boolean::ContextObject ctxObj;
- ctxObj._node = &node_31;
- // copy data from upstream nodes into context
- ctxObj._input_IN = node_29.output_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__pulse_on_change__boolean::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_31_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_34_isNodeDirty |= g_transaction.node_31_isOutputDirty_OUT;
- }
- }
- { // xod__core__pulse_on_change__boolean #32
- if (g_transaction.node_32_hasUpstreamError) {
- g_transaction.node_35_hasUpstreamError = true;
- } else if (g_transaction.node_32_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(32);
- xod__core__pulse_on_change__boolean::ContextObject ctxObj;
- ctxObj._node = &node_32;
- // copy data from upstream nodes into context
- ctxObj._input_IN = node_30.output_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__pulse_on_change__boolean::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_32_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_35_isNodeDirty |= g_transaction.node_32_isOutputDirty_OUT;
- }
- }
- { // xod__core__cast_to_pulse__boolean #33
- if (g_transaction.node_33_hasUpstreamError) {
- g_transaction.node_36_hasUpstreamError = true;
- } else if (g_transaction.node_33_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(33);
- xod__core__cast_to_pulse__boolean::ContextObject ctxObj;
- ctxObj._node = &node_33;
- // copy data from upstream nodes into context
- ctxObj._input_IN = node_30.output_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__cast_to_pulse__boolean::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_33_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_36_isNodeDirty |= g_transaction.node_33_isOutputDirty_OUT;
- }
- }
- { // xod__core__any #34
- if (g_transaction.node_34_hasUpstreamError) {
- g_transaction.node_37_hasUpstreamError = true;
- } else if (g_transaction.node_34_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(34);
- xod__core__any::ContextObject ctxObj;
- ctxObj._node = &node_34;
- // copy data from upstream nodes into context
- ctxObj._isInputDirty_IN1 = g_transaction.node_31_isOutputDirty_OUT;
- ctxObj._isInputDirty_IN2 = g_transaction.node_19_isOutputDirty_BOOT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__any::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_34_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_37_isNodeDirty |= g_transaction.node_34_isOutputDirty_OUT;
- }
- }
- { // xod__core__any #35
- if (g_transaction.node_35_hasUpstreamError) {
- g_transaction.node_38_hasUpstreamError = true;
- } else if (g_transaction.node_35_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(35);
- xod__core__any::ContextObject ctxObj;
- ctxObj._node = &node_35;
- // copy data from upstream nodes into context
- ctxObj._isInputDirty_IN1 = g_transaction.node_32_isOutputDirty_OUT;
- ctxObj._isInputDirty_IN2 = g_transaction.node_19_isOutputDirty_BOOT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__any::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_35_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_38_isNodeDirty |= g_transaction.node_35_isOutputDirty_OUT;
- }
- }
- { // xod__core__any #36
- if (g_transaction.node_36_hasUpstreamError) {
- g_transaction.node_39_hasUpstreamError = true;
- } else if (g_transaction.node_36_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(36);
- xod__core__any::ContextObject ctxObj;
- ctxObj._node = &node_36;
- // copy data from upstream nodes into context
- ctxObj._isInputDirty_IN1 = g_transaction.node_26_isOutputDirty_OUT;
- ctxObj._isInputDirty_IN2 = g_transaction.node_33_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__any::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_36_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_39_isNodeDirty |= g_transaction.node_36_isOutputDirty_OUT;
- }
- }
- { // xod__core__any #37
- if (g_transaction.node_37_hasUpstreamError) {
- g_transaction.node_40_hasUpstreamError = true;
- } else if (g_transaction.node_37_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(37);
- xod__core__any::ContextObject ctxObj;
- ctxObj._node = &node_37;
- // copy data from upstream nodes into context
- ctxObj._isInputDirty_IN1 = g_transaction.node_34_isOutputDirty_OUT;
- ctxObj._isInputDirty_IN2 = g_transaction.node_22_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__any::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_37_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_40_isNodeDirty |= g_transaction.node_37_isOutputDirty_OUT;
- }
- }
- { // xod__core__any #38
- if (g_transaction.node_38_hasUpstreamError) {
- g_transaction.node_41_hasUpstreamError = true;
- } else if (g_transaction.node_38_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(38);
- xod__core__any::ContextObject ctxObj;
- ctxObj._node = &node_38;
- // copy data from upstream nodes into context
- ctxObj._isInputDirty_IN1 = g_transaction.node_35_isOutputDirty_OUT;
- ctxObj._isInputDirty_IN2 = g_transaction.node_23_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__any::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_38_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_41_isNodeDirty |= g_transaction.node_38_isOutputDirty_OUT;
- }
- }
- { // xod__core__gate__pulse #39
- if (g_transaction.node_39_hasUpstreamError) {
- g_transaction.node_42_hasUpstreamError = true;
- } else if (g_transaction.node_39_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(39);
- xod__core__gate__pulse::ContextObject ctxObj;
- ctxObj._node = &node_39;
- // copy data from upstream nodes into context
- ctxObj._input_EN = node_30.output_OUT;
- ctxObj._isInputDirty_IN = g_transaction.node_36_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__gate__pulse::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_39_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_42_isNodeDirty |= g_transaction.node_39_isOutputDirty_OUT;
- }
- }
- { // xod__core__gate__pulse #40
- if (g_transaction.node_40_hasUpstreamError) {
- g_transaction.node_43_hasUpstreamError = true;
- } else if (g_transaction.node_40_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(40);
- xod__core__gate__pulse::ContextObject ctxObj;
- ctxObj._node = &node_40;
- // copy data from upstream nodes into context
- ctxObj._input_EN = node_4_output_VAL;
- ctxObj._isInputDirty_IN = g_transaction.node_37_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__gate__pulse::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_40_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_43_isNodeDirty |= g_transaction.node_40_isOutputDirty_OUT;
- }
- }
- { // xod__core__gate__pulse #41
- if (g_transaction.node_41_hasUpstreamError) {
- g_transaction.node_44_hasUpstreamError = true;
- } else if (g_transaction.node_41_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(41);
- xod__core__gate__pulse::ContextObject ctxObj;
- ctxObj._node = &node_41;
- // copy data from upstream nodes into context
- ctxObj._input_EN = node_6_output_VAL;
- ctxObj._isInputDirty_IN = g_transaction.node_38_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_OUT = false;
- xod__core__gate__pulse::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- g_transaction.node_41_isOutputDirty_OUT = ctxObj._isOutputDirty_OUT;
- // mark downstream nodes dirty
- g_transaction.node_44_isNodeDirty |= g_transaction.node_41_isOutputDirty_OUT;
- }
- }
- { // xod_dev__servo__rotate #42
- if (g_transaction.node_42_hasUpstreamError) {
- } else if (g_transaction.node_42_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(42);
- xod_dev__servo__rotate::ContextObject ctxObj;
- ctxObj._node = &node_42;
- // copy data from upstream nodes into context
- ctxObj._input_VAL = node_0_output_VAL;
- ctxObj._input_DEV = node_21.output_DEV;
- ctxObj._isInputDirty_DO = g_transaction.node_39_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_ACK = false;
- ctxObj._isOutputDirty_DEVU0027 = false;
- xod_dev__servo__rotate::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- // mark downstream nodes dirty
- }
- }
- { // xod__gpio__digital_write #43
- if (g_transaction.node_43_hasUpstreamError) {
- } else if (g_transaction.node_43_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(43);
- xod__gpio__digital_write::ContextObject ctxObj;
- ctxObj._node = &node_43;
- // copy data from upstream nodes into context
- ctxObj._input_PORT = node_5_output_VAL;
- ctxObj._input_SIG = node_29.output_OUT;
- ctxObj._isInputDirty_UPD = g_transaction.node_40_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_DONE = false;
- xod__gpio__digital_write::NodeErrors previousErrors = node_43.errors;
- node_43.errors.output_DONE = false;
- xod__gpio__digital_write::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- if (previousErrors.flags != node_43.errors.flags) {
- detail::printErrorToDebugSerial(43, node_43.errors.flags);
- // if an error was just raised or cleared from an output,
- // mark nearest downstream error catchers as dirty
- if (node_43.errors.output_DONE != previousErrors.output_DONE) {
- }
- // if a pulse output was cleared from error, mark downstream nodes as dirty
- // (no matter if a pulse was emitted or not)
- if (previousErrors.output_DONE && !node_43.errors.output_DONE) {
- }
- }
- // mark downstream nodes dirty
- }
- // propagate errors hold by the node outputs
- if (node_43.errors.flags) {
- if (node_43.errors.output_DONE) {
- }
- }
- }
- { // xod__gpio__digital_write #44
- if (g_transaction.node_44_hasUpstreamError) {
- } else if (g_transaction.node_44_isNodeDirty) {
- XOD_TRACE_F("Eval node #");
- XOD_TRACE_LN(44);
- xod__gpio__digital_write::ContextObject ctxObj;
- ctxObj._node = &node_44;
- // copy data from upstream nodes into context
- ctxObj._input_PORT = node_7_output_VAL;
- ctxObj._input_SIG = node_30.output_OUT;
- ctxObj._isInputDirty_UPD = g_transaction.node_41_isOutputDirty_OUT;
- // initialize temporary output dirtyness state in the context,
- // where it can be modified from `raiseError` and `emitValue`
- ctxObj._isOutputDirty_DONE = false;
- xod__gpio__digital_write::NodeErrors previousErrors = node_44.errors;
- node_44.errors.output_DONE = false;
- xod__gpio__digital_write::evaluate(&ctxObj);
- // transfer possibly modified dirtiness state from context to g_transaction
- if (previousErrors.flags != node_44.errors.flags) {
- detail::printErrorToDebugSerial(44, node_44.errors.flags);
- // if an error was just raised or cleared from an output,
- // mark nearest downstream error catchers as dirty
- if (node_44.errors.output_DONE != previousErrors.output_DONE) {
- }
- // if a pulse output was cleared from error, mark downstream nodes as dirty
- // (no matter if a pulse was emitted or not)
- if (previousErrors.output_DONE && !node_44.errors.output_DONE) {
- }
- }
- // mark downstream nodes dirty
- }
- // propagate errors hold by the node outputs
- if (node_44.errors.flags) {
- if (node_44.errors.output_DONE) {
- }
- }
- }
- // Clear dirtieness and timeouts for all nodes and pins
- memset(&g_transaction, 0, sizeof(g_transaction));
- detail::clearStaleTimeout(&node_18);
- detail::clearStaleTimeout(&node_29);
- XOD_TRACE_F("Transaction completed, t=");
- XOD_TRACE_LN(millis());
- }
- } // namespace xod
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement