Files @ 2a60a19d0303
Branch filter:

Location: FeatherHAB/wsprhab/src/main.c - annotation

Ethan Zonca
Fix encoding, add some dummy values, code compiles and might work now
4202475a7575
4202475a7575
4202475a7575
4202475a7575
0d9900312165
0d9900312165
c1b1dfc6c2f4
0d9900312165
c1b1dfc6c2f4
0d9900312165
a127e9133034
bb703e19f242
0d9900312165
0d9900312165
23ecc15c694d
659774b354b1
f40195400941
659774b354b1
659774b354b1
ddbcfaffc98a
ddbcfaffc98a
ddbcfaffc98a
ddbcfaffc98a
ddbcfaffc98a
ddbcfaffc98a
ddbcfaffc98a
659774b354b1
659774b354b1
b32b9376de92
659774b354b1
659774b354b1
50cc79d449a4
659774b354b1
f126c64d1202
736f2e74e445
736f2e74e445
736f2e74e445
f126c64d1202
659774b354b1
0d9900312165
0d9900312165
0d9900312165
f40195400941
0d9900312165
0d9900312165
bb703e19f242
0dd5c923fdea
4202475a7575
659774b354b1
23ecc15c694d
0d9900312165
21759af9d2ad
21759af9d2ad
4ffdc5eab0ff
659774b354b1
659774b354b1
4ffdc5eab0ff
0b86288f0749
0b86288f0749
b32b9376de92
dda4d4df3034
b32b9376de92
0b86288f0749
b113d7d76caf
b113d7d76caf
dd3b59fcb7a7
f40195400941
736f2e74e445
0d9900312165
0d9900312165
677c51754ccf
b32b9376de92
f40195400941
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
677c51754ccf
0b86288f0749
677c51754ccf
9ba4d6855ba4
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
f40195400941
b32b9376de92
dda4d4df3034
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
dda4d4df3034
b32b9376de92
b32b9376de92
0b86288f0749
677c51754ccf
677c51754ccf
677c51754ccf
677c51754ccf
659774b354b1
f76c13fc8299
659774b354b1
659774b354b1
659774b354b1
659774b354b1
659774b354b1
ddbcfaffc98a
ddbcfaffc98a
dda4d4df3034
ddbcfaffc98a
ddbcfaffc98a
fb8415e8edb9
fb8415e8edb9
ddbcfaffc98a
ddbcfaffc98a
ddbcfaffc98a
dda4d4df3034
659774b354b1
dda4d4df3034
ddbcfaffc98a
ddbcfaffc98a
ddbcfaffc98a
659774b354b1
659774b354b1
659774b354b1
659774b354b1
659774b354b1
e1db5d4a8be4
659774b354b1
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
659774b354b1
9ba4d6855ba4
0b86288f0749
b32b9376de92
9ba4d6855ba4
0b86288f0749
659774b354b1
bb703e19f242
dda4d4df3034
659774b354b1
659774b354b1
9ba4d6855ba4
659774b354b1
659774b354b1
659774b354b1
659774b354b1
b295af18d965
659774b354b1
0b86288f0749
659774b354b1
659774b354b1
bb703e19f242
bb703e19f242
0b86288f0749
bb703e19f242
0b86288f0749
bb703e19f242
38f0f2457409
38f0f2457409
bb703e19f242
0b86288f0749
659774b354b1
a127e9133034
659774b354b1
659774b354b1
659774b354b1
659774b354b1
1ecaddb549ab
659774b354b1
50cc79d449a4
50cc79d449a4
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f40195400941
f40195400941
f40195400941
1ecaddb549ab
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
b32b9376de92
dda4d4df3034
b32b9376de92
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
fb8415e8edb9
21759af9d2ad
659774b354b1
659774b354b1
659774b354b1
659774b354b1
659774b354b1
f76c13fc8299
aa624684a65e
659774b354b1
e1db5d4a8be4
0d9900312165
736f2e74e445
0d9900312165
0d9900312165
4ffdc5eab0ff
736f2e74e445
736f2e74e445
736f2e74e445
736f2e74e445
736f2e74e445
736f2e74e445
0d9900312165
0d9900312165
0d9900312165
736f2e74e445
736f2e74e445
736f2e74e445
736f2e74e445
736f2e74e445
0d9900312165
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
4ffdc5eab0ff
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
f126c64d1202
4ffdc5eab0ff
//
// WSPRHAB: Minimal high-altitude balloon tracker with WSPR telemetry
//

#include "stm32f0xx_hal.h"
#include "adc.h"
#include "system.h"
#include "i2c.h"
#include "uart.h"
#include "gpio.h"
#include "wspr.h"
#include "rtc.h"
#include "gps.h"


// 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
// 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
// MSG13charmax:
// 	X: gridloc
//  Y: altitude
//  Z: temperature
//  KD8TDF XXYYZZ // could use alt callsign thing

enum _state
{
    SYSTEM_IDLE = 0, // awaiting RTC interrupt for wakeup TODO wake up before scheduled time to get fix?
    SYSTEM_GPSACQ, // RTC interrupted
    SYSTEM_WSPRTX, // Wait for timeslot and actually transmit the message
};

static void __calc_gridloc(char *dst, double lat, double lon);
static void ledpulse(void);

uint32_t statled_ontime = 0;


int main(void)
{
    HAL_Init();
    HAL_Delay(1000); // startup delay before infinisleep

    sysclk_init();
    rtc_init();
    gpio_init();
    adc_init();
    wspr_init();

    uint32_t led_timer = HAL_GetTick();

    led_blink(4);

    uint16_t blink_rate = BLINK_FAST;
    uint8_t state = SYSTEM_GPSACQ;

    uint32_t gps_polltimer = 0;
    uint32_t fix_acq_starttime = 0;
    uint32_t nextwspr_time = 0;
    uint8_t nextwspr_time_valid = 0;
    uint32_t last_wspr_tx_time = 0;

    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 */))
    	{
    		state = SYSTEM_GPSACQ;
    	}

        // Update fix status every 2 seconds
        if(HAL_GetTick() - gps_polltimer > 2000)
        {
            if(gps_ison())
            {
            	gps_update_data();

            	// If odd minute
            	if(gps_getdata()->minute % 2)
            	{
            		// Wait until even minute plus one second, coming soon
            		nextwspr_time = HAL_GetTick() + (60000 - (gps_getdata()->second * 1000));
                    nextwspr_time_valid = 1;

            	}
            	// If even minute
            	else
            	{
            		// Wait until odd minute, one minute and some change away
            		nextwspr_time = HAL_GetTick() + 60000 + (60000 - (gps_getdata()->second * 1000));
                    nextwspr_time_valid = 1;
            	}
            }
            gps_polltimer = HAL_GetTick();
        }



        switch(state)
        {

            // Idling: sleep and wait for RTC timeslot trigger
            case SYSTEM_IDLE:
            {
                blink_rate = BLINK_SLOW;

                // Actually sleep for real: disable systick and sleep until RTC interrupt
//                HAL_SuspendTick();

                // Enter sleep mode: wait for interrupt
                HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);

                // We have woken up!

                // This is hopefully the only timer that needs to stay alive in idle mode
 //               last_wspr_tx_time += 0; // move this timer forward based on sleep length

 //               HAL_ResumeTick();

                // TODO: Eventually use GPS time to calibrate the RTC maybe

            } break;


            // Attempt to acquire GPS fix
            case SYSTEM_GPSACQ:
            {
                blink_rate = BLINK_FAST;
                HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);
                HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);
                HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);
                HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);


                if(!gps_ison())
                {
                	fix_acq_starttime = HAL_GetTick();
                    gps_poweron(); // power on and initialize GPS module
                }

                // If 3d fix with a decent enough precision
                if( ((gps_getdata()->fixtype == 2) || (gps_getdata()->fixtype == 3)) && gps_getdata()->pdop < 10 && nextwspr_time_valid == 1)
                {
                    // Disable GPS module
                    gps_poweroff();

                    // TODO: Set RTC from GPS time

                    // TODO: Set RTC for countdown to next transmission timeslot!

                    // TODO: Set wspr countdown timer for this transmission!
                    fix_acq_starttime = 0;
                    state = SYSTEM_WSPRTX;
                }
                // If no decent fix in 3 minutes
                else if(HAL_GetTick() - fix_acq_starttime > 60000 * 3)
                {
                	// Flash error code and go to idle, try again next time
                	led_blink(4);
                    gps_poweroff();
                    fix_acq_starttime = 0;
                    last_wspr_tx_time = HAL_GetTick(); // repeat acq/tx cycle after big time delay
                	state = SYSTEM_IDLE;
                }
            } break;

            
            // Wait for wspr timeslot and start transmitting
            case SYSTEM_WSPRTX:
            {
            	blink_rate = BLINK_MED;
                // Wait for wspr countdown timer to expire and go to tx
//                if(timeout_expired)
//                {

            	// If we're after the minute but not more than 2s after the minute, start tx
            	if(HAL_GetTick() >= nextwspr_time)
            	{
            		if(HAL_GetTick() < nextwspr_time + 2000)
            		{
            			volatile double latitude_flt = (double)gps_getdata()->latitude / 10000000.0;
            			volatile double longitude_flt = (double)gps_getdata()->longitude / 10000000.0;
            			volatile uint8_t grid_locator[7];

            			__calc_gridloc(grid_locator, latitude_flt, longitude_flt);

                        // 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;
            		}
            		else
            		{
            			// Window was missed, go back to idle, and try again after time delay
						last_wspr_tx_time = HAL_GetTick();
            			state = SYSTEM_IDLE;
            		}
                    nextwspr_time_valid = 0; // invalidate wspr time
                }
            	else
            	{
                    HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);
                    HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);
                    HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);
                    HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);
            	}

                // Schedule next wakeup (maybe 2mins prior ot timeslot if no osc trim)
                // Next wakeup should enter SYSTEM_GPSACQ state...

            } break;

        }


        if(HAL_GetTick() - led_timer > blink_rate)
        {
            ledpulse();
            led_timer = HAL_GetTick();
        }

        if(statled_ontime && HAL_GetTick() - statled_ontime > 10)
        {
            HAL_GPIO_WritePin(LED_BLUE, 0);
            statled_ontime = 0;
        }

    }
}

static void ledpulse(void)
{
    HAL_GPIO_WritePin(LED_BLUE, 1);
	statled_ontime = HAL_GetTick();
}

static void __calc_gridloc(char *dst, double lat, double lon)
{
	int o1, o2, o3;
	int a1, a2, a3;
	double remainder;
	// longitude
	remainder = lon + 180.0;
	o1 = (int)(remainder / 20.0);
	remainder = remainder - (double)o1 * 20.0;
	o2 = (int)(remainder / 2.0);
	remainder = remainder - 2.0 * (double)o2;
	o3 = (int)(12.0 * remainder);

	// latitude
	remainder = lat + 90.0;
	a1 = (int)(remainder / 10.0);
	remainder = remainder - (double)a1 * 10.0;
	a2 = (int)(remainder);
	remainder = remainder - (double)a2;
	a3 = (int)(24.0 * remainder);
	dst[0] = (char)o1 + 'A';
	dst[1] = (char)a1 + 'A';
	dst[2] = (char)o2 + '0';
	dst[3] = (char)a2 + '0';
	dst[4] = (char)o3 + 'A';
	dst[5] = (char)a3 + 'A';
	dst[6] = (char)0;
}