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

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers osd.c Source File

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