-
Notifications
You must be signed in to change notification settings - Fork 4
/
hadie.c
189 lines (155 loc) · 3.89 KB
/
hadie.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/* 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. */
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <util/delay.h>
#include <util/crc16.h>
#include <avr/interrupt.h>
#include "rtty.h"
#include "gps.h"
#include "c328.h"
#include "rs8.h"
#include "ssdv.h"
/* Message buffer */
#define MSG_SIZE (100)
char msg[MSG_SIZE];
#define PREFIX "$$"
/* Image TX data */
uint8_t pkt[SSDV_PKT_SIZE], img[64];
/* 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 */
char tx_image(void)
{
static char setup = 0;
static uint8_t img_id = 0;
static ssdv_t ssdv;
int r;
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);
}
setup = -1;
ssdv_enc_init(&ssdv, CALLSIGN, img_id++);
ssdv_enc_set_buffer(&ssdv, pkt);
}
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);
}
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);
}
if(ssdv.state == S_EOI || c3_eof())
{
/* The end of the image has been reached */
c3_close();
setup = 0;
}
/* Got the packet! Transmit it */
rtx_data(pkt, SSDV_PKT_SIZE);
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,?",
counter++,
gps.hour, gps.minute, gps.second,
(gps.latitude_h == 'S' ? "-" : ""),
gps.latitude_i, gps.latitude_f,
(gps.longitude_h == 'W' ? "-" : ""),
gps.longitude_i, gps.longitude_f,
gps.altitude, gps.fix, gps.sats);
/* Append the checksum, skipping the $$ prefix */
crccat(msg + 2);
/* Begin transmitting */
rtx_string(msg);
/* 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"));
}
return(0);
}
int main(void)
{
char r;
/* Initalise the various bits */
rtx_init();
gps_init();
c3_init();
/* Turn on the radio and let it settle before beginning */
rtx_enable(1);
_delay_ms(2000);
/* Start interrupts and enter the main loop */
sei();
while(1)
{
if(tx_image() == -1)
{
/* The camera goes to sleep while transmitting telemetry,
* sync'ing here seems to prevent it. */
c3_sync();
rtx_string_P(PSTR("\n"));
r = 1;
}
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;
}
for(; r > 0; r--) tx_telemetry();
}
return(0);
}