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

nexstar_old.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 #ifdef NEVERCOMPILETHIS
00024 
00025 #include "mbed.h"
00026 #include "nexstar.h"
00027 #include "utils.h"
00028 #include "debug.h"
00029 #include "main.h"
00030 
00031 DigitalOut led1(LED1);
00032 DigitalOut led2(LED2);
00033 DigitalOut led3(LED3);
00034 DigitalOut led4(LED4);
00035 
00036 /* The main place holder data structure for the Nexstar. */
00037 NEXSTAR_DATA nexstar;
00038 
00039 /* A timer to look for serial comms failure. */
00040 OneMS   timeout;
00041 
00042 /** nexstar_process(void)
00043  *
00044  * Standard module _process function.
00045  */
00046 void nexstar_process(void) {
00047     int i, j, q;
00048     signed char status, type;
00049     
00050     BLAT4;
00051     
00052     /* Multiple queued requests will start automatically after the previous
00053        request (see the ISR for details). However, it is possible that when
00054        the ISR detects the completion of a request there are, at that time,
00055        no more pending requests in the queue. So loop over the request queue 
00056        and if none are in progress, initiate a request transfer to the Nexstar. */
00057     if (! nexstar_request_count_status(NEXSTAR_REQUEST_IN_PROGRESS)) {
00058         if (nexstar_request_count_status(NEXSTAR_REQUEST_PENDING)) {
00059             for (i = 0, q = nexstar.currentRequest; i < NEXSTAR_NUM_OF_PACKETS; i++) {
00060                 if (nexstar.commsPackets[q].requestStatus == NEXSTAR_REQUEST_PENDING) {
00061                     nexstar.currentRequest = q;
00062                     nexstar_send_request(q);
00063                     i = NEXSTAR_NUM_OF_PACKETS;
00064                 }
00065                 else {
00066                     NEXSTAR_NEXT_REQUEST(q);
00067                 }
00068             }
00069         }
00070     }
00071     
00072     /* look through all the comms request packets and see if any need processing. */
00073     /*
00074     for (i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
00075         status = nexstar.commsPackets[i].requestStatus;
00076         type   = nexstar.commsPackets[i].requestType; 
00077         if (status == NEXSTAR_REQUEST_TIMEOUT) {                        
00078             for (j = 0; j < NEXSTAR_NUM_OF_PACKETS; j++) {
00079                 REQUEST_SET_PACKET_STATUS(j, NEXSTAR_REQUEST_IDLE); 
00080                 nexstar_request_packet_reset(&nexstar.commsPackets[j]);
00081             }
00082             NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
00083         }
00084         else if (status == NEXSTAR_REQUEST_COMPLETE) {
00085             switch (type) {
00086                 case NEXSTAR_ECHO_COMMS:
00087                     nexstar_request_echo(NEXSTAR_PROCESS_REQUEST, i);
00088                     break;
00089                 case NEXSTAR_ASK_IS_ALIGNED:
00090                     nexstar_request_get_aligned(NEXSTAR_PROCESS_REQUEST, i);
00091                     break;
00092                 case NEXSTAR_ASK_ALTAZM_POSITION:
00093                     nexstar_request_get_altazm(NEXSTAR_PROCESS_REQUEST, i);
00094                     break;
00095             }
00096         }       
00097     }
00098     */
00099     
00100     if (nexstar.commsPackets[nexstar.currentRequest].requestStatus; == NEXSTAR_REQUEST_COMPLETE) {
00101         switch (type) {
00102             case NEXSTAR_ECHO_COMMS:
00103                 nexstar_request_echo(NEXSTAR_PROCESS_REQUEST, nexstar.currentRequest);
00104                 break;
00105             case NEXSTAR_ASK_IS_ALIGNED:
00106                 nexstar_request_get_aligned(NEXSTAR_PROCESS_REQUEST, nexstar.currentRequest);
00107                 break;
00108             case NEXSTAR_ASK_ALTAZM_POSITION:
00109                 nexstar_request_get_altazm(NEXSTAR_PROCESS_REQUEST, nexstar.currentRequest);
00110                 break;
00111         }
00112     }       
00113     
00114    /* If the Nexstar is in an unknown state attempt to ask it for
00115        alignment. Once we get a positive response we at least know
00116        a Nexstar is connected and responding. Until we have that
00117        knowledge there is little else we can do. */
00118     switch(nexstar.status) {
00119         case NEXSTAR_NOT_CONNECTED:
00120             if (! nexstar_request_count_request_type(NEXSTAR_ECHO_COMMS)) { 
00121                 Uart2_flush_rxfifo();
00122                 nexstar_request_echo(NEXSTAR_SEND_REQUEST, 0);                
00123             }
00124             return;            
00125 
00126         case NEXSTAR_CONNECTED:
00127         case NEXSTAR_NOT_ALIGNED:
00128             if (! nexstar_request_count_request_type(NEXSTAR_ASK_IS_ALIGNED)) {             
00129                 Uart2_flush_rxfifo();
00130                 nexstar_request_get_aligned(NEXSTAR_SEND_REQUEST, 0);                
00131             }
00132             return; 
00133             
00134         default:
00135             debug.printf("I don't know what to do! status is %d\r\n", nexstar.status);
00136             break;           
00137     }    
00138 
00139     /* As possible as often, request the Nexstar's pointing position. */
00140     if (! nexstar_request_count_request_type(NEXSTAR_ASK_ALTAZM_POSITION)) {
00141         nexstar_request_get_altazm(NEXSTAR_SEND_REQUEST, 0);
00142     }
00143 
00144     
00145 }
00146 
00147 /** nexstar_init(void)
00148  *
00149  * Standard module _init function. 
00150  */
00151 void nexstar_init(void) {
00152 
00153     /* Setup the global mode of this Nexstar. */
00154     NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
00155 
00156     /* Initialise the comms packets and buffers. */
00157     nexstar.currentRequest = 0;
00158     nexstar.availableRequest = 0;
00159     for (int i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
00160         nexstar_request_packet_reset(&nexstar.commsPackets[i]);
00161         //nexstar.commsPackets[i].requestType = 0;
00162         //nexstar.commsPackets[i].requestStatus = NEXSTAR_REQUEST_IDLE;
00163         //nexstar.commsPackets[i].bufferPointer = 0;
00164         //nexstar.commsPackets[i].callback = NULL;
00165         //memset(nexstar.commsPackets[i].buffer, 0, NEXSTAR_PACKET_BUFFER_SIZE);
00166     }
00167     
00168     /* Prepare the one-shot timeout timers. */
00169     timeout.mode(ONEMS_MODE_TIMEOUT_CALLBACK);
00170     timeout.attach(nexstar_timeout);
00171 
00172     /* Initialise the UART we use. */
00173     Uart2_init();
00174 }
00175 
00176 /** nexstar_request_packet_reset
00177  *
00178  * Return a request packet back to default state.
00179  *
00180  * @param NEXSTAR_COMMS_PACKET *p A pointer to the packet to reset.
00181  */
00182 void nexstar_request_packet_reset(NEXSTAR_COMMS_PACKET *p) {
00183     p->requestType = 0;
00184     p->bufferPointer = 0;
00185     p->callback = NULL;
00186     memset(p->buffer, 0, NEXSTAR_PACKET_BUFFER_SIZE);
00187     p->requestStatus = NEXSTAR_REQUEST_IDLE;
00188 }
00189 
00190 /** nexstar_p(void)
00191  *
00192  * Get a pointer to the data structure for the Nexstar.
00193  * Used by the API to get data.
00194  */
00195 NEXSTAR_DATA * nexstar_p(void) {
00196     return &nexstar;
00197 }
00198 
00199 /** nexstar_request_count_request_type(char requestType)
00200  *
00201  * Used to find out if any of the packets are currently marked as the supplied request type.
00202  *
00203  * @param char The status to test.
00204  * @return bool True otherwise false
00205  */
00206 int nexstar_request_count_request_type(char requestType) {
00207     int count, i;
00208     
00209     for (count = 0, i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
00210         if (nexstar.commsPackets[i].requestType == requestType) {
00211             count++;;
00212         }
00213     }    
00214     return count;
00215 }
00216 
00217 /** nexstar_request_count_status (char status)
00218  *
00219  * Used to find out if any of the packets are currently marked as the supplied status.
00220  *
00221  * @param char The status to test.
00222  * @return bool True otherwise false
00223  */
00224 int nexstar_request_count_status(char status) {
00225     int count, i;
00226     
00227     for (count = 0, i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
00228         if (nexstar.commsPackets[i].requestStatus == status) {
00229             count++;;
00230         }
00231     }    
00232     return count;
00233 }
00234 
00235 /** nexstar_timeout(class OneMS *q)
00236  *
00237  * A callback for the timeout timer.
00238  *
00239  * @param pointer class OneMS that invoked the callback.
00240  */
00241 void nexstar_timeout(class OneMS *q) {
00242     q->stop();  /* Ensure we stop this timer. */
00243     
00244     /* Mark this request timed out. */
00245     REQUEST_SET_PACKET_STATUS(nexstar.currentRequest, NEXSTAR_REQUEST_TIMEOUT);
00246 }
00247 
00248 /** nexstar_request_get_altazm(int mode, unsigned char handle)
00249  *
00250  * Used to either create a request to get the current AltAzm position of the Nextsra
00251  * or to process a previously completed request.
00252  *
00253  * @param int mode Determine what action to create, queue request or process packet.
00254  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00255  * @return zero on failure or error, non-zero otherwise.
00256  */
00257 int nexstar_request_get_altazm(int mode, unsigned char handle) {
00258     
00259     /* Create a request to get the ALT/AZM and queue it. */
00260     if (mode == NEXSTAR_SEND_REQUEST) {
00261         REQUEST_HANDLE;
00262         nexstar.commsPackets[handle].buffer[0] = 'Z';
00263         REQUEST_SET(NEXSTAR_ASK_ALTAZM_POSITION, 1);
00264         led3 = 1;
00265         return 1;
00266     }
00267     
00268     /* Given a completed request, parse the data and update our information. */
00269     if (mode == NEXSTAR_PROCESS_REQUEST) {
00270         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00271         char *buffer = nexstar.commsPackets[handle].buffer;
00272         REQUEST_BUFFER_CHECK(9, 0);
00273         nexstar.currentAltRaw = hex2bin(buffer + 5, 4);
00274         nexstar.currentAlt    = (double)(((double)nexstar.currentAltRaw / 65536.) * 360.);
00275         nexstar.currentAzmRaw = hex2bin(buffer + 0, 4);
00276         nexstar.currentAzm    = (double)(((double)nexstar.currentAzmRaw / 65536.) * 360.);
00277         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);
00278         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00279         led3 = 0;
00280         return 1;
00281     }
00282     
00283     return 0;
00284 }
00285 
00286 /** nexstar_request_get_aligned(int mode, unsigned char handle)
00287  *
00288  * Used to either create a request to check teh Nexstar is aligned
00289  * or to process a previously completed request.
00290  *
00291  * @param int mode Determine what action to create, queue request or process packet.
00292  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00293  * @return zero on failure or error, non-zero otherwise.
00294  */
00295 int nexstar_request_get_aligned(int mode, unsigned char handle) {
00296     
00297     /* Create a request to get the ALT/AZM and queue it. */
00298     if (mode == NEXSTAR_SEND_REQUEST) {
00299         REQUEST_HANDLE;
00300         nexstar.commsPackets[handle].buffer[0] = 'J';
00301         nexstar.commsPackets[handle].timeout = 2000;
00302         REQUEST_SET(NEXSTAR_ASK_IS_ALIGNED, 1);
00303         led2 = 1;
00304         return 1;
00305     }
00306     
00307     /* Given a completed request, parse the data and update our information. */
00308     if (mode == NEXSTAR_PROCESS_REQUEST) {
00309         if (nexstar.commsPackets[handle].requestStatus == NEXSTAR_REQUEST_TIMEOUT) {
00310             NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
00311             nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00312             led2 = 0;
00313             return 0;
00314         }
00315         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00316         char *buffer = nexstar.commsPackets[handle].buffer;
00317         REQUEST_BUFFER_CHECK(1, 0);
00318         NEXSTAR_SET_STATUS((buffer[0] == 1) ? NEXSTAR_ALIGNED : NEXSTAR_NOT_ALIGNED);
00319         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00320         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00321         led2 = 0;
00322         return 1;
00323     }
00324     
00325     return 0;
00326 }
00327 
00328 /** nexstar_request_echo(int mode, unsigned char handle)
00329  *
00330  * Used to either echo a data byte off the Nexstar.
00331  *
00332  * @param int mode Determine what action to create, queue request or process packet.
00333  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00334  * @return zero on failure or error, non-zero otherwise.
00335  */
00336 int nexstar_request_echo(int mode, unsigned char handle) {
00337     
00338     /* Create a request to get the ALT/AZM and queue it. */
00339     if (mode == NEXSTAR_SEND_REQUEST) {
00340         REQUEST_HANDLE;
00341         nexstar.commsPackets[handle].buffer[0] = 'K';
00342         nexstar.commsPackets[handle].buffer[1] = 'k';
00343         nexstar.commsPackets[handle].timeout = 2000;
00344         REQUEST_SET(NEXSTAR_ECHO_COMMS, 2);
00345         led1 = 1;
00346         return 1;
00347     }
00348     
00349     /* Given a completed request, parse the data and update our information. */
00350     if (mode == NEXSTAR_PROCESS_REQUEST) {
00351     led3 = 1;
00352         if (nexstar.commsPackets[handle].requestStatus == NEXSTAR_REQUEST_TIMEOUT) {
00353             NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
00354             nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00355             led1 = 0;
00356             return 0;
00357         }
00358         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00359         char *buffer = nexstar.commsPackets[handle].buffer;
00360         REQUEST_BUFFER_CHECK(1, 0);
00361         if (buffer[0] == 'k') debug.printf("YES! ");
00362         else debug.printf("NO! ");
00363             
00364         NEXSTAR_SET_STATUS((buffer[0] == 'k') ? NEXSTAR_CONNECTED : NEXSTAR_NOT_CONNECTED);
00365         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00366         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00367         led1 = 0;
00368         return 1;
00369     }
00370     
00371     return 0;
00372 }
00373 
00374 /** nexstar_request_set_tracking_mode(int mode, unsigned char handle, char tracking)
00375  *
00376  * Used to set the tracking mode of the Nexstar
00377  *
00378  * @param int mode Determine what action to create, queue request or process packet.
00379  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00380  * @param char tracking The mode to send.
00381  * @return zero on failure or error, non-zero otherwise.
00382  */
00383 int nexstar_request_set_tracking_mode(int mode, unsigned char handle, char tracking) {
00384 
00385     /* Create request and queue. */    
00386     if (mode == NEXSTAR_SEND_REQUEST) {
00387         REQUEST_HANDLE;
00388         nexstar.commsPackets[handle].buffer[0] = 'T';
00389         nexstar.commsPackets[handle].buffer[1] = tracking;
00390         REQUEST_SET(NEXSTAR_SET_TRACKING, 2);
00391         return 1;
00392     }
00393     
00394     /* Given a completed request, parse the data and update our information. */
00395     if (mode == NEXSTAR_PROCESS_REQUEST) {
00396         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00397         char *buffer = nexstar.commsPackets[handle].buffer;
00398         REQUEST_BUFFER_CHECK(0, 0);
00399         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00400         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00401         return 1;
00402     }
00403     
00404     return 0;
00405 }
00406 
00407 /** nexstar_request_get_tracking_mode(int mode, unsigned char handle)
00408  *
00409  * Used to find out what tracking mode Nexstar is in.
00410  *
00411  * @param int mode Determine what action to create, queue request or process packet.
00412  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00413  * @return zero on failure or error, non-zero otherwise.
00414  */
00415 int nexstar_request_get_tracking_mode(int mode, unsigned char handle) {
00416 
00417     /* Create request and queue. */    
00418     if (mode == NEXSTAR_SEND_REQUEST) {
00419         REQUEST_HANDLE;
00420         nexstar.commsPackets[handle].buffer[0] = 't';
00421         REQUEST_SET(NEXSTAR_ASK_TRACKING, 1);
00422         return 1;
00423     }
00424     
00425     /* Given a completed request, parse the data and update our information. */
00426     if (mode == NEXSTAR_PROCESS_REQUEST) {
00427         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00428         char *buffer = nexstar.commsPackets[handle].buffer;
00429         REQUEST_BUFFER_CHECK(1, 0);
00430         nexstar.trackingMode = buffer[0];
00431         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00432         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00433         return 1;
00434     }
00435     
00436     return 0;
00437 }
00438 
00439 /** nexstar_request_set_slew(int mode, unsigned char handle, double alt, double azm)
00440  *
00441  * Used to set a variable slew rate.
00442  *
00443  * @param int mode Determine what action to create, queue request or process packet.
00444  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00445  * @param double alt The alt slew rate in degrees per second.
00446  * @param double azm The azm slew rate in degrees per second.
00447  * @return zero on failure or error, non-zero otherwise.
00448  */
00449 int nexstar_request_set_slew(int mode, unsigned char handle, double alt, double azm) {
00450     int i;
00451     
00452     /* Create request and queue. */    
00453     if (mode == NEXSTAR_SEND_REQUEST) {
00454         REQUEST_HANDLE;
00455         nexstar.commsPackets[handle].buffer[0] = 'P';
00456         nexstar.commsPackets[handle].buffer[1] = '\x3';
00457         nexstar.commsPackets[handle].buffer[2] = '\x11';
00458         nexstar.commsPackets[handle].buffer[3] = alt > 0 ? '\x6' : '\x7';
00459         i = ((int)(alt * 3600.)) * 4;
00460         nexstar.commsPackets[handle].buffer[4] = (char)((i & 0xFF00) >> 8);
00461         nexstar.commsPackets[handle].buffer[5] = (char)(i & 0xFF);
00462         nexstar.commsPackets[handle].buffer[6] = '\0';
00463         nexstar.commsPackets[handle].buffer[7] = '\0';
00464         REQUEST_SET(NEXSTAR_SET_ALT_RATE, 8);
00465         
00466         REQUEST_HANDLE;
00467         nexstar.commsPackets[handle].buffer[0] = 'P';
00468         nexstar.commsPackets[handle].buffer[1] = '\x3';
00469         nexstar.commsPackets[handle].buffer[2] = '\x10';
00470         nexstar.commsPackets[handle].buffer[3] = azm > 0 ? '\x6' : '\x7';
00471         i = ((int)(azm * 3600.)) * 4;
00472         nexstar.commsPackets[handle].buffer[4] = (char)((i & 0xFF00) >> 8);
00473         nexstar.commsPackets[handle].buffer[5] = (char)(i & 0xFF);
00474         nexstar.commsPackets[handle].buffer[6] = '\0';
00475         nexstar.commsPackets[handle].buffer[7] = '\0';
00476         REQUEST_SET(NEXSTAR_SET_AZM_RATE, 8);
00477         return 1;
00478     }
00479     
00480     /* Given a completed request, parse the data and update our information. */
00481     if (mode == NEXSTAR_PROCESS_REQUEST) {
00482         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00483         char *buffer = nexstar.commsPackets[handle].buffer;
00484         REQUEST_BUFFER_CHECK(0, 0);
00485         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00486         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00487         return 1;
00488     }
00489     
00490     return 0;
00491 }
00492 
00493 /** nexstar_request_set_location(int mode, unsigned char handle, NEXSTAR_LOCATION *location)
00494  *
00495  * Used to set the Nexstar's location.
00496  *
00497  * @param int mode Determine what action to create, queue request or process packet.
00498  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00499  * @param NEXSTAR_LOCATION *location A pointer to a data struct holding the data.
00500  * @return zero on failure or error, non-zero otherwise.
00501  */
00502 int nexstar_request_set_location(int mode, unsigned char handle, NEXSTAR_LOCATION *location) {
00503 
00504     /* Create request and queue. */    
00505     if (mode == NEXSTAR_SEND_REQUEST) {
00506         REQUEST_HANDLE;
00507         nexstar.commsPackets[handle].buffer[0] = 'W';
00508         memcpy((char *)nexstar.commsPackets[handle].buffer + 1, (char *)location, 8);
00509         REQUEST_SET(NEXSTAR_SET_LOCATION, 9);
00510         return 1;
00511     }
00512     
00513     /* Given a completed request, parse the data and update our information. */
00514     if (mode == NEXSTAR_PROCESS_REQUEST) {
00515         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00516         char *buffer = nexstar.commsPackets[handle].buffer;
00517         REQUEST_BUFFER_CHECK(1, 0);
00518         nexstar.trackingMode = buffer[0];
00519         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00520         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00521         return 1;
00522     }
00523     
00524     return 0;
00525 }
00526 
00527 /** nexstar_request_set_time(int mode, unsigned char handle, NEXSTAR_TIME *time)
00528  *
00529  * Used to set the Nexstar time.
00530  *
00531  * @param int mode Determine what action to create, queue request or process packet.
00532  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00533  * @param NEXSTAR_TIME *time A pointer to a data struct holding the data.
00534  * @return zero on failure or error, non-zero otherwise.
00535  */
00536 int nexstar_request_set_time(int mode, unsigned char handle, NEXSTAR_TIME *time) {
00537 
00538     /* Create request and queue. */    
00539     if (mode == NEXSTAR_SEND_REQUEST) {
00540         REQUEST_HANDLE;
00541         nexstar.commsPackets[handle].buffer[0] = 'H';
00542         memcpy((char *)nexstar.commsPackets[handle].buffer + 1, (char *)time, 8);
00543         REQUEST_SET(NEXSTAR_SET_TIME, 9);
00544         return 1;
00545     }
00546     
00547     /* Given a completed request, parse the data and update our information. */
00548     if (mode == NEXSTAR_PROCESS_REQUEST) {
00549         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00550         char *buffer = nexstar.commsPackets[handle].buffer;
00551         REQUEST_BUFFER_CHECK(0, 0);
00552         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00553         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00554         return 1;
00555     }
00556     
00557     return 0;
00558 }
00559 
00560 /** nexstar_request_get_version(int mode, unsigned char handle)
00561  *
00562  * Used to set the Nexstar software version.
00563  *
00564  * @param int mode Determine what action to create, queue request or process packet.
00565  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00566  * @return zero on failure or error, non-zero otherwise.
00567  */
00568 int nexstar_request_get_version(int mode, unsigned char handle) {
00569 
00570     /* Create request and queue. */    
00571     if (mode == NEXSTAR_SEND_REQUEST) {
00572         REQUEST_HANDLE;
00573         nexstar.commsPackets[handle].buffer[0] = 'V';
00574         REQUEST_SET(NEXSTAR_ASK_VERSION, 1);
00575         return 1;
00576     }
00577     
00578     /* Given a completed request, parse the data and update our information. */
00579     if (mode == NEXSTAR_PROCESS_REQUEST) {
00580         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00581         char *buffer = nexstar.commsPackets[handle].buffer;
00582         REQUEST_BUFFER_CHECK(2, 0);
00583         nexstar.version = (buffer[0] << 8) | buffer[1];
00584         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00585         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00586         return 1;
00587     }
00588     
00589     return 0;
00590 }
00591 
00592 /** nexstar_request_raw(int mode, unsigned char handle, NEXSTAR_COMMS_PACKET *q)
00593  *
00594  * Used for external callers to setup a REQUEST based on an externally defined packet structure.
00595  *
00596  * This function allows other parts of the system to make Nextstar requests that are not covered
00597  * by the API or just want to handle a request via a callback. 
00598  *
00599  * @param int mode Determine what action to create, queue request or process packet.
00600  * @param unsigned char handle If processing a request this is the index of the packet to be processed.
00601  * @param pointer A pointer to a predefined comms request packet to copy into our queue.
00602  * @return zero on failure or error, non-zero otherwise.
00603  */
00604 int nexstar_request_raw(int mode, unsigned char handle, NEXSTAR_COMMS_PACKET *q) {
00605 
00606     /* Create request and queue. */    
00607     if (mode == NEXSTAR_SEND_REQUEST) {
00608         /* Externally handled requests must have a callback defined as a completion handler. */
00609         if (q->callback == NULL) {
00610             return 0;
00611         }
00612         REQUEST_HANDLE;
00613         memcpy(&nexstar.commsPackets[handle], q, sizeof(NEXSTAR_COMMS_PACKET));
00614         REQUEST_SET(NEXSTAR_REQUEST_RAW, 0);
00615         return 1;
00616     }
00617     
00618     /* Given a completed request, parse the data and update our information. */
00619     if (mode == NEXSTAR_PROCESS_REQUEST) {
00620         if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
00621         if (nexstar.commsPackets[handle].callback != NULL) {
00622             (nexstar.commsPackets[handle].callback)(&nexstar.commsPackets[handle]);
00623         }
00624         nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
00625         REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
00626         return 1;
00627     }
00628    
00629     return 0;
00630 }
00631 
00632 
00633 /** nexstar_send_request(int handle)
00634  *
00635  * Used to send a request packet to Nexstar via the serial port.
00636  *
00637  * @param int handle The packet to send.
00638  * @return zero on failure, non-zero otherwise. 
00639  */
00640 int nexstar_send_request(int handle) {
00641     if (nexstar.commsPackets[handle].requestStatus == NEXSTAR_REQUEST_PENDING) {
00642         nexstar.commsPackets[handle].requestStatus = NEXSTAR_REQUEST_IN_PROGRESS;
00643         if (Uart2_puts(nexstar.commsPackets[handle].buffer, (int)nexstar.commsPackets[handle].txLength) != 0) {                
00644             memset(nexstar.commsPackets[handle].buffer, 0, NEXSTAR_PACKET_BUFFER_SIZE);
00645             nexstar.commsPackets[handle].bufferPointer = 0;
00646             // Note, we only start the timeout timer AFTER the TxFIFO goes empty, see below.
00647             return 1;
00648         }
00649         else {
00650             /* If we failed to fill the Tx FIFo then switch this request back to pending. */
00651             REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_PENDING);        
00652             return 0;
00653         }
00654     }
00655     return 0;
00656 }
00657 
00658 /** UART2_IRQHandler(void)
00659  *
00660  * The interrupt service routine for the UART2.
00661  */
00662 extern "C" void UART2_IRQHandler(void) {
00663     char c;
00664     uint32_t iir; 
00665 
00666     /* Get the interrupt identification register which also resets IIR. */
00667     iir = LPC_UART2->IIR;
00668 
00669     if (iir & 0x0001) {
00670         /* Eh? Then why did we interrupt? */
00671         return;
00672     }
00673        
00674     /* Do we have incoming data? */
00675     if (iir & UART_ISSET_RDA) {
00676         c = (char)LPC_UART2->RBR;
00677         //debug.printf(" %c", c & 0x7f);
00678         if (nexstar.commsPackets[nexstar.currentRequest].requestStatus != NEXSTAR_REQUEST_IN_PROGRESS) { 
00679             return;
00680         }
00681         nexstar.commsPackets[nexstar.currentRequest].buffer[nexstar.commsPackets[nexstar.currentRequest].bufferPointer] = c;
00682         nexstar.commsPackets[nexstar.currentRequest].bufferPointer++;
00683         nexstar.commsPackets[nexstar.currentRequest].bufferPointer &= (NEXSTAR_PACKET_BUFFER_SIZE-1);
00684         if (c == '#' || c == '\r' || c == '\n') {            
00685             timeout.stop();   /* Halt the timeout timer. */
00686             REQUEST_SET_PACKET_STATUS(nexstar.currentRequest, NEXSTAR_REQUEST_COMPLETE);
00687             
00688             /* Advance to the next request packet and if pending start it. */
00689             //NEXSTAR_NEXT_REQUEST(nexstar.currentRequest);
00690             //nexstar_send_request(nexstar.currentRequest);
00691             //debug.printf("\r\n");
00692         }
00693     }
00694 
00695     /* If the THRE goes empty AND the TxFIFO is also empty then a command
00696        was just sent to the Nexstar. Start the serial timeout timer so we 
00697        only make a timeout measurement AFTER we have sent our command. 
00698        That way we don't include our serial transmit time within the timeout
00699        specified by the timer. */
00700     if (iir & UART_ISSET_THRE) {
00701         if ((LPC_UART2->FIFOLVL & UART_ISSET_FIFOLVL_TXFULL) == 0) {
00702             timeout.start(nexstar.commsPackets[nexstar.currentRequest].timeout == 0 ? NEXSTAR_SERIAL_TIMEOUT : (uint32_t)nexstar.commsPackets[nexstar.currentRequest].timeout);
00703         }
00704     }  
00705     
00706     if (iir & UART_ISSET_RLS) {
00707         // Do nothing for now other than read the iir register and clear the interrupt.
00708     }
00709 }
00710 
00711 /** Uart2_init
00712  *
00713  * Initialise UART2 to our requirements for Nexstar.
00714  */
00715 void Uart2_init (void) {
00716 
00717     /* Switch on UART2. */
00718     LPC_SC->PCONP |= UART2_ORMASK_PCONP;
00719 
00720     /* Set PCLK == CCLK, 96Mhz */
00721     LPC_SC->PCLKSEL1 |= UART2_ORMASK_PCLKSEL1;
00722 
00723     /* Enable the tx/rx to pins and select pin mode. */
00724     LPC_PINCON->PINSEL0  |= UART2_ORMASK_PINSEL0;
00725     LPC_PINCON->PINMODE0 |= UART2_ORMASK_PINMODE0;
00726        
00727     /* Set the divisor values for 9600 and then set 8,n,1 */
00728     LPC_UART2->LCR = UART2_SET_LCR_DLAB;
00729     LPC_UART2->DLL = UART2_SET_DLLSB;
00730     LPC_UART2->DLM = UART2_SET_DLMSB;
00731     LPC_UART2->LCR = UART2_SET_LCR;
00732     
00733     /* Enable FIFOs and then clear them. */
00734     LPC_UART2->FCR = UART2_SET_FCR;
00735     LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
00736 
00737     /* Enable the RDA and THRE interrupts. */
00738     LPC_UART2->IER = UART2_SET_IER;
00739     
00740     /* Now it's time to do interrupts. */
00741     NVIC_SetVector(UART2_IRQn, (uint32_t)UART2_IRQHandler);
00742     NVIC_EnableIRQ(UART2_IRQn);    
00743 }
00744 
00745 /** Uart2_flush_rxfifo
00746  * 
00747  * Flush the input RX fifo to make sure it's empty.
00748  */
00749 void Uart2_flush_rxfifo(void) {
00750     uint8_t c;
00751     while (LPC_UART2->LSR & 0x1) {
00752         c = LPC_UART2->RBR;
00753     }
00754 }
00755 
00756 /** Uart2_putc
00757  *
00758  * Put the character given into the TxFIFO.
00759  * By design there should always be room in 
00760  * the fifo, but check it to make sure.
00761  *
00762  * @param char The character to write.
00763  * @return int zero on failure, non-zero otherwise.
00764  */
00765 int Uart2_putc(char c) {
00766     /* Check the TxFIFO is not full.  */
00767     if ((LPC_UART2->FIFOLVL & UART_ISSET_FIFOLVL_TXFULL) != 0) return 0;
00768     LPC_UART2->THR = (uint8_t)c;
00769     return -1;
00770 }
00771 
00772 /** Uart2_puts
00773  *
00774  * Put the string given into the TX FIFO.
00775  * By design there should always be room in 
00776  * the fifo, but check it to make sure.
00777  *
00778  * @param char *s Pointer The string to write.
00779  * @return int zero on failure, non-zero (number of chars written) otherwise.
00780  */
00781 int Uart2_puts(char *s, int len) {
00782     int i;
00783     
00784     /* Check the FIFO is empty, as it should always be by design. */
00785     if ((LPC_UART2->FIFOLVL & UART_ISSET_FIFOLVL_TXFULL) == 0) {
00786         for (i = 0; i < len; i++) {
00787             LPC_UART2->THR = (uint8_t)s[i];
00788             debug.printf("%c", s[i]);
00789         }
00790         debug.printf("\r\n");
00791     }
00792     else {
00793         return 0;
00794     }
00795     return i;
00796 }
00797 
00798 #endif