diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-06-29 18:48:05 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-06-29 18:48:05 +0200 |
commit | cc0301784156543c7c9bec36b6f42df1d2adba28 (patch) | |
tree | 02b0d45518bfc53bafdf011320d4309b7f218ba0 /src/common/GPS/gps.c | |
parent | f19631d2a66d01c0cdd85134c5eb63a1da42b34a (diff) | |
download | glutte-o-matic-cc0301784156543c7c9bec36b6f42df1d2adba28.tar.gz glutte-o-matic-cc0301784156543c7c9bec36b6f42df1d2adba28.tar.bz2 glutte-o-matic-cc0301784156543c7c9bec36b6f42df1d2adba28.zip |
Change common/ folder structure
Diffstat (limited to 'src/common/GPS/gps.c')
-rw-r--r-- | src/common/GPS/gps.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/common/GPS/gps.c b/src/common/GPS/gps.c new file mode 100644 index 0000000..bfdc1c1 --- /dev/null +++ b/src/common/GPS/gps.c @@ -0,0 +1,166 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Matthias P. Braendli + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*/ + +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "task.h" +#include "semphr.h" +#include "Core/common.h" +#include "GPS/gps.h" +#include "GPS/minmea.h" +#include "GPIO/usart.h" + + +TickType_t gps_timeutc_last_updated = 0; +static struct tm gps_timeutc; +static int gps_num_sv_used; +static int gps_timeutc_valid; // Validity flag for both gps_timeutc and gps_num_sv_used + +const TickType_t gps_data_validity_timeout = GPS_MS_TIMEOUT / portTICK_PERIOD_MS; + +static void gps_task(void *pvParameters); + +SemaphoreHandle_t timeutc_semaphore; + +// Get current time from GPS +int gps_utctime(struct tm *timeutc, int *num_sv_used) +{ + int valid = 0; + + xSemaphoreTake(timeutc_semaphore, portMAX_DELAY); + if (xTaskGetTickCount() - gps_timeutc_last_updated < gps_data_validity_timeout) { + timeutc->tm_year = gps_timeutc.tm_year; + timeutc->tm_mon = gps_timeutc.tm_mon; + timeutc->tm_mday = gps_timeutc.tm_mday; + timeutc->tm_hour = gps_timeutc.tm_hour; + timeutc->tm_min = gps_timeutc.tm_min; + timeutc->tm_sec = gps_timeutc.tm_sec; + *num_sv_used = gps_num_sv_used; + valid = gps_timeutc_valid; + } + + xSemaphoreGive(timeutc_semaphore); + + return valid; +} + +#define RXBUF_LEN MAX_NMEA_SENTENCE_LEN +static char rxbuf[RXBUF_LEN]; + +static void gps_task(void __attribute__ ((unused))*pvParameters) { + + // The initialisation placed the GPS into reset + usart_gps_remove_reset(); + + while (1) { + taskYIELD(); + + int success = usart_get_nmea_sentence(rxbuf); + + if (success) { + const int strict = 1; + switch (minmea_sentence_id(rxbuf, strict)) { + case MINMEA_SENTENCE_RMC: + { + struct minmea_sentence_rmc frame; + if (minmea_parse_rmc(&frame, rxbuf)) { + xSemaphoreTake(timeutc_semaphore, portMAX_DELAY); + // tm_year is saved as Year - 1900 in struct tm + gps_timeutc.tm_year = 2000 + frame.date.year - 1900; + // struct tm months are zero-indexed + gps_timeutc.tm_mon = frame.date.month - 1; + gps_timeutc.tm_mday = frame.date.day; + gps_timeutc.tm_hour = frame.time.hours; + gps_timeutc.tm_min = frame.time.minutes; + gps_timeutc.tm_sec = frame.time.seconds; + gps_timeutc_valid = frame.valid; + gps_timeutc_last_updated = xTaskGetTickCount(); + xSemaphoreGive(timeutc_semaphore); + } + } break; + case MINMEA_SENTENCE_TXT: + { + struct minmea_sentence_txt frame; + if (minmea_parse_txt(&frame, rxbuf)) { + rxbuf[MINMEA_TXT_START_IX + frame.text_len] = '\0'; + + switch (frame.msgtype) { + case MINMEA_GPTXT_ERROR: + usart_debug_puts_header("GPS ERROR ", frame.text); + break; + case MINMEA_GPTXT_WARNING: + usart_debug_puts_header("GPS WARNING ", frame.text); + break; + default: + usart_debug_puts_header("GPS Message ", frame.text); + break; + } + } + } break; + case MINMEA_SENTENCE_GGA: + { + struct minmea_sentence_gga frame; + if (minmea_parse_gga(&frame, rxbuf)) { + xSemaphoreTake(timeutc_semaphore, portMAX_DELAY); + gps_num_sv_used = frame.satellites_tracked; + xSemaphoreGive(timeutc_semaphore); + } + } break; + default: + break; + } + } + } +} + +void gps_init() { + gps_timeutc_valid = 0; + + usart_gps_init(); + + timeutc_semaphore = xSemaphoreCreateBinary(); + + if (timeutc_semaphore == NULL) { + trigger_fault(FAULT_SOURCE_GPS); + } else { + xSemaphoreGive(timeutc_semaphore); + } + + xTaskCreate( + gps_task, + "TaskGPS", + 4*configMINIMAL_STACK_SIZE, + (void*) NULL, + tskIDLE_PRIORITY + 2UL, + NULL); +} + +// Return 1 of the GPS is receiving time +int gps_locked() { + if (xTaskGetTickCount() - gps_timeutc_last_updated < gps_data_validity_timeout) { + return gps_timeutc_valid; + } else { + return 0; + } +} |