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 nexstar.c Source File

nexstar.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 /*
00024    Update: This whole module requires refactoring into something much more
00025    sane. Basically, I "organically" grew the code in this module with trial
00026    and error using the hardware since getting simple things done proved hard.
00027    I did design (see below) what I thought reasonable system but the Nexstar
00028    kept throwing up problems. So I really need to come back to this code and
00029    sort it out properly.
00030    
00031    Frustrations: I originally implemented an "intelligent" start-up routine
00032    that sent echo requests to check the Nexstar was there, then requested 
00033    isAligned and, once aligned, would finally send the Tracking Off command
00034    and enter operational state. However, that's all out the window.
00035    
00036    Basically, I have found that if you send anything down the serial cable 
00037    while the Nexstar is powering up it goes dumb and won't responsd to 
00038    anything you send it. How useless, someone needs to educate their 
00039    software engineers to designing robust serial protocols that can 
00040    handle battery/power failure. Really very silly because I now know
00041    that my software MUST assume the end user has powered on their Nexstar
00042    before I start sending serial commands! Rubbish design, I like smart
00043    designs that don't rely on the end user having to do "special things",
00044    they should just work!
00045    
00046    Additionally, I have found that, based on documents from TheSky program
00047    you cannot ask the Nexstar for it's pointing position faster than once
00048    per second! WTF? Asking too fast can crash the Nexstar hand controller.
00049    Doh! Since we really need the position at a higher frequency then at the
00050    subsecond level, the pointing position is calculated from the last position
00051    known +/- whatever variable speed rates have been sent since then.
00052    
00053    For the purposes of trying to track a fast moving object (an artificial
00054    satellite in this case) we end up having to do most of the work ourselves
00055    and hope the Nexstar tracks it with a sub-standard pointing system.
00056    Hopefully I'll get it right!
00057    
00058    Means the serial protocol I develop here is more basic than I would have 
00059    prefered. For example, rather than sending periodic echo requests to 
00060    detect the Nexstar, I'll send just one. If no reply I'll have to prompt
00061    the user to "Power on the Nexstar and press a key to continue". Doh.
00062 */
00063 
00064 #define NEXSTAR_C
00065 
00066 #include "sowb.h"
00067 #include "nexstar.h"
00068 #include "utils.h"
00069 #include "rit.h"
00070 #include "user.h"
00071 #include "osd.h"
00072 #include "debug.h"
00073 #include "gpio.h"
00074 #include "main.h"
00075 
00076 /* Module global variables. */
00077 int  nexstar_status;
00078 int  nexstar_command;
00079 int  nexstar_command_status;
00080 char rx_buffer[NEXSTAR_BUFFER_SIZE];
00081 int  rx_buffer_in;
00082 
00083 bool nexstar_aligned;
00084 
00085 double last_elevation;
00086 double last_azmith;
00087 double virtual_elevation;
00088 double virtual_azmith;
00089 
00090 double elevation_rate;
00091 double elevation_rate_coarse;
00092 double elevation_rate_fine;
00093 double elevation_rate_auto;
00094 
00095 double azmith_rate;
00096 double azmith_rate_coarse;
00097 double azmith_rate_fine;
00098 double azmith_rate_auto;
00099 
00100 bool nexstar_goto_in_progress;
00101 char nexstar_goto_elevation[5];
00102 char nexstar_goto_azmith[5];
00103 
00104 int virtual_update_counter;
00105 
00106 /* Local function prototypes. */
00107 static void Uart2_init(void);
00108 static inline void Uart2_putc(char c);
00109 static inline void Uart2_puts(char *s, int len);
00110 
00111 /** nexstar_process
00112  *
00113  * Our system _process function.
00114  */
00115 void nexstar_process(void) {
00116         
00117     if (nexstar_command_status != 0) {
00118         switch (nexstar_command) {
00119             case NEXSTAR_IS_ALIGNED:
00120                 nexstar_aligned = rx_buffer[0] == 1 ? true : false;
00121                 nexstar_command = 0;
00122                 nexstar_command_status = 0;
00123                 break;
00124             case NEXSTAR_GET_AZMALT:
00125                 last_azmith    = virtual_azmith    = 360.0 * (((double)hex2bin(&rx_buffer[0], 4)) / 65536.0);                
00126                 last_elevation = virtual_elevation = 360.0 * (((double)hex2bin(&rx_buffer[5], 4)) / 65536.0);
00127                 nexstar_command = 0;
00128                 nexstar_command_status = 0;
00129                 virtual_update_counter = 0;    
00130                 if (nexstar_goto_in_progress) {
00131                     if (!memcmp(&rx_buffer[0], nexstar_goto_azmith, 4) && !memcmp(&rx_buffer[5], nexstar_goto_elevation, 4)) {
00132                         nexstar_goto_in_progress = false;
00133                         osd_clear_line(2);
00134                         osd_clear_line(3);
00135                         _nexstar_set_tracking_mode(0);
00136                     }
00137                 }            
00138                 break;
00139             case NEXSTAR_GET_RADEC:
00140             
00141                 break;
00142             case NEXSTAR_SET_ELEVATION_RATE:
00143             case NEXSTAR_SET_AZMITH_RATE:
00144                 nexstar_command = 0;
00145                 nexstar_command_status = 0;
00146                 break;
00147             case NEXSTAR_GOTO:
00148                 nexstar_command = 0;
00149                 nexstar_command_status = 0;
00150                 break;
00151             case NEXSTAR_GOTO_AZM_FAST:
00152                 nexstar_command = 0;
00153                 nexstar_command_status = 0;
00154                 break;
00155             case NEXSTAR_SET_APPROACH:
00156                 nexstar_command = 0;
00157                 nexstar_command_status = 0;
00158                 break;
00159             case NEXSTAR_SET_TIME:
00160                 nexstar_command = 0;
00161                 nexstar_command_status = 0;
00162                 break;
00163             case NEXSTAR_SET_LOCATION:
00164                 nexstar_command = 0;
00165                 nexstar_command_status = 0;
00166                 break;    
00167             case NEXSTAR_SYNC:
00168                 nexstar_command = 0;
00169                 nexstar_command_status = 0;
00170                 break;    
00171         }
00172     }    
00173 }
00174 
00175 /** nexstar_timeout_callback
00176  *
00177  * The generic timer callback handler.
00178  *
00179  * @param int index The timer index (handle).
00180  */
00181 void _nexstar_timeout_callback(int index) {
00182     nexstar_status = NEXSTAR_STATE_NOT_CONN;
00183 }
00184 
00185 void _nexstar_one_second_timer(int index) {
00186     _nexstar_get_altazm();
00187     //_nexstar_get_radec();
00188     rit_timer_set_counter(RIT_ONESEC_NEXSTAR, 200);
00189 }
00190 
00191 double nexstar_get_rate_azm(void) {
00192     if (nexstar_goto_in_progress) return 0.0;
00193     return azmith_rate_coarse + azmith_rate_fine + azmith_rate_auto;
00194 }
00195 
00196 double nexstar_get_rate_alt(void) {
00197     if (nexstar_goto_in_progress) return 0.0;
00198     return elevation_rate_coarse + elevation_rate_fine + elevation_rate_auto;
00199 }
00200 
00201 void _nexstar_100th_timer(int index) {
00202     rit_timer_set_counter(RIT_100TH_NEXSTAR, 100);
00203 }
00204 
00205 /** nexstar_init
00206  *
00207  * Used to initialise the system.
00208  */
00209 void nexstar_init(void) {
00210 
00211     DEBUG_INIT_START;
00212     
00213     rit_timer_set_counter(RIT_TIMER_NEXSTAR, 0);
00214     rit_timer_set_counter(RIT_ONESEC_NEXSTAR, 250);
00215     rit_timer_set_counter(RIT_100TH_NEXSTAR, 100);
00216     nexstar_status = NEXSTAR_STATE_IDLE;
00217     nexstar_command = 0;
00218     nexstar_command_status = 0;
00219     last_elevation = 0.0;
00220     last_azmith = 0.0;
00221     virtual_elevation = 0.0;
00222     virtual_azmith = 0.0;
00223     
00224     elevation_rate = elevation_rate_coarse = elevation_rate_fine = elevation_rate_auto = 0.0;
00225     azmith_rate = azmith_rate_coarse = azmith_rate_fine = azmith_rate_auto = 0.0;
00226     
00227     nexstar_goto_in_progress = false;
00228     
00229     nexstar_aligned = false;
00230     
00231     rx_buffer_in = 0;
00232     virtual_update_counter = 0;
00233     
00234     DEBUG_INIT_END;
00235     
00236     Uart2_init();
00237 }
00238 
00239 /* External API functions. */
00240 void nexstar_get_elazm(double *el, double *azm) {
00241     *(el)  = last_elevation;
00242     *(azm) = last_azmith;
00243 }
00244 
00245 /* Internal API functions. */
00246 int _nexstar_set_tracking_mode(int mode) {
00247     if (nexstar_status == NEXSTAR_STATE_IDLE) {
00248         nexstar_status = NEXSTAR_STATE_BUSY;
00249         rx_buffer_in = 0;
00250         nexstar_command_status = 0;
00251         nexstar_command = NEXSTAR_SET_TRACKING;
00252         LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00253         Uart2_putc('T');
00254         Uart2_putc((char)mode);
00255         rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00256         return 1;
00257     }
00258     return 0;
00259 }
00260 
00261 int _nexstar_get_altazm(void) {
00262     if (nexstar_status == NEXSTAR_STATE_IDLE) {
00263         nexstar_status = NEXSTAR_STATE_BUSY;
00264         rx_buffer_in = 0;
00265         nexstar_command_status = 0;
00266         nexstar_command = NEXSTAR_GET_AZMALT;
00267         LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00268         Uart2_putc('Z');
00269         rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00270         return 1;
00271     }
00272     return 0;
00273 }
00274 
00275 int _nexstar_get_radec(void) {
00276     if (nexstar_status == NEXSTAR_STATE_IDLE) {
00277         nexstar_status = NEXSTAR_STATE_BUSY;
00278         rx_buffer_in = 0;
00279         nexstar_command_status = 0;
00280         nexstar_command = NEXSTAR_GET_RADEC;
00281         LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00282         Uart2_putc('E');
00283         rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00284         return 1;
00285     }
00286     return 0;
00287 }
00288 
00289 void _nexstar_set_elevation_rate_coarse(double rate) {
00290     elevation_rate_coarse = rate;
00291     _nexstar_set_elevation_rate();
00292 }
00293 
00294 void _nexstar_set_elevation_rate_fine(double rate) {
00295     elevation_rate_fine = rate;
00296     _nexstar_set_elevation_rate();
00297 }
00298 
00299 void _nexstar_set_elevation_rate_auto(double rate) {
00300     elevation_rate_auto = rate;
00301     _nexstar_set_elevation_rate();
00302 }
00303 
00304 int _nexstar_set_elevation_rate(void) {
00305     char dir, high, low, cmd[32];
00306     double rate;
00307 
00308     rate = elevation_rate_coarse + elevation_rate_fine + elevation_rate_auto;
00309     
00310     if (elevation_rate == rate) return 0;
00311     
00312     if (rate != 0.0) {
00313         if (nexstar_goto_in_progress || nexstar_status != NEXSTAR_STATE_IDLE) return 0;
00314     }
00315         
00316     while (nexstar_status != NEXSTAR_STATE_IDLE) {
00317         if (nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
00318         user_wait_ms(1);
00319     };
00320     
00321     //if (rate >= 0.0) osd_string_xyl(0, 14, cmd, sprintf(cmd, " ALT >> %c%.1f", '+', rate)); 
00322     //else             osd_string_xyl(0, 14, cmd, sprintf(cmd, " ALT >> %+.1f", rate)); 
00323     nexstar_status = NEXSTAR_STATE_BUSY;
00324     rx_buffer_in = 0;
00325     nexstar_command_status = 0;
00326     nexstar_command = NEXSTAR_SET_ELEVATION_RATE;
00327     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00328     dir = 6;
00329     if (rate < 0.0) {
00330         dir = 7;
00331         rate *= -1;
00332     }
00333     high = ((int)(3600.0 * rate * 4.0) / 256) & 0xFF;
00334     low  = ((int)(3600.0 * rate * 4.0) % 256) & 0xFF;            
00335     Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 17, dir, high, low, 0, 0));
00336     rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00337     elevation_rate = rate;
00338     return 1;    
00339 }
00340 
00341 void _nexstar_set_azmith_rate_coarse(double rate) {
00342     azmith_rate_coarse = rate;
00343     _nexstar_set_azmith_rate();
00344 }
00345 
00346 void _nexstar_set_azmith_rate_fine(double rate) {
00347     azmith_rate_fine = rate;
00348     _nexstar_set_azmith_rate();
00349 }
00350 
00351 void _nexstar_set_azmith_rate_auto(double rate) {
00352     azmith_rate_auto = rate;
00353     _nexstar_set_azmith_rate();
00354 }
00355 
00356 int _nexstar_set_azmith_rate(void) {
00357     char dir, high, low, cmd[32];
00358     double rate;
00359     
00360     rate = azmith_rate_coarse + azmith_rate_fine + azmith_rate_auto;
00361     
00362     if (azmith_rate == rate)  return 0;
00363     
00364     if (rate != 0.0) {
00365         if (nexstar_goto_in_progress || nexstar_status != NEXSTAR_STATE_IDLE) return 0;
00366     }
00367     
00368     while (nexstar_status != NEXSTAR_STATE_IDLE) {
00369         if (nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
00370         user_wait_ms(1);
00371     };
00372         
00373     //if (rate >= 0.0) osd_string_xyl(14, 14, cmd, sprintf(cmd, " AZM >> %c%.1f", '+', rate)); 
00374     //else             osd_string_xyl(14, 14, cmd, sprintf(cmd, " AZM >> %+.1f", rate)); 
00375     nexstar_status = NEXSTAR_STATE_BUSY;
00376     nexstar_status = NEXSTAR_STATE_BUSY;
00377     rx_buffer_in = 0;
00378     nexstar_command_status = 0;
00379     nexstar_command = NEXSTAR_SET_AZMITH_RATE;
00380     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00381     dir = 6;
00382     if (rate < 0.0) {
00383         dir = 7;
00384         rate *= -1;
00385     }
00386     high = ((int)(3600.0 * rate * 4.0) / 256) & 0xFF;
00387     low  = ((int)(3600.0 * rate * 4.0) % 256) & 0xFF;
00388     Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 16, dir, high, low, 0, 0));            
00389     rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00390     azmith_rate = rate;
00391     return 1;    
00392 }
00393 
00394 int _nexstar_goto(uint32_t elevation, uint32_t azmith) {
00395     char cmd[32], buf1[6], buf2[6];
00396     double azm_target, azm_current;
00397 
00398     if (nexstar_goto_in_progress) return 0;
00399     
00400     printDouble_3_2(buf1, 360.0 * ((double)elevation / 65536));
00401     osd_stringl(2, cmd, sprintf(cmd, "     GOTO > %s < ALT", buf1)); 
00402     printDouble_3_2(buf2, 360.0 * ((double)azmith / 65536));
00403     osd_stringl(3, cmd, sprintf(cmd, "          > %s < AZM", buf2));
00404     osd_clear_line(14); 
00405        
00406     /* Adjust the GOTO approach based on where we are pointing now
00407        comapred to where we want to go. */
00408     azm_target = 360.0 * ((double)((double)azmith / 65536.0));
00409     azm_current = last_azmith - azm_target;
00410 
00411     if (azm_current > 180.) _nexstar_set_azm_approach(1);        
00412     else                   _nexstar_set_azm_approach(-1);            
00413 
00414     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00415         if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
00416         user_wait_ms(1);
00417     };
00418             
00419     nexstar_goto_in_progress = true;
00420     nexstar_status = NEXSTAR_STATE_BUSY;
00421     rx_buffer_in = 0;
00422     nexstar_command_status = 0;
00423     nexstar_command = NEXSTAR_GOTO;
00424     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00425     sprintf(nexstar_goto_azmith, "%04X", azmith);
00426     sprintf(nexstar_goto_elevation, "%04X", elevation);
00427     Uart2_puts(cmd, sprintf(cmd, "B%s,%s", nexstar_goto_azmith, nexstar_goto_elevation));
00428     rit_timer_set_counter(RIT_TIMER_NEXSTAR, 60000);
00429     return 1;    
00430 }
00431 
00432 int _nexstar_goto_azm_fast(uint32_t azmith) {
00433     char cmd[16];
00434     
00435     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00436         if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
00437         user_wait_ms(1);
00438     };
00439             
00440     nexstar_status = NEXSTAR_STATE_BUSY;
00441     rx_buffer_in = 0;
00442     nexstar_command_status = 0;
00443     nexstar_command = NEXSTAR_GOTO_AZM_FAST;
00444     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00445     Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 16, 2, (azmith >> 8) & 0xFF, azmith & 0xFF, 0, 0));            
00446     
00447     rit_timer_set_counter(RIT_TIMER_NEXSTAR, 60000);
00448     return 1;    
00449 }
00450 
00451 void _nexstar_set_azm_approach(int approach) {
00452     char cmd[16];
00453     
00454     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00455         if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return;
00456         user_wait_ms(1);
00457     };
00458     
00459     nexstar_command = NEXSTAR_SET_APPROACH;    
00460     nexstar_command_status = 0;
00461     nexstar_status = NEXSTAR_STATE_BUSY;
00462     rx_buffer_in = 0;
00463     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00464     Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 16, 0xFD, approach < 0 ? 1 : 0, 0, 0, 0));
00465     rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00466 }
00467 
00468 bool _nexstar_is_aligned(void) {
00469     
00470     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00471         if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return false;
00472         user_wait_ms(1);
00473     };
00474     
00475     nexstar_command = NEXSTAR_IS_ALIGNED;    
00476     nexstar_command_status = 0;
00477     nexstar_status = NEXSTAR_STATE_BUSY;
00478     rx_buffer_in = 0;
00479     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00480     Uart2_putc('J');
00481     rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00482     
00483     /* This command blocks while we wait for an answer. */
00484     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00485         user_wait_ms(10);
00486     };
00487     
00488     return nexstar_aligned;
00489 }
00490 
00491 void _nexstar_sync(RaDec *radec) {
00492     char cmd[32];
00493     uint16_t ra, dec;
00494     
00495     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00496         user_wait_ms(1);
00497     };
00498     
00499     ra  = (uint16_t)((radec->ra  / 360.0) * 65536);
00500     dec = (uint16_t)((radec->dec / 360.0) * 65536);
00501     
00502     nexstar_command = NEXSTAR_SYNC;    
00503     nexstar_command_status = 0;
00504     nexstar_status = NEXSTAR_STATE_BUSY;
00505     rx_buffer_in = 0;
00506     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00507     Uart2_puts(cmd, sprintf(cmd, "S%02X,%02X", ra, dec));
00508     rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);   
00509 
00510 }
00511 
00512 void _nexstar_set_time(GPS_TIME *t) {
00513     char cmd[32];
00514     GPS_TIME rt;
00515     
00516     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00517         user_wait_ms(1);
00518     };
00519     
00520     if (t == (GPS_TIME *)NULL) {
00521         t = &rt;
00522         gps_get_time(t);        
00523     }
00524     
00525     nexstar_command = NEXSTAR_SET_TIME;    
00526     nexstar_command_status = 0;
00527     nexstar_status = NEXSTAR_STATE_BUSY;
00528     rx_buffer_in = 0;
00529     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00530     Uart2_puts(cmd, sprintf(cmd, "H%c%c%c%c%c%c%c%c", t->hour, t->minute, t->second, t->month, t->day, t->year - 2000, 0, 0));
00531     rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);   
00532 }
00533 
00534 void _nexstar_set_location(GPS_LOCATION_AVERAGE *l) {
00535     char cmd[32];
00536     GPS_LOCATION_AVERAGE rl;
00537     double d, t;
00538     char lat_degrees, lat_minutes, lat_seconds, lon_degrees, lon_minutes, lon_seconds;
00539     
00540     while(nexstar_status != NEXSTAR_STATE_IDLE) {
00541         user_wait_ms(1);
00542     };
00543     
00544     if (l == (GPS_LOCATION_AVERAGE *)NULL) {
00545         l = &rl;
00546         gps_get_location_average(l);        
00547     }
00548     
00549     d = l->latitude;
00550     lat_degrees = (char)d; t = (d - (double)lat_degrees) * 60.0;
00551     lat_minutes = (char)t;
00552     lat_seconds = (t - (double)lat_minutes) * 60.0;
00553     d = l->longitude;
00554     lon_degrees = (int)d; t = (d - (double)lon_degrees) * 60.0;
00555     lon_minutes = (int)t;
00556     lon_seconds = (t - (double)lon_minutes) * 60.0;
00557     
00558     nexstar_command = NEXSTAR_SET_LOCATION;    
00559     nexstar_command_status = 0;
00560     nexstar_status = NEXSTAR_STATE_BUSY;
00561     rx_buffer_in = 0;
00562     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00563     Uart2_puts(cmd, sprintf(cmd, "W%c%c%c%c%c%c%c%c", lat_degrees, lat_minutes, lat_seconds, l->north_south == 'N' ? 0 : 1, lon_degrees, lon_minutes, lon_seconds, l->east_west == 'E' ? 0 : 1));
00564     rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);   
00565 }
00566 
00567 /** UART2_IRQHandler(void)
00568  *
00569  * The interrupt service routine for the UART2.
00570  */
00571 extern "C" void UART2_IRQHandler(void) __irq {
00572     volatile uint32_t iir; 
00573     char c;
00574 
00575     /* Get the interrupt identification register which also resets IIR. */
00576     iir = LPC_UART2->IIR;
00577        
00578     if (iir & 0x1) return;
00579     
00580     iir = (iir >> 1) & 0x3;
00581     
00582     /* Handle the incoming character. */
00583     if (iir == 2) {
00584         c = LPC_UART2->RBR;
00585         //Uart0_putc(c);
00586         rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
00587         rx_buffer[rx_buffer_in] = c;
00588         rx_buffer_in++;
00589         if (rx_buffer_in >= NEXSTAR_BUFFER_SIZE) {
00590             rx_buffer_in = 0;
00591         }
00592         if (c == '#') {
00593             rit_timer_set_counter(RIT_TIMER_NEXSTAR, 0);
00594             nexstar_command_status = 1;
00595             nexstar_status = NEXSTAR_STATE_IDLE;
00596         }
00597     }
00598 }
00599 
00600 /** Uart2_init
00601  *
00602  * Initialise UART2 to our requirements for Nexstar.
00603  */
00604 static void Uart2_init (void) {
00605     volatile char c __attribute__((unused));
00606     
00607     DEBUG_INIT_START;
00608     
00609     LPC_SC->PCONP       |=  (1UL << 24);
00610     LPC_SC->PCLKSEL1    &= ~(3UL << 16);
00611     LPC_SC->PCLKSEL1    |=  (1UL << 16);
00612     LPC_PINCON->PINSEL0 |= ((1UL << 20) | (1UL << 22));
00613     LPC_UART2->LCR       = 0x80;
00614     LPC_UART2->DLM       = 0x2;  // 115200 baud, for 9600 use 0x2;
00615     LPC_UART2->DLL       = 0x71; // 115200 baud, for 9600 use 0x71;
00616     LPC_UART2->LCR       = 0x3;
00617     LPC_UART2->FCR       = 0x1;
00618 
00619     /* Ensure the FIFO is empty. */
00620     while (LPC_UART2->LSR & 0x1) c = (char)LPC_UART2->RBR;
00621     
00622     NVIC_SetVector(UART2_IRQn, (uint32_t)UART2_IRQHandler);
00623     NVIC_EnableIRQ(UART2_IRQn);
00624     
00625     /* Enable UART0 RX interrupt only. */
00626     LPC_UART2->IER = 0x1; 
00627     
00628     DEBUG_INIT_END;  
00629 }
00630 
00631 static inline void Uart2_putc(char c) {
00632     //Uart0_putc(c);
00633     LPC_UART2->THR = (uint32_t)(c & 0xFF);
00634 }
00635 
00636 static inline void Uart2_puts(char *s, int len) {
00637     int i;
00638     if (len > 0) for (i = 0; len; i++, len--) Uart2_putc(s[i]);
00639 }
00640