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

gps.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     Implementation notes.
00025     The SOWB reads GPS data in on RDX1. We don't use TDX1 as we use it as part 
00026     of the SSP/SPI for the MAX7456/Flash card reader. However, we are not really
00027     interested in writing to the GPS module as the most crucial data is the time
00028     rather than the location. We do use the location data but we don't need any
00029     WAAS data correction, 10metres is enough accuracy. So we only use Uart1 Rx to 
00030     get data.
00031     
00032     Additionally, the GPS 1 pulse per second signal is connected to a P29 (P0.5)
00033     and the gpioirq.c module routes that interrupt back to us via the _gps_pps_irq()
00034     callback function.    
00035 */ 
00036 
00037 #include "sowb.h"
00038 #include "rit.h"
00039 #include "gpio.h"
00040 #include "gps.h"
00041 #include "math.h"
00042 #include "debug.h"
00043 
00044 /* Module global variables. */
00045 double              lat_average;
00046 double              lon_average;
00047 double              lat_history[GPS_HISTORY_SIZE];
00048 double              lon_history[GPS_HISTORY_SIZE];
00049 int                 history_in_index;
00050 int                 history_complete;
00051 GPS_TIME            the_time; 
00052 GPS_LOCATION_RAW    the_location;
00053 
00054 double              lat_acc_average;
00055 double              lon_acc_average;
00056 double              cnt_acc_average;
00057 
00058 /* We maintain two serial input buffers so that the
00059    _process() function can be processing one buffer
00060    while the serial interrupt system can be capturing 
00061    to the other. */
00062 char uart1_buffer[2][GPS_BUFFER_SIZE];
00063 
00064 #define UART1_BUFFER_A  0
00065 #define UART1_BUFFER_B  1
00066 
00067 char active_buffer, active_buffer_in;
00068 char passive_buffer_ready;
00069 
00070 /* Update flag to signal new data in the active buffer. */
00071 char have_new_location;
00072 
00073 /* Set to non-zero by the updater interrupts. */
00074 char time_updated;
00075 char location_updated;
00076 
00077 /* Internal function prototypes. */
00078 void _gps_process_rmc(char passive_buffer);
00079 void _gps_process_gga(char passive_buffer);
00080 void _gps_time_inc(GPS_TIME *q);
00081 void _gps_date_inc(GPS_TIME *q);
00082 void _gps_timer_tick_cb(int);
00083 void _gps_pps_alive_cb(int);
00084 void Uart1_init(void);
00085 
00086 /** gps_process
00087  */
00088 void gps_process(void) {
00089     int i, j;
00090     uint32_t ier_copy;
00091     char passive_buffer;
00092     double lat_temp, lon_temp;
00093     
00094     if (passive_buffer_ready == 1) {
00095         /* Disable serial interrupts on UART1 */   
00096         ier_copy = LPC_UART1->IER;
00097         LPC_UART1->IER = 0x0;
00098     
00099         /* What index is the passive buffer, i.e., what is the opposite
00100            of the current active buffer? */
00101         passive_buffer = active_buffer == 0 ? 1 : 0;
00102         
00103         if (!strncmp(uart1_buffer[passive_buffer], "$GPRMC", 6)) {
00104             _gps_process_rmc(passive_buffer);
00105         }
00106         else if (!strncmp(uart1_buffer[passive_buffer], "$GPGGA", 6)) {
00107             _gps_process_gga(passive_buffer);
00108         }
00109         
00110         /* Flag we have completed processing the passive buffer. */
00111         passive_buffer_ready = 0;
00112         
00113         /* Enable serial interrupts on UART1 */   
00114         LPC_UART1->IER = ier_copy;
00115     }
00116     
00117     /* Update the latitude/longitude moving average filter. */
00118     if (the_location.is_valid && have_new_location != 0) {
00119         have_new_location = 0;
00120         lat_history[history_in_index] = gps_convert_coord(the_location.lat, GPS_LAT_STR);
00121         lon_history[history_in_index] = gps_convert_coord(the_location.lon, GPS_LON_STR);
00122         history_in_index++;
00123         if (history_in_index >= GPS_HISTORY_SIZE) {
00124             history_in_index = 0;
00125             history_complete = 1;
00126         }
00127         j = history_complete == 1 ? GPS_HISTORY_SIZE+1 : history_in_index;
00128         for(lat_temp = lon_temp = 0., i = 1; i < j; i++) {            
00129             lat_temp += lat_history[i - 1];
00130             lon_temp += lon_history[i - 1];        
00131         }
00132         if (i) {
00133             lat_average = lat_temp / (double)(i - 1);
00134             lon_average = lon_temp / (double)(i - 1);
00135             location_updated = 1;
00136         }
00137     }  
00138 }
00139 
00140 /** _gps_process_rmc
00141  *
00142  * Extract the NMEA data from an RMC packet. 
00143  * Sample:-
00144  * $GPRMC,132555.639,A,5611.5374,N,00302.0325,W,000.0,129.3,020910,,,A*75
00145  *
00146  * @param char passive_buffer Which buffer holds the RMC packet data.
00147  */
00148 void _gps_process_rmc(char passive_buffer) {
00149     char *token;
00150     int  token_counter = 0;
00151     char *time   = (char *)NULL;
00152     char *date   = (char *)NULL;
00153     char *status = (char *)NULL;
00154     
00155     token = strtok(uart1_buffer[passive_buffer], ",");
00156     while (token) {
00157         switch (token_counter) {
00158             case 9: date   = token; break;
00159             case 1: time   = token; break;
00160             case 2: status = token; break;
00161         }
00162         token = strtok((char *)NULL, ",");
00163         token_counter++;
00164     }
00165     
00166     if (status && date && time) {
00167         the_time.hour       = (char)((time[0] - '0') * 10) + (time[1] - '0');
00168         the_time.minute     = (char)((time[2] - '0') * 10) + (time[3] - '0');
00169         the_time.second     = (char)((time[4] - '0') * 10) + (time[5] - '0');
00170         the_time.day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
00171         the_time.month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
00172         the_time.year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
00173         the_time.is_valid   = status[0] == 'A' ? 1 : 0;
00174         the_time.prev_valid = 1;
00175     }
00176     else {
00177         the_time.is_valid = 0;
00178     }
00179 }
00180 
00181 /** _gps_process_gga
00182  *
00183  * Extract the NMEA data from a GGA packet. 
00184  * Sample:-
00185  * $GPGGA,132526.639,5611.5417,N,00302.0298,W,1,05,7.3,43.4,M,52.0,M,,0000*70
00186  *
00187  * @param char passive_buffer Which buffer holds the GGA packet data.
00188  */
00189 void _gps_process_gga(char passive_buffer) {
00190     char *token;
00191     int  token_counter = 0;
00192     char *latitude  = (char *)NULL;
00193     char *longitude = (char *)NULL;
00194     char *lat_dir   = (char *)NULL;
00195     char *lon_dir   = (char *)NULL;
00196     char *qual      = (char *)NULL;
00197     char *altitude  = (char *)NULL;
00198     char *sats      = (char *)NULL;
00199     
00200     token = strtok(uart1_buffer[passive_buffer], ",");
00201     while (token) {
00202         switch (token_counter) {
00203                 case 2:  latitude  = token; break;
00204                 case 4:  longitude = token; break;
00205                 case 3:  lat_dir   = token; break;    
00206                 case 5:  lon_dir   = token; break;    
00207                 case 6:  qual      = token; break;
00208                 case 7:  sats      = token; break;
00209                 case 9:  altitude  = token; break;
00210         }
00211         token = strtok((char *)NULL, ",");
00212         token_counter++;
00213     }
00214 
00215     /* If the fix quality is valid set our location information. */
00216     if (latitude && longitude && altitude && sats) { 
00217         memcpy(the_location.lat, latitude,  10); /* Fixed length string. */
00218         memcpy(the_location.lon, longitude, 10); /* Fixed length string. */
00219         memset(the_location.alt, 0, sizeof(the_location.alt)); /* Clean string out first. */
00220         strncpy(the_location.alt, altitude, 10); /* Variable length string. */
00221         strncpy(the_location.sats, sats, 3);     /* Variable length string. */
00222         the_location.north_south = lat_dir[0];
00223         the_location.east_west   = lon_dir[0];
00224         the_location.is_valid    = qual[0];
00225         the_location.updated++;
00226         have_new_location = 1;
00227     }
00228     else {
00229         the_location.is_valid = qual[0];
00230     }    
00231 }
00232 
00233 /** gps_convert_coord
00234  *
00235  * Given a string and a type convert the string into a double.
00236  *
00237  * @param char *s A pointer to the string to convert.
00238  * @param int type The conversion type required (lat or lon)
00239  * @return double the converted string.
00240  */
00241 double gps_convert_coord(char *s, int type) {
00242     int deg, min, sec;
00243     double fsec, val;
00244     
00245     if (type == GPS_LAT_STR) {
00246         deg  = ( (s[0] - '0') * 10) + s[1] - '0';
00247         min  = ( (s[2] - '0') * 10) + s[3] - '0';
00248         sec  = ( ((s[5] - '0') * 1000) + ((s[6] - '0') * 100) + ((s[7] - '0') * 10) + (s[8] - '0'));
00249         fsec = (double)((double)sec /10000.0);
00250         val  = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);
00251         return val;
00252     }
00253     else {
00254         deg  = ( (s[0] - '0') * 100) + ((s[1] - '0') * 10) + (s[2] - '0');
00255         min  = ( (s[3] - '0') * 10) + s[4] - '0';
00256         sec  = ( ((s[6] - '0') * 1000) + ((s[7] - '0') * 100) + ((s[8] - '0') * 10) + (s[9] - '0'));
00257         fsec = (double)((double)sec /10000.0);
00258         val  = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);
00259         return val;
00260     }
00261 }
00262 
00263 /** gps_init
00264  */
00265 void gps_init(void) {
00266     int i;
00267     
00268     DEBUG_INIT_START;
00269     
00270     /* Set the time to a known starting point in the past. */
00271     the_time.year       = 2000;
00272     the_time.month      = 1;
00273     the_time.day        = 1;
00274     the_time.hour       = 0;
00275     the_time.minute     = 0;
00276     the_time.second     = 0;
00277     the_time.tenth      = 0;
00278     the_time.hundreth   = 0;
00279     the_time.is_valid   = 0;
00280     the_time.prev_valid = 0;
00281     
00282     memset(&the_location, 0, sizeof(GPS_LOCATION_RAW));
00283     
00284     /* Initial condition. */
00285     time_updated = 0;
00286     
00287     /* Zero out the moving average filter. */
00288     lat_average = 0.;
00289     lon_average = 0.;
00290     history_in_index = 0;
00291     history_complete = 0;
00292     for(i = 0; i < GPS_HISTORY_SIZE; i++) {
00293         lat_history[i] = 0.;
00294         lon_history[i] = 0.;
00295     }
00296 
00297     lat_acc_average = 0.;
00298     lon_acc_average = 0.;
00299     cnt_acc_average = 0.;
00300 
00301     /* Init the active buffer and the serial in pointer. */
00302     active_buffer = active_buffer_in = 0;
00303     
00304     /* Flag the passive buffer is not ready. The passive buffer
00305        is the opposite of the active buffer. When the serial irq
00306        system detects the end of a NEMA message it automatically 
00307        switches buffers and sets passive_buffer_ready non-zero to
00308        indicate it's just finished dumping data into it. */
00309     passive_buffer_ready = 0;
00310     
00311     /* Updated to non-zero after a new location packet is received. */
00312     have_new_location = 0;
00313     
00314     /* Setup the 0.01second timer. */
00315     rit_timer_set_reload(RIT_TIMER_CB_GPS, 10);  /* Recurring reload. */
00316     rit_timer_set_counter(RIT_TIMER_CB_GPS, 10); /* Start timer. */
00317     
00318     DEBUG_INIT_END;
00319     
00320     Uart1_init();    
00321 }
00322 
00323 /** gps_get_time
00324  * 
00325  * Copies our internal time data structure to a buffer supplied by the caller.
00326  *
00327  * Note, the update flag is set to non-zero by the interrupt routines when an
00328  * update occurs. The loop is to test if an update occured while the copy was
00329  * in progress. If it did, do the copy again as it's most likely corrupted the
00330  * orginal copy operation.
00331  *
00332  * @param GPS_TIME *q A pointer to the GPS_TIME data structure to copy to.
00333  * @return GPS_TIME * The supplied pointer.
00334  */
00335 GPS_TIME *gps_get_time(GPS_TIME *q) {
00336 
00337     do {
00338         time_updated = 0;
00339         memcpy(q, &the_time, sizeof(GPS_TIME));
00340     } while (time_updated != 0);
00341     
00342     return q;
00343 }
00344 
00345 /** gps_get_location_raw
00346  * 
00347  * Copies our internal location data structure to a buffer supplied by the caller.
00348  *
00349  * Note, the update flag is set to non-zero by the interrupt routines when an
00350  * update occurs. The loop is to test if an update occured while the copy was
00351  * in progress. If it did, do the copy again as it's most likely corrupted the
00352  * orginal copy operation.
00353  *
00354  * @param GPS_LOCATION_RAW *q A pointer to the GPS_LOCATION_RAW data structure to copy to.
00355  * @return GPS_LOCATION_RAW * The supplied pointer.
00356  */
00357 GPS_LOCATION_RAW *gps_get_location_raw(GPS_LOCATION_RAW *q) {
00358 
00359     do {
00360         location_updated = 0;
00361         memcpy(q, &the_location, sizeof(GPS_LOCATION_RAW));
00362     } while (location_updated != 0);
00363     
00364     return q;
00365 }
00366 
00367 /** gps_get_location_average
00368  *
00369  * Places the current average location into the supplied struct buffer.
00370  * The caller is responsible for allocating the buffer storage space.
00371  *
00372  * Note, the update flag is set to non-zero by the interrupt routines when an
00373  * update occurs. The loop is to test if an update occured while the copy was
00374  * in progress. If it did, do the copy again as it's most likely corrupted the
00375  * orginal copy operation.
00376  *
00377  * @param GPS_LOCATION_AVERAGE *q A pointer to the struct buffer to write data to.
00378  * @return GPS_LOCATION_AVERAGE *  The supplied pointer returned.
00379  */
00380 GPS_LOCATION_AVERAGE *gps_get_location_average(GPS_LOCATION_AVERAGE *q) {
00381     char **p = NULL;
00382 
00383     do {
00384         location_updated = 0;
00385         q->north_south  = the_location.north_south;
00386         q->latitude     = lat_average;
00387         q->east_west    = the_location.east_west;
00388         q->longitude    = lon_average;
00389         q->height       = strtod(the_location.alt, p); 
00390         q->sats         = the_location.sats;   
00391         q->is_valid     = the_location.is_valid;
00392     } while (location_updated != 0);
00393 
00394     /* Test the values to ensure the data is valid. */
00395     if (isnan(q->latitude) || isnan(q->longitude) || isnan(q->height)) {
00396         q->is_valid = 0;
00397     }
00398     
00399     return q;
00400 }
00401 
00402 /** gps_julian_day_number
00403  *
00404  * Gets the Julian Day Number from the supplied time reference passed.
00405  * http://en.wikipedia.org/wiki/Julian_day#Converting_Gregorian_calendar_date_to_Julian_Day_Number
00406  *
00407  * @param GPS_TIME *t A pointer to a time data structure.
00408  * @return double The Julian Day Number.
00409  */
00410 double gps_julian_day_number(GPS_TIME *t) {
00411     double wikipedia_jdn = (double)(1461 * ((int)t->year + 4800 + ((int)t->month - 14) / 12)) / 4 + (367 * ((int)t->month - 2 - 12 * (((int)t->month - 14) / 12))) / 12 - (3 * (((int)t->year + 4900 + ((int)t->month - 14) / 12 ) / 100)) / 4 + (int)t->day - 32075;
00412     
00413     /* Not sure why yet but the calculation on the Wikipedia site returns a value that
00414        is 0.5 too big. */
00415     return wikipedia_jdn;
00416 }
00417 
00418 /** gps_julian_date
00419  * 
00420  * Find the Julian Date based on the supplied args.
00421  *
00422  * @param GPS_TIME *t A pointer to a time data structure.
00423  * @return double The Julian Date.
00424  */
00425 double gps_julian_date(GPS_TIME *t) {
00426     double hour, minute, second, jd;
00427     hour   = (double)t->hour;
00428     minute = (double)t->minute;
00429     second = (double)t->second + ((double)t->tenth / 10.) + ((double)t->hundreth / 100.);
00430                                    /* Wiki fix, see above. */  
00431     jd = gps_julian_day_number(t) -           0.5 +
00432          ((hour - 12.) / 24.) +
00433          (minute / 1440.) + 
00434          (second / 86400.);        
00435         
00436     return jd;
00437 }
00438 
00439 /** gps_siderealDegrees_by_jd
00440  *
00441  * Calculate the sidereal degree angle based on the 
00442  * Julian Date supplied.
00443  *
00444  * @param double jd Julian Date.
00445  * @return The sidereal angle in degrees.
00446  */
00447 double gps_siderealDegrees_by_jd(double jd) {
00448     double sidereal, gmst, lmst, mul;
00449     double T  = jd - 2451545.0;
00450     double T1 = T / 36525.0;
00451     double T2 = T1 * T1;
00452     double T3 = T2 * T1;
00453      
00454     /* Calculate gmst angle. */
00455     sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
00456      
00457     /* Convert to degrees. */
00458     sidereal = fmod(sidereal, 360.0);
00459     if (sidereal < 0.0) sidereal += 360.0;
00460  
00461     mul = (the_location.east_west == 'W') ? -1.0 : 1.0;
00462     
00463     gmst = sidereal;
00464     lmst = gmst + (lon_average * mul);
00465     return lmst;
00466 }
00467 
00468 /** gps_siderealDegrees_by_time
00469  *
00470  * Calculate the sidereal degree angle based on the 
00471  * time data structure supplied.
00472  *
00473  * @param GPS_TIME *t A pointer to the time structure.
00474  * @return The sidereal angle in degrees.
00475  */
00476 double gps_siderealDegrees_by_time(GPS_TIME *t) {
00477     GPS_TIME temp;
00478     if (t == (GPS_TIME *)NULL) {
00479         t = &temp;
00480         gps_get_time(t);        
00481     }
00482     return gps_siderealDegrees_by_jd(gps_julian_date(t));
00483 }
00484 
00485 /** gps_siderealHA_by_jd
00486  *
00487  * Calculate the HA (hour angle) based on the supplied Julian Date.
00488  *
00489  * @param double jd The Julian Date.
00490  * @return double The Hour Angle.
00491  */
00492 double gps_siderealHA_by_jd(double jd) {
00493     double lmst = gps_siderealDegrees_by_jd(jd);
00494     return lmst / 360.0 * 24.0;
00495 }
00496 
00497 /** gps_siderealHA_by_time
00498  *
00499  * Calculate the HA (hour angle) based on the supplied time data structure.
00500  *
00501  * @param GPS_TIME *t The time data structure.
00502  * @return double The Hour Angle.
00503  */
00504 double gps_siderealHA_by_time(GPS_TIME *t) {
00505     double lmst = gps_siderealDegrees_by_time(t);
00506     return lmst / 360.0 * 24.0;
00507 }
00508 
00509 /** _gps_inc_time
00510  *
00511  * Used to increment the time structure by 0.01sec.
00512  * Called by the RIT timer callback.
00513  *
00514  * @see gpioirq.c
00515  * @param int t_index The timer's index number (handle).
00516  */
00517 void _gps_timer_tick_cb(int t_index) {
00518     
00519     /* We use x so that the_time.hundreth can never be 10 as I have noticed
00520        occasionally between the ++ and the == 10 test an interrupt can occur
00521        and then the_time.hundreth contains an invalid value. So using x to do
00522        the ++ and ==10 test means the_time.hundreth can never itself be 10. 
00523        We reuse x on the tenths for a similar reason. */
00524     char x = the_time.hundreth;
00525     x++;
00526     
00527     if (x == 10) {
00528         the_time.hundreth = 0;
00529         x = the_time.tenth + 1;
00530         if (x < 10) {  
00531             the_time.tenth = x;
00532             time_updated = 1;
00533         }
00534     }
00535     else {
00536         the_time.hundreth = x;
00537         time_updated = 1;
00538     }
00539 }
00540 
00541 /** _gps_pps_alive_cb
00542  *
00543  * Timeout that goes off if the GPS 1PPS signal doesn't
00544  * fire within 1.5seconds telling us that the GPS isn't
00545  * connected. Not currently used.
00546  */
00547 void _gps_pps_alive_cb(int index) {
00548     the_time.is_valid = 0;
00549 }
00550  
00551 /** gps_pps_fall
00552  *
00553  * Increments the seconds. Called by the GPS 1PP callback interrupt.
00554  *
00555  * Note, some GPS modules, including the one used in this design, 
00556  * provide a 1PPS signal. However, it's almost always positive logic
00557  * and it doesn't interface directly to an Mbed pin/interrupt. So we 
00558  * have a simple FET that buffers the signal and in so doing it becomes
00559  * an active low signal. Hence why this is a falling edge interrupt.
00560  *
00561  * @see gpioirq.c
00562  */
00563 void gps_pps_fall(void) {
00564     the_time.hundreth = 0;
00565     the_time.tenth    = 0;
00566     _gps_time_inc(&the_time);           
00567 }
00568 
00569 /** gps_date_inc
00570  *
00571  * Increment the time.
00572  *
00573  * @param GPS_TIME *q Pointer the data struct holding the time.
00574  */
00575 void _gps_time_inc(GPS_TIME *q) {
00576     
00577     time_updated = 1;
00578     
00579     q->second++;
00580     if (q->second == 60) {
00581         q->second = 0;
00582         q->minute++;
00583         if (q->minute == 60) {
00584             q->minute = 0;
00585             q->hour++;
00586             if (q->hour == 24) {
00587                 q->hour = 0;
00588                 _gps_date_inc(q);
00589             }
00590         }
00591     }
00592 }
00593 
00594 /** _gps_date_inc
00595  *
00596  * Increment the date.
00597  *
00598  * @param GPS_TIME *q Pointer the data struct holding the time.
00599  */
00600 void _gps_date_inc(GPS_TIME *q) {
00601     const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 } ;
00602 
00603     /* Handle February leap year. */    
00604     int leap_year = ((the_time.year % 4 == 0 && the_time.year % 100 != 0) || the_time.year % 400 == 0) ? 1 : 0;
00605     int days_this_month = days[q->month - 1];
00606     if (q->month == 2 && leap_year) days_this_month++;
00607     
00608     q->day++;
00609     if (q->day > days_this_month) {
00610         q->day = 1;
00611         q->month++;
00612         if (q->month == 13) {
00613             q->year++;
00614         }
00615     }
00616 }
00617 
00618 /* UART1 functions. */
00619 
00620 extern "C" void UART1_IRQHandler(void) __irq {
00621     volatile uint32_t iir;
00622     volatile char c;
00623     
00624     iir = LPC_UART1->IIR;
00625     
00626     if (iir & 0x1) return;
00627     
00628     /* Do we have a serial character(s) in the fifo? */
00629     if (UART_RX_INTERRUPT) {
00630         while (UART1_FIFO_NOT_EMPTY) {
00631             c = UART1_GETC;
00632             uart1_buffer[active_buffer][active_buffer_in++] = c;
00633             active_buffer_in &= (GPS_BUFFER_SIZE - 1);
00634             if (c == '\n') {
00635                 /* Swap buffers and clean it out. */
00636                 active_buffer = active_buffer == 0 ? 1 : 0;
00637                 memset(uart1_buffer[active_buffer], 0, GPS_BUFFER_SIZE);
00638                 active_buffer_in = 0;
00639                 passive_buffer_ready = 1;
00640             }
00641         } 
00642     }
00643 }
00644 
00645 /** Uart1_init
00646  */
00647 void Uart1_init(void) {
00648     
00649     DEBUG_INIT_START;
00650     
00651     LPC_SC->PCONP       |=  (1UL << 4);
00652     LPC_SC->PCLKSEL0    &= ~(3UL << 8);
00653     LPC_SC->PCLKSEL0    |=  (1UL << 8);
00654     LPC_PINCON->PINSEL4 &= ~(3UL << 2); /* TXD1 not used. See SSP0_init() in max7456.c */
00655     LPC_PINCON->PINSEL4 |=  (2UL << 2); /* TXD1 not used. See SSP0_init() in max7456.c */
00656     LPC_UART1->LCR       = 0x83;
00657     LPC_UART1->DLL       = 0x71;
00658     LPC_UART1->DLM       = 0x02;
00659     LPC_UART1->LCR       = 0x03;
00660     LPC_UART1->FCR       = 0x07;
00661     
00662     NVIC_SetVector(UART1_IRQn, (uint32_t)UART1_IRQHandler);
00663     NVIC_EnableIRQ(UART1_IRQn);    
00664     
00665     /* Enable the RDA interrupt. */
00666     LPC_UART1->IER = 0x01; 
00667     
00668     DEBUG_INIT_END;
00669 }
00670