// // 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 "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 // Probabl wake up 1 minute early -- 0.45min possible +/- on wakeup time with 15min sync intervals 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 }; int main(void) { HAL_Init(); sysclk_init(); gpio_init(); adc_init(); i2c_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; uint32_t last_wspr_tx_time = 0; uint8_t fix_ok = 0; uint8_t numsats = 0; while (1) { // Every 10 minutes, wake up and try to wspr if(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(); gps_getdata()->minute; gps_getdata()->second; // If odd minute if(gps_getdata()->minute % 2) { volatile uint8_t minute = gps_getdata()->minute; // Wait until even minute, coming soon nextwspr_time = HAL_GetTick() + (60000 - (gps_getdata()->second * 1000)); } // If even minute else { // Wait until odd minute, one minute and some change away nextwspr_time = HAL_GetTick() + 60000 + (60000 - (gps_getdata()->second * 1000)); } } gps_polltimer = HAL_GetTick(); } switch(state) { // Idling: sleep and wait for RTC timeslot trigger case SYSTEM_IDLE: { blink_rate = BLINK_SLOW; // Wait for RTC wakeup interrupt //wfi(); //enter_sleep(); // Somehow go to another state when we get an interrupt // state = SYSTEM_GPSACQ; } break; // Attempt to acquire GPS fix case SYSTEM_GPSACQ: { blink_rate = BLINK_FAST; if(!gps_ison()) { fix_acq_starttime = HAL_GetTick(); gps_poweron(); // power on and initialize GPS module } if(gps_getdata()->fixtype > 0 && gps_getdata()->pdop < 5) { // 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; } else if(HAL_GetTick() - fix_acq_starttime > 60000) { // Flash error code and go to idle probably? or just try forever? led_blink(4); } } break; // Wait for wspr timeslot and start transmitting case SYSTEM_WSPRTX: { blink_rate = BLINK_SLOW; // 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) { wspr_transmit(); 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; } } // 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) { HAL_GPIO_TogglePin(LED_BLUE); led_timer = HAL_GetTick(); } } }