# HG changeset patch # User Michiel Broek # Date 1697826592 -7200 # Node ID 053649608c09538b31df2709de1cbcf33951275e # Parent 86b275481021cc21aa7f497b16d286c589363e7b Begin coding transmit bits. diff -r 86b275481021 -r 053649608c09 main/dcf77tx.h --- a/main/dcf77tx.h Fri Oct 20 15:57:56 2023 +0200 +++ b/main/dcf77tx.h Fri Oct 20 20:29:52 2023 +0200 @@ -30,6 +30,7 @@ #include "esp_wpa2.h" #include "esp_netif_sntp.h" #include "esp_sntp.h" +#include "esp_timer.h" #include "nvs_flash.h" diff -r 86b275481021 -r 053649608c09 main/task_dcf.c --- a/main/task_dcf.c Fri Oct 20 15:57:56 2023 +0200 +++ b/main/task_dcf.c Fri Oct 20 20:29:52 2023 +0200 @@ -13,6 +13,15 @@ SemaphoreHandle_t xSemaphoreDCF = NULL; ///< Semaphore DCF task. EventGroupHandle_t xEventGroupDCF; ///< Events DCF task. DCF_State *dcf_state = NULL; ///< Public state for other tasks. +esp_timer_handle_t timerHandle; ///< Timer handler +int impulseCount = 0; ///< 100 mSec transmit slices. +int8_t impulseArray[61]; ///< Pulses, 0 = no pulse, 1=100ms, 2=200ms +int actualSecond = 0; ///< Current second to transmit. +time_t dcf_now; ///< Current time to send. +struct tm dcf_tm; ///< Local broken down time. + /// +extern bool System_TimeOk; + #define LED1 CONFIG_LED1_PIN #define LED2 CONFIG_LED2_PIN @@ -33,6 +42,100 @@ void request_DCF(bool run) { + ESP_LOGI(TAG, "request_DCF(%s)", run ? "start":"stop"); + + if (run) + xEventGroupSetBits(xEventGroupDCF, TASK_DCF_REQUEST_START); + else + xEventGroupSetBits(xEventGroupDCF, TASK_DCF_REQUEST_STOP); +} + + +int bin2bcd(int data) +{ + int msb, lsb; + + if (data < 10) + return data; + msb = (data / 10) << 4; + lsb = data % 10; + return msb + lsb; +} + + +static void DCFout(void* arg); +void DCFout(void* arg) +{ + int i, tmp, parity; + + switch (impulseCount++) { + case 0: if (actualSecond == 0) { + time(&dcf_now); + dcf_now += 60; + } + if (impulseArray[actualSecond] != 0) { + gpio_set_level(CONFIG_LED1_PIN, 1); + } + break; + case 1: if (impulseArray[actualSecond] == 1) { + gpio_set_level(CONFIG_LED1_PIN, 0); + } + break; + case 2: gpio_set_level(CONFIG_LED1_PIN, 0); + break; + case 9: impulseCount = 0; + /* + * To spread the CPU load, we set all bits during the first seconds + * because we don't use these bits. + */ + switch (actualSecond) { + case 0: /* the first 20 bits of each minute at a logical zero value */ + for (i = 0; i < 20; i++) + impulseArray[i] = 1; + break; + case 1: localtime_r(&dcf_now, &dcf_tm); + char strftime_buf[64]; + strftime(strftime_buf, sizeof(strftime_buf), "%c", &dcf_tm); + ESP_LOGI(TAG, "The current date/time to send is: %s", strftime_buf); + break; + case 2: /* DST bits */ + if (dcf_tm.tm_isdst == 0) { + impulseArray[17] = 1; + impulseArray[18] = 2; + } else { + impulseArray[17] = 2; + impulseArray[18] = 1; + } + /* bit 20 must be 1 to indicate active time */ + impulseArray[20] = 2; + break; + case 3: int minute = bin2bcd(dcf_tm.tm_min); + parity = 0; + for (i = 21; i < 28; i++) { + tmp = minute & 1; + impulseArray[i] = tmp + 1; + parity += tmp; + minute >>= 1; + } + impulseArray[28] = (parity & 1) ? 2:1; + ESP_LOGI(TAG, "minute %d%d%d%d%d%d%d %d", impulseArray[21], impulseArray[22], impulseArray[23], + impulseArray[24], impulseArray[25], impulseArray[26], impulseArray[27], impulseArray[28]); + break; + + + } + if (actualSecond < 59) /* Can include leap second */ + actualSecond++; + break; + } + + if (actualSecond >= 59) { + time_t now = time(NULL); + localtime_r(&now, &dcf_tm); + if (dcf_tm.tm_sec == 0) { + actualSecond = impulseCount = 0; + } + } } @@ -51,6 +154,16 @@ gpio_set_direction(LED1, GPIO_MODE_OUTPUT); gpio_set_direction(LED2, GPIO_MODE_OUTPUT); + esp_timer_create_args_t timerDCF = { + .callback = &DCFout, + .name = "DCF timer" + }; + esp_timer_create(&timerDCF, &timerHandle); + + for (int i = 0; i < 59; i++) + impulseArray[i] = 1; + impulseArray[59] = impulseArray[60] = 0; + xEventGroupClearBits(xEventGroupDCF, TASK_DCF_RUN); EventBits_t uxBits; @@ -60,11 +173,16 @@ if (uxBits & TASK_DCF_REQUEST_START) { if (dcf_state->DCF_running) { /* Already running */ - xEventGroupClearBits(xEventGroupDCF, TASK_DCF_REQUEST_START); + } else { + actualSecond = 0; + impulseCount = 0; + esp_timer_start_periodic(timerHandle, 100000); + dcf_state->DCF_running = true; } + xEventGroupClearBits(xEventGroupDCF, TASK_DCF_REQUEST_START); } else if (uxBits & TASK_DCF_REQUEST_STOP) { - + esp_timer_stop(timerHandle); } } /* for(;;) */ }