OpenRTX/platform/drivers/GPS/GPS_ttwrplus.c

151 wiersze
4.0 KiB
C

/***************************************************************************
* Copyright (C) 2023 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <zephyr/drivers/uart.h>
#include <zephyr/kernel.h>
#include <interfaces/delays.h>
#include <peripherals/gps.h>
#include <hwconfig.h>
#include <string.h>
#include <pmu.h>
#if DT_NODE_HAS_STATUS(DT_ALIAS(gps), okay)
#define UART_GPS_DEV_NODE DT_ALIAS(gps)
#else
#error "Please select the correct gps UART device"
#endif
#define NMEA_MSG_SIZE 82
K_MSGQ_DEFINE(gps_uart_msgq, NMEA_MSG_SIZE, 10, 4);
static const struct device *const gps_dev = DEVICE_DT_GET(UART_GPS_DEV_NODE);
// receive buffer used in UART ISR callback
static char rx_buf[NMEA_MSG_SIZE];
static uint16_t rx_buf_pos;
static void gps_serialCb(const struct device *dev, void *user_data)
{
uint8_t c;
if (uart_irq_update(gps_dev) == false)
return;
if (uart_irq_rx_ready(gps_dev) == false)
return;
// read until FIFO empty
while (uart_fifo_read(gps_dev, &c, 1) == 1)
{
if (c == '$' && rx_buf_pos > 0)
{
// terminate string
rx_buf[rx_buf_pos] = '\0';
// if queue is full, message is silently dropped
k_msgq_put(&gps_uart_msgq, &rx_buf, K_NO_WAIT);
// reset the buffer (it was copied to the msgq)
rx_buf_pos = 0;
rx_buf[rx_buf_pos++] = '$';
}
else if (rx_buf_pos < (sizeof(rx_buf) - 1))
{
rx_buf[rx_buf_pos++] = c;
}
}
}
void gps_init(const uint16_t baud)
{
int ret = 0;
// Check if GPS UART is ready
if (device_is_ready(gps_dev) == false)
{
printk("UART device not found!\n");
return;
}
ret = uart_irq_callback_user_data_set(gps_dev, gps_serialCb, NULL);
if (ret < 0)
{
if (ret == -ENOTSUP)
{
printk("Interrupt-driven UART support not enabled\n");
}
else if (ret == -ENOSYS)
{
printk("UART device does not support interrupt-driven API\n");
}
else
{
printk("Error setting UART callback: %d\n", ret);
}
return;
}
uart_irq_rx_enable(gps_dev);
}
void gps_terminate()
{
gps_disable();
}
void gps_enable()
{
pmu_setGPSPower(true);
}
void gps_disable()
{
pmu_setGPSPower(false);
}
bool gps_detect(uint16_t timeout)
{
return true;
}
int gps_getNmeaSentence(char *buf, const size_t maxLength)
{
k_msgq_get(&gps_uart_msgq, buf, K_FOREVER);
return 0;
}
bool gps_nmeaSentenceReady()
{
return k_msgq_num_used_get(&gps_uart_msgq) != 0;
}
void gps_waitForNmeaSentence()
{
while (k_msgq_num_used_get(&gps_uart_msgq) != 0)
{
sleepFor(0, 100);
}
}