--- /dev/null
+#ifdef USE_LOGGING
+
+#include <avr/io.h>
+#include <avr/eeprom.h>
+#include <util/atomic.h>
+
+#include "logging.h"
+
+static unsigned char buffer_ee[LOG_EE_BUF_SIZE] EEMEM;
+static unsigned char buffer_ram[LOG_RAM_BUF_SIZE];
+
+static unsigned char buffer_ram_ptr, buffer_ee_ptr;
+static unsigned char log_enabled = 0;
+
+static void inline log_init_common()
+{
+ log_enabled = 1;
+ buffer_ram_ptr = 0;
+ buffer_ee_ptr = 0;
+}
+
+#ifdef LOG_RATELIMIT_BOOTCOUNT
+static unsigned char reboot_count EEMEM;
+
+void log_init()
+{
+ unsigned char r_count;
+
+ r_count = eeprom_read_byte(&reboot_count);
+ r_count >>= 4;
+
+ if (r_count < LOG_RATELIMIT_BOOTCOUNT) {
+ r_count++;
+ eeprom_write_byte(&reboot_count,
+ (r_count << 4) | (MCUSR & 0xF));
+ log_init_common();
+ }
+}
+#else
+void log_init() { log_init_common(); }
+#endif
+
+void log_byte(unsigned char byte)
+{
+ if (!log_enabled)
+ return;
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ buffer_ram[buffer_ram_ptr++] = byte;
+
+ if (buffer_ram_ptr >= LOG_RAM_BUF_SIZE)
+ log_flush();
+ }
+}
+
+void log_word(uint16_t word)
+{
+ if (!log_enabled)
+ return;
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ log_byte(word & 0xFF);
+ log_byte(word >> 8);
+ }
+}
+
+void log_flush()
+{
+ unsigned char i;
+
+ if (!log_enabled)
+ return;
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ for (i = 0; i < buffer_ram_ptr; i++) {
+ eeprom_write_byte(&buffer_ee[buffer_ee_ptr++],
+ buffer_ram[i]);
+
+ if (buffer_ee_ptr >= LOG_EE_BUF_SIZE) {
+ log_enabled = 0;
+ return;
+ }
+ }
+ buffer_ram_ptr = 0;
+ }
+}
+
+#endif
+