kopia lustrzana https://github.com/OpenRTX/OpenRTX
Porównaj commity
8 Commity
8ff4985567
...
55ce31bf63
Autor | SHA1 | Data |
---|---|---|
Wojciech Kaczmarski | 55ce31bf63 | |
Morgan Diepart | d43dd57031 | |
Marco | 70f0ce45d3 | |
Marco | a17ad80f10 | |
Marco | e4a62f30ee | |
Marco | 36ef3b310c | |
Wojciech Kaczmarski | 7966143ba0 | |
Wojciech Kaczmarski | e4cf2e33d9 |
|
@ -80,6 +80,8 @@ jobs:
|
|||
run: meson test -C build "M17 RRC Test"
|
||||
- name: Codeplug Test
|
||||
run: meson test -C build "Codeplug Test"
|
||||
- name: minmea Conversion Test
|
||||
run: meson test -C build "minmea conversion Test"
|
||||
# The following tests are disabled because they appear to be flakey when run in CI
|
||||
# - name: Sine Test
|
||||
# run: meson test -C build "Sine Test"
|
||||
|
|
|
@ -252,6 +252,25 @@ static inline float minmea_tocoord(struct minmea_float *f)
|
|||
return (float) degrees + (float) minutes / (60 * f->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a raw coordinate to a fixed point value.
|
||||
* Returns zero for "unknown" values.
|
||||
*/
|
||||
int minmea_tofixedpoint(struct minmea_float *f);
|
||||
|
||||
|
||||
/**
|
||||
* Convert a fixed-point value to an integer value.
|
||||
* Returns zero for "unknown" values.
|
||||
*/
|
||||
static inline int minmea_toint(struct minmea_float *f)
|
||||
{
|
||||
if(f->scale == 0)
|
||||
return 0;
|
||||
|
||||
return f->value / f->scale;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -642,4 +642,20 @@ int minmea_gettime(struct timespec *ts, const struct minmea_date *date, const st
|
|||
}
|
||||
}
|
||||
|
||||
int minmea_tofixedpoint(struct minmea_float *f) {
|
||||
|
||||
if (f->scale == 0)
|
||||
return 0;
|
||||
|
||||
int32_t value = f->value;
|
||||
int32_t scale = f->scale;
|
||||
int8_t sign = value < 0 ? -1 : 1;
|
||||
// Ensure value is always positive
|
||||
value = value * sign;
|
||||
int32_t coord_int = value / (scale * 100);
|
||||
int32_t coord_dec = (value % (scale * 100)) * (100000 / scale) / 6;
|
||||
return (coord_int * 1000000 + coord_dec) * sign;
|
||||
}
|
||||
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
|
|
@ -880,6 +880,10 @@ vp_test = executable('vp_test',
|
|||
sources : unit_test_src + ['tests/unit/voice_prompts.c'],
|
||||
kwargs : unit_test_opts)
|
||||
|
||||
minmea_conversion_test = executable('minmea_conversion_test',
|
||||
sources : unit_test_src + ['tests/unit/convert_minmea_coord.c'],
|
||||
kwargs : unit_test_opts)
|
||||
|
||||
test('M17 Golay Unit Test', m17_golay_test)
|
||||
test('M17 Viterbi Unit Test', m17_viterbi_test)
|
||||
## test('M17 Demodulator Test', m17_demodulator_test) # Skipped for now as this test no longer works after an M17 refactor
|
||||
|
@ -888,3 +892,4 @@ test('Codeplug Test', cps_test)
|
|||
test('Linux InputStream Test', linux_inputStream_test)
|
||||
test('Sine Test', sine_test)
|
||||
## test('Voice Prompts Test', vp_test) # Skipped for now as this test no longer works
|
||||
test('minmea conversion Test', minmea_conversion_test)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <datetime.h>
|
||||
#include <stdint.h>
|
||||
#include <minmea.h>
|
||||
|
||||
/**
|
||||
* Data structure representing a single satellite as part of a GPS fix.
|
||||
|
@ -47,12 +48,12 @@ typedef struct
|
|||
uint8_t satellites_in_view; // Satellites in view
|
||||
gpssat_t satellites[12]; // Details about satellites in view
|
||||
uint32_t active_sats; // Bitmap representing which sats are part of the fix
|
||||
float latitude; // Latitude coordinates
|
||||
float longitude; // Longitude coordinates
|
||||
float altitude; // Antenna altitude above mean sea level (geoid) in m
|
||||
float speed; // Ground speed in km/h
|
||||
float tmg_mag; // Course over ground, degrees, magnetic
|
||||
float tmg_true; // Course over ground, degrees, true
|
||||
int32_t latitude; // Latitude coordinates
|
||||
int32_t longitude; // Longitude coordinates
|
||||
int16_t altitude; // Antenna altitude above mean sea level (geoid) in m
|
||||
uint16_t speed; // Ground speed in km/h
|
||||
int16_t tmg_mag; // Course over ground, degrees, magnetic
|
||||
int16_t tmg_true; // Course over ground, degrees, true
|
||||
}
|
||||
gps_t;
|
||||
|
||||
|
@ -63,4 +64,5 @@ gps_t;
|
|||
*/
|
||||
void gps_task();
|
||||
|
||||
|
||||
#endif /* GPS_H */
|
||||
|
|
|
@ -59,11 +59,11 @@ public:
|
|||
float operator()(const float& input)
|
||||
{
|
||||
u[0] = input;
|
||||
y[0] = (a/d)*(u[0])
|
||||
+ (b/d)*(u[1])
|
||||
+ (c/d)*(u[2])
|
||||
- (e/d)*(y[1])
|
||||
- (f/d)*(y[2]);
|
||||
y[0] = b[0] * u[0]
|
||||
+ b[1] * u[1]
|
||||
+ b[2] * u[2]
|
||||
- a[1] * y[1]
|
||||
- a[2] * y[2];
|
||||
|
||||
for(size_t i = 2; i > 0; i--)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ public:
|
|||
y[i] = y[i - 1];
|
||||
}
|
||||
|
||||
return y[0] * 0.5f;
|
||||
return y[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,12 +85,13 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
static constexpr float a = 4982680082321166792352.0f;
|
||||
static constexpr float b = -6330013275146484168000.0f;
|
||||
static constexpr float c = 1871109008789062500000.0f;
|
||||
static constexpr float d = 548027992248535162477.0f;
|
||||
static constexpr float e = -24496793746948241250.0f;
|
||||
static constexpr float f = 244617462158203125.0f;
|
||||
static constexpr float b[3]={
|
||||
4.098580379420818f, -5.206850085165959f, 1.539109584496514f
|
||||
};
|
||||
|
||||
static constexpr float a[3]={
|
||||
0.0f, -0.044699895066380f, 0.000446359429843f
|
||||
};
|
||||
|
||||
std::array< float, 3 > u; ///< History of past inputs.
|
||||
std::array< float, 3 > y; ///< History of past outputs.
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define KNOTS2KMH 1.852f
|
||||
#define KNOTS2KMH(x) ((((int) x) * 1852) / 1000)
|
||||
|
||||
static char sentence[2*MINMEA_MAX_LENGTH];
|
||||
static bool gpsEnabled = false;
|
||||
|
@ -90,8 +90,8 @@ void gps_task()
|
|||
struct minmea_sentence_rmc frame;
|
||||
if (minmea_parse_rmc(&frame, sentence))
|
||||
{
|
||||
gps_data.latitude = minmea_tocoord(&frame.latitude);
|
||||
gps_data.longitude = minmea_tocoord(&frame.longitude);
|
||||
gps_data.latitude = minmea_tofixedpoint(&frame.latitude);
|
||||
gps_data.longitude = minmea_tofixedpoint(&frame.longitude);
|
||||
gps_data.timestamp.hour = frame.time.hours;
|
||||
gps_data.timestamp.minute = frame.time.minutes;
|
||||
gps_data.timestamp.second = frame.time.seconds;
|
||||
|
@ -102,7 +102,7 @@ void gps_task()
|
|||
}
|
||||
|
||||
gps_data.tmg_true = minmea_tofloat(&frame.course);
|
||||
gps_data.speed = minmea_tofloat(&frame.speed) * KNOTS2KMH;
|
||||
gps_data.speed = KNOTS2KMH(minmea_toint(&frame.speed));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -113,7 +113,7 @@ void gps_task()
|
|||
{
|
||||
gps_data.fix_quality = frame.fix_quality;
|
||||
gps_data.satellites_tracked = frame.satellites_tracked;
|
||||
gps_data.altitude = minmea_tofloat(&frame.altitude);
|
||||
gps_data.altitude = minmea_toint(&frame.altitude);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -166,9 +166,9 @@ void gps_task()
|
|||
struct minmea_sentence_vtg frame;
|
||||
if (minmea_parse_vtg(&frame, sentence))
|
||||
{
|
||||
gps_data.speed = minmea_tofloat(&frame.speed_kph);
|
||||
gps_data.tmg_mag = minmea_tofloat(&frame.magnetic_track_degrees);
|
||||
gps_data.tmg_true = minmea_tofloat(&frame.true_track_degrees);
|
||||
gps_data.speed = minmea_toint(&frame.speed_kph);
|
||||
gps_data.tmg_mag = minmea_toint(&frame.magnetic_track_degrees);
|
||||
gps_data.tmg_true = minmea_toint(&frame.true_track_degrees);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <utils.h>
|
||||
#include <inttypes.h>
|
||||
#include <ui/ui_default.h>
|
||||
#include <beeps.h>
|
||||
#include "interfaces/cps_io.h"
|
||||
|
@ -549,7 +550,7 @@ void vp_announceM17Info(const channel_t* channel, bool isEditing,
|
|||
|
||||
static bool IsCompassCloseEnoughToCardinalPoint()
|
||||
{
|
||||
float tmg_true = state.gps_data.tmg_true;
|
||||
int16_t tmg_true = state.gps_data.tmg_true;
|
||||
|
||||
return (tmg_true < (0 + margin) || tmg_true > (360 - margin)) || // north
|
||||
(tmg_true > (90 - margin) && tmg_true < (90 + margin)) || // east
|
||||
|
@ -637,7 +638,7 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
|
|||
vp_queuePrompt(PROMPT_COMPASS);
|
||||
if (!IsCompassCloseEnoughToCardinalPoint())
|
||||
{
|
||||
sniprintf(buffer, 16, "%3.1f", state.gps_data.tmg_true);
|
||||
sniprintf(buffer, 16, "%d", state.gps_data.tmg_true);
|
||||
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||
vp_queuePrompt(PROMPT_DEGREES);
|
||||
}
|
||||
|
@ -672,7 +673,7 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
|
|||
if ((gpsInfoFlags & vpGPSSpeed) != 0)
|
||||
{
|
||||
// speed/altitude:
|
||||
sniprintf(buffer, 16, "%4.1fkm/h", state.gps_data.speed);
|
||||
sniprintf(buffer, 16, "%dkm/h", state.gps_data.speed);
|
||||
vp_queuePrompt(PROMPT_SPEED);
|
||||
vp_queueString(buffer, vpAnnounceCommonSymbols |
|
||||
vpAnnounceLessCommonSymbols);
|
||||
|
@ -682,27 +683,33 @@ void vp_announceGPSInfo(vpGPSInfoFlags_t gpsInfoFlags)
|
|||
{
|
||||
vp_queuePrompt(PROMPT_ALTITUDE);
|
||||
|
||||
sniprintf(buffer, 16, "%4.1fm", state.gps_data.altitude);
|
||||
sniprintf(buffer, 16, "%dm", state.gps_data.altitude);
|
||||
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||
addSilenceIfNeeded(flags);
|
||||
}
|
||||
|
||||
if ((gpsInfoFlags & vpGPSLatitude) != 0)
|
||||
{
|
||||
// lat/long
|
||||
sniprintf(buffer, 16, "%8.6f", state.gps_data.latitude);
|
||||
// Convert from signed longitude, to unsigned + direction
|
||||
int32_t latitude = abs(state.gps_data.latitude);
|
||||
uint8_t latitude_int = latitude / 1000000;
|
||||
int32_t latitude_dec = latitude % 1000000;
|
||||
voicePrompt_t direction = (state.gps_data.latitude < 0) ? PROMPT_SOUTH : PROMPT_NORTH;
|
||||
sniprintf(buffer, 16, "%d.%06"PRId32, latitude_int, latitude_dec);
|
||||
stripTrailingZeroes(buffer);
|
||||
vp_queuePrompt(PROMPT_LATITUDE);
|
||||
vp_queueString(buffer, vpAnnounceCommonSymbols);
|
||||
vp_queuePrompt(PROMPT_NORTH);
|
||||
vp_queuePrompt(direction);
|
||||
}
|
||||
|
||||
if ((gpsInfoFlags & vpGPSLongitude) != 0)
|
||||
{
|
||||
float longitude = state.gps_data.longitude;
|
||||
voicePrompt_t direction = (longitude < 0) ? PROMPT_WEST : PROMPT_EAST;
|
||||
longitude = (longitude < 0) ? -longitude : longitude;
|
||||
sniprintf(buffer, 16, "%8.6f", longitude);
|
||||
// Convert from signed longitude, to unsigned + direction
|
||||
int32_t longitude = abs(state.gps_data.longitude);
|
||||
uint8_t longitude_int = longitude / 1000000;
|
||||
int32_t longitude_dec = longitude % 1000000;
|
||||
voicePrompt_t direction = (state.gps_data.longitude < 0) ? PROMPT_WEST : PROMPT_EAST;
|
||||
sniprintf(buffer, 16, "%d.%06"PRId32, longitude_int, longitude_dec);
|
||||
stripTrailingZeroes(buffer);
|
||||
|
||||
vp_queuePrompt(PROMPT_LONGITUDE);
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <ui/ui_default.h>
|
||||
#include <rtx.h>
|
||||
|
@ -1269,12 +1270,12 @@ void ui_saveState()
|
|||
}
|
||||
|
||||
#ifdef CONFIG_GPS
|
||||
static float priorGPSSpeed = 0;
|
||||
static float priorGPSAltitude = 0;
|
||||
static float priorGPSDirection = 500; // impossible value init.
|
||||
static uint8_t priorGPSFixQuality= 0;
|
||||
static uint8_t priorGPSFixType = 0;
|
||||
static uint8_t priorSatellitesInView = 0;
|
||||
static uint16_t priorGPSSpeed = 0;
|
||||
static int16_t priorGPSAltitude = 0;
|
||||
static int16_t priorGPSDirection = 500; // impossible value init.
|
||||
static uint8_t priorGPSFixQuality= 0;
|
||||
static uint8_t priorGPSFixType = 0;
|
||||
static uint8_t priorSatellitesInView = 0;
|
||||
static uint32_t vpGPSLastUpdate = 0;
|
||||
|
||||
static vpGPSInfoFlags_t GetGPSDirectionOrSpeedChanged()
|
||||
|
@ -1300,22 +1301,19 @@ static vpGPSInfoFlags_t GetGPSDirectionOrSpeedChanged()
|
|||
priorGPSFixType = state.gps_data.fix_type;
|
||||
}
|
||||
|
||||
float speedDiff=fabs(state.gps_data.speed - priorGPSSpeed);
|
||||
if (speedDiff >= 1)
|
||||
if (state.gps_data.speed != priorGPSSpeed)
|
||||
{
|
||||
whatChanged |= vpGPSSpeed;
|
||||
priorGPSSpeed = state.gps_data.speed;
|
||||
}
|
||||
|
||||
float altitudeDiff = fabs(state.gps_data.altitude - priorGPSAltitude);
|
||||
if (altitudeDiff >= 5)
|
||||
if (state.gps_data.altitude != priorGPSAltitude)
|
||||
{
|
||||
whatChanged |= vpGPSAltitude;
|
||||
priorGPSAltitude = state.gps_data.altitude;
|
||||
}
|
||||
|
||||
float degreeDiff = fabs(state.gps_data.tmg_true - priorGPSDirection);
|
||||
if (degreeDiff >= 1)
|
||||
if (state.gps_data.tmg_true != priorGPSDirection)
|
||||
{
|
||||
whatChanged |= vpGPSDirection;
|
||||
priorGPSDirection = state.gps_data.tmg_true;
|
||||
|
|
|
@ -682,22 +682,32 @@ void _ui_drawMenuGPS()
|
|||
}
|
||||
gfx_print(layout.line1_pos, layout.top_font, TEXT_ALIGN_LEFT,
|
||||
color_white, fix_buf);
|
||||
|
||||
// Convert from signed longitude, to unsigned + direction
|
||||
int32_t latitude = abs(last_state.gps_data.latitude);
|
||||
uint8_t latitude_int = latitude / 1000000;
|
||||
int32_t latitude_dec = latitude % 1000000;
|
||||
char *direction_lat = (last_state.gps_data.latitude < 0) ? "S " : "N ";
|
||||
|
||||
gfx_print(layout.line1_pos, layout.top_font, TEXT_ALIGN_CENTER,
|
||||
color_white, "N ");
|
||||
color_white, direction_lat);
|
||||
gfx_print(layout.line1_pos, layout.top_font, TEXT_ALIGN_RIGHT,
|
||||
color_white, "%8.6f", last_state.gps_data.latitude);
|
||||
color_white, "%d.%.6d", latitude_int, latitude_dec);
|
||||
gfx_print(layout.line2_pos, layout.top_font, TEXT_ALIGN_LEFT,
|
||||
color_white, type_buf);
|
||||
|
||||
// Convert from signed longitude, to unsigned + direction
|
||||
float longitude = last_state.gps_data.longitude;
|
||||
char *direction = (longitude < 0) ? "W " : "E ";
|
||||
longitude = (longitude < 0) ? -longitude : longitude;
|
||||
int32_t longitude = abs(last_state.gps_data.longitude);
|
||||
uint8_t longitude_int = longitude / 1000000;
|
||||
int32_t longitude_dec = longitude % 1000000;
|
||||
char *direction_lon = (last_state.gps_data.longitude < 0) ? "W " : "E ";
|
||||
|
||||
gfx_print(layout.line2_pos, layout.top_font, TEXT_ALIGN_CENTER,
|
||||
color_white, direction);
|
||||
color_white, direction_lon);
|
||||
gfx_print(layout.line2_pos, layout.top_font, TEXT_ALIGN_RIGHT,
|
||||
color_white, "%8.6f", longitude);
|
||||
color_white, "%d.%.6d", longitude_int, longitude_dec);
|
||||
gfx_print(layout.bottom_pos, layout.bottom_font, TEXT_ALIGN_CENTER,
|
||||
color_white, "S %4.1fkm/h A %4.1fm",
|
||||
color_white, "S %dkm/h A %dm",
|
||||
last_state.gps_data.speed,
|
||||
last_state.gps_data.altitude);
|
||||
}
|
||||
|
|
|
@ -765,7 +765,7 @@ void ui_updateFSM(bool *sync_rtx)
|
|||
_ui_changeWiper(&mod17CalData.tx_wiper, -1);
|
||||
break;
|
||||
case D_RXWIPER:
|
||||
_ui_changeWiper(&mod17CalData.tx_wiper, -1);
|
||||
_ui_changeWiper(&mod17CalData.rx_wiper, -1);
|
||||
break;
|
||||
case D_TXINVERT:
|
||||
mod17CalData.bb_tx_invert -= 1;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gps.h>
|
||||
|
||||
static void assert_conversion(struct minmea_float *f, int32_t expected)
|
||||
{
|
||||
int32_t result = minmea_tofixedpoint(f);
|
||||
if (result != expected)
|
||||
{
|
||||
printf("FAILED! result value %d - expected %d\n",
|
||||
result, expected);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("minmea coordinate conversion test\n");
|
||||
struct minmea_float test = {5333735, 1000};
|
||||
assert_conversion(&test, 53562250);
|
||||
test.scale = 1;
|
||||
test.value = 0;
|
||||
assert_conversion(&test, 0);
|
||||
test.scale = 1000;
|
||||
test.value = -5333735;
|
||||
assert_conversion(&test, -53562250);
|
||||
test.scale = 1000;
|
||||
test.value = -330;
|
||||
assert_conversion(&test, -5500);
|
||||
test.scale = 1000;
|
||||
test.value = -3296;
|
||||
assert_conversion(&test, -54933);
|
||||
printf("PASS\n");
|
||||
|
||||
return 0;
|
||||
}
|
Ładowanie…
Reference in New Issue