diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/inc/i2c.h b/inc/i2c.h
--- a/inc/i2c.h
+++ b/inc/i2c.h
@@ -4,6 +4,7 @@
#include "stm32f0xx_hal.h"
void i2c_init(void);
+void i2c_deinit(void);
I2C_HandleTypeDef* i2c_get(void);
#endif
diff --git a/inc/wspr.h b/inc/wspr.h
--- a/inc/wspr.h
+++ b/inc/wspr.h
@@ -5,7 +5,7 @@
void wspr_init(void);
void wspr_sleep(void);
void wspr_wakeup(void);
-void wspr_transmit(uint8_t* grid_locator);
+void wspr_transmit(uint8_t* grid_locator, uint8_t send_alternate);
#endif
diff --git a/src/main.c b/src/main.c
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
// We have access to the 1PPS pin of the gps... could have trim routine for internal oscillator based on this when we have a fix
-// Probabl wake up 1 minute early -- 0.45min possible +/- on wakeup time with 15min sync intervals
+// Probable wake up 1 minute early -- 0.45min possible +/- on wakeup time with 15min sync intervals
// TODO: Add JT9 message with more grid locator digits + altitude + vbatt + temp
@@ -40,7 +40,7 @@ uint32_t statled_ontime = 0;
int main(void)
{
HAL_Init();
- HAL_Delay(2000); // startup delay before infinisleep
+ HAL_Delay(1000); // startup delay before infinisleep
sysclk_init();
rtc_init();
@@ -64,12 +64,13 @@ int main(void)
uint8_t fix_ok = 0;
uint8_t numsats = 0;
+ uint8_t packet_type = 0;
while (1)
{
// Every 10 minutes, wake up and try to wspr
- if(state == SYSTEM_IDLE && (HAL_GetTick() - last_wspr_tx_time > 60000))// * 10))
+ if(state == SYSTEM_IDLE && (HAL_GetTick() - last_wspr_tx_time > 60000 /* * 10 */))
{
state = SYSTEM_GPSACQ;
}
@@ -84,7 +85,7 @@ int main(void)
// If odd minute
if(gps_getdata()->minute % 2)
{
- // Wait until even minute, coming soon
+ // Wait until even minute plus one second, coming soon
nextwspr_time = HAL_GetTick() + (60000 - (gps_getdata()->second * 1000));
nextwspr_time_valid = 1;
@@ -190,7 +191,9 @@ int main(void)
__calc_gridloc(grid_locator, latitude_flt, longitude_flt);
- wspr_transmit(grid_locator);
+ // TODO: Switch between alternate and standard packet
+ wspr_transmit(grid_locator, packet_type);
+ //packet_type = !packet_type; // alternate packet type
last_wspr_tx_time = HAL_GetTick();
state = SYSTEM_IDLE;
}
diff --git a/src/wspr.c b/src/wspr.c
--- a/src/wspr.c
+++ b/src/wspr.c
@@ -4,6 +4,7 @@
#include "gpio.h"
#include "wspr.h"
#include "i2c.h"
+#include "gps.h"
#include "config.h"
@@ -11,9 +12,13 @@
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
#define WSPR_CTC 10672 // CTC value for WSPR
+char call_orig[7] = "KD8TDF";
+#define DBM_ORIG 10
+
+
// Test stuff
char call[7] = "KD8TDF";
-char loc[5] = "EN72";
+char loc[5] = "EN82";
uint8_t dbm = 10;
uint8_t tx_buffer[255];
@@ -48,13 +53,158 @@ void wspr_wakeup(void)
// Bring up TCXO and oscillator IC
-void wspr_transmit(uint8_t* grid_locator)
+void wspr_transmit(uint8_t* grid_locator, uint8_t send_alternate)
{
// Copy 4 digit grid locator to local buffer; null terminate
for(uint8_t i=0; i<4; i++)
loc[i] = grid_locator[i];
loc[4] = '\0';
+ // Set power to altitude in m / 150
+ uint8_t altscaled = gps_getdata()->altitude / 150;
+ if(altscaled > 60)
+ altscaled = 60;
+
+
+ // If alternate packet, send 0XFXXEN82XX
+ if(send_alternate)
+ {
+
+
+
+ /////////////////////////////////////////////////
+ // Composite altitude and sub-maidenhead locator
+ /////////////////////////////////////////////////
+ uint16_t maiden_ext = (loc[4] - 'A') + ((loc[5] - 'A') * 24); // 0-575
+ uint16_t altitude_mod = gps_getdata()->altitude / 20;
+
+ // Ciel at 21,340 meters
+ if(altitude_mod > 1067)
+ altitude_mod = 1067; // Don't overflow into maidenhead!
+
+ // Compose composite altitude (lsbs) with maidenhead locator (msbs)
+ uint32_t subalt = (1068 * maiden_ext) + (gps_getdata()->altitude / 20);
+
+
+
+ ////////////////////////////////////////////
+ // Encode extended maidenhead and altitude
+ ////////////////////////////////////////////
+ call[0] = '0';
+
+ // Split into chunks of valmax 36, 26, 26, 26
+
+ // Mask off following 3 26valmax fields
+ uint32_t chunk = subalt / 26 / 26 / 26;
+
+ // Encode to callsign
+ if(chunk < 10)
+ call[1] = '0' + chunk
+ else
+ call[1] = chunk - 10 + 'A';
+
+ // Subtract off previous portion
+ subalt -= (chunk * 26 * 26 * 26);
+
+ // Mask off following 2 26bit values
+ chunk = (subalt / 26 / 26);
+
+ call[3] = 'A' + chunk;
+
+ // Subtract off previous portion
+ subalt -= (chunk * 26 * 26)
+
+ // Mask off following 1 26bit values
+ chunk = (subalt / 26);
+
+ call[4] = 'A' + chunk;
+
+ // Subtract off previous portion
+ subalt -= (chunk * 26);
+
+ // Remainder is the last call char
+ call[5] = 'A' + subalt;
+
+
+ ////////////////////////////////////////
+ // Composite temp/batt/speed/gps
+ ////////////////////////////////////////
+
+ // Encode value from -50C to 39C => 0-89. TODO: Bounds!
+ uint8_t temp_enc = 0 + 50;
+
+ // Encode value from 0-39 with some scalar/offset/etc
+ uint8_t batt_enc = 0;
+
+ // Encode speed in knots from 0-82 to 0-41
+ uint8_t speed_enc = gpsdata()->speed / 2;
+ if(speed_enc > 41)
+ speed_enc = 41;
+
+ // Encode GPS status
+ uint8_t gps_status = 0b00; // MSB is valid fix, lsb is sats > 8
+
+ uint32_t engdata = gps_status + 2 * (speed_enc + 42 * (batt_enc + 40 * temp_enc));
+
+ ////////////////////////////////////////////
+ // Encode temp/batt/speed/gps
+ ////////////////////////////////////////////
+
+ // Mask off fields
+ chunk = engdata / 18 / 10 / 10 / 19;
+
+ // Encode to grid locator
+ grid_locator[0] = 'A' + chunk;
+
+ // Subtract off previous portion
+ engdata -= (chunk * 18 * 10 * 10 * 19);
+
+ // Mask of fields
+ chunk = engdata / 10 / 10 / 19;
+
+ // Encode to grid locator
+ grid_locator[1] = 'A' + chunk;
+
+ // Subtract off previous portion
+ engdata -= (chunk * 10 * 10 * 19);
+
+ // Mask off fields
+ chunk = engdata / 10 / 19;
+
+ // Encode
+ grid_locater[2] = '0' + chunk;
+
+ // Subtract
+ engdata -= (chunk * 10 * 19);
+
+ // Mask off
+ chunk = engdata / 19;
+
+ // Encode
+ grid_locator[3] = chunk;
+
+ // Subtract
+ engdata -= (chunk * 19);
+
+ // Mask off
+ chunk = engdata;
+
+ // Encode
+ uint8_t powers[] = {0, 3, 7, 10, 13, 17, 20, 23, 27, 30, 33, 37, 40, 43, 47, 50, 53, 57, 60}
+ dbm = powers[chunk];
+ }
+ else
+ {
+ call[0] = call_orig[0];
+ call[1] = call_orig[1];
+ call[2] = call_orig[2];
+ call[3] = call_orig[3];
+ call[4] = call_orig[4];
+ call[5] = call_orig[5];
+ call[6] = call_orig[6];
+
+ dbm = DBM_ORIG;
+ }
// Start timer for WSPR
__TIM1_CLK_ENABLE();