v1.7..152: DCF77 fixes (experimental)
This commit is contained in:
parent
39e2df7a05
commit
17cd82da68
@ -15,10 +15,6 @@
|
||||
#include "rtctime.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_DCF77
|
||||
#include "dcf77.h"
|
||||
#endif
|
||||
|
||||
void doHousekeeping(void);
|
||||
uint64_t uptime(void);
|
||||
void reset_counters(void);
|
||||
|
@ -102,6 +102,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble,
|
||||
batt_voltage; // display values
|
||||
extern hw_timer_t *sendCycle, *displaytimer;
|
||||
extern SemaphoreHandle_t I2Caccess;
|
||||
extern bool volatile BitsPending;
|
||||
|
||||
extern std::set<uint16_t, std::less<uint16_t>, Mallocator<uint16_t>> macs;
|
||||
extern std::array<uint64_t, 0xff>::iterator it;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
; ---> SELECT TARGET PLATFORM HERE! <---
|
||||
[platformio]
|
||||
;env_default = generic
|
||||
env_default = generic
|
||||
;env_default = ebox
|
||||
;env_default = eboxtube
|
||||
;env_default = heltec
|
||||
@ -24,16 +24,16 @@
|
||||
;env_default = lolin32lora
|
||||
;env_default = lolin32lite
|
||||
;env_default = octopus32
|
||||
env_default = ebox, eboxtube, heltec, ttgobeam, lopy4, lopy, ttgov21old, ttgov21new, ttgofox
|
||||
;env_default = ebox, eboxtube, heltec, ttgobeam, lopy4, lopy, ttgov21old, ttgov21new, ttgofox
|
||||
;
|
||||
description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around.
|
||||
|
||||
[common]
|
||||
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
||||
release_version = 1.7.143
|
||||
release_version = 1.7.152
|
||||
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
||||
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
||||
debug_level = 3
|
||||
debug_level = 0
|
||||
; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA
|
||||
upload_protocol = esptool
|
||||
;upload_protocol = custom
|
||||
@ -45,9 +45,9 @@ monitor_speed = 115200
|
||||
lib_deps_lora =
|
||||
MCCI LoRaWAN LMIC library@^2.3.1
|
||||
lib_deps_display =
|
||||
U8g2@>=2.25.5
|
||||
U8g2@>=2.25.7
|
||||
lib_deps_rgbled =
|
||||
SmartLeds@>=1.1.3
|
||||
SmartLeds@>=1.1.5
|
||||
lib_deps_gps =
|
||||
TinyGPSPlus@>=1.0.2
|
||||
lib_deps_rtc =
|
||||
|
@ -83,11 +83,6 @@ void doHousekeeping() {
|
||||
bme_status.temperature, bme_status.iaq, bme_status.iaq_accuracy);
|
||||
#endif
|
||||
|
||||
// generate DCF77 timeframes
|
||||
#ifdef HAS_DCF77
|
||||
sendDCF77();
|
||||
#endif
|
||||
|
||||
// check free heap memory
|
||||
if (ESP.getMinFreeHeap() <= MEM_LOW) {
|
||||
ESP_LOGI(TAG,
|
||||
|
209
src/dcf77.cpp
209
src/dcf77.cpp
@ -1,13 +1,10 @@
|
||||
//
|
||||
// source:
|
||||
// https://www.elektormagazine.com/labs/dcf77-emulator-with-esp8266-elektor-labs-version-150713
|
||||
//
|
||||
/*
|
||||
Simulate a DCF77 radio receiver
|
||||
Emit a complete three minute pulses train from the GPIO output
|
||||
the train is preceded by a single pulse and the lacking 59th pulse to allow
|
||||
some clock model syncronization of the beginning frame. After the three pulses
|
||||
train one more single pulse is sent to safely close the frame
|
||||
// Emulate a DCF77 radio receiver
|
||||
//
|
||||
// parts of this code werde adapted from source:
|
||||
//
|
||||
https://www.elektormagazine.com/labs/dcf77-emulator-with-esp8266-elektor-labs-version-150713
|
||||
//
|
||||
*/
|
||||
|
||||
#if defined HAS_DCF77
|
||||
@ -18,11 +15,9 @@
|
||||
static const char TAG[] = "main";
|
||||
|
||||
TaskHandle_t DCF77Task;
|
||||
QueueHandle_t DCFSendQueue;
|
||||
hw_timer_t *dcfCycle = NULL;
|
||||
|
||||
#define DCF77_FRAME_SIZE 60
|
||||
#define DCF_FRAME_QUEUE_SIZE (HOMECYCLE / 60 + 1)
|
||||
|
||||
// array of dcf pulses for three minutes
|
||||
uint8_t DCFtimeframe[DCF77_FRAME_SIZE];
|
||||
@ -30,84 +25,31 @@ uint8_t DCFtimeframe[DCF77_FRAME_SIZE];
|
||||
// initialize and configure DCF77 output
|
||||
int dcf77_init(void) {
|
||||
|
||||
DCFSendQueue = xQueueCreate(DCF_FRAME_QUEUE_SIZE,
|
||||
sizeof(DCFtimeframe) / sizeof(DCFtimeframe[0]));
|
||||
if (!DCFSendQueue) {
|
||||
ESP_LOGE(TAG, "Could not create DCF77 send queue. Aborting.");
|
||||
return 0; // failure
|
||||
}
|
||||
ESP_LOGI(TAG, "DCF77 send queue created, size %d Bytes",
|
||||
DCF_FRAME_QUEUE_SIZE * sizeof(DCFtimeframe) /
|
||||
sizeof(DCFtimeframe[0]));
|
||||
|
||||
pinMode(HAS_DCF77, OUTPUT);
|
||||
digitalWrite(HAS_DCF77, LOW);
|
||||
digitalWrite(HAS_DCF77, HIGH);
|
||||
|
||||
xTaskCreatePinnedToCore(dcf77_loop, // task function
|
||||
"dcf77loop", // name of task
|
||||
2048, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
3, // priority of the task
|
||||
&DCF77Task, // task handle
|
||||
0); // CPU core
|
||||
|
||||
assert(DCF77Task); // has dcf77 task started?
|
||||
|
||||
// setup 100ms clock signal for DCF77 generator using esp32 hardware timer 1
|
||||
ESP_LOGD(TAG, "Starting DCF pulse...");
|
||||
dcfCycle = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
|
||||
timerAttachInterrupt(dcfCycle, &DCF77IRQ, true);
|
||||
timerAlarmWrite(dcfCycle, 2000, true); // 100ms cycle
|
||||
timerAlarmEnable(dcfCycle);
|
||||
xTaskNotify(DCF77Task, 0, eNoAction);
|
||||
|
||||
return 1; // success
|
||||
|
||||
} // ifdcf77_init
|
||||
|
||||
// called every 100msec for DCF77 output
|
||||
void DCF_Ticker() {
|
||||
|
||||
static uint8_t DCF_Frame[DCF77_FRAME_SIZE];
|
||||
static uint8_t bit = 0;
|
||||
static uint8_t pulse = 0;
|
||||
static bool BitsPending = false;
|
||||
|
||||
while (BitsPending) {
|
||||
switch (pulse++) {
|
||||
|
||||
case 0: // start of second -> start of timeframe for logic signal
|
||||
if (DCF_Frame[bit] != dcf_off)
|
||||
digitalWrite(HAS_DCF77, LOW);
|
||||
return;
|
||||
|
||||
case 1: // 100ms after start of second -> end of timeframe for logic 0
|
||||
if (DCF_Frame[bit] == dcf_zero)
|
||||
digitalWrite(HAS_DCF77, HIGH);
|
||||
return;
|
||||
|
||||
case 2: // 200ms after start of second -> end of timeframe for logic signal
|
||||
digitalWrite(HAS_DCF77, HIGH);
|
||||
return;
|
||||
|
||||
case 9: // last pulse before next second starts
|
||||
pulse = 0;
|
||||
if (bit++ != DCF77_FRAME_SIZE)
|
||||
return;
|
||||
else { // last pulse of DCF77 frame (59th second)
|
||||
bit = 0;
|
||||
BitsPending = false;
|
||||
};
|
||||
break;
|
||||
|
||||
}; // switch
|
||||
}; // while
|
||||
|
||||
// get next frame to send from queue
|
||||
if (xQueueReceive(DCFSendQueue, &DCF_Frame, (TickType_t)0) == pdTRUE)
|
||||
BitsPending = true;
|
||||
|
||||
} // DCF_Ticker()
|
||||
|
||||
void dcf77_loop(void *pvParameters) {
|
||||
|
||||
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||
|
||||
// task remains in blocked state until it is notified by isr
|
||||
for (;;) {
|
||||
xTaskNotifyWait(
|
||||
0x00, // don't clear any bits on entry
|
||||
ULONG_MAX, // clear all bits on exit
|
||||
NULL,
|
||||
portMAX_DELAY); // wait forever (missing error handling here...)
|
||||
|
||||
DCF_Ticker();
|
||||
}
|
||||
vTaskDelete(DCF77Task); // shoud never be reached
|
||||
} // dcf77_loop()
|
||||
|
||||
uint8_t dec2bcd(uint8_t dec, uint8_t startpos, uint8_t endpos,
|
||||
uint8_t pArray[]) {
|
||||
|
||||
@ -123,7 +65,7 @@ uint8_t dec2bcd(uint8_t dec, uint8_t startpos, uint8_t endpos,
|
||||
return parity;
|
||||
}
|
||||
|
||||
void enqueueTimeframe(time_t t) {
|
||||
void generateTimeframe(time_t t) {
|
||||
|
||||
uint8_t ParityCount;
|
||||
|
||||
@ -156,21 +98,7 @@ void enqueueTimeframe(time_t t) {
|
||||
|
||||
// ENCODE TAIL (bit 59)
|
||||
DCFtimeframe[59] = dcf_off;
|
||||
// --> missing code here for switching second!
|
||||
/*
|
||||
In unregelmäßigen Zeitabständen muss eine Schaltsekunde eingefügt werden. Dies
|
||||
ist dadurch bedingt, dass sich die Erde nicht genau in 24 Stunden um sich
|
||||
selbst dreht. Auf die koordinierte Weltzeitskala UTC bezogen, wird diese
|
||||
Korrektur zum Ende der letzten Stunde des 31. Dezember oder 30. Juni
|
||||
vorgenommen. In Mitteleuropa muss die Schaltsekunde daher am 1. Januar um 1.00
|
||||
Uhr MEZ oder am 1.Juli um 2.00 MESZ eingeschoben werden. Zu den genannten
|
||||
Zeiten werden daher 61 Sekunden gesendet.
|
||||
*/
|
||||
|
||||
// post generated DCFtimeframe data to DCF SendQueue
|
||||
if (xQueueSendToBack(DCFSendQueue, (void *)&DCFtimeframe[0], (TickType_t)0) !=
|
||||
pdPASS)
|
||||
ESP_LOGE(TAG, "Failed to send DCF data");
|
||||
// !! missing code here for leap second !!
|
||||
|
||||
// for debug: print the DCF77 frame buffer
|
||||
char out[DCF77_FRAME_SIZE + 1];
|
||||
@ -179,41 +107,80 @@ void enqueueTimeframe(time_t t) {
|
||||
out[i] = DCFtimeframe[i] + '0'; // convert int digit to printable ascii
|
||||
}
|
||||
out[DCF77_FRAME_SIZE] = '\0'; // string termination char
|
||||
ESP_LOGD(TAG, "DCF=%s", out);
|
||||
ESP_LOGD(TAG, "DCF Timeframe = %s", out);
|
||||
}
|
||||
|
||||
void sendDCF77() {
|
||||
// called every 100msec by hardware time
|
||||
void DCF_Out() {
|
||||
|
||||
time_t t = now();
|
||||
static uint8_t bit = 0;
|
||||
static uint8_t pulse = 0;
|
||||
|
||||
/*
|
||||
if (second(t) > 56) {
|
||||
delay(30000);
|
||||
if (!BitsPending) {
|
||||
// prepare next frame to send
|
||||
generateTimeframe(now());
|
||||
BitsPending = true;
|
||||
// wait until next minute, then kick off hardware timer and first DCF pulse
|
||||
do {
|
||||
delay(2);
|
||||
} while (second());
|
||||
}
|
||||
|
||||
// ticker out current frame
|
||||
while (BitsPending) {
|
||||
switch (pulse++) {
|
||||
|
||||
case 0: // start of second -> start of timeframe for logic signal
|
||||
if (DCFtimeframe[bit] != dcf_off)
|
||||
digitalWrite(HAS_DCF77, LOW);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// enqueue DCF timeframes for each i minute
|
||||
for (uint8_t i = 0; i < DCF_FRAME_QUEUE_SIZE; i++)
|
||||
enqueueTimeframe(t + i * 60);
|
||||
case 1: // 100ms after start of second -> end of timeframe for logic 0
|
||||
if (DCFtimeframe[bit] == dcf_zero)
|
||||
digitalWrite(HAS_DCF77, HIGH);
|
||||
return;
|
||||
|
||||
/*
|
||||
// how many to the minute end ?
|
||||
// don't forget that we begin transmission at second 58
|
||||
delay((58 - second(t)) * 1000);
|
||||
case 2: // 200ms after start of second -> end of timeframe for logic 1
|
||||
digitalWrite(HAS_DCF77, HIGH);
|
||||
return;
|
||||
|
||||
// three minutes are needed to transmit all the packet
|
||||
// then wait more 30 secs to locate safely at the half of minute
|
||||
// NB 150+60=210sec, 60secs are lost from main routine
|
||||
delay(150000);
|
||||
*/
|
||||
case 9: // last pulse before next second starts
|
||||
pulse = 0;
|
||||
if (bit++ != DCF77_FRAME_SIZE)
|
||||
return;
|
||||
else { // end of DCF77 frame (59th second)
|
||||
bit = 0;
|
||||
BitsPending = false;
|
||||
};
|
||||
break;
|
||||
|
||||
} // Ende ReadAndDecodeTime()
|
||||
}; // switch
|
||||
}; // while
|
||||
|
||||
} // DCF_Out()
|
||||
|
||||
// interrupt service routine triggered each 100ms by ESP32 hardware timer
|
||||
void IRAM_ATTR DCF77IRQ() {
|
||||
xTaskNotifyFromISR(DCF77Task, xTaskGetTickCountFromISR(), eSetBits, NULL);
|
||||
xTaskNotifyFromISR(DCF77Task, 0, eNoAction, NULL);
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
void dcf77_loop(void *pvParameters) {
|
||||
|
||||
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||
|
||||
// task remains in blocked state until it is notified by isr
|
||||
for (;;) {
|
||||
xTaskNotifyWait(
|
||||
0x00, // don't clear any bits on entry
|
||||
ULONG_MAX, // clear all bits on exit
|
||||
NULL,
|
||||
portMAX_DELAY); // wait forever (missing error handling here...)
|
||||
|
||||
DCF_Out();
|
||||
}
|
||||
BitsPending = false; // stop blink in display
|
||||
vTaskDelete(DCF77Task); // shoud never be reached
|
||||
} // dcf77_loop()
|
||||
|
||||
#endif // HAS_DCF77
|
@ -145,14 +145,14 @@ void refreshtheDisplay() {
|
||||
|
||||
uint8_t msgWaiting;
|
||||
char buff[16]; // 16 chars line buffer
|
||||
#if defined HAS_RTC || defined HAS_GPS
|
||||
#if (defined HAS_DCF77) || (defined HAS_IF482)
|
||||
const char timeNosyncSymbol = '?';
|
||||
#if defined HAS_IF482 || defined HAS_DCF77
|
||||
#if (defined HAS_IF482)
|
||||
const char timesyncSymbol = '+';
|
||||
#else
|
||||
const char timesyncSymbol = '*';
|
||||
#endif
|
||||
#endif // HAS_RTC
|
||||
#endif
|
||||
|
||||
// update counter (lines 0-1)
|
||||
snprintf(
|
||||
@ -217,21 +217,20 @@ void refreshtheDisplay() {
|
||||
|
||||
#ifdef HAS_LORA
|
||||
u8x8.setCursor(0, 6);
|
||||
#if (!defined HAS_RTC) && (!defined HAS_GPS)
|
||||
#if (!defined HAS_DCF77) && (!defined HAS_IF482)
|
||||
// update LoRa status display (line 6)
|
||||
u8x8.printf("%-16s", display_line6);
|
||||
#else // HAS_RTC or HAS_GPS
|
||||
#else // we want a time display instead LoRa status
|
||||
// update time/date display (line 6)
|
||||
time_t t = myTZ.toLocal(now());
|
||||
char timeState =
|
||||
timeStatus() == timeSet ? timesyncSymbol : timeNosyncSymbol;
|
||||
#ifdef RTC_INT // make timestatus symbol blinking if pps line
|
||||
if (second(t) % 2)
|
||||
// make timestatus symbol blinking if pps line
|
||||
if ((BitsPending) && (second(t) % 2))
|
||||
timeState = ' ';
|
||||
#endif // RTC_INT
|
||||
u8x8.printf("%02d:%02d:%02d%c %2d.%3s", hour(t), minute(t), second(t),
|
||||
timeState, day(t), printmonth[month(t)]);
|
||||
#endif // HAS_RTC
|
||||
#endif
|
||||
|
||||
// update LMiC event display (line 7)
|
||||
u8x8.setCursor(0, 7);
|
||||
|
@ -103,7 +103,20 @@ int if482_init(void) {
|
||||
ESP_LOGE(TAG, "I2c bus busy - IF482 initialization error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
xTaskCreatePinnedToCore(if482_loop, // task function
|
||||
"if482loop", // name of task
|
||||
2048, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
3, // priority of the task
|
||||
&IF482Task, // task handle
|
||||
0); // CPU core
|
||||
|
||||
assert(IF482Task); // has if482loop task started?
|
||||
// setup external interupt for active low RTC INT pin
|
||||
pinMode(RTC_INT, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(RTC_INT), IF482IRQ, FALLING);
|
||||
|
||||
return 1;
|
||||
|
||||
} // if482_init
|
||||
@ -134,6 +147,8 @@ String if482Telegram(time_t tt) {
|
||||
month(t), day(t), weekday(t), hour(t), minute(t), second(t));
|
||||
|
||||
snprintf(out, sizeof out, "O%cL%s\r", mon, buf);
|
||||
ESP_LOGD(TAG, "IF482 = %s", out);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -152,6 +167,8 @@ void if482_loop(void *pvParameters) {
|
||||
do {
|
||||
tt = now();
|
||||
} while (t == tt);
|
||||
|
||||
BitsPending = true; // start blink in display
|
||||
|
||||
// take timestamp at moment of start of new second
|
||||
const TickType_t shotTime = xTaskGetTickCount() - startTime - timeOffset;
|
||||
@ -169,6 +186,7 @@ void if482_loop(void *pvParameters) {
|
||||
vTaskDelayUntil(&wakeTime, shotTime); // sets waketime to moment of shot
|
||||
IF482.print(if482Telegram(now() + 1));
|
||||
}
|
||||
BitsPending = false; // stop blink in display
|
||||
vTaskDelete(IF482Task); // shoud never be reached
|
||||
} // if482_loop()
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
// faster or slower. This causes the transceiver to be earlier switched on,
|
||||
// so consuming more power. You may sharpen (reduce) this value if you are
|
||||
// limited on battery.
|
||||
#define CLOCK_ERROR_PROCENTAGE 30
|
||||
#define CLOCK_ERROR_PROCENTAGE 3
|
||||
|
||||
// Set this to 1 to enable some basic debug output (using printf) about
|
||||
// RF settings used during transmission and reception. Set to 2 to
|
||||
|
43
src/main.cpp
43
src/main.cpp
@ -34,7 +34,7 @@ spiloop 0 2 reads/writes data on spi interface
|
||||
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
||||
|
||||
looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
||||
irqhandler 1 1 executes tasks triggered by irq
|
||||
irqhandler 1 1 executes tasks triggered by hw irq, see table below
|
||||
gpsloop 1 2 reads data from GPS via serial or i2c
|
||||
bmeloop 1 1 reads data from BME sensor via i2c
|
||||
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
||||
@ -44,7 +44,7 @@ Low priority numbers denote low priority tasks.
|
||||
Tasks using i2c bus all must have same priority, because using mutex semaphore
|
||||
(irqhandler, bmeloop)
|
||||
|
||||
ESP32 hardware timers
|
||||
ESP32 hardware irq timers
|
||||
================================
|
||||
0 triggers display refresh
|
||||
1 triggers DCF77 clock signal
|
||||
@ -65,6 +65,7 @@ char display_line6[16], display_line7[16]; // display buffers
|
||||
uint8_t volatile channel = 0; // channel rotation counter
|
||||
uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
|
||||
batt_voltage = 0; // globals for display
|
||||
bool volatile BitsPending = false; // DCF77 or IF482 ticker indicator
|
||||
|
||||
hw_timer_t *sendCycle = NULL, *homeCycle = NULL;
|
||||
#ifdef HAS_DISPLAY
|
||||
@ -97,7 +98,7 @@ void setup() {
|
||||
char features[100] = "";
|
||||
|
||||
I2Caccess = xSemaphoreCreateMutex(); // for access management of i2c bus
|
||||
if ((I2Caccess) != NULL)
|
||||
if (I2Caccess)
|
||||
xSemaphoreGive((I2Caccess)); // Flag the i2c bus available for use
|
||||
|
||||
// disable brownout detection
|
||||
@ -334,7 +335,6 @@ void setup() {
|
||||
|
||||
#if defined HAS_DCF77
|
||||
strcat_P(features, " DCF77");
|
||||
assert(dcf77_init());
|
||||
#endif
|
||||
|
||||
#if defined HAS_IF482 && defined RTC_INT
|
||||
@ -417,37 +417,14 @@ void setup() {
|
||||
setSyncInterval(TIME_SYNC_INTERVAL_GPS * 60);
|
||||
#endif
|
||||
|
||||
#if defined HAS_IF482 && defined RTC_INT
|
||||
#if defined HAS_IF482 && defined DCF_77
|
||||
#error "You may define at most one of HAS_IF482 or DCF_77"
|
||||
#elif defined HAS_IF482 && defined RTC_INT
|
||||
ESP_LOGI(TAG, "Starting IF482 Generator...");
|
||||
xTaskCreatePinnedToCore(if482_loop, // task function
|
||||
"if482loop", // name of task
|
||||
2048, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
3, // priority of the task
|
||||
&IF482Task, // task handle
|
||||
0); // CPU core
|
||||
|
||||
// setup external interupt for active low RTC INT pin
|
||||
assert(IF482Task != NULL); // has if482loop task started?
|
||||
attachInterrupt(digitalPinToInterrupt(RTC_INT), IF482IRQ, FALLING);
|
||||
#endif
|
||||
|
||||
#if defined HAS_DCF77
|
||||
assert(if482_init());
|
||||
#elif defined HAS_DCF77
|
||||
ESP_LOGI(TAG, "Starting DCF77 Generator...");
|
||||
xTaskCreatePinnedToCore(dcf77_loop, // task function
|
||||
"dcf77loop", // name of task
|
||||
2048, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
3, // priority of the task
|
||||
&DCF77Task, // task handle
|
||||
0); // CPU core
|
||||
|
||||
// setup 100ms clock signal for DCF77 generator using esp32 hardware timer 1
|
||||
assert(DCF77Task != NULL); // has dcf77 task started?
|
||||
dcfCycle = timerBegin(1, 8000, true);
|
||||
timerAttachInterrupt(dcfCycle, &DCF77IRQ, true);
|
||||
timerAlarmWrite(dcfCycle, 1000, true);
|
||||
timerAlarmEnable(dcfCycle);
|
||||
assert(dcf77_init());
|
||||
#endif
|
||||
|
||||
} // setup()
|
||||
|
Loading…
Reference in New Issue
Block a user