pico-tracker/firmware/src/main.c

366 wiersze
8.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"
#include "system/events.h"
#include "system/extint.h"
2014-08-30 20:11:35 +00:00
#include "tc/tc_driver.h"
#include "gps.h"
#include "mfsk.h"
#include "ubx_messages.h"
2014-08-31 10:02:22 +00:00
#include "system/wdt.h"
#include "xosc.h"
2014-08-31 10:02:22 +00:00
#include "telemetry.h"
#include "contestia.h"
#include "rsid.h"
#include "si_trx.h"
#include "si_trx_defs.h"
#include "analogue.h"
#include "spi_bitbang.h"
2014-08-30 20:11:35 +00:00
#include "system/interrupt.h"
#define CALLSIGN "UBSEDSx"
/**
* Initialises the status LED
*/
static inline void led_init(void)
{
port_pin_set_config(LED0_PIN,
PORT_PIN_DIR_INPUT, /* 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 */
}
/**
2015-03-07 16:02:22 +00:00
* 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
/**
* Power Management
*/
void powermananger_init(void)
{
system_apb_clock_clear_mask(SYSTEM_CLOCK_APB_APBA,
PM_APBAMASK_EIC | /* EIC is unused */
PM_APBAMASK_RTC); /* RTC is unused */
}
/**
* Telemetry String
* =============================================================================
*/
void output_telemetry_string(enum telemetry_t type)
{
double lat_fmt = 0.0;
double lon_fmt = 0.0;
uint32_t altitude = 0;
uint16_t len;
uint8_t dollars = 2;
/**
* Collect Data
* ---------------------------------------------------------------------------
*/
/* Analogue */
float battery = get_battery();
float temperature = si_trx_get_temperature(); // Requires control of the radio - radio on also??
/* GPS Time */
gps_update_time();
/* Sleep Wait */
while (gps_update_time_pending()) {
system_sleep();
}
/* Time */
struct ubx_nav_timeutc time = gps_get_nav_timeutc();
uint8_t hours = time.payload.hour;
uint8_t minutes = time.payload.min;
uint8_t seconds = time.payload.sec;
/* Request updates from the gps */
gps_update_position();
if (gps_is_locked()) {
led_on();
} else {
led_off();
}
/* Wait for the gps update */
while (gps_update_position_pending()) {
system_sleep();
}
if (gps_is_locked()) {
led_off();
} else {
led_on();
}
/* GPS Status */
struct ubx_nav_sol sol = gps_get_nav_sol();
uint8_t lock = sol.payload.gpsFix;
uint8_t satillite_count = sol.payload.numSV;
/* GPS Position */
if (lock == 0x2 || lock == 0x3 || lock == 0x4) {
struct ubx_nav_posllh pos = gps_get_nav_posllh();
lat_fmt = (double)pos.payload.lat / 10000000.0;
lon_fmt = (double)pos.payload.lon / 10000000.0;
altitude = pos.payload.height / 1000;
}
/**
* Format
* ---------------------------------------------------------------------------
*/
if (type == TELEMETRY_RTTY) {
dollars = 5; // Extra dollars for RTTY
}
/* sprintf - preamble */
memset(telemetry_string, '$', dollars);
len = dollars;
/* sprintf - full string */
len += sprintf(telemetry_string + len,
2015-03-07 16:02:22 +00:00
"%s,%02u:%02u:%02u,%02.5f,%03.5f,%ld,%u,%.2f,%.1f",
2014-10-25 22:36:44 +00:00
CALLSIGN, hours, minutes, seconds, lat_fmt, lon_fmt,
altitude, satillite_count, battery, temperature);
if (type == TELEMETRY_CONTESTIA) { contestiaize(telemetry_string + dollars); }
/* sprintf - checksum. don't include dollars */
len += sprintf(telemetry_string + len,
"*%04X\r",
crc_checksum(telemetry_string + dollars));
/**
* Starting up the radio blocks on high-prio interrupt for ~100ms: todo fixme
*/
/* RSID */
/* start - SI NOW BELONGS TO TELEMETRY, WE CANNOT ACCESS */
if (type == TELEMETRY_CONTESTIA) {
telemetry_start_rsid(RSID_CONTESTIA_32_1000);
}
/* Sleep Wait for RSID to be done */
while (telemetry_active()) {
system_sleep();
}
/* Main telemetry */
telemetry_start(type, len);
/* Sleep Wait */
while (telemetry_active()) {
system_sleep();
}
}
/**
2015-03-13 19:42:01 +00:00
* Internal initialisation
* =============================================================================
*/
2015-03-13 19:42:01 +00:00
void init(void)
2014-07-13 13:33:10 +00:00
{
/**
* 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();
system_events_init();
system_extint_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_STANDBY);
system_set_sleepmode(SYSTEM_SLEEPMODE_IDLE_2); /* Disable CPU, AHB and APB */
/* Configure the Power Manager */
//powermananger_init();
/**
* System initialisation
* ---------------------------------------------------------------------------
*/
2014-08-31 10:54:20 +00:00
/* Set the wdt here. We should get to the first reset in one min */
//wdt_init();
//wdt_reset_count();
2015-03-13 19:42:01 +00:00
xosc_init();
led_init();
gps_init();
/* Initialise Si4060 interface */
si_trx_init();
2015-03-13 19:42:01 +00:00
}
2014-08-30 20:11:35 +00:00
void xosc_measure_callback(uint32_t result)
{
}
2015-03-13 19:42:01 +00:00
/**
* MAIN
* =============================================================================
*/
int main(void)
{
init();
measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback);
while (1) {
system_sleep();
}
led_on();
while (1) {
/* Watchdog */
//wdt_reset_count();
2014-08-31 10:54:20 +00:00
/* Send the next packet */
output_telemetry_string(TELEMETRY_RTTY);
telemetry_start(TELEMETRY_PIPS, 5);
/* Sleep Wait */
while (telemetry_active()) {
system_sleep();
}
/* Send the next packet */
output_telemetry_string(TELEMETRY_CONTESTIA);
telemetry_start(TELEMETRY_PIPS, 5);
/* Sleep Wait */
while (telemetry_active()) {
system_sleep();
}
}
2014-07-13 13:33:10 +00:00
}