Changeset - 1ecaddb549ab
[Not reviewed]
default
0 3 0
Ethan Zonca - 9 years ago 2016-10-13 21:00:18
ez@ethanzonca.com
Disable timer clocks, fix transmission issues
3 files changed with 37 insertions and 17 deletions:
0 comments (0 inline, 0 general)
src/i2c.c
Show inline comments
 
@@ -15,29 +15,36 @@ void i2c_init(void)
 
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
 
    GPIO_InitStruct.Pull = GPIO_NOPULL;
 
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
 
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
 
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
 
    __I2C1_CLK_ENABLE();
 
 
    hi2c1.Instance = I2C1;
 
    hi2c1.Init.Timing = 0x2000090E;
 
    hi2c1.Init.OwnAddress1 = 0;
 
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
 
    hi2c1.Init.OwnAddress2 = 0;
 
    hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
 
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
 
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
 
    HAL_I2C_Init(&hi2c1);
 
 
    HAL_I2CEx_AnalogFilter_Config(&hi2c1, I2C_ANALOGFILTER_ENABLED);
 
}
 
 
 
void i2c_deinit(void)
 
{
 
    HAL_I2C_DeInit(&hi2c1);
 
    __I2C1_CLK_DISABLE();
 
}
 
 
 
// Get pointer to I2C port
 
I2C_HandleTypeDef* i2c_get(void)
 
{
 
    return &hi2c1;
 
}
src/main.c
Show inline comments
 
@@ -17,72 +17,71 @@
 
// 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
 
};
 
 
static void __calc_gridloc(char *dst, double lat, double lon);
 
static void ledpulse(void);
 
 
uint32_t statled_ontime = 0;
 
 
 
int main(void)
 
{
 
    HAL_Init();
 
 
    sysclk_init();
 
    rtc_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)
 
    	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, 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));
 
            	}
 
@@ -129,66 +128,66 @@ int main(void)
 
                    // 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_SLOW;
 
            	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);
 
 
						last_wspr_tx_time = HAL_GetTick();
 
						wspr_transmit(grid_locator);
 
						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)
 
        {
 
            ledpulse();
 
            led_timer = HAL_GetTick();
 
        }
 
src/wspr.c
Show inline comments
 
@@ -9,110 +9,124 @@
 

	
 
#define WSPR_DEFAULT_FREQ 10140100UL
 
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
 
#define WSPR_CTC 10672 // CTC value for WSPR
 

	
 
// Test stuff
 
char call[7] = "KD8TDF";
 
char loc[5] = "EN72";
 
uint8_t dbm = 10;
 
uint8_t tx_buffer[255];
 

	
 
// Frequencies and channel info
 
uint32_t freq = WSPR_DEFAULT_FREQ;
 
uint8_t symbol_count = WSPR_SYMBOL_COUNT;
 
uint16_t ctc = WSPR_CTC;
 
uint16_t tone_spacing = WSPR_TONE_SPACING;
 
volatile uint8_t proceed = 0;
 

	
 
TIM_HandleTypeDef htim1;
 

	
 

	
 

	
 
void wspr_init(void)
 
{
 
    // Start timer for WSPR
 
    __TIM1_CLK_ENABLE();
 
    htim1.Instance = TIM1;
 
    htim1.Init.Prescaler = 512; // gives 64uS ticks from 8MHz ahbclk
 
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
 
    htim1.Init.Period = ctc; // Count up to this value (how many 64uS ticks per symbol)
 
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 
    htim1.Init.RepetitionCounter = 0;
 
    HAL_TIM_Base_Init(&htim1);
 
    HAL_TIM_Base_Start_IT(&htim1);
 
    HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0, 0);
 
    HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
 

	
 
    // Turn off ICs
 
    HAL_GPIO_WritePin(OSC_NOTEN, 1);
 
    HAL_GPIO_WritePin(TCXO_EN, 0);
 
}
 

	
 
// Do anything needed to prepare for sleep
 
void wspr_sleep(void)
 
{
 
    HAL_TIM_Base_Stop_IT(&htim1);
 
}
 

	
 
void wspr_wakeup(void)
 
{
 
    HAL_TIM_Base_Start_IT(&htim1);
 
}
 

	
 

	
 
// Bring up TCXO and oscillator IC
 
void wspr_transmit(uint8_t* grid_locator)
 
{
 
	// 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';
 

	
 

	
 
    // Start timer for WSPR
 
    __TIM1_CLK_ENABLE();
 
    htim1.Instance = TIM1;
 
    htim1.Init.Prescaler = 512; // gives 64uS ticks from 8MHz ahbclk
 
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
 
    htim1.Init.Period = ctc; // Count up to this value (how many 64uS ticks per symbol)
 
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 
    htim1.Init.RepetitionCounter = 0;
 
    HAL_TIM_Base_Init(&htim1);
 
    HAL_TIM_Base_Start_IT(&htim1);
 
    HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0, 0);
 
    HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
 

	
 

	
 
    HAL_GPIO_WritePin(OSC_NOTEN, 0);
 
    HAL_GPIO_WritePin(TCXO_EN, 1);
 
    HAL_Delay(100);
 

	
 
    // Bring up the chip
 
    i2c_init();
 
    si5351_init(i2c_get(), SI5351_CRYSTAL_LOAD_8PF, 0);
 
    si5351_set_correction(0);
 
    //si5351_set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
 
    //si5351_set_ms_source(SI5351_CLK0, SI5351_PLLA);
 
    si5351_set_freq(WSPR_DEFAULT_FREQ * 100, 0, SI5351_CLK0);
 
    si5351_drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power if desired (8ma max)
 
    si5351_output_enable(SI5351_CLK0, 1);
 
    //si5351_pll_reset(SI5351_PLLA);
 

	
 
    // Make sure the other outputs of the SI5351 are disabled
 
    si5351_output_enable(SI5351_CLK1, 0); // Disable the clock initially
 
    si5351_output_enable(SI5351_CLK2, 0); // Disable the clock initially
 

	
 
    // disable clock powers
 
    si5351_set_clock_pwr(SI5351_CLK1, 0);
 
    si5351_set_clock_pwr(SI5351_CLK2, 0);
 

	
 

	
 
    // Encode message to transmit
 
    wspr_encode(call, loc, dbm, tx_buffer);
 

	
 
    // Key transmitter
 
    si5351_output_enable(SI5351_CLK0, 1);
 

	
 
    // Loop through and transmit symbols TODO: Do this from an ISR or ISR-triggered main loop function call (optimal)
 
    uint8_t i;
 
    for(i=0; i<symbol_count; i++)
 
    {
 
        uint32_t freq2 = (freq * 100) + (tx_buffer[i] * tone_spacing);
 
        si5351_set_freq(freq2, 0, SI5351_CLK0);
 
        HAL_GPIO_TogglePin(LED_BLUE);
 

	
 
        proceed = 0;
 
        while(!proceed);
 
    }
 

	
 
    // Disable transmitter
 
    si5351_output_enable(SI5351_CLK0, 0);
 

	
 
    HAL_GPIO_WritePin(OSC_NOTEN, 1);
 
    HAL_GPIO_WritePin(TCXO_EN, 0);
 

	
 
    i2c_deinit();
 

	
 
    // Disable timer
 
    HAL_NVIC_DisableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
 
    HAL_TIM_Base_Stop_IT(&htim1);
 
    HAL_TIM_Base_DeInit(&htim1);
 

	
 
    __TIM1_CLK_DISABLE();
 

	
 

	
 
}
 

	
0 comments (0 inline, 0 general)