Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions dcf77.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,42 @@ namespace Internal {
Clock_Controller::process_1_kHz_tick_data(the_input_provider());
}
#endif

#if defined(ARDUINO_ARCH_ESP32)
hw_timer_t *timer = NULL;
const uint32_t GPTimer_freq = 16000000;
const uint32_t ticks_per_ms = GPTimer_freq/1000;
const uint32_t ticks_per_us = ticks_per_ms/1000;

void setup(const Clock::input_provider_t input_provider) {
timer = timerBegin(GPTimer_freq); // Set timer frequency to 16Mhz, 0,0625 us tick
timerAttachInterrupt(timer, &isr_handler);
timerAlarm(timer, ticks_per_ms, true, 0); // call isr_handler function onetime after 1000 microseconds
the_input_provider = input_provider;
}

// 1000 / 16 000 000 = 1 / 16 000
const uint16_t inverse_timer_resolution = 16000;

void ARDUINO_ISR_ATTR isr_handler() {
cumulated_phase_deviation += adjust_pp16m;
if (cumulated_phase_deviation >= inverse_timer_resolution) {
cumulated_phase_deviation -= inverse_timer_resolution;
// cumulated drift exceeds microsecond)
// drop microsecond step to realign
timerAlarm(timer, ticks_per_ms - ticks_per_us, true, 0);
} else if (cumulated_phase_deviation <= -inverse_timer_resolution) {
cumulated_phase_deviation += inverse_timer_resolution;
// cumulated drift exceeds 1 microsecond
// insert one microsecond to realign
timerAlarm(timer, ticks_per_ms + ticks_per_us, true, 0);
} else {
timerAlarm(timer, ticks_per_ms, true, 0);
}

Clock_Controller::process_1_kHz_tick_data(the_input_provider());
}
#endif
}
}

Expand Down
21 changes: 19 additions & 2 deletions dcf77.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,17 @@ struct Configuration {

// the constant(s) below are assumed to be configured by the user of the library

#if defined(ARDUINO_ARCH_ESP32)
//Low memory footprint default for ESP32
static const bool want_high_phase_lock_resolution = false;
#else
static const bool want_high_phase_lock_resolution = true;
//const bool want_high_phase_lock_resolution = false;
#endif

// end of configuration section, the stuff below
// will compute the implications of the desired configuration,
// ready for the compiler to consume
#if defined(__arm__)
#if defined(__arm__) || defined(ARDUINO_ARCH_ESP32)
static const bool has_lots_of_memory = true;
#else
static const bool has_lots_of_memory = false;
Expand Down Expand Up @@ -553,6 +557,19 @@ namespace Internal {
#warning Compiling for Linux target only supported for unit test purposes. Only fake support for atomic sections. Please take care.

#define CRITICAL_SECTION for (int __n = 1; __n; __n = 0)
#elif defined(ARDUINO_ARCH_ESP32)
#warning Experimental ESP32 support using espressif arduino-esp32
// Inspired by
// --> https://github.com/wizard97/SimplyAtomic/blob/master/esp32.h
static __inline__ void SA_iRestore(const uint32_t *__s){
XTOS_RESTORE_INTLEVEL(*__s);
}

// Note value can be 0-15, 0 = Enable all interrupts, 15 = no interrupts
#define SA_ATOMIC_RESTORESTATE uint32_t _sa_saved \
__attribute__((__cleanup__(SA_iRestore))) = XTOS_DISABLE_LOWPRI_INTERRUPTS

#define CRITICAL_SECTION for ( SA_ATOMIC_RESTORESTATE, _sa_done = 1; _sa_done; _sa_done = 0 )
#else
#error Unsupported controller architecture
#endif
Expand Down