// Challenge: Make printf() print to the Serial Monitor
// Hint: https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

#include <stdio.h>

unsigned char month, day, year;

const char *months[] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

void getdate(void) {
  char temp [] = __DATE__;
  unsigned char i;

  year = atoi(temp + 9);
  *(temp + 6) = 0;

  day = atoi(temp + 4);
  *(temp + 3) = 0;

  for (i = 0; i < 12; i++) {
    if (!strcmp(temp, months[i])) {
      month = i + 1;
      return;
    }
  }
}

int serial_putc(char c, FILE *) {
  Serial.write(c);
  return c;
}

void printf_begin(void) {
  fdevopen(&serial_putc, 0);
}

void setup() {
  Serial.begin(115200);

  char s[] = __FILE__;
  byte b = sizeof(s);
  while ((b > 0) && (s[b] != 47)) b--;
  char *u = s + b + 1;

  printf_begin();
  printf("Hello, printf()!\n");
  getdate();
  printf("%s %d, 20%d %s\n", months[month - 1], day, year, u);
  printf("GCC Version: %d.%d.%d\n",
         __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
}

unsigned long timeOfUpdate = 0;

void loop() {
  if (millis() - timeOfUpdate >= 1000) {
    timeOfUpdate = millis();
    printf("%lu ms\n", millis());
  }
}