Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
osd.c
00001 /**************************************************************************** 00002 * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd 00003 * 00004 * This file is part of the Satellite Observers Workbench (SOWB). 00005 * 00006 * SOWB is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * SOWB is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with SOWB. If not, see <http://www.gnu.org/licenses/>. 00018 * 00019 * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $ 00020 * 00021 ***************************************************************************/ 00022 00023 #include "sowb.h" 00024 #include "debug.h" 00025 #include "osd.h" 00026 #include "gps.h" 00027 #include "satapi.h" 00028 #include "utils.h" 00029 #include "nexstar.h" 00030 00031 int test_counter = 0; 00032 00033 /* Define the array of OSD dislay lines. */ 00034 OSD_display_line osd_display_area[MAX7456_DISPLAY_LINES]; 00035 00036 /* Toggle between odd and even fields. */ 00037 int video_field; 00038 00039 /* The top two display lines have a special use case. This int 00040 is used to select the mode in which it works. */ 00041 int l01_mode; 00042 00043 /* Handles whether and how the crosshair is displayed. */ 00044 int crosshair_mode; 00045 00046 00047 /** osd_init 00048 */ 00049 void osd_init(void) { 00050 00051 DEBUG_INIT_START; 00052 video_field = 0; 00053 l01_mode = 0; 00054 crosshair_mode = 1; 00055 osd_clear(); 00056 DEBUG_INIT_END; 00057 } 00058 00059 /** osd_clear 00060 * 00061 * Clear the display area buffer. 00062 */ 00063 void osd_clear(void) { 00064 for (int i = 0; i < MAX7456_DISPLAY_LINES; i++) { 00065 osd_clear_line(i); 00066 } 00067 } 00068 00069 /** osd_clear_line 00070 * 00071 * Clear a single line. 00072 * 00073 * @param int line The line to clear. 00074 */ 00075 void osd_clear_line(int line) { 00076 for (int i = 0; i < MAX7456_DISPLAY_LINE_LEN; i++) { 00077 osd_display_area[line].line_buffer[i] = '\0'; 00078 } 00079 osd_display_area[line].update = true; 00080 } 00081 00082 /** osd_string 00083 * 00084 * Write a null terminated string to a display line. 00085 * 00086 * @param int line The display line to write to. 00087 * @param char *s The null terminated string. 00088 */ 00089 void osd_string(int line, char *s) { 00090 for (int i = 0; *s; s++, i++) { 00091 osd_display_area[line].line_buffer[i] = *s; 00092 } 00093 osd_display_area[line].update = true; 00094 } 00095 00096 /** osd_string_xy 00097 * 00098 * Write a null terminated string to a display line at x y. 00099 * 00100 * @param int line The display line to write to. 00101 * @param char *s The null terminated string. 00102 */ 00103 void osd_string_xy(int x, int y, char *s) { 00104 for (int i = x; *s; s++, i++) { 00105 osd_display_area[y].line_buffer[i] = *s; 00106 } 00107 osd_display_area[y].update = true; 00108 } 00109 00110 /** osd_string_xyl 00111 * 00112 * Write a null terminated string to a display line at x y. 00113 * 00114 * @param int line The display line to write to. 00115 * @param char *s The null terminated string. 00116 * @param int len The length of the string to print. 00117 */ 00118 void osd_string_xyl(int x, int y, char *s, int len) { 00119 for (int i = x; len; s++, i++, len--) { 00120 osd_display_area[y].line_buffer[i] = *s; 00121 } 00122 osd_display_area[y].update = true; 00123 } 00124 00125 /** osd_stringl 00126 * 00127 * Write a string of specified length to a display line. 00128 * 00129 * @param int line The display line to write to. 00130 * @param char *s The string. 00131 * @param int len The length to write. 00132 */ 00133 void osd_stringl(int line, char *s, int len) { 00134 for (int i = 0; len; s++, i++, len--) { 00135 osd_display_area[line].line_buffer[i] = *s; 00136 } 00137 osd_display_area[line].update = true; 00138 } 00139 00140 /** osd_get_mode_l01 00141 */ 00142 int osd_get_mode_l01(void) { 00143 return l01_mode; 00144 } 00145 00146 /** osd_set_mode_l01 00147 */ 00148 void osd_set_mode_l01(int mode) { 00149 l01_mode = mode; 00150 } 00151 00152 /** osd_l01_next_mode 00153 */ 00154 void osd_l01_next_mode(void) { 00155 int m = osd_get_mode_l01(); 00156 m++; 00157 if (m > L01_MODE_D) m = L01_MODE_A; 00158 osd_set_mode_l01(m); 00159 } 00160 00161 /** osd_set_crosshair 00162 */ 00163 int osd_set_crosshair(int mode) { 00164 if (mode > -1) { 00165 crosshair_mode = mode; 00166 } 00167 return crosshair_mode; 00168 } 00169 00170 /** osd_crosshair_toggle 00171 */ 00172 int osd_crosshair_toggle(void) { 00173 crosshair_mode = crosshair_mode == 0 ? 1 : 0; 00174 if (!crosshair_mode) osd_clear(); 00175 return crosshair_mode; 00176 } 00177 00178 /** osd_write_buffers 00179 * 00180 * Write the line buffers to the display. 00181 */ 00182 static void osd_write_buffers(void) { 00183 for (int i = 0; i < MAX7456_DISPLAY_LINES; i++) { 00184 if (osd_display_area[i].update) { 00185 MAX7456_cursor(0, i); 00186 MAX7456_write_byte(0x04, 0x01); /* Enable 8bit write. */ 00187 for (int j = 0; j < MAX7456_DISPLAY_LINE_LEN; j++) { 00188 MAX7456_write_byte(0x80, MAX7456_map_char(osd_display_area[i].line_buffer[j])); 00189 } 00190 MAX7456_write_byte(0x80, 0xFF); 00191 osd_display_area[i].update = false; 00192 } 00193 } 00194 } 00195 00196 void osd_l01_position(void) { 00197 GPS_LOCATION_AVERAGE loc; 00198 char buf[64], buf2[64]; 00199 double el, azm; 00200 00201 gps_get_location_average(&loc); 00202 00203 if (l01_mode != 0) { 00204 if (IS_NEXSTAR_ALIGNED) { 00205 nexstar_get_elazm(&el, &azm); 00206 printDouble_3_2(buf, el); osd_string_xy(12, 0, buf); 00207 printDouble_3_2(buf, azm); osd_string_xy(12, 1, buf); 00208 } 00209 else { 00210 strcpy(buf, "---.--"); 00211 osd_string_xy(12, 0, buf); 00212 osd_string_xy(12, 1, buf); 00213 } 00214 } 00215 00216 switch(l01_mode) { 00217 case L01_MODE_C: 00218 case L01_MODE_D: 00219 double2dms(buf2, loc.latitude); sprintf(buf, "%c%s", loc.north_south, buf2); osd_string_xy(18, 0, buf); 00220 double2dms(buf2, loc.longitude); sprintf(buf, "%c%s", loc.east_west, buf2); osd_string_xy(18, 1, buf); 00221 break; 00222 case L01_MODE_A: 00223 case L01_MODE_B: 00224 printDouble(buf2, loc.latitude); sprintf(buf, " %c%c%s", loc.is_valid, loc.north_south, buf2); osd_string_xy(18, 0, buf); 00225 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); 00226 break; 00227 } 00228 } 00229 00230 /** osd_vsync 00231 * 00232 * A callback made when the MAX7456 vertical sync fires. 00233 */ 00234 void osd_vsync(void) { 00235 GPS_TIME latched_time; 00236 char buffer[32]; 00237 00238 /* captire the time at which this VSync pulse occured. */ 00239 gps_get_time(&latched_time); 00240 00241 /* We don't actually know if this is an odd or even field. 00242 All we can do is divide by two so each frame only displays 00243 the time, otherwise it will "smudge" the display. We may 00244 well add in an LM1881 device to the final design as that 00245 has an odd/even field ttl output. */ 00246 if (!video_field) { video_field = 1; return; } 00247 else { video_field = 0; } 00248 00249 /* If no mode is set, do not display line0/1. */ 00250 if (l01_mode == 0) return; 00251 00252 /* Display lines 0 and 1 are used for a specific feature, i.e. 00253 the display of the time, GPS position, telescope pointing 00254 position, etc. Handle the "time" display portion now. */ 00255 osd_clear_line(0); 00256 osd_clear_line(1); 00257 00258 char buf2[32]; 00259 double jd = gps_julian_date(&latched_time); 00260 00261 if (crosshair_mode) { 00262 osd_string_xy(13, 7, "\xE0\xE1"); 00263 } 00264 00265 switch(l01_mode) { 00266 case L01_MODE_D: 00267 case L01_MODE_B: 00268 /* Display time as Julain Date. */ 00269 sprintf(buf2, "%.7f", jd - (long)jd); 00270 memset(buffer, 0, 32); sprintf(buffer, "JDI %07ld", (long)jd); osd_string_xy(0, 0, buffer); 00271 memset(buffer, 0, 32); sprintf(buffer, "JDF.%s", buf2 + 2); osd_string_xy(0, 1, buffer); 00272 break; 00273 case L01_MODE_C: 00274 case L01_MODE_A: 00275 /* Display time as UTC. */ 00276 memset(buffer, 0, 32); date_AsString(&latched_time, buffer); osd_string_xy(0, 0, buffer); 00277 memset(buffer, 0, 32); time_AsString(&latched_time, buffer); osd_string_xy(0, 1, buffer); 00278 break; 00279 } 00280 00281 osd_l01_position(); 00282 00283 #ifdef NEVECOMPILETHIS 00284 /* TEST TEST TEST !!! */ 00285 /* Test failed. It actually worked, once. It seems the total math 00286 involved in doing this is WAY to much to be inside what is effectively 00287 an interrupt service routine. It does tell me lots, I need to move all 00288 this to _process() but do it in a way that's fast enough for user output 00289 in "real time" as it would appear to the user. */ 00290 test_counter++; 00291 if (test_counter == 1000) { 00292 test_counter = 0; 00293 SAT_POS_DATA data; 00294 data.tsince = 0; 00295 strcpy(data.elements[0], "ISS (ZARYA)"); 00296 strcpy(data.elements[1], "1 25544U 98067A 10249.33655722 .00010912 00000-0 87866-4 0 8417"); 00297 strcpy(data.elements[2], "2 25544 051.6459 175.3962 0008058 342.0418 161.2933 15.71504826676236"); 00298 gps_get_time(&data.t); 00299 gps_get_location_average(&data.l); 00300 satallite_calculate(&data); 00301 if (!isnan(data.elevation) && !isnan(data.azimuth) && !isnan(data.range)) { 00302 sprintf(buffer, " ISS EL:%.1f AZM:%.1f RG:%.1f", data.elevation, data.azimuth, data.range); 00303 osd_string_xy(0, 14, buffer); 00304 } 00305 } 00306 /* TEST TEST TEST !!! */ 00307 #endif 00308 00309 osd_write_buffers(); 00310 } 00311 00312 00313 00314 00315
Generated on Tue Jul 12 2022 18:05:35 by 1.7.2