#ifndef DEBUG_H #define DEBUG_H #include "config-check.h" template struct conditional { typedef T type; }; template struct conditional { typedef F type; }; #include #ifdef __AVR_ATtiny85__ class Serial { public: void begin(int); void write(uint8_t); int read(); void print(...); void println(...); operator bool(); bool available(); void flush(); }; extern Serial Serial; #endif enum DebugSink { DEBUG_SINK_VOID, DEBUG_SINK_SERIAL, DEBUG_SINK_SOFTWARE_SERIAL, }; struct DebugEmptyBase {}; struct DebugSoftwareSerialBase { // TODO: these should be customizable static const int rx_pin = 1; static const int tx_pin = 0; public: SoftwareSerial ss; DebugSoftwareSerialBase() : ss(rx_pin, tx_pin) { } }; template class Debug : public conditional::type { public: const enum DebugSink sink; Debug() : sink(sink_) { } inline void begin(const long baud_rate) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.begin(baud_rate); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.begin(baud_rate); } } inline operator bool() { if (sink_ == DEBUG_SINK_SERIAL) { Serial.operator bool(); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.operator bool(); } else { return false; } }; inline bool available() { if (sink_ == DEBUG_SINK_SERIAL) { return Serial.available(); } if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { return this->ss.available(); } return false; }; inline int read() { if (sink_ == DEBUG_SINK_SERIAL) { return Serial.read(); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { return this->ss.read(); } return '\0'; }; size_t write(uint8_t value) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.write(value); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.write(value); } return value; } template inline void print(T t, int format = DEC) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.print(t, format); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.print(t, format); } }; template inline void print(const T *t) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.print(t); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.print(t); } }; template inline void print(T *t) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.print(t); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.print(t); } }; template inline void println(T t, int format = DEC) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.println(t, format); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.println(t, format); } }; template inline void println(const T *t) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.println(t); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.println(t); } }; template inline void println(T *t) { if (sink_ == DEBUG_SINK_SERIAL) { Serial.println(t); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.println(t); } }; inline void println() { if (sink_ == DEBUG_SINK_SERIAL) { Serial.println(); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.println(); } }; inline void flush() { if (sink_ == DEBUG_SINK_SERIAL) { Serial.flush(); } else if (sink_ == DEBUG_SINK_SOFTWARE_SERIAL) { this->ss.flush(); } }; }; #if DEBUG_SINK == 0 static Debug debug; #elif DEBUG_SINK == 1 static Debug debug; #elif DEBUG_SINK == 2 static Debug debug; #else #error Invalid value for DEBUG_SINK, must be one of 1 (for no output), 2 for serial port, or 3 for software serial. #endif #endif