hadie/hadie.c

190 wiersze
3.9 KiB
C

/* hadie - High Altitude Balloon flight software */
/*============================================================*/
/* Copyright (C)2010 Philip Heron <phil@sanslogic.co.uk> */
/* */
/* This program is distributed under the terms of the GNU */
/* General Public License, version 2. You may use, modify, */
/* and redistribute it under the terms of this license. A */
/* copy should be included with this source. */
2010-06-07 12:10:32 +00:00
#include "config.h"
2010-07-06 11:16:42 +00:00
#include <stdio.h>
#include <string.h>
2010-06-08 10:45:12 +00:00
#include <util/delay.h>
2010-06-09 15:32:22 +00:00
#include <util/crc16.h>
#include <avr/interrupt.h>
2010-06-08 10:19:37 +00:00
#include "rtty.h"
2010-08-03 22:42:15 +00:00
#include "gps.h"
2010-07-06 11:16:42 +00:00
#include "c328.h"
#include "rs8.h"
#include "ssdv.h"
2010-07-06 11:16:42 +00:00
/* Message buffer */
#define MSG_SIZE (100)
char msg[MSG_SIZE];
2010-10-12 10:43:18 +00:00
#define PREFIX "$$"
2010-08-03 22:42:15 +00:00
2010-07-06 11:16:42 +00:00
/* Image TX data */
uint8_t pkt[SSDV_PKT_SIZE], img[64];
2010-07-06 11:16:42 +00:00
/* State of the flight */
#define ALT_STEP (200)
static int32_t r_altitude = 0; /* Reference altitude */
static char ascent = 1; /* Direction of travel. 0 = Down, 1 = Up */
2010-07-06 11:16:42 +00:00
char tx_image(void)
2010-06-09 15:32:22 +00:00
{
2010-07-06 11:16:42 +00:00
static char setup = 0;
static uint8_t img_id = 0;
static ssdv_t ssdv;
int r;
2010-06-09 15:32:22 +00:00
2010-07-06 11:16:42 +00:00
if(!setup)
{
/* Don't begin transmitting a new image if the payload is falling */
if(ascent == 0) return(setup);
if(c3_open(SR_320x240) != 0)
{
rtx_string_P(PSTR(PREFIX CALLSIGN ":Camera error\n"));
return(setup);
}
2010-08-07 15:58:06 +00:00
setup = -1;
2012-03-04 23:36:37 +00:00
ssdv_enc_init(&ssdv, CALLSIGN, img_id++);
ssdv_enc_set_buffer(&ssdv, pkt);
2010-07-06 11:16:42 +00:00
}
while((r = ssdv_enc_get_packet(&ssdv)) == SSDV_FEED_ME)
{
size_t r = c3_read(img, 64);
if(r == 0) break;
ssdv_enc_feed(&ssdv, img, r);
}
2010-06-09 15:32:22 +00:00
if(r != SSDV_OK)
{
/* Something went wrong! */
c3_close();
setup = 0;
rtx_string_P(PSTR(PREFIX CALLSIGN ":ssdv_enc_get_packet() failed\n"));
return(setup);
}
2010-08-07 15:58:06 +00:00
if(ssdv.state == S_EOI || c3_eof())
2010-07-06 11:16:42 +00:00
{
/* The end of the image has been reached */
2010-08-07 15:58:06 +00:00
c3_close();
setup = 0;
2010-07-06 11:16:42 +00:00
}
/* Got the packet! Transmit it */
rtx_data(pkt, SSDV_PKT_SIZE);
2010-08-03 22:42:15 +00:00
return(setup);
}
uint16_t crccat(char *msg)
{
uint16_t x;
for(x = 0xFFFF; *msg; msg++)
x = _crc_xmodem_update(x, *msg);
snprintf(msg, 8, "*%04X\n", x);
return(x);
}
char tx_telemetry(void)
{
static unsigned int counter = 0;
gpsfix_t gps;
/* Read the GPS data */
gps_parse(&gps);
rtx_wait();
snprintf(msg, MSG_SIZE,
PREFIX CALLSIGN ",%u,%02i:%02i:%02i,%s%i.%06lu,%s%i.%06lu,%li,%i,%i,?",
2010-08-03 22:42:15 +00:00
counter++,
gps.hour, gps.minute, gps.second,
(gps.latitude_h == 'S' ? "-" : ""),
2010-08-03 22:42:15 +00:00
gps.latitude_i, gps.latitude_f,
(gps.longitude_h == 'W' ? "-" : ""),
2010-08-03 22:42:15 +00:00
gps.longitude_i, gps.longitude_f,
gps.altitude, gps.fix, gps.sats);
2010-10-12 10:43:18 +00:00
/* Append the checksum, skipping the $$ prefix */
crccat(msg + 2);
2010-08-03 22:42:15 +00:00
/* Begin transmitting */
rtx_string(msg);
2010-07-06 11:16:42 +00:00
/* Update the ascent / descent status */
if(gps.fix > 0)
{
int32_t i = ascent;
if(gps.altitude >= r_altitude + ALT_STEP)
{
/* Payload is rising */
ascent = 1;
r_altitude = gps.altitude;
}
else if(gps.altitude <= r_altitude - ALT_STEP)
{
/* Payload is falling */
ascent = 0;
r_altitude = gps.altitude;
}
/* If staring to fall above 4000 metres... */
if(gps.altitude >= 4000 && i == 1 && ascent == 0)
rtx_string_P(PSTR(PREFIX CALLSIGN ":Geronimo!!!!\n"));
}
2010-07-06 11:16:42 +00:00
return(0);
2010-06-09 15:32:22 +00:00
}
int main(void)
{
2010-08-03 22:42:15 +00:00
char r;
2010-07-06 11:16:42 +00:00
/* Initalise the various bits */
2010-06-08 10:19:37 +00:00
rtx_init();
2010-08-03 22:42:15 +00:00
gps_init();
2010-07-06 11:16:42 +00:00
c3_init();
/* Turn on the radio and let it settle before beginning */
rtx_enable(1);
2010-06-08 10:45:12 +00:00
_delay_ms(2000);
2010-07-06 11:16:42 +00:00
/* Start interrupts and enter the main loop */
sei();
2010-06-08 10:45:12 +00:00
while(1)
{
2010-08-03 22:42:15 +00:00
if(tx_image() == -1)
{
/* The camera goes to sleep while transmitting telemetry,
* sync'ing here seems to prevent it. */
c3_sync();
2011-01-08 17:06:05 +00:00
rtx_string_P(PSTR("\n"));
2010-08-03 22:42:15 +00:00
r = 1;
}
2011-01-08 17:06:05 +00:00
else
{
/* Put UBLOX5 GPS in proper nav mode */
if(gps_ubx_init() != 0)
rtx_string_P(PSTR(PREFIX CALLSIGN ":GPS mode set failed\n"));
r = 10;
}
2010-08-03 22:42:15 +00:00
for(; r > 0; r--) tx_telemetry();
}
return(0);
}