Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.

Dependencies:   mbed

Committer:
AjK
Date:
Mon Oct 11 10:34:55 2010 +0000
Revision:
0:0a841b89d614
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:0a841b89d614 1 /****************************************************************************
AjK 0:0a841b89d614 2 * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
AjK 0:0a841b89d614 3 *
AjK 0:0a841b89d614 4 * This file is part of the Satellite Observers Workbench (SOWB).
AjK 0:0a841b89d614 5 *
AjK 0:0a841b89d614 6 * SOWB is free software: you can redistribute it and/or modify
AjK 0:0a841b89d614 7 * it under the terms of the GNU General Public License as published by
AjK 0:0a841b89d614 8 * the Free Software Foundation, either version 3 of the License, or
AjK 0:0a841b89d614 9 * (at your option) any later version.
AjK 0:0a841b89d614 10 *
AjK 0:0a841b89d614 11 * SOWB is distributed in the hope that it will be useful,
AjK 0:0a841b89d614 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
AjK 0:0a841b89d614 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
AjK 0:0a841b89d614 14 * GNU General Public License for more details.
AjK 0:0a841b89d614 15 *
AjK 0:0a841b89d614 16 * You should have received a copy of the GNU General Public License
AjK 0:0a841b89d614 17 * along with SOWB. If not, see <http://www.gnu.org/licenses/>.
AjK 0:0a841b89d614 18 *
AjK 0:0a841b89d614 19 * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
AjK 0:0a841b89d614 20 *
AjK 0:0a841b89d614 21 ***************************************************************************/
AjK 0:0a841b89d614 22
AjK 0:0a841b89d614 23 #include "sowb.h"
AjK 0:0a841b89d614 24 #include "debug.h"
AjK 0:0a841b89d614 25 #include "osd.h"
AjK 0:0a841b89d614 26 #include "gps.h"
AjK 0:0a841b89d614 27 #include "satapi.h"
AjK 0:0a841b89d614 28 #include "utils.h"
AjK 0:0a841b89d614 29 #include "nexstar.h"
AjK 0:0a841b89d614 30
AjK 0:0a841b89d614 31 int test_counter = 0;
AjK 0:0a841b89d614 32
AjK 0:0a841b89d614 33 /* Define the array of OSD dislay lines. */
AjK 0:0a841b89d614 34 OSD_display_line osd_display_area[MAX7456_DISPLAY_LINES];
AjK 0:0a841b89d614 35
AjK 0:0a841b89d614 36 /* Toggle between odd and even fields. */
AjK 0:0a841b89d614 37 int video_field;
AjK 0:0a841b89d614 38
AjK 0:0a841b89d614 39 /* The top two display lines have a special use case. This int
AjK 0:0a841b89d614 40 is used to select the mode in which it works. */
AjK 0:0a841b89d614 41 int l01_mode;
AjK 0:0a841b89d614 42
AjK 0:0a841b89d614 43 /* Handles whether and how the crosshair is displayed. */
AjK 0:0a841b89d614 44 int crosshair_mode;
AjK 0:0a841b89d614 45
AjK 0:0a841b89d614 46
AjK 0:0a841b89d614 47 /** osd_init
AjK 0:0a841b89d614 48 */
AjK 0:0a841b89d614 49 void osd_init(void) {
AjK 0:0a841b89d614 50
AjK 0:0a841b89d614 51 DEBUG_INIT_START;
AjK 0:0a841b89d614 52 video_field = 0;
AjK 0:0a841b89d614 53 l01_mode = 0;
AjK 0:0a841b89d614 54 crosshair_mode = 1;
AjK 0:0a841b89d614 55 osd_clear();
AjK 0:0a841b89d614 56 DEBUG_INIT_END;
AjK 0:0a841b89d614 57 }
AjK 0:0a841b89d614 58
AjK 0:0a841b89d614 59 /** osd_clear
AjK 0:0a841b89d614 60 *
AjK 0:0a841b89d614 61 * Clear the display area buffer.
AjK 0:0a841b89d614 62 */
AjK 0:0a841b89d614 63 void osd_clear(void) {
AjK 0:0a841b89d614 64 for (int i = 0; i < MAX7456_DISPLAY_LINES; i++) {
AjK 0:0a841b89d614 65 osd_clear_line(i);
AjK 0:0a841b89d614 66 }
AjK 0:0a841b89d614 67 }
AjK 0:0a841b89d614 68
AjK 0:0a841b89d614 69 /** osd_clear_line
AjK 0:0a841b89d614 70 *
AjK 0:0a841b89d614 71 * Clear a single line.
AjK 0:0a841b89d614 72 *
AjK 0:0a841b89d614 73 * @param int line The line to clear.
AjK 0:0a841b89d614 74 */
AjK 0:0a841b89d614 75 void osd_clear_line(int line) {
AjK 0:0a841b89d614 76 for (int i = 0; i < MAX7456_DISPLAY_LINE_LEN; i++) {
AjK 0:0a841b89d614 77 osd_display_area[line].line_buffer[i] = '\0';
AjK 0:0a841b89d614 78 }
AjK 0:0a841b89d614 79 osd_display_area[line].update = true;
AjK 0:0a841b89d614 80 }
AjK 0:0a841b89d614 81
AjK 0:0a841b89d614 82 /** osd_string
AjK 0:0a841b89d614 83 *
AjK 0:0a841b89d614 84 * Write a null terminated string to a display line.
AjK 0:0a841b89d614 85 *
AjK 0:0a841b89d614 86 * @param int line The display line to write to.
AjK 0:0a841b89d614 87 * @param char *s The null terminated string.
AjK 0:0a841b89d614 88 */
AjK 0:0a841b89d614 89 void osd_string(int line, char *s) {
AjK 0:0a841b89d614 90 for (int i = 0; *s; s++, i++) {
AjK 0:0a841b89d614 91 osd_display_area[line].line_buffer[i] = *s;
AjK 0:0a841b89d614 92 }
AjK 0:0a841b89d614 93 osd_display_area[line].update = true;
AjK 0:0a841b89d614 94 }
AjK 0:0a841b89d614 95
AjK 0:0a841b89d614 96 /** osd_string_xy
AjK 0:0a841b89d614 97 *
AjK 0:0a841b89d614 98 * Write a null terminated string to a display line at x y.
AjK 0:0a841b89d614 99 *
AjK 0:0a841b89d614 100 * @param int line The display line to write to.
AjK 0:0a841b89d614 101 * @param char *s The null terminated string.
AjK 0:0a841b89d614 102 */
AjK 0:0a841b89d614 103 void osd_string_xy(int x, int y, char *s) {
AjK 0:0a841b89d614 104 for (int i = x; *s; s++, i++) {
AjK 0:0a841b89d614 105 osd_display_area[y].line_buffer[i] = *s;
AjK 0:0a841b89d614 106 }
AjK 0:0a841b89d614 107 osd_display_area[y].update = true;
AjK 0:0a841b89d614 108 }
AjK 0:0a841b89d614 109
AjK 0:0a841b89d614 110 /** osd_string_xyl
AjK 0:0a841b89d614 111 *
AjK 0:0a841b89d614 112 * Write a null terminated string to a display line at x y.
AjK 0:0a841b89d614 113 *
AjK 0:0a841b89d614 114 * @param int line The display line to write to.
AjK 0:0a841b89d614 115 * @param char *s The null terminated string.
AjK 0:0a841b89d614 116 * @param int len The length of the string to print.
AjK 0:0a841b89d614 117 */
AjK 0:0a841b89d614 118 void osd_string_xyl(int x, int y, char *s, int len) {
AjK 0:0a841b89d614 119 for (int i = x; len; s++, i++, len--) {
AjK 0:0a841b89d614 120 osd_display_area[y].line_buffer[i] = *s;
AjK 0:0a841b89d614 121 }
AjK 0:0a841b89d614 122 osd_display_area[y].update = true;
AjK 0:0a841b89d614 123 }
AjK 0:0a841b89d614 124
AjK 0:0a841b89d614 125 /** osd_stringl
AjK 0:0a841b89d614 126 *
AjK 0:0a841b89d614 127 * Write a string of specified length to a display line.
AjK 0:0a841b89d614 128 *
AjK 0:0a841b89d614 129 * @param int line The display line to write to.
AjK 0:0a841b89d614 130 * @param char *s The string.
AjK 0:0a841b89d614 131 * @param int len The length to write.
AjK 0:0a841b89d614 132 */
AjK 0:0a841b89d614 133 void osd_stringl(int line, char *s, int len) {
AjK 0:0a841b89d614 134 for (int i = 0; len; s++, i++, len--) {
AjK 0:0a841b89d614 135 osd_display_area[line].line_buffer[i] = *s;
AjK 0:0a841b89d614 136 }
AjK 0:0a841b89d614 137 osd_display_area[line].update = true;
AjK 0:0a841b89d614 138 }
AjK 0:0a841b89d614 139
AjK 0:0a841b89d614 140 /** osd_get_mode_l01
AjK 0:0a841b89d614 141 */
AjK 0:0a841b89d614 142 int osd_get_mode_l01(void) {
AjK 0:0a841b89d614 143 return l01_mode;
AjK 0:0a841b89d614 144 }
AjK 0:0a841b89d614 145
AjK 0:0a841b89d614 146 /** osd_set_mode_l01
AjK 0:0a841b89d614 147 */
AjK 0:0a841b89d614 148 void osd_set_mode_l01(int mode) {
AjK 0:0a841b89d614 149 l01_mode = mode;
AjK 0:0a841b89d614 150 }
AjK 0:0a841b89d614 151
AjK 0:0a841b89d614 152 /** osd_l01_next_mode
AjK 0:0a841b89d614 153 */
AjK 0:0a841b89d614 154 void osd_l01_next_mode(void) {
AjK 0:0a841b89d614 155 int m = osd_get_mode_l01();
AjK 0:0a841b89d614 156 m++;
AjK 0:0a841b89d614 157 if (m > L01_MODE_D) m = L01_MODE_A;
AjK 0:0a841b89d614 158 osd_set_mode_l01(m);
AjK 0:0a841b89d614 159 }
AjK 0:0a841b89d614 160
AjK 0:0a841b89d614 161 /** osd_set_crosshair
AjK 0:0a841b89d614 162 */
AjK 0:0a841b89d614 163 int osd_set_crosshair(int mode) {
AjK 0:0a841b89d614 164 if (mode > -1) {
AjK 0:0a841b89d614 165 crosshair_mode = mode;
AjK 0:0a841b89d614 166 }
AjK 0:0a841b89d614 167 return crosshair_mode;
AjK 0:0a841b89d614 168 }
AjK 0:0a841b89d614 169
AjK 0:0a841b89d614 170 /** osd_crosshair_toggle
AjK 0:0a841b89d614 171 */
AjK 0:0a841b89d614 172 int osd_crosshair_toggle(void) {
AjK 0:0a841b89d614 173 crosshair_mode = crosshair_mode == 0 ? 1 : 0;
AjK 0:0a841b89d614 174 if (!crosshair_mode) osd_clear();
AjK 0:0a841b89d614 175 return crosshair_mode;
AjK 0:0a841b89d614 176 }
AjK 0:0a841b89d614 177
AjK 0:0a841b89d614 178 /** osd_write_buffers
AjK 0:0a841b89d614 179 *
AjK 0:0a841b89d614 180 * Write the line buffers to the display.
AjK 0:0a841b89d614 181 */
AjK 0:0a841b89d614 182 static void osd_write_buffers(void) {
AjK 0:0a841b89d614 183 for (int i = 0; i < MAX7456_DISPLAY_LINES; i++) {
AjK 0:0a841b89d614 184 if (osd_display_area[i].update) {
AjK 0:0a841b89d614 185 MAX7456_cursor(0, i);
AjK 0:0a841b89d614 186 MAX7456_write_byte(0x04, 0x01); /* Enable 8bit write. */
AjK 0:0a841b89d614 187 for (int j = 0; j < MAX7456_DISPLAY_LINE_LEN; j++) {
AjK 0:0a841b89d614 188 MAX7456_write_byte(0x80, MAX7456_map_char(osd_display_area[i].line_buffer[j]));
AjK 0:0a841b89d614 189 }
AjK 0:0a841b89d614 190 MAX7456_write_byte(0x80, 0xFF);
AjK 0:0a841b89d614 191 osd_display_area[i].update = false;
AjK 0:0a841b89d614 192 }
AjK 0:0a841b89d614 193 }
AjK 0:0a841b89d614 194 }
AjK 0:0a841b89d614 195
AjK 0:0a841b89d614 196 void osd_l01_position(void) {
AjK 0:0a841b89d614 197 GPS_LOCATION_AVERAGE loc;
AjK 0:0a841b89d614 198 char buf[64], buf2[64];
AjK 0:0a841b89d614 199 double el, azm;
AjK 0:0a841b89d614 200
AjK 0:0a841b89d614 201 gps_get_location_average(&loc);
AjK 0:0a841b89d614 202
AjK 0:0a841b89d614 203 if (l01_mode != 0) {
AjK 0:0a841b89d614 204 if (IS_NEXSTAR_ALIGNED) {
AjK 0:0a841b89d614 205 nexstar_get_elazm(&el, &azm);
AjK 0:0a841b89d614 206 printDouble_3_2(buf, el); osd_string_xy(12, 0, buf);
AjK 0:0a841b89d614 207 printDouble_3_2(buf, azm); osd_string_xy(12, 1, buf);
AjK 0:0a841b89d614 208 }
AjK 0:0a841b89d614 209 else {
AjK 0:0a841b89d614 210 strcpy(buf, "---.--");
AjK 0:0a841b89d614 211 osd_string_xy(12, 0, buf);
AjK 0:0a841b89d614 212 osd_string_xy(12, 1, buf);
AjK 0:0a841b89d614 213 }
AjK 0:0a841b89d614 214 }
AjK 0:0a841b89d614 215
AjK 0:0a841b89d614 216 switch(l01_mode) {
AjK 0:0a841b89d614 217 case L01_MODE_C:
AjK 0:0a841b89d614 218 case L01_MODE_D:
AjK 0:0a841b89d614 219 double2dms(buf2, loc.latitude); sprintf(buf, "%c%s", loc.north_south, buf2); osd_string_xy(18, 0, buf);
AjK 0:0a841b89d614 220 double2dms(buf2, loc.longitude); sprintf(buf, "%c%s", loc.east_west, buf2); osd_string_xy(18, 1, buf);
AjK 0:0a841b89d614 221 break;
AjK 0:0a841b89d614 222 case L01_MODE_A:
AjK 0:0a841b89d614 223 case L01_MODE_B:
AjK 0:0a841b89d614 224 printDouble(buf2, loc.latitude); sprintf(buf, " %c%c%s", loc.is_valid, loc.north_south, buf2); osd_string_xy(18, 0, buf);
AjK 0:0a841b89d614 225 printDouble(buf2, loc.longitude); sprintf(buf, "%c%c%c%s", loc.sats[0] == '0' ? ' ' : loc.sats[0], loc.sats[1], loc.east_west, buf2); osd_string_xy(18, 1, buf);
AjK 0:0a841b89d614 226 break;
AjK 0:0a841b89d614 227 }
AjK 0:0a841b89d614 228 }
AjK 0:0a841b89d614 229
AjK 0:0a841b89d614 230 /** osd_vsync
AjK 0:0a841b89d614 231 *
AjK 0:0a841b89d614 232 * A callback made when the MAX7456 vertical sync fires.
AjK 0:0a841b89d614 233 */
AjK 0:0a841b89d614 234 void osd_vsync(void) {
AjK 0:0a841b89d614 235 GPS_TIME latched_time;
AjK 0:0a841b89d614 236 char buffer[32];
AjK 0:0a841b89d614 237
AjK 0:0a841b89d614 238 /* captire the time at which this VSync pulse occured. */
AjK 0:0a841b89d614 239 gps_get_time(&latched_time);
AjK 0:0a841b89d614 240
AjK 0:0a841b89d614 241 /* We don't actually know if this is an odd or even field.
AjK 0:0a841b89d614 242 All we can do is divide by two so each frame only displays
AjK 0:0a841b89d614 243 the time, otherwise it will "smudge" the display. We may
AjK 0:0a841b89d614 244 well add in an LM1881 device to the final design as that
AjK 0:0a841b89d614 245 has an odd/even field ttl output. */
AjK 0:0a841b89d614 246 if (!video_field) { video_field = 1; return; }
AjK 0:0a841b89d614 247 else { video_field = 0; }
AjK 0:0a841b89d614 248
AjK 0:0a841b89d614 249 /* If no mode is set, do not display line0/1. */
AjK 0:0a841b89d614 250 if (l01_mode == 0) return;
AjK 0:0a841b89d614 251
AjK 0:0a841b89d614 252 /* Display lines 0 and 1 are used for a specific feature, i.e.
AjK 0:0a841b89d614 253 the display of the time, GPS position, telescope pointing
AjK 0:0a841b89d614 254 position, etc. Handle the "time" display portion now. */
AjK 0:0a841b89d614 255 osd_clear_line(0);
AjK 0:0a841b89d614 256 osd_clear_line(1);
AjK 0:0a841b89d614 257
AjK 0:0a841b89d614 258 char buf2[32];
AjK 0:0a841b89d614 259 double jd = gps_julian_date(&latched_time);
AjK 0:0a841b89d614 260
AjK 0:0a841b89d614 261 if (crosshair_mode) {
AjK 0:0a841b89d614 262 osd_string_xy(13, 7, "\xE0\xE1");
AjK 0:0a841b89d614 263 }
AjK 0:0a841b89d614 264
AjK 0:0a841b89d614 265 switch(l01_mode) {
AjK 0:0a841b89d614 266 case L01_MODE_D:
AjK 0:0a841b89d614 267 case L01_MODE_B:
AjK 0:0a841b89d614 268 /* Display time as Julain Date. */
AjK 0:0a841b89d614 269 sprintf(buf2, "%.7f", jd - (long)jd);
AjK 0:0a841b89d614 270 memset(buffer, 0, 32); sprintf(buffer, "JDI %07ld", (long)jd); osd_string_xy(0, 0, buffer);
AjK 0:0a841b89d614 271 memset(buffer, 0, 32); sprintf(buffer, "JDF.%s", buf2 + 2); osd_string_xy(0, 1, buffer);
AjK 0:0a841b89d614 272 break;
AjK 0:0a841b89d614 273 case L01_MODE_C:
AjK 0:0a841b89d614 274 case L01_MODE_A:
AjK 0:0a841b89d614 275 /* Display time as UTC. */
AjK 0:0a841b89d614 276 memset(buffer, 0, 32); date_AsString(&latched_time, buffer); osd_string_xy(0, 0, buffer);
AjK 0:0a841b89d614 277 memset(buffer, 0, 32); time_AsString(&latched_time, buffer); osd_string_xy(0, 1, buffer);
AjK 0:0a841b89d614 278 break;
AjK 0:0a841b89d614 279 }
AjK 0:0a841b89d614 280
AjK 0:0a841b89d614 281 osd_l01_position();
AjK 0:0a841b89d614 282
AjK 0:0a841b89d614 283 #ifdef NEVECOMPILETHIS
AjK 0:0a841b89d614 284 /* TEST TEST TEST !!! */
AjK 0:0a841b89d614 285 /* Test failed. It actually worked, once. It seems the total math
AjK 0:0a841b89d614 286 involved in doing this is WAY to much to be inside what is effectively
AjK 0:0a841b89d614 287 an interrupt service routine. It does tell me lots, I need to move all
AjK 0:0a841b89d614 288 this to _process() but do it in a way that's fast enough for user output
AjK 0:0a841b89d614 289 in "real time" as it would appear to the user. */
AjK 0:0a841b89d614 290 test_counter++;
AjK 0:0a841b89d614 291 if (test_counter == 1000) {
AjK 0:0a841b89d614 292 test_counter = 0;
AjK 0:0a841b89d614 293 SAT_POS_DATA data;
AjK 0:0a841b89d614 294 data.tsince = 0;
AjK 0:0a841b89d614 295 strcpy(data.elements[0], "ISS (ZARYA)");
AjK 0:0a841b89d614 296 strcpy(data.elements[1], "1 25544U 98067A 10249.33655722 .00010912 00000-0 87866-4 0 8417");
AjK 0:0a841b89d614 297 strcpy(data.elements[2], "2 25544 051.6459 175.3962 0008058 342.0418 161.2933 15.71504826676236");
AjK 0:0a841b89d614 298 gps_get_time(&data.t);
AjK 0:0a841b89d614 299 gps_get_location_average(&data.l);
AjK 0:0a841b89d614 300 satallite_calculate(&data);
AjK 0:0a841b89d614 301 if (!isnan(data.elevation) && !isnan(data.azimuth) && !isnan(data.range)) {
AjK 0:0a841b89d614 302 sprintf(buffer, " ISS EL:%.1f AZM:%.1f RG:%.1f", data.elevation, data.azimuth, data.range);
AjK 0:0a841b89d614 303 osd_string_xy(0, 14, buffer);
AjK 0:0a841b89d614 304 }
AjK 0:0a841b89d614 305 }
AjK 0:0a841b89d614 306 /* TEST TEST TEST !!! */
AjK 0:0a841b89d614 307 #endif
AjK 0:0a841b89d614 308
AjK 0:0a841b89d614 309 osd_write_buffers();
AjK 0:0a841b89d614 310 }
AjK 0:0a841b89d614 311
AjK 0:0a841b89d614 312
AjK 0:0a841b89d614 313
AjK 0:0a841b89d614 314
AjK 0:0a841b89d614 315