pico-tracker/firmware/src/main.c

256 wiersze
6.7 KiB
C
Czysty Zwykły widok Historia

2014-07-13 13:33:10 +00:00
/*
* Bristol SEDS pico-tracker
2014-07-13 13:33:10 +00:00
* Copyright (C) 2014 Richard Meadows <richardeoin>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <math.h>
2014-08-31 10:54:20 +00:00
#include <string.h>
#include "samd20.h"
2014-07-13 13:33:10 +00:00
#include "semihosting.h"
#include "hw_config.h"
#include "system/system.h"
#include "sercom/usart.h"
#include "system/port.h"
2014-08-30 20:11:35 +00:00
#include "tc/tc_driver.h"
#include "gps.h"
2014-08-31 10:02:22 +00:00
#include "system/wdt.h"
#include "timepulse.h"
2014-08-31 10:02:22 +00:00
#include "telemetry.h"
//#include "si406x.h"
#include "si4060.h"
#include "spi_bitbang.h"
2014-08-30 20:11:35 +00:00
#include "rtty.h"
#include "system/interrupt.h"
void si4060_hw_init(void)
{
/* Configure the SDN pin */
port_pin_set_config(SI406X_SDN_PIN,
PORT_PIN_DIR_OUTPUT, /* Direction */
PORT_PIN_PULL_NONE, /* Pull */
false); /* Powersave */
/* Put the SI406x in shutdown */
//_si406x_sdn_enable();
si4060_shutdown();
/* Configure the SDN pin */
port_pin_set_config(SI406X_SEL_PIN,
PORT_PIN_DIR_OUTPUT, /* Direction */
PORT_PIN_PULL_NONE, /* Pull */
false); /* Powersave */
/* Put the SEL pin in reset */
_si406x_cs_disable();
2014-08-30 20:11:35 +00:00
/* Configure the serial port */
spi_bitbang_init(SI406X_SERCOM_MOSI_PIN,
SI406X_SERCOM_MISO_PIN,
SI406X_SERCOM_SCK_PIN);
}
void si4060_gpio_init()
{
/* Configure the GPIO and IRQ pins */
port_pin_set_config(SI406X_GPIO0_PIN,
PORT_PIN_DIR_OUTPUT, /* Direction */
PORT_PIN_PULL_NONE, /* Pull */
false); /* Powersave */
port_pin_set_output_level(SI406X_GPIO0_PIN, 0);
2014-08-30 20:11:35 +00:00
/* Configure the GPIO and IRQ pins */
port_pin_set_config(SI406X_GPIO1_PIN,
PORT_PIN_DIR_OUTPUT, /* Direction */
PORT_PIN_PULL_NONE, /* Pull */
false); /* Powersave */
port_pin_set_output_level(SI406X_GPIO1_PIN, 0);
}
/**
* Initialises the status LED
*/
static inline void led_init(void)
{
port_pin_set_config(LED0_PIN,
PORT_PIN_DIR_OUTPUT, /* Direction */
PORT_PIN_PULL_NONE, /* Pull */
false); /* Powersave */
port_pin_set_output_level(LED0_PIN, 1); /* LED is active low */
}
/**
* Turns the status LED on
*/
static inline void led_on(void)
{
port_pin_set_output_level(LED0_PIN, 0); /* LED is active low */
}
/**
* Turns the status lED off
*/
static inline void led_off(void)
{
port_pin_set_output_level(LED0_PIN, 1); /* LED is active low */
}
2014-08-30 20:11:35 +00:00
void set_timer(uint32_t time)
{
bool capture_channel_enables[] = {false, false};
uint32_t compare_channel_values[] = {time, 0x0000};
tc_init(TC2,
GCLK_GENERATOR_0,
TC_COUNTER_SIZE_32BIT,
TC_CLOCK_PRESCALER_DIV1,
TC_WAVE_GENERATION_NORMAL_FREQ,
TC_RELOAD_ACTION_GCLK,
TC_COUNT_DIRECTION_UP,
TC_WAVEFORM_INVERT_OUTPUT_NONE,
false, /* Oneshot = false */
false, /* Run in standby = false */
0x0000, /* Initial value */
time+1, /* Top value */
capture_channel_enables, /* Capture Channel Enables */
compare_channel_values); /* Compare Channels Values */
struct tc_events ev;
memset(&ev, 0, sizeof(ev));
ev.generate_event_on_compare_channel[0] = true;
ev.event_action = TC_EVENT_ACTION_RETRIGGER;
tc_enable_events(TC2, &ev);
irq_register_handler(TC2_IRQn, 3);
tc_enable(TC2);
tc_start_counter(TC2);
}
/* void wdt_init() { */
/* /\* 64 seconds timeout. So 2^(15+6) cycles of the wdt clock *\/ */
/* system_gclk_gen_set_config(WDT_GCLK, */
/* GCLK_SOURCE_OSCULP32K, /\* Source *\/ */
/* false, /\* High When Disabled *\/ */
/* 128, /\* Division Factor *\/ */
/* false, /\* Run in standby *\/ */
/* true); /\* Output Pin Enable *\/ */
/* system_gclk_gen_enable(WDT_GCLK); */
/* /\* Set the watchdog timer. On 256Hz gclk 4 *\/ */
/* wdt_set_config(true, /\* Lock WDT *\/ */
/* true, /\* Enable WDT *\/ */
/* GCLK_GENERATOR_4, /\* Clock Source *\/ */
/* WDT_PERIOD_16384CLK, /\* Timeout Period *\/ */
/* WDT_PERIOD_NONE, /\* Window Period *\/ */
/* WDT_PERIOD_NONE); /\* Early Warning Period *\/ */
/* } */
2014-07-13 13:33:10 +00:00
int main(void)
{
/**
* Internal initialisation
* ---------------------------------------------------------------------------
*/
2014-08-30 20:11:35 +00:00
/* Clock up to 14MHz with 0 wait states */
system_flash_set_waitstates(SYSTEM_WAIT_STATE_1_8V_14MHZ);
2014-07-13 13:33:10 +00:00
/* Up the clock rate to 4MHz */
system_clock_source_osc8m_set_config(SYSTEM_OSC8M_DIV_2, /* Prescaler */
false, /* Run in Standby */
false); /* Run on Demand */
/* Restart the GCLK Module */
system_gclk_init();
2014-07-13 13:33:10 +00:00
/* Get the current CPU Clock */
SystemCoreClock = system_cpu_clock_get_hz();
/* Configure Sleep Mode */
system_set_sleepmode(SYSTEM_SLEEPMODE_IDLE_0);
//TODO: system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY);
/* Configure the SysTick for 50Hz triggering */
SysTick_Config(SystemCoreClock / 50);
2014-07-13 13:33:10 +00:00
/**
* System initialisation
* ---------------------------------------------------------------------------
*/
2014-08-31 10:54:20 +00:00
led_init();
gps_init();
/* Initialise Si4060 */
si4060_hw_init();
2014-10-08 15:08:36 +00:00
si4060_gpio_init();
si4060_reset();
/* check radio communication */
int i = si4060_part_info();
if (i != 0x4063) {
while(1);
}
2014-10-08 15:08:36 +00:00
si4060_power_up();
si4060_setup(MOD_TYPE_2FSK);
2014-08-31 10:02:22 +00:00
2014-10-08 15:08:36 +00:00
si4060_gpio_init();
si4060_start_tx(0);
2014-08-30 20:11:35 +00:00
while (1) {
2014-08-30 20:11:35 +00:00
/* Send the last packet */
2014-10-08 15:08:36 +00:00
while (rtty_active());
2014-08-31 10:54:20 +00:00
2014-10-08 15:08:36 +00:00
port_pin_set_output_level(SI406X_GPIO0_PIN, 0);
2014-08-31 10:02:22 +00:00
2014-08-30 20:11:35 +00:00
/* Send requests to the gps */
gps_update();
2014-08-30 20:11:35 +00:00
/* Wait between frames */
led_on();
for (int i = 0; i < 100*1000; i++);
led_off();
2014-08-30 20:11:35 +00:00
for (int i = 0; i < 100*1000; i++);
2014-08-30 20:11:35 +00:00
/* Set the next packet */
2014-10-08 15:08:36 +00:00
set_telemetry_string();
2014-08-31 10:54:20 +00:00
2014-10-08 15:08:36 +00:00
port_pin_set_output_level(SI406X_GPIO0_PIN, 1);
2014-08-31 10:54:20 +00:00
//system_sleep();
}
2014-07-13 13:33:10 +00:00
}
2014-08-30 20:11:35 +00:00
/**
* Called at 50Hz
*/
2014-07-13 13:33:10 +00:00
void SysTick_Handler(void)
{
2014-08-30 20:11:35 +00:00
/* Output RTTY */
rtty_tick();
2014-07-13 13:33:10 +00:00
}