Changed Grid Square calculations.

Changed Grid Square  calculations from double to float that has adequate precision.
pull/16/merge
Bob Larkin 2 years ago
parent 2e7df3af34
commit 78b7fc91dc
  1. 4
      examples/FT8Receive/FT8Receive.ino
  2. 6
      examples/FT8Receive/decode_ft8R.ino
  3. 70
      examples/FT8Receive/locatorR.ino
  4. 69
      examples/FT8Receive/maidenheadR.ino
  5. 6
      radioFT8Demodulator_F32.h

@ -63,6 +63,10 @@
#define ft8_min_freq FT8_FREQ_SPACING * LOW_FREQ_INDEX #define ft8_min_freq FT8_FREQ_SPACING * LOW_FREQ_INDEX
#define ft8_msg_samples 92 #define ft8_msg_samples 92
// A couple of prototypes to help the compile order
void init_DSP(void);
void extract_power(int);
// Alternate interface format. // Alternate interface format.
// #define W5BAA // #define W5BAA

@ -44,7 +44,7 @@ const int kMax_decoded_messages = 20;
const int kMax_message_length = 20; const int kMax_message_length = 20;
const int kMin_score = 40; // Minimum sync score threshold for candidates const int kMin_score = 40; // Minimum sync score threshold for candidates
int validate_locator(char locator[]); int validate_locator(char locator[]);
int strindex(char s[],char t[]); int strindex(char s[], char t[]);
typedef struct typedef struct
{ {
@ -220,8 +220,8 @@ int ft8_decode(void) {
strcpy(Target_Locator, new_decoded[num_decoded].field3); strcpy(Target_Locator, new_decoded[num_decoded].field3);
if (validate_locator(Target_Locator) == 1) if (validate_locator(Target_Locator) == 1)
{ {
distance = Target_Distance(Target_Locator); distance = Target_Distancef(Target_Locator);
new_decoded[num_decoded].distance = (int)distance; new_decoded[num_decoded].distance = (int)(0.5f + distance);
} }
else else
{ {

@ -1,24 +1,16 @@
/* /*
* locator.ino * Was locator.ino
*
* Created on: Nov 4, 2019 * Created on: Nov 4, 2019
* Author: user * Author: user
*/ */
// locatorR.ino Bob Larkin 12 Nov 2022
// Built from the K. Goba double precision files.
// Data types float precision, funtion unchanged, names have added 'f'
//#include "locator.h" const float32_t EARTH_RAD = 6371.0f; //radius in km
//#include <math.h> float32_t Latitude, Longitude;
//#include "arm_math.h" float32_t Station_Latitude, Station_Longitude;
float32_t Target_Latitude, Target_Longitude;
// TODO - Looks like single precision would be adequate - RSL
const double EARTH_RAD = 6371; //radius in km
//void process_locator(char locator[]);
//double distance(double lat1, double lon1, double lat2, double lon2);
//double deg2rad(double deg);
float Latitude, Longitude;
float Station_Latitude, Station_Longitude;
float Target_Latitude, Target_Longitude;
//float Target_Distance(char target[]);
void set_Station_Coordinates(char station[]){ void set_Station_Coordinates(char station[]){
process_locator(station); process_locator(station);
@ -26,21 +18,21 @@ void set_Station_Coordinates(char station[]){
Station_Longitude = Longitude; Station_Longitude = Longitude;
} }
float Target_Distance(char target[]) { float32_t Target_Distancef(char target[]) {
float targetDistance; float32_t targetDistance;
process_locator(target); process_locator(target);
Target_Latitude = Latitude; Target_Latitude = Latitude;
Target_Longitude = Longitude; Target_Longitude = Longitude;
targetDistance = (float) distance((double)Station_Latitude,(double)Station_Longitude, targetDistance = distancef((float32_t)Station_Latitude, (float32_t)Station_Longitude,
(double)Target_Latitude,(double)Target_Longitude); (float32_t)Target_Latitude, (float32_t)Target_Longitude);
return targetDistance; return targetDistance;
} }
void process_locator(char locator[]) { void process_locator(char locator[]) {
uint8_t A1, A2, N1, N2; uint8_t A1, A2, N1, N2;
uint8_t A1_value, A2_value, N1_value, N2_value; uint8_t A1_value, A2_value, N1_value, N2_value;
float Latitude_1, Latitude_2, Latitude_3; float32_t Latitude_1, Latitude_2, Latitude_3;
float Longitude_1, Longitude_2, Longitude_3; float32_t Longitude_1, Longitude_2, Longitude_3;
A1 = locator[0]; A1 = locator[0];
A2 = locator[1]; A2 = locator[1];
N1 = locator[2]; N1 = locator[2];
@ -49,27 +41,29 @@ void process_locator(char locator[]) {
A2_value = A2-65; A2_value = A2-65;
N1_value = N1- 48; N1_value = N1- 48;
N2_value = N2 - 48; N2_value = N2 - 48;
Latitude_1 = (float) A2_value * 10; Latitude_1 = (float32_t) A2_value * 10.0f;
Latitude_2 = (float) N2_value; Latitude_2 = (float32_t) N2_value;
Latitude_3 = (11.0/24.0 + 1.0/48.0) - 90.0; Latitude_3 = (11.0f/24.0f + 1.0f/48.0f) - 90.0f;
Latitude = Latitude_1 + Latitude_2 + Latitude_3; Latitude = Latitude_1 + Latitude_2 + Latitude_3;
Longitude_1 = (float)A1_value * 20.0; Longitude_1 = (float32_t)A1_value * 20.0f;
Longitude_2 = (float)N1_value * 2.0; Longitude_2 = (float32_t)N1_value * 2.0f;
Longitude_3 = 11.0/12.0 + 1.0/24.0; Longitude_3 = 11.0f/12.0f + 1.0f/24.0f;
Longitude = Longitude_1 + Longitude_2 + Longitude_3 - 180.0; // global Longitude
Longitude = Longitude_1 + Longitude_2 + Longitude_3 - 180.0f;
} }
// distance (km) on earth's surface from point 1 to point 2 // distance (km) on earth's surface from point 1 to point 2
double distance(double lat1, double lon1, double lat2, double lon2) { float32_t distancef(float32_t lat1, float32_t lon1, float32_t lat2, float32_t lon2) {
double lat1r = deg2rad(lat1); float32_t lat1r = deg2radf(lat1);
double lon1r = deg2rad(lon1); float32_t lon1r = deg2radf(lon1);
double lat2r = deg2rad(lat2); float32_t lat2r = deg2radf(lat2);
double lon2r = deg2rad(lon2); float32_t lon2r = deg2radf(lon2);
return acos(sin(lat1r) * sin(lat2r)+cos(lat1r) * cos(lat2r) * cos(lon2r-lon1r)) * EARTH_RAD; return acos(sinf(lat1r) * sinf(lat2r) +
cosf(lat1r) * cosf(lat2r) * cosf(lon2r-lon1r)) * EARTH_RAD;
} }
// convert degrees to radians // convert degrees to radians (i.e., * PI/180)
double deg2rad(double deg) float32_t deg2radf(float32_t deg)
{ {
return deg * (PI / 180.0); return deg * 0.017453292f;
} }

@ -1,36 +1,31 @@
//#include "maidenhead.h" // maidenheadR.ino Bob Larkin 12 Nov 2022
//#include <math.h> // Built from the K. Goba double precision files.
//#include <stdio.h> // Data types float precision, funtion unchanged, names have added 'f'
//#include <string.h>
//#ifdef __cplusplus
//extern "C" {
//#endif
// TODO This looks like a float change?? RSL
char letterizeR(int x) { char letterizeR(int x) {
return (char) x + 65; return (char) x + 65;
} }
char* get_mh(double lat, double lon, int size) { // Input lat, lon in degrees; Input grid locator size 4, 6, 8, or 10
// Output grid square string pointer.
char* get_mhf(float32_t lat, float32_t lon, int size) {
static char locator[11]; static char locator[11];
double LON_F[]={20,2.0,0.083333,0.008333,0.0003472083333333333}; float32_t LON_F[]={20.0f, 2.0f, 0.0833333f, 0.008333f, 0.00034720833f};
double LAT_F[]={10,1.0,0.0416665,0.004166,0.0001735833333333333}; float32_t LAT_F[]={10.0f, 1.0f, 0.0416665f, 0.004166f, 0.00017358333f};
int i; int i;
lon += 180; lon += 180.0f;
lat += 90; lat += 90.0f;
if (size <= 0 || size > 10) size = 6; if (size <= 0 || size > 10) size = 6;
size/=2; size*=2; size/=2; size*=2;
for (i = 0; i < size/2; i++){ for (i = 0; i < size/2; i++){
if (i % 2 == 1) { if (i % 2 == 1) {
locator[i*2] = (char) (lon/LON_F[i] + '0'); locator[i*2] = (char)(lon/LON_F[i] + '0');
locator[i*2+1] = (char) (lat/LAT_F[i] + '0'); locator[i*2+1] = (char)(lat/LAT_F[i] + '0');
} else { } else {
locator[i*2] = letterizeR((int) (lon/LON_F[i])); locator[i*2] = letterizeR((int)(lon/LON_F[i]));
locator[i*2+1] = letterizeR((int) (lat/LAT_F[i])); locator[i*2+1] = letterizeR((int)(lat/LAT_F[i]));
} }
lon = fmod(lon, LON_F[i]); lon = fmod(lon, LON_F[i]);
lat = fmod(lat, LAT_F[i]); lat = fmod(lat, LAT_F[i]);
@ -47,32 +42,30 @@ char* complete_mh(char* locator) {
return locator2; return locator2;
} }
double mh2lon(char* locator) { // Convert grid square string to longitude
double field, square, subsquare, extsquare, precsquare; float32_t mh2lonf(char* locator) {
float32_t field, square, subsquare, extsquare, precsquare;
int len = strlen(locator); int len = strlen(locator);
if (len > 10) return 0; if (len > 10) return 0;
if (len < 10) locator = complete_mh(locator); if (len < 10) locator = complete_mh(locator);
field = (locator[0] - 'A') * 20.0; field = (locator[0] - 'A') * 20.0f;
square = (locator[2] - '0') * 2.0; square = (locator[2] - '0') * 2.0f;
subsquare = (locator[4] - 'A') / 12.0; subsquare = (locator[4] - 'A') / 12.0f;
extsquare = (locator[6] - '0') / 120.0; extsquare = (locator[6] - '0') / 120.0f;
precsquare = (locator[8] - 'A') / 2880.0; precsquare = (locator[8] - 'A') / 2880.0f;
return field + square + subsquare + extsquare + precsquare - 180; return field + square + subsquare + extsquare + precsquare - 180.0f;
} }
double mh2lat(char* locator) { // Convert grid square string to latitude
double field, square, subsquare, extsquare, precsquare; float32_t mh2latf(char* locator) {
float field, square, subsquare, extsquare, precsquare;
int len = strlen(locator); int len = strlen(locator);
if (len > 10) return 0; if (len > 10) return 0;
if (len < 10) locator = complete_mh(locator); if (len < 10) locator = complete_mh(locator);
field = (locator[1] - 'A') * 10.0; field = (locator[1] - 'A') * 10.0f;
square = (locator[3] - '0') * 1.0; square = (locator[3] - '0') * 1.0f;
subsquare = (locator[5] - 'A') / 24.0; subsquare = (locator[5] - 'A') / 24.0f;
extsquare = (locator[7] - '0') / 240.0; extsquare = (locator[7] - '0') / 240.0f;
precsquare = (locator[9] - 'A') / 5760.0; precsquare = (locator[9] - 'A') / 5760.0f;
return field + square + subsquare + extsquare + precsquare - 90; return field + square + subsquare + extsquare + precsquare - 90;
} }
//#ifdef __cplusplus
//}
//#endif

@ -115,7 +115,7 @@ public:
void initialize(void) { void initialize(void) {
// Initialize 2 FIR instances (ARM DSP Math Library) // Initialize 2 FIR instances (ARM DSP Math Library)
//arm_fir_init_f32 (arm_fir_instance_f32 *S, uint16_t numTaps, //arm_fir_init_f32 (arm_fir_instance_f32 *S, uint16_t numTaps,
const float32_t *pCoeffs, float32_t *pState, uint32_t blockSize) // const float32_t *pCoeffs, float32_t *pState, uint32_t blockSize)
arm_fir_init_f32(&fir_inst1, 55, &firDecimate1[0], &dec1FIRWork[0], 128UL); arm_fir_init_f32(&fir_inst1, 55, &firDecimate1[0], &dec1FIRWork[0], 128UL);
arm_fir_init_f32(&fir_inst2, 167, &firDecimate2[0], &dec2FIRWork[0], 128UL); arm_fir_init_f32(&fir_inst2, 167, &firDecimate2[0], &dec2FIRWork[0], 128UL);
// CHECK SAMPLE RATE AND SET index <<<<<<<<<<<<< // CHECK SAMPLE RATE AND SET index <<<<<<<<<<<<<
@ -350,7 +350,7 @@ int32_t kkk;
* Sampling frequency = 96000 Hz * Sampling frequency = 96000 Hz
* 0 Hz - 3200 Hz ripple = 0.065 dB * 0 Hz - 3200 Hz ripple = 0.065 dB
* 9600 Hz - 48000 Hz att = -81.1 dB */ * 9600 Hz - 48000 Hz att = -81.1 dB */
const float32_t firDecimate1[55] = { // constexpr static float32_t firDecimate1[55] = { // constexpr static
0.000037640f, 0.000248621f, 0.000535682f, 0.001017563f, 0.001647298, 0.000037640f, 0.000248621f, 0.000535682f, 0.001017563f, 0.001647298,
0.002359693f, 0.003009942f, 0.003388980f, 0.003245855f, 0.002335195, 0.002359693f, 0.003009942f, 0.003388980f, 0.003245855f, 0.002335195,
0.000482309f, -0.002343975f, -0.005965316f, -0.009953093f, -0.013627779f, 0.000482309f, -0.002343975f, -0.005965316f, -0.009953093f, -0.013627779f,
@ -367,7 +367,7 @@ const float32_t firDecimate1[55] = { // constexpr static
* Sampling frequency = 19200 Hz * Sampling frequency = 19200 Hz
* 0 Hz - 2800 Hz ripple = 0.073 dB * 0 Hz - 2800 Hz ripple = 0.073 dB
* 3200 Hz - 9600 Hz att = -80.0 dB */ * 3200 Hz - 9600 Hz att = -80.0 dB */
const float32_t firDecimate2[167] = { float32_t firDecimate2[167] = {
0.000200074f, 0.000438821f, 0.000648425f, 0.000636175f, 0.000315069f, 0.000200074f, 0.000438821f, 0.000648425f, 0.000636175f, 0.000315069f,
-0.000193500f, -0.000591064f, -0.000600896f, -0.000202482f, 0.000301473f, -0.000193500f, -0.000591064f, -0.000600896f, -0.000202482f, 0.000301473f,
0.000486276f, 0.000152104f, -0.000466930f, -0.000846593f, -0.000601871f, 0.000486276f, 0.000152104f, -0.000466930f, -0.000846593f, -0.000601871f,

Loading…
Cancel
Save