55#include " gps_interface.h"
66
77#include < etl/algorithm.h>
8+ #include < ulog.h>
89
910#include < cmath>
1011
@@ -14,18 +15,26 @@ namespace gps {
1415
1516GpsInterface::GpsInterface () {
1617 datum_lat_ = datum_long_ = NAN;
18+ chMtxObjectInit (&processing_mutex);
1719}
1820bool GpsInterface::start_driver (UARTDriver *uart, uint32_t baudrate) {
1921 chDbgAssert (stopped_, " don't start the driver twice" );
2022 chDbgAssert (uart != nullptr , " need to provide a driver" );
2123 if (!stopped_) {
2224 return false ;
2325 }
24- stopped_ = false ;
2526 this ->uart = uart;
2627 uart_config.speed = baudrate;
27- chThdCreateStatic (&wa, sizeof (wa), NORMALPRIO, GpsInterface::threadHelper, this );
28- return uartStart (uart, &uart_config) == MSG_OK;
28+ bool uartStarted = uartStart (uart, &uart_config) == MSG_OK;
29+ if (!uartStarted) {
30+ return false ;
31+ }
32+
33+ stopped_ = false ;
34+ processing_thread_ = chThdCreateStatic (&wa, sizeof (wa), NORMALPRIO, threadHelper, this );
35+ // Allow higher prio in order to not lose buffers. Active time in this thread is very minimal (it's just swapping buffers)
36+ chThdCreateStatic (&recvThdWa, sizeof (recvThdWa), NORMALPRIO+1 , receivingThreadHelper, this );
37+ return true ;
2938}
3039
3140void GpsInterface::set_state_callback (const GpsInterface::StateCallback &function) {
@@ -45,23 +54,59 @@ bool GpsInterface::send_raw(const void *data, size_t size) {
4554}
4655
4756void GpsInterface::threadFunc () {
48- size_t bytes_to_process = 1 ;
57+ // size_t bytes_to_process = 1;
4958 while (!stopped_) {
59+ // Wait for data to arrive
60+ chEvtWaitAny (ALL_EVENTS);
61+ // Lock the processing buffer and process the data
62+ chMtxLock (&processing_mutex);
5063 // try to read as much as possible in order to not interrupt on single bytes
51- size_t read = sizeof (gps_buffer);
52- uartReceiveTimeout (uart, &read, gps_buffer, TIME_MS2I (100 ));
53- size_t processed = 0 ;
54- while (processed < read) {
55- size_t in = etl::min (bytes_to_process, read-processed);
56- bytes_to_process = process_bytes (gps_buffer+processed, in);
57- processed+=in;
64+ // size_t processed = 0;
65+ // while(processed < processing_buffer_len) {
66+ // const size_t in = etl::min(bytes_to_process, processing_buffer_len-processed);
67+ // bytes_to_process = process_bytes(processing_buffer+processed, in);
68+ // processed+=in;
69+ // }
70+ process_bytes (processing_buffer, processing_buffer_len);
71+ chMtxUnlock (&processing_mutex);
72+ }
73+ }
74+
75+
76+ void GpsInterface::receivingThreadFunc () {
77+ while (!stopped_) {
78+ // try to read as much as possible in order to not interrupt on single bytes
79+ size_t read = RECV_BUFFER_SIZE;
80+ // Get the pointer to the receiving buffer (it's not the processing buffer)
81+ uint8_t * buffer = (processing_buffer == recv_buffer1) ? recv_buffer2 : recv_buffer1;
82+ memset (buffer, 0 , RECV_BUFFER_SIZE);
83+ uartReceiveTimeout (uart, &read, buffer, TIME_S2I (1 ));
84+ // swap buffers and instantly restart DMA
85+ bool locked = chMtxTryLock (&processing_mutex);
86+ if (!locked) {
87+ ULOG_WARNING (" GPS processing too slow to keep up with incoming data" );
88+ chMtxLock (&processing_mutex);
89+ }
90+ // Swap the buffers
91+ processing_buffer = buffer;
92+ processing_buffer_len = read;
93+ chMtxUnlock (&processing_mutex);
94+ // Signal the processing thread
95+ if (processing_thread_) {
96+ chEvtSignal (processing_thread_, 1 );
5897 }
5998 }
6099}
100+
101+
61102void GpsInterface::threadHelper (void *instance) {
62103 auto *gps_interface = static_cast <GpsInterface *>(instance);
63104 gps_interface->threadFunc ();
64105}
106+ void GpsInterface::receivingThreadHelper (void *instance) {
107+ auto *gps_interface = static_cast <GpsInterface *>(instance);
108+ gps_interface->receivingThreadFunc ();
109+ }
65110
66111void GpsInterface::send_rtcm (const uint8_t *data, size_t size) {
67112 send_raw (data, size);
0 commit comments