Fri, 20 Oct 2023 20:29:52 +0200
Begin coding transmit bits.
/** * @file task_dcf.c * @brief DCF77 task. */ #include "dcf77tx.h" static const char *TAG = "task_dcf"; 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 const int TASK_DCF_REQUEST_START = BIT0; const int TASK_DCF_REQUEST_STOP = BIT1; const int TASK_DCF_RUN = BIT2; bool ready_DCF(void) { return dcf_state->DCF_running; } 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; } } } void task_DCF(void *pvParameters) { ESP_LOGI(TAG, "Starting DCF77"); xEventGroupDCF = xEventGroupCreate(); xSemaphoreDCF = xSemaphoreCreateMutex(); dcf_state = malloc(sizeof(DCF_State)); memset(dcf_state, 0x00, sizeof(DCF_State)); gpio_reset_pin(LED1); gpio_reset_pin(LED2); 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; for (;;) { uxBits = xEventGroupWaitBits(xEventGroupDCF, TASK_DCF_REQUEST_START | TASK_DCF_REQUEST_STOP, pdFALSE, pdFALSE, portMAX_DELAY ); if (uxBits & TASK_DCF_REQUEST_START) { if (dcf_state->DCF_running) { /* Already running */ } 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(;;) */ }