Skip to content

Instantly share code, notes, and snippets.

@rlcamp
Last active October 18, 2023 13:20
Show Gist options
  • Save rlcamp/15430e007e8401e6d2cf2d1bcea608d7 to your computer and use it in GitHub Desktop.
Save rlcamp/15430e007e8401e6d2cf2d1bcea608d7 to your computer and use it in GitHub Desktop.
/* allows c code to printf() within arduino sketches, given arm newlib or avr-libc */
#ifdef __arm__
/* TODO: proper check for newlib */
#ifdef USE_TINYUSB
#include <Adafruit_TinyUSB.h>
#endif
#include <Arduino.h>
extern "C"
int _write(int file, char * buf, int bytes) {
if (file != 1 && file != 2) return -1;
(void)file;
static char initted = 0;
if (!initted) {
Serial.begin(9600);
while (!Serial) __WFI();
initted = 1;
}
if (!Serial.dtr()) NVIC_SystemReset();
Serial.write(buf, bytes);
return bytes;
}
#elif defined(__AVR__)
#include <avr/io.h>
#include <stdio.h>
#ifndef BAUD
#define BAUD 9600
#endif
#include <util/setbaud.h>
static int uart_putchar(char c, FILE * stream __attribute((unused))) {
static char initted = 0;
if (!initted) {
initted = 1;
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
UCSR0A &= ~(1 << U2X0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8-bit data */
UCSR0B = (1 << TXEN0); /* enable tx only */
}
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return c;
}
/* inefficient but required due to incompatibilities between avr-libc and c++ */
__attribute((constructor)) static void init(void) {
static FILE uart_output;
stdout = &uart_output;
fdev_setup_stream(stdout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
}
#endif
/* this must be included before any other headers, or not at all */
#include <Arduino.h>
static const unsigned long interval_milliseconds = 1000;
void setup() {
/* function-like macro, which calls a c++ wrapper with c linkage, which interacts with Serial.print() for us */
printf("hello world from %s\n", __func__);
}
void loop() {
static unsigned long prev;
const unsigned long now = millis();
/* wait until interval_milliseconds since the previous wakeup */
if (now - prev < interval_milliseconds) return;
/* note we do this instead of prev = now s.t. error doesn't accumulate over time */
prev += interval_milliseconds;
printf("now = %lu ms\n", now);
}
/* this file can be empty, but will be compiled the same as a .cpp with #include <Arduino.h> at the top if not */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment