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

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
AjK
Date:
Mon Oct 11 10:34:55 2010 +0000
Commit message:
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums

Changed in this revision

config/config.c Show annotated file Show diff for this revision Revisions of this file
config/config.h Show annotated file Show diff for this revision Revisions of this file
debug/debug.c Show annotated file Show diff for this revision Revisions of this file
debug/debug.h Show annotated file Show diff for this revision Revisions of this file
debug/debug_printf.c Show annotated file Show diff for this revision Revisions of this file
dma/dma.c Show annotated file Show diff for this revision Revisions of this file
dma/dma.h Show annotated file Show diff for this revision Revisions of this file
flash/25AA02EE48.c Show annotated file Show diff for this revision Revisions of this file
flash/FatFS/diskio.c Show annotated file Show diff for this revision Revisions of this file
flash/FatFS/diskio.h Show annotated file Show diff for this revision Revisions of this file
flash/FatFS/ff.c Show annotated file Show diff for this revision Revisions of this file
flash/FatFS/ff.h Show annotated file Show diff for this revision Revisions of this file
flash/FatFS/ffconf.h Show annotated file Show diff for this revision Revisions of this file
flash/FatFS/integer.h Show annotated file Show diff for this revision Revisions of this file
flash/FatFS/option/ccsbcs.c Show annotated file Show diff for this revision Revisions of this file
flash/flash.c Show annotated file Show diff for this revision Revisions of this file
flash/flash.h Show annotated file Show diff for this revision Revisions of this file
flash/flash_erase.c Show annotated file Show diff for this revision Revisions of this file
flash/flash_read.c Show annotated file Show diff for this revision Revisions of this file
flash/flash_write.c Show annotated file Show diff for this revision Revisions of this file
flash/ssp0.c Show annotated file Show diff for this revision Revisions of this file
flash/ssp0.h Show annotated file Show diff for this revision Revisions of this file
gpio/gpio.c Show annotated file Show diff for this revision Revisions of this file
gpio/gpio.h Show annotated file Show diff for this revision Revisions of this file
gpioirq/gpioirq.c Show annotated file Show diff for this revision Revisions of this file
gpioirq/gpioirq.h Show annotated file Show diff for this revision Revisions of this file
gps/gps.c Show annotated file Show diff for this revision Revisions of this file
gps/gps.h Show annotated file Show diff for this revision Revisions of this file
main.c Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
md5/md5.c Show annotated file Show diff for this revision Revisions of this file
md5/md5.h Show annotated file Show diff for this revision Revisions of this file
nexstar/nexstar.c Show annotated file Show diff for this revision Revisions of this file
nexstar/nexstar.h Show annotated file Show diff for this revision Revisions of this file
nexstar/nexstar_align.c Show annotated file Show diff for this revision Revisions of this file
nexstar/nexstar_old.c Show annotated file Show diff for this revision Revisions of this file
osd/MAX7456.c Show annotated file Show diff for this revision Revisions of this file
osd/MAX7456.h Show annotated file Show diff for this revision Revisions of this file
osd/MAX7456_chars.c Show annotated file Show diff for this revision Revisions of this file
osd/MAX7456_chars.h Show annotated file Show diff for this revision Revisions of this file
osd/osd.c Show annotated file Show diff for this revision Revisions of this file
osd/osd.h Show annotated file Show diff for this revision Revisions of this file
pccomms/handlers/mode1.c Show annotated file Show diff for this revision Revisions of this file
pccomms/pccomms.c Show annotated file Show diff for this revision Revisions of this file
pccomms/pccomms.h Show annotated file Show diff for this revision Revisions of this file
rit/rit.c Show annotated file Show diff for this revision Revisions of this file
rit/rit.h Show annotated file Show diff for this revision Revisions of this file
satapi/mbedfilesys.c Show annotated file Show diff for this revision Revisions of this file
satapi/mbedfilesys.h Show annotated file Show diff for this revision Revisions of this file
satapi/satapi.c Show annotated file Show diff for this revision Revisions of this file
satapi/satapi.h Show annotated file Show diff for this revision Revisions of this file
sdcard/sdcard.c Show annotated file Show diff for this revision Revisions of this file
sdcard/sdcard.h Show annotated file Show diff for this revision Revisions of this file
sgp4sdp4/sgp4sdp4.c Show annotated file Show diff for this revision Revisions of this file
sgp4sdp4/sgp4sdp4.h Show annotated file Show diff for this revision Revisions of this file
sgp4sdp4/sgp_in.c Show annotated file Show diff for this revision Revisions of this file
sgp4sdp4/sgp_math.c Show annotated file Show diff for this revision Revisions of this file
sgp4sdp4/sgp_obs.c Show annotated file Show diff for this revision Revisions of this file
sgp4sdp4/sgp_time.c Show annotated file Show diff for this revision Revisions of this file
sgp4sdp4/solar.c Show annotated file Show diff for this revision Revisions of this file
sowb.h Show annotated file Show diff for this revision Revisions of this file
test/predict_th.c Show annotated file Show diff for this revision Revisions of this file
test/predict_th.h Show annotated file Show diff for this revision Revisions of this file
test/th_xbox360gamepad.c Show annotated file Show diff for this revision Revisions of this file
test/th_xbox360gamepad.h Show annotated file Show diff for this revision Revisions of this file
usbeh/readme.c Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh.h Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_api.c Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_api.h Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_controller.cpp Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_controller.h Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_device.cpp Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_device.h Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_endpoint.cpp Show annotated file Show diff for this revision Revisions of this file
usbeh/usbeh_endpoint.h Show annotated file Show diff for this revision Revisions of this file
usbeh/xbox360gamepad.c Show annotated file Show diff for this revision Revisions of this file
usbeh/xbox360gamepad.h Show annotated file Show diff for this revision Revisions of this file
user.c Show annotated file Show diff for this revision Revisions of this file
user.h Show annotated file Show diff for this revision Revisions of this file
utils/star.c Show annotated file Show diff for this revision Revisions of this file
utils/star.h Show annotated file Show diff for this revision Revisions of this file
utils/stations.c Show annotated file Show diff for this revision Revisions of this file
utils/stations.h Show annotated file Show diff for this revision Revisions of this file
utils/utils.c Show annotated file Show diff for this revision Revisions of this file
utils/utils.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/config.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,129 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/* Need to come back and finish this. */
+
+#include "sowb.h"
+#include "user.h"
+#include "debug.h"
+#include "config.h"
+#include "ff.h"
+
+CONFIG_UNION    system_config;
+
+bool config_block_process;
+bool config_loaded;
+bool config_reload;
+
+/** config_init
+ */
+void config_init(void) {
+    int i, j;
+    
+    DEBUG_INIT_START;
+    
+    /*
+    for (i = CONFIG_FLASH_PAGE_BASE, j = 0; i < 4096; i++, j++) {
+        flash_read_page(i, system_config.buffers[j], true);
+    }
+    
+    config_loaded        = true;
+    config_reload        = false;
+    config_block_process = false;
+    */
+    
+    DEBUG_INIT_END;
+}
+
+/** config_process
+ */
+void config_process(void) {
+
+    /* For long period operations (e.g. config_save()) that may call
+       system _process() functions, block ourselves from re-entering. */
+    if (config_block_process) return;
+    
+}
+
+void config_save(void) {
+    int i, j;
+    char buffer[FLASH_PAGE_SIZE];
+    
+    /* Don't re-enter this function from _process(). */
+    config_block_process = true;
+    
+    /* Sector 15 is used as a "scratch area". It allows us to store
+       pages from other sectors that we need to "restore" since the
+       LPC1768 doesn't have enough space to store entire sectors. */
+    while (flash_sector_erase_in_progress()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    flash_erase_sector(15);
+    while (flash_sector_erase_in_progress()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    /* We need to make a copy of all the pages below our config area
+       before we store our configuration. */
+    for (i = 4096 - 256; i < CONFIG_FLASH_PAGE_BASE; i++) {
+        flash_read_page(i, buffer, true);
+        flash_page_write(3840 + i, buffer);
+        while(flash_write_in_progress()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    }
+
+    /* Now erase the sector in which our config resides. */
+    while (flash_sector_erase_in_progress()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    flash_erase_sector(14);
+    while (flash_sector_erase_in_progress()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+
+        
+    for (i = CONFIG_FLASH_PAGE_BASE, j = 0; i < CONFIG_FLASH_PAGE_BASE + CONFIG_FLASH_PAGES; i++, j++) {
+        while(flash_write_in_progress() || flash_sector_erase_in_progress()) {
+            WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+        }
+        flash_page_write(i, system_config.buffers[j]);
+    }
+    
+    config_block_process = false;
+}
+
+/** config_copy_flash_page
+ *
+ * Used to copy the raw config struct, page by page
+ * to an external memory buffer.
+ *
+ * @param int page The page to copy.
+ * @param char* buffer The buffer to copy the page to.
+ */
+void config_copy_flash_page(int page, char *buffer) {
+    memcpy(buffer, system_config.buffers[page], FLASH_PAGE_SIZE);
+}
+
+/** config_get_page
+ *
+ * Get the base address of a specific page of config data.
+ *
+ * @param int page The page to get the address of.
+ * @return char* The address of the page.
+ */
+char * config_get_page(int page) {
+    return system_config.buffers[page];
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/config.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,46 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "flash.h"
+
+#define CONFIG_MAX_SIZE         4096
+#define CONFIG_FLASH_PAGES      CONFIG_MAX_SIZE / FLASH_PAGE_SIZE
+#define CONFIG_FLASH_PAGE_BASE  3840 - CONFIG_FLASH_PAGES
+
+typedef struct _config_values {
+    int config_struct_version;
+} CONFIG_VALUES;
+
+typedef union _config_union {
+    char buffers[CONFIG_FLASH_PAGES][FLASH_PAGE_SIZE];
+    CONFIG_VALUES   values;
+} CONFIG_UNION;
+
+void config_init(void);
+void config_process(void);
+void config_copy_flash_page(int page, char *buffer);
+char * config_get_page(int page);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debug/debug.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,193 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "debug.h"
+
+/* Design note. We do not use a txBufferOverflow flag like we
+   do with the RX buffer as all calls to Uart0_putc() will 
+   block if there isn't room to send. It's up to the designer
+   to either ensure they don't flood the TX buffer with too
+   many debug strings or alternatively increase the buffer
+   size to handle the higher amounts of traffic. */
+
+volatile char txBuffer[UART0_TX_BUFFER_SIZE];
+volatile char rxBuffer[UART0_RX_BUFFER_SIZE];
+volatile unsigned char txBufferIn, txBufferOut;
+volatile unsigned char rxBufferIn, rxBufferOut;
+volatile bool txBufferFull, rxBufferFull, rxBufferOverflow;
+
+/** UART0_IRQHandler
+ */
+extern "C" void UART0_IRQHandler(void) __irq {
+    uint32_t iir;
+    
+    iir = LPC_UART0->IIR;
+    
+    if (iir & 1) return;
+    
+    iir = (iir >> 1) & 0x3;
+    
+    if (iir == 2) {
+        if (rxBufferIn == rxBufferOut && rxBufferFull) {            
+            char c __attribute__((unused)); /* oh dear, no room, send to /dev/null */
+            c = LPC_UART0->RBR;
+            rxBufferOverflow = true;
+        }
+        else {
+            rxBuffer[rxBufferIn++] = LPC_UART0->RBR;
+            rxBufferIn &= (UART0_RX_BUFFER_SIZE - 1);
+            if (rxBufferIn == rxBufferOut) rxBufferFull = true;
+        }
+    }
+    
+    if (iir == 1) {
+        if (txBufferIn != txBufferOut || txBufferFull) {
+            LPC_UART0->THR = (uint8_t)(txBuffer[txBufferOut++]);
+            txBufferOut &= (UART0_TX_BUFFER_SIZE - 1);
+            txBufferFull = false;
+        }
+        else {
+            LPC_UART0->IER = 0x1;
+        }
+    } 
+}
+
+/** Uart0_init
+ */
+void Uart0_init(void) {
+    volatile char c __attribute__((unused));
+    
+    LPC_SC->PCONP       |=  (1UL << 3);
+    LPC_SC->PCLKSEL0    &= ~(3UL << 6);
+    LPC_SC->PCLKSEL0    |=  (1UL << 6);
+    LPC_PINCON->PINSEL0 &= ~((1UL << 4) | (1UL << 6));
+    LPC_PINCON->PINSEL0 |=  ((1UL << 4) | (1UL << 6));
+    LPC_UART0->LCR       = 0x80;
+    LPC_UART0->DLM       = 0x0;  // 0x00 for 115200 baud, for 9600 use 0x2;
+    LPC_UART0->DLL       = 0x34; // 0x34 for 115200 baud, for 9600 use 0x71;
+    LPC_UART0->LCR       = 0x3;
+    LPC_UART0->FCR       = 0x7;
+    
+    NVIC_SetVector(UART0_IRQn, (uint32_t)UART0_IRQHandler);
+    NVIC_EnableIRQ(UART0_IRQn);
+    
+    /* Enable UART0 RX interrupt only. */
+    LPC_UART0->IER = 0x1;
+}
+
+/** debug_init
+ */
+void debug_init(void) {
+    txBufferIn = txBufferOut = 0;
+    memset((char *)txBuffer, 0, UART0_TX_BUFFER_SIZE);
+    rxBufferIn = rxBufferOut = 0;
+    memset((char *)txBuffer, 0, UART0_RX_BUFFER_SIZE);
+    txBufferFull = rxBufferFull = false;
+    rxBufferOverflow = false;
+    Uart0_init();
+}
+
+#ifdef DEBUG_USE_UART0
+
+/** debug_string
+ *
+ * Print a null termimnated string to UART0.
+ *
+ * @param char *s A pointer to the null terminated string. 
+ */
+void debug_string(char *s) {
+    while (*(s)) {
+        Uart0_putc(*s++);
+    }
+}
+
+/** debug_stringl
+ *
+ * Print a string of specified length to UART0.
+ *
+ * @param char *s A pointer to the null terminated string. 
+ * @param int length The length of the string to print.
+ */
+void debug_stringl(char *s, int length) {
+    while (length--) {
+        Uart0_putc(*s++);
+    }
+}
+
+/* Local function prototype for _init(). */
+void Uart0_init(void);
+
+/** Uart0_putc
+ *
+ * Put a character out the UART0 serial port. 
+ * Note, if the THR register is not empty AND the output buffer is not empty
+ * then place the character into the output buffer and enable interrupt to
+ * flush the buffer.
+ *
+ * Additionally, if the TX buffer is full this function will BLOCK!
+ * If you have lots of debugging messages to spit out then it may be
+ * wise to either "slimeline" what you need to print out or alternatively
+ * increase the size of the txBuffer to cope with the increased traffic.
+ * Be aware of this blocking!
+ *
+ * @param char c The character to send out of UART0.
+ */
+void Uart0_putc(char c) {
+    if ((LPC_UART0->LSR & 0x20) && (txBufferIn == txBufferOut && !txBufferFull)) {
+        LPC_UART0->THR = (uint8_t)c;
+    }
+    else {  
+        while (txBufferFull) ; /* Blocks!!! */    
+        txBuffer[txBufferIn++] = c;
+        txBufferIn &= (UART0_TX_BUFFER_SIZE - 1);
+        if (txBufferIn == txBufferOut && !txBufferFull) txBufferFull = true;
+        LPC_UART0->IER = 0x3;
+    }
+}
+
+/** Uart0_getc
+ *
+ * Used to get a character from Uart0. If the passed arg "block" is non-zero
+ * then this function will block (wait) for user input. Otherwise if a char
+ * is available return it, otherwise return -1 to show buffer was empty.
+ *
+ * @param int block Should we block?
+ * @return int Cast char to int for char or -1 if non-blocking and no char.
+ */
+int Uart0_getc(int block) {
+    char c;
+    
+    if (block) while (rxBufferOut == rxBufferIn && !rxBufferFull) ; /* Blocks! */    
+    else if (rxBufferIn == rxBufferOut && !rxBufferFull) return -1;
+    
+    c = rxBuffer[rxBufferOut++];
+    rxBufferOut &= (UART0_RX_BUFFER_SIZE - 1);
+    if (rxBufferFull) rxBufferFull = false;     
+    return (int)c;   
+}
+
+/* end of #ifdef DEBUG_USE_UART0 */
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debug/debug.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,79 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* Comment out the following to totally disable debugging output on UART0. 
+   This is the global kill switch for debug output. */
+#define DEBUG_ON
+
+
+/* These are finer grained debug enable switches. */
+#ifdef DEBUG_ON
+#define DEBUG_USE_UART0
+#endif
+
+/* The following is used "interally" by the debug.c and various other modules. */
+
+void debug_init(void);
+
+/* Buffer sizes MUST be a aligned 2^, for example 8, 16, 32, 64, 128, 256, 512, 1024, etc 
+   Do NOT use any other value or the buffer wrapping firmware won't work. */ 
+#ifdef DEBUG_USE_UART0 
+#define UART0_TX_BUFFER_SIZE   8192
+#define UART0_RX_BUFFER_SIZE   16
+#else
+#define UART0_TX_BUFFER_SIZE   4
+#define UART0_RX_BUFFER_SIZE   4
+#endif
+
+
+#ifdef DEBUG_USE_UART0 
+/* If debugging is on declare the real function prototypes. */
+int  debug_printf(const char *format, ...);
+int  debug_sprintf(char *out, const char *format, ...);
+void debug_string(char *s);
+void debug_stringl(char *s, int length);
+
+#else
+
+/* If no debugging, replace debug functions with simple empty macros. */
+#define debug_printf(x, ...)
+#define debug_sprintf(x, y, ...)
+#define debug_string(x)
+#define debug_stringl(x, y)
+
+/* End #ifdef DEBUG_USE_UART0 */
+#endif
+
+#define DEBUG_INIT_START debug_printf("INIT: %s()... ", __FUNCTION__)
+#define DEBUG_INIT_END   debug_printf("complete.\r\n")
+
+/* These function prototypes are always declared. */
+void Uart0_putc(char c);
+int  Uart0_getc(int block);
+
+
+/* End #ifndef DEBUG_H */ 
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debug/debug_printf.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,214 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/* The following is from (with only minor edits to fit onto Mbed):-
+     Copyright 2001, 2002 Georges Menie (www.menie.org)
+     stdarg version contributed by Christian Ettinger
+     See...
+     http://www.menie.org/georges/embedded/ 
+     http://www.menie.org/georges/embedded/printf-stdarg.c  
+     
+     This printf function will accept integer formats (%d, %x, %X, %u), string format (%s) 
+     and character format (%c); left and right alignement, padding with space or 'O'. */
+
+#include "sowb.h"
+#include "debug.h"
+#include <stdarg.h>
+
+#ifdef DEBUG_ON
+
+static void printchar(char **str, int c)
+{
+    if (str) {
+        **str = c;
+        ++(*str);
+    }
+    else (void)Uart0_putc(c);
+}
+
+#define PAD_RIGHT 1
+#define PAD_ZERO 2
+
+static int prints(char **out, const char *string, int width, int pad)
+{
+    register int pc = 0, padchar = ' ';
+
+    if (width > 0) {
+        register int len = 0;
+        register const char *ptr;
+        for (ptr = string; *ptr; ++ptr) ++len;
+        if (len >= width) width = 0;
+        else width -= len;
+        if (pad & PAD_ZERO) padchar = '0';
+    }
+    if (!(pad & PAD_RIGHT)) {
+        for ( ; width > 0; --width) {
+            printchar (out, padchar);
+            ++pc;
+        }
+    }
+    for ( ; *string ; ++string) {
+        printchar (out, *string);
+        ++pc;
+    }
+    for ( ; width > 0; --width) {
+        printchar (out, padchar);
+        ++pc;
+    }
+
+    return pc;
+}
+
+/* the following should be enough for 32 bit int */
+#define PRINT_BUF_LEN 12
+
+static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
+{
+    char print_buf[PRINT_BUF_LEN];
+    register char *s;
+    register int t, neg = 0, pc = 0;
+    register unsigned int u = i;
+
+    if (i == 0) {
+        print_buf[0] = '0';
+        print_buf[1] = '\0';
+        return prints (out, print_buf, width, pad);
+    }
+
+    if (sg && b == 10 && i < 0) {
+        neg = 1;
+        u = -i;
+    }
+
+    s = print_buf + PRINT_BUF_LEN-1;
+    *s = '\0';
+
+    while (u) {
+        t = u % b;
+        if( t >= 10 )
+            t += letbase - '0' - 10;
+        *--s = t + '0';
+        u /= b;
+    }
+
+    if (neg) {
+        if( width && (pad & PAD_ZERO) ) {
+            printchar (out, '-');
+            ++pc;
+            --width;
+        }
+        else {
+            *--s = '-';
+        }
+    }
+
+    return pc + prints (out, s, width, pad);
+}
+
+static int print(char **out, const char *format, va_list args )
+{
+    register int width, pad;
+    register int pc = 0;
+    char scr[2];
+
+    for (; *format != 0; ++format) {
+        if (*format == '%') {
+            ++format;
+            width = pad = 0;
+            if (*format == '\0') break;
+            if (*format == '%') goto out;
+            if (*format == '-') {
+                ++format;
+                pad = PAD_RIGHT;
+            }
+            while (*format == '0') {
+                ++format;
+                pad |= PAD_ZERO;
+            }
+            for ( ; *format >= '0' && *format <= '9'; ++format) {
+                width *= 10;
+                width += *format - '0';
+            }
+            if( *format == 's' ) {
+                register char *s = (char *)va_arg( args, int );
+                pc += prints (out, s?s:"(null)", width, pad);
+                continue;
+            }
+            if( *format == 'd' ) {
+                pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');
+                continue;
+            }
+            if( *format == 'x' ) {
+                pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');
+                continue;
+            }
+            if( *format == 'X' ) {
+                pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');
+                continue;
+            }
+            if( *format == 'u' ) {
+                pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');
+                continue;
+            }
+            if( *format == 'c' ) {
+                /* char are converted to int then pushed on the stack */
+                scr[0] = (char)va_arg( args, int );
+                scr[1] = '\0';
+                pc += prints (out, scr, width, pad);
+                continue;
+            }
+        }
+        else {
+        out:
+            printchar (out, *format);
+            ++pc;
+        }
+    }
+    if (out) **out = '\0';
+    va_end( args );
+    return pc;
+}
+
+
+int debug_printf(const char *format, ...) {
+    #ifdef DEBUG_ON        
+    va_list args;
+    va_start( args, format );
+    return print( 0, format, args );
+    #else
+    return 0;
+    #endif
+}
+
+int debug_sprintf(char *out, const char *format, ...) {    
+    #ifdef DEBUG_ON        
+    va_list args;
+    va_start( args, format );
+    return print( &out, format, args );
+    #else
+    return 0;
+    #endif
+}
+
+/* end of #ifdef DEBUG_ON */
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dma/dma.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,161 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "debug.h"
+#include "dma.h"
+
+uint32_t channel_in_use_flags = 0;
+
+/* Declare callback functions here before placing 
+   in the array below. */
+int flash_read_dma0_irq(int);
+int flash_read_dma1_irq(int);
+int flash_write_dma0_irq(int);
+
+/* Make sure each array definition below ends with 
+   a NULL,NULL struct to mark the end of the array. */
+
+const DMA_CALLBACKS   dma_channel0[] = {
+    { flash_read_dma0_irq,      flash_read_dma0_irq },
+    { flash_write_dma0_irq,     flash_write_dma0_irq },
+    { NULL,                     NULL }
+};
+
+const DMA_CALLBACKS   dma_channel1[] = {
+    { flash_read_dma1_irq,      flash_read_dma1_irq },
+    { NULL,                     NULL }
+};
+
+const DMA_CALLBACKS   dma_channel2[] = {
+    { NULL,                     NULL }
+};
+
+const DMA_CALLBACKS   dma_channel3[] = {
+    { NULL,                     NULL }
+};
+
+const DMA_CALLBACKS   dma_channel4[] = {
+    { NULL,                     NULL }
+};
+
+const DMA_CALLBACKS   dma_channel5[] = {
+    { NULL,                     NULL }
+};
+
+const DMA_CALLBACKS   dma_channel6[] = {
+    { NULL,                     NULL }
+};
+
+const DMA_CALLBACKS   dma_channel7[] = {
+    { NULL,                     NULL }
+};
+
+/* Don't change anything below here. */
+
+/* An array of pointers to the channel ISR handlers. */
+const DMA_CALLBACKS   *dma_channels[8] = {
+    dma_channel0, dma_channel1, dma_channel2, dma_channel3,
+    dma_channel4, dma_channel5, dma_channel6, dma_channel7
+};
+
+/** DMA_IRQHandler
+ */
+extern "C" void DMA_IRQHandler(void) __irq {
+    for (int channel_number = 0; channel_number < 8; channel_number++) {
+        if (LPC_GPDMA->DMACIntStat & (1UL << channel_number)) {
+            if (LPC_GPDMA->DMACIntTCStat & (1UL << channel_number)) {
+                int irq_idx = 0;
+                while (dma_channels[channel_number][irq_idx].TcCallback != NULL) {
+                    if ((dma_channels[channel_number][irq_idx].TcCallback)(channel_number)) {
+                        LPC_GPDMA->DMACIntTCClear = (1UL << channel_number);
+                        break;
+                    }
+                    irq_idx++;
+                }
+            }
+            if (LPC_GPDMA->DMACIntErrStat & (1UL << channel_number)) {
+                int irq_idx = 0;
+                while (dma_channels[channel_number][irq_idx].ErrCallback != NULL) {
+                    if ((dma_channels[channel_number][irq_idx].ErrCallback)(channel_number)) {
+                        LPC_GPDMA->DMACIntErrClr = (1UL << channel_number);
+                        break;
+                    }
+                    irq_idx++;
+                }
+            }
+        }
+    }
+    
+    /* IRQ should be handled by now, check to make sure. */
+    if (LPC_GPDMA->DMACIntStat) {
+        LPC_GPDMA->DMACIntTCClear = (uint32_t)0xFF; /* If not, clear anyway! */
+    }
+    if (LPC_GPDMA->DMACIntErrStat) {
+        LPC_GPDMA->DMACIntErrClr = (uint32_t)0xFF; /* If not, clear anyway! */
+    }
+}
+
+
+/** DMA_init
+ */
+void DMA_init(void) {
+    DEBUG_INIT_START;
+    LPC_SC->PCONP |= (1UL << 29);
+    LPC_GPDMA->DMACConfig = 1;
+    NVIC_SetVector(DMA_IRQn, (uint32_t)DMA_IRQHandler);
+    NVIC_EnableIRQ(DMA_IRQn);
+    DEBUG_INIT_END;
+}
+
+/** DMA_process
+ */
+void DMA_process(void) {
+    /* Nothing to do. */
+}
+
+/** dma_request_channel
+ *
+ * Used to request control of a DMA channel. Allows modules
+ * to share channels if needed.
+ *
+ * @param int channel The channel being requested.
+ * @return bool true if given control, false if another is already in control.
+ */
+bool DMA_request_channel(int channel) {
+    if (!(channel_in_use_flags & (1UL << channel))) {
+        channel_in_use_flags |= (1UL << channel);
+        return true;
+    }
+    return false;
+}
+
+/** dma_release_channel
+ *
+ * Used to release a previously requested channel.
+ *
+ * @param int channel The channel to release.
+ */
+void DMA_release_channel(int channel) {
+    channel_in_use_flags &= ~(1UL << channel);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dma/dma.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,47 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef DMA_H
+#define DMA_H
+
+#define DMA_CHANNEL_0   (1UL << 0)
+#define DMA_CHANNEL_1   (1UL << 1)
+#define DMA_CHANNEL_2   (1UL << 2)
+#define DMA_CHANNEL_3   (1UL << 3)
+#define DMA_CHANNEL_4   (1UL << 4)
+#define DMA_CHANNEL_5   (1UL << 5)
+#define DMA_CHANNEL_6   (1UL << 6)
+#define DMA_CHANNEL_7   (1UL << 7)
+
+typedef int (*DMA_callback)(int channel);
+
+typedef struct _dma_callbacks {
+    DMA_callback    TcCallback;
+    DMA_callback    ErrCallback; 
+} DMA_CALLBACKS;
+
+void DMA_init(void);
+void DMA_process(void);
+bool DMA_request_channel(int channel);
+void DMA_release_channel(int channel);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/25AA02EE48.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,88 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "user.h"
+#include "flash.h"
+#include "ssp0.h"
+#include "gpio.h"
+
+char mac_addr[6];
+
+/** _25AA02E48_mac_addr
+ *
+ * Get a copy of the MAC address with a null terminator.
+ *
+ * @param char *s a buffer, 7 bytes long, to hold the MAC+null
+ */
+void _25AA02E48_mac_addr(char *s) {
+    memcpy(s, mac_addr, 6);
+    s[6] = '\0';
+}
+
+/** _25AA02E48_mac_addr_printable
+ *
+ * Create a string that represents the MAC addr as a
+ * printable ASCII string. The caller is responsible 
+ * for allocating enough space in the buffer pointed
+ * to by s to hold the string.
+ *
+ * @param char *s a buffer, 18 bytes long, to hold the MAC
+ * @param char divider A character to divide the bytes or 0
+ */
+void _25AA02E48_mac_addr_printable(char *s, char divider) {
+    if (divider != 0) {
+        sprintf(s, "%02X%c%02X%c%02X%c%02X%c%02X%c%02X", 
+            mac_addr[0], divider, mac_addr[1], divider, mac_addr[2], divider, 
+            mac_addr[3], divider, mac_addr[4], divider, mac_addr[5]);
+    }
+    else {
+        sprintf(s, "%02X%02X%02X%02X%02X%02X", 
+            mac_addr[0], mac_addr[1], mac_addr[2], 
+            mac_addr[3], mac_addr[4], mac_addr[5]);    
+    }
+}
+
+/** _25AA02E48_init
+ */
+void _25AA02E48_init(void) {
+
+    /* Assumes SSP0 is already _init() */
+    
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    LPC_SSP0->CPSR = _25AA02E48_SSP_INIT_CPSR;    
+    AA02E48_CS_ASSERT;
+    FLASH_SHORT_COMMAND(FLASH_READ);
+    SSP0_WRITE_BYTE(0xFA);
+    SSP0_FLUSH_RX_FIFO;
+    
+    for (int i = 0; i < 6; i++) {
+        SSP0_WRITE_BYTE(0x00);
+        while(SSP0_IS_BUSY || (LPC_SSP0->SR & (1UL << 2)) == 0);
+        mac_addr[i] = (char)LPC_SSP0->DR;        
+    }
+    
+    AA02E48_CS_DEASSERT;
+    LPC_SSP0->CPSR = FLASH_SSP_INIT_CPSR;
+    SSP0_release();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/FatFS/diskio.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,664 @@
+/*-----------------------------------------------------------------------*/
+/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2007        */
+/*-----------------------------------------------------------------------*/
+/* This is a stub disk I/O module that acts as front end of the existing */
+/* disk I/O modules and attach it to FatFs module with common interface. */
+/*-----------------------------------------------------------------------*/
+
+#include "diskio.h"
+#include "sowb.h"
+#include "user.h"
+#include "gpio.h"
+#include "gps.h"
+#include "ssp0.h"
+
+#define R1_IDLE_STATE           (1 << 0)
+#define R1_ERASE_RESET          (1 << 1)
+#define R1_ILLEGAL_COMMAND      (1 << 2)
+#define R1_COM_CRC_ERROR        (1 << 3)
+#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
+#define R1_ADDRESS_ERROR        (1 << 5)
+#define R1_PARAMETER_ERROR      (1 << 6)
+
+//******************************************************************************************************************
+// MBED SPI/CS Select functions.... Modify for your layout.
+//**************************************************************************************
+
+//SPI _spi(p5, p6, p7); // mosi, miso, sclk
+//DigitalOut _cs(p8);
+//DigitalOut P20(p20);
+//SPI * _spi;
+
+
+//******************************************************************************************************************
+// Low Level Sector Access Function Prototypes('C' Castrated versions of Simon Ford's C++ MBED SDFileSystem class
+//******************************************************************************************************************
+int _cmd(int cmd, int arg);
+int _cmd8(void);
+int _cmdR2(int cmd, int arg);
+int _read(BYTE *buffer, int length);
+int _write(BYTE *buffer, int length);
+int ext_bits(BYTE *data, int msb, int lsb);
+int _sd_sectors();
+int _sectors;
+
+#define SD_COMMAND_TIMEOUT 5000
+
+void deassert_cs(void) {
+    SDCARD_CS_DEASSERT; //_cs = 1;
+}
+
+//******************************************************************************************************************
+// Sector Access functions for CHAN FatFs 
+//******************************************************************************************************************
+
+DRESULT disk_ioctl (
+    BYTE drv,        /* Physical drive nmuber (0..) */
+    BYTE ctrl,        /* Control code */
+    void *buff        /* Buffer to send/receive control data */
+)
+{
+    DRESULT res;
+
+    switch(ctrl)
+    {
+        case CTRL_SYNC:
+             res = RES_OK;
+        break;
+    
+        case GET_SECTOR_SIZE:
+              res = RES_OK;
+            *(WORD *)buff = 512;
+        break;
+        
+        case GET_SECTOR_COUNT:
+            res = RES_OK;
+           *(DWORD *)buff = (WORD)_sd_sectors();
+        break;
+        
+        case GET_BLOCK_SIZE:
+         res = RES_OK;
+          *(DWORD *)buff = 1;
+        break;
+        
+        default:
+        res = RES_OK;
+        break;
+    }
+    return res;
+}
+
+int _cmd58() {
+    SDCARD_CS_ASSERT; //_cs = 0; 
+    int arg = 0;
+    
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    // send a command
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0x40 | 58);
+    SSP0_WRITE_BYTE(arg >> 24);
+    SSP0_WRITE_BYTE(arg >> 16);
+    SSP0_WRITE_BYTE(arg >> 8);
+    SSP0_WRITE_BYTE(arg >> 0);
+    SSP0_WRITE_BYTE(0x95);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    
+    //_spi->write(0x40 | 58);
+    //_spi->write(arg >> 24);
+    //_spi->write(arg >> 16);
+    //_spi->write(arg >> 8);
+    //_spi->write(arg >> 0);
+    //_spi->write(0x95);
+
+    // wait for the repsonse (response[7] == 0)
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    for(int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+        int response = LPC_SSP0->DR;
+        if(!(response & 0x80)) {
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+            int ocr = LPC_SSP0->DR << 24;
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+            ocr |= LPC_SSP0->DR  << 16;
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+            ocr |= LPC_SSP0->DR  << 8;
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+            ocr |= LPC_SSP0->DR << 0;
+//            printf("OCR = 0x%08X\n", ocr);
+            SDCARD_CS_DEASSERT; //_cs = 1;
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+            SSP0_FLUSH_RX_FIFO;
+            // _spi->write(0xFF);
+            SSP0_release();
+            return response;
+        }
+        SSP0_WRITE_BYTE(0xFF);
+        while(SSP0_IS_BUSY);
+    }
+    SDCARD_CS_DEASSERT;
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    SSP0_release();
+    return -1; // timeout
+}
+
+int initialise_card_v1() {
+    
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+        _cmd(55, 0); 
+        if(_cmd(41, 0) == 0) { 
+            SSP0_release();
+            return 0; //SDCARD_V1;
+        }
+    }
+
+    //fprintf(stderr, "Timeout waiting for v1.x card\n");
+    SSP0_release();
+    return STA_NOINIT;
+}
+
+int initialise_card_v2() {
+    int c41, c58, r;
+    
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+        _cmd(55, 0);
+        c41 = _cmd(41, 0);
+        if(c41 == 0) { 
+            SSP0_release();
+            c58 = _cmd58();
+            //fprintf(stderr, "C41 returned %02x and C58 returned %02x\r\n", c41, c58);
+            return 0; //SDCARD_V2;
+        }        
+    }
+    
+    
+    //fprintf(stderr, "Timeout waiting for v2.x card response=0x%04x\r\n", c41);
+    SSP0_release();
+    return STA_NOINIT;
+}
+
+DSTATUS disk_initialize(BYTE Drive) {
+    int i, cmd8_r;
+    uint32_t cpsr = LPC_SSP0->CPSR;
+    
+    //_spi = new SPI(p5, p6, p7);
+    
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    //_spi->frequency(100000); // Set to 100kHz for initialisation
+    LPC_SSP0->CPSR = 0x64;
+    SDCARD_CS_ASSERT; //_cs = 1;
+    
+    // Initialise the card by clocking it a bit (cs = 1)
+    for(int i=0; i < 16; i++) {   
+        SSP0_WRITE_BYTE(0xFF);
+    }
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    
+
+    
+    // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
+    if(_cmd(0, 0) != 0x01) { 
+        //fprintf(stderr, "Not in idle state\n");
+        SSP0_release();
+        return STA_NOINIT;
+    }
+    
+    for(i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+        cmd8_r = _cmd8();
+        if (cmd8_r == 0 || cmd8_r == 1 || cmd8_r == R1_ILLEGAL_COMMAND) break;
+        if (cmd8_r == 0 || cmd8_r == R1_ILLEGAL_COMMAND) break;
+    }
+    
+    if ( (cmd8_r & R1_ILLEGAL_COMMAND) != 0) {
+        //fprintf(stderr, "V1 %d\r\n", cmd8_r);
+        SSP0_release();
+        return initialise_card_v1();
+    }
+    
+    if (cmd8_r == 0 || cmd8_r == 1) {
+        //fprintf(stderr, "V2 %d\r\n", cmd8_r);
+        SSP0_release();
+        return initialise_card_v2();
+    }
+    
+    
+    //fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?) response = %d\r\n", cmd8_r);
+    SSP0_release();
+    return STA_NOINIT;
+    
+    // ACMD41 to give host capacity support (repeat until not busy)
+    // ACMD41 is application specific command, so we send APP_CMD (CMD55) beforehand
+    for(int i=0;; i++) {
+        _cmd(55, 0); 
+        int response = _cmd(41, 0);
+        if(response == 0) { 
+            break;
+        } else if(i > SD_COMMAND_TIMEOUT) {
+            //fprintf(stderr, "Timeout waiting for card\n");
+            SSP0_release();
+            return STA_NOINIT;
+        }    
+    }
+
+    _sectors = _sd_sectors();
+
+    // Set block length to 512 (CMD16)
+    if(_cmd(16, 512) != 0) {
+        //fprintf(stderr, "Set block timeout\n");
+        SSP0_release();
+        return STA_NOINIT;
+    }
+    
+    LPC_SSP0->CPSR = cpsr;    
+    SSP0_release();
+    //_spi->frequency(10000000); // Set to 10MHz for data transfer
+    return 0;
+}
+
+DRESULT disk_write(BYTE Drive,const BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount)
+{
+    BYTE i;
+    
+    BYTE * MyBufOut = (BYTE *)Buffer;
+    
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    for(i=0;i<SectorCount;i++)
+    {
+        // set write address for single block (CMD24)
+        if(_cmd(24, (SectorNumber + i) * 512 ) != 0) {
+            SSP0_release();
+            return RES_ERROR;
+        }
+
+        // send the data block
+        _write(MyBufOut, 512);    
+        
+        MyBufOut+=512;
+    }
+    
+    SSP0_release();
+    return RES_OK;    
+}
+
+DRESULT disk_read(BYTE Drive, BYTE * Buffer,DWORD SectorNumber, BYTE SectorCount)
+{        
+    BYTE i;
+    
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    for(i=0;i<SectorCount;i++)
+    {
+        // set read address for single block (CMD17)
+        if(_cmd(17, (SectorNumber+i) * 512) != 0)
+        {
+            SSP0_release();
+            return RES_ERROR;
+        }
+        // receive the data
+        _read(Buffer, 512);
+       
+        Buffer+=512;
+    }
+    
+    SSP0_release(); 
+    return RES_OK;
+}
+
+
+extern "C" DWORD get_fattime(void) {
+    GPS_TIME the_time;
+    
+    gps_get_time(&the_time);
+    
+    uint32_t year   = (the_time.year - 1980) << 25;
+    uint32_t month  = the_time.month << 21;
+    uint32_t day    = the_time.day << 16;
+    uint32_t hour   = the_time.hour << 11;
+    uint32_t minute = the_time.minute << 5;
+    uint32_t second = (the_time.second / 2) &0xF;
+    return (DWORD)(year | month | day | hour | minute | second);
+}
+
+DSTATUS disk_status(BYTE Drive)
+{
+    return 0;
+}
+
+//**************************************************************************************
+// Low Level Sector Access Functions (Castrated versions of Simon Fords C++ MBED class
+//**************************************************************************************
+
+int _cmd(int cmd, int arg) {
+    volatile int delay;
+    
+    for (delay = 500; delay; delay--);
+    SDCARD_CS_ASSERT; //_cs = 0; 
+    for (delay = 500; delay; delay--);
+    
+    // send a command
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0x40 | cmd);
+    SSP0_WRITE_BYTE(arg >> 24);
+    SSP0_WRITE_BYTE(arg >> 16);
+    SSP0_WRITE_BYTE(arg >> 8);
+    SSP0_WRITE_BYTE(arg >> 0);
+    SSP0_WRITE_BYTE(0x95);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    
+    //_spi->write(0x40 | cmd);
+    //_spi->write(arg >> 24);
+    //_spi->write(arg >> 16);
+    //_spi->write(arg >> 8);
+    //_spi->write(arg >> 0);
+    //_spi->write(0x95);
+
+    // wait for the repsonse (response[7] == 0)
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+        int response = LPC_SSP0->DR;
+        if(!(response & 0x80)) {
+            SDCARD_CS_DEASSERT; //_cs = 1;
+            return response;
+        }
+        SSP0_WRITE_BYTE(0xFF);
+        while(SSP0_IS_BUSY);
+    }
+    
+    SDCARD_CS_ASSERT; //_cs = 1;
+    return -1; // timeout
+}
+
+int _cmdR2(int cmd, int arg) {
+    int response;
+    
+    SDCARD_CS_ASSERT; //_cs = 0; 
+    
+    // send a command
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0x40 | cmd);
+    SSP0_WRITE_BYTE(arg >> 24);
+    SSP0_WRITE_BYTE(arg >> 16);
+    SSP0_WRITE_BYTE(arg >> 8);
+    SSP0_WRITE_BYTE(arg >> 0);
+    SSP0_WRITE_BYTE(0x95);
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    
+    //_spi->write(0x40 | cmd);
+    //_spi->write(arg >> 24);
+    //_spi->write(arg >> 16);
+    //_spi->write(arg >> 8);
+    //_spi->write(arg >> 0);
+    //_spi->write(0x95);    
+    //_spi->write(0xFF);
+    
+    // wait for the repsonse (response[7] == 0)
+    //for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+        response = 0;
+        SSP0_WRITE_BYTE(0x00);
+        while(SSP0_IS_BUSY);
+        response = (LPC_SSP0->DR & 0xFF);
+        response = (response << 8) & 0xFF00;
+        SSP0_WRITE_BYTE(0x00);
+        while(SSP0_IS_BUSY);
+        response |= (LPC_SSP0->DR & 0xFF);
+        SDCARD_CS_DEASSERT; //_cs = 1;
+        return response;
+    //}
+    SDCARD_CS_DEASSERT; //_cs = 1;
+    return -1; // timeout
+}
+
+int _cmd8(void) {
+    SDCARD_CS_ASSERT; //_cs = 0; 
+    
+    // send a command
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0x40 | 8);
+    SSP0_WRITE_BYTE(00);
+    SSP0_WRITE_BYTE(00);
+    SSP0_WRITE_BYTE(01);
+    SSP0_WRITE_BYTE(0xAA);
+    SSP0_WRITE_BYTE(0x87);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    
+    //_spi->write(0x40 | 8); // CMD8
+    //_spi->write(0x00);     // reserved
+    //_spi->write(0x00);     // reserved
+    //_spi->write(0x01);     // 3.3v
+    //_spi->write(0xAA);     // check pattern
+    //_spi->write(0x87);     // crc
+
+    // wait for the repsonse (response[7] == 0)
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
+        char response[5];
+        response[0] = LPC_SSP0->DR;
+        SSP0_WRITE_BYTE(0xFF);
+        while(SSP0_IS_BUSY);
+        for(int j=1; j<5; j++) {
+            response[i] = LPC_SSP0->DR;
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+        }
+        SDCARD_CS_DEASSERT; //_cs = 1;
+        SSP0_WRITE_BYTE(0xFF);
+        while(SSP0_IS_BUSY);
+        SSP0_FLUSH_RX_FIFO;
+        return response[0];
+    }
+    
+    SDCARD_CS_DEASSERT; //_cs = 1;
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    //_spi->write(0xFF);
+    return -1; // timeout
+}
+
+int _cmd8original(void) {
+    SDCARD_CS_ASSERT; //_cs = 0; 
+    
+    // send a command
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0x40 | 8);
+    SSP0_WRITE_BYTE(00);
+    SSP0_WRITE_BYTE(00);
+    SSP0_WRITE_BYTE(01);
+    SSP0_WRITE_BYTE(0xAA);
+    SSP0_WRITE_BYTE(0x87);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    
+    //_spi->write(0x40 | 8); // CMD8
+    //_spi->write(0x00);     // reserved
+    //_spi->write(0x00);     // reserved
+    //_spi->write(0x01);     // 3.3v
+    //_spi->write(0xAA);     // check pattern
+    //_spi->write(0x87);     // crc
+
+    // wait for the repsonse (response[7] == 0)
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
+        char response[5];
+        response[0] = LPC_SSP0->DR;
+        if(!(response[0] & 0x80)) {
+            //fprintf(stderr, "RS = %d\r\n", response[0]);
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+            for(int j=1; j<5; j++) {
+                response[i] = LPC_SSP0->DR;
+                SSP0_WRITE_BYTE(0xFF);
+                while(SSP0_IS_BUSY);
+            }
+            SDCARD_CS_DEASSERT; //_cs = 1;
+            SSP0_WRITE_BYTE(0xFF);
+            while(SSP0_IS_BUSY);
+            //_spi->write(0xFF);
+            return response[0];
+        }
+    }
+    
+    SDCARD_CS_DEASSERT; //_cs = 1;
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    //_spi->write(0xFF);
+    return -1; // timeout
+}
+
+int _read(BYTE *buffer, int length) {
+    SDCARD_CS_ASSERT; //_cs = 0;
+
+    // read until start byte (0xFF)
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    while(LPC_SSP0->DR != 0xFE) {
+        SSP0_WRITE_BYTE(0xFF);
+        while(SSP0_IS_BUSY);
+    }
+
+    // read data
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    for(int i=0; i<length; i++) {
+        buffer[i] = LPC_SSP0->DR;
+        SSP0_WRITE_BYTE(0xFF);
+        while(SSP0_IS_BUSY);
+    }
+    SSP0_WRITE_BYTE(0xFF);
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    SSP0_FLUSH_RX_FIFO;
+    //_spi->write(0xFF); // checksum
+    //_spi->write(0xFF);
+
+    SDCARD_CS_DEASSERT; //_cs = 1;    
+    return 0;
+}
+
+int _write(BYTE *buffer, int length) {
+    SDCARD_CS_ASSERT; //_cs = 0;
+    
+    // indicate start of block
+    SSP0_WRITE_BYTE(0xFE);
+    while(SSP0_IS_BUSY);
+    //_spi->write(0xFE);
+    
+    // write the data
+    for(int i=0; i<length; i++) {
+        SSP0_WRITE_BYTE(buffer[i]);
+        while(SSP0_IS_BUSY);
+        //_spi->write(buffer[i]);
+    }
+    
+    // write the checksum
+    SSP0_WRITE_BYTE(0xFF);
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    //_spi->write(0xFF); 
+    //_spi->write(0xFF);
+
+    // check the repsonse token
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    if((LPC_SSP0->DR & 0x1F) != 0x05) {
+        SDCARD_CS_DEASSERT; //_cs = 1; 
+        return 1;
+    }
+
+    // wait for write to finish
+    SSP0_FLUSH_RX_FIFO;
+    SSP0_WRITE_BYTE(0xFF);
+    while(SSP0_IS_BUSY);
+    while(LPC_SSP0->DR == 0) {
+        SSP0_WRITE_BYTE(0xFF);
+        while(SSP0_IS_BUSY);
+    }
+
+    SDCARD_CS_DEASSERT; //_cs = 1; 
+    return 0;
+}
+
+int ext_bits(BYTE *data, int msb, int lsb) {
+    int bits = 0;
+    int size = 1 + msb - lsb; 
+    for(int i=0; i<size; i++) {
+        int position = lsb + i;
+        int byte = 15 - (position >> 3);
+        int bit = position & 0x7;
+        int value = (data[byte] >> bit) & 1;
+        bits |= value << i;
+    }
+    return bits;
+}
+
+int _sd_sectors() {
+
+    // CMD9, Response R2 (R1 byte + 16-byte block read)
+    if(_cmd(9, 0) != 0) {
+        //fprintf(stderr, "Didn't get a response from the disk\n");
+        return 0;
+    }
+    
+    BYTE csd[16];    
+    if(_read(csd, 16) != 0) {
+        //fprintf(stderr, "Couldn't read csd response from disk\n");
+        return 0;
+    }
+
+    // csd_structure : csd[127:126]
+    // c_size        : csd[73:62]
+    // c_size_mult   : csd[49:47]
+    // read_bl_len   : csd[83:80] 
+
+    int csd_structure = ext_bits(csd, 127, 126);
+    int c_size = ext_bits(csd, 73, 62);
+    int c_size_mult = ext_bits(csd, 49, 47);
+    int read_bl_len = ext_bits(csd, 83, 80);
+    
+    if(csd_structure != 0) {
+        //fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures");
+        return 0;
+    }
+                            
+    int blocks = (c_size + 1) * (1 << (c_size_mult + 2));
+    int block_size = 1 << read_bl_len;
+
+    if(block_size != 512) {
+        //fprintf(stderr, "This disk tastes funny! I only like 512 byte blocks (%d)\r\n",block_size);
+        return 0;
+    }
+    
+    return blocks;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/FatFS/diskio.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,85 @@
+/*-----------------------------------------------------------------------
+/  Low level disk interface modlue include file   (C)ChaN, 2010
+/-----------------------------------------------------------------------*/
+
+#ifndef _DISKIO
+#define _DISKIO
+
+#define _READONLY     0    /* 1: Remove write functions */
+#define _USE_IOCTL    1    /* 1: Use disk_ioctl fucntion */
+
+#include "integer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Status of Disk Functions */
+typedef BYTE    DSTATUS;
+
+/* Results of Disk Functions */
+typedef enum {
+    RES_OK = 0,        /* 0: Successful */
+    RES_ERROR,        /* 1: R/W Error */
+    RES_WRPRT,        /* 2: Write Protected */
+    RES_NOTRDY,        /* 3: Not Ready */
+    RES_PARERR        /* 4: Invalid Parameter */
+} DRESULT;
+
+
+/*---------------------------------------*/
+/* Prototypes for disk control functions */
+
+int assign_drives (int, int);
+DSTATUS disk_initialize (BYTE);
+DSTATUS disk_status (BYTE);
+DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
+DWORD get_fattime(void);
+#if    _READONLY == 0
+DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
+#endif
+DRESULT disk_ioctl (BYTE, BYTE, void*);
+
+
+
+/* Disk Status Bits (DSTATUS) */
+
+#define STA_NOINIT        0x01    /* Drive not initialized */
+#define STA_NODISK        0x02    /* No medium in the drive */
+#define STA_PROTECT        0x04    /* Write protected */
+
+
+/* Command code for disk_ioctrl fucntion */
+
+/* Generic command (defined for FatFs) */
+#define CTRL_SYNC            0    /* Flush disk cache (for write functions) */
+#define GET_SECTOR_COUNT    1    /* Get media size (for only f_mkfs()) */
+#define GET_SECTOR_SIZE        2    /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
+#define GET_BLOCK_SIZE        3    /* Get erase block size (for only f_mkfs()) */
+#define CTRL_ERASE_SECTOR    4    /* Force erased a block of sectors (for only _USE_ERASE) */
+
+/* Generic command */
+#define CTRL_POWER            5    /* Get/Set power status */
+#define CTRL_LOCK            6    /* Lock/Unlock media removal */
+#define CTRL_EJECT            7    /* Eject media */
+
+/* MMC/SDC specific ioctl command */
+#define MMC_GET_TYPE        10    /* Get card type */
+#define MMC_GET_CSD            11    /* Get CSD */
+#define MMC_GET_CID            12    /* Get CID */
+#define MMC_GET_OCR            13    /* Get OCR */
+#define MMC_GET_SDSTAT        14    /* Get SD status */
+
+/* ATA/CF specific ioctl command */
+#define ATA_GET_REV            20    /* Get F/W revision */
+#define ATA_GET_MODEL        21    /* Get model name */
+#define ATA_GET_SN            22    /* Get serial number */
+
+/* NAND specific ioctl command */
+#define NAND_FORMAT            30    /* Create physical format */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/FatFS/ff.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,3735 @@
+/*----------------------------------------------------------------------------/
+/  FatFs - FAT file system module  R0.08a                 (C)ChaN, 2010
+/-----------------------------------------------------------------------------/
+/ FatFs module is a generic FAT file system module for small embedded systems.
+/ This is a free software that opened for education, research and commercial
+/ developments under license policy of following terms.
+/
+/  Copyright (C) 2010, ChaN, all right reserved.
+/
+/ * The FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/-----------------------------------------------------------------------------/
+/ Feb 26,'06 R0.00  Prototype.
+/
+/ Apr 29,'06 R0.01  First stable version.
+/
+/ Jun 01,'06 R0.02  Added FAT12 support.
+/                   Removed unbuffered mode.
+/                   Fixed a problem on small (<32M) partition.
+/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM).
+/
+/ Sep 22,'06 R0.03  Added f_rename().
+/                   Changed option _FS_MINIMUM to _FS_MINIMIZE.
+/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast.
+/                   Fixed f_mkdir() creates incorrect directory on FAT32.
+/
+/ Feb 04,'07 R0.04  Supported multiple drive system.
+/                   Changed some interfaces for multiple drive system.
+/                   Changed f_mountdrv() to f_mount().
+/                   Added f_mkfs().
+/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive.
+/                   Added a capability of extending file size to f_lseek().
+/                   Added minimization level 3.
+/                   Fixed an endian sensitive code in f_mkfs().
+/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.
+/                   Added FSInfo support.
+/                   Fixed DBCS name can result FR_INVALID_NAME.
+/                   Fixed short seek (<= csize) collapses the file object.
+/
+/ Aug 25,'07 R0.05  Changed arguments of f_read(), f_write() and f_mkfs().
+/                   Fixed f_mkfs() on FAT32 creates incorrect FSInfo.
+/                   Fixed f_mkdir() on FAT32 creates incorrect directory.
+/ Feb 03,'08 R0.05a Added f_truncate() and f_utime().
+/                   Fixed off by one error at FAT sub-type determination.
+/                   Fixed btr in f_read() can be mistruncated.
+/                   Fixed cached sector is not flushed when create and close without write.
+/
+/ Apr 01,'08 R0.06  Added fputc(), fputs(), fprintf() and fgets().
+/                   Improved performance of f_lseek() on moving to the same or following cluster.
+/
+/ Apr 01,'09 R0.07  Merged Tiny-FatFs as a buffer configuration option. (_FS_TINY)
+/                   Added long file name support.
+/                   Added multiple code page support.
+/                   Added re-entrancy for multitask operation.
+/                   Added auto cluster size selection to f_mkfs().
+/                   Added rewind option to f_readdir().
+/                   Changed result code of critical errors.
+/                   Renamed string functions to avoid name collision.
+/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg.
+/                   Added multiple sector size support.
+/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error.
+/                   Fixed wrong cache control in f_lseek().
+/                   Added relative path feature.
+/                   Added f_chdir() and f_chdrive().
+/                   Added proper case conversion to extended char.
+/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h.
+/                   Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
+/                   Fixed name matching error on the 13 char boundary.
+/                   Added a configuration option, _LFN_UNICODE.
+/                   Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
+/
+/ May 15,'10 R0.08  Added a memory configuration option. (_USE_LFN = 3)
+/                   Added file lock feature. (_FS_SHARE)
+/                   Added fast seek feature. (_USE_FASTSEEK)
+/                   Changed some types on the API, XCHAR->TCHAR.
+/                   Changed fname member in the FILINFO structure on Unicode cfg.
+/                   String functions support UTF-8 encoding files on Unicode cfg.
+/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
+/                   Added sector erase feature. (_USE_ERASE)
+/                   Moved file lock semaphore table from fs object to the bss.
+/                   Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
+/                   Fixed f_mkfs() creates wrong FAT32 volume.
+/---------------------------------------------------------------------------*/
+
+#include "ff.h"            /* FatFs configurations and declarations */
+#include "diskio.h"        /* Declarations of low level disk I/O functions */
+
+
+/*--------------------------------------------------------------------------
+
+   Module Private Definitions
+
+---------------------------------------------------------------------------*/
+
+#if _FATFS != 8255
+#error Wrong include file (ff.h).
+#endif
+
+/* Definitions on sector size */
+#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096
+#error Wrong sector size.
+#endif
+#if _MAX_SS != 512
+#define    SS(fs)    ((fs)->ssize)    /* Multiple sector size */
+#else
+#define    SS(fs)    512U            /* Fixed sector size */
+#endif
+
+
+/* Reentrancy related */
+#if _FS_REENTRANT
+#if _USE_LFN == 1
+#error Static LFN work area must not be used in re-entrant configuration.
+#endif
+#define    ENTER_FF(fs)        { if (!lock_fs(fs)) return FR_TIMEOUT; }
+#define    LEAVE_FF(fs, res)    { unlock_fs(fs, res); return res; }
+#else
+#define    ENTER_FF(fs)
+#define LEAVE_FF(fs, res)    return res
+#endif
+
+#define    ABORT(fs, res)        { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
+
+
+/* File shareing feature */
+#if _FS_SHARE
+#if _FS_READONLY
+#error _FS_SHARE must be 0 on read-only cfg.
+#endif
+typedef struct {
+    FATFS *fs;                /* File ID 1, volume (NULL:blank entry) */
+    DWORD clu;                /* File ID 2, directory */
+    WORD idx;                /* File ID 3, directory index */
+    WORD ctr;                /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */
+} FILESEM;
+#endif
+
+
+/* Misc definitions */
+#define LD_CLUST(dir)    (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
+#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
+
+
+/* Character code support macros */
+#define IsUpper(c)    (((c)>='A')&&((c)<='Z'))
+#define IsLower(c)    (((c)>='a')&&((c)<='z'))
+#define IsDigit(c)    (((c)>='0')&&((c)<='9'))
+
+#if _DF1S        /* Code page is DBCS */
+
+#ifdef _DF2S    /* Two 1st byte areas */
+#define IsDBCS1(c)    (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
+#else            /* One 1st byte area */
+#define IsDBCS1(c)    ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
+#endif
+
+#ifdef _DS3S    /* Three 2nd byte areas */
+#define IsDBCS2(c)    (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
+#else            /* Two 2nd byte areas */
+#define IsDBCS2(c)    (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
+#endif
+
+#else            /* Code page is SBCS */
+
+#define IsDBCS1(c)    0
+#define IsDBCS2(c)    0
+
+#endif /* _DF1S */
+
+
+/* Name status flags */
+#define NS            11        /* Offset of name status byte */
+#define NS_LOSS        0x01    /* Out of 8.3 format */
+#define NS_LFN        0x02    /* Force to create LFN entry */
+#define NS_LAST        0x04    /* Last segment */
+#define NS_BODY        0x08    /* Lower case flag (body) */
+#define NS_EXT        0x10    /* Lower case flag (ext) */
+#define NS_DOT        0x20    /* Dot entry */
+
+
+/* FAT sub-type boundaries */
+/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */
+#define MIN_FAT16    4086    /* Minimum number of clusters for FAT16 */
+#define    MIN_FAT32    65526    /* Minimum number of clusters for FAT32 */
+
+
+/* FatFs refers the members in the FAT structures as byte array instead of
+/ structure member because there are incompatibility of the packing option
+/ between compilers. */
+
+#define BS_jmpBoot            0
+#define BS_OEMName            3
+#define BPB_BytsPerSec        11
+#define BPB_SecPerClus        13
+#define BPB_RsvdSecCnt        14
+#define BPB_NumFATs            16
+#define BPB_RootEntCnt        17
+#define BPB_TotSec16        19
+#define BPB_Media            21
+#define BPB_FATSz16            22
+#define BPB_SecPerTrk        24
+#define BPB_NumHeads        26
+#define BPB_HiddSec            28
+#define BPB_TotSec32        32
+#define BS_DrvNum            36
+#define BS_BootSig            38
+#define BS_VolID            39
+#define BS_VolLab            43
+#define BS_FilSysType        54
+#define BPB_FATSz32            36
+#define BPB_ExtFlags        40
+#define BPB_FSVer            42
+#define BPB_RootClus        44
+#define BPB_FSInfo            48
+#define BPB_BkBootSec        50
+#define BS_DrvNum32            64
+#define BS_BootSig32        66
+#define BS_VolID32            67
+#define BS_VolLab32            71
+#define BS_FilSysType32        82
+#define    FSI_LeadSig            0
+#define    FSI_StrucSig        484
+#define    FSI_Free_Count        488
+#define    FSI_Nxt_Free        492
+#define MBR_Table            446
+#define BS_55AA                510
+
+#define    DIR_Name            0
+#define    DIR_Attr            11
+#define    DIR_NTres            12
+#define    DIR_CrtTime            14
+#define    DIR_CrtDate            16
+#define    DIR_FstClusHI        20
+#define    DIR_WrtTime            22
+#define    DIR_WrtDate            24
+#define    DIR_FstClusLO        26
+#define    DIR_FileSize        28
+#define    LDIR_Ord            0
+#define    LDIR_Attr            11
+#define    LDIR_Type            12
+#define    LDIR_Chksum            13
+#define    LDIR_FstClusLO        26
+
+
+
+/*------------------------------------------------------------*/
+/* Work area                                                  */
+
+#if _VOLUMES
+static
+FATFS *FatFs[_VOLUMES];    /* Pointer to the file system objects (logical drives) */
+#else
+#error Number of drives must not be 0.
+#endif
+
+static
+WORD Fsid;                /* File system mount ID */
+
+#if _FS_RPATH
+static
+BYTE CurrVol;            /* Current drive */
+#endif
+
+#if _FS_SHARE
+static
+FILESEM    Files[_FS_SHARE];    /* File lock semaphores */
+#endif
+
+#if _USE_LFN == 0            /* No LFN */
+#define    DEF_NAMEBUF            BYTE sfn[12]
+#define INIT_BUF(dobj)        (dobj).fn = sfn
+#define    FREE_BUF()
+
+#elif _USE_LFN == 1            /* LFN with static LFN working buffer */
+static WCHAR LfnBuf[_MAX_LFN+1];
+#define    DEF_NAMEBUF            BYTE sfn[12]
+#define INIT_BUF(dobj)        { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
+#define    FREE_BUF()
+
+#elif _USE_LFN == 2         /* LFN with dynamic LFN working buffer on the stack */
+#define    DEF_NAMEBUF            BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
+#define INIT_BUF(dobj)        { (dobj).fn = sfn; (dobj).lfn = lbuf; }
+#define    FREE_BUF()
+
+#elif _USE_LFN == 3         /* LFN with dynamic LFN working buffer on the heap */
+#define    DEF_NAMEBUF            BYTE sfn[12]; WCHAR *lfn
+#define INIT_BUF(dobj)        { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
+                              if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
+                              (dobj).lfn = lfn;    (dobj).fn = sfn; }
+#define    FREE_BUF()            ff_memfree(lfn)
+
+#else
+#error Wrong LFN configuration.
+#endif
+
+
+
+
+/*--------------------------------------------------------------------------
+
+   Module Private Functions
+
+---------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* String functions                                                      */
+/*-----------------------------------------------------------------------*/
+
+/* Copy memory to memory */
+static
+void mem_cpy (void* dst, const void* src, UINT cnt) {
+    BYTE *d = (BYTE*)dst;
+    const BYTE *s = (const BYTE*)src;
+
+#if _WORD_ACCESS == 1
+    while (cnt >= sizeof(int)) {
+        *(int*)d = *(int*)s;
+        d += sizeof(int); s += sizeof(int);
+        cnt -= sizeof(int);
+    }
+#endif
+    while (cnt--)
+        *d++ = *s++;
+}
+
+/* Fill memory */
+static
+void mem_set (void* dst, int val, UINT cnt) {
+    BYTE *d = (BYTE*)dst;
+
+    while (cnt--)
+        *d++ = (BYTE)val;
+}
+
+/* Compare memory to memory */
+static
+int mem_cmp (const void* dst, const void* src, UINT cnt) {
+    const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
+    int r = 0;
+
+    while (cnt-- && (r = *d++ - *s++) == 0) ;
+    return r;
+}
+
+/* Check if chr is contained in the string */
+static
+int chk_chr (const char* str, int chr) {
+    while (*str && *str != chr) str++;
+    return *str;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Request/Release grant to access the volume                            */
+/*-----------------------------------------------------------------------*/
+#if _FS_REENTRANT
+
+static
+int lock_fs (
+    FATFS *fs        /* File system object */
+)
+{
+    return ff_req_grant(fs->sobj);
+}
+
+
+static
+void unlock_fs (
+    FATFS *fs,        /* File system object */
+    FRESULT res        /* Result code to be returned */
+)
+{
+    if (res != FR_NOT_ENABLED &&
+        res != FR_INVALID_DRIVE &&
+        res != FR_INVALID_OBJECT &&
+        res != FR_TIMEOUT) {
+        ff_rel_grant(fs->sobj);
+    }
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* File shareing control functions                                       */
+/*-----------------------------------------------------------------------*/
+#if _FS_SHARE
+
+static
+FRESULT chk_lock (    /* Check if the file can be accessed */
+    DIR* dj,        /* Directory object pointing the file to be checked */
+    int acc            /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
+)
+{
+    UINT i, be;
+
+    /* Search file semaphore table */
+    for (i = be = 0; i < _FS_SHARE; i++) {
+        if (Files[i].fs) {    /* Existing entry */
+            if (Files[i].fs == dj->fs &&         /* Check if the file matched with an open file */
+                Files[i].clu == dj->sclust &&
+                Files[i].idx == dj->index) break;
+        } else {            /* Blank entry */
+            be++;
+        }
+    }
+    if (i == _FS_SHARE)    /* The file is not opened */
+        return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES;    /* Is there a blank entry for new file? */
+
+    /* The file has been opened. Reject any open against writing file and all write mode open */
+    return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
+}
+
+
+static
+int enq_lock (    /* Check if an entry is available for a new file */
+    FATFS* fs    /* File system object */
+)
+{
+    UINT i;
+
+    for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
+    return (i == _FS_SHARE) ? 0 : 1;
+}
+
+
+static
+UINT inc_lock (    /* Increment file open counter and returns its index (0:int error) */
+    DIR* dj,    /* Directory object pointing the file to register or increment */
+    int acc        /* Desired access mode (0:Read, !0:Write) */
+)
+{
+    UINT i;
+
+
+    for (i = 0; i < _FS_SHARE; i++) {    /* Find the file */
+        if (Files[i].fs == dj->fs &&
+            Files[i].clu == dj->sclust &&
+            Files[i].idx == dj->index) break;
+    }
+
+    if (i == _FS_SHARE) {                /* Not opened. Register it as new. */
+        for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
+        if (i == _FS_SHARE) return 0;    /* No space to register (int err) */
+        Files[i].fs = dj->fs;
+        Files[i].clu = dj->sclust;
+        Files[i].idx = dj->index;
+        Files[i].ctr = 0;
+    }
+
+    if (acc && Files[i].ctr) return 0;    /* Access violation (int err) */
+
+    Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1;    /* Set semaphore value */
+
+    return i + 1;
+}
+
+
+static
+FRESULT dec_lock (    /* Decrement file open counter */
+    UINT i            /* Semaphore index */
+)
+{
+    WORD n;
+    FRESULT res;
+
+
+    if (--i < _FS_SHARE) {
+        n = Files[i].ctr;
+        if (n == 0x100) n = 0;
+        if (n) n--;
+        Files[i].ctr = n;
+        if (!n) Files[i].fs = 0;
+        res = FR_OK;
+    } else {
+        res = FR_INT_ERR;
+    }
+    return res;
+}
+
+
+static
+void clear_lock (    /* Clear lock entries of the volume */
+    FATFS *fs
+)
+{
+    UINT i;
+
+    for (i = 0; i < _FS_SHARE; i++) {
+        if (Files[i].fs == fs) Files[i].fs = 0;
+    }
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change window offset                                                  */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT move_window (
+    FATFS *fs,        /* File system object */
+    DWORD sector    /* Sector number to make appearance in the fs->win[] */
+)                    /* Move to zero only writes back dirty window */
+{
+    DWORD wsect;
+
+
+    wsect = fs->winsect;
+    if (wsect != sector) {    /* Changed current window */
+#if !_FS_READONLY
+        if (fs->wflag) {    /* Write back dirty window if needed */
+            if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK)
+                return FR_DISK_ERR;
+            fs->wflag = 0;
+            if (wsect < (fs->fatbase + fs->fsize)) {    /* In FAT area */
+                BYTE nf;
+                for (nf = fs->n_fats; nf > 1; nf--) {    /* Reflect the change to all FAT copies */
+                    wsect += fs->fsize;
+                    disk_write(fs->drv, fs->win, wsect, 1);
+                }
+            }
+        }
+#endif
+        if (sector) {
+            if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK)
+                return FR_DISK_ERR;
+            fs->winsect = sector;
+        }
+    }
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Clean-up cached data                                                  */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+FRESULT sync (    /* FR_OK: successful, FR_DISK_ERR: failed */
+    FATFS *fs    /* File system object */
+)
+{
+    FRESULT res;
+
+
+    res = move_window(fs, 0);
+    if (res == FR_OK) {
+        /* Update FSInfo sector if needed */
+        if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {
+            fs->winsect = 0;
+            mem_set(fs->win, 0, 512);
+            ST_WORD(fs->win+BS_55AA, 0xAA55);
+            ST_DWORD(fs->win+FSI_LeadSig, 0x41615252);
+            ST_DWORD(fs->win+FSI_StrucSig, 0x61417272);
+            ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust);
+            ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust);
+            disk_write(fs->drv, fs->win, fs->fsi_sector, 1);
+            fs->fsi_flag = 0;
+        }
+        /* Make sure that no pending write process in the physical drive */
+        if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK)
+            res = FR_DISK_ERR;
+    }
+
+    return res;
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get sector# from cluster#                                             */
+/*-----------------------------------------------------------------------*/
+
+
+DWORD clust2sect (    /* !=0: Sector number, 0: Failed - invalid cluster# */
+    FATFS *fs,        /* File system object */
+    DWORD clst        /* Cluster# to be converted */
+)
+{
+    clst -= 2;
+    if (clst >= (fs->n_fatent - 2)) return 0;        /* Invalid cluster# */
+    return clst * fs->csize + fs->database;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT access - Read value of a FAT entry                                */
+/*-----------------------------------------------------------------------*/
+
+
+DWORD get_fat (    /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */
+    FATFS *fs,    /* File system object */
+    DWORD clst    /* Cluster# to get the link information */
+)
+{
+    UINT wc, bc;
+    BYTE *p;
+
+
+    if (clst < 2 || clst >= fs->n_fatent)    /* Chack range */
+        return 1;
+
+    switch (fs->fs_type) {
+    case FS_FAT12 :
+        bc = (UINT)clst; bc += bc / 2;
+        if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
+        wc = fs->win[bc % SS(fs)]; bc++;
+        if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
+        wc |= fs->win[bc % SS(fs)] << 8;
+        return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
+
+    case FS_FAT16 :
+        if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break;
+        p = &fs->win[clst * 2 % SS(fs)];
+        return LD_WORD(p);
+
+    case FS_FAT32 :
+        if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break;
+        p = &fs->win[clst * 4 % SS(fs)];
+        return LD_DWORD(p) & 0x0FFFFFFF;
+    }
+
+    return 0xFFFFFFFF;    /* An error occurred at the disk I/O layer */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT access - Change value of a FAT entry                              */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+
+FRESULT put_fat (
+    FATFS *fs,    /* File system object */
+    DWORD clst,    /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */
+    DWORD val    /* New value to mark the cluster */
+)
+{
+    UINT bc;
+    BYTE *p;
+    FRESULT res;
+
+
+    if (clst < 2 || clst >= fs->n_fatent) {    /* Check range */
+        res = FR_INT_ERR;
+
+    } else {
+        switch (fs->fs_type) {
+        case FS_FAT12 :
+            bc = clst; bc += bc / 2;
+            res = move_window(fs, fs->fatbase + (bc / SS(fs)));
+            if (res != FR_OK) break;
+            p = &fs->win[bc % SS(fs)];
+            *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
+            bc++;
+            fs->wflag = 1;
+            res = move_window(fs, fs->fatbase + (bc / SS(fs)));
+            if (res != FR_OK) break;
+            p = &fs->win[bc % SS(fs)];
+            *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
+            break;
+
+        case FS_FAT16 :
+            res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
+            if (res != FR_OK) break;
+            p = &fs->win[clst * 2 % SS(fs)];
+            ST_WORD(p, (WORD)val);
+            break;
+
+        case FS_FAT32 :
+            res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
+            if (res != FR_OK) break;
+            p = &fs->win[clst * 4 % SS(fs)];
+            val |= LD_DWORD(p) & 0xF0000000;
+            ST_DWORD(p, val);
+            break;
+
+        default :
+            res = FR_INT_ERR;
+        }
+        fs->wflag = 1;
+    }
+
+    return res;
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT handling - Remove a cluster chain                                 */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+FRESULT remove_chain (
+    FATFS *fs,            /* File system object */
+    DWORD clst            /* Cluster# to remove a chain from */
+)
+{
+    FRESULT res;
+    DWORD nxt;
+#if _USE_ERASE
+    DWORD scl = clst, ecl = clst, resion[2];
+#endif
+
+    if (clst < 2 || clst >= fs->n_fatent) {    /* Check range */
+        res = FR_INT_ERR;
+
+    } else {
+        res = FR_OK;
+        while (clst < fs->n_fatent) {            /* Not a last link? */
+            nxt = get_fat(fs, clst);            /* Get cluster status */
+            if (nxt == 0) break;                /* Empty cluster? */
+            if (nxt == 1) { res = FR_INT_ERR; break; }    /* Internal error? */
+            if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }    /* Disk error? */
+            res = put_fat(fs, clst, 0);            /* Mark the cluster "empty" */
+            if (res != FR_OK) break;
+            if (fs->free_clust != 0xFFFFFFFF) {    /* Update FSInfo */
+                fs->free_clust++;
+                fs->fsi_flag = 1;
+            }
+#if _USE_ERASE
+            if (ecl + 1 == nxt) {    /* Next cluster is contiguous */
+                ecl = nxt;
+            } else {                /* End of contiguous clusters */ 
+                resion[0] = clust2sect(fs, scl);                    /* Start sector */
+                resion[1] = clust2sect(fs, ecl) + fs->csize - 1;    /* End sector */
+                disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion);        /* Erase the block */
+                scl = ecl = nxt;
+            }
+#endif
+            clst = nxt;    /* Next cluster */
+        }
+    }
+
+    return res;
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT handling - Stretch or Create a cluster chain                      */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+DWORD create_chain (    /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
+    FATFS *fs,            /* File system object */
+    DWORD clst            /* Cluster# to stretch. 0 means create a new chain. */
+)
+{
+    DWORD cs, ncl, scl;
+    FRESULT res;
+
+
+    if (clst == 0) {        /* Create a new chain */
+        scl = fs->last_clust;            /* Get suggested start point */
+        if (!scl || scl >= fs->n_fatent) scl = 1;
+    }
+    else {                    /* Stretch the current chain */
+        cs = get_fat(fs, clst);            /* Check the cluster status */
+        if (cs < 2) return 1;            /* It is an invalid cluster */
+        if (cs < fs->n_fatent) return cs;    /* It is already followed by next cluster */
+        scl = clst;
+    }
+
+    ncl = scl;                /* Start cluster */
+    for (;;) {
+        ncl++;                            /* Next cluster */
+        if (ncl >= fs->n_fatent) {        /* Wrap around */
+            ncl = 2;
+            if (ncl > scl) return 0;    /* No free cluster */
+        }
+        cs = get_fat(fs, ncl);            /* Get the cluster status */
+        if (cs == 0) break;                /* Found a free cluster */
+        if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */
+            return cs;
+        if (ncl == scl) return 0;        /* No free cluster */
+    }
+
+    res = put_fat(fs, ncl, 0x0FFFFFFF);    /* Mark the new cluster "last link" */
+    if (res == FR_OK && clst != 0) {
+        res = put_fat(fs, clst, ncl);    /* Link it to the previous one if needed */
+    }
+    if (res == FR_OK) {
+        fs->last_clust = ncl;            /* Update FSINFO */
+        if (fs->free_clust != 0xFFFFFFFF) {
+            fs->free_clust--;
+            fs->fsi_flag = 1;
+        }
+    } else {
+        ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
+    }
+
+    return ncl;        /* Return new cluster number or error code */
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Set directory index                              */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_sdi (
+    DIR *dj,        /* Pointer to directory object */
+    WORD idx        /* Directory index number */
+)
+{
+    DWORD clst;
+    WORD ic;
+
+
+    dj->index = idx;
+    clst = dj->sclust;
+    if (clst == 1 || clst >= dj->fs->n_fatent)    /* Check start cluster range */
+        return FR_INT_ERR;
+    if (!clst && dj->fs->fs_type == FS_FAT32)    /* Replace cluster# 0 with root cluster# if in FAT32 */
+        clst = dj->fs->dirbase;
+
+    if (clst == 0) {    /* Static table (root-dir in FAT12/16) */
+        dj->clust = clst;
+        if (idx >= dj->fs->n_rootdir)        /* Index is out of range */
+            return FR_INT_ERR;
+        dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32);    /* Sector# */
+    }
+    else {                /* Dynamic table (sub-dirs or root-dir in FAT32) */
+        ic = SS(dj->fs) / 32 * dj->fs->csize;    /* Entries per cluster */
+        while (idx >= ic) {    /* Follow cluster chain */
+            clst = get_fat(dj->fs, clst);                /* Get next cluster */
+            if (clst == 0xFFFFFFFF) return FR_DISK_ERR;    /* Disk error */
+            if (clst < 2 || clst >= dj->fs->n_fatent)    /* Reached to end of table or int error */
+                return FR_INT_ERR;
+            idx -= ic;
+        }
+        dj->clust = clst;
+        dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32);    /* Sector# */
+    }
+
+    dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32;    /* Ptr to the entry in the sector */
+
+    return FR_OK;    /* Seek succeeded */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Move directory index next                        */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_next (    /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */
+    DIR *dj,        /* Pointer to directory object */
+    int stretch        /* 0: Do not stretch table, 1: Stretch table if needed */
+)
+{
+    DWORD clst;
+    WORD i;
+
+
+    i = dj->index + 1;
+    if (!i || !dj->sect)    /* Report EOT when index has reached 65535 */
+        return FR_NO_FILE;
+
+    if (!(i % (SS(dj->fs) / 32))) {    /* Sector changed? */
+        dj->sect++;                    /* Next sector */
+
+        if (dj->clust == 0) {    /* Static table */
+            if (i >= dj->fs->n_rootdir)    /* Report EOT when end of table */
+                return FR_NO_FILE;
+        }
+        else {                    /* Dynamic table */
+            if (((i / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) {    /* Cluster changed? */
+                clst = get_fat(dj->fs, dj->clust);                /* Get next cluster */
+                if (clst <= 1) return FR_INT_ERR;
+                if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
+                if (clst >= dj->fs->n_fatent) {                    /* When it reached end of dynamic table */
+#if !_FS_READONLY
+                    BYTE c;
+                    if (!stretch) return FR_NO_FILE;            /* When do not stretch, report EOT */
+                    clst = create_chain(dj->fs, dj->clust);        /* Stretch cluster chain */
+                    if (clst == 0) return FR_DENIED;            /* No free cluster */
+                    if (clst == 1) return FR_INT_ERR;
+                    if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
+                    /* Clean-up stretched table */
+                    if (move_window(dj->fs, 0)) return FR_DISK_ERR;    /* Flush active window */
+                    mem_set(dj->fs->win, 0, SS(dj->fs));            /* Clear window buffer */
+                    dj->fs->winsect = clust2sect(dj->fs, clst);    /* Cluster start sector */
+                    for (c = 0; c < dj->fs->csize; c++) {        /* Fill the new cluster with 0 */
+                        dj->fs->wflag = 1;
+                        if (move_window(dj->fs, 0)) return FR_DISK_ERR;
+                        dj->fs->winsect++;
+                    }
+                    dj->fs->winsect -= c;                        /* Rewind window address */
+#else
+                    return FR_NO_FILE;            /* Report EOT */
+#endif
+                }
+                dj->clust = clst;                /* Initialize data for new cluster */
+                dj->sect = clust2sect(dj->fs, clst);
+            }
+        }
+    }
+
+    dj->index = i;
+    dj->dir = dj->fs->win + (i % (SS(dj->fs) / 32)) * 32;
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry   */
+/*-----------------------------------------------------------------------*/
+#if _USE_LFN
+static
+const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30};    /* Offset of LFN chars in the directory entry */
+
+
+static
+int cmp_lfn (            /* 1:Matched, 0:Not matched */
+    WCHAR *lfnbuf,        /* Pointer to the LFN to be compared */
+    BYTE *dir            /* Pointer to the directory entry containing a part of LFN */
+)
+{
+    UINT i, s;
+    WCHAR wc, uc;
+
+
+    i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13;    /* Get offset in the LFN buffer */
+    s = 0; wc = 1;
+    do {
+        uc = LD_WORD(dir+LfnOfs[s]);    /* Pick an LFN character from the entry */
+        if (wc) {    /* Last char has not been processed */
+            wc = ff_wtoupper(uc);        /* Convert it to upper case */
+            if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++]))    /* Compare it */
+                return 0;                /* Not matched */
+        } else {
+            if (uc != 0xFFFF) return 0;    /* Check filler */
+        }
+    } while (++s < 13);                /* Repeat until all chars in the entry are checked */
+
+    if ((dir[LDIR_Ord] & 0x40) && wc && lfnbuf[i])    /* Last segment matched but different length */
+        return 0;
+
+    return 1;                        /* The part of LFN matched */
+}
+
+
+
+static
+int pick_lfn (            /* 1:Succeeded, 0:Buffer overflow */
+    WCHAR *lfnbuf,        /* Pointer to the Unicode-LFN buffer */
+    BYTE *dir            /* Pointer to the directory entry */
+)
+{
+    UINT i, s;
+    WCHAR wc, uc;
+
+
+    i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13;    /* Offset in the LFN buffer */
+
+    s = 0; wc = 1;
+    do {
+        uc = LD_WORD(dir+LfnOfs[s]);        /* Pick an LFN character from the entry */
+        if (wc) {    /* Last char has not been processed */
+            if (i >= _MAX_LFN) return 0;    /* Buffer overflow? */
+            lfnbuf[i++] = wc = uc;            /* Store it */
+        } else {
+            if (uc != 0xFFFF) return 0;        /* Check filler */
+        }
+    } while (++s < 13);                        /* Read all character in the entry */
+
+    if (dir[LDIR_Ord] & 0x40) {                /* Put terminator if it is the last LFN part */
+        if (i >= _MAX_LFN) return 0;        /* Buffer overflow? */
+        lfnbuf[i] = 0;
+    }
+
+    return 1;
+}
+
+
+#if !_FS_READONLY
+static
+void fit_lfn (
+    const WCHAR *lfnbuf,    /* Pointer to the LFN buffer */
+    BYTE *dir,                /* Pointer to the directory entry */
+    BYTE ord,                /* LFN order (1-20) */
+    BYTE sum                /* SFN sum */
+)
+{
+    UINT i, s;
+    WCHAR wc;
+
+
+    dir[LDIR_Chksum] = sum;            /* Set check sum */
+    dir[LDIR_Attr] = AM_LFN;        /* Set attribute. LFN entry */
+    dir[LDIR_Type] = 0;
+    ST_WORD(dir+LDIR_FstClusLO, 0);
+
+    i = (ord - 1) * 13;                /* Get offset in the LFN buffer */
+    s = wc = 0;
+    do {
+        if (wc != 0xFFFF) wc = lfnbuf[i++];    /* Get an effective char */
+        ST_WORD(dir+LfnOfs[s], wc);    /* Put it */
+        if (!wc) wc = 0xFFFF;        /* Padding chars following last char */
+    } while (++s < 13);
+    if (wc == 0xFFFF || !lfnbuf[i]) ord |= 0x40;    /* Bottom LFN part is the start of LFN sequence */
+    dir[LDIR_Ord] = ord;            /* Set the LFN order */
+}
+
+#endif
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Create numbered name                                                  */
+/*-----------------------------------------------------------------------*/
+#if _USE_LFN
+void gen_numname (
+    BYTE *dst,            /* Pointer to generated SFN */
+    const BYTE *src,    /* Pointer to source SFN to be modified */
+    const WCHAR *lfn,    /* Pointer to LFN */
+    WORD seq            /* Sequence number */
+)
+{
+    BYTE ns[8], c;
+    UINT i, j;
+
+
+    mem_cpy(dst, src, 11);
+
+    if (seq > 5) {    /* On many collisions, generate a hash number instead of sequential number */
+        do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn);
+    }
+
+    /* itoa */
+    i = 7;
+    do {
+        c = (seq % 16) + '0';
+        if (c > '9') c += 7;
+        ns[i--] = c;
+        seq /= 16;
+    } while (seq);
+    ns[i] = '~';
+
+    /* Append the number */
+    for (j = 0; j < i && dst[j] != ' '; j++) {
+        if (IsDBCS1(dst[j])) {
+            if (j == i - 1) break;
+            j++;
+        }
+    }
+    do {
+        dst[j++] = (i < 8) ? ns[i++] : ' ';
+    } while (j < 8);
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Calculate sum of an SFN                                               */
+/*-----------------------------------------------------------------------*/
+#if _USE_LFN
+static
+BYTE sum_sfn (
+    const BYTE *dir        /* Ptr to directory entry */
+)
+{
+    BYTE sum = 0;
+    UINT n = 11;
+
+    do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
+    return sum;
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Find an object in the directory                  */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_find (
+    DIR *dj            /* Pointer to the directory object linked to the file name */
+)
+{
+    FRESULT res;
+    BYTE c, *dir;
+#if _USE_LFN
+    BYTE a, ord, sum;
+#endif
+
+    res = dir_sdi(dj, 0);            /* Rewind directory object */
+    if (res != FR_OK) return res;
+
+#if _USE_LFN
+    ord = sum = 0xFF;
+#endif
+    do {
+        res = move_window(dj->fs, dj->sect);
+        if (res != FR_OK) break;
+        dir = dj->dir;                    /* Ptr to the directory entry of current index */
+        c = dir[DIR_Name];
+        if (c == 0) { res = FR_NO_FILE; break; }    /* Reached to end of table */
+#if _USE_LFN    /* LFN configuration */
+        a = dir[DIR_Attr] & AM_MASK;
+        if (c == 0xE5 || ((a & AM_VOL) && a != AM_LFN)) {    /* An entry without valid data */
+            ord = 0xFF;
+        } else {
+            if (a == AM_LFN) {            /* An LFN entry is found */
+                if (dj->lfn) {
+                    if (c & 0x40) {        /* Is it start of LFN sequence? */
+                        sum = dir[LDIR_Chksum];
+                        c &= 0xBF; ord = c;    /* LFN start order */
+                        dj->lfn_idx = dj->index;
+                    }
+                    /* Check validity of the LFN entry and compare it with given name */
+                    ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
+                }
+            } else {                    /* An SFN entry is found */
+                if (!ord && sum == sum_sfn(dir)) break;    /* LFN matched? */
+                ord = 0xFF; dj->lfn_idx = 0xFFFF;    /* Reset LFN sequence */
+                if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break;    /* SFN matched? */
+            }
+        }
+#else        /* Non LFN configuration */
+        if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */
+            break;
+#endif
+        res = dir_next(dj, 0);        /* Next entry */
+    } while (res == FR_OK);
+
+    return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read an object from the directory                                     */
+/*-----------------------------------------------------------------------*/
+#if _FS_MINIMIZE <= 1
+static
+FRESULT dir_read (
+    DIR *dj            /* Pointer to the directory object that pointing the entry to be read */
+)
+{
+    FRESULT res;
+    BYTE c, *dir;
+#if _USE_LFN
+    BYTE a, ord = 0xFF, sum = 0xFF;
+#endif
+
+    res = FR_NO_FILE;
+    while (dj->sect) {
+        res = move_window(dj->fs, dj->sect);
+        if (res != FR_OK) break;
+        dir = dj->dir;                    /* Ptr to the directory entry of current index */
+        c = dir[DIR_Name];
+        if (c == 0) { res = FR_NO_FILE; break; }    /* Reached to end of table */
+#if _USE_LFN    /* LFN configuration */
+        a = dir[DIR_Attr] & AM_MASK;
+        if (c == 0xE5 || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) {    /* An entry without valid data */
+            ord = 0xFF;
+        } else {
+            if (a == AM_LFN) {            /* An LFN entry is found */
+                if (c & 0x40) {            /* Is it start of LFN sequence? */
+                    sum = dir[LDIR_Chksum];
+                    c &= 0xBF; ord = c;
+                    dj->lfn_idx = dj->index;
+                }
+                /* Check LFN validity and capture it */
+                ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
+            } else {                    /* An SFN entry is found */
+                if (ord || sum != sum_sfn(dir))    /* Is there a valid LFN? */
+                    dj->lfn_idx = 0xFFFF;        /* It has no LFN. */
+                break;
+            }
+        }
+#else        /* Non LFN configuration */
+        if (c != 0xE5 && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL))    /* Is it a valid entry? */
+            break;
+#endif
+        res = dir_next(dj, 0);                /* Next entry */
+        if (res != FR_OK) break;
+    }
+
+    if (res != FR_OK) dj->sect = 0;
+
+    return res;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Register an object to the directory                                   */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+FRESULT dir_register (    /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
+    DIR *dj                /* Target directory with object name to be created */
+)
+{
+    FRESULT res;
+    BYTE c, *dir;
+#if _USE_LFN    /* LFN configuration */
+    WORD n, ne, is;
+    BYTE sn[12], *fn, sum;
+    WCHAR *lfn;
+
+
+    fn = dj->fn; lfn = dj->lfn;
+    mem_cpy(sn, fn, 12);
+
+    if (_FS_RPATH && (sn[NS] & NS_DOT))        /* Cannot create dot entry */
+        return FR_INVALID_NAME;
+
+    if (sn[NS] & NS_LOSS) {            /* When LFN is out of 8.3 format, generate a numbered name */
+        fn[NS] = 0; dj->lfn = 0;            /* Find only SFN */
+        for (n = 1; n < 100; n++) {
+            gen_numname(fn, sn, lfn, n);    /* Generate a numbered name */
+            res = dir_find(dj);                /* Check if the name collides with existing SFN */
+            if (res != FR_OK) break;
+        }
+        if (n == 100) return FR_DENIED;        /* Abort if too many collisions */
+        if (res != FR_NO_FILE) return res;    /* Abort if the result is other than 'not collided' */
+        fn[NS] = sn[NS]; dj->lfn = lfn;
+    }
+
+    if (sn[NS] & NS_LFN) {            /* When LFN is to be created, reserve an SFN + LFN entries. */
+        for (ne = 0; lfn[ne]; ne++) ;
+        ne = (ne + 25) / 13;
+    } else {                        /* Otherwise reserve only an SFN entry. */
+        ne = 1;
+    }
+
+    /* Reserve contiguous entries */
+    res = dir_sdi(dj, 0);
+    if (res != FR_OK) return res;
+    n = is = 0;
+    do {
+        res = move_window(dj->fs, dj->sect);
+        if (res != FR_OK) break;
+        c = *dj->dir;                /* Check the entry status */
+        if (c == 0xE5 || c == 0) {    /* Is it a blank entry? */
+            if (n == 0) is = dj->index;    /* First index of the contiguous entry */
+            if (++n == ne) break;    /* A contiguous entry that required count is found */
+        } else {
+            n = 0;                    /* Not a blank entry. Restart to search */
+        }
+        res = dir_next(dj, 1);        /* Next entry with table stretch */
+    } while (res == FR_OK);
+
+    if (res == FR_OK && ne > 1) {    /* Initialize LFN entry if needed */
+        res = dir_sdi(dj, is);
+        if (res == FR_OK) {
+            sum = sum_sfn(dj->fn);    /* Sum of the SFN tied to the LFN */
+            ne--;
+            do {                    /* Store LFN entries in bottom first */
+                res = move_window(dj->fs, dj->sect);
+                if (res != FR_OK) break;
+                fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum);
+                dj->fs->wflag = 1;
+                res = dir_next(dj, 0);    /* Next entry */
+            } while (res == FR_OK && --ne);
+        }
+    }
+
+#else    /* Non LFN configuration */
+    res = dir_sdi(dj, 0);
+    if (res == FR_OK) {
+        do {    /* Find a blank entry for the SFN */
+            res = move_window(dj->fs, dj->sect);
+            if (res != FR_OK) break;
+            c = *dj->dir;
+            if (c == 0xE5 || c == 0) break;    /* Is it a blank entry? */
+            res = dir_next(dj, 1);            /* Next entry with table stretch */
+        } while (res == FR_OK);
+    }
+#endif
+
+    if (res == FR_OK) {        /* Initialize the SFN entry */
+        res = move_window(dj->fs, dj->sect);
+        if (res == FR_OK) {
+            dir = dj->dir;
+            mem_set(dir, 0, 32);        /* Clean the entry */
+            mem_cpy(dir, dj->fn, 11);    /* Put SFN */
+#if _USE_LFN
+            dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT);    /* Put NT flag */
+#endif
+            dj->fs->wflag = 1;
+        }
+    }
+
+    return res;
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Remove an object from the directory                                   */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY && !_FS_MINIMIZE
+static
+FRESULT dir_remove (    /* FR_OK: Successful, FR_DISK_ERR: A disk error */
+    DIR *dj                /* Directory object pointing the entry to be removed */
+)
+{
+    FRESULT res;
+#if _USE_LFN    /* LFN configuration */
+    WORD i;
+
+    i = dj->index;    /* SFN index */
+    res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx));    /* Goto the SFN or top of the LFN entries */
+    if (res == FR_OK) {
+        do {
+            res = move_window(dj->fs, dj->sect);
+            if (res != FR_OK) break;
+            *dj->dir = 0xE5;            /* Mark the entry "deleted" */
+            dj->fs->wflag = 1;
+            if (dj->index >= i) break;    /* When reached SFN, all entries of the object has been deleted. */
+            res = dir_next(dj, 0);        /* Next entry */
+        } while (res == FR_OK);
+        if (res == FR_NO_FILE) res = FR_INT_ERR;
+    }
+
+#else            /* Non LFN configuration */
+    res = dir_sdi(dj, dj->index);
+    if (res == FR_OK) {
+        res = move_window(dj->fs, dj->sect);
+        if (res == FR_OK) {
+            *dj->dir = 0xE5;            /* Mark the entry "deleted" */
+            dj->fs->wflag = 1;
+        }
+    }
+#endif
+
+    return res;
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Pick a segment and create the object name in directory form           */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT create_name (
+    DIR *dj,            /* Pointer to the directory object */
+    const TCHAR **path    /* Pointer to pointer to the segment in the path string */
+)
+{
+#ifdef _EXCVT
+    static const BYTE excvt[] = _EXCVT;    /* Upper conversion table for extended chars */
+#endif
+
+#if _USE_LFN    /* LFN configuration */
+    BYTE b, cf;
+    WCHAR w, *lfn;
+    UINT i, ni, si, di;
+    const TCHAR *p;
+
+    /* Create LFN in Unicode */
+    si = di = 0;
+    p = *path;
+    lfn = dj->lfn;
+    for (;;) {
+        w = p[si++];                    /* Get a character */
+        if (w < ' ' || w == '/' || w == '\\') break;    /* Break on end of segment */
+        if (di >= _MAX_LFN)                /* Reject too long name */
+            return FR_INVALID_NAME;
+#if !_LFN_UNICODE
+        w &= 0xFF;
+        if (IsDBCS1(w)) {                /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
+            b = (BYTE)p[si++];            /* Get 2nd byte */
+            if (!IsDBCS2(b))
+                return FR_INVALID_NAME;    /* Reject invalid sequence */
+            w = (w << 8) + b;            /* Create a DBC */
+        }
+        w = ff_convert(w, 1);            /* Convert ANSI/OEM to Unicode */
+        if (!w) return FR_INVALID_NAME;    /* Reject invalid code */
+#endif
+        if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */
+            return FR_INVALID_NAME;
+        lfn[di++] = w;                    /* Store the Unicode char */
+    }
+    *path = &p[si];                        /* Return pointer to the next segment */
+    cf = (w < ' ') ? NS_LAST : 0;        /* Set last segment flag if end of path */
+#if _FS_RPATH
+    if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */
+        (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) {
+        lfn[di] = 0;
+        for (i = 0; i < 11; i++)
+            dj->fn[i] = (i < di) ? '.' : ' ';
+        dj->fn[i] = cf | NS_DOT;        /* This is a dot entry */
+        return FR_OK;
+    }
+#endif
+    while (di) {                        /* Strip trailing spaces and dots */
+        w = lfn[di-1];
+        if (w != ' ' && w != '.') break;
+        di--;
+    }
+    if (!di) return FR_INVALID_NAME;    /* Reject nul string */
+
+    lfn[di] = 0;                        /* LFN is created */
+
+    /* Create SFN in directory form */
+    mem_set(dj->fn, ' ', 11);
+    for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ;    /* Strip leading spaces and dots */
+    if (si) cf |= NS_LOSS | NS_LFN;
+    while (di && lfn[di - 1] != '.') di--;    /* Find extension (di<=si: no extension) */
+
+    b = i = 0; ni = 8;
+    for (;;) {
+        w = lfn[si++];                    /* Get an LFN char */
+        if (!w) break;                    /* Break on end of the LFN */
+        if (w == ' ' || (w == '.' && si != di)) {    /* Remove spaces and dots */
+            cf |= NS_LOSS | NS_LFN; continue;
+        }
+
+        if (i >= ni || si == di) {        /* Extension or end of SFN */
+            if (ni == 11) {                /* Long extension */
+                cf |= NS_LOSS | NS_LFN; break;
+            }
+            if (si != di) cf |= NS_LOSS | NS_LFN;    /* Out of 8.3 format */
+            if (si > di) break;            /* No extension */
+            si = di; i = 8; ni = 11;    /* Enter extension section */
+            b <<= 2; continue;
+        }
+
+        if (w >= 0x80) {                /* Non ASCII char */
+#ifdef _EXCVT
+            w = ff_convert(w, 0);        /* Unicode -> OEM code */
+            if (w) w = excvt[w - 0x80];    /* Convert extended char to upper (SBCS) */
+#else
+            w = ff_convert(ff_wtoupper(w), 0);    /* Upper converted Unicode -> OEM code */
+#endif
+            cf |= NS_LFN;                /* Force create LFN entry */
+        }
+
+        if (_DF1S && w >= 0x100) {        /* Double byte char (always false on SBCS cfg) */
+            if (i >= ni - 1) {
+                cf |= NS_LOSS | NS_LFN; i = ni; continue;
+            }
+            dj->fn[i++] = (BYTE)(w >> 8);
+        } else {                        /* Single byte char */
+            if (!w || chk_chr("+,;=[]", w)) {    /* Replace illegal chars for SFN */
+                w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
+            } else {
+                if (IsUpper(w)) {        /* ASCII large capital */
+                    b |= 2;
+                } else {
+                    if (IsLower(w)) {    /* ASCII small capital */
+                        b |= 1; w -= 0x20;
+                    }
+                }
+            }
+        }
+        dj->fn[i++] = (BYTE)w;
+    }
+
+    if (dj->fn[0] == 0xE5) dj->fn[0] = 0x05;    /* If the first char collides with deleted mark, replace it with 0x05 */
+
+    if (ni == 8) b <<= 2;
+    if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03)    /* Create LFN entry when there are composite capitals */
+        cf |= NS_LFN;
+    if (!(cf & NS_LFN)) {                        /* When LFN is in 8.3 format without extended char, NT flags are created */
+        if ((b & 0x03) == 0x01) cf |= NS_EXT;    /* NT flag (Extension has only small capital) */
+        if ((b & 0x0C) == 0x04) cf |= NS_BODY;    /* NT flag (Filename has only small capital) */
+    }
+
+    dj->fn[NS] = cf;    /* SFN is created */
+
+    return FR_OK;
+
+
+#else    /* Non-LFN configuration */
+    BYTE b, c, d, *sfn;
+    UINT ni, si, i;
+    const char *p;
+
+    /* Create file name in directory form */
+    sfn = dj->fn;
+    mem_set(sfn, ' ', 11);
+    si = i = b = 0; ni = 8;
+    p = *path;
+#if _FS_RPATH
+    if (p[si] == '.') { /* Is this a dot entry? */
+        for (;;) {
+            c = (BYTE)p[si++];
+            if (c != '.' || si >= 3) break;
+            sfn[i++] = c;
+        }
+        if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
+        *path = &p[si];                                    /* Return pointer to the next segment */
+        sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT;    /* Set last segment flag if end of path */
+        return FR_OK;
+    }
+#endif
+    for (;;) {
+        c = (BYTE)p[si++];
+        if (c <= ' ' || c == '/' || c == '\\') break;    /* Break on end of segment */
+        if (c == '.' || i >= ni) {
+            if (ni != 8 || c != '.') return FR_INVALID_NAME;
+            i = 8; ni = 11;
+            b <<= 2; continue;
+        }
+        if (c >= 0x80) {                /* Extended char? */
+            b |= 3;                        /* Eliminate NT flag */
+#ifdef _EXCVT
+            c = excvt[c-0x80];            /* Upper conversion (SBCS) */
+#else
+#if !_DF1S    /* ASCII only cfg */
+            return FR_INVALID_NAME;
+#endif
+#endif
+        }
+        if (IsDBCS1(c)) {                /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
+            d = (BYTE)p[si++];            /* Get 2nd byte */
+            if (!IsDBCS2(d) || i >= ni - 1)    /* Reject invalid DBC */
+                return FR_INVALID_NAME;
+            sfn[i++] = c;
+            sfn[i++] = d;
+        } else {                        /* Single byte code */
+            if (chk_chr("\"*+,:;<=>\?[]|\x7F", c))    /* Reject illegal chrs for SFN */
+                return FR_INVALID_NAME;
+            if (IsUpper(c)) {            /* ASCII large capital? */
+                b |= 2;
+            } else {
+                if (IsLower(c)) {        /* ASCII small capital? */
+                    b |= 1; c -= 0x20;
+                }
+            }
+            sfn[i++] = c;
+        }
+    }
+    *path = &p[si];                        /* Return pointer to the next segment */
+    c = (c <= ' ') ? NS_LAST : 0;        /* Set last segment flag if end of path */
+
+    if (!i) return FR_INVALID_NAME;        /* Reject nul string */
+    if (sfn[0] == 0xE5) sfn[0] = 0x05;    /* When first char collides with 0xE5, replace it with 0x05 */
+
+    if (ni == 8) b <<= 2;
+    if ((b & 0x03) == 0x01) c |= NS_EXT;    /* NT flag (Name extension has only small capital) */
+    if ((b & 0x0C) == 0x04) c |= NS_BODY;    /* NT flag (Name body has only small capital) */
+
+    sfn[NS] = c;        /* Store NT flag, File name is created */
+
+    return FR_OK;
+#endif
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get file information from directory entry                             */
+/*-----------------------------------------------------------------------*/
+#if _FS_MINIMIZE <= 1
+static
+void get_fileinfo (        /* No return code */
+    DIR *dj,            /* Pointer to the directory object */
+    FILINFO *fno         /* Pointer to the file information to be filled */
+)
+{
+    UINT i;
+    BYTE nt, *dir;
+    TCHAR *p, c;
+
+
+    p = fno->fname;
+    if (dj->sect) {
+        dir = dj->dir;
+        nt = dir[DIR_NTres];        /* NT flag */
+        for (i = 0; i < 8; i++) {    /* Copy name body */
+            c = dir[i];
+            if (c == ' ') break;
+            if (c == 0x05) c = (TCHAR)0xE5;
+            if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20;
+#if _LFN_UNICODE
+            if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1]))
+                c = (c << 8) | dir[++i];
+            c = ff_convert(c, 1);
+            if (!c) c = '?';
+#endif
+            *p++ = c;
+        }
+        if (dir[8] != ' ') {        /* Copy name extension */
+            *p++ = '.';
+            for (i = 8; i < 11; i++) {
+                c = dir[i];
+                if (c == ' ') break;
+                if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20;
+#if _LFN_UNICODE
+                if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1]))
+                    c = (c << 8) | dir[++i];
+                c = ff_convert(c, 1);
+                if (!c) c = '?';
+#endif
+                *p++ = c;
+            }
+        }
+        fno->fattrib = dir[DIR_Attr];                /* Attribute */
+        fno->fsize = LD_DWORD(dir+DIR_FileSize);    /* Size */
+        fno->fdate = LD_WORD(dir+DIR_WrtDate);        /* Date */
+        fno->ftime = LD_WORD(dir+DIR_WrtTime);        /* Time */
+    }
+    *p = 0;        /* Terminate SFN str by a \0 */
+
+#if _USE_LFN
+    if (fno->lfname && fno->lfsize) {
+        TCHAR *tp = fno->lfname;
+        WCHAR w, *lfn;
+
+        i = 0;
+        if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */
+            lfn = dj->lfn;
+            while ((w = *lfn++) != 0) {            /* Get an LFN char */
+#if !_LFN_UNICODE
+                w = ff_convert(w, 0);            /* Unicode -> OEM conversion */
+                if (!w) { i = 0; break; }        /* Could not convert, no LFN */
+                if (_DF1S && w >= 0x100)        /* Put 1st byte if it is a DBC (always false on SBCS cfg) */
+                    tp[i++] = (TCHAR)(w >> 8);
+#endif
+                if (i >= fno->lfsize - 1) { i = 0; break; }    /* Buffer overflow, no LFN */
+                tp[i++] = (TCHAR)w;
+            }
+        }
+        tp[i] = 0;    /* Terminate the LFN str by a \0 */
+    }
+#endif
+}
+#endif /* _FS_MINIMIZE <= 1 */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Follow a file path                                                    */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT follow_path (    /* FR_OK(0): successful, !=0: error code */
+    DIR *dj,            /* Directory object to return last directory and found object */
+    const TCHAR *path    /* Full-path string to find a file or directory */
+)
+{
+    FRESULT res;
+    BYTE *dir, ns;
+
+
+#if _FS_RPATH
+    if (*path == '/' || *path == '\\') { /* There is a heading separator */
+        path++;    dj->sclust = 0;        /* Strip it and start from the root dir */
+    } else {                            /* No heading separator */
+        dj->sclust = dj->fs->cdir;    /* Start from the current dir */
+    }
+#else
+    if (*path == '/' || *path == '\\')    /* Strip heading separator if exist */
+        path++;
+    dj->sclust = 0;                        /* Start from the root dir */
+#endif
+
+    if ((UINT)*path < ' ') {            /* Nul path means the start directory itself */
+        res = dir_sdi(dj, 0);
+        dj->dir = 0;
+
+    } else {                            /* Follow path */
+        for (;;) {
+            res = create_name(dj, &path);    /* Get a segment */
+            if (res != FR_OK) break;
+            res = dir_find(dj);                /* Find it */
+            ns = *(dj->fn+NS);
+            if (res != FR_OK) {                /* Failed to find the object */
+                if (res != FR_NO_FILE) break;    /* Abort if any hard error occured */
+                /* Object not found */
+                if (_FS_RPATH && (ns & NS_DOT)) {    /* If dot entry is not exit */
+                    dj->sclust = 0; dj->dir = 0;    /* It is the root dir */
+                    res = FR_OK;
+                    if (!(ns & NS_LAST)) continue;
+                } else {                            /* Could not find the object */
+                    if (!(ns & NS_LAST)) res = FR_NO_PATH;
+                }
+                break;
+            }
+            if (ns & NS_LAST) break;            /* Last segment match. Function completed. */
+            dir = dj->dir;                        /* There is next segment. Follow the sub directory */
+            if (!(dir[DIR_Attr] & AM_DIR)) {    /* Cannot follow because it is a file */
+                res = FR_NO_PATH; break;
+            }
+            dj->sclust = LD_CLUST(dir);
+        }
+    }
+
+    return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Load boot record and check if it is an FAT boot record                */
+/*-----------------------------------------------------------------------*/
+
+static
+BYTE check_fs (    /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
+    FATFS *fs,    /* File system object */
+    DWORD sect    /* Sector# (lba) to check if it is an FAT boot record or not */
+)
+{
+    if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK)    /* Load boot record */
+        return 3;
+    if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)        /* Check record signature (always placed at offset 510 even if the sector size is >512) */
+        return 2;
+
+    if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146)    /* Check "FAT" string */
+        return 0;
+    if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
+        return 0;
+
+    return 1;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Check if the file system object is valid or not                       */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT chk_mounted (    /* FR_OK(0): successful, !=0: any error occurred */
+    const TCHAR **path,    /* Pointer to pointer to the path name (drive number) */
+    FATFS **rfs,        /* Pointer to pointer to the found file system object */
+    BYTE chk_wp            /* !=0: Check media write protection for write access */
+)
+{
+    BYTE fmt, b, *tbl;
+    UINT vol;
+    DSTATUS stat;
+    DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
+    WORD nrsv;
+    const TCHAR *p = *path;
+    FATFS *fs;
+
+    /* Get logical drive number from the path name */
+    vol = p[0] - '0';                    /* Is there a drive number? */
+    if (vol <= 9 && p[1] == ':') {        /* Found a drive number, get and strip it */
+        p += 2; *path = p;                /* Return pointer to the path name */
+    } else {                            /* No drive number is given */
+#if _FS_RPATH
+        vol = CurrVol;                    /* Use current drive */
+#else
+        vol = 0;                        /* Use drive 0 */
+#endif
+    }
+
+    /* Check if the logical drive is valid or not */
+    if (vol >= _VOLUMES)                 /* Is the drive number valid? */
+        return FR_INVALID_DRIVE;
+    *rfs = fs = FatFs[vol];                /* Return pointer to the corresponding file system object */
+    if (!fs) return FR_NOT_ENABLED;        /* Is the file system object available? */
+
+    ENTER_FF(fs);                        /* Lock file system */
+
+    if (fs->fs_type) {                    /* If the logical drive has been mounted */
+        stat = disk_status(fs->drv);
+        if (!(stat & STA_NOINIT)) {        /* and the physical drive is kept initialized (has not been changed), */
+#if !_FS_READONLY
+            if (chk_wp && (stat & STA_PROTECT))    /* Check write protection if needed */
+                return FR_WRITE_PROTECTED;
+#endif
+            return FR_OK;                /* The file system object is valid */
+        }
+    }
+
+    /* The logical drive must be mounted. */
+    /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */
+
+    fs->fs_type = 0;                    /* Clear the file system object */
+    fs->drv = (BYTE)LD2PD(vol);            /* Bind the logical drive and a physical drive */
+    stat = disk_initialize(fs->drv);    /* Initialize low level disk I/O layer */
+    if (stat & STA_NOINIT)                /* Check if the initialization succeeded */
+        return FR_NOT_READY;            /* Failed to initialize due to no media or hard error */
+#if _MAX_SS != 512                        /* Get disk sector size (variable sector size cfg only) */
+    if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
+        return FR_DISK_ERR;
+#endif
+#if !_FS_READONLY
+    if (chk_wp && (stat & STA_PROTECT))    /* Check disk write protection if needed */
+        return FR_WRITE_PROTECTED;
+#endif
+    /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */
+    fmt = check_fs(fs, bsect = 0);        /* Check sector 0 if it is a VBR */
+    if (fmt == 1) {                        /* Not an FAT-VBR, the disk may be partitioned */
+        /* Check the partition listed in top of the partition table */
+        tbl = &fs->win[MBR_Table + LD2PT(vol) * 16];    /* Partition table */
+        if (tbl[4]) {                                    /* Is the partition existing? */
+            bsect = LD_DWORD(&tbl[8]);                    /* Partition offset in LBA */
+            fmt = check_fs(fs, bsect);                    /* Check the partition */
+        }
+    }
+    if (fmt == 3) return FR_DISK_ERR;
+    if (fmt) return FR_NO_FILESYSTEM;                    /* No FAT volume is found */
+
+    /* Following code initializes the file system object */
+
+    if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs))        /* (BPB_BytsPerSec must be equal to the physical sector size) */
+        return FR_NO_FILESYSTEM;
+
+    fasize = LD_WORD(fs->win+BPB_FATSz16);                /* Number of sectors per FAT */
+    if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32);
+    fs->fsize = fasize;
+
+    fs->n_fats = b = fs->win[BPB_NumFATs];                /* Number of FAT copies */
+    if (b != 1 && b != 2) return FR_NO_FILESYSTEM;        /* (Must be 1 or 2) */
+    fasize *= b;                                        /* Number of sectors for FAT area */
+
+    fs->csize = b = fs->win[BPB_SecPerClus];            /* Number of sectors per cluster */
+    if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM;    /* (Must be power of 2) */
+
+    fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt);    /* Number of root directory entries */
+    if (fs->n_rootdir % (SS(fs) / 32)) return FR_NO_FILESYSTEM;    /* (BPB_RootEntCnt must be sector aligned) */
+
+    tsect = LD_WORD(fs->win+BPB_TotSec16);                /* Number of sectors on the volume */
+    if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32);
+
+    nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt);                /* Number of reserved sectors */
+    if (!nrsv) return FR_NO_FILESYSTEM;                    /* (BPB_RsvdSecCnt must not be 0) */
+
+    /* Determine the FAT sub type */
+    sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / 32);    /* RSV+FAT+DIR */
+    if (tsect < sysect) return FR_NO_FILESYSTEM;        /* (Invalid volume size) */
+    nclst = (tsect - sysect) / fs->csize;                /* Number of clusters */
+    if (!nclst) return FR_NO_FILESYSTEM;                /* (Invalid volume size) */
+    fmt = FS_FAT12;
+    if (nclst >= MIN_FAT16) fmt = FS_FAT16;
+    if (nclst >= MIN_FAT32) fmt = FS_FAT32;
+
+    /* Boundaries and Limits */
+    fs->n_fatent = nclst + 2;                            /* Number of FAT entries */
+    fs->database = bsect + sysect;                        /* Data start sector */
+    fs->fatbase = bsect + nrsv;                         /* FAT start sector */
+    if (fmt == FS_FAT32) {
+        if (fs->n_rootdir) return FR_NO_FILESYSTEM;        /* (BPB_RootEntCnt must be 0) */
+        fs->dirbase = LD_DWORD(fs->win+BPB_RootClus);    /* Root directory start cluster */
+        szbfat = fs->n_fatent * 4;                        /* (Required FAT size) */
+    } else {
+        if (!fs->n_rootdir)    return FR_NO_FILESYSTEM;    /* (BPB_RootEntCnt must not be 0) */
+        fs->dirbase = fs->fatbase + fasize;                /* Root directory start sector */
+        szbfat = (fmt == FS_FAT16) ?                    /* (Required FAT size) */
+            fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
+    }
+    if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))    /* (FAT size must not be less than FAT sectors */
+        return FR_NO_FILESYSTEM;
+
+#if !_FS_READONLY
+    /* Initialize cluster allocation information */
+    fs->free_clust = 0xFFFFFFFF;
+    fs->last_clust = 0;
+
+    /* Get fsinfo if available */
+    if (fmt == FS_FAT32) {
+         fs->fsi_flag = 0;
+        fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo);
+        if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK &&
+            LD_WORD(fs->win+BS_55AA) == 0xAA55 &&
+            LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 &&
+            LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) {
+                fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free);
+                fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count);
+        }
+    }
+#endif
+    fs->fs_type = fmt;        /* FAT sub-type */
+    fs->id = ++Fsid;        /* File system mount ID */
+    fs->winsect = 0;        /* Invalidate sector cache */
+    fs->wflag = 0;
+#if _FS_RPATH
+    fs->cdir = 0;            /* Current directory (root dir) */
+#endif
+#if _FS_SHARE                /* Clear file lock semaphores */
+    clear_lock(fs);
+#endif
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Check if the file/dir object is valid or not                          */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT validate (    /* FR_OK(0): The object is valid, !=0: Invalid */
+    FATFS *fs,        /* Pointer to the file system object */
+    WORD id            /* Member id of the target object to be checked */
+)
+{
+    if (!fs || !fs->fs_type || fs->id != id)
+        return FR_INVALID_OBJECT;
+
+    ENTER_FF(fs);        /* Lock file system */
+
+    if (disk_status(fs->drv) & STA_NOINIT)
+        return FR_NOT_READY;
+
+    return FR_OK;
+}
+
+
+
+
+/*--------------------------------------------------------------------------
+
+   Public Functions
+
+--------------------------------------------------------------------------*/
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Mount/Unmount a Logical Drive                                         */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_mount (
+    BYTE vol,        /* Logical drive number to be mounted/unmounted */
+    FATFS *fs        /* Pointer to new file system object (NULL for unmount)*/
+)
+{
+    FATFS *rfs;
+
+
+    if (vol >= _VOLUMES)            /* Check if the drive number is valid */
+        return FR_INVALID_DRIVE;
+    rfs = FatFs[vol];                /* Get current fs object */
+
+    if (rfs) {
+#if _FS_SHARE
+        clear_lock(rfs);
+#endif
+#if _FS_REENTRANT                    /* Discard sync object of the current volume */
+        if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
+#endif
+        rfs->fs_type = 0;            /* Clear old fs object */
+    }
+
+    if (fs) {
+        fs->fs_type = 0;            /* Clear new fs object */
+#if _FS_REENTRANT                    /* Create sync object for the new volume */
+        if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
+#endif
+    }
+    FatFs[vol] = fs;                /* Register new fs object */
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Open or Create a File                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_open (
+    FIL *fp,            /* Pointer to the blank file object */
+    const TCHAR *path,    /* Pointer to the file name */
+    BYTE mode            /* Access mode and file open mode flags */
+)
+{
+    FRESULT res;
+    DIR dj;
+    BYTE *dir;
+    DEF_NAMEBUF;
+
+
+    fp->fs = 0;            /* Clear file object */
+
+#if !_FS_READONLY
+    mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
+    res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ));
+#else
+    mode &= FA_READ;
+    res = chk_mounted(&path, &dj.fs, 0);
+#endif
+    INIT_BUF(dj);
+    if (res == FR_OK)
+        res = follow_path(&dj, path);    /* Follow the file path */
+    dir = dj.dir;
+
+#if !_FS_READONLY    /* R/W configuration */
+    if (res == FR_OK) {
+        if (!dir)    /* Current dir itself */
+            res = FR_INVALID_NAME;
+#if _FS_SHARE
+        else
+            res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+#endif
+    }
+    /* Create or Open a file */
+    if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
+        DWORD dw, cl;
+
+        if (res != FR_OK) {                    /* No file, create new */
+            if (res == FR_NO_FILE)            /* There is no file to open, create a new entry */
+#if _FS_SHARE
+                res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
+#else
+                res = dir_register(&dj);
+#endif
+            mode |= FA_CREATE_ALWAYS;        /* File is created */
+            dir = dj.dir;                    /* New entry */
+        }
+        else {                                /* Any object is already existing */
+            if (mode & FA_CREATE_NEW) {        /* Cannot create new */
+                res = FR_EXIST;
+            } else {
+                if (dir[DIR_Attr] & (AM_RDO | AM_DIR))    /* Cannot overwrite it (R/O or DIR) */
+                    res = FR_DENIED;
+            }
+        }
+        if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {    /* Truncate it if overwrite mode */
+            dw = get_fattime();                    /* Created time */
+            ST_DWORD(dir+DIR_CrtTime, dw);
+            dir[DIR_Attr] = 0;                    /* Reset attribute */
+            ST_DWORD(dir+DIR_FileSize, 0);        /* size = 0 */
+            cl = LD_CLUST(dir);                    /* Get start cluster */
+            ST_CLUST(dir, 0);                    /* cluster = 0 */
+            dj.fs->wflag = 1;
+            if (cl) {                            /* Remove the cluster chain if exist */
+                dw = dj.fs->winsect;
+                res = remove_chain(dj.fs, cl);
+                if (res == FR_OK) {
+                    dj.fs->last_clust = cl - 1;    /* Reuse the cluster hole */
+                    res = move_window(dj.fs, dw);
+                }
+            }
+        }
+    }
+    else {    /* Open an existing file */
+        if (res == FR_OK) {                        /* Follow succeeded */
+            if (dir[DIR_Attr] & AM_DIR) {        /* It is a directory */
+                res = FR_NO_FILE;
+            } else {
+                if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
+                    res = FR_DENIED;
+            }
+        }
+    }
+    if (res == FR_OK) {
+        if (mode & FA_CREATE_ALWAYS)            /* Set file change flag if created or overwritten */
+            mode |= FA__WRITTEN;
+        fp->dir_sect = dj.fs->winsect;            /* Pointer to the directory entry */
+        fp->dir_ptr = dir;
+#if _FS_SHARE
+        fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+        if (!fp->lockid) res = FR_INT_ERR;
+#endif
+    }
+
+#else                /* R/O configuration */
+    if (res == FR_OK) {                    /* Follow succeeded */
+        if (!dir) {                        /* Current dir itself */
+            res = FR_INVALID_NAME;
+        } else {
+            if (dir[DIR_Attr] & AM_DIR)    /* It is a directory */
+                res = FR_NO_FILE;
+        }
+    }
+#endif
+    FREE_BUF();
+
+    if (res == FR_OK) {
+        fp->flag = mode;                    /* File access mode */
+        fp->org_clust =    LD_CLUST(dir);        /* File start cluster */
+        fp->fsize = LD_DWORD(dir+DIR_FileSize);    /* File size */
+        fp->fptr = 0;                        /* File pointer */
+        fp->dsect = 0;
+#if _USE_FASTSEEK
+        fp->cltbl = 0;                        /* No cluster link map table */
+#endif
+        fp->fs = dj.fs; fp->id = dj.fs->id;    /* Validate file object */
+    }
+
+    LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read File                                                             */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_read (
+    FIL *fp,         /* Pointer to the file object */
+    void *buff,        /* Pointer to data buffer */
+    UINT btr,        /* Number of bytes to read */
+    UINT *br        /* Pointer to number of bytes read */
+)
+{
+    FRESULT res;
+    DWORD clst, sect, remain;
+    UINT rcnt, cc;
+    BYTE csect, *rbuff = (BYTE *)buff;
+
+
+    *br = 0;    /* Initialize byte counter */
+
+    res = validate(fp->fs, fp->id);                    /* Check validity of the object */
+    if (res != FR_OK) LEAVE_FF(fp->fs, res);
+    if (fp->flag & FA__ERROR)                        /* Check abort flag */
+        LEAVE_FF(fp->fs, FR_INT_ERR);
+    if (!(fp->flag & FA_READ))                         /* Check access mode */
+        LEAVE_FF(fp->fs, FR_DENIED);
+    remain = fp->fsize - fp->fptr;
+    if (btr > remain) btr = (UINT)remain;            /* Truncate btr by remaining bytes */
+
+    for ( ;  btr;                                    /* Repeat until all data transferred */
+        rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
+        if ((fp->fptr % SS(fp->fs)) == 0) {            /* On the sector boundary? */
+            csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1));    /* Sector offset in the cluster */
+            if (!csect) {                            /* On the cluster boundary? */
+                clst = (fp->fptr == 0) ?            /* On the top of the file? */
+                    fp->org_clust : get_fat(fp->fs, fp->curr_clust);
+                if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
+                if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+                fp->curr_clust = clst;                /* Update current cluster */
+            }
+            sect = clust2sect(fp->fs, fp->curr_clust);    /* Get current sector */
+            if (!sect) ABORT(fp->fs, FR_INT_ERR);
+            sect += csect;
+            cc = btr / SS(fp->fs);                    /* When remaining bytes >= sector size, */
+            if (cc) {                                /* Read maximum contiguous sectors directly */
+                if (csect + cc > fp->fs->csize)        /* Clip at cluster boundary */
+                    cc = fp->fs->csize - csect;
+                if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
+                    ABORT(fp->fs, FR_DISK_ERR);
+#if !_FS_READONLY && _FS_MINIMIZE <= 2                /* Replace one of the read sectors with cached data if it contains a dirty sector */
+#if _FS_TINY
+                if (fp->fs->wflag && fp->fs->winsect - sect < cc)
+                    mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
+#else
+                if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
+                    mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs));
+#endif
+#endif
+                rcnt = SS(fp->fs) * cc;                /* Number of bytes transferred */
+                continue;
+            }
+#if !_FS_TINY
+#if !_FS_READONLY
+            if (fp->flag & FA__DIRTY) {                /* Write sector I/O buffer if needed */
+                if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+                    ABORT(fp->fs, FR_DISK_ERR);
+                fp->flag &= ~FA__DIRTY;
+            }
+#endif
+            if (fp->dsect != sect) {                /* Fill sector buffer with file data */
+                if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
+                    ABORT(fp->fs, FR_DISK_ERR);
+            }
+#endif
+            fp->dsect = sect;
+        }
+        rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));    /* Get partial sector data from sector buffer */
+        if (rcnt > btr) rcnt = btr;
+#if _FS_TINY
+        if (move_window(fp->fs, fp->dsect))            /* Move sector window */
+            ABORT(fp->fs, FR_DISK_ERR);
+        mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt);    /* Pick partial sector */
+#else
+        mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt);    /* Pick partial sector */
+#endif
+    }
+
+    LEAVE_FF(fp->fs, FR_OK);
+}
+
+
+
+
+#if !_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Write File                                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_write (
+    FIL *fp,            /* Pointer to the file object */
+    const void *buff,    /* Pointer to the data to be written */
+    UINT btw,            /* Number of bytes to write */
+    UINT *bw            /* Pointer to number of bytes written */
+)
+{
+    FRESULT res;
+    DWORD clst, sect;
+    UINT wcnt, cc;
+    const BYTE *wbuff = (const BYTE *)buff;
+    BYTE csect;
+
+
+    *bw = 0;    /* Initialize byte counter */
+
+    res = validate(fp->fs, fp->id);                    /* Check validity of the object */
+    if (res != FR_OK) LEAVE_FF(fp->fs, res);
+    if (fp->flag & FA__ERROR)                        /* Check abort flag */
+        LEAVE_FF(fp->fs, FR_INT_ERR);
+    if (!(fp->flag & FA_WRITE))                        /* Check access mode */
+        LEAVE_FF(fp->fs, FR_DENIED);
+    if (fp->fsize + btw < fp->fsize) btw = 0;        /* File size cannot reach 4GB */
+
+    for ( ;  btw;                                    /* Repeat until all data transferred */
+        wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
+        if ((fp->fptr % SS(fp->fs)) == 0) {            /* On the sector boundary? */
+            csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1));    /* Sector offset in the cluster */
+            if (!csect) {                            /* On the cluster boundary? */
+                if (fp->fptr == 0) {                /* On the top of the file? */
+                    clst = fp->org_clust;            /* Follow from the origin */
+                    if (clst == 0)                    /* When there is no cluster chain, */
+                        fp->org_clust = clst = create_chain(fp->fs, 0);    /* Create a new cluster chain */
+                } else {                            /* Middle or end of the file */
+                    clst = create_chain(fp->fs, fp->curr_clust);            /* Follow or stretch cluster chain */
+                }
+                if (clst == 0) break;                /* Could not allocate a new cluster (disk full) */
+                if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
+                if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+                fp->curr_clust = clst;                /* Update current cluster */
+            }
+#if _FS_TINY
+            if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0))    /* Write back data buffer prior to following direct transfer */
+                ABORT(fp->fs, FR_DISK_ERR);
+#else
+            if (fp->flag & FA__DIRTY) {        /* Write back data buffer prior to following direct transfer */
+                if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+                    ABORT(fp->fs, FR_DISK_ERR);
+                fp->flag &= ~FA__DIRTY;
+            }
+#endif
+            sect = clust2sect(fp->fs, fp->curr_clust);    /* Get current sector */
+            if (!sect) ABORT(fp->fs, FR_INT_ERR);
+            sect += csect;
+            cc = btw / SS(fp->fs);                    /* When remaining bytes >= sector size, */
+            if (cc) {                                /* Write maximum contiguous sectors directly */
+                if (csect + cc > fp->fs->csize)        /* Clip at cluster boundary */
+                    cc = fp->fs->csize - csect;
+                if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK)
+                    ABORT(fp->fs, FR_DISK_ERR);
+#if _FS_TINY
+                if (fp->fs->winsect - sect < cc) {    /* Refill sector cache if it gets dirty by the direct write */
+                    mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
+                    fp->fs->wflag = 0;
+                }
+#else
+                if (fp->dsect - sect < cc) {        /* Refill sector cache if it gets dirty by the direct write */
+                    mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
+                    fp->flag &= ~FA__DIRTY;
+                }
+#endif
+                wcnt = SS(fp->fs) * cc;                /* Number of bytes transferred */
+                continue;
+            }
+#if _FS_TINY
+            if (fp->fptr >= fp->fsize) {            /* Avoid silly buffer filling at growing edge */
+                if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR);
+                fp->fs->winsect = sect;
+            }
+#else
+            if (fp->dsect != sect) {                /* Fill sector buffer with file data */
+                if (fp->fptr < fp->fsize &&
+                    disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
+                        ABORT(fp->fs, FR_DISK_ERR);
+            }
+#endif
+            fp->dsect = sect;
+        }
+        wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
+        if (wcnt > btw) wcnt = btw;
+#if _FS_TINY
+        if (move_window(fp->fs, fp->dsect))            /* Move sector window */
+            ABORT(fp->fs, FR_DISK_ERR);
+        mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt);    /* Fit partial sector */
+        fp->fs->wflag = 1;
+#else
+        mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt);    /* Fit partial sector */
+        fp->flag |= FA__DIRTY;
+#endif
+    }
+
+    if (fp->fptr > fp->fsize) fp->fsize = fp->fptr;    /* Update file size if needed */
+    fp->flag |= FA__WRITTEN;                        /* Set file change flag */
+
+    LEAVE_FF(fp->fs, FR_OK);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Synchronize the File Object                                           */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_sync (
+    FIL *fp        /* Pointer to the file object */
+)
+{
+    FRESULT res;
+    DWORD tim;
+    BYTE *dir;
+
+
+    res = validate(fp->fs, fp->id);        /* Check validity of the object */
+    if (res == FR_OK) {
+        if (fp->flag & FA__WRITTEN) {    /* Has the file been written? */
+#if !_FS_TINY    /* Write-back dirty buffer */
+            if (fp->flag & FA__DIRTY) {
+                if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+                    LEAVE_FF(fp->fs, FR_DISK_ERR);
+                fp->flag &= ~FA__DIRTY;
+            }
+#endif
+            /* Update the directory entry */
+            res = move_window(fp->fs, fp->dir_sect);
+            if (res == FR_OK) {
+                dir = fp->dir_ptr;
+                dir[DIR_Attr] |= AM_ARC;                    /* Set archive bit */
+                ST_DWORD(dir+DIR_FileSize, fp->fsize);        /* Update file size */
+                ST_CLUST(dir, fp->org_clust);                /* Update start cluster */
+                tim = get_fattime();                        /* Update updated time */
+                ST_DWORD(dir+DIR_WrtTime, tim);
+                fp->flag &= ~FA__WRITTEN;
+                fp->fs->wflag = 1;
+                res = sync(fp->fs);
+            }
+        }
+    }
+
+    LEAVE_FF(fp->fs, res);
+}
+
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Close File                                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_close (
+    FIL *fp        /* Pointer to the file object to be closed */
+)
+{
+    FRESULT res;
+
+#if _FS_READONLY
+    FATFS *fs = fp->fs;
+    res = validate(fs, fp->id);
+    if (res == FR_OK) fp->fs = 0;    /* Discard file object */
+    LEAVE_FF(fs, res);
+
+#else
+    res = f_sync(fp);        /* Flush cached data */
+#if _FS_SHARE
+    if (res == FR_OK) {        /* Decrement open counter */
+#if _FS_REENTRANT
+        res = validate(fp->fs, fp->id);
+        if (res == FR_OK) {
+            res = dec_lock(fp->lockid);    
+            unlock_fs(fp->fs, FR_OK);
+        }
+#else
+        res = dec_lock(fp->lockid);
+#endif
+    }
+#endif
+    if (res == FR_OK) fp->fs = 0;    /* Discard file object */
+    return res;
+#endif
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Current Drive/Directory Handlings                                     */
+/*-----------------------------------------------------------------------*/
+
+#if _FS_RPATH >= 1
+
+FRESULT f_chdrive (
+    BYTE drv        /* Drive number */
+)
+{
+    if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
+
+    CurrVol = drv;
+
+    return FR_OK;
+}
+
+
+
+FRESULT f_chdir (
+    const TCHAR *path    /* Pointer to the directory path */
+)
+{
+    FRESULT res;
+    DIR dj;
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path, &dj.fs, 0);
+    if (res == FR_OK) {
+        INIT_BUF(dj);
+        res = follow_path(&dj, path);        /* Follow the path */
+        FREE_BUF();
+        if (res == FR_OK) {                    /* Follow completed */
+            if (!dj.dir) {
+                dj.fs->cdir = dj.sclust;    /* Start directory itself */
+            } else {
+                if (dj.dir[DIR_Attr] & AM_DIR)    /* Reached to the directory */
+                    dj.fs->cdir = LD_CLUST(dj.dir);
+                else
+                    res = FR_NO_PATH;        /* Reached but a file */
+            }
+        }
+        if (res == FR_NO_FILE) res = FR_NO_PATH;
+    }
+
+    LEAVE_FF(dj.fs, res);
+}
+
+
+#if _FS_RPATH >= 2
+FRESULT f_getcwd (
+    TCHAR *path,    /* Pointer to the directory path */
+    UINT sz_path    /* Size of path */
+)
+{
+    FRESULT res;
+    DIR dj;
+    UINT i, n;
+    DWORD ccl;
+    TCHAR *tp;
+    FILINFO fno;
+    DEF_NAMEBUF;
+
+
+    *path = 0;
+    res = chk_mounted((const TCHAR**)&path, &dj.fs, 0);    /* Get current volume */
+    if (res == FR_OK) {
+        INIT_BUF(dj);
+        i = sz_path;        /* Bottom of buffer (dir stack base) */
+        dj.sclust = dj.fs->cdir;            /* Start to follow upper dir from current dir */
+        while ((ccl = dj.sclust) != 0) {    /* Repeat while current dir is a sub-dir */
+            res = dir_sdi(&dj, 1);            /* Get parent dir */
+            if (res != FR_OK) break;
+            res = dir_read(&dj);
+            if (res != FR_OK) break;
+            dj.sclust = LD_CLUST(dj.dir);    /* Goto parent dir */
+            res = dir_sdi(&dj, 0);
+            if (res != FR_OK) break;
+            do {                            /* Find the entry links to the child dir */
+                res = dir_read(&dj);
+                if (res != FR_OK) break;
+                if (ccl == LD_CLUST(dj.dir)) break;    /* Found the entry */
+                res = dir_next(&dj, 0);    
+            } while (res == FR_OK);
+            if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
+            if (res != FR_OK) break;
+#if _USE_LFN
+            fno.lfname = path;
+            fno.lfsize = i;
+#endif
+            get_fileinfo(&dj, &fno);        /* Get the dir name and push it to the buffer */
+            tp = fno.fname;
+            if (_USE_LFN && *path) tp = path;
+            for (n = 0; tp[n]; n++) ;
+            if (i < n + 3) {
+                res = FR_NOT_ENOUGH_CORE; break;
+            }
+            while (n) path[--i] = tp[--n];
+            path[--i] = '/';
+        }
+        tp = path;
+        if (res == FR_OK) {
+            *tp++ = '0' + CurrVol;            /* Put drive number */
+            *tp++ = ':';
+            if (i == sz_path) {                /* Root-dir */
+                *tp++ = '/';
+            } else {                        /* Sub-dir */
+                do        /* Add stacked path str */
+                    *tp++ = path[i++];
+                while (i < sz_path);
+            }
+        }
+        *tp = 0;
+        FREE_BUF();
+    }
+
+    LEAVE_FF(dj.fs, res);
+}
+#endif /* _FS_RPATH >= 2 */
+#endif /* _FS_RPATH >= 1 */
+
+
+
+#if _FS_MINIMIZE <= 2
+/*-----------------------------------------------------------------------*/
+/* Seek File R/W Pointer                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_lseek (
+    FIL *fp,        /* Pointer to the file object */
+    DWORD ofs        /* File pointer from top of file */
+)
+{
+    FRESULT res;
+
+
+    res = validate(fp->fs, fp->id);        /* Check validity of the object */
+    if (res != FR_OK) LEAVE_FF(fp->fs, res);
+    if (fp->flag & FA__ERROR)            /* Check abort flag */
+        LEAVE_FF(fp->fs, FR_INT_ERR);
+
+#if _USE_FASTSEEK
+    if (fp->cltbl) {    /* Fast seek */
+        DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl;
+        BYTE csc;
+
+        tlen = *tbl++;
+        if (ofs == CREATE_LINKMAP) {    /* Create link map table */
+            cl = fp->org_clust;
+            if (cl) {
+                do {
+                    if (tlen < 4) {    /* Not enough table items */
+                        res = FR_NOT_ENOUGH_CORE; break;
+                    }
+                    tcl = cl; ncl = 0;
+                    do {        /* Get a fragment and store the top and length */
+                        pcl = cl; ncl++;
+                        cl = get_fat(fp->fs, cl);
+                        if (cl <= 1) ABORT(fp->fs, FR_INT_ERR);
+                        if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+                    } while (cl == pcl + 1);
+                    *tbl++ = ncl; *tbl++ = tcl;
+                    tlen -= 2;
+                } while (cl < fp->fs->n_fatent);
+            }
+            *tbl = 0;    /* Terminate table */
+
+        } else {                        /* Fast seek */
+            if (ofs > fp->fsize)        /* Clip offset at the file size */
+                ofs = fp->fsize;
+            fp->fptr = ofs;                /* Set file pointer */
+            if (ofs) {
+                dsc = (ofs - 1) / SS(fp->fs);
+                cl = dsc / fp->fs->csize;
+                for (;;) {
+                    ncl = *tbl++;
+                    if (!ncl) ABORT(fp->fs, FR_INT_ERR);
+                    if (cl < ncl) break;
+                    cl -= ncl; tbl++;
+                }
+                fp->curr_clust = cl + *tbl;
+                csc = (BYTE)(dsc & (fp->fs->csize - 1));
+                dsc = clust2sect(fp->fs, fp->curr_clust);
+                if (!dsc) ABORT(fp->fs, FR_INT_ERR);
+                dsc += csc;
+                if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) {
+#if !_FS_TINY
+#if !_FS_READONLY
+                    if (fp->flag & FA__DIRTY) {        /* Flush dirty buffer if needed */
+                        if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+                            ABORT(fp->fs, FR_DISK_ERR);
+                        fp->flag &= ~FA__DIRTY;
+                    }
+#endif
+                    if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK)
+                        ABORT(fp->fs, FR_DISK_ERR);
+#endif
+                    fp->dsect = dsc;
+                }
+            }
+        }
+    } else
+#endif
+
+    /* Normal Seek */
+    {
+        DWORD clst, bcs, nsect, ifptr;
+
+        if (ofs > fp->fsize                    /* In read-only mode, clip offset with the file size */
+#if !_FS_READONLY
+             && !(fp->flag & FA_WRITE)
+#endif
+            ) ofs = fp->fsize;
+
+        ifptr = fp->fptr;
+        fp->fptr = nsect = 0;
+        if (ofs) {
+            bcs = (DWORD)fp->fs->csize * SS(fp->fs);    /* Cluster size (byte) */
+            if (ifptr > 0 &&
+                (ofs - 1) / bcs >= (ifptr - 1) / bcs) {    /* When seek to same or following cluster, */
+                fp->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */
+                ofs -= fp->fptr;
+                clst = fp->curr_clust;
+            } else {                                    /* When seek to back cluster, */
+                clst = fp->org_clust;                    /* start from the first cluster */
+#if !_FS_READONLY
+                if (clst == 0) {                        /* If no cluster chain, create a new chain */
+                    clst = create_chain(fp->fs, 0);
+                    if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
+                    if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+                    fp->org_clust = clst;
+                }
+#endif
+                fp->curr_clust = clst;
+            }
+            if (clst != 0) {
+                while (ofs > bcs) {                        /* Cluster following loop */
+#if !_FS_READONLY
+                    if (fp->flag & FA_WRITE) {            /* Check if in write mode or not */
+                        clst = create_chain(fp->fs, clst);    /* Force stretch if in write mode */
+                        if (clst == 0) {                /* When disk gets full, clip file size */
+                            ofs = bcs; break;
+                        }
+                    } else
+#endif
+                        clst = get_fat(fp->fs, clst);    /* Follow cluster chain if not in write mode */
+                    if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+                    if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
+                    fp->curr_clust = clst;
+                    fp->fptr += bcs;
+                    ofs -= bcs;
+                }
+                fp->fptr += ofs;
+                if (ofs % SS(fp->fs)) {
+                    nsect = clust2sect(fp->fs, clst);    /* Current sector */
+                    if (!nsect) ABORT(fp->fs, FR_INT_ERR);
+                    nsect += ofs / SS(fp->fs);
+                }
+            }
+        }
+        if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) {
+#if !_FS_TINY
+#if !_FS_READONLY
+            if (fp->flag & FA__DIRTY) {            /* Flush dirty buffer if needed */
+                if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+                    ABORT(fp->fs, FR_DISK_ERR);
+                fp->flag &= ~FA__DIRTY;
+            }
+#endif
+            if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK)
+                ABORT(fp->fs, FR_DISK_ERR);
+#endif
+            fp->dsect = nsect;
+        }
+#if !_FS_READONLY
+        if (fp->fptr > fp->fsize) {            /* Set change flag if the file size is extended */
+            fp->fsize = fp->fptr;
+            fp->flag |= FA__WRITTEN;
+        }
+#endif
+    }
+
+    LEAVE_FF(fp->fs, res);
+}
+
+
+
+#if _FS_MINIMIZE <= 1
+/*-----------------------------------------------------------------------*/
+/* Create a Directroy Object                                             */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_opendir (
+    DIR *dj,            /* Pointer to directory object to create */
+    const TCHAR *path    /* Pointer to the directory path */
+)
+{
+    FRESULT res;
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path, &dj->fs, 0);
+    if (res == FR_OK) {
+        INIT_BUF(*dj);
+        res = follow_path(dj, path);            /* Follow the path to the directory */
+        FREE_BUF();
+        if (res == FR_OK) {                        /* Follow completed */
+            if (dj->dir) {                        /* It is not the root dir */
+                if (dj->dir[DIR_Attr] & AM_DIR) {    /* The object is a directory */
+                    dj->sclust = LD_CLUST(dj->dir);
+                } else {                        /* The object is not a directory */
+                    res = FR_NO_PATH;
+                }
+            }
+            if (res == FR_OK) {
+                dj->id = dj->fs->id;
+                res = dir_sdi(dj, 0);            /* Rewind dir */
+            }
+        }
+        if (res == FR_NO_FILE) res = FR_NO_PATH;
+    }
+
+    LEAVE_FF(dj->fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Directory Entry in Sequense                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_readdir (
+    DIR *dj,            /* Pointer to the open directory object */
+    FILINFO *fno        /* Pointer to file information to return */
+)
+{
+    FRESULT res;
+    DEF_NAMEBUF;
+
+
+    res = validate(dj->fs, dj->id);            /* Check validity of the object */
+    if (res == FR_OK) {
+        if (!fno) {
+            res = dir_sdi(dj, 0);            /* Rewind the directory object */
+        } else {
+            INIT_BUF(*dj);
+            res = dir_read(dj);                /* Read an directory item */
+            if (res == FR_NO_FILE) {        /* Reached end of dir */
+                dj->sect = 0;
+                res = FR_OK;
+            }
+            if (res == FR_OK) {                /* A valid entry is found */
+                get_fileinfo(dj, fno);        /* Get the object information */
+                res = dir_next(dj, 0);        /* Increment index for next */
+                if (res == FR_NO_FILE) {
+                    dj->sect = 0;
+                    res = FR_OK;
+                }
+            }
+            FREE_BUF();
+        }
+    }
+
+    LEAVE_FF(dj->fs, res);
+}
+
+
+
+#if _FS_MINIMIZE == 0
+/*-----------------------------------------------------------------------*/
+/* Get File Status                                                       */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_stat (
+    const TCHAR *path,    /* Pointer to the file path */
+    FILINFO *fno        /* Pointer to file information to return */
+)
+{
+    FRESULT res;
+    DIR dj;
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path, &dj.fs, 0);
+    if (res == FR_OK) {
+        INIT_BUF(dj);
+        res = follow_path(&dj, path);    /* Follow the file path */
+        if (res == FR_OK) {                /* Follow completed */
+            if (dj.dir)        /* Found an object */
+                get_fileinfo(&dj, fno);
+            else            /* It is root dir */
+                res = FR_INVALID_NAME;
+        }
+        FREE_BUF();
+    }
+
+    LEAVE_FF(dj.fs, res);
+}
+
+
+
+#if !_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Get Number of Free Clusters                                           */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_getfree (
+    const TCHAR *path,    /* Pointer to the logical drive number (root dir) */
+    DWORD *nclst,        /* Pointer to the variable to return number of free clusters */
+    FATFS **fatfs        /* Pointer to pointer to corresponding file system object to return */
+)
+{
+    FRESULT res;
+    DWORD n, clst, sect, stat;
+    UINT i;
+    BYTE fat, *p;
+
+
+    /* Get drive number */
+    res = chk_mounted(&path, fatfs, 0);
+    if (res == FR_OK) {
+        /* If free_clust is valid, return it without full cluster scan */
+        if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) {
+            *nclst = (*fatfs)->free_clust;
+        } else {
+            /* Get number of free clusters */
+            fat = (*fatfs)->fs_type;
+            n = 0;
+            if (fat == FS_FAT12) {
+                clst = 2;
+                do {
+                    stat = get_fat(*fatfs, clst);
+                    if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
+                    if (stat == 1) { res = FR_INT_ERR; break; }
+                    if (stat == 0) n++;
+                } while (++clst < (*fatfs)->n_fatent);
+            } else {
+                clst = (*fatfs)->n_fatent;
+                sect = (*fatfs)->fatbase;
+                i = 0; p = 0;
+                do {
+                    if (!i) {
+                        res = move_window(*fatfs, sect++);
+                        if (res != FR_OK) break;
+                        p = (*fatfs)->win;
+                        i = SS(*fatfs);
+                    }
+                    if (fat == FS_FAT16) {
+                        if (LD_WORD(p) == 0) n++;
+                        p += 2; i -= 2;
+                    } else {
+                        if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++;
+                        p += 4; i -= 4;
+                    }
+                } while (--clst);
+            }
+            (*fatfs)->free_clust = n;
+            if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
+            *nclst = n;
+        }
+    }
+    LEAVE_FF(*fatfs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Truncate File                                                         */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_truncate (
+    FIL *fp        /* Pointer to the file object */
+)
+{
+    FRESULT res;
+    DWORD ncl;
+
+
+    res = validate(fp->fs, fp->id);        /* Check validity of the object */
+    if (res == FR_OK) {
+        if (fp->flag & FA__ERROR) {            /* Check abort flag */
+            res = FR_INT_ERR;
+        } else {
+            if (!(fp->flag & FA_WRITE))        /* Check access mode */
+                res = FR_DENIED;
+        }
+    }
+    if (res == FR_OK) {
+        if (fp->fsize > fp->fptr) {
+            fp->fsize = fp->fptr;    /* Set file size to current R/W point */
+            fp->flag |= FA__WRITTEN;
+            if (fp->fptr == 0) {    /* When set file size to zero, remove entire cluster chain */
+                res = remove_chain(fp->fs, fp->org_clust);
+                fp->org_clust = 0;
+            } else {                /* When truncate a part of the file, remove remaining clusters */
+                ncl = get_fat(fp->fs, fp->curr_clust);
+                res = FR_OK;
+                if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
+                if (ncl == 1) res = FR_INT_ERR;
+                if (res == FR_OK && ncl < fp->fs->n_fatent) {
+                    res = put_fat(fp->fs, fp->curr_clust, 0x0FFFFFFF);
+                    if (res == FR_OK) res = remove_chain(fp->fs, ncl);
+                }
+            }
+        }
+        if (res != FR_OK) fp->flag |= FA__ERROR;
+    }
+
+    LEAVE_FF(fp->fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Delete a File or Directory                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_unlink (
+    const TCHAR *path        /* Pointer to the file or directory path */
+)
+{
+    FRESULT res;
+    DIR dj, sdj;
+    BYTE *dir;
+    DWORD dclst;
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path, &dj.fs, 1);
+    if (res == FR_OK) {
+        INIT_BUF(dj);
+        res = follow_path(&dj, path);        /* Follow the file path */
+        if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
+            res = FR_INVALID_NAME;            /* Cannot remove dot entry */
+#if _FS_SHARE
+        if (res == FR_OK) res = chk_lock(&dj, 2);    /* Cannot remove open file */
+#endif
+        if (res == FR_OK) {                    /* The object is accessible */
+            dir = dj.dir;
+            if (!dir) {
+                res = FR_INVALID_NAME;        /* Cannot remove the start directory */
+            } else {
+                if (dir[DIR_Attr] & AM_RDO)
+                    res = FR_DENIED;        /* Cannot remove R/O object */
+            }
+            dclst = LD_CLUST(dir);
+            if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) {    /* Is it a sub-dir? */
+                if (dclst < 2) {
+                    res = FR_INT_ERR;
+                } else {
+                    mem_cpy(&sdj, &dj, sizeof(DIR));    /* Check if the sub-dir is empty or not */
+                    sdj.sclust = dclst;
+                    res = dir_sdi(&sdj, 2);        /* Exclude dot entries */
+                    if (res == FR_OK) {
+                        res = dir_read(&sdj);
+                        if (res == FR_OK            /* Not empty dir */
+#if _FS_RPATH
+                        || dclst == sdj.fs->cdir    /* Current dir */
+#endif
+                        ) res = FR_DENIED;
+                        if (res == FR_NO_FILE) res = FR_OK;    /* Empty */
+                    }
+                }
+            }
+            if (res == FR_OK) {
+                res = dir_remove(&dj);        /* Remove the directory entry */
+                if (res == FR_OK) {
+                    if (dclst)                /* Remove the cluster chain if exist */
+                        res = remove_chain(dj.fs, dclst);
+                    if (res == FR_OK) res = sync(dj.fs);
+                }
+            }
+        }
+        FREE_BUF();
+    }
+    LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Create a Directory                                                    */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_mkdir (
+    const TCHAR *path        /* Pointer to the directory path */
+)
+{
+    FRESULT res;
+    DIR dj;
+    BYTE *dir, n;
+    DWORD dsc, dcl, pcl, tim = get_fattime();
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path, &dj.fs, 1);
+    if (res == FR_OK) {
+        INIT_BUF(dj);
+        res = follow_path(&dj, path);            /* Follow the file path */
+        if (res == FR_OK) res = FR_EXIST;        /* Any object with same name is already existing */
+        if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT))
+            res = FR_INVALID_NAME;
+        if (res == FR_NO_FILE) {                /* Can create a new directory */
+            dcl = create_chain(dj.fs, 0);        /* Allocate a cluster for the new directory table */
+            res = FR_OK;
+            if (dcl == 0) res = FR_DENIED;        /* No space to allocate a new cluster */
+            if (dcl == 1) res = FR_INT_ERR;
+            if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
+            if (res == FR_OK)                    /* Flush FAT */
+                res = move_window(dj.fs, 0);
+            if (res == FR_OK) {                    /* Initialize the new directory table */
+                dsc = clust2sect(dj.fs, dcl);
+                dir = dj.fs->win;
+                mem_set(dir, 0, SS(dj.fs));
+                mem_set(dir+DIR_Name, ' ', 8+3);    /* Create "." entry */
+                dir[DIR_Name] = '.';
+                dir[DIR_Attr] = AM_DIR;
+                ST_DWORD(dir+DIR_WrtTime, tim);
+                ST_CLUST(dir, dcl);
+                mem_cpy(dir+32, dir, 32);             /* Create ".." entry */
+                dir[33] = '.'; pcl = dj.sclust;
+                if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
+                    pcl = 0;
+                ST_CLUST(dir+32, pcl);
+                for (n = dj.fs->csize; n; n--) {    /* Write dot entries and clear following sectors */
+                    dj.fs->winsect = dsc++;
+                    dj.fs->wflag = 1;
+                    res = move_window(dj.fs, 0);
+                    if (res != FR_OK) break;
+                    mem_set(dir, 0, SS(dj.fs));
+                }
+            }
+            if (res == FR_OK) res = dir_register(&dj);    /* Register the object to the directoy */
+            if (res != FR_OK) {
+                remove_chain(dj.fs, dcl);            /* Could not register, remove cluster chain */
+            } else {
+                dir = dj.dir;
+                dir[DIR_Attr] = AM_DIR;                /* Attribute */
+                ST_DWORD(dir+DIR_WrtTime, tim);        /* Created time */
+                ST_CLUST(dir, dcl);                    /* Table start cluster */
+                dj.fs->wflag = 1;
+                res = sync(dj.fs);
+            }
+        }
+        FREE_BUF();
+    }
+
+    LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change Attribute                                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_chmod (
+    const TCHAR *path,    /* Pointer to the file path */
+    BYTE value,            /* Attribute bits */
+    BYTE mask            /* Attribute mask to change */
+)
+{
+    FRESULT res;
+    DIR dj;
+    BYTE *dir;
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path, &dj.fs, 1);
+    if (res == FR_OK) {
+        INIT_BUF(dj);
+        res = follow_path(&dj, path);        /* Follow the file path */
+        FREE_BUF();
+        if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
+            res = FR_INVALID_NAME;
+        if (res == FR_OK) {
+            dir = dj.dir;
+            if (!dir) {                        /* Is it a root directory? */
+                res = FR_INVALID_NAME;
+            } else {                        /* File or sub directory */
+                mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC;    /* Valid attribute mask */
+                dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask);    /* Apply attribute change */
+                dj.fs->wflag = 1;
+                res = sync(dj.fs);
+            }
+        }
+    }
+
+    LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change Timestamp                                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_utime (
+    const TCHAR *path,    /* Pointer to the file/directory name */
+    const FILINFO *fno    /* Pointer to the time stamp to be set */
+)
+{
+    FRESULT res;
+    DIR dj;
+    BYTE *dir;
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path, &dj.fs, 1);
+    if (res == FR_OK) {
+        INIT_BUF(dj);
+        res = follow_path(&dj, path);    /* Follow the file path */
+        FREE_BUF();
+        if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
+            res = FR_INVALID_NAME;
+        if (res == FR_OK) {
+            dir = dj.dir;
+            if (!dir) {                    /* Root directory */
+                res = FR_INVALID_NAME;
+            } else {                    /* File or sub-directory */
+                ST_WORD(dir+DIR_WrtTime, fno->ftime);
+                ST_WORD(dir+DIR_WrtDate, fno->fdate);
+                dj.fs->wflag = 1;
+                res = sync(dj.fs);
+            }
+        }
+    }
+
+    LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Rename File/Directory                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_rename (
+    const TCHAR *path_old,    /* Pointer to the old name */
+    const TCHAR *path_new    /* Pointer to the new name */
+)
+{
+    FRESULT res;
+    DIR djo, djn;
+    BYTE buf[21], *dir;
+    DWORD dw;
+    DEF_NAMEBUF;
+
+
+    res = chk_mounted(&path_old, &djo.fs, 1);
+    if (res == FR_OK) {
+        djn.fs = djo.fs;
+        INIT_BUF(djo);
+        res = follow_path(&djo, path_old);        /* Check old object */
+        if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
+            res = FR_INVALID_NAME;
+#if _FS_SHARE
+        if (res == FR_OK) res = chk_lock(&djo, 2);
+#endif
+        if (res == FR_OK) {                        /* Old object is found */
+            if (!djo.dir) {                        /* Is root dir? */
+                res = FR_NO_FILE;
+            } else {
+                mem_cpy(buf, djo.dir+DIR_Attr, 21);        /* Save the object information except for name */
+                mem_cpy(&djn, &djo, sizeof(DIR));        /* Check new object */
+                res = follow_path(&djn, path_new);
+                if (res == FR_OK) res = FR_EXIST;        /* The new object name is already existing */
+                if (res == FR_NO_FILE) {                 /* Is it a valid path and no name collision? */
+/* Start critical section that any interruption or error can cause cross-link */
+                    res = dir_register(&djn);            /* Register the new entry */
+                    if (res == FR_OK) {
+                        dir = djn.dir;                    /* Copy object information except for name */
+                        mem_cpy(dir+13, buf+2, 19);
+                        dir[DIR_Attr] = buf[0] | AM_ARC;
+                        djo.fs->wflag = 1;
+                        if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) {        /* Update .. entry in the directory if needed */
+                            dw = clust2sect(djn.fs, LD_CLUST(dir));
+                            if (!dw) {
+                                res = FR_INT_ERR;
+                            } else {
+                                res = move_window(djn.fs, dw);
+                                dir = djn.fs->win+32;    /* .. entry */
+                                if (res == FR_OK && dir[1] == '.') {
+                                    dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust;
+                                    ST_CLUST(dir, dw);
+                                    djn.fs->wflag = 1;
+                                }
+                            }
+                        }
+                        if (res == FR_OK) {
+                            res = dir_remove(&djo);        /* Remove old entry */
+                            if (res == FR_OK)
+                                res = sync(djo.fs);
+                        }
+                    }
+/* End critical section */
+                }
+            }
+        }
+        FREE_BUF();
+    }
+    LEAVE_FF(djo.fs, res);
+}
+
+#endif /* !_FS_READONLY */
+#endif /* _FS_MINIMIZE == 0 */
+#endif /* _FS_MINIMIZE <= 1 */
+#endif /* _FS_MINIMIZE <= 2 */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Forward data to the stream directly (available on only tiny cfg)      */
+/*-----------------------------------------------------------------------*/
+#if _USE_FORWARD && _FS_TINY
+
+FRESULT f_forward (
+    FIL *fp,                         /* Pointer to the file object */
+    UINT (*func)(const BYTE*,UINT),    /* Pointer to the streaming function */
+    UINT btr,                        /* Number of bytes to forward */
+    UINT *bf                        /* Pointer to number of bytes forwarded */
+)
+{
+    FRESULT res;
+    DWORD remain, clst, sect;
+    UINT rcnt;
+    BYTE csect;
+
+
+    *bf = 0;    /* Initialize byte counter */
+
+    res = validate(fp->fs, fp->id);                    /* Check validity of the object */
+    if (res != FR_OK) LEAVE_FF(fp->fs, res);
+    if (fp->flag & FA__ERROR)                        /* Check error flag */
+        LEAVE_FF(fp->fs, FR_INT_ERR);
+    if (!(fp->flag & FA_READ))                        /* Check access mode */
+        LEAVE_FF(fp->fs, FR_DENIED);
+
+    remain = fp->fsize - fp->fptr;
+    if (btr > remain) btr = (UINT)remain;            /* Truncate btr by remaining bytes */
+
+    for ( ;  btr && (*func)(0, 0);                    /* Repeat until all data transferred or stream becomes busy */
+        fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) {
+        csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1));    /* Sector offset in the cluster */
+        if ((fp->fptr % SS(fp->fs)) == 0) {            /* On the sector boundary? */
+            if (!csect) {                            /* On the cluster boundary? */
+                clst = (fp->fptr == 0) ?            /* On the top of the file? */
+                    fp->org_clust : get_fat(fp->fs, fp->curr_clust);
+                if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
+                if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+                fp->curr_clust = clst;                /* Update current cluster */
+            }
+        }
+        sect = clust2sect(fp->fs, fp->curr_clust);    /* Get current data sector */
+        if (!sect) ABORT(fp->fs, FR_INT_ERR);
+        sect += csect;
+        if (move_window(fp->fs, sect))                /* Move sector window */
+            ABORT(fp->fs, FR_DISK_ERR);
+        fp->dsect = sect;
+        rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs));    /* Forward data from sector window */
+        if (rcnt > btr) rcnt = btr;
+        rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt);
+        if (!rcnt) ABORT(fp->fs, FR_INT_ERR);
+    }
+
+    LEAVE_FF(fp->fs, FR_OK);
+}
+#endif /* _USE_FORWARD */
+
+
+
+#if _USE_MKFS && !_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Create File System on the Drive                                       */
+/*-----------------------------------------------------------------------*/
+#define N_ROOTDIR    512        /* Multiple of 32 */
+#define N_FATS        1        /* 1 or 2 */
+
+
+FRESULT f_mkfs (
+    BYTE drv,        /* Logical drive number */
+    BYTE sfd,        /* Partitioning rule 0:FDISK, 1:SFD */
+    UINT au            /* Allocation unit size [bytes] */
+)
+{
+    static const WORD vst[] = { 1024,   512,  256,  128,   64,    32,   16,    8,    4,    2,   0};
+    static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
+    BYTE fmt, md, *tbl;
+    DWORD n_clst, vs, n, wsect;
+    UINT i;
+    DWORD b_vol, b_fat, b_dir, b_data;    /* Offset (LBA) */
+    DWORD n_vol, n_rsv, n_fat, n_dir;    /* Size */
+    FATFS *fs;
+    DSTATUS stat;
+
+
+    /* Check mounted drive and clear work area */
+    if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
+    fs = FatFs[drv];
+    if (!fs) return FR_NOT_ENABLED;
+    fs->fs_type = 0;
+    drv = LD2PD(drv);
+
+    /* Get disk statics */
+    stat = disk_initialize(drv);
+    if (stat & STA_NOINIT) return FR_NOT_READY;
+    if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
+#if _MAX_SS != 512                    /* Get disk sector size */
+    if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK)
+        return FR_DISK_ERR;
+#endif
+    if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
+        return FR_DISK_ERR;
+    b_vol = (sfd) ? 0 : 63;    /* Volume start sector */
+    n_vol -= b_vol;
+    if (au & (au - 1)) au = 0;        /* Check validity of the allocation unit size */
+    if (!au) {                        /* AU auto selection */
+        vs = n_vol / (2000 / (SS(fs) / 512));
+        for (i = 0; vs < vst[i]; i++) ;
+        au = cst[i];
+    }
+    au /= SS(fs);        /* Number of sectors per cluster */
+    if (au == 0) au = 1;
+    if (au > 128) au = 128;
+
+    /* Pre-compute number of clusters and FAT syb-type */
+    n_clst = n_vol / au;
+    fmt = FS_FAT12;
+    if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
+    if (n_clst >= MIN_FAT32) fmt = FS_FAT32;
+
+    /* Determine offset and size of FAT structure */
+    if (fmt == FS_FAT32) {
+        n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
+        n_rsv = 32;
+        n_dir = 0;
+    } else {
+        n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
+        n_fat = (n_fat + SS(fs) - 1) / SS(fs);
+        n_rsv = 1;
+        n_dir = N_ROOTDIR * 32UL / SS(fs);
+    }
+    b_fat = b_vol + n_rsv;                /* FAT area start sector */
+    b_dir = b_fat + n_fat * N_FATS;        /* Directory area start sector */
+    b_data = b_dir + n_dir;                /* Data area start sector */
+    if (n_vol < b_data + au) return FR_MKFS_ABORTED;    /* Too small volume */
+
+    /* Align data start sector to erase block boundary (for flash memory media) */
+    if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
+    n = (b_data + n - 1) & ~(n - 1);    /* Next nearest erase block from current data start */
+    n = (n - b_data) / N_FATS;
+    if (fmt == FS_FAT32) {        /* FAT32: Move FAT offset */
+        n_rsv += n;
+        b_fat += n;
+    } else {                    /* FAT12/16: Expand FAT size */
+        n_fat += n;
+    }
+
+    /* Determine number of cluster and final check of validity of the FAT sub-type */
+    n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
+    if (   (fmt == FS_FAT16 && n_clst < MIN_FAT16)
+        || (fmt == FS_FAT32 && n_clst < MIN_FAT32))
+        return FR_MKFS_ABORTED;
+
+    /* Create partition table if required */
+    if (sfd) {
+        md = 0xF0;
+    } else {
+        DWORD n_disk = b_vol + n_vol;
+
+        mem_set(fs->win, 0, SS(fs));
+        tbl = fs->win+MBR_Table;
+        ST_DWORD(tbl, 0x00010180);            /* Partition start in CHS */
+        if (n_disk < 63UL * 255 * 1024) {    /* Partition end in CHS */
+            n_disk = n_disk / 63 / 255;
+            tbl[7] = (BYTE)n_disk;
+            tbl[6] = (BYTE)((n_disk >> 2) | 63);
+        } else {
+            ST_WORD(&tbl[6], 0xFFFF);
+        }
+        tbl[5] = 254;
+        if (fmt != FS_FAT32)                /* System ID */
+            tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06;
+        else
+            tbl[4] = 0x0c;
+        ST_DWORD(tbl+8, 63);                /* Partition start in LBA */
+        ST_DWORD(tbl+12, n_vol);            /* Partition size in LBA */
+        ST_WORD(tbl+64, 0xAA55);            /* Signature */
+        if (disk_write(drv, fs->win, 0, 1) != RES_OK)
+            return FR_DISK_ERR;
+        md = 0xF8;
+    }
+
+    /* Create volume boot record */
+    tbl = fs->win;                            /* Clear sector */
+    mem_set(tbl, 0, SS(fs));
+    mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot code, OEM name */
+    i = SS(fs);                                /* Sector size */
+    ST_WORD(tbl+BPB_BytsPerSec, i);
+    tbl[BPB_SecPerClus] = (BYTE)au;            /* Sectors per cluster */
+    ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv);        /* Reserved sectors */
+    tbl[BPB_NumFATs] = N_FATS;                /* Number of FATs */
+    i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR;    /* Number of rootdir entries */
+    ST_WORD(tbl+BPB_RootEntCnt, i);
+    if (n_vol < 0x10000) {                    /* Number of total sectors */
+        ST_WORD(tbl+BPB_TotSec16, n_vol);
+    } else {
+        ST_DWORD(tbl+BPB_TotSec32, n_vol);
+    }
+    tbl[BPB_Media] = md;                    /* Media descriptor */
+    ST_WORD(tbl+BPB_SecPerTrk, 63);            /* Number of sectors per track */
+    ST_WORD(tbl+BPB_NumHeads, 255);            /* Number of heads */
+    ST_DWORD(tbl+BPB_HiddSec, b_vol);        /* Hidden sectors */
+    n = get_fattime();                        /* Use current time as VSN */
+    if (fmt == FS_FAT32) {
+        ST_DWORD(tbl+BS_VolID32, n);        /* VSN */
+        ST_DWORD(tbl+BPB_FATSz32, n_fat);    /* Number of sectors per FAT */
+        ST_DWORD(tbl+BPB_RootClus, 2);        /* Root directory start cluster (2) */
+        ST_WORD(tbl+BPB_FSInfo, 1);            /* FSInfo record offset (VBR+1) */
+        ST_WORD(tbl+BPB_BkBootSec, 6);        /* Backup boot record offset (VBR+6) */
+        tbl[BS_DrvNum32] = 0x80;            /* Drive number */
+        tbl[BS_BootSig32] = 0x29;            /* Extended boot signature */
+        mem_cpy(tbl+BS_VolLab32, "NO NAME    " "FAT32   ", 19);    /* Volume label, FAT signature */
+    } else {
+        ST_DWORD(tbl+BS_VolID, n);            /* VSN */
+        ST_WORD(tbl+BPB_FATSz16, n_fat);    /* Number of sectors per FAT */
+        tbl[BS_DrvNum] = 0x80;                /* Drive number */
+        tbl[BS_BootSig] = 0x29;                /* Extended boot signature */
+        mem_cpy(tbl+BS_VolLab, "NO NAME    " "FAT     ", 19);    /* Volume label, FAT signature */
+    }
+    ST_WORD(tbl+BS_55AA, 0xAA55);            /* Signature (Offset is fixed here regardless of sector size) */
+    if (disk_write(drv, tbl, b_vol, 1) != RES_OK)/* Write original (VBR) */
+        return FR_DISK_ERR;
+    if (fmt == FS_FAT32)                    /* Write backup (VBR+6) */
+        disk_write(drv, tbl, b_vol + 6, 1);
+
+    /* Initialize FAT area */
+    wsect = b_fat;
+    for (i = 0; i < N_FATS; i++) {
+        mem_set(tbl, 0, SS(fs));            /* 1st sector of the FAT  */
+        n = md;                                /* Media descriptor byte */
+        if (fmt != FS_FAT32) {
+            n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
+            ST_DWORD(tbl+0, n);                /* Reserve cluster #0-1 (FAT12/16) */
+        } else {
+            n |= 0xFFFFFF00;
+            ST_DWORD(tbl+0, n);                /* Reserve cluster #0-1 (FAT32) */
+            ST_DWORD(tbl+4, 0xFFFFFFFF);
+            ST_DWORD(tbl+8, 0x0FFFFFFF);    /* Reserve cluster #2 for root dir */
+        }
+        if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+            return FR_DISK_ERR;
+        mem_set(tbl, 0, SS(fs));            /* Fill following FAT entries with zero */
+        for (n = 1; n < n_fat; n++) {        /* This loop may take a time on FAT32 volume due to many single sector write */
+            if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+                return FR_DISK_ERR;
+        }
+    }
+
+    /* Initialize root directory */
+    i = (fmt == FS_FAT32) ? au : n_dir;
+    do {
+        if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+            return FR_DISK_ERR;
+    } while (--i);
+
+#if _USE_ERASE    /* Erase data area if needed */
+    {
+        DWORD eb[2];
+
+        eb[0] = wsect; eb[1] = wsect + n_clst * au - 1;
+        disk_ioctl(drv, CTRL_ERASE_SECTOR, eb);
+    }
+#endif
+
+    /* Create FSInfo if needed */
+    if (fmt == FS_FAT32) {
+        ST_WORD(tbl+BS_55AA, 0xAA55);
+        ST_DWORD(tbl+FSI_LeadSig, 0x41615252);
+        ST_DWORD(tbl+FSI_StrucSig, 0x61417272);
+        ST_DWORD(tbl+FSI_Free_Count, n_clst - 1);
+        ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF);
+        disk_write(drv, tbl, b_vol + 1, 1);    /* Write original (VBR+1) */
+        disk_write(drv, tbl, b_vol + 7, 1);    /* Write backup (VBR+7) */
+    }
+
+    return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR;
+}
+
+#endif /* _USE_MKFS && !_FS_READONLY */
+
+
+
+
+#if _USE_STRFUNC
+/*-----------------------------------------------------------------------*/
+/* Get a string from the file                                            */
+/*-----------------------------------------------------------------------*/
+TCHAR* f_gets (
+    TCHAR* buff,    /* Pointer to the string buffer to read */
+    int len,        /* Size of string buffer (characters) */
+    FIL* fil        /* Pointer to the file object */
+)
+{
+    int n = 0;
+    TCHAR c, *p = buff;
+    BYTE s[2];
+    UINT rc;
+
+
+    while (n < len - 1) {            /* Read bytes until buffer gets filled */
+        f_read(fil, s, 1, &rc);
+        if (rc != 1) break;            /* Break on EOF or error */
+        c = s[0];
+#if _LFN_UNICODE                    /* Read a character in UTF-8 encoding */
+        if (c >= 0x80) {
+            if (c < 0xC0) continue;    /* Skip stray trailer */
+            if (c < 0xE0) {            /* Two-byte sequense */
+                f_read(fil, s, 1, &rc);
+                if (rc != 1) break;
+                c = ((c & 0x1F) << 6) | (s[0] & 0x3F);
+                if (c < 0x80) c = '?';
+            } else {
+                if (c < 0xF0) {        /* Three-byte sequense */
+                    f_read(fil, s, 2, &rc);
+                    if (rc != 2) break;
+                    c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F);
+                    if (c < 0x800) c = '?';
+                } else {            /* Reject four-byte sequense */
+                    c = '?';
+                }
+            }
+        }
+#endif
+#if _USE_STRFUNC >= 2
+        if (c == '\r') continue;    /* Strip '\r' */
+#endif
+        *p++ = c;
+        n++;
+        if (c == '\n') break;        /* Break on EOL */
+    }
+    *p = 0;
+    return n ? buff : 0;            /* When no data read (eof or error), return with error. */
+}
+
+
+
+#if !_FS_READONLY
+#include <stdarg.h>
+/*-----------------------------------------------------------------------*/
+/* Put a character to the file                                           */
+/*-----------------------------------------------------------------------*/
+int f_putc (
+    TCHAR c,    /* A character to be output */
+    FIL* fil    /* Pointer to the file object */
+)
+{
+    UINT bw, btw;
+    BYTE s[3];
+
+
+#if _USE_STRFUNC >= 2
+    if (c == '\n') f_putc ('\r', fil);    /* LF -> CRLF conversion */
+#endif
+
+#if _LFN_UNICODE    /* Write the character in UTF-8 encoding */
+    if (c < 0x80) {            /* 7-bit */
+        s[0] = (BYTE)c;
+        btw = 1;
+    } else {
+        if (c < 0x800) {    /* 11-bit */
+            s[0] = (BYTE)(0xC0 | (c >> 6));
+            s[1] = (BYTE)(0x80 | (c & 0x3F));
+            btw = 2;
+        } else {            /* 16-bit */
+            s[0] = (BYTE)(0xE0 | (c >> 12));
+            s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F));
+            s[2] = (BYTE)(0x80 | (c & 0x3F));
+            btw = 3;
+        }
+    }
+#else                /* Write the character without conversion */
+    s[0] = (BYTE)c;
+    btw = 1;
+#endif
+    f_write(fil, s, btw, &bw);        /* Write the char to the file */
+    return (bw == btw) ? 1 : EOF;    /* Return the result */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Put a string to the file                                              */
+/*-----------------------------------------------------------------------*/
+int f_puts (
+    const TCHAR* str,    /* Pointer to the string to be output */
+    FIL* fil            /* Pointer to the file object */
+)
+{
+    int n;
+
+
+    for (n = 0; *str; str++, n++) {
+        if (f_putc(*str, fil) == EOF) return EOF;
+    }
+    return n;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Put a formatted string to the file                                    */
+/*-----------------------------------------------------------------------*/
+int f_printf (
+    FIL* fil,            /* Pointer to the file object */
+    const TCHAR* str,    /* Pointer to the format string */
+    ...                    /* Optional arguments... */
+)
+{
+    va_list arp;
+    BYTE f, r;
+    UINT i, w;
+    ULONG val;
+    TCHAR c, d, s[16];
+    int res, cc;
+
+
+    va_start(arp, str);
+
+    for (cc = res = 0; cc != EOF; res += cc) {
+        c = *str++;
+        if (c == 0) break;            /* End of string */
+        if (c != '%') {                /* Non escape character */
+            cc = f_putc(c, fil);
+            if (cc != EOF) cc = 1;
+            continue;
+        }
+        w = f = 0;
+        c = *str++;
+        if (c == '0') {                /* Flag: '0' padding */
+            f = 1; c = *str++;
+        }
+        while (IsDigit(c)) {        /* Precision */
+            w = w * 10 + c - '0';
+            c = *str++;
+        }
+        if (c == 'l' || c == 'L') {    /* Prefix: Size is long int */
+            f |= 2; c = *str++;
+        }
+        if (!c) break;
+        d = c;
+        if (IsLower(d)) d -= 0x20;
+        switch (d) {                /* Type is... */
+        case 'S' :                    /* String */
+            cc = f_puts(va_arg(arp, TCHAR*), fil); continue;
+        case 'C' :                    /* Character */
+            cc = f_putc((TCHAR)va_arg(arp, int), fil); continue;
+        case 'B' :                    /* Binary */
+            r = 2; break;
+        case 'O' :                    /* Octal */
+            r = 8; break;
+        case 'D' :                    /* Signed decimal */
+        case 'U' :                    /* Unsigned decimal */
+            r = 10; break;
+        case 'X' :                    /* Hexdecimal */
+            r = 16; break;
+        default:                    /* Unknown */
+            cc = f_putc(c, fil); continue;
+        }
+
+        /* Get an argument */
+        val = (f & 2) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int));
+        if (d == 'D' && (val & 0x80000000)) {
+            val = 0 - val;
+            f |= 4;
+        }
+        /* Put it in numeral string */
+        i = 0;
+        do {
+            d = (TCHAR)(val % r); val /= r;
+            if (d > 9) {
+                d += 7;
+                if (c == 'x') d += 0x20;
+            }
+            s[i++] = d + '0';
+        } while (val && i < sizeof(s) / sizeof(s[0]));
+        if (f & 4) s[i++] = '-';
+        cc = 0;
+        while (i < w-- && cc != EOF) {
+            cc = f_putc((TCHAR)((f & 1) ? '0' : ' '), fil);
+            res++;
+        }
+        do {
+            cc = f_putc(s[--i], fil); 
+            res++;
+        } while (i && cc != EOF);
+        if (cc != EOF) cc = 0;
+    }
+
+    va_end(arp);
+    return (cc == EOF) ? cc : res;
+}
+
+#endif /* !_FS_READONLY */
+#endif /* _USE_STRFUNC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/FatFS/ff.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,541 @@
+/*---------------------------------------------------------------------------/
+/  FatFs - FAT file system module include file  R0.08a    (C)ChaN, 2010
+/----------------------------------------------------------------------------/
+/ FatFs module is a generic FAT file system module for small embedded systems.
+/ This is a free software that opened for education, research and commercial
+/ developments under license policy of following trems.
+/
+/  Copyright (C) 2010, ChaN, all right reserved.
+/
+/ * The FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/   personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/----------------------------------------------------------------------------*/
+
+#ifndef _FATFS
+#define _FATFS    8255    /* Revision ID */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "integer.h"    /* Basic integer types */
+#include "ffconf.h"        /* FatFs configuration options */
+
+#if _FATFS != _FFCONF
+#error Wrong configuration file (ffconf.h).
+#endif
+
+
+/* DBCS code ranges and SBCS extend char conversion table */
+
+#if _CODE_PAGE == 932    /* Japanese Shift-JIS */
+#define _DF1S    0x81    /* DBC 1st byte range 1 start */
+#define _DF1E    0x9F    /* DBC 1st byte range 1 end */
+#define _DF2S    0xE0    /* DBC 1st byte range 2 start */
+#define _DF2E    0xFC    /* DBC 1st byte range 2 end */
+#define _DS1S    0x40    /* DBC 2nd byte range 1 start */
+#define _DS1E    0x7E    /* DBC 2nd byte range 1 end */
+#define _DS2S    0x80    /* DBC 2nd byte range 2 start */
+#define _DS2E    0xFC    /* DBC 2nd byte range 2 end */
+
+#elif _CODE_PAGE == 936    /* Simplified Chinese GBK */
+#define _DF1S    0x81
+#define _DF1E    0xFE
+#define _DS1S    0x40
+#define _DS1E    0x7E
+#define _DS2S    0x80
+#define _DS2E    0xFE
+
+#elif _CODE_PAGE == 949    /* Korean */
+#define _DF1S    0x81
+#define _DF1E    0xFE
+#define _DS1S    0x41
+#define _DS1E    0x5A
+#define _DS2S    0x61
+#define _DS2E    0x7A
+#define _DS3S    0x81
+#define _DS3E    0xFE
+
+#elif _CODE_PAGE == 950    /* Traditional Chinese Big5 */
+#define _DF1S    0x81
+#define _DF1E    0xFE
+#define _DS1S    0x40
+#define _DS1E    0x7E
+#define _DS2S    0xA1
+#define _DS2E    0xFE
+
+#elif _CODE_PAGE == 437    /* U.S. (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 720    /* Arabic (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 737    /* Greek (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
+                0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 775    /* Baltic (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
+                0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 850    /* Multilingual Latin 1 (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
+                0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 852    /* Latin 2 (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
+                0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
+
+#elif _CODE_PAGE == 855    /* Cyrillic (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
+                0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
+                0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 857    /* Turkish (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
+                0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 858    /* Multilingual Latin 1 + Euro (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
+                0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 862    /* Hebrew (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 866    /* Russian (OEM) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 874    /* Thai (OEM, Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
+                0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
+
+#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
+                0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
+
+#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
+                0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
+
+#elif _CODE_PAGE == 1253 /* Greek (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
+                0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
+
+#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
+                0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
+
+#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
+                0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+                0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
+
+#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
+#define _DF1S    0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
+                0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+                0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
+
+#elif _CODE_PAGE == 1    /* ASCII (for only non-LFN cfg) */
+#define _DF1S    0
+
+#else
+#error Unknown code page
+
+#endif
+
+
+
+/* Definitions of volume management */
+
+#if _MULTI_PARTITION        /* Multiple partition configuration */
+#define LD2PD(vol) (VolToPart[vol].pd)    /* Get physical drive# */
+#define LD2PT(vol) (VolToPart[vol].pt)    /* Get partition# */
+typedef struct {
+    BYTE pd;    /* Physical drive# */
+    BYTE pt;    /* Partition # (0-3) */
+} PARTITION;
+extern const PARTITION VolToPart[];    /* Volume - Physical location resolution table */
+
+#else                        /* Single partition configuration */
+#define LD2PD(vol) (vol)    /* Logical drive# is bound to the same physical drive# */
+#define LD2PT(vol) 0        /* Always mounts the 1st partition */
+
+#endif
+
+
+
+/* Type of path name strings on FatFs API */
+
+#if _LFN_UNICODE            /* Unicode string */
+#if !_USE_LFN
+#error _LFN_UNICODE must be 0 in non-LFN cfg.
+#endif
+#ifndef _INC_TCHAR
+typedef WCHAR TCHAR;
+#define _T(x) L ## x
+#define _TEXT(x) L ## x
+#endif
+
+#else                        /* ANSI/OEM string */
+#ifndef _INC_TCHAR
+typedef char TCHAR;
+#define _T(x) x
+#define _TEXT(x) x
+#endif
+
+#endif
+
+
+
+/* File system object structure (FATFS) */
+
+typedef struct {
+    BYTE    fs_type;        /* FAT sub-type (0:Not mounted) */
+    BYTE    drv;            /* Physical drive number */
+    BYTE    csize;            /* Sectors per cluster (1,2,4...128) */
+    BYTE    n_fats;            /* Number of FAT copies (1,2) */
+    BYTE    wflag;            /* win[] dirty flag (1:must be written back) */
+    BYTE    fsi_flag;        /* fsinfo dirty flag (1:must be written back) */
+    WORD    id;                /* File system mount ID */
+    WORD    n_rootdir;        /* Number of root directory entries (FAT12/16) */
+#if _MAX_SS != 512
+    WORD    ssize;            /* Bytes per sector (512,1024,2048,4096) */
+#endif
+#if _FS_REENTRANT
+    _SYNC_t    sobj;            /* Identifier of sync object */
+#endif
+#if !_FS_READONLY
+    DWORD    last_clust;        /* Last allocated cluster */
+    DWORD    free_clust;        /* Number of free clusters */
+    DWORD    fsi_sector;        /* fsinfo sector (FAT32) */
+#endif
+#if _FS_RPATH
+    DWORD    cdir;            /* Current directory start cluster (0:root) */
+#endif
+    DWORD    n_fatent;        /* Number of FAT entries (= number of clusters + 2) */
+    DWORD    fsize;            /* Sectors per FAT */
+    DWORD    fatbase;        /* FAT start sector */
+    DWORD    dirbase;        /* Root directory start sector (FAT32:Cluster#) */
+    DWORD    database;        /* Data start sector */
+    DWORD    winsect;        /* Current sector appearing in the win[] */
+    BYTE    win[_MAX_SS];    /* Disk access window for Directory, FAT (and Data on tiny cfg) */
+} FATFS;
+
+
+
+/* File object structure (FIL) */
+
+typedef struct {
+    FATFS*    fs;                /* Pointer to the owner file system object */
+    WORD    id;                /* Owner file system mount ID */
+    BYTE    flag;            /* File status flags */
+    BYTE    pad1;
+    DWORD    fptr;            /* File read/write pointer (0 on file open) */
+    DWORD    fsize;            /* File size */
+    DWORD    org_clust;        /* File start cluster (0 when fsize==0) */
+    DWORD    curr_clust;        /* Current cluster */
+    DWORD    dsect;            /* Current data sector */
+#if !_FS_READONLY
+    DWORD    dir_sect;        /* Sector containing the directory entry */
+    BYTE*    dir_ptr;        /* Ponter to the directory entry in the window */
+#endif
+#if _USE_FASTSEEK
+    DWORD*    cltbl;            /* Pointer to the cluster link map table (null on file open) */
+#endif
+#if _FS_SHARE
+    UINT    lockid;            /* File lock ID (index of file semaphore table) */
+#endif
+#if !_FS_TINY
+    BYTE    buf[_MAX_SS];    /* File data read/write buffer */
+#endif
+} FIL;
+
+
+
+/* Directory object structure (DIR) */
+
+typedef struct {
+    FATFS*    fs;                /* Pointer to the owner file system object */
+    WORD    id;                /* Owner file system mount ID */
+    WORD    index;            /* Current read/write index number */
+    DWORD    sclust;            /* Table start cluster (0:Root dir) */
+    DWORD    clust;            /* Current cluster */
+    DWORD    sect;            /* Current sector */
+    BYTE*    dir;            /* Pointer to the current SFN entry in the win[] */
+    BYTE*    fn;                /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
+#if _USE_LFN
+    WCHAR*    lfn;            /* Pointer to the LFN working buffer */
+    WORD    lfn_idx;        /* Last matched LFN index number (0xFFFF:No LFN) */
+#endif
+} DIR;
+
+
+
+/* File status structure (FILINFO) */
+
+typedef struct {
+    DWORD    fsize;            /* File size */
+    WORD    fdate;            /* Last modified date */
+    WORD    ftime;            /* Last modified time */
+    BYTE    fattrib;        /* Attribute */
+    TCHAR    fname[13];        /* Short file name (8.3 format) */
+#if _USE_LFN
+    TCHAR*    lfname;            /* Pointer to the LFN buffer */
+    UINT     lfsize;            /* Size of LFN buffer in TCHAR */
+#endif
+} FILINFO;
+
+
+
+/* File function return code (FRESULT) */
+
+typedef enum {
+    FR_OK = 0,                /* (0) Succeeded */
+    FR_DISK_ERR,            /* (1) A hard error occured in the low level disk I/O layer */
+    FR_INT_ERR,                /* (2) Assertion failed */
+    FR_NOT_READY,            /* (3) The physical drive cannot work */
+    FR_NO_FILE,                /* (4) Could not find the file */
+    FR_NO_PATH,                /* (5) Could not find the path */
+    FR_INVALID_NAME,        /* (6) The path name format is invalid */
+    FR_DENIED,                /* (7) Acces denied due to prohibited access or directory full */
+    FR_EXIST,                /* (8) Acces denied due to prohibited access */
+    FR_INVALID_OBJECT,        /* (9) The file/directory object is invalid */
+    FR_WRITE_PROTECTED,        /* (10) The physical drive is write protected */
+    FR_INVALID_DRIVE,        /* (11) The logical drive number is invalid */
+    FR_NOT_ENABLED,            /* (12) The volume has no work area */
+    FR_NO_FILESYSTEM,        /* (13) There is no valid FAT volume on the physical drive */
+    FR_MKFS_ABORTED,        /* (14) The f_mkfs() aborted due to any parameter error */
+    FR_TIMEOUT,                /* (15) Could not get a grant to access the volume within defined period */
+    FR_LOCKED,                /* (16) The operation is rejected according to the file shareing policy */
+    FR_NOT_ENOUGH_CORE,        /* (17) LFN working buffer could not be allocated */
+    FR_TOO_MANY_OPEN_FILES    /* (18) Number of open files > _FS_SHARE */
+} FRESULT;
+
+
+
+/*--------------------------------------------------------------*/
+/* FatFs module application interface                           */
+
+FRESULT f_mount (BYTE, FATFS*);                        /* Mount/Unmount a logical drive */
+FRESULT f_open (FIL*, const TCHAR*, BYTE);            /* Open or create a file */
+FRESULT f_read (FIL*, void*, UINT, UINT*);            /* Read data from a file */
+FRESULT f_lseek (FIL*, DWORD);                        /* Move file pointer of a file object */
+FRESULT f_close (FIL*);                                /* Close an open file object */
+FRESULT f_opendir (DIR*, const TCHAR*);                /* Open an existing directory */
+FRESULT f_readdir (DIR*, FILINFO*);                    /* Read a directory item */
+FRESULT f_stat (const TCHAR*, FILINFO*);            /* Get file status */
+
+#if !_FS_READONLY
+FRESULT f_write (FIL*, const void*, UINT, UINT*);    /* Write data to a file */
+FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**);    /* Get number of free clusters on the drive */
+FRESULT f_truncate (FIL*);                            /* Truncate file */
+FRESULT f_sync (FIL*);                                /* Flush cached data of a writing file */
+FRESULT f_unlink (const TCHAR*);                    /* Delete an existing file or directory */
+FRESULT    f_mkdir (const TCHAR*);                        /* Create a new directory */
+FRESULT f_chmod (const TCHAR*, BYTE, BYTE);            /* Change attriburte of the file/dir */
+FRESULT f_utime (const TCHAR*, const FILINFO*);        /* Change timestamp of the file/dir */
+FRESULT f_rename (const TCHAR*, const TCHAR*);        /* Rename/Move a file or directory */
+#endif
+
+#if _USE_FORWARD
+FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*);    /* Forward data to the stream */
+#endif
+
+#if _USE_MKFS
+FRESULT f_mkfs (BYTE, BYTE, UINT);                    /* Create a file system on the drive */
+#endif
+
+#if _FS_RPATH
+FRESULT f_chdrive (BYTE);                            /* Change current drive */
+FRESULT f_chdir (const TCHAR*);                        /* Change current directory */
+FRESULT f_getcwd (TCHAR*, UINT);                    /* Get current directory */
+#endif
+
+#if _USE_STRFUNC
+int f_putc (TCHAR, FIL*);                            /* Put a character to the file */
+int f_puts (const TCHAR*, FIL*);                    /* Put a string to the file */
+int f_printf (FIL*, const TCHAR*, ...);                /* Put a formatted string to the file */
+TCHAR* f_gets (TCHAR*, int, FIL*);                    /* Get a string from the file */
+#ifndef EOF
+#define EOF (-1)
+#endif
+#endif
+
+#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
+#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
+#define f_tell(fp) ((fp)->fptr)
+#define f_size(fp) ((fp)->fsize)
+
+
+
+/*--------------------------------------------------------------*/
+/* Additional user defined functions                            */
+
+/* RTC function */
+#if !_FS_READONLY
+DWORD get_fattime (void);
+#endif
+
+/* Unicode support functions */
+#if _USE_LFN                        /* Unicode - OEM code conversion */
+WCHAR ff_convert (WCHAR, UINT);        /* OEM-Unicode bidirectional conversion */
+WCHAR ff_wtoupper (WCHAR);            /* Unicode upper-case conversion */
+#if _USE_LFN == 3                    /* Memory functions */
+void* ff_memalloc (UINT);            /* Allocate memory block */
+void ff_memfree (void*);            /* Free memory block */
+#endif
+#endif
+
+/* Sync functions */
+#if _FS_REENTRANT
+int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */
+int ff_del_syncobj (_SYNC_t);        /* Delete a sync object */
+int ff_req_grant (_SYNC_t);            /* Lock sync object */
+void ff_rel_grant (_SYNC_t);        /* Unlock sync object */
+#endif
+
+
+
+
+/*--------------------------------------------------------------*/
+/* Flags and offset address                                     */
+
+
+/* File access control and file status flags (FIL.flag) */
+
+#define    FA_READ                0x01
+#define    FA_OPEN_EXISTING    0x00
+#define FA__ERROR            0x80
+
+#if !_FS_READONLY
+#define    FA_WRITE            0x02
+#define    FA_CREATE_NEW        0x04
+#define    FA_CREATE_ALWAYS    0x08
+#define    FA_OPEN_ALWAYS        0x10
+#define FA__WRITTEN            0x20
+#define FA__DIRTY            0x40
+#endif
+
+
+/* FAT sub type (FATFS.fs_type) */
+
+#define FS_FAT12    1
+#define FS_FAT16    2
+#define FS_FAT32    3
+
+
+/* File attribute bits for directory entry */
+
+#define    AM_RDO    0x01    /* Read only */
+#define    AM_HID    0x02    /* Hidden */
+#define    AM_SYS    0x04    /* System */
+#define    AM_VOL    0x08    /* Volume label */
+#define AM_LFN    0x0F    /* LFN entry */
+#define AM_DIR    0x10    /* Directory */
+#define AM_ARC    0x20    /* Archive */
+#define AM_MASK    0x3F    /* Mask of defined bits */
+
+
+/* Fast seek function */
+#define CREATE_LINKMAP    0xFFFFFFFF
+
+
+/*--------------------------------*/
+/* Multi-byte word access macros  */
+
+#if _WORD_ACCESS == 1    /* Enable word access to the FAT structure */
+#define    LD_WORD(ptr)        (WORD)(*(WORD*)(BYTE*)(ptr))
+#define    LD_DWORD(ptr)        (DWORD)(*(DWORD*)(BYTE*)(ptr))
+#define    ST_WORD(ptr,val)    *(WORD*)(BYTE*)(ptr)=(WORD)(val)
+#define    ST_DWORD(ptr,val)    *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
+#else                    /* Use byte-by-byte access to the FAT structure */
+#define    LD_WORD(ptr)        (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
+#define    LD_DWORD(ptr)        (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
+#define    ST_WORD(ptr,val)    *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
+#define    ST_DWORD(ptr,val)    *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FATFS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/FatFS/ffconf.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,188 @@
+/*---------------------------------------------------------------------------/
+/  FatFs - FAT file system module configuration file  R0.08a (C)ChaN, 2010
+/----------------------------------------------------------------------------/
+/
+/ CAUTION! Do not forget to make clean the project after any changes to
+/ the configuration options.
+/
+/----------------------------------------------------------------------------*/
+#ifndef _FFCONF
+#define _FFCONF 8255    /* Revision ID */
+
+
+/*---------------------------------------------------------------------------/
+/ Function and Buffer Configurations
+/----------------------------------------------------------------------------*/
+
+#define    _FS_TINY    0        /* 0:Normal or 1:Tiny */
+/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
+/  object instead of the sector buffer in the individual file object for file
+/  data transfer. This reduces memory consumption 512 bytes each file object. */
+
+
+#define _FS_READONLY    0    /* 0:Read/Write or 1:Read only */
+/* Setting _FS_READONLY to 1 defines read only configuration. This removes
+/  writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
+/  f_truncate and useless f_getfree. */
+
+
+#define _FS_MINIMIZE    0    /* 0 to 3 */
+/* The _FS_MINIMIZE option defines minimization level to remove some functions.
+/
+/   0: Full function.
+/   1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
+/      are removed.
+/   2: f_opendir and f_readdir are removed in addition to 1.
+/   3: f_lseek is removed in addition to 2. */
+
+
+#define    _USE_STRFUNC    1    /* 0:Disable or 1/2:Enable */
+/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
+
+
+#define    _USE_MKFS    0        /* 0:Disable or 1:Enable */
+/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
+
+
+#define    _USE_FORWARD    0    /* 0:Disable or 1:Enable */
+/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
+
+
+#define    _USE_FASTSEEK    0    /* 0:Disable or 1:Enable */
+/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
+
+
+
+/*---------------------------------------------------------------------------/
+/ Locale and Namespace Configurations
+/----------------------------------------------------------------------------*/
+
+#define _CODE_PAGE    437
+/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
+/  Incorrect setting of the code page can cause a file open failure.
+/
+/   932  - Japanese Shift-JIS (DBCS, OEM, Windows)
+/   936  - Simplified Chinese GBK (DBCS, OEM, Windows)
+/   949  - Korean (DBCS, OEM, Windows)
+/   950  - Traditional Chinese Big5 (DBCS, OEM, Windows)
+/   1250 - Central Europe (Windows)
+/   1251 - Cyrillic (Windows)
+/   1252 - Latin 1 (Windows)
+/   1253 - Greek (Windows)
+/   1254 - Turkish (Windows)
+/   1255 - Hebrew (Windows)
+/   1256 - Arabic (Windows)
+/   1257 - Baltic (Windows)
+/   1258 - Vietnam (OEM, Windows)
+/   437  - U.S. (OEM)
+/   720  - Arabic (OEM)
+/   737  - Greek (OEM)
+/   775  - Baltic (OEM)
+/   850  - Multilingual Latin 1 (OEM)
+/   858  - Multilingual Latin 1 + Euro (OEM)
+/   852  - Latin 2 (OEM)
+/   855  - Cyrillic (OEM)
+/   866  - Russian (OEM)
+/   857  - Turkish (OEM)
+/   862  - Hebrew (OEM)
+/   874  - Thai (OEM, Windows)
+/    1    - ASCII only (Valid for non LFN cfg.)
+*/
+
+
+#define    _USE_LFN    1        /* 0 to 3 */
+#define    _MAX_LFN    255        /* Maximum LFN length to handle (12 to 255) */
+/* The _USE_LFN option switches the LFN support.
+/
+/   0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
+/   1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
+/   2: Enable LFN with dynamic working buffer on the STACK.
+/   3: Enable LFN with dynamic working buffer on the HEAP.
+/
+/  The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
+/  Unicode handling functions ff_convert() and ff_wtoupper() must be added
+/  to the project. When enable to use heap, memory control functions
+/  ff_memalloc() and ff_memfree() must be added to the project. */
+
+
+#define    _LFN_UNICODE    0    /* 0:ANSI/OEM or 1:Unicode */
+/* To switch the character code set on FatFs API to Unicode,
+/  enable LFN feature and set _LFN_UNICODE to 1. */
+
+
+#define _FS_RPATH    0        /* 0 to 2 */
+/* The _FS_RPATH option configures relative path feature.
+/
+/   0: Disable relative path feature and remove related functions.
+/   1: Enable relative path. f_chdrive() and f_chdir() are available.
+/   2: f_getcwd() is available in addition to 1.
+/
+/  Note that output of the f_readdir fnction is affected by this option. */
+
+
+
+/*---------------------------------------------------------------------------/
+/ Physical Drive Configurations
+/----------------------------------------------------------------------------*/
+
+#define _VOLUMES    1
+/* Number of volumes (logical drives) to be used. */
+
+
+#define    _MAX_SS        512        /* 512, 1024, 2048 or 4096 */
+/* Maximum sector size to be handled.
+/  Always set 512 for memory card and hard disk but a larger value may be
+/  required for floppy disk (512/1024) and optical disk (512/2048).
+/  When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted
+/  to the disk_ioctl function. */
+
+
+#define    _MULTI_PARTITION    0    /* 0:Single partition or 1:Multiple partition */
+/* When set to 0, each volume is bound to the same physical drive number and
+/ it can mount only first primaly partition. When it is set to 1, each volume
+/ is tied to the partitions listed in VolToPart[]. */
+
+
+#define    _USE_ERASE    0    /* 0:Disable or 1:Enable */
+/* To enable sector erase feature, set _USE_ERASE to 1. */
+
+
+
+/*---------------------------------------------------------------------------/
+/ System Configurations
+/----------------------------------------------------------------------------*/
+
+#define _WORD_ACCESS    0    /* 0 or 1 */
+/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
+/  option defines which access method is used to the word data on the FAT volume.
+/
+/   0: Byte-by-byte access.
+/   1: Word access. Do not choose this unless following condition is met.
+/
+/  When the byte order on the memory is big-endian or address miss-aligned word
+/  access results incorrect behavior, the _WORD_ACCESS must be set to 0.
+/  If it is not the case, the value can also be set to 1 to improve the
+/  performance and code size. */
+
+
+/* Include a header file here to define sync object types on the O/S */
+/* #include <windows.h>, <ucos_ii.h.h>, <semphr.h> or ohters. */
+
+#define _FS_REENTRANT    0        /* 0:Disable or 1:Enable */
+#define _FS_TIMEOUT        1000    /* Timeout period in unit of time ticks */
+#define    _SYNC_t            HANDLE    /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
+
+/* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
+/
+/   0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
+/   1: Enable reentrancy. Also user provided synchronization handlers,
+/      ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
+/      function must be added to the project. */
+
+
+#define    _FS_SHARE    0    /* 0:Disable or >=1:Enable */
+/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
+   defines how many files can be opened simultaneously. */
+
+
+#endif /* _FFCONFIG */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/FatFS/integer.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,37 @@
+/*-------------------------------------------*/
+/* Integer type definitions for FatFs module */
+/*-------------------------------------------*/
+
+#ifndef _INTEGER
+#define _INTEGER
+
+#ifdef _WIN32    /* FatFs development platform */
+
+#include <windows.h>
+#include <tchar.h>
+
+#else            /* Embedded platform */
+
+/* These types must be 16-bit, 32-bit or larger integer */
+typedef int                INT;
+typedef unsigned int    UINT;
+
+/* These types must be 8-bit integer */
+typedef char            CHAR;
+typedef unsigned char    UCHAR;
+typedef unsigned char    BYTE;
+
+/* These types must be 16-bit integer */
+typedef short            SHORT;
+typedef unsigned short    USHORT;
+typedef unsigned short    WORD;
+typedef unsigned short    WCHAR;
+
+/* These types must be 32-bit integer */
+typedef long            LONG;
+typedef unsigned long    ULONG;
+typedef unsigned long    DWORD;
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/FatFS/option/ccsbcs.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,542 @@
+
+
+/* (SBCS code pages)                                                      */
+/*------------------------------------------------------------------------*/
+/*  437   U.S. (OEM)
+/   720   Arabic (OEM)
+/   1256  Arabic (Windows)
+/   737   Greek (OEM)
+/   1253  Greek (Windows)
+/   1250  Central Europe (Windows)
+/   775   Baltic (OEM)
+/   1257  Baltic (Windows)
+/   850   Multilingual Latin 1 (OEM)
+/   852   Latin 2 (OEM)
+/   1252  Latin 1 (Windows)
+/   855   Cyrillic (OEM)
+/   1251  Cyrillic (Windows) AjK Patched http://elm-chan.org/fsw/ff/patches.html
+/   866   Russian (OEM)
+/   857   Turkish (OEM)
+/   1254  Turkish (Windows)
+/   858   Multilingual Latin 1 + Euro (OEM)
+/   862   Hebrew (OEM)
+/   1255  Hebrew (Windows)
+/   874   Thai (OEM, Windows)
+/   1258  Vietnam (OEM, Windows)
+*/
+
+#include "../ff.h"
+
+
+#if _CODE_PAGE == 437
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP437(0x80-0xFF) to Unicode conversion table */
+    0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+    0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+    0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+    0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
+    0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+    0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+    0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+    0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
+    0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
+    0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
+    0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 720
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP720(0x80-0xFF) to Unicode conversion table */
+    0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
+    0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
+    0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
+    0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+    0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+    0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+    0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642,
+    0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
+    0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0xO650, 0x2248,
+    0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 737
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP737(0x80-0xFF) to Unicode conversion table */
+    0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
+    0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
+    0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
+    0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
+    0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
+    0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+    0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+    0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD,
+    0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
+    0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248,
+    0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 775
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP775(0x80-0xFF) to Unicode conversion table */
+    0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
+    0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
+    0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
+    0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
+    0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6,
+    0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118,
+    0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
+    0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B,
+    0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+    0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144,
+    0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
+    0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E,
+    0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 850
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP850(0x80-0xFF) to Unicode conversion table */
+    0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+    0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+    0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+    0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
+    0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+    0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
+    0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+    0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
+    0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
+    0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
+    0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
+    0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
+    0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 852
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP852(0x80-0xFF) to Unicode conversion table */
+    0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
+    0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
+    0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
+    0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
+    0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E,
+    0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A,
+    0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+    0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE,
+    0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
+    0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161,
+    0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
+    0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8,
+    0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 855
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP855(0x80-0xFF) to Unicode conversion table */
+    0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
+    0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
+    0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
+    0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
+    0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414,
+    0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438,
+    0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+    0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E,
+    0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
+    0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443,
+    0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
+    0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D,
+    0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 857
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP857(0x80-0xFF) to Unicode conversion table */
+    0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+    0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
+    0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+    0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
+    0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F,
+    0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
+    0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+    0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE,
+    0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
+    0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000,
+    0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
+    0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
+    0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 858
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP858(0x80-0xFF) to Unicode conversion table */
+    0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+    0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+    0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+    0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
+    0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+    0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
+    0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+    0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE,
+    0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580,
+    0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
+    0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
+    0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
+    0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 862
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP862(0x80-0xFF) to Unicode conversion table */
+    0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+    0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+    0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+    0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
+    0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+    0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+    0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+    0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
+    0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
+    0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
+    0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 866
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP866(0x80-0xFF) to Unicode conversion table */
+    0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+    0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+    0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+    0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+    0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+    0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+    0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+    0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+    0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+    0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E,
+    0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 874
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP874(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
+    0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
+    0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
+    0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
+    0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
+    0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+    0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
+    0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F,
+    0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
+    0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
+    0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
+    0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+#elif _CODE_PAGE == 1250
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1250(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
+    0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
+    0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
+    0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
+    0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+    0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
+    0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+    0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
+    0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+    0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
+    0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
+};
+
+#elif _CODE_PAGE == 1251
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1251(0x80-0xFF) to Unicode conversion table */
+    0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
+    0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
+    0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
+    0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
+    0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
+    0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
+    0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+    0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+    0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+    0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+    0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+    0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+    0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+    0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F
+};
+
+#elif _CODE_PAGE == 1252
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1252(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178,
+    0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+    0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+    0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+    0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
+};
+
+#elif _CODE_PAGE == 1253
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1253(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7,
+    0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+    0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+    0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+    0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+    0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+    0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+    0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+    0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+    0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
+};
+
+#elif _CODE_PAGE == 1254
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1254(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
+    0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+    0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+    0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+    0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
+};
+
+#elif _CODE_PAGE == 1255
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1255(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+    0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+    0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+    0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
+    0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+    0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+    0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+    0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
+};
+
+#elif _CODE_PAGE == 1256
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1256(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
+    0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
+    0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
+    0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+    0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+    0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7,
+    0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643,
+    0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
+    0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7,
+    0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2
+}
+
+#elif _CODE_PAGE == 1257
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1257(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000,
+    0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7,
+    0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+    0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
+    0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+    0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
+    0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+    0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
+    0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+    0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
+    0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9
+};
+
+#elif _CODE_PAGE == 1258
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {    /*  CP1258(0x80-0xFF) to Unicode conversion table */
+    0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+    0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+    0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
+    0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+    0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
+    0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
+    0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
+    0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
+    0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF
+};
+
+#endif
+
+
+#if !_TBLDEF || !_USE_LFN
+#error This file is not needed in current configuration
+#endif
+
+
+WCHAR ff_convert (    /* Converted character, Returns zero on error */
+    WCHAR    src,    /* Character code to be converted */
+    UINT    dir        /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
+)
+{
+    WCHAR c;
+
+
+    if (src < 0x80) {    /* ASCII */
+        c = src;
+
+    } else {
+        if (dir) {        /* OEMCP to Unicode */
+            c = (src >= 0x100) ? 0 : Tbl[src - 0x80];
+
+        } else {        /* Unicode to OEMCP */
+            for (c = 0; c < 0x80; c++) {
+                if (src == Tbl[c]) break;
+            }
+            c = (c + 0x80) & 0xFF;
+        }
+    }
+
+    return c;
+}
+
+
+WCHAR ff_wtoupper (    /* Upper converted character */
+    WCHAR chr        /* Input character */
+)
+{
+    static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 };
+    static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 };
+    int i;
+
+
+    for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ;
+
+    return tbl_lower[i] ? tbl_upper[i] : chr;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/flash.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,112 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "debug.h"
+#include "ssp0.h"
+#include "gpio.h"
+#include "flash.h"
+#include "user.h"
+
+extern bool sector_erase_in_progress;
+extern bool page_write_in_progress;
+
+char flash_buffer[2][FLASH_PAGE_SIZE];
+int current_buffer;
+unsigned int flash_address;
+
+/** flash_init
+ */
+void flash_init(void) {
+    
+    /* Initialise the SSP0 to talk to the flash device. */    
+    SSP0_init();
+    
+    DEBUG_INIT_START;
+    
+    /* Clear out the page buffers. */
+    memset(flash_buffer, 0, 2 * FLASH_PAGE_SIZE);
+    
+    /* Default the buffer in use. */
+    current_buffer = 0;
+    
+    /* Default pointer set-up. */
+    flash_address = 0;
+    
+    /* Prime our buffers for expected future access. */
+    flash_read_page(0, flash_buffer[0], true);
+    flash_read_page(1, flash_buffer[1], true);
+    
+    /* Although not part of the flash system, SOWB includes
+       a 25AA02E48 device from Microchip that holds a globally
+       unique 48bit (6byte) MAC address. We use this for the
+       SOWB "STL authentic product" serial number and in future
+       may be used as the ethernet MAC address if we ever write 
+       code to support Ethernet. This device is also connected
+       to SSP1 and so we'll _init() it here now. */
+    //_25AA02E48_init();
+    
+    DEBUG_INIT_END;
+}
+
+/** flash_process
+ */
+void flash_process(void) {
+    /* Currently does nothing. */
+}
+
+/** flash_getc
+ */
+char flash_getc(bool peek) {
+    char c;
+    
+    /* Flash being deleted, undefined memory. */
+    if (sector_erase_in_progress) return 0xFF;
+    
+    /* Wait for any page loads to complete. */
+    while (page_write_in_progress) user_call_process();
+    
+    /* Get the character from the internal buffer. */
+    c = flash_buffer[current_buffer][flash_address];
+    
+    /* If this is just a peek then return the character without
+       incrementing the memory pointers etc etc. */
+    if (peek) return c;
+    
+    /* Inc the address pointer and load a new page if needed. Note,
+       we load the page in background using DMA. */
+    flash_address++;
+    if ((flash_address & 0xFF) == 0) {
+        flash_read_page(current_buffer >> 8, flash_buffer[current_buffer], false);
+        current_buffer = current_buffer ? 0 : 1;        
+    }
+    
+    return c;
+}
+
+/** flash_seek
+ */
+void flash_seek(unsigned int addr) {
+    flash_read_page((addr >> 8) + 0, flash_buffer[0], true);
+    flash_read_page((addr >> 8) + 1, flash_buffer[1], true);
+    flash_address = addr;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/flash.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,113 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef FLASH_H
+#define FLASH_H
+
+#define FLASH_PAGE_SIZE 256
+
+#define FLASH_WIP_TEST_TIME 2
+
+#define FLASH_WREN      0x06
+#define FLASH_WRDI      0x04
+#define FLASH_RDID      0x9F
+#define FLASH_RDSR      0x05
+#define FLASH_WRSR      0x01
+#define FLASH_READ      0x03
+#define FLASH_FAST_READ 0x0B
+#define FLASH_PP        0x02
+#define FLASH_SE        0xD8
+#define FLASH_BE        0xC7
+
+#define DMA_CHANNEL_ENABLE  1
+//#define DMA_CHANNEL_SRC_PERIPHERAL_SSP1_RX  (3UL << 1)
+//#define DMA_CHANNEL_SRC_PERIPHERAL_SSP1_TX  (2UL << 1)
+//#define DMA_CHANNEL_DST_PERIPHERAL_SSP1_RX  (3UL << 6)
+//#define DMA_CHANNEL_DST_PERIPHERAL_SSP1_TX  (2UL << 6)
+#define DMA_CHANNEL_SRC_PERIPHERAL_SSP0_RX  (1UL << 1)
+#define DMA_CHANNEL_SRC_PERIPHERAL_SSP0_TX  (0UL << 1)
+#define DMA_CHANNEL_DST_PERIPHERAL_SSP0_RX  (1UL << 6)
+#define DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX  (0UL << 6)
+#define DMA_CHANNEL_SRC_INC                 (1UL << 26)
+#define DMA_CHANNEL_DST_INC                 (1UL << 27)
+#define DMA_CHANNEL_TCIE                    (1UL << 31)
+#define DMA_TRANSFER_TYPE_M2M               (0UL << 11)
+#define DMA_TRANSFER_TYPE_M2P               (1UL << 11)
+#define DMA_TRANSFER_TYPE_P2M               (2UL << 11)
+#define DMA_TRANSFER_TYPE_P2P               (3UL << 11)
+#define DMA_MASK_IE                         (1UL << 14)
+#define DMA_MASK_ITC                        (1UL << 15)
+#define DMA_LOCK                            (1UL << 16)
+#define DMA_ACTIVE                          (1UL << 17)
+#define DMA_HALT                            (1UL << 18)
+
+#define FLASH_SHORT_COMMAND(x)              \
+    SSP0_WRITE_BYTE(x);                     \
+    while(SSP0_IS_BUSY);                    \
+    SSP0_FLUSH_RX_FIFO;
+
+#define FLASH_LONG_COMMAND(x,y)             \
+    SSP0_WRITE_BYTE(x);                     \
+    SSP0_WRITE_BYTE((y >> 8) & (0xFF));     \
+    SSP0_WRITE_BYTE(y & 0xFF);              \
+    SSP0_WRITE_BYTE(0);                     \
+    while(SSP0_IS_BUSY);                    \
+    SSP0_FLUSH_RX_FIFO;
+    
+#define FLASH_WAIT_WHILE_WIP                \
+    SSP0_CS_ASSERT;                         \
+    FLASH_SHORT_COMMAND(FLASH_RDSR);        \
+    SSP0_FLUSH_RX_FIFO;                     \
+    do {                                    \
+        SSP0_WRITE_BYTE(0);                 \
+    }                                       \
+    while (LPC_SSP0->DR & 0x1);             \
+    SSP0_CS_DEASSERT;
+    
+
+/* Defined in flash.c */
+void flash_init(void);
+void flash_process(void);
+char flash_getc(bool peek);
+void flash_seek(unsigned int addr);
+
+/* Defined in flash_read.c */
+bool flash_read_in_progress(void);
+void  flash_read_page(unsigned int page_address, char *buffer, bool block);
+
+/* Defined in flash_write.c */
+int  flash_erase_sector(int sector);
+bool flash_write_in_progress(void);
+bool flash_sector_erase_in_progress(void);
+int  flash_page_write(int page, char *buffer);
+
+/* Defined in flash_erase.c */
+bool flash_sector_erase_in_progress(void);
+int flash_erase_sector(int sector);
+int flash_erase_bulk(void);
+
+/* Defined in 25AA02E44.c */
+void _25AA02E48_init(void);
+void _25AA02E48_mac_addr(char *);
+void _25AA02E48_mac_addr_printable(char *, char);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/flash_erase.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,141 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "flash.h"
+#include "ssp0.h"
+#include "dma.h"
+#include "gpio.h"
+#include "rit.h"
+#include "user.h"
+#include "utils.h"
+#include "debug.h"
+
+/* Flags to show what state we are in. */
+bool sector_erase_in_progress = false;
+extern bool page_write_in_progress;
+
+bool flash_sector_erase_in_progress(void) {
+    return sector_erase_in_progress;
+}
+
+/** flash_erase_sector
+ */
+int flash_erase_sector(int sector) {
+
+    /* If a sector erase is in progress already
+       we return zero rather than wait (block)
+       because an erase can take so long to complete
+       we don't want to hang around waiting. Let the
+       caller reschedule it sometime later. */
+    if (sector_erase_in_progress) {
+        return 0;
+    }
+
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    sector_erase_in_progress = true;
+    
+    FLASH_CS_ASSERT;
+    FLASH_SHORT_COMMAND(FLASH_WREN);
+    FLASH_CS_DEASSERT;
+    
+    SSP0_FLUSH_RX_FIFO;
+    
+    /* Wait until the flash device has the WEL bit on. */
+    while ((LPC_SSP0->DR & 0x2) == 0) {            
+        FLASH_CS_ASSERT;
+        FLASH_SHORT_COMMAND(FLASH_RDSR);
+        SSP0_FLUSH_RX_FIFO;
+        SSP0_WRITE_BYTE(0);
+        while (SSP0_IS_BUSY);
+        FLASH_CS_DEASSERT;
+    }
+
+    SSP0_FLUSH_RX_FIFO;
+    
+    FLASH_CS_ASSERT;
+    FLASH_LONG_COMMAND(FLASH_SE, sector);
+    FLASH_CS_DEASSERT;
+    
+    /* Note, a sector erase takes much longer than
+       a page write (typical 600ms by the datasheet)
+       so there's no point making the first timeout
+       very short and producing a lot of uneeded 
+       interrupts. So we set the first timeout to
+       be 600 and then it'll switch to a much shorter
+       time in the ISR. */
+    rit_timer_set_counter(FLASH_WRITE_CB, 600);
+    return 1;
+}
+
+/** flash_erase_bulk
+ */
+int flash_erase_bulk(void) {
+
+    /* If a sector erase is in progress already
+       we return zero rather than wait (block)
+       because an erase can take so long to complete
+       we don't want to hang around waiting. Let the
+       caller reschedule it sometime later. */
+   
+    if (sector_erase_in_progress || page_write_in_progress) {
+        return 0;
+    }
+
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    sector_erase_in_progress = true;
+    
+    FLASH_CS_ASSERT;
+    FLASH_SHORT_COMMAND(FLASH_WREN);
+    FLASH_CS_DEASSERT;
+    
+    SSP0_FLUSH_RX_FIFO;
+    
+    /* Wait until the flash device has the WEL bit on. */
+    while ((LPC_SSP0->DR & 0x2) == 0) {            
+        FLASH_CS_ASSERT;
+        FLASH_SHORT_COMMAND(FLASH_RDSR);
+        SSP0_FLUSH_RX_FIFO;
+        SSP0_WRITE_BYTE(0);
+        while (SSP0_IS_BUSY);
+        FLASH_CS_DEASSERT;
+    }
+
+    FLASH_CS_ASSERT;
+    FLASH_SHORT_COMMAND(FLASH_BE);
+    FLASH_CS_DEASSERT;
+    
+    /* Note, a bulk erase takes much longer than
+       a page write (typical 8s by the datasheet)
+       so there's no point making the first timeout
+       very short and producing a lot of uneeded 
+       interrupts. So we set the first timeout to
+       be 8000 and then it'll switch to a much shorter
+       time in the ISR. */
+    rit_timer_set_counter(FLASH_WRITE_CB, 8000);
+    return 1;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/flash_read.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,177 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "flash.h"
+#include "dma.h"
+#include "ssp0.h"
+#include "gpio.h"
+#include "user.h"
+#include "debug.h"
+
+bool page_read_in_progress = false;
+
+/* Local function prototypes. */
+static int _flash_read_page(unsigned int page_address, char *buffer);
+
+void flash_read_page(unsigned int page_address, char *buffer, bool block) {
+    _flash_read_page(page_address, buffer);
+    
+    if (block) {
+        while(page_read_in_progress) {
+            WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+        }
+    }
+}
+
+/** flash_read_in_progress
+ */
+bool flash_read_in_progress(void) {
+    return page_read_in_progress;
+}
+
+/** flash_read_page
+ * 
+ * Load the given flash page into the supplied buffer.
+ *
+ * @param unsigned int the page to load, between 0 and 4095
+ * @param char * buffer The RAM buffer to load the page to.
+ */
+static int _flash_read_page(unsigned int page_address, char *buffer) {
+
+    /* We can't read a page while a write or erase is in progress. */    
+    if (flash_write_in_progress() || flash_sector_erase_in_progress()) {
+        return 0;
+    }
+    
+    /* Wait for any previous read operation to complete. */
+    while (page_read_in_progress) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    /* Mark a read is in operation. */
+    page_read_in_progress = true; 
+    
+    /* Request use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    /* Ensure the SSP1 RX FIFO is empty. */
+    SSP0_FLUSH_RX_FIFO;
+    
+    /* Send the command and page read to the flash device. */
+    FLASH_CS_ASSERT;
+    FLASH_LONG_COMMAND(FLASH_READ, page_address);
+    
+    /* We use two DMA channels to achieve the required results.
+       The higher priority channel0 is used to drive the SSP0
+       SCLK0 pin with "don't care" bytes. We do this to flush 
+       the bytes out of the flash device. We then use Channel1 
+       to transfer the incoming bytes to RAM. */
+
+    while(!DMA_request_channel(0)) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    while(!DMA_request_channel(1)) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+
+    LPC_GPDMA->DMACIntTCClear = 0x3;
+    LPC_GPDMA->DMACSoftSReq   = 0xC;
+    
+    /* Prep Channel1 to receive the incoming byte stream. */
+    LPC_GPDMACH1->DMACCSrcAddr  = (uint32_t)&LPC_SSP0->DR;
+    LPC_GPDMACH1->DMACCDestAddr = (uint32_t)buffer;
+    LPC_GPDMACH1->DMACCLLI      = 0;
+    LPC_GPDMACH1->DMACCControl  = DMA_CHANNEL_TCIE | DMA_CHANNEL_DST_INC | (uint32_t)FLASH_PAGE_SIZE;
+    
+    /* Prep Channel0 to send "don't care" bytes in order to clock out the data from the flash device. */
+    LPC_GPDMACH0->DMACCSrcAddr  = (uint32_t)buffer; /* don't care data. */
+    LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR;
+    LPC_GPDMACH0->DMACCLLI      = 0;
+    LPC_GPDMACH0->DMACCControl  = DMA_CHANNEL_TCIE | (uint32_t)FLASH_PAGE_SIZE;
+    
+    /* Enable SSP0 DMA. */
+    LPC_SSP0->DMACR = 0x3;
+
+    /* Enable Channel0 */
+    LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | 
+                                DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | 
+                                DMA_TRANSFER_TYPE_M2P |
+                                DMA_MASK_IE |
+                                DMA_MASK_ITC;
+    
+    /* Wait until at least one byte has arrived into the RX FIFO
+       and then start-up the Channel1 DMA to begin transferring them. */
+    while((LPC_SSP0->SR & (1UL << 2)) == 0);
+    
+    /* Enable Channel1 */
+    LPC_GPDMACH1->DMACCConfig = DMA_CHANNEL_ENABLE | 
+                                DMA_CHANNEL_SRC_PERIPHERAL_SSP0_RX | 
+                                DMA_TRANSFER_TYPE_P2M |
+                                DMA_MASK_IE |
+                                DMA_MASK_ITC;
+                                
+    /* SSP0 CS line and "page_read_in_progress" flag are now 
+       under DMA/SSP0 interrupt control. See the DMA ISR handlers 
+       and SSP0 ISR handlers for more information. */
+       
+    return 1;   
+}
+
+/** flash_read_ssp0_irq
+ * 
+ * Called by the SSP0 ISR handler.
+ */
+int flash_read_ssp0_irq(void) {
+    if (page_read_in_progress) {
+        if (LPC_SSP0->MIS & (1UL << 3)) {
+            LPC_SSP0->IMSC &= ~(1UL << 3); 
+            while(SSP0_IS_BUSY);
+            FLASH_CS_DEASSERT;
+            SSP0_release();
+            page_read_in_progress = false; 
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/* The following two functions are the DMA ISR handlers. They are
+   called from dma.c so see that module for more details. */
+   
+/** flash_read_dma0_irq
+ */
+int flash_read_dma0_irq(int channel_number) {
+    if (page_read_in_progress) {
+        LPC_GPDMACH0->DMACCConfig = 0;
+        DMA_release_channel(0);        
+        return 1;        
+    }
+    return 0;
+}
+
+/** flash_read_dma1_irq
+ */
+int flash_read_dma1_irq(int channel_number) {
+    if (page_read_in_progress) {
+        LPC_GPDMACH1->DMACCConfig = 0;
+        DMA_release_channel(1);
+        LPC_SSP0->IMSC = (1UL << 3);
+        return 1;        
+    }
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/flash_write.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,224 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "flash.h"
+#include "ssp0.h"
+#include "dma.h"
+#include "gpio.h"
+#include "rit.h"
+#include "user.h"
+#include "utils.h"
+#include "debug.h"
+
+/* Flags to show what state we are in. */
+bool page_write_in_progress = false;
+bool page_write_buffer_in_use = false;
+
+/* Flag used by the flash_erase.c file. */
+extern bool sector_erase_in_progress;
+
+/* Buffer used to hold a copy of the page to write. Used
+   to ensure the DMA has a valid buffer to copy. */
+char flash_page_write_buffer[FLASH_PAGE_SIZE];
+
+/** flash_write_in_progress
+ */
+bool flash_write_in_progress(void) {
+    return page_write_in_progress;
+}
+
+/** flash_page_write
+ */
+int flash_page_write(int page, char *buffer) {
+    
+    /* Wait for the write page buffer to be released by
+       the DMA ISR handler, if in use, then make a copy
+       of the source buffer for the DMA. */
+    while (page_write_buffer_in_use) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    memcpy(flash_page_write_buffer, buffer, FLASH_PAGE_SIZE);
+    page_write_buffer_in_use = true;
+
+    
+    /* Below this we check for conditions that should stall 
+       us before continuing. However, sector erase is different,
+       it can take quite some time to complete. If this is the
+       case, rather than block (wait), we'll return zero (not
+       done) and allow the caller to schedule a write later. */
+    if (sector_erase_in_progress) return 0;
+    
+    /* Do not start a page write while another page write
+       is in progress. This flag is released by the RIT
+       timer callback when the WIP flag shows a previous
+       write has completed. */    
+    while(page_write_in_progress) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+
+    /* Do not start a page write while a page read is in operation. */
+    while (flash_read_in_progress()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+
+    /* Request DMA channel0. */
+    while(!DMA_request_channel(0)) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    /* Request the use of SSP0. */
+    while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
+    
+    /* Flag a write is in progress. */    
+    page_write_in_progress = true;
+    
+    /* Switch on WIP/WEL. */
+    FLASH_CS_ASSERT;       
+    FLASH_SHORT_COMMAND(FLASH_WREN);        
+    FLASH_CS_DEASSERT;
+
+    /* Originally I dropped into a do { ... } while(); here but
+       found the time between the CS deassert and reassert inside
+       the loop was *very* short and the flash device wasn't to
+       keen on this. So, I switched to a "flush rx fifo" and the
+       use a while() { ... } loop, just puts some delay between
+       the CS manipulation. */
+    SSP0_FLUSH_RX_FIFO;
+    
+    /* Wait until the flash device has the WEL bit on. */
+    while ((LPC_SSP0->DR & 0x2) == 0) {            
+        FLASH_CS_ASSERT;
+        FLASH_SHORT_COMMAND(FLASH_RDSR);
+        SSP0_FLUSH_RX_FIFO;
+        SSP0_WRITE_BYTE(0);
+        while (SSP0_IS_BUSY);
+        FLASH_CS_DEASSERT;
+    }
+    
+    FLASH_CS_ASSERT;
+    FLASH_LONG_COMMAND(FLASH_PP, page); 
+
+    LPC_GPDMA->DMACIntTCClear = 0x1;
+    LPC_GPDMA->DMACSoftSReq   = 0xC;
+        
+    /* Prep Channel0 to send the buffer to the flash device. */
+    LPC_GPDMACH0->DMACCSrcAddr  = (uint32_t)flash_page_write_buffer;
+    LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR;
+    LPC_GPDMACH0->DMACCLLI      = 0;
+    LPC_GPDMACH0->DMACCControl  = DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | (uint32_t)FLASH_PAGE_SIZE;
+    
+    /* Enable SSP0 DMA. */
+    LPC_SSP0->DMACR = 0x2;
+
+    /* Enable Channel0 */
+    LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | 
+                                DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | 
+                                DMA_TRANSFER_TYPE_M2P |
+                                DMA_MASK_IE |
+                                DMA_MASK_ITC;
+    
+                                
+    /* SSP0 CS line and "page_write_in_progress" flag are now 
+       under DMA/SSP0 interrupt control. See ISR handlers for 
+       more information. */
+       
+    return 1;
+}
+
+/** _flash_write_timer_callback
+ *
+ * RIT timer callback.
+ *
+ * After the write operation is complete this callback
+ * is used to examine the WIP flag in the flash status
+ * register. If it's still set then we reset the timer
+ * and try again in the future. If it's clear then we
+ * can mark the process as complete.
+ *
+ * @param int index The index of the timer the RIT modulr used.
+ */
+void _flash_write_timer_callback(int index) {
+    uint32_t sr = 1;
+    
+    /* Read the WIP flag from the flash device status
+       register and if the write cycle is complete mark
+       the operation as complete. Otherwise, reset the
+       timer to test again in the future. */
+    FLASH_CS_ASSERT;
+    FLASH_SHORT_COMMAND(FLASH_RDSR);
+    SSP0_WRITE_BYTE(0);
+    while (SSP0_IS_BUSY);
+    FLASH_CS_DEASSERT;
+    while(LPC_SSP0->SR & (1UL << 2)) {
+        /* This loop ensures we read the last byte in the
+           RX FIFO and test that. */
+        sr = LPC_SSP0->DR;
+    }
+    if (sr & 0x1) {
+        if (sector_erase_in_progress) rit_timer_set_counter(index, 100);
+        else rit_timer_set_counter(index, FLASH_WIP_TEST_TIME);
+    }
+    else {
+        FLASH_CS_ASSERT;
+        FLASH_SHORT_COMMAND(FLASH_WRDI);
+        SSP0_FLUSH_RX_FIFO;
+        FLASH_CS_DEASSERT;
+        if (sector_erase_in_progress) sector_erase_in_progress = false;
+        if (page_write_in_progress)   page_write_in_progress = false;
+        SSP0_release();
+    }
+}
+
+/** flash_write_dma0_irq
+ *
+ * DMA transfer irq callback. 
+ */
+int flash_write_dma0_irq(int channel) {
+    int rval = 0;
+    
+    /* If we were using DMA to transfer our buffer to the flash
+       device then mark the buffer as "released" and no longer 
+       in use, release the DMA channel and start the "detect WIP
+       indicates complete" timer. */
+    if (page_write_buffer_in_use) {
+        page_write_buffer_in_use = false;
+        LPC_GPDMACH0->DMACCConfig = 0;
+        DMA_release_channel(0);
+        LPC_SSP0->IMSC = (1UL << 3);
+        rit_timer_set_counter(FLASH_WRITE_CB, FLASH_WIP_TEST_TIME);
+        rval = 1;
+    }
+        
+    return rval;
+}
+
+/** flash_read_ssp0_irq
+ * 
+ * Called by the SSP0 ISR handler.
+ */
+int flash_write_ssp0_irq(void) {
+    if (page_write_in_progress) {
+        if (LPC_SSP0->MIS & (1UL << 3)) {
+            LPC_SSP0->IMSC &= ~(1UL << 3); 
+            while(SSP0_IS_BUSY);            
+            FLASH_CS_DEASSERT;            
+            SSP0_release();
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/ssp0.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,124 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "debug.h"
+#include "ssp0.h"
+
+bool ssp0_in_use;
+
+bool SSP0_request(void) {
+    if (!ssp0_in_use) {
+        ssp0_in_use = true;
+        return true;
+    }
+    return false;
+}
+
+void SSP0_release(void) {
+    ssp0_in_use = false;
+}
+
+/* Declare ISR callbacks. */
+extern int flash_read_ssp0_irq(void);
+extern int flash_write_ssp0_irq(void);
+
+/* Function pointer type for the following table. */
+typedef int (*SSP0_callback)(void);
+
+/* Define an array of callbacks to make. */
+const SSP0_callback ssp0_callbacks[] = {
+    flash_read_ssp0_irq,
+    flash_write_ssp0_irq,
+    NULL
+};
+
+/** SSP0_IRQHandler
+ */
+extern "C" void SSP0_IRQHandler(void) __irq {
+    for (int i = 0; ssp0_callbacks[i] != NULL; i++) {
+        if ((ssp0_callbacks[i])() != 0) {
+            break;
+        }
+    }
+}
+
+/** SSP0_init
+ */
+void SSP0_init(void) {
+
+    DEBUG_INIT_START;
+    
+    ssp0_in_use = false;
+    
+    /* The flash device is connected to SSP1 via the Mbed pins.
+       So this init is about configuring just the SSP1. */
+    
+    /* Enable the SSP1 peripheral. */
+    //LPC_SC->PCONP |= (1UL << 10);
+    LPC_SC->PCONP |= (1UL << 21);
+
+    /* Select the clock required for SSP1. */
+    LPC_SC->PCLKSEL1  &= ~(3UL << 10);
+    LPC_SC->PCLKSEL1  |=  (3UL << 10);
+    //LPC_SC->PCLKSEL0  &= ~(3UL << 20);
+    //LPC_SC->PCLKSEL0  |=  (3UL << 20);
+    
+    /* Select the GPIO pins for the SSP0 functions. */
+    /* SCK0 */
+    LPC_PINCON->PINSEL0  &= ~(3UL << 30);
+    LPC_PINCON->PINSEL0  |=  (2UL << 30);
+    /* MISO0 */
+    LPC_PINCON->PINSEL1  &= ~(3UL << 2);
+    LPC_PINCON->PINSEL1  |=  (2UL << 2);
+    /* MISI0 */
+    LPC_PINCON->PINSEL1  &= ~(3UL << 4);
+    LPC_PINCON->PINSEL1  |=  (2UL << 4);
+
+    /* Select the GPIO pins for the SSP1 functions. */
+    /* SCK1 */
+    //LPC_PINCON->PINSEL0  &= ~(3UL << 14);
+    //LPC_PINCON->PINSEL0  |=  (2UL << 14);
+    /* MISO1 */
+    //LPC_PINCON->PINSEL0  &= ~(3UL << 16);
+    //LPC_PINCON->PINSEL0  |=  (2UL << 16);
+    /* MOSI1 */
+    //LPC_PINCON->PINSEL0  &= ~(3UL << 18);
+    //LPC_PINCON->PINSEL0  |=  (2UL << 18);
+    
+    /* Note, we don't use SSEL1 in our design, we just use a standard GPIO
+       because writing multi-byte data is simpler. */
+    
+    /* Setup the interrupt system. Note however, the SSP1 interrupt
+       is only actually activated within the DMA ISR and is self disabling. */
+    NVIC_SetVector(SSP0_IRQn, (uint32_t)SSP0_IRQHandler);
+    NVIC_EnableIRQ(SSP0_IRQn);
+    
+    /* Setup the control registers for SSP1 */
+    LPC_SSP0->IMSC = 0;
+    LPC_SSP0->CR0  = 0x7;
+    LPC_SSP0->CPSR = FLASH_SSP_INIT_CPSR;
+    LPC_SSP0->CR1  = 0x2;
+    
+    DEBUG_INIT_END;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash/ssp0.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,53 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef SSP0_H
+#define SSP0_H
+
+#define FLASH_SSP_INIT_CPSR 2
+#define _25AA02E48_SSP_INIT_CPSR 0x64
+
+
+#define SSP0_TX_FIFO_SPACE_AVAILABLE  \
+    LPC_SSP0->SR & (1UL << 1)
+
+#define SSP0_TX_FIFO_NOT_EMPTY \
+    (!(SSP0_TX_FIFO_SPACE_AVAILABLE))
+
+#define SSP0_IS_BUSY \
+    LPC_SSP0->SR & (1UL << 4)
+
+#define SSP0_FLUSH_RX_FIFO  \
+    while(LPC_SSP0->SR & (1UL << 2)) { \
+        unsigned int dev_null = LPC_SSP0->DR; \
+    }
+
+#define SSP0_WRITE_BYTE(byte)         \
+    while(!SSP0_TX_FIFO_SPACE_AVAILABLE);  \
+    LPC_SSP0->DR=(uint32_t)(byte&0xFF)
+    
+
+void SSP0_init(void);
+bool SSP0_request(void);
+void SSP0_release(void);
+
+#endif    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpio/gpio.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,115 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+ #include "sowb.h"
+ #include "debug.h"
+ #include "gpio.h"
+ 
+ 
+ /** gpio_init
+  */
+ void gpio_init(void) {
+ 
+    DEBUG_INIT_START;
+    
+    /* The following code could be condensed into a single set of
+       and/or statements. However, for code clarity they are laid
+       out on a "use case" way to see each pin being defined. Since
+       this is "init" code and only called once at start-up, the
+       extra overhead isn't worth the effort over cleaner to read
+       code. */
+       
+    /* The MAX7456 module uses p0.23 (p15) for it's chip select
+       output. Define it's setup here and use the macros in gpio.h
+       to assert, deassert or read the pin. */
+    //LPC_PINCON->PINSEL1 &= ~(3UL << 14);  /* Function GPIO. */
+    //LPC_GPIO0->FIODIR   |=  (1UL << 23);  /* P0.23 as output. */
+    
+    /* The MAX7456 module uses p0.16 (p14) for it's chip select
+       output. Define it's setup here and use the macros in gpio.h
+       to assert, deassert or read the pin. */
+    //LPC_PINCON->PINSEL1 &= ~(3UL << 14);  /* Function GPIO. */
+    //LPC_GPIO0->FIODIR   |=  (1UL << 16);  /* P0.23 as output. */
+
+    /* The MAX7456 module uses p0.6 (p8) for it's chip select
+       output. Define it's setup here and use the macros in gpio.h
+       to assert, deassert or read the pin. */
+    LPC_PINCON->PINSEL0 &= ~(3UL << 12);  /* Function GPIO. */
+    LPC_GPIO0->FIODIR   |=  (1UL <<  6);  /* P0.6 as output. */       
+
+             
+    /* The MAX7456 module uses p1.31 (p20) for it's reset output.
+       Define it's setup here and use the macros in gpio.h to assert, 
+       deassert or read the pin. */
+    LPC_PINCON->PINSEL3 &= ~(3UL << 30);  /* Function GPIO. */
+    LPC_GPIO1->FIODIR   |=  (1UL << 31);  /* P1.31 as output. */
+    
+    /* We use p0.25 (p17) for the SD Card detect. */
+    LPC_PINCON->PINSEL1 &= ~(3UL << 18);  /* Function GPIO. */
+    LPC_GPIO0->FIODIR   &= ~(1UL << 25);  /* P0.25 as Input. */
+    
+    /* We use p0.16 (p14) for the Flash device SSP0 CS signal. */
+    LPC_PINCON->PINSEL1 &= ~(3UL << 14);  /* Function GPIO. */
+    LPC_GPIO0->FIODIR   |=  (1UL << 16);  /* P0.23 as output. */
+
+    /* We use p0.24 (p16) for the 25AA02E48 device SSP0 CS signal. */
+    LPC_PINCON->PINSEL1 &= ~(3UL << 14);  /* Function GPIO. */
+    LPC_GPIO0->FIODIR   |=  (1UL << 24);  /* P0.24 as output. */ 
+    
+    /* We use p1.30 (p19) for the MicroSD card device SSP0 CS signal. */
+    LPC_PINCON->PINSEL3 &= ~(3UL << 28);  /* Function GPIO. */
+    LPC_GPIO1->FIODIR   |=  (1UL << 30);  /* P1.30 as output. */    
+    
+    /* We use p2.5 (p21) for debugging. */
+    LPC_PINCON->PINSEL4 &= ~(3UL << 10);  /* Function GPIO. */
+    LPC_GPIO2->FIODIR   |=  (1UL << 5);  /* P2.5 as output. */
+    
+    /* We use p2.4 (p22) for debugging. */
+    LPC_PINCON->PINSEL4 &= ~(3UL << 8);  /* Function GPIO. */
+    LPC_GPIO2->FIODIR   |=  (1UL << 4);  /* P2.4 as output. */
+    
+    
+#ifdef MBED_LEDS
+    /* The MBED has four useful little blue LEDs that can be used. 
+       Mbed examples use the DigitalOut led1(LED1) style. Mimic that
+       using our system here. Here however, I will use shorthand ;)     
+                                LED1           LED2           LED3           LED4     */
+    LPC_PINCON->PINSEL3 &= ( ~(3UL <<  4) & ~(3UL <<  8) & ~(3UL << 10) & ~(3UL << 14) );  
+    LPC_GPIO1->FIODIR   |= (  (1UL << 18) |  (1UL << 20) |  (1UL << 21) |  (1UL << 23) );
+#endif
+    
+    
+    SSP0_CS_DEASSERT;
+    FLASH_CS_DEASSERT;
+    SDCARD_CS_DEASSERT;
+    AA02E48_CS_DEASSERT;
+    MAX7456_CS_DEASSERT;
+    
+    DEBUG_INIT_END;
+}
+ 
+/** gpio_process
+ */
+void gpio_process(void) {
+   /* Does nothing, no house keeping required. */
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpio/gpio.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,135 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef GPIO_H
+#define GPIO_H
+
+/* Switch on our macros to use the 4 LEDs on the Mbed. */
+#define MBED_LEDS
+ 
+/* Used by the MAX7456 module. 
+   The MAX7456 !cs signal is connected to Mbed pin 8
+   which is internally connected to Port0.6 */
+#define SET_P0_06       (LPC_GPIO0->FIOSET = (1UL << 6))
+#define CLR_P0_06       (LPC_GPIO0->FIOCLR = (1UL << 6))
+#define VAL_P0_06       (LPC_GPIO0->FIOPIN & (1UL << 6))
+#define MAX7456_CS_ASSERT      CLR_P0_06
+#define MAX7456_CS_DEASSERT    SET_P0_06
+#define MAX7456_CS_VALUE       VAL_P0_06
+#define MAX7456_CS_TOGGLE      MAX7456_CS_VALUE ? MAX7456_CS_DEASSERT : MAX7456_CS_ASSERT
+
+/* Used by the MAX7456 module. 
+   The MAX7456 !rst signal is connected to Mbed pin 20
+   which is internally connected to Port1.31 */
+#define SET_P1_31      (LPC_GPIO1->FIOSET = (1UL << 31))
+#define CLR_P1_31      (LPC_GPIO1->FIOCLR = (1UL << 31))
+#define VAL_P1_31      (LPC_GPIO1->FIOPIN & (1UL << 31))
+#define MAX7456_RST_ASSERT     CLR_P1_31
+#define MAX7456_RST_DEASSERT   SET_P1_31
+#define MAX7456_RST_VALUE      VAL_P1_31
+#define MAX7456_RST_TOGGLE     MAX7456_RST_VALUE ? MAX7456_RST_DEASSERT : MAX7456_RST_ASSERT
+#define SSP0_CS_ASSERT         CLR_P1_31
+#define SSP0_CS_DEASSERT       SET_P1_31
+#define SSP0_CS_VALUE          VAL_P1_31
+#define SSP0_CS_TOGGLE         MAX7456_RST_VALUE ? MAX7456_RST_DEASSERT : MAX7456_RST_ASSERT
+
+/* Used by the flash module. 
+   The flash !cs signal is connected to Mbed pin 14
+   which is internally connected to Port0.16 */
+#define SET_P0_16      (LPC_GPIO0->FIOSET = (1UL << 16))
+#define CLR_P0_16      (LPC_GPIO0->FIOCLR = (1UL << 16))
+#define VAL_P0_16      (LPC_GPIO0->FIOPIN & (1UL << 16))
+#define FLASH_CS_ASSERT         CLR_P0_16
+#define FLASH_CS_DEASSERT       SET_P0_16
+#define FLASH_CS_VALUE          VAL_P0_16
+#define FLASH_CS_TOGGLE         FLASH_CS_VALUE ? FLASH_CS_DEASSERT : FLASH_CS_ASSERT
+
+/* Used by the 25AA02E48 module. 
+   The device !cs signal is connected to Mbed pin 16
+   which is internally connected to Port0.24 */
+#define SET_P0_24      (LPC_GPIO0->FIOSET = (1UL << 24))
+#define CLR_P0_24      (LPC_GPIO0->FIOCLR = (1UL << 24))
+#define VAL_P0_24      (LPC_GPIO0->FIOPIN & (1UL << 24))
+#define AA02E48_CS_ASSERT       CLR_P0_24
+#define AA02E48_CS_DEASSERT     SET_P0_24
+#define AA02E48_CS_VALUE        VAL_P0_24
+#define AA02E48_CS_TOGGLE       AA02E48_CS_VALUE ? AA02E48_CS_DEASSERT : AA02E48_CS_ASSERT
+
+/* Used by the SD card. 
+   The device !cs signal is connected to Mbed pin 19
+   which is internally connected to Port1.30 */
+#define SET_P1_30      (LPC_GPIO1->FIOSET = (1UL << 30))
+#define CLR_P1_30      (LPC_GPIO1->FIOCLR = (1UL << 30))
+#define VAL_P1_30      (LPC_GPIO1->FIOPIN & (1UL << 30))
+#define SDCARD_CS_ASSERT       CLR_P1_30
+#define SDCARD_CS_DEASSERT     SET_P1_30
+#define SDCARD_CS_VALUE        VAL_P1_30
+#define SDCARD_CS_TOGGLE       SDCARD_CS_VALUE ? SDCARD_CS_DEASSERT : SDCARD_CS_ASSERT
+
+/* Used for reading the SD Card detect pin. */
+#define SDCARD_DETECT   (LPC_GPIO0->FIOPIN & (1UL << 25))       
+
+/* For debugging. 
+   Mbed pin 21 which is internally connected to Port2.5 */
+#define SET_P2_05      (LPC_GPIO2->FIOSET = (1UL << 5))
+#define CLR_P2_05      (LPC_GPIO2->FIOCLR = (1UL << 5))
+#define VAL_P2_05      (LPC_GPIO2->FIOPIN & (1UL << 5))
+#define P21_ASSERT     SET_P2_05
+#define P21_DEASSERT   CLR_P2_05
+#define P21_VALUE      VAL_P2_05
+#define P21_TOGGLE     P21_VALUE ? P21_DEASSERT : P21_ASSERT
+
+/* For debugging. 
+   Mbed pin 22 which is internally connected to Port2.4 */
+#define SET_P2_04      (LPC_GPIO2->FIOSET = (1UL << 4))
+#define CLR_P2_04      (LPC_GPIO2->FIOCLR = (1UL << 4))
+#define VAL_P2_04      (LPC_GPIO2->FIOPIN & (1UL << 4))
+#define P22_ASSERT     SET_P2_04
+#define P22_DEASSERT   CLR_P2_04
+#define P22_VALUE      VAL_P2_04
+#define P22_TOGGLE     P22_VALUE ? P22_DEASSERT : P22_ASSERT
+
+#ifdef MBED_LEDS
+#define LED1_ON        (LPC_GPIO1->FIOSET = (1UL << 18))
+#define LED1_OFF       (LPC_GPIO1->FIOCLR = (1UL << 18))
+#define LED1_IS_ON     (LPC_GPIO1->FIOPIN & (1UL << 18))
+#define LED1_TOGGLE    LED1_IS_ON ? LED1_OFF : LED1_ON
+#define LED2_ON        (LPC_GPIO1->FIOSET = (1UL << 20))
+#define LED2_OFF       (LPC_GPIO1->FIOCLR = (1UL << 20))
+#define LED2_IS_ON     (LPC_GPIO1->FIOPIN & (1UL << 20))
+#define LED2_TOGGLE    LED2_IS_ON ? LED2_OFF : LED2_ON
+#define LED3_ON        (LPC_GPIO1->FIOSET = (1UL << 21))
+#define LED3_OFF       (LPC_GPIO1->FIOCLR = (1UL << 21))
+#define LED3_IS_ON     (LPC_GPIO1->FIOPIN & (1UL << 21))
+#define LED3_TOGGLE    LED3_IS_ON ? LED3_OFF : LED3_ON
+#define LED4_ON        (LPC_GPIO1->FIOSET = (1UL << 23))
+#define LED4_OFF       (LPC_GPIO1->FIOCLR = (1UL << 23))
+#define LED4_IS_ON     (LPC_GPIO1->FIOPIN & (1UL << 23))
+#define LED4_TOGGLE    LED4_IS_ON ? LED4_OFF : LED4_ON
+#endif
+ 
+/* Function prototypes. */
+void gpio_init(void);
+void gpio_process(void);
+ 
+#endif
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpioirq/gpioirq.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,88 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "debug.h"
+#include "gpioirq.h"
+
+/* Declare the external interrupt callback functions. */
+extern void MAX7456_vsync_rise(void);
+extern void MAX7456_vsync_fall(void);
+//extern void max7456_los_rise(void);
+//extern void max7456_los_fall(void);
+extern void gps_pps_rise(void);
+extern void gps_pps_fall(void);
+
+/** EINT3_IRQHandler
+ */
+extern "C" void GPIOIRQ_IRQHandler (void) {
+    
+    /* Test for IRQ on Port0. */
+    if (LPC_GPIOINT->IntStatus & 0x1) {
+        
+        /* GPS PPS is connected to MBED P29 (Port0.5) */
+        //if (LPC_GPIOINT->IO0IntStatR & (1 << 5))  gps_pps_rise();      
+
+        /* GPS PPS is connected to MBED P29 (Port0.5) */
+        if (LPC_GPIOINT->IO0IntStatF & (1 << 5))  gps_pps_fall();
+
+        /* MAX7456 Vertical Sync is connected to MBED P15 (Port0.23) */
+        if (LPC_GPIOINT->IO0IntStatF & (1 << 23)) MAX7456_vsync_fall();
+        
+        /* MAX7456 LOS is connected to P17 (Port0.25) */
+        //if (LPC_GPIOINT->IO0IntStatR & (1 << 25)) max7456_los_rise();  
+
+        LPC_GPIOINT->IO0IntClr = (LPC_GPIOINT->IO0IntStatR | LPC_GPIOINT->IO0IntStatF);
+    }
+
+    /* Test for IRQ on Port2. */
+    if (LPC_GPIOINT->IntStatus & 0x4) {
+                
+        LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
+    }
+}
+ 
+/** gpioirq_init
+ */
+void gpioirq_init(void) {
+
+    DEBUG_INIT_START;
+    
+    /* Enable the interrupts for connected signals. 
+       For bit definitions see the ISR function above. */
+    LPC_GPIOINT->IO0IntEnR |= ( (1UL << 5) | (1UL << 25) | (1UL << 23) );
+    LPC_GPIOINT->IO0IntEnF |= ( (1UL << 5) | (1UL << 25) | (1UL << 23) );
+    //LPC_GPIOINT->IO2IntEnR |= ( (1UL << 5) );
+    //LPC_GPIOINT->IO2IntEnF |= ( (1UL << 5) );
+    
+    NVIC_SetVector(EINT3_IRQn, (uint32_t)GPIOIRQ_IRQHandler);
+    NVIC_EnableIRQ(EINT3_IRQn);
+    
+    DEBUG_INIT_END;
+}
+
+void gpioirq_process(void) {
+    /* Does nothing, no periodic house keeping required. */
+}
+
+ 
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpioirq/gpioirq.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,30 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef GPIOIRQ_H
+#define GPIOIRQ_H
+
+/* Function prototypes. */
+void gpioirq_init(void);
+void gpioirq_process(void);
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gps/gps.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,670 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/*
+    Implementation notes.
+    The SOWB reads GPS data in on RDX1. We don't use TDX1 as we use it as part 
+    of the SSP/SPI for the MAX7456/Flash card reader. However, we are not really
+    interested in writing to the GPS module as the most crucial data is the time
+    rather than the location. We do use the location data but we don't need any
+    WAAS data correction, 10metres is enough accuracy. So we only use Uart1 Rx to 
+    get data.
+    
+    Additionally, the GPS 1 pulse per second signal is connected to a P29 (P0.5)
+    and the gpioirq.c module routes that interrupt back to us via the _gps_pps_irq()
+    callback function.    
+*/ 
+
+#include "sowb.h"
+#include "rit.h"
+#include "gpio.h"
+#include "gps.h"
+#include "math.h"
+#include "debug.h"
+
+/* Module global variables. */
+double              lat_average;
+double              lon_average;
+double              lat_history[GPS_HISTORY_SIZE];
+double              lon_history[GPS_HISTORY_SIZE];
+int                 history_in_index;
+int                 history_complete;
+GPS_TIME            the_time; 
+GPS_LOCATION_RAW    the_location;
+
+double              lat_acc_average;
+double              lon_acc_average;
+double              cnt_acc_average;
+
+/* We maintain two serial input buffers so that the
+   _process() function can be processing one buffer
+   while the serial interrupt system can be capturing 
+   to the other. */
+char uart1_buffer[2][GPS_BUFFER_SIZE];
+
+#define UART1_BUFFER_A  0
+#define UART1_BUFFER_B  1
+
+char active_buffer, active_buffer_in;
+char passive_buffer_ready;
+
+/* Update flag to signal new data in the active buffer. */
+char have_new_location;
+
+/* Set to non-zero by the updater interrupts. */
+char time_updated;
+char location_updated;
+
+/* Internal function prototypes. */
+void _gps_process_rmc(char passive_buffer);
+void _gps_process_gga(char passive_buffer);
+void _gps_time_inc(GPS_TIME *q);
+void _gps_date_inc(GPS_TIME *q);
+void _gps_timer_tick_cb(int);
+void _gps_pps_alive_cb(int);
+void Uart1_init(void);
+
+/** gps_process
+ */
+void gps_process(void) {
+    int i, j;
+    uint32_t ier_copy;
+    char passive_buffer;
+    double lat_temp, lon_temp;
+    
+    if (passive_buffer_ready == 1) {
+        /* Disable serial interrupts on UART1 */   
+        ier_copy = LPC_UART1->IER;
+        LPC_UART1->IER = 0x0;
+    
+        /* What index is the passive buffer, i.e., what is the opposite
+           of the current active buffer? */
+        passive_buffer = active_buffer == 0 ? 1 : 0;
+        
+        if (!strncmp(uart1_buffer[passive_buffer], "$GPRMC", 6)) {
+            _gps_process_rmc(passive_buffer);
+        }
+        else if (!strncmp(uart1_buffer[passive_buffer], "$GPGGA", 6)) {
+            _gps_process_gga(passive_buffer);
+        }
+        
+        /* Flag we have completed processing the passive buffer. */
+        passive_buffer_ready = 0;
+        
+        /* Enable serial interrupts on UART1 */   
+        LPC_UART1->IER = ier_copy;
+    }
+    
+    /* Update the latitude/longitude moving average filter. */
+    if (the_location.is_valid && have_new_location != 0) {
+        have_new_location = 0;
+        lat_history[history_in_index] = gps_convert_coord(the_location.lat, GPS_LAT_STR);
+        lon_history[history_in_index] = gps_convert_coord(the_location.lon, GPS_LON_STR);
+        history_in_index++;
+        if (history_in_index >= GPS_HISTORY_SIZE) {
+            history_in_index = 0;
+            history_complete = 1;
+        }
+        j = history_complete == 1 ? GPS_HISTORY_SIZE+1 : history_in_index;
+        for(lat_temp = lon_temp = 0., i = 1; i < j; i++) {            
+            lat_temp += lat_history[i - 1];
+            lon_temp += lon_history[i - 1];        
+        }
+        if (i) {
+            lat_average = lat_temp / (double)(i - 1);
+            lon_average = lon_temp / (double)(i - 1);
+            location_updated = 1;
+        }
+    }  
+}
+
+/** _gps_process_rmc
+ *
+ * Extract the NMEA data from an RMC packet. 
+ * Sample:-
+ * $GPRMC,132555.639,A,5611.5374,N,00302.0325,W,000.0,129.3,020910,,,A*75
+ *
+ * @param char passive_buffer Which buffer holds the RMC packet data.
+ */
+void _gps_process_rmc(char passive_buffer) {
+    char *token;
+    int  token_counter = 0;
+    char *time   = (char *)NULL;
+    char *date   = (char *)NULL;
+    char *status = (char *)NULL;
+    
+    token = strtok(uart1_buffer[passive_buffer], ",");
+    while (token) {
+        switch (token_counter) {
+            case 9: date   = token; break;
+            case 1: time   = token; break;
+            case 2: status = token; break;
+        }
+        token = strtok((char *)NULL, ",");
+        token_counter++;
+    }
+    
+    if (status && date && time) {
+        the_time.hour       = (char)((time[0] - '0') * 10) + (time[1] - '0');
+        the_time.minute     = (char)((time[2] - '0') * 10) + (time[3] - '0');
+        the_time.second     = (char)((time[4] - '0') * 10) + (time[5] - '0');
+        the_time.day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
+        the_time.month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
+        the_time.year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
+        the_time.is_valid   = status[0] == 'A' ? 1 : 0;
+        the_time.prev_valid = 1;
+    }
+    else {
+        the_time.is_valid = 0;
+    }
+}
+
+/** _gps_process_gga
+ *
+ * Extract the NMEA data from a GGA packet. 
+ * Sample:-
+ * $GPGGA,132526.639,5611.5417,N,00302.0298,W,1,05,7.3,43.4,M,52.0,M,,0000*70
+ *
+ * @param char passive_buffer Which buffer holds the GGA packet data.
+ */
+void _gps_process_gga(char passive_buffer) {
+    char *token;
+    int  token_counter = 0;
+    char *latitude  = (char *)NULL;
+    char *longitude = (char *)NULL;
+    char *lat_dir   = (char *)NULL;
+    char *lon_dir   = (char *)NULL;
+    char *qual      = (char *)NULL;
+    char *altitude  = (char *)NULL;
+    char *sats      = (char *)NULL;
+    
+    token = strtok(uart1_buffer[passive_buffer], ",");
+    while (token) {
+        switch (token_counter) {
+                case 2:  latitude  = token; break;
+                case 4:  longitude = token; break;
+                case 3:  lat_dir   = token; break;    
+                case 5:  lon_dir   = token; break;    
+                case 6:  qual      = token; break;
+                case 7:  sats      = token; break;
+                case 9:  altitude  = token; break;
+        }
+        token = strtok((char *)NULL, ",");
+        token_counter++;
+    }
+
+    /* If the fix quality is valid set our location information. */
+    if (latitude && longitude && altitude && sats) { 
+        memcpy(the_location.lat, latitude,  10); /* Fixed length string. */
+        memcpy(the_location.lon, longitude, 10); /* Fixed length string. */
+        memset(the_location.alt, 0, sizeof(the_location.alt)); /* Clean string out first. */
+        strncpy(the_location.alt, altitude, 10); /* Variable length string. */
+        strncpy(the_location.sats, sats, 3);     /* Variable length string. */
+        the_location.north_south = lat_dir[0];
+        the_location.east_west   = lon_dir[0];
+        the_location.is_valid    = qual[0];
+        the_location.updated++;
+        have_new_location = 1;
+    }
+    else {
+        the_location.is_valid = qual[0];
+    }    
+}
+
+/** gps_convert_coord
+ *
+ * Given a string and a type convert the string into a double.
+ *
+ * @param char *s A pointer to the string to convert.
+ * @param int type The conversion type required (lat or lon)
+ * @return double the converted string.
+ */
+double gps_convert_coord(char *s, int type) {
+    int deg, min, sec;
+    double fsec, val;
+    
+    if (type == GPS_LAT_STR) {
+        deg  = ( (s[0] - '0') * 10) + s[1] - '0';
+        min  = ( (s[2] - '0') * 10) + s[3] - '0';
+        sec  = ( ((s[5] - '0') * 1000) + ((s[6] - '0') * 100) + ((s[7] - '0') * 10) + (s[8] - '0'));
+        fsec = (double)((double)sec /10000.0);
+        val  = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);
+        return val;
+    }
+    else {
+        deg  = ( (s[0] - '0') * 100) + ((s[1] - '0') * 10) + (s[2] - '0');
+        min  = ( (s[3] - '0') * 10) + s[4] - '0';
+        sec  = ( ((s[6] - '0') * 1000) + ((s[7] - '0') * 100) + ((s[8] - '0') * 10) + (s[9] - '0'));
+        fsec = (double)((double)sec /10000.0);
+        val  = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);
+        return val;
+    }
+}
+
+/** gps_init
+ */
+void gps_init(void) {
+    int i;
+    
+    DEBUG_INIT_START;
+    
+    /* Set the time to a known starting point in the past. */
+    the_time.year       = 2000;
+    the_time.month      = 1;
+    the_time.day        = 1;
+    the_time.hour       = 0;
+    the_time.minute     = 0;
+    the_time.second     = 0;
+    the_time.tenth      = 0;
+    the_time.hundreth   = 0;
+    the_time.is_valid   = 0;
+    the_time.prev_valid = 0;
+    
+    memset(&the_location, 0, sizeof(GPS_LOCATION_RAW));
+    
+    /* Initial condition. */
+    time_updated = 0;
+    
+    /* Zero out the moving average filter. */
+    lat_average = 0.;
+    lon_average = 0.;
+    history_in_index = 0;
+    history_complete = 0;
+    for(i = 0; i < GPS_HISTORY_SIZE; i++) {
+        lat_history[i] = 0.;
+        lon_history[i] = 0.;
+    }
+
+    lat_acc_average = 0.;
+    lon_acc_average = 0.;
+    cnt_acc_average = 0.;
+
+    /* Init the active buffer and the serial in pointer. */
+    active_buffer = active_buffer_in = 0;
+    
+    /* Flag the passive buffer is not ready. The passive buffer
+       is the opposite of the active buffer. When the serial irq
+       system detects the end of a NEMA message it automatically 
+       switches buffers and sets passive_buffer_ready non-zero to
+       indicate it's just finished dumping data into it. */
+    passive_buffer_ready = 0;
+    
+    /* Updated to non-zero after a new location packet is received. */
+    have_new_location = 0;
+    
+    /* Setup the 0.01second timer. */
+    rit_timer_set_reload(RIT_TIMER_CB_GPS, 10);  /* Recurring reload. */
+    rit_timer_set_counter(RIT_TIMER_CB_GPS, 10); /* Start timer. */
+    
+    DEBUG_INIT_END;
+    
+    Uart1_init();    
+}
+
+/** gps_get_time
+ * 
+ * Copies our internal time data structure to a buffer supplied by the caller.
+ *
+ * Note, the update flag is set to non-zero by the interrupt routines when an
+ * update occurs. The loop is to test if an update occured while the copy was
+ * in progress. If it did, do the copy again as it's most likely corrupted the
+ * orginal copy operation.
+ *
+ * @param GPS_TIME *q A pointer to the GPS_TIME data structure to copy to.
+ * @return GPS_TIME * The supplied pointer.
+ */
+GPS_TIME *gps_get_time(GPS_TIME *q) {
+
+    do {
+        time_updated = 0;
+        memcpy(q, &the_time, sizeof(GPS_TIME));
+    } while (time_updated != 0);
+    
+    return q;
+}
+
+/** gps_get_location_raw
+ * 
+ * Copies our internal location data structure to a buffer supplied by the caller.
+ *
+ * Note, the update flag is set to non-zero by the interrupt routines when an
+ * update occurs. The loop is to test if an update occured while the copy was
+ * in progress. If it did, do the copy again as it's most likely corrupted the
+ * orginal copy operation.
+ *
+ * @param GPS_LOCATION_RAW *q A pointer to the GPS_LOCATION_RAW data structure to copy to.
+ * @return GPS_LOCATION_RAW * The supplied pointer.
+ */
+GPS_LOCATION_RAW *gps_get_location_raw(GPS_LOCATION_RAW *q) {
+
+    do {
+        location_updated = 0;
+        memcpy(q, &the_location, sizeof(GPS_LOCATION_RAW));
+    } while (location_updated != 0);
+    
+    return q;
+}
+
+/** gps_get_location_average
+ *
+ * Places the current average location into the supplied struct buffer.
+ * The caller is responsible for allocating the buffer storage space.
+ *
+ * Note, the update flag is set to non-zero by the interrupt routines when an
+ * update occurs. The loop is to test if an update occured while the copy was
+ * in progress. If it did, do the copy again as it's most likely corrupted the
+ * orginal copy operation.
+ *
+ * @param GPS_LOCATION_AVERAGE *q A pointer to the struct buffer to write data to.
+ * @return GPS_LOCATION_AVERAGE *  The supplied pointer returned.
+ */
+GPS_LOCATION_AVERAGE *gps_get_location_average(GPS_LOCATION_AVERAGE *q) {
+    char **p = NULL;
+
+    do {
+        location_updated = 0;
+        q->north_south  = the_location.north_south;
+        q->latitude     = lat_average;
+        q->east_west    = the_location.east_west;
+        q->longitude    = lon_average;
+        q->height       = strtod(the_location.alt, p); 
+        q->sats         = the_location.sats;   
+        q->is_valid     = the_location.is_valid;
+    } while (location_updated != 0);
+
+    /* Test the values to ensure the data is valid. */
+    if (isnan(q->latitude) || isnan(q->longitude) || isnan(q->height)) {
+        q->is_valid = 0;
+    }
+    
+    return q;
+}
+
+/** gps_julian_day_number
+ *
+ * Gets the Julian Day Number from the supplied time reference passed.
+ * http://en.wikipedia.org/wiki/Julian_day#Converting_Gregorian_calendar_date_to_Julian_Day_Number
+ *
+ * @param GPS_TIME *t A pointer to a time data structure.
+ * @return double The Julian Day Number.
+ */
+double gps_julian_day_number(GPS_TIME *t) {
+    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;
+    
+    /* Not sure why yet but the calculation on the Wikipedia site returns a value that
+       is 0.5 too big. */
+    return wikipedia_jdn;
+}
+
+/** gps_julian_date
+ * 
+ * Find the Julian Date based on the supplied args.
+ *
+ * @param GPS_TIME *t A pointer to a time data structure.
+ * @return double The Julian Date.
+ */
+double gps_julian_date(GPS_TIME *t) {
+    double hour, minute, second, jd;
+    hour   = (double)t->hour;
+    minute = (double)t->minute;
+    second = (double)t->second + ((double)t->tenth / 10.) + ((double)t->hundreth / 100.);
+                                   /* Wiki fix, see above. */  
+    jd = gps_julian_day_number(t) -           0.5 +
+         ((hour - 12.) / 24.) +
+         (minute / 1440.) + 
+         (second / 86400.);        
+        
+    return jd;
+}
+
+/** gps_siderealDegrees_by_jd
+ *
+ * Calculate the sidereal degree angle based on the 
+ * Julian Date supplied.
+ *
+ * @param double jd Julian Date.
+ * @return The sidereal angle in degrees.
+ */
+double gps_siderealDegrees_by_jd(double jd) {
+    double sidereal, gmst, lmst, mul;
+    double T  = jd - 2451545.0;
+    double T1 = T / 36525.0;
+    double T2 = T1 * T1;
+    double T3 = T2 * T1;
+     
+    /* Calculate gmst angle. */
+    sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
+     
+    /* Convert to degrees. */
+    sidereal = fmod(sidereal, 360.0);
+    if (sidereal < 0.0) sidereal += 360.0;
+ 
+    mul = (the_location.east_west == 'W') ? -1.0 : 1.0;
+    
+    gmst = sidereal;
+    lmst = gmst + (lon_average * mul);
+    return lmst;
+}
+
+/** gps_siderealDegrees_by_time
+ *
+ * Calculate the sidereal degree angle based on the 
+ * time data structure supplied.
+ *
+ * @param GPS_TIME *t A pointer to the time structure.
+ * @return The sidereal angle in degrees.
+ */
+double gps_siderealDegrees_by_time(GPS_TIME *t) {
+    GPS_TIME temp;
+    if (t == (GPS_TIME *)NULL) {
+        t = &temp;
+        gps_get_time(t);        
+    }
+    return gps_siderealDegrees_by_jd(gps_julian_date(t));
+}
+
+/** gps_siderealHA_by_jd
+ *
+ * Calculate the HA (hour angle) based on the supplied Julian Date.
+ *
+ * @param double jd The Julian Date.
+ * @return double The Hour Angle.
+ */
+double gps_siderealHA_by_jd(double jd) {
+    double lmst = gps_siderealDegrees_by_jd(jd);
+    return lmst / 360.0 * 24.0;
+}
+
+/** gps_siderealHA_by_time
+ *
+ * Calculate the HA (hour angle) based on the supplied time data structure.
+ *
+ * @param GPS_TIME *t The time data structure.
+ * @return double The Hour Angle.
+ */
+double gps_siderealHA_by_time(GPS_TIME *t) {
+    double lmst = gps_siderealDegrees_by_time(t);
+    return lmst / 360.0 * 24.0;
+}
+
+/** _gps_inc_time
+ *
+ * Used to increment the time structure by 0.01sec.
+ * Called by the RIT timer callback.
+ *
+ * @see gpioirq.c
+ * @param int t_index The timer's index number (handle).
+ */
+void _gps_timer_tick_cb(int t_index) {
+    
+    /* We use x so that the_time.hundreth can never be 10 as I have noticed
+       occasionally between the ++ and the == 10 test an interrupt can occur
+       and then the_time.hundreth contains an invalid value. So using x to do
+       the ++ and ==10 test means the_time.hundreth can never itself be 10. 
+       We reuse x on the tenths for a similar reason. */
+    char x = the_time.hundreth;
+    x++;
+    
+    if (x == 10) {
+        the_time.hundreth = 0;
+        x = the_time.tenth + 1;
+        if (x < 10) {  
+            the_time.tenth = x;
+            time_updated = 1;
+        }
+    }
+    else {
+        the_time.hundreth = x;
+        time_updated = 1;
+    }
+}
+
+/** _gps_pps_alive_cb
+ *
+ * Timeout that goes off if the GPS 1PPS signal doesn't
+ * fire within 1.5seconds telling us that the GPS isn't
+ * connected. Not currently used.
+ */
+void _gps_pps_alive_cb(int index) {
+    the_time.is_valid = 0;
+}
+ 
+/** gps_pps_fall
+ *
+ * Increments the seconds. Called by the GPS 1PP callback interrupt.
+ *
+ * Note, some GPS modules, including the one used in this design, 
+ * provide a 1PPS signal. However, it's almost always positive logic
+ * and it doesn't interface directly to an Mbed pin/interrupt. So we 
+ * have a simple FET that buffers the signal and in so doing it becomes
+ * an active low signal. Hence why this is a falling edge interrupt.
+ *
+ * @see gpioirq.c
+ */
+void gps_pps_fall(void) {
+    the_time.hundreth = 0;
+    the_time.tenth    = 0;
+    _gps_time_inc(&the_time);           
+}
+
+/** gps_date_inc
+ *
+ * Increment the time.
+ *
+ * @param GPS_TIME *q Pointer the data struct holding the time.
+ */
+void _gps_time_inc(GPS_TIME *q) {
+    
+    time_updated = 1;
+    
+    q->second++;
+    if (q->second == 60) {
+        q->second = 0;
+        q->minute++;
+        if (q->minute == 60) {
+            q->minute = 0;
+            q->hour++;
+            if (q->hour == 24) {
+                q->hour = 0;
+                _gps_date_inc(q);
+            }
+        }
+    }
+}
+
+/** _gps_date_inc
+ *
+ * Increment the date.
+ *
+ * @param GPS_TIME *q Pointer the data struct holding the time.
+ */
+void _gps_date_inc(GPS_TIME *q) {
+    const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 } ;
+
+    /* Handle February leap year. */    
+    int leap_year = ((the_time.year % 4 == 0 && the_time.year % 100 != 0) || the_time.year % 400 == 0) ? 1 : 0;
+    int days_this_month = days[q->month - 1];
+    if (q->month == 2 && leap_year) days_this_month++;
+    
+    q->day++;
+    if (q->day > days_this_month) {
+        q->day = 1;
+        q->month++;
+        if (q->month == 13) {
+            q->year++;
+        }
+    }
+}
+
+/* UART1 functions. */
+
+extern "C" void UART1_IRQHandler(void) __irq {
+    volatile uint32_t iir;
+    volatile char c;
+    
+    iir = LPC_UART1->IIR;
+    
+    if (iir & 0x1) return;
+    
+    /* Do we have a serial character(s) in the fifo? */
+    if (UART_RX_INTERRUPT) {
+        while (UART1_FIFO_NOT_EMPTY) {
+            c = UART1_GETC;
+            uart1_buffer[active_buffer][active_buffer_in++] = c;
+            active_buffer_in &= (GPS_BUFFER_SIZE - 1);
+            if (c == '\n') {
+                /* Swap buffers and clean it out. */
+                active_buffer = active_buffer == 0 ? 1 : 0;
+                memset(uart1_buffer[active_buffer], 0, GPS_BUFFER_SIZE);
+                active_buffer_in = 0;
+                passive_buffer_ready = 1;
+            }
+        } 
+    }
+}
+
+/** Uart1_init
+ */
+void Uart1_init(void) {
+    
+    DEBUG_INIT_START;
+    
+    LPC_SC->PCONP       |=  (1UL << 4);
+    LPC_SC->PCLKSEL0    &= ~(3UL << 8);
+    LPC_SC->PCLKSEL0    |=  (1UL << 8);
+    LPC_PINCON->PINSEL4 &= ~(3UL << 2); /* TXD1 not used. See SSP0_init() in max7456.c */
+    LPC_PINCON->PINSEL4 |=  (2UL << 2); /* TXD1 not used. See SSP0_init() in max7456.c */
+    LPC_UART1->LCR       = 0x83;
+    LPC_UART1->DLL       = 0x71;
+    LPC_UART1->DLM       = 0x02;
+    LPC_UART1->LCR       = 0x03;
+    LPC_UART1->FCR       = 0x07;
+    
+    NVIC_SetVector(UART1_IRQn, (uint32_t)UART1_IRQHandler);
+    NVIC_EnableIRQ(UART1_IRQn);    
+    
+    /* Enable the RDA interrupt. */
+    LPC_UART1->IER = 0x01; 
+    
+    DEBUG_INIT_END;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gps/gps.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,109 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef GPS_H
+#define GPS_H
+
+#define GPS_LAT_STR 0
+#define GPS_LON_STR 1
+
+#define GPS_HISTORY_SIZE  60
+
+typedef struct _gps_time {
+    int     year;
+    char    month;
+    char    day;
+    char    hour;
+    char    minute;
+    char    second;
+    char    tenth;
+    char    hundreth;
+    char    is_valid;
+    char    prev_valid;
+} GPS_TIME;
+
+typedef struct _gps_location_raw {
+    char        north_south;
+    char        east_west;
+    char        lat[16];
+    char        lon[16];
+    char        alt[16];
+    char        sats[8];
+    char        is_valid;
+    uint32_t    updated;
+} GPS_LOCATION_RAW;
+
+typedef struct _gps_location_average {
+    char    north_south;
+    double  latitude;
+    char    east_west;
+    double  longitude;
+    double  height;
+    char    *sats;
+    char    is_valid;
+} GPS_LOCATION_AVERAGE;
+
+/* GPS module API function prototypes. */
+void                 gps_init(void);
+void                 gps_process(void);
+double               gps_convert_coord(char *s, int type);
+double               gps_julian_day_number(GPS_TIME *t);
+double               gps_julian_date(GPS_TIME *t);
+double               gps_siderealDegrees_by_jd(double jd);
+double               gps_siderealDegrees_by_time(GPS_TIME *t);
+double               gps_siderealHA_by_jd(double jd);
+double               gps_siderealHA_by_time(GPS_TIME *t);
+GPS_TIME             *gps_get_time(GPS_TIME *q);
+GPS_LOCATION_RAW     *gps_get_location_raw(GPS_LOCATION_RAW *q);
+GPS_LOCATION_AVERAGE *gps_get_location_average(GPS_LOCATION_AVERAGE *q);
+
+/* Used by other modules to make callbacks. */
+void gps_pps_fall(void);    /* gpioirq.c needs this to know what to callback to. */
+
+#define GPS_BUFFER_SIZE     128
+
+/* Used to test the IIR register. Common across UARTs. */
+#define UART_ISSET_THRE              0x0002
+#define UART_ISSET_RDA               0x0004
+#define UART_ISSET_CTI               0x000C
+#define UART_ISSET_RLS               0x0006
+#define UART_ISSET_FIFOLVL_RXFULL    0x0000000F
+#define UART_ISSET_FIFOLVL_TXFULL    0x00000F00
+
+#define UART_RX_INTERRUPT       iir & UART_ISSET_RDA
+
+
+/* UART1 register configuration values. */
+#define UART1_SET_LCR           0x00000003
+#define UART1_SET_LCR_DLAB      0x00000083
+#define UART1_SET_DLLSB         0x71
+#define UART1_SET_DLMSB         0x02
+#define UART1_SET_FCR           0x01
+#define UART1_SET_FCR_CLEAR     0x07
+#define UART1_SET_IER           0x07
+
+/* Macros. */
+#define UART1_FIFO_NOT_EMPTY    LPC_UART1->LSR & 0x1
+#define UART1_GETC              (char)LPC_UART1->RBR
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,289 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef MAIN_CPP
+#define MAIN_CPP
+#endif
+
+#include "sowb.h"
+#include "gpioirq.h"
+#include "gpio.h"
+#include "rit.h"
+#include "usbeh.h"
+#include "usbeh_endpoint.h"
+#include "usbeh_device.h"
+#include "usbeh_controller.h"
+#include "usbeh_api.h"
+#include "xbox360gamepad.h"
+#include "th_xbox360gamepad.h"
+#include "gps.h"
+#include "MAX7456.h"
+#include "osd.h"
+#include "nexstar.h"
+#include "utils.h"
+#include "user.h"
+#include "dma.h"
+#include "flash.h"
+#include "sdcard.h"
+#include "config.h"
+#include "ff.h"
+#include "sgp4sdp4.h"
+#include "satapi.h"
+#include "star.h"
+
+#include "main.h"
+#include "debug.h"
+#include "predict_th.h"
+
+int test_flash_page;
+
+/* Create an array of _process function pointers
+   to call while user_io is waiting. */
+typedef void (PROCESS_FUNC)();
+
+PROCESS_FUNC *process_callbacks[] = {
+    usbeh_api_process,
+    xbox360gamepad_process,
+    gps_process,
+    gpioirq_process,
+    nexstar_process,
+    sdcard_process,
+    config_process,
+    NULL
+};
+
+int main_test_flag;
+
+void _main_test_callback(int index) {
+    main_test_flag = 0;
+}
+
+
+
+int main() {
+    int counter = 0;
+    char test_buffer[256];
+    DIR fDir;
+    FILINFO fInfo;
+    int f_return;
+    GPS_LOCATION_RAW location;
+    
+    /* Carry out module start-up _init() functions. 
+       Note, the order is important, do not change. */
+    debug_init();
+    gpio_init();
+    rit_init();
+    xbox360gamepad_init();
+    usbeh_api_init();
+    MAX7456_init();
+    osd_init();
+    gps_init();
+    gpioirq_init();
+    
+    /* We use raw MAX7456 calls to display the splash screen because
+       at this point not all interrupts are active and the OSD system
+       will not yet be fully operational even though we've _init() it. */
+    MAX7456_cursor(0, 5);  MAX7456_string((unsigned char *)"     Satellite Observers  ");
+    MAX7456_cursor(0, 6);  MAX7456_string((unsigned char *)"       Workbench V0.1     ");
+    MAX7456_cursor(0, 7);  MAX7456_string((unsigned char *)"     (c) Copyright 2010   ");
+    MAX7456_cursor(0, 8);  MAX7456_string((unsigned char *)"  Stellar Technologies Ltd");
+    if (LPC_WDT->WDMOD & 0x4) { MAX7456_cursor(0, 14);  MAX7456_string((unsigned char *)" WDT Error detected"); }
+    user_wait_ms_blocking(2000); /* Simple splash screen delay. */
+    MAX7456_cursor(0, 11);  MAX7456_string((unsigned char *)"    Press A to continue");
+    while (user_get_button(false) != BUTT_A_PRESS)   ;
+    while (user_get_button(false) != BUTT_A_RELEASE) ;
+    
+    /* Complete the module _init() stage. */
+    nexstar_init();
+    DMA_init();
+    flash_init();
+    sdcard_init();
+    config_init();
+    th_xbox360gamepad_init();
+    
+    if (!_nexstar_is_aligned()) {
+        debug_printf("Nexstar not aligned, forcing user to align.\r\n");
+        nexstar_force_align();
+    }
+    
+    MAX7456_cursor(0, 11);  MAX7456_string((unsigned char *)"    Waiting for GPS....");
+    do { 
+        gps_get_location_raw(&location);
+        WHILE_WAITING_DO_PROCESS_FUNCTIONS; 
+    } while (location.is_valid == '0');
+    osd_clear(); osd_set_mode_l01(L01_MODE_A);
+    
+    /* Tell the Nexstar the real time and place. */
+    _nexstar_set_time(NULL);
+    _nexstar_set_location(NULL);
+        
+    /* Init the watchdog and then go into the main loop. */
+    LPC_SC->PCLKSEL0 |= 0x3;
+    LPC_WDT->WDCLKSEL = 1;
+    LPC_WDT->WDTC = 6000000;
+    LPC_WDT->WDMOD = 3;
+    KICK_WATCHDOG;
+    
+    while(1) {
+                
+        char c = user_get_button(false);
+        switch (c) {
+            case BUTT_START_PRESS:
+                if (!sdcard_is_mounted()) {
+                    osd_string_xy(1, 14, "No SD card inserted");
+                }
+                break;
+            
+            case BUTT_XBOX_PRESS:
+                SAT_POS_DATA q;
+                satapi_aos(&q, true);
+                break;
+                    
+            case BUTT_LS_PRESS:
+                osd_l01_next_mode();
+                break;
+            case BUTT_RS_PRESS:
+                osd_crosshair_toggle();
+                break;    
+            case BUTT_B_PRESS:
+                //_nexstar_goto_azm_fast(0x238F);
+                //_nexstar_goto(0x238F, 0x238F);
+                _nexstar_goto(0x0, 0x0);
+                break;
+            case BUTT_X_PRESS:
+                /*
+                _nexstar_set_elevation_rate_auto(1.0);
+                main_test_flag = 1;
+                rit_timer_set_counter(MAIN_TEST_CB, 5000);
+                P22_ASSERT;
+                while (main_test_flag == 1) {
+                    user_call_process();
+                }
+                _nexstar_set_elevation_rate_auto(0);
+                P22_DEASSERT;
+                */
+                
+                for (int i = 0; i < 256; i++) {
+                    test_buffer[i] = 255 - i;
+                }
+                debug_printf("Test buffer before:-\r\n");
+                printBuffer(test_buffer, 256);
+                flash_page_write(1, test_buffer);
+                LED1_ON;
+                while(flash_write_in_progress());
+                LED1_OFF; 
+                flash_read_page(1, test_buffer, true);
+                debug_printf("Test buffer after:-\r\n");
+                printBuffer(test_buffer, 256);
+                break;
+                
+            case BUTT_Y_PRESS:
+                memset(test_buffer, 0xAA, 256);
+                flash_read_page(0, test_buffer, true);
+                debug_printf("Page 0\r\n");
+                printBuffer(test_buffer, 256);
+                memset(test_buffer, 0xAA, 256);
+                flash_read_page(1, test_buffer, true);
+                debug_printf("Page 1\r\n");
+                printBuffer(test_buffer, 256);
+                memset(test_buffer, 0xAA, 256);
+                flash_read_page(2, test_buffer, true);
+                debug_printf("Page 2\r\n");
+                printBuffer(test_buffer, 256);
+                memset(test_buffer, 0xAA, 256);
+                flash_read_page(3, test_buffer, true);
+                debug_printf("Page 3\r\n");
+                printBuffer(test_buffer, 256);
+                break;
+            case BUTT_DPAD_DOWN_PRESS:
+                flash_erase_sector(0);
+                break;
+            case BUTT_DPAD_UP_PRESS:
+                flash_erase_bulk();
+                break;
+            case BUTT_DPAD_LEFT_PRESS:
+                {
+                    AltAz y;
+                    RaDec x;
+                    GPS_LOCATION_AVERAGE loc;
+                    GPS_TIME t;
+                    memset(&t, 0, sizeof(GPS_TIME));
+                    t.year = 2010; t.month = 10; t.day = 7; t.hour = 21; t.minute = 15; t.second = 21;
+                
+                    double jd = gps_julian_date(&t);
+                    sprintf(test_buffer, "\n\n\rJD = %f\r\n", jd);
+                    debug_printf(test_buffer);
+                    
+                    gps_get_location_average(&loc);
+                    double siderealDegrees = gps_siderealDegrees_by_time(&t);
+                    sprintf(test_buffer, "SR by time = %f\r\n", siderealDegrees);
+                    debug_printf(test_buffer);
+                    
+                    x.dec = 28.026111;
+                    x.ra  = 116.32875;
+                    
+                    sprintf(test_buffer, "Staring with Dec = %f, RA = %f\r\n", x.dec, x.ra);
+                    debug_printf(test_buffer);
+                    
+                    radec2altaz(siderealDegrees, &loc, &x, &y);
+                    sprintf(test_buffer, "Alt = %f, Azm = %f\r\n", y.alt, y.azm);
+                    debug_printf(test_buffer);
+                                        
+                    altaz2radec(siderealDegrees, &loc, &y, &x);
+                    sprintf(test_buffer, "Dec = %f, RA = %f\r\n", x.dec, x.ra);
+                    debug_printf(test_buffer);
+                    
+                    // Lets look for the brightest star near Sirius.
+                    // It should return HR2491, Sirius it's self.
+                    // RA 6 45 8.9      101.2606833
+                    // Dec -16 42, 58   -16.716111
+                    x.ra = 101.2606833; x.dec = -16.716111;
+                    char test_buffer2[32];
+                    basicStarData star, *p;
+                    p = star_closest(&x, &star);
+                    if (!p) {
+                        debug_printf("No star found\r\n");
+                    }
+                    else {
+                        sprintf(test_buffer, "HR%d %f %f %f\r\n", star.hr, star.ra, star.dec, star.mag);
+                        debug_printf(test_buffer);
+                    }
+                    
+                    
+                }
+    
+    
+                break;
+        }
+        
+        //sgp4sdp4_th_init(); 
+        
+   /* 
+        for(int i = 0; process_callbacks[i] != NULL; i++) {
+            (process_callbacks[i])();
+        }
+        
+        th_xbox360gamepad();
+    */
+    }    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,37 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef MAIN_H
+#define MAIN_H
+
+#ifdef MAIN_CPP
+
+/* Define system globals here. */
+//Serial debug(USBTX, USBRX);
+
+#else
+
+/* Declare system globals here. */
+//extern Serial debug;
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/md5/md5.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,396 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/*
+    Not even sure where I lifted this code now, but I think it was the
+    FreeBSD project. So any copyright that is attributable to that project
+    and the BSD license is acknowledged. This module is dual licensed:-
+    
+    http://www.opensource.org/licenses/bsd-license.php
+    
+    Copyright (c) 2010, Stellar Technologies Ltd/Andy Kirkham
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+    are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this 
+      list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+    * Neither the name of the <ORGANIZATION> nor the names of its contributors may 
+      be used to endorse or promote products derived from this software without 
+      specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
+    IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+    
+    Additionally see http://www.freebsd.org/copyright/license.html
+*/
+
+#include "sowb.h"
+
+/**
+ * MD5 context structure.
+ */
+typedef struct {
+    uint32_t lo, hi;
+    uint32_t a, b, c, d;
+    unsigned char buffer[64];
+    uint32_t block[16];
+} MD5_CTX;
+
+/* Used to create human text for MD5 */
+static const char hexits[17] = "0123456789ABCDEF";
+
+/**
+ * Internal function prototypes.
+ */
+static void make_digest(char *md5str, unsigned char *digest);
+static void md5_init(MD5_CTX *);
+static void md5_update(MD5_CTX *, const void *, unsigned int);
+static void md5_final(unsigned char *, MD5_CTX *);
+static const void *body(MD5_CTX *, const void *, unsigned int);
+
+void md5(const char *s, char *md5str) {
+
+    // A local MD5 context.
+    MD5_CTX context;
+
+    // Place to store the raw MD5 digest.
+    unsigned char digest[16];
+
+    // Clear the output string and initialise the context.
+    md5str[0] = '\0';
+    md5_init(&context);
+
+    // Make the MD5 and finalise.
+    md5_update(&context, s, strlen(s));
+    md5_final(digest, &context);
+
+    // Convert the binary digest into human text in the caller's output buffer.
+    make_digest(md5str, digest);
+}
+
+/**
+ * md5_short
+ *
+ * As MD5 function but selects 5 fixed characters
+ * from the 32 generated to return a short name.
+ */
+void md5_short(const char *s, char *md5str, int d) {
+    char temp[33];
+    static const int day[7][5] = {
+      { 18,  3,  8, 27, 19 }, // 01
+      { 12, 11,  6, 21, 15 }, // 02
+      { 27, 14, 12,  4, 11 }, // 03
+      { 12, 18, 13,  6,  2 }, // 04
+      { 29, 13,  8,  1, 15 }, // 05
+      { 13, 12,  9, 30, 22 }, // 06
+      { 29, 31,  2,  5, 14 }  // 07
+    };
+        
+    // Get the full MD5 string.
+    md5(s, temp);
+    
+    // Ensure we stay within our array boundaries.
+    d &= 0x7;
+    
+    // Get the shortened version of the MD5.
+    md5str[0] = temp[day[d][0]];
+    md5str[1] = temp[day[d][1]];
+    md5str[2] = temp[day[d][2]];
+    md5str[3] = temp[day[d][3]];
+    md5str[4] = temp[day[d][4]];
+    md5str[5] = '\0';
+}
+
+static void make_digest(char *md5str, unsigned char *digest) {
+    int i;
+    
+    for (i = 0; i < 16; i++) {
+        md5str[i * 2]       = hexits[digest[i] >> 4];
+        md5str[(i * 2) + 1] = hexits[digest[i] & 0x0F];
+    }
+    
+    md5str[32] = '\0';
+}
+
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security,
+ * Inc. MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Written by Solar Designer <solar at openwall.com> in 2001, and placed
+ * in the public domain.  There's absolutely no warranty.
+ *
+ * This differs from Colin Plumb's older public domain implementation in
+ * that no 32-bit integer data type is required, there's no compile-time
+ * endianness configuration, and the function prototypes match OpenSSL's.
+ * The primary goals are portability and ease of use.
+ *
+ * This implementation is meant to be fast, but not as fast as possible.
+ * Some known optimizations are not included to reduce source code size
+ * and avoid compile-time configuration.
+ */
+
+
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z)            ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z)            ((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z)            ((x) ^ (y) ^ (z))
+#define I(x, y, z)            ((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+    (a) += f((b), (c), (d)) + (x) + (t); \
+    (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+    (a) += (b);
+
+# define SET(n) \
+    (ctx->block[(n)] = \
+    (uint32_t)ptr[(n) * 4] | \
+    ((uint32_t)ptr[(n) * 4 + 1] << 8) | \
+    ((uint32_t)ptr[(n) * 4 + 2] << 16) | \
+    ((uint32_t)ptr[(n) * 4 + 3] << 24))
+# define GET(n) \
+    (ctx->block[(n)])
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update
+ * the bit counters.  There are no alignment requirements.
+ */
+static const void *body(MD5_CTX *ctx, const void *data, unsigned int size) {
+    const unsigned char *ptr;
+    uint32_t a, b, c, d;
+    uint32_t saved_a, saved_b, saved_c, saved_d;
+
+    ptr = (const unsigned char *)data;
+
+    a = ctx->a;
+    b = ctx->b;
+    c = ctx->c;
+    d = ctx->d;
+
+    do {
+        saved_a = a;
+        saved_b = b;
+        saved_c = c;
+        saved_d = d;
+
+        /* Round 1 */
+        STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+        STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+        STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+        STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+        STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+        STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+        STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+        STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+        STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+        STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+        STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+        STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+        STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+        STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+        STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+        STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+        /* Round 2 */
+        STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+        STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+        STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+        STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+        STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+        STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+        STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+        STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+        STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+        STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+        STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+        STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+        STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+        STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+        STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+        STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+        /* Round 3 */
+        STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+        STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
+        STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+        STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
+        STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+        STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+        STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+        STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
+        STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+        STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
+        STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+        STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
+        STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+        STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
+        STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+        STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+        /* Round 4 */
+        STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+        STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+        STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+        STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+        STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+        STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+        STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+        STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+        STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+        STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+        STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+        STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+        STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+        STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+        STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+        STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+        a += saved_a;
+        b += saved_b;
+        c += saved_c;
+        d += saved_d;
+
+        ptr += 64;
+    } while (size -= 64);
+
+    ctx->a = a;
+    ctx->b = b;
+    ctx->c = c;
+    ctx->d = d;
+
+    return ptr;
+}
+
+static void md5_init(MD5_CTX *ctx) {
+    ctx->a = 0x67452301;
+    ctx->b = 0xefcdab89;
+    ctx->c = 0x98badcfe;
+    ctx->d = 0x10325476;
+
+    ctx->lo = 0;
+    ctx->hi = 0;
+}
+
+static void md5_update(MD5_CTX *ctx, const void *data, unsigned int size) {
+    uint32_t saved_lo;
+    uint32_t used, free;
+    
+    saved_lo = ctx->lo;
+    if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) {
+        ctx->hi++;
+    }
+    ctx->hi += size >> 29;
+
+    used = saved_lo & 0x3f;
+
+    if (used) {
+        free = 64 - used;
+
+        if (size < free) {
+            memcpy(&ctx->buffer[used], data, size);
+            return;
+        }
+
+        memcpy(&ctx->buffer[used], data, free);
+        data = (unsigned char *)data + free;
+        size -= free;
+        body(ctx, ctx->buffer, 64);
+    }
+
+    if (size >= 64) {
+        data = body(ctx, data, size & ~(size_t)0x3f);
+        size &= 0x3f;
+    }
+
+    memcpy(ctx->buffer, data, size);
+}
+
+static void md5_final(unsigned char *result, MD5_CTX *ctx) {
+    uint32_t used, free;
+    
+    used = ctx->lo & 0x3f;
+    
+    ctx->buffer[used++] = 0x80;
+
+    free = 64 - used;
+
+    if (free < 8) {
+        memset(&ctx->buffer[used], 0, free);
+        body(ctx, ctx->buffer, 64);
+        used = 0;
+        free = 64;
+    }
+
+    memset(&ctx->buffer[used], 0, free - 8);
+
+    ctx->lo <<= 3;
+    ctx->buffer[56] = (unsigned char)ctx->lo;
+    ctx->buffer[57] = (unsigned char)(ctx->lo >> 8);
+    ctx->buffer[58] = (unsigned char)(ctx->lo >> 16);
+    ctx->buffer[59] = (unsigned char)(ctx->lo >> 24);
+    ctx->buffer[60] = (unsigned char)(ctx->hi);
+    ctx->buffer[61] = (unsigned char)(ctx->hi >> 8);
+    ctx->buffer[62] = (unsigned char)(ctx->hi >> 16);
+    ctx->buffer[63] = (unsigned char)(ctx->hi >> 24);
+
+    body(ctx, ctx->buffer, 64);
+
+    result[0] = (unsigned char)ctx->a;
+    result[1] = (unsigned char)(ctx->a >> 8);
+    result[2] = (unsigned char)(ctx->a >> 16);
+    result[3] = (unsigned char)(ctx->a >> 24);
+    result[4] = (unsigned char)ctx->b;
+    result[5] = (unsigned char)(ctx->b >> 8);
+    result[6] = (unsigned char)(ctx->b >> 16);
+    result[7] = (unsigned char)(ctx->b >> 24);
+    result[8] = (unsigned char)ctx->c;
+    result[9] = (unsigned char)(ctx->c >> 8);
+    result[10] = (unsigned char)(ctx->c >> 16);
+    result[11] = (unsigned char)(ctx->c >> 24);
+    result[12] = (unsigned char)ctx->d;
+    result[13] = (unsigned char)(ctx->d >> 8);
+    result[14] = (unsigned char)(ctx->d >> 16);
+    result[15] = (unsigned char)(ctx->d >> 24);
+
+    memset(ctx, 0, sizeof(*ctx));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/md5/md5.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,9 @@
+
+#ifndef MD5_H
+#define MD5_H
+
+
+void md5(const char *s, char *md5str);
+void md5_short(const char *s, char *md5str, int day);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nexstar/nexstar.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,640 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/*
+   Update: This whole module requires refactoring into something much more
+   sane. Basically, I "organically" grew the code in this module with trial
+   and error using the hardware since getting simple things done proved hard.
+   I did design (see below) what I thought reasonable system but the Nexstar
+   kept throwing up problems. So I really need to come back to this code and
+   sort it out properly.
+   
+   Frustrations: I originally implemented an "intelligent" start-up routine
+   that sent echo requests to check the Nexstar was there, then requested 
+   isAligned and, once aligned, would finally send the Tracking Off command
+   and enter operational state. However, that's all out the window.
+   
+   Basically, I have found that if you send anything down the serial cable 
+   while the Nexstar is powering up it goes dumb and won't responsd to 
+   anything you send it. How useless, someone needs to educate their 
+   software engineers to designing robust serial protocols that can 
+   handle battery/power failure. Really very silly because I now know
+   that my software MUST assume the end user has powered on their Nexstar
+   before I start sending serial commands! Rubbish design, I like smart
+   designs that don't rely on the end user having to do "special things",
+   they should just work!
+   
+   Additionally, I have found that, based on documents from TheSky program
+   you cannot ask the Nexstar for it's pointing position faster than once
+   per second! WTF? Asking too fast can crash the Nexstar hand controller.
+   Doh! Since we really need the position at a higher frequency then at the
+   subsecond level, the pointing position is calculated from the last position
+   known +/- whatever variable speed rates have been sent since then.
+   
+   For the purposes of trying to track a fast moving object (an artificial
+   satellite in this case) we end up having to do most of the work ourselves
+   and hope the Nexstar tracks it with a sub-standard pointing system.
+   Hopefully I'll get it right!
+   
+   Means the serial protocol I develop here is more basic than I would have 
+   prefered. For example, rather than sending periodic echo requests to 
+   detect the Nexstar, I'll send just one. If no reply I'll have to prompt
+   the user to "Power on the Nexstar and press a key to continue". Doh.
+*/
+
+#define NEXSTAR_C
+
+#include "sowb.h"
+#include "nexstar.h"
+#include "utils.h"
+#include "rit.h"
+#include "user.h"
+#include "osd.h"
+#include "debug.h"
+#include "gpio.h"
+#include "main.h"
+
+/* Module global variables. */
+int  nexstar_status;
+int  nexstar_command;
+int  nexstar_command_status;
+char rx_buffer[NEXSTAR_BUFFER_SIZE];
+int  rx_buffer_in;
+
+bool nexstar_aligned;
+
+double last_elevation;
+double last_azmith;
+double virtual_elevation;
+double virtual_azmith;
+
+double elevation_rate;
+double elevation_rate_coarse;
+double elevation_rate_fine;
+double elevation_rate_auto;
+
+double azmith_rate;
+double azmith_rate_coarse;
+double azmith_rate_fine;
+double azmith_rate_auto;
+
+bool nexstar_goto_in_progress;
+char nexstar_goto_elevation[5];
+char nexstar_goto_azmith[5];
+
+int virtual_update_counter;
+
+/* Local function prototypes. */
+static void Uart2_init(void);
+static inline void Uart2_putc(char c);
+static inline void Uart2_puts(char *s, int len);
+
+/** nexstar_process
+ *
+ * Our system _process function.
+ */
+void nexstar_process(void) {
+        
+    if (nexstar_command_status != 0) {
+        switch (nexstar_command) {
+            case NEXSTAR_IS_ALIGNED:
+                nexstar_aligned = rx_buffer[0] == 1 ? true : false;
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;
+            case NEXSTAR_GET_AZMALT:
+                last_azmith    = virtual_azmith    = 360.0 * (((double)hex2bin(&rx_buffer[0], 4)) / 65536.0);                
+                last_elevation = virtual_elevation = 360.0 * (((double)hex2bin(&rx_buffer[5], 4)) / 65536.0);
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                virtual_update_counter = 0;    
+                if (nexstar_goto_in_progress) {
+                    if (!memcmp(&rx_buffer[0], nexstar_goto_azmith, 4) && !memcmp(&rx_buffer[5], nexstar_goto_elevation, 4)) {
+                        nexstar_goto_in_progress = false;
+                        osd_clear_line(2);
+                        osd_clear_line(3);
+                        _nexstar_set_tracking_mode(0);
+                    }
+                }            
+                break;
+            case NEXSTAR_GET_RADEC:
+            
+                break;
+            case NEXSTAR_SET_ELEVATION_RATE:
+            case NEXSTAR_SET_AZMITH_RATE:
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;
+            case NEXSTAR_GOTO:
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;
+            case NEXSTAR_GOTO_AZM_FAST:
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;
+            case NEXSTAR_SET_APPROACH:
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;
+            case NEXSTAR_SET_TIME:
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;
+            case NEXSTAR_SET_LOCATION:
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;    
+            case NEXSTAR_SYNC:
+                nexstar_command = 0;
+                nexstar_command_status = 0;
+                break;    
+        }
+    }    
+}
+
+/** nexstar_timeout_callback
+ *
+ * The generic timer callback handler.
+ *
+ * @param int index The timer index (handle).
+ */
+void _nexstar_timeout_callback(int index) {
+    nexstar_status = NEXSTAR_STATE_NOT_CONN;
+}
+
+void _nexstar_one_second_timer(int index) {
+    _nexstar_get_altazm();
+    //_nexstar_get_radec();
+    rit_timer_set_counter(RIT_ONESEC_NEXSTAR, 200);
+}
+
+double nexstar_get_rate_azm(void) {
+    if (nexstar_goto_in_progress) return 0.0;
+    return azmith_rate_coarse + azmith_rate_fine + azmith_rate_auto;
+}
+
+double nexstar_get_rate_alt(void) {
+    if (nexstar_goto_in_progress) return 0.0;
+    return elevation_rate_coarse + elevation_rate_fine + elevation_rate_auto;
+}
+
+void _nexstar_100th_timer(int index) {
+    rit_timer_set_counter(RIT_100TH_NEXSTAR, 100);
+}
+
+/** nexstar_init
+ *
+ * Used to initialise the system.
+ */
+void nexstar_init(void) {
+
+    DEBUG_INIT_START;
+    
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, 0);
+    rit_timer_set_counter(RIT_ONESEC_NEXSTAR, 250);
+    rit_timer_set_counter(RIT_100TH_NEXSTAR, 100);
+    nexstar_status = NEXSTAR_STATE_IDLE;
+    nexstar_command = 0;
+    nexstar_command_status = 0;
+    last_elevation = 0.0;
+    last_azmith = 0.0;
+    virtual_elevation = 0.0;
+    virtual_azmith = 0.0;
+    
+    elevation_rate = elevation_rate_coarse = elevation_rate_fine = elevation_rate_auto = 0.0;
+    azmith_rate = azmith_rate_coarse = azmith_rate_fine = azmith_rate_auto = 0.0;
+    
+    nexstar_goto_in_progress = false;
+    
+    nexstar_aligned = false;
+    
+    rx_buffer_in = 0;
+    virtual_update_counter = 0;
+    
+    DEBUG_INIT_END;
+    
+    Uart2_init();
+}
+
+/* External API functions. */
+void nexstar_get_elazm(double *el, double *azm) {
+    *(el)  = last_elevation;
+    *(azm) = last_azmith;
+}
+
+/* Internal API functions. */
+int _nexstar_set_tracking_mode(int mode) {
+    if (nexstar_status == NEXSTAR_STATE_IDLE) {
+        nexstar_status = NEXSTAR_STATE_BUSY;
+        rx_buffer_in = 0;
+        nexstar_command_status = 0;
+        nexstar_command = NEXSTAR_SET_TRACKING;
+        LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+        Uart2_putc('T');
+        Uart2_putc((char)mode);
+        rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+        return 1;
+    }
+    return 0;
+}
+
+int _nexstar_get_altazm(void) {
+    if (nexstar_status == NEXSTAR_STATE_IDLE) {
+        nexstar_status = NEXSTAR_STATE_BUSY;
+        rx_buffer_in = 0;
+        nexstar_command_status = 0;
+        nexstar_command = NEXSTAR_GET_AZMALT;
+        LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+        Uart2_putc('Z');
+        rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+        return 1;
+    }
+    return 0;
+}
+
+int _nexstar_get_radec(void) {
+    if (nexstar_status == NEXSTAR_STATE_IDLE) {
+        nexstar_status = NEXSTAR_STATE_BUSY;
+        rx_buffer_in = 0;
+        nexstar_command_status = 0;
+        nexstar_command = NEXSTAR_GET_RADEC;
+        LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+        Uart2_putc('E');
+        rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+        return 1;
+    }
+    return 0;
+}
+
+void _nexstar_set_elevation_rate_coarse(double rate) {
+    elevation_rate_coarse = rate;
+    _nexstar_set_elevation_rate();
+}
+
+void _nexstar_set_elevation_rate_fine(double rate) {
+    elevation_rate_fine = rate;
+    _nexstar_set_elevation_rate();
+}
+
+void _nexstar_set_elevation_rate_auto(double rate) {
+    elevation_rate_auto = rate;
+    _nexstar_set_elevation_rate();
+}
+
+int _nexstar_set_elevation_rate(void) {
+    char dir, high, low, cmd[32];
+    double rate;
+
+    rate = elevation_rate_coarse + elevation_rate_fine + elevation_rate_auto;
+    
+    if (elevation_rate == rate) return 0;
+    
+    if (rate != 0.0) {
+        if (nexstar_goto_in_progress || nexstar_status != NEXSTAR_STATE_IDLE) return 0;
+    }
+        
+    while (nexstar_status != NEXSTAR_STATE_IDLE) {
+        if (nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
+        user_wait_ms(1);
+    };
+    
+    //if (rate >= 0.0) osd_string_xyl(0, 14, cmd, sprintf(cmd, " ALT >> %c%.1f", '+', rate)); 
+    //else             osd_string_xyl(0, 14, cmd, sprintf(cmd, " ALT >> %+.1f", rate)); 
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    nexstar_command_status = 0;
+    nexstar_command = NEXSTAR_SET_ELEVATION_RATE;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    dir = 6;
+    if (rate < 0.0) {
+        dir = 7;
+        rate *= -1;
+    }
+    high = ((int)(3600.0 * rate * 4.0) / 256) & 0xFF;
+    low  = ((int)(3600.0 * rate * 4.0) % 256) & 0xFF;            
+    Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 17, dir, high, low, 0, 0));
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+    elevation_rate = rate;
+    return 1;    
+}
+
+void _nexstar_set_azmith_rate_coarse(double rate) {
+    azmith_rate_coarse = rate;
+    _nexstar_set_azmith_rate();
+}
+
+void _nexstar_set_azmith_rate_fine(double rate) {
+    azmith_rate_fine = rate;
+    _nexstar_set_azmith_rate();
+}
+
+void _nexstar_set_azmith_rate_auto(double rate) {
+    azmith_rate_auto = rate;
+    _nexstar_set_azmith_rate();
+}
+
+int _nexstar_set_azmith_rate(void) {
+    char dir, high, low, cmd[32];
+    double rate;
+    
+    rate = azmith_rate_coarse + azmith_rate_fine + azmith_rate_auto;
+    
+    if (azmith_rate == rate)  return 0;
+    
+    if (rate != 0.0) {
+        if (nexstar_goto_in_progress || nexstar_status != NEXSTAR_STATE_IDLE) return 0;
+    }
+    
+    while (nexstar_status != NEXSTAR_STATE_IDLE) {
+        if (nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
+        user_wait_ms(1);
+    };
+        
+    //if (rate >= 0.0) osd_string_xyl(14, 14, cmd, sprintf(cmd, " AZM >> %c%.1f", '+', rate)); 
+    //else             osd_string_xyl(14, 14, cmd, sprintf(cmd, " AZM >> %+.1f", rate)); 
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    nexstar_command_status = 0;
+    nexstar_command = NEXSTAR_SET_AZMITH_RATE;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    dir = 6;
+    if (rate < 0.0) {
+        dir = 7;
+        rate *= -1;
+    }
+    high = ((int)(3600.0 * rate * 4.0) / 256) & 0xFF;
+    low  = ((int)(3600.0 * rate * 4.0) % 256) & 0xFF;
+    Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 16, dir, high, low, 0, 0));            
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+    azmith_rate = rate;
+    return 1;    
+}
+
+int _nexstar_goto(uint32_t elevation, uint32_t azmith) {
+    char cmd[32], buf1[6], buf2[6];
+    double azm_target, azm_current;
+
+    if (nexstar_goto_in_progress) return 0;
+    
+    printDouble_3_2(buf1, 360.0 * ((double)elevation / 65536));
+    osd_stringl(2, cmd, sprintf(cmd, "     GOTO > %s < ALT", buf1)); 
+    printDouble_3_2(buf2, 360.0 * ((double)azmith / 65536));
+    osd_stringl(3, cmd, sprintf(cmd, "          > %s < AZM", buf2));
+    osd_clear_line(14); 
+       
+    /* Adjust the GOTO approach based on where we are pointing now
+       comapred to where we want to go. */
+    azm_target = 360.0 * ((double)((double)azmith / 65536.0));
+    azm_current = last_azmith - azm_target;
+
+    if (azm_current > 180.) _nexstar_set_azm_approach(1);        
+    else                   _nexstar_set_azm_approach(-1);            
+
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
+        user_wait_ms(1);
+    };
+            
+    nexstar_goto_in_progress = true;
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    nexstar_command_status = 0;
+    nexstar_command = NEXSTAR_GOTO;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    sprintf(nexstar_goto_azmith, "%04X", azmith);
+    sprintf(nexstar_goto_elevation, "%04X", elevation);
+    Uart2_puts(cmd, sprintf(cmd, "B%s,%s", nexstar_goto_azmith, nexstar_goto_elevation));
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, 60000);
+    return 1;    
+}
+
+int _nexstar_goto_azm_fast(uint32_t azmith) {
+    char cmd[16];
+    
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return 0;
+        user_wait_ms(1);
+    };
+            
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    nexstar_command_status = 0;
+    nexstar_command = NEXSTAR_GOTO_AZM_FAST;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 16, 2, (azmith >> 8) & 0xFF, azmith & 0xFF, 0, 0));            
+    
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, 60000);
+    return 1;    
+}
+
+void _nexstar_set_azm_approach(int approach) {
+    char cmd[16];
+    
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return;
+        user_wait_ms(1);
+    };
+    
+    nexstar_command = NEXSTAR_SET_APPROACH;    
+    nexstar_command_status = 0;
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    Uart2_puts(cmd, sprintf(cmd, "P%c%c%c%c%c%c%c", 3, 16, 0xFD, approach < 0 ? 1 : 0, 0, 0, 0));
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+}
+
+bool _nexstar_is_aligned(void) {
+    
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        if(nexstar_status == NEXSTAR_STATE_NOT_CONN) return false;
+        user_wait_ms(1);
+    };
+    
+    nexstar_command = NEXSTAR_IS_ALIGNED;    
+    nexstar_command_status = 0;
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    Uart2_putc('J');
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+    
+    /* This command blocks while we wait for an answer. */
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        user_wait_ms(10);
+    };
+    
+    return nexstar_aligned;
+}
+
+void _nexstar_sync(RaDec *radec) {
+    char cmd[32];
+    uint16_t ra, dec;
+    
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        user_wait_ms(1);
+    };
+    
+    ra  = (uint16_t)((radec->ra  / 360.0) * 65536);
+    dec = (uint16_t)((radec->dec / 360.0) * 65536);
+    
+    nexstar_command = NEXSTAR_SYNC;    
+    nexstar_command_status = 0;
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    Uart2_puts(cmd, sprintf(cmd, "S%02X,%02X", ra, dec));
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);   
+
+}
+
+void _nexstar_set_time(GPS_TIME *t) {
+    char cmd[32];
+    GPS_TIME rt;
+    
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        user_wait_ms(1);
+    };
+    
+    if (t == (GPS_TIME *)NULL) {
+        t = &rt;
+        gps_get_time(t);        
+    }
+    
+    nexstar_command = NEXSTAR_SET_TIME;    
+    nexstar_command_status = 0;
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    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));
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);   
+}
+
+void _nexstar_set_location(GPS_LOCATION_AVERAGE *l) {
+    char cmd[32];
+    GPS_LOCATION_AVERAGE rl;
+    double d, t;
+    char lat_degrees, lat_minutes, lat_seconds, lon_degrees, lon_minutes, lon_seconds;
+    
+    while(nexstar_status != NEXSTAR_STATE_IDLE) {
+        user_wait_ms(1);
+    };
+    
+    if (l == (GPS_LOCATION_AVERAGE *)NULL) {
+        l = &rl;
+        gps_get_location_average(l);        
+    }
+    
+    d = l->latitude;
+    lat_degrees = (char)d; t = (d - (double)lat_degrees) * 60.0;
+    lat_minutes = (char)t;
+    lat_seconds = (t - (double)lat_minutes) * 60.0;
+    d = l->longitude;
+    lon_degrees = (int)d; t = (d - (double)lon_degrees) * 60.0;
+    lon_minutes = (int)t;
+    lon_seconds = (t - (double)lon_minutes) * 60.0;
+    
+    nexstar_command = NEXSTAR_SET_LOCATION;    
+    nexstar_command_status = 0;
+    nexstar_status = NEXSTAR_STATE_BUSY;
+    rx_buffer_in = 0;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+    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));
+    rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);   
+}
+
+/** UART2_IRQHandler(void)
+ *
+ * The interrupt service routine for the UART2.
+ */
+extern "C" void UART2_IRQHandler(void) __irq {
+    volatile uint32_t iir; 
+    char c;
+
+    /* Get the interrupt identification register which also resets IIR. */
+    iir = LPC_UART2->IIR;
+       
+    if (iir & 0x1) return;
+    
+    iir = (iir >> 1) & 0x3;
+    
+    /* Handle the incoming character. */
+    if (iir == 2) {
+        c = LPC_UART2->RBR;
+        //Uart0_putc(c);
+        rit_timer_set_counter(RIT_TIMER_NEXSTAR, NEXSTAR_SERIAL_TIMEOUT);
+        rx_buffer[rx_buffer_in] = c;
+        rx_buffer_in++;
+        if (rx_buffer_in >= NEXSTAR_BUFFER_SIZE) {
+            rx_buffer_in = 0;
+        }
+        if (c == '#') {
+            rit_timer_set_counter(RIT_TIMER_NEXSTAR, 0);
+            nexstar_command_status = 1;
+            nexstar_status = NEXSTAR_STATE_IDLE;
+        }
+    }
+}
+
+/** Uart2_init
+ *
+ * Initialise UART2 to our requirements for Nexstar.
+ */
+static void Uart2_init (void) {
+    volatile char c __attribute__((unused));
+    
+    DEBUG_INIT_START;
+    
+    LPC_SC->PCONP       |=  (1UL << 24);
+    LPC_SC->PCLKSEL1    &= ~(3UL << 16);
+    LPC_SC->PCLKSEL1    |=  (1UL << 16);
+    LPC_PINCON->PINSEL0 |= ((1UL << 20) | (1UL << 22));
+    LPC_UART2->LCR       = 0x80;
+    LPC_UART2->DLM       = 0x2;  // 115200 baud, for 9600 use 0x2;
+    LPC_UART2->DLL       = 0x71; // 115200 baud, for 9600 use 0x71;
+    LPC_UART2->LCR       = 0x3;
+    LPC_UART2->FCR       = 0x1;
+
+    /* Ensure the FIFO is empty. */
+    while (LPC_UART2->LSR & 0x1) c = (char)LPC_UART2->RBR;
+    
+    NVIC_SetVector(UART2_IRQn, (uint32_t)UART2_IRQHandler);
+    NVIC_EnableIRQ(UART2_IRQn);
+    
+    /* Enable UART0 RX interrupt only. */
+    LPC_UART2->IER = 0x1; 
+    
+    DEBUG_INIT_END;  
+}
+
+static inline void Uart2_putc(char c) {
+    //Uart0_putc(c);
+    LPC_UART2->THR = (uint32_t)(c & 0xFF);
+}
+
+static inline void Uart2_puts(char *s, int len) {
+    int i;
+    if (len > 0) for (i = 0; len; i++, len--) Uart2_putc(s[i]);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nexstar/nexstar.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,126 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef NEXSTAR_H
+#define NEXSTAR_H
+
+#ifndef NEXSTAR_C
+extern bool nexstar_aligned;
+#endif
+
+#define IS_NEXSTAR_ALIGNED nexstar_aligned
+
+#define NEXSTAR_INIT    0
+#define NEXSTAR_IDLE    1
+#define NEXSTAR_CMD     2
+
+/* Nexstar statuses. */
+#define NEXSTAR_STATE_NOT_CONN  -1
+#define NEXSTAR_STATE_IDLE      1
+#define NEXSTAR_STATE_BUSY      2
+
+/* Statuses for command packets. */
+#define NEXSTAR_SET_TRACKING        1
+#define NEXSTAR_GET_AZMALT          2
+#define NEXSTAR_GET_RADEC           3
+#define NEXSTAR_SET_ELEVATION_RATE  4
+#define NEXSTAR_SET_AZMITH_RATE     5
+#define NEXSTAR_GOTO                6
+#define NEXSTAR_SET_APPROACH        7
+#define NEXSTAR_GOTO_AZM_FAST       8
+#define NEXSTAR_GOTO_ELE_FAST       9
+#define NEXSTAR_IS_ALIGNED          10
+#define NEXSTAR_SET_TIME            11
+#define NEXSTAR_SET_LOCATION        12
+#define NEXSTAR_SYNC                13
+
+#define NEXSTAR_BUFFER_SIZE  16
+#define NEXSTAR_SERIAL_TIMEOUT  350
+
+/* API functions. */
+void nexstar_get_elazm(double *el, double *azm);
+
+/* Function prototypes. */
+int _nexstar_set_tracking_mode(int mode);
+int _nexstar_get_altazm(void);
+int _nexstar_get_radec(void);
+void _nexstar_set_elevation_rate_coarse(double rate);
+void _nexstar_set_elevation_rate_fine(double rate);
+void _nexstar_set_elevation_rate_auto(double rate);
+void _nexstar_set_azmith_rate_coarse(double rate);
+void _nexstar_set_azmith_rate_fine(double rate);
+void _nexstar_set_azmith_rate_auto(double rate);
+
+int _nexstar_set_elevation_rate(void);
+int _nexstar_set_azmith_rate(void);
+void _nexstar_set_azm_approach(int approach);
+
+int _nexstar_goto(uint32_t, uint32_t);
+int _nexstar_goto_azm_fast(uint32_t azmith);
+
+#include "gps.h"
+void _nexstar_set_time(GPS_TIME *t);
+void _nexstar_set_location(GPS_LOCATION_AVERAGE *l);
+
+#include "satapi.h"
+void _nexstar_sync(RaDec *);
+
+double nexstar_get_rate_azm(void);
+double nexstar_get_rate_alt(void);
+
+bool _nexstar_is_aligned(void);
+
+/* Defined in nexstar_align.c */
+void nexstar_force_align(void);
+
+/* Macros */
+            
+/* Used to test the IIR register. Common across UARTs. */
+#define UART_ISSET_THRE              0x0002
+#define UART_ISSET_RDA               0x0004
+#define UART_ISSET_CTI               0x000C
+#define UART_ISSET_RLS               0x0006
+#define UART_ISSET_FIFOLVL_RXFULL    0x0000000F
+#define UART_ISSET_FIFOLVL_TXFULL    0x00000F00
+
+/* UART2 peripheral control masks. */
+#define UART2_ORMASK_PCONP      0x01000000
+#define UART2_ORMASK_PCLKSEL1   0x00010000
+#define UART2_ORMASK_PINMODE0   0x00A00000
+#define UART2_ORMASK_PINSEL0    0x00500000
+
+/* UART2 register configuration values. */
+#define UART2_SET_LCR           0x00000003
+#define UART2_SET_LCR_DLAB      0x00000083
+#define UART2_SET_DLLSB         0x71
+#define UART2_SET_DLMSB         0x02
+#define UART2_SET_FCR           0x01
+#define UART2_SET_FCR_CLEAR     0x07
+#define UART2_SET_IER           0x01
+
+/* Standard API functions. */
+void nexstar_init(void);
+void nexstar_process(void);
+
+/* endif NEXSTAR_H */
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nexstar/nexstar_align.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,54 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "osd.h"
+#include "nexstar.h"
+#include "xbox360gamepad.h"
+#include "user.h"
+
+/** nexstar_force_align
+ *
+ * On boot-up if main() detects the Nexstar is not aligned
+ * full control is passed here to force the user to align 
+ * the Nexstar.
+ */
+void nexstar_force_align(void) {
+    char c, buf[32];
+
+    osd_stringl(11, buf, sprintf(buf, "  Please align the NexStar"));
+    osd_stringl(12, buf, sprintf(buf, "  Press 'start'  when done"));
+    
+    do {
+        c = 0;
+        while(c != BUTT_START_PRESS) {
+            c = user_get_button(false);
+        }
+    }
+    while(!_nexstar_is_aligned());
+    
+    osd_clear_line(11);
+    osd_clear_line(12);
+    
+    _nexstar_set_tracking_mode(0);
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nexstar/nexstar_old.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,798 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifdef NEVERCOMPILETHIS
+
+#include "mbed.h"
+#include "nexstar.h"
+#include "utils.h"
+#include "debug.h"
+#include "main.h"
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+/* The main place holder data structure for the Nexstar. */
+NEXSTAR_DATA nexstar;
+
+/* A timer to look for serial comms failure. */
+OneMS   timeout;
+
+/** nexstar_process(void)
+ *
+ * Standard module _process function.
+ */
+void nexstar_process(void) {
+    int i, j, q;
+    signed char status, type;
+    
+    BLAT4;
+    
+    /* Multiple queued requests will start automatically after the previous
+       request (see the ISR for details). However, it is possible that when
+       the ISR detects the completion of a request there are, at that time,
+       no more pending requests in the queue. So loop over the request queue 
+       and if none are in progress, initiate a request transfer to the Nexstar. */
+    if (! nexstar_request_count_status(NEXSTAR_REQUEST_IN_PROGRESS)) {
+        if (nexstar_request_count_status(NEXSTAR_REQUEST_PENDING)) {
+            for (i = 0, q = nexstar.currentRequest; i < NEXSTAR_NUM_OF_PACKETS; i++) {
+                if (nexstar.commsPackets[q].requestStatus == NEXSTAR_REQUEST_PENDING) {
+                    nexstar.currentRequest = q;
+                    nexstar_send_request(q);
+                    i = NEXSTAR_NUM_OF_PACKETS;
+                }
+                else {
+                    NEXSTAR_NEXT_REQUEST(q);
+                }
+            }
+        }
+    }
+    
+    /* look through all the comms request packets and see if any need processing. */
+    /*
+    for (i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
+        status = nexstar.commsPackets[i].requestStatus;
+        type   = nexstar.commsPackets[i].requestType; 
+        if (status == NEXSTAR_REQUEST_TIMEOUT) {                        
+            for (j = 0; j < NEXSTAR_NUM_OF_PACKETS; j++) {
+                REQUEST_SET_PACKET_STATUS(j, NEXSTAR_REQUEST_IDLE); 
+                nexstar_request_packet_reset(&nexstar.commsPackets[j]);
+            }
+            NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
+        }
+        else if (status == NEXSTAR_REQUEST_COMPLETE) {
+            switch (type) {
+                case NEXSTAR_ECHO_COMMS:
+                    nexstar_request_echo(NEXSTAR_PROCESS_REQUEST, i);
+                    break;
+                case NEXSTAR_ASK_IS_ALIGNED:
+                    nexstar_request_get_aligned(NEXSTAR_PROCESS_REQUEST, i);
+                    break;
+                case NEXSTAR_ASK_ALTAZM_POSITION:
+                    nexstar_request_get_altazm(NEXSTAR_PROCESS_REQUEST, i);
+                    break;
+            }
+        }       
+    }
+    */
+    
+    if (nexstar.commsPackets[nexstar.currentRequest].requestStatus; == NEXSTAR_REQUEST_COMPLETE) {
+        switch (type) {
+            case NEXSTAR_ECHO_COMMS:
+                nexstar_request_echo(NEXSTAR_PROCESS_REQUEST, nexstar.currentRequest);
+                break;
+            case NEXSTAR_ASK_IS_ALIGNED:
+                nexstar_request_get_aligned(NEXSTAR_PROCESS_REQUEST, nexstar.currentRequest);
+                break;
+            case NEXSTAR_ASK_ALTAZM_POSITION:
+                nexstar_request_get_altazm(NEXSTAR_PROCESS_REQUEST, nexstar.currentRequest);
+                break;
+        }
+    }       
+    
+   /* If the Nexstar is in an unknown state attempt to ask it for
+       alignment. Once we get a positive response we at least know
+       a Nexstar is connected and responding. Until we have that
+       knowledge there is little else we can do. */
+    switch(nexstar.status) {
+        case NEXSTAR_NOT_CONNECTED:
+            if (! nexstar_request_count_request_type(NEXSTAR_ECHO_COMMS)) { 
+                Uart2_flush_rxfifo();
+                nexstar_request_echo(NEXSTAR_SEND_REQUEST, 0);                
+            }
+            return;            
+
+        case NEXSTAR_CONNECTED:
+        case NEXSTAR_NOT_ALIGNED:
+            if (! nexstar_request_count_request_type(NEXSTAR_ASK_IS_ALIGNED)) {             
+                Uart2_flush_rxfifo();
+                nexstar_request_get_aligned(NEXSTAR_SEND_REQUEST, 0);                
+            }
+            return; 
+            
+        default:
+            debug.printf("I don't know what to do! status is %d\r\n", nexstar.status);
+            break;           
+    }    
+
+    /* As possible as often, request the Nexstar's pointing position. */
+    if (! nexstar_request_count_request_type(NEXSTAR_ASK_ALTAZM_POSITION)) {
+        nexstar_request_get_altazm(NEXSTAR_SEND_REQUEST, 0);
+    }
+
+    
+}
+
+/** nexstar_init(void)
+ *
+ * Standard module _init function. 
+ */
+void nexstar_init(void) {
+
+    /* Setup the global mode of this Nexstar. */
+    NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
+
+    /* Initialise the comms packets and buffers. */
+    nexstar.currentRequest = 0;
+    nexstar.availableRequest = 0;
+    for (int i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
+        nexstar_request_packet_reset(&nexstar.commsPackets[i]);
+        //nexstar.commsPackets[i].requestType = 0;
+        //nexstar.commsPackets[i].requestStatus = NEXSTAR_REQUEST_IDLE;
+        //nexstar.commsPackets[i].bufferPointer = 0;
+        //nexstar.commsPackets[i].callback = NULL;
+        //memset(nexstar.commsPackets[i].buffer, 0, NEXSTAR_PACKET_BUFFER_SIZE);
+    }
+    
+    /* Prepare the one-shot timeout timers. */
+    timeout.mode(ONEMS_MODE_TIMEOUT_CALLBACK);
+    timeout.attach(nexstar_timeout);
+
+    /* Initialise the UART we use. */
+    Uart2_init();
+}
+
+/** nexstar_request_packet_reset
+ *
+ * Return a request packet back to default state.
+ *
+ * @param NEXSTAR_COMMS_PACKET *p A pointer to the packet to reset.
+ */
+void nexstar_request_packet_reset(NEXSTAR_COMMS_PACKET *p) {
+    p->requestType = 0;
+    p->bufferPointer = 0;
+    p->callback = NULL;
+    memset(p->buffer, 0, NEXSTAR_PACKET_BUFFER_SIZE);
+    p->requestStatus = NEXSTAR_REQUEST_IDLE;
+}
+
+/** nexstar_p(void)
+ *
+ * Get a pointer to the data structure for the Nexstar.
+ * Used by the API to get data.
+ */
+NEXSTAR_DATA * nexstar_p(void) {
+    return &nexstar;
+}
+
+/** nexstar_request_count_request_type(char requestType)
+ *
+ * Used to find out if any of the packets are currently marked as the supplied request type.
+ *
+ * @param char The status to test.
+ * @return bool True otherwise false
+ */
+int nexstar_request_count_request_type(char requestType) {
+    int count, i;
+    
+    for (count = 0, i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
+        if (nexstar.commsPackets[i].requestType == requestType) {
+            count++;;
+        }
+    }    
+    return count;
+}
+
+/** nexstar_request_count_status (char status)
+ *
+ * Used to find out if any of the packets are currently marked as the supplied status.
+ *
+ * @param char The status to test.
+ * @return bool True otherwise false
+ */
+int nexstar_request_count_status(char status) {
+    int count, i;
+    
+    for (count = 0, i = 0; i < NEXSTAR_NUM_OF_PACKETS; i++) {
+        if (nexstar.commsPackets[i].requestStatus == status) {
+            count++;;
+        }
+    }    
+    return count;
+}
+
+/** nexstar_timeout(class OneMS *q)
+ *
+ * A callback for the timeout timer.
+ *
+ * @param pointer class OneMS that invoked the callback.
+ */
+void nexstar_timeout(class OneMS *q) {
+    q->stop();  /* Ensure we stop this timer. */
+    
+    /* Mark this request timed out. */
+    REQUEST_SET_PACKET_STATUS(nexstar.currentRequest, NEXSTAR_REQUEST_TIMEOUT);
+}
+
+/** nexstar_request_get_altazm(int mode, unsigned char handle)
+ *
+ * Used to either create a request to get the current AltAzm position of the Nextsra
+ * or to process a previously completed request.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_get_altazm(int mode, unsigned char handle) {
+    
+    /* Create a request to get the ALT/AZM and queue it. */
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'Z';
+        REQUEST_SET(NEXSTAR_ASK_ALTAZM_POSITION, 1);
+        led3 = 1;
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(9, 0);
+        nexstar.currentAltRaw = hex2bin(buffer + 5, 4);
+        nexstar.currentAlt    = (double)(((double)nexstar.currentAltRaw / 65536.) * 360.);
+        nexstar.currentAzmRaw = hex2bin(buffer + 0, 4);
+        nexstar.currentAzm    = (double)(((double)nexstar.currentAzmRaw / 65536.) * 360.);
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        led3 = 0;
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_get_aligned(int mode, unsigned char handle)
+ *
+ * Used to either create a request to check teh Nexstar is aligned
+ * or to process a previously completed request.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_get_aligned(int mode, unsigned char handle) {
+    
+    /* Create a request to get the ALT/AZM and queue it. */
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'J';
+        nexstar.commsPackets[handle].timeout = 2000;
+        REQUEST_SET(NEXSTAR_ASK_IS_ALIGNED, 1);
+        led2 = 1;
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus == NEXSTAR_REQUEST_TIMEOUT) {
+            NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
+            nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+            led2 = 0;
+            return 0;
+        }
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(1, 0);
+        NEXSTAR_SET_STATUS((buffer[0] == 1) ? NEXSTAR_ALIGNED : NEXSTAR_NOT_ALIGNED);
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        led2 = 0;
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_echo(int mode, unsigned char handle)
+ *
+ * Used to either echo a data byte off the Nexstar.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_echo(int mode, unsigned char handle) {
+    
+    /* Create a request to get the ALT/AZM and queue it. */
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'K';
+        nexstar.commsPackets[handle].buffer[1] = 'k';
+        nexstar.commsPackets[handle].timeout = 2000;
+        REQUEST_SET(NEXSTAR_ECHO_COMMS, 2);
+        led1 = 1;
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+    led3 = 1;
+        if (nexstar.commsPackets[handle].requestStatus == NEXSTAR_REQUEST_TIMEOUT) {
+            NEXSTAR_SET_STATUS(NEXSTAR_NOT_CONNECTED);
+            nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+            led1 = 0;
+            return 0;
+        }
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(1, 0);
+        if (buffer[0] == 'k') debug.printf("YES! ");
+        else debug.printf("NO! ");
+            
+        NEXSTAR_SET_STATUS((buffer[0] == 'k') ? NEXSTAR_CONNECTED : NEXSTAR_NOT_CONNECTED);
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        led1 = 0;
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_set_tracking_mode(int mode, unsigned char handle, char tracking)
+ *
+ * Used to set the tracking mode of the Nexstar
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @param char tracking The mode to send.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_set_tracking_mode(int mode, unsigned char handle, char tracking) {
+
+    /* Create request and queue. */    
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'T';
+        nexstar.commsPackets[handle].buffer[1] = tracking;
+        REQUEST_SET(NEXSTAR_SET_TRACKING, 2);
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(0, 0);
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_get_tracking_mode(int mode, unsigned char handle)
+ *
+ * Used to find out what tracking mode Nexstar is in.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_get_tracking_mode(int mode, unsigned char handle) {
+
+    /* Create request and queue. */    
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 't';
+        REQUEST_SET(NEXSTAR_ASK_TRACKING, 1);
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(1, 0);
+        nexstar.trackingMode = buffer[0];
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_set_slew(int mode, unsigned char handle, double alt, double azm)
+ *
+ * Used to set a variable slew rate.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @param double alt The alt slew rate in degrees per second.
+ * @param double azm The azm slew rate in degrees per second.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_set_slew(int mode, unsigned char handle, double alt, double azm) {
+    int i;
+    
+    /* Create request and queue. */    
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'P';
+        nexstar.commsPackets[handle].buffer[1] = '\x3';
+        nexstar.commsPackets[handle].buffer[2] = '\x11';
+        nexstar.commsPackets[handle].buffer[3] = alt > 0 ? '\x6' : '\x7';
+        i = ((int)(alt * 3600.)) * 4;
+        nexstar.commsPackets[handle].buffer[4] = (char)((i & 0xFF00) >> 8);
+        nexstar.commsPackets[handle].buffer[5] = (char)(i & 0xFF);
+        nexstar.commsPackets[handle].buffer[6] = '\0';
+        nexstar.commsPackets[handle].buffer[7] = '\0';
+        REQUEST_SET(NEXSTAR_SET_ALT_RATE, 8);
+        
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'P';
+        nexstar.commsPackets[handle].buffer[1] = '\x3';
+        nexstar.commsPackets[handle].buffer[2] = '\x10';
+        nexstar.commsPackets[handle].buffer[3] = azm > 0 ? '\x6' : '\x7';
+        i = ((int)(azm * 3600.)) * 4;
+        nexstar.commsPackets[handle].buffer[4] = (char)((i & 0xFF00) >> 8);
+        nexstar.commsPackets[handle].buffer[5] = (char)(i & 0xFF);
+        nexstar.commsPackets[handle].buffer[6] = '\0';
+        nexstar.commsPackets[handle].buffer[7] = '\0';
+        REQUEST_SET(NEXSTAR_SET_AZM_RATE, 8);
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(0, 0);
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_set_location(int mode, unsigned char handle, NEXSTAR_LOCATION *location)
+ *
+ * Used to set the Nexstar's location.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @param NEXSTAR_LOCATION *location A pointer to a data struct holding the data.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_set_location(int mode, unsigned char handle, NEXSTAR_LOCATION *location) {
+
+    /* Create request and queue. */    
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'W';
+        memcpy((char *)nexstar.commsPackets[handle].buffer + 1, (char *)location, 8);
+        REQUEST_SET(NEXSTAR_SET_LOCATION, 9);
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(1, 0);
+        nexstar.trackingMode = buffer[0];
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_set_time(int mode, unsigned char handle, NEXSTAR_TIME *time)
+ *
+ * Used to set the Nexstar time.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @param NEXSTAR_TIME *time A pointer to a data struct holding the data.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_set_time(int mode, unsigned char handle, NEXSTAR_TIME *time) {
+
+    /* Create request and queue. */    
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'H';
+        memcpy((char *)nexstar.commsPackets[handle].buffer + 1, (char *)time, 8);
+        REQUEST_SET(NEXSTAR_SET_TIME, 9);
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(0, 0);
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_get_version(int mode, unsigned char handle)
+ *
+ * Used to set the Nexstar software version.
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_get_version(int mode, unsigned char handle) {
+
+    /* Create request and queue. */    
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        REQUEST_HANDLE;
+        nexstar.commsPackets[handle].buffer[0] = 'V';
+        REQUEST_SET(NEXSTAR_ASK_VERSION, 1);
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        char *buffer = nexstar.commsPackets[handle].buffer;
+        REQUEST_BUFFER_CHECK(2, 0);
+        nexstar.version = (buffer[0] << 8) | buffer[1];
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        return 1;
+    }
+    
+    return 0;
+}
+
+/** nexstar_request_raw(int mode, unsigned char handle, NEXSTAR_COMMS_PACKET *q)
+ *
+ * Used for external callers to setup a REQUEST based on an externally defined packet structure.
+ *
+ * This function allows other parts of the system to make Nextstar requests that are not covered
+ * by the API or just want to handle a request via a callback. 
+ *
+ * @param int mode Determine what action to create, queue request or process packet.
+ * @param unsigned char handle If processing a request this is the index of the packet to be processed.
+ * @param pointer A pointer to a predefined comms request packet to copy into our queue.
+ * @return zero on failure or error, non-zero otherwise.
+ */
+int nexstar_request_raw(int mode, unsigned char handle, NEXSTAR_COMMS_PACKET *q) {
+
+    /* Create request and queue. */    
+    if (mode == NEXSTAR_SEND_REQUEST) {
+        /* Externally handled requests must have a callback defined as a completion handler. */
+        if (q->callback == NULL) {
+            return 0;
+        }
+        REQUEST_HANDLE;
+        memcpy(&nexstar.commsPackets[handle], q, sizeof(NEXSTAR_COMMS_PACKET));
+        REQUEST_SET(NEXSTAR_REQUEST_RAW, 0);
+        return 1;
+    }
+    
+    /* Given a completed request, parse the data and update our information. */
+    if (mode == NEXSTAR_PROCESS_REQUEST) {
+        if (nexstar.commsPackets[handle].requestStatus != NEXSTAR_REQUEST_COMPLETE) return 0;
+        if (nexstar.commsPackets[handle].callback != NULL) {
+            (nexstar.commsPackets[handle].callback)(&nexstar.commsPackets[handle]);
+        }
+        nexstar_request_packet_reset(&nexstar.commsPackets[handle]);            
+        REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_IDLE);
+        return 1;
+    }
+   
+    return 0;
+}
+
+
+/** nexstar_send_request(int handle)
+ *
+ * Used to send a request packet to Nexstar via the serial port.
+ *
+ * @param int handle The packet to send.
+ * @return zero on failure, non-zero otherwise. 
+ */
+int nexstar_send_request(int handle) {
+    if (nexstar.commsPackets[handle].requestStatus == NEXSTAR_REQUEST_PENDING) {
+        nexstar.commsPackets[handle].requestStatus = NEXSTAR_REQUEST_IN_PROGRESS;
+        if (Uart2_puts(nexstar.commsPackets[handle].buffer, (int)nexstar.commsPackets[handle].txLength) != 0) {                
+            memset(nexstar.commsPackets[handle].buffer, 0, NEXSTAR_PACKET_BUFFER_SIZE);
+            nexstar.commsPackets[handle].bufferPointer = 0;
+            // Note, we only start the timeout timer AFTER the TxFIFO goes empty, see below.
+            return 1;
+        }
+        else {
+            /* If we failed to fill the Tx FIFo then switch this request back to pending. */
+            REQUEST_SET_PACKET_STATUS(handle, NEXSTAR_REQUEST_PENDING);        
+            return 0;
+        }
+    }
+    return 0;
+}
+
+/** UART2_IRQHandler(void)
+ *
+ * The interrupt service routine for the UART2.
+ */
+extern "C" void UART2_IRQHandler(void) {
+    char c;
+    uint32_t iir; 
+
+    /* Get the interrupt identification register which also resets IIR. */
+    iir = LPC_UART2->IIR;
+
+    if (iir & 0x0001) {
+        /* Eh? Then why did we interrupt? */
+        return;
+    }
+       
+    /* Do we have incoming data? */
+    if (iir & UART_ISSET_RDA) {
+        c = (char)LPC_UART2->RBR;
+        //debug.printf(" %c", c & 0x7f);
+        if (nexstar.commsPackets[nexstar.currentRequest].requestStatus != NEXSTAR_REQUEST_IN_PROGRESS) { 
+            return;
+        }
+        nexstar.commsPackets[nexstar.currentRequest].buffer[nexstar.commsPackets[nexstar.currentRequest].bufferPointer] = c;
+        nexstar.commsPackets[nexstar.currentRequest].bufferPointer++;
+        nexstar.commsPackets[nexstar.currentRequest].bufferPointer &= (NEXSTAR_PACKET_BUFFER_SIZE-1);
+        if (c == '#' || c == '\r' || c == '\n') {            
+            timeout.stop();   /* Halt the timeout timer. */
+            REQUEST_SET_PACKET_STATUS(nexstar.currentRequest, NEXSTAR_REQUEST_COMPLETE);
+            
+            /* Advance to the next request packet and if pending start it. */
+            //NEXSTAR_NEXT_REQUEST(nexstar.currentRequest);
+            //nexstar_send_request(nexstar.currentRequest);
+            //debug.printf("\r\n");
+        }
+    }
+
+    /* If the THRE goes empty AND the TxFIFO is also empty then a command
+       was just sent to the Nexstar. Start the serial timeout timer so we 
+       only make a timeout measurement AFTER we have sent our command. 
+       That way we don't include our serial transmit time within the timeout
+       specified by the timer. */
+    if (iir & UART_ISSET_THRE) {
+        if ((LPC_UART2->FIFOLVL & UART_ISSET_FIFOLVL_TXFULL) == 0) {
+            timeout.start(nexstar.commsPackets[nexstar.currentRequest].timeout == 0 ? NEXSTAR_SERIAL_TIMEOUT : (uint32_t)nexstar.commsPackets[nexstar.currentRequest].timeout);
+        }
+    }  
+    
+    if (iir & UART_ISSET_RLS) {
+        // Do nothing for now other than read the iir register and clear the interrupt.
+    }
+}
+
+/** Uart2_init
+ *
+ * Initialise UART2 to our requirements for Nexstar.
+ */
+void Uart2_init (void) {
+
+    /* Switch on UART2. */
+    LPC_SC->PCONP |= UART2_ORMASK_PCONP;
+
+    /* Set PCLK == CCLK, 96Mhz */
+    LPC_SC->PCLKSEL1 |= UART2_ORMASK_PCLKSEL1;
+
+    /* Enable the tx/rx to pins and select pin mode. */
+    LPC_PINCON->PINSEL0  |= UART2_ORMASK_PINSEL0;
+    LPC_PINCON->PINMODE0 |= UART2_ORMASK_PINMODE0;
+       
+    /* Set the divisor values for 9600 and then set 8,n,1 */
+    LPC_UART2->LCR = UART2_SET_LCR_DLAB;
+    LPC_UART2->DLL = UART2_SET_DLLSB;
+    LPC_UART2->DLM = UART2_SET_DLMSB;
+    LPC_UART2->LCR = UART2_SET_LCR;
+    
+    /* Enable FIFOs and then clear them. */
+    LPC_UART2->FCR = UART2_SET_FCR;
+    LPC_UART2->FCR = UART2_SET_FCR_CLEAR;
+
+    /* Enable the RDA and THRE interrupts. */
+    LPC_UART2->IER = UART2_SET_IER;
+    
+    /* Now it's time to do interrupts. */
+    NVIC_SetVector(UART2_IRQn, (uint32_t)UART2_IRQHandler);
+    NVIC_EnableIRQ(UART2_IRQn);    
+}
+
+/** Uart2_flush_rxfifo
+ * 
+ * Flush the input RX fifo to make sure it's empty.
+ */
+void Uart2_flush_rxfifo(void) {
+    uint8_t c;
+    while (LPC_UART2->LSR & 0x1) {
+        c = LPC_UART2->RBR;
+    }
+}
+
+/** Uart2_putc
+ *
+ * Put the character given into the TxFIFO.
+ * By design there should always be room in 
+ * the fifo, but check it to make sure.
+ *
+ * @param char The character to write.
+ * @return int zero on failure, non-zero otherwise.
+ */
+int Uart2_putc(char c) {
+    /* Check the TxFIFO is not full.  */
+    if ((LPC_UART2->FIFOLVL & UART_ISSET_FIFOLVL_TXFULL) != 0) return 0;
+    LPC_UART2->THR = (uint8_t)c;
+    return -1;
+}
+
+/** Uart2_puts
+ *
+ * Put the string given into the TX FIFO.
+ * By design there should always be room in 
+ * the fifo, but check it to make sure.
+ *
+ * @param char *s Pointer The string to write.
+ * @return int zero on failure, non-zero (number of chars written) otherwise.
+ */
+int Uart2_puts(char *s, int len) {
+    int i;
+    
+    /* Check the FIFO is empty, as it should always be by design. */
+    if ((LPC_UART2->FIFOLVL & UART_ISSET_FIFOLVL_TXFULL) == 0) {
+        for (i = 0; i < len; i++) {
+            LPC_UART2->THR = (uint8_t)s[i];
+            debug.printf("%c", s[i]);
+        }
+        debug.printf("\r\n");
+    }
+    else {
+        return 0;
+    }
+    return i;
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osd/MAX7456.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,374 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/*
+    Design notes. 
+    The MAX7456 is connected to SSP1 on the Mbed. Additionally, the vertical sync
+    is connected to Pxx, horizontal sync to Pxx, LOS to Pxx, RST to Pxx. These IO
+    pins are setup and macros made available via gpio.c and the interrupts (vsync)
+    via gpioirq.c so for information regarding those see those modules.
+*/
+
+#include "sowb.h"
+#include "gpio.h"
+#include "gpioirq.h"
+#include "utils.h"
+#include "user.h"
+#include "MAX7456.h"
+#include "MAX7456_chars.h"
+#include "debug.h"
+
+/* Forward local function prototypes. */
+static void SSP1_init(void);
+
+/* Declare the custom character map (CM) definitions.
+   See MAX7456_chars.c for more details. */
+extern MAX7456_CUSTOM_CHAR custom_chars[];
+
+/* Map ASCII table to the MAX7456 character map.
+   Note, the MAX7456 in-built character map is no where near the ascii
+   table mapping and very few characters are abailable to map. Where 
+   possible we create new characters for those we need that are missing
+   from the MAX7456 that we want to use and also we create some special
+   characters of our own that are not ASCII chars (crosshair for example).
+   These additional character definitions are listed below the table. 
+   Character maps we have create can be found in MAX7456_chars.c */
+const unsigned char MAX7456_ascii[256] = {
+
+    /* Regular ASCII table. */
+    /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
+    /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* 20 */ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x46,  0x3F, 0x40, 0x00, 0x4d, 0x45, 0x49, 0x41, 0x47, 
+    /* 30 */ 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  0x08, 0x09, 0x44, 0x43, 0x4A, 0x00, 0x4B, 0x42,
+    /* 40 */ 0x4C, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,  0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 
+    /* 50 */ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0X1F, 0x20, 0x21,  0x22, 0x23, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* 60 */ 0x46, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,  0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+    /* 70 */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,  0x3C, 0x3D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    
+    /* Extended ASCII table. */
+    /*         00    01    02    03    04    05    06    07     08    09    0A    0B    0C    0D    0E    0F  */  
+    /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* B0 */ 0xB0, 0x00, 0x00, 0xB3, 0xB4, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF,   
+    /* C0 */ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0xD9, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* E0 */ 0xe0, 0xe1, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00     
+};
+
+/** MAX7456_map_char
+ *
+ * Convert the supplied ASCII character to a MAX7456 character.
+ * Note, the MAX7456 does not support all ASCII chars. Those it
+ * cannot convert are converted to spaces. Proceedure is a simple
+ * table look-up.
+ *
+ * @See const unsigned char MAX7456_ascii
+ *
+ * @param unsigned char c The character to convert.
+ * @return unsigned char The converted character.
+ */
+unsigned char MAX7456_map_char(unsigned char c) {
+    return MAX7456_ascii[c];
+}
+
+/** MAX7456_init
+ */
+void MAX7456_init(void) {
+    
+    /* Setup SSP1 to interface to the MAX7456 chip. */
+    SSP1_init();
+
+    DEBUG_INIT_START;
+    
+    /* Reset the MAX7456 device. */    
+    MAX7456_RST_ASSERT;
+    user_wait_ms_blocking(100);    
+    MAX7456_RST_DEASSERT;
+    user_wait_ms_blocking(100);
+
+    /* Write the custom CM map. */
+    MAX7456_write_byte(0, MAX7456_read_byte(0) & 0xF7);
+    for (int index = 0; custom_chars[index].ascii != 0; index++) {
+        MAX7456_write_char_map(custom_chars[index].ascii, custom_chars[index].map);
+    }
+    user_wait_ms_blocking(100);
+
+    /* Change the vertical offset. */
+    MAX7456_write_byte(0x3, 0x16);
+    
+    /* Enable display of OSD image. */
+    MAX7456_write_byte(0x0, 0x48);
+    
+    DEBUG_INIT_END;
+}
+
+/** MAX7456_vsync_fall
+ *
+ * Interrupt handler for the vertical sync signal from the MAX7456 chip.
+ * Note, this is called from gpioirq.c module which handles GPIO interrupts.
+ */
+void osd_vsync(void);
+void MAX7456_vsync_fall(void) {
+    osd_vsync();
+}
+
+/** MAX7456_vsync_rise
+ *
+ * Interrupt handler for the vertical sync signal from the MAX7456 chip.
+ * Note, this is called from gpioirq.c module which handles GPIO interrupts.
+ */
+void MAX7456_vsync_rise(void) {
+    // Does nothing.
+}
+
+/** MAX7456_write_byte
+ *
+ * Used to write a byte to a specific address.
+ * This function also doubles up to allow a byte
+ * to be written without an address (less than 0x80)
+ * and this is used to make 16bit transfer from two
+ * 8bit transfers or to construct continuous 8bit
+ * transfer where the MAX7456 auto-increments an 
+ * internal location pointer on each write operation.
+ *
+ * Note, this function effectivly "blocks". However, the
+ * speed of the SSP serial bus is pretty high to say the
+ * least and experimentation has show it, so far, to have
+ * had no adverse effects.
+ *
+ * @param unsigned char address The register address to write to.
+ * @param unsigned char byte The byte to write to teh register.
+ */
+void MAX7456_write_byte(unsigned char address, unsigned char byte) {
+    volatile int dev_null __attribute__((unused));
+    
+    MAX7456_CS_ASSERT;
+    
+    /* MAX7456 addresses are always less than 0x80 so if the
+       address is > 0x7F then the caller is requesting an direct
+       8bit data transfer. */
+    if (address < 0x80) {
+        LPC_SSP1->DR = (uint32_t)(address & 0xFF);
+        while(LPC_SSP1->SR & 0x10);     
+        dev_null = LPC_SSP1->DR;            
+    }
+    
+    LPC_SSP1->DR = (uint32_t)byte & 0xFF;
+    while(LPC_SSP1->SR & 0x10); 
+    dev_null = LPC_SSP1->DR;
+            
+    MAX7456_CS_DEASSERT;
+}
+
+/** MAX7456_read_byte
+ *
+ * Read a byte from a specific address.
+ *
+ * Note, this function effectivly "blocks". However, the
+ * speed of the SSP serial bus is pretty high to say the
+ * least and experimentation has show it, so far, to have
+ * had no adverse effects.
+ *
+ * @param unsigned char address The address of the register to read.
+ * @return int data The value of the register addressed.
+ */
+int MAX7456_read_byte(unsigned char address) {
+    int data;
+
+    MAX7456_CS_ASSERT;
+    
+    LPC_SSP1->DR = (uint32_t)address & 0xFF;
+    while(LPC_SSP1->SR & 0x10);
+    data = LPC_SSP1->DR; /* Discarded. */
+    
+    LPC_SSP1->DR = 0;
+    while(LPC_SSP1->SR & 0x10);
+    data = LPC_SSP1->DR & 0xFF;
+    
+    MAX7456_CS_DEASSERT;
+    
+    return data;
+}
+
+/** MAX7456_cursor
+ *
+ * Move the MAX7456 "cursor" (next display memory write)
+ * to the specified position.
+ *
+ * @param int x The X position.
+ * @param int y The Y position.
+ */
+void MAX7456_cursor(int x, int y) {
+    int pos = (y * 30) + x;
+    MAX7456_write_byte(0x05, (unsigned char)((pos >> 8) & 0xFF));
+    MAX7456_write_byte(0x06, (unsigned char)(pos & 0xFF));
+}
+
+/** MAX7456_convert_string
+ *
+ * Convert the NULL terminated raw string to MAX7456 character set compat bytes.
+ * Note, alters the string passed, doesn't make a copy of the string so cannot 
+ * be a const value.
+ *
+ * @param unisgned char *s A pointer to the string to convert.
+ */
+void MAX7456_convert_string(unsigned char *s) {
+    while(*(s)) {
+        *(s) = MAX7456_ascii[*(s)];
+        s++;
+    }
+}
+
+/** MAX7456_string
+ *
+ * Send the NULL terminated ASCII string to the display memory.
+ *
+ * @param unisgned char *s A pointer to the ASCII string to write.
+ */
+void MAX7456_string(unsigned char *s) {
+    MAX7456_write_byte(0x04, 0x01);  /* Enable 8bit write */
+    while(*(s)) {
+        MAX7456_write_byte(0x80, MAX7456_map_char(*s++));
+    }
+    MAX7456_write_byte(0x80, 0xFF);
+}
+
+/** MAX7456_stringl
+ *
+ * Send the ASCII string to the display memory. A null will terminate the write.
+ *
+ * @param int x The X position to write the string to.
+ * @param int y The Y position to write the string to.
+ * @param unisgned char *s A pointer to the string to write.
+ * @param int len The length of the string to send.
+ */
+void MAX7456_stringl(int x, int y, unsigned char *s, int len) {
+    MAX7456_cursor(x, y);            
+    MAX7456_write_byte(0x04, 0x01);  /* Enable 8bit write */
+    while(len--) {
+        if (*s == '\0') break;
+        MAX7456_write_byte(0x80, MAX7456_map_char(*s++));
+    }
+    MAX7456_write_byte(0x80, 0xFF);
+}
+
+/** MAX7456_read_char_map
+ *
+ * Reads the 54byte character make-up bytes and stores them into a buffer.
+ *
+ */
+void MAX7456_read_char_map(unsigned char address, unsigned char *data54) {
+    MAX7456_write_byte(0x9, address);
+    MAX7456_write_byte(0x8, 0x50);
+    user_wait_ms_blocking(100);
+    for (int index = 0; index < 54; index++) {
+        MAX7456_write_byte(0xA, index);
+        user_wait_ms_blocking(1);
+        *(data54 + index) = MAX7456_read_byte(0xC0);
+    }
+}
+
+/** MAX7456_write_char_map
+ *
+ * Used to write the 54bytes that make up a character into
+ * the MAX7456 CM non-volatile memory. Note, it tests the
+ * current non-v memory against the supplied buffer and only
+ * writes the buffer out if they don't match. Used to ensure
+ * we don't keep writing the same data into non-v memory which
+ * has a "lifetime" associated with it.
+ *
+ * @param unsigned char address The character address we are writing.
+ * @param unsigned char *data54 An array that contains the 54bytes of CM data.
+ */
+void MAX7456_write_char_map(unsigned char address, const unsigned char *data54) {
+    unsigned char index, c, match = 1;
+    
+    MAX7456_write_byte(0x9, address);
+    MAX7456_write_byte(0x8, 0x50);
+    user_wait_ms_blocking(20);
+    for (index = 0; index < 54; index++) {
+        MAX7456_write_byte(0xA, index);
+        c = MAX7456_read_byte(0xC0);
+        if (c != data54[index]) {
+            match = 0;            
+            break;
+        }
+    }
+    
+    if (!match) {   
+        MAX7456_write_byte(0x9, address);
+        for (index = 0; index < 0x36; index++) {
+            MAX7456_write_byte(0x0A, index);
+            MAX7456_write_byte(0x0B, data54[index]);
+        }
+        MAX7456_write_byte(0x08, 0xA0);
+        user_wait_ms_blocking(20);
+        while ((MAX7456_read_byte(0xA0) & 0x20) != 0x00);    
+    }
+}
+
+/** SSP1_init
+ */
+static void SSP1_init(void) {
+
+    DEBUG_INIT_START;
+    
+    /* The MAX7456 device is connected to SSP1 via the Mbed pins.
+       So this init is about configuring just the SSP1, other
+       MAX7456 signals (vsync, etc) are setup elsewhere although
+       make call backs to this module as the "clearing house" for
+       MAX7456 signals. */
+    
+    /* Enable the SSP1 peripheral. */
+    LPC_SC->PCONP |= (1UL << 10);
+
+    /* Select the clock required for SSP1. */    
+    LPC_SC->PCLKSEL0  &= ~(3UL << 20);
+    LPC_SC->PCLKSEL0  |=  (3UL << 20);
+    
+    /* Select the GPIO pins for the SSP1 functions. */
+    /* SCK1 */
+    LPC_PINCON->PINSEL0  &= ~(3UL << 14);
+    LPC_PINCON->PINSEL0  |=  (2UL << 14);
+    /* MISO1 */
+    LPC_PINCON->PINSEL0  &= ~(3UL << 16);
+    LPC_PINCON->PINSEL0  |=  (2UL << 16);
+    /* MOSI1 */
+    LPC_PINCON->PINSEL0  &= ~(3UL << 18);
+    LPC_PINCON->PINSEL0  |=  (2UL << 18);
+    
+    /* Note, we don't use SSEL1 in our design, we just use a standard GPIO
+       because a) the MAX7456 didn't really like the speed! and b) writing
+       16bit data is somewhat simpler than reconfiguring the SSP each time
+       when all we need to do is hold CS low across 2 8bit operations. */
+    
+    /* Setup the control registers for SSP1 */
+    LPC_SSP1->CR0  = 0x7;
+    LPC_SSP1->CPSR = 0x2;
+    LPC_SSP1->CR1  = 0x2;
+    
+    DEBUG_INIT_END;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osd/MAX7456.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,41 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef MAX7456_H
+#define MAX7456_H
+
+#define MAX7456_DISPLAY_LINES 15
+#define MAX7456_DISPLAY_LINE_LEN 32
+
+/* Function prototypes. */
+void MAX7456_init(void);
+void MAX7456_write_byte(unsigned char address, unsigned char byte);
+int MAX7456_read_byte(unsigned char address);
+void MAX7456_cursor(int x, int y);
+unsigned char MAX7456_map_char(unsigned char c);
+void MAX7456_convert_string(unsigned char *s);
+void MAX7456_string(unsigned char *s);
+void MAX7456_stringl(int x, int y, unsigned char *s, int len);
+void MAX7456_read_char_map(unsigned char address, unsigned char *data54);
+void MAX7456_write_char_map(unsigned char address, const unsigned char *data54);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osd/MAX7456_chars.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,405 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "MAX7456_chars.h"
+
+/* Why doesn't the MAX7456 have a + symbol? wtf! */
+const unsigned char ascii_4d[54] = {
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x00, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x00, 0x28, 0x00,
+    0x4A, 0xAA, 0xA1,
+    0x4A, 0xAA, 0xA1,
+    0x00, 0x28, 0x00,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x00, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55    };
+
+const unsigned char crosshair1_left[54] = {
+    0x55, 0x55, 0x56, // 0
+    0x55, 0x55, 0x56, // 1
+    0x55, 0x55, 0x56, // 2
+    0x55, 0x55, 0x56, // 3
+    0x55, 0x55, 0x56, // 4
+    0x55, 0x55, 0x56, // 5
+    0x55, 0x55, 0x55, // 6
+    0x55, 0x55, 0x55, // 7
+    0x55, 0xAA, 0x95, // 8
+    0x55, 0xAA, 0x95, // 9  - 8
+    0x55, 0x55, 0x55, // 10 - 7
+    0x55, 0x55, 0x55, // 11 - 6
+    0x55, 0x55, 0x56, // 12 - 5
+    0x55, 0x55, 0x56, // 13 - 4
+    0x55, 0x55, 0x56, // 14 - 3
+    0x55, 0x55, 0x56, // 15 - 2
+    0x55, 0x55, 0x56, // 16 - 1
+    0x55, 0x55, 0x56    };
+
+const unsigned char crosshair1_right[54] = {
+    0x95, 0x55, 0x55, // 0
+    0x95, 0x55, 0x55, // 1
+    0x95, 0x55, 0x55, // 2
+    0x95, 0x55, 0x55, // 3
+    0x95, 0x55, 0x55, // 4
+    0x95, 0x55, 0x55, // 5
+    0x55, 0x55, 0x55, // 6
+    0x55, 0x55, 0x55, // 7
+    0x56, 0xAA, 0x55, // 8
+    0x56, 0xAA, 0x55, // 9  - 8
+    0x55, 0x55, 0x55, // 10 - 7
+    0x55, 0x55, 0x55, // 11 - 6
+    0x95, 0x55, 0x55, // 12 - 5
+    0x95, 0x55, 0x55, // 13 - 4
+    0x95, 0x55, 0x55, // 14 - 3
+    0x95, 0x55, 0x55, // 15 - 2
+    0x95, 0x55, 0x55, // 16 - 1
+    0x95, 0x55, 0x55    };
+    
+const unsigned char crosshair_centre[54] = {
+    0x55, 0x28, 0x55,   // 0
+    0x55, 0x28, 0x55,   // 1
+    0x55, 0x28, 0x55,   // 2
+    0x55, 0x28, 0x55,   // 3
+    0x55, 0x28, 0x55,   // 4
+    0x55, 0x00, 0x55,   // 5
+    0x55, 0x55, 0x55,   // 6
+    0x01, 0x55, 0x40,   // 7
+    0xA1, 0x69, 0x4A,   // 8
+    0xA1, 0x69, 0x4A,   // 9
+    0x01, 0x55, 0x40,   // 10
+    0x55, 0x55, 0x55,   // 11
+    0x55, 0x00, 0x55,   // 12
+    0x55, 0x28, 0x55,   // 13
+    0x55, 0x28, 0x55,   // 14
+    0x55, 0x28, 0x55,   // 15
+    0x55, 0x28, 0x55,   // 16
+    0x55, 0x28, 0x55    };
+    
+
+const unsigned char ascii_b0[54] = {
+    0x55, 0x55, 0x55, // 0
+    0x55, 0x55, 0x55, // 1
+    0x50, 0x01, 0x55, // 2
+    0x42, 0xA0, 0x55, // 3
+    0x0A, 0xA8, 0x15, // 4
+    0x28, 0x0A, 0x15, // 5
+    0x28, 0x0A, 0x15, // 6
+    0x28, 0x0A, 0x15,
+    0x0A, 0xA8, 0x15,
+    0x42, 0xA0, 0x55,
+    0x50, 0x01, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55    };
+
+const unsigned char ascii_b3[54] = {
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55    };
+
+const unsigned char ascii_b4[54] = {
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x00, 0x28, 0x55,
+    0xAA, 0xA8, 0x55,
+    0xAA, 0xA8, 0x55,
+    0x00, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55    };
+
+const unsigned char ascii_bf[54] = {
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x00, 0x00, 0x55,
+    0xAA, 0xA8, 0x55,
+    0xAA, 0xA8, 0x55,
+    0x00, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55    };
+
+const unsigned char ascii_c0[54] = {
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x00,
+    0x55, 0x2A, 0xAA,
+    0x55, 0x2A, 0xAA,
+    0x55, 0x00, 0x00,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55    };
+
+const unsigned char ascii_c1[54] = {
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x00, 0x28, 0x00,
+    0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA,
+    0x00, 0x00, 0x00,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55    };
+
+const unsigned char ascii_c2[54] = {
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x00, 0x00, 0x00,
+    0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA,
+    0x00, 0x28, 0x00,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55    };
+
+const unsigned char ascii_c3[54] = {
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x00,
+    0x55, 0x2A, 0xAA,
+    0x55, 0x2A, 0xAA,
+    0x55, 0x28, 0x00,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55    };
+
+const unsigned char ascii_c4[54] = {
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x00, 0x00, 0x00,
+    0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA,
+    0x00, 0x00, 0x00,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55    };
+
+const unsigned char ascii_c5[54] = {
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x00, 0x28, 0x00,
+    0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA,
+    0x00, 0x28, 0x00,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55    };
+
+const unsigned char ascii_d9[54] = {
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x00, 0x28, 0x55,
+    0xAA, 0xA8, 0x55,
+    0xAA, 0xA8, 0x55,
+    0x00, 0x00, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55    };
+
+const unsigned char ascii_da[54] = {
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x55, 0x55,
+    0x55, 0x00, 0x00,
+    0x55, 0x2A, 0xAA,
+    0x55, 0x2A, 0xAA,
+    0x55, 0x28, 0x00,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55,
+    0x55, 0x28, 0x55    };
+
+/* For the curious, during testing I managed to screw up the
+   characher at CM index2, ('2'). So I needed to reprogram
+   index2 with the correct character, doh! Anyway, since I
+   went to the trouble I'll leave it in the code. I managed
+   to find a default CM map at:- 
+        http://www.maxim-ic.com/tools/evkit/index.cfm?EVKit=558
+   If you download this then be aware that the DEFAULTCM.MCM file
+   defines each charmap as 64bytes, the 10 additional bytes need
+   to be stripped off as "not used". */
+#ifdef FIX_CM2_SCREW_UP
+const unsigned char ascii_02[54] = {
+    0x55, 0x55, 0x55, // 01010101 01010101 01010101
+    0x55, 0x55, 0x55, // 01010101 01010101 01010101
+    0x54, 0x00, 0x15, // 01010100 00000000 00010101
+    0x52, 0xAA, 0x85, // 01010010 10101010 10000101
+    0x4A, 0xAA, 0xA1, // 01001010 10101010 10100001
+    0x2A, 0x80, 0xA8, // 00101010 10000000 10101000
+    0x2A, 0x15, 0x28, // 00101010 00010101 00101000
+    0x40, 0x55, 0x28, // 01000000 01010101 00101000
+    0x55, 0x54, 0xA8, // 01010101 01010100 10101000
+    0x55, 0x52, 0xA1, // 01010101 01010010 10100001
+    0x55, 0x4A, 0x85, // 01010101 01001010 10000101
+    0x55, 0x2A, 0x15, // 01010101 00101010 00010101
+    0x54, 0xA8, 0x55, // 01010100 10101000 01010101
+    0x52, 0xA1, 0x55, // 01010010 10100001 01010101
+    0x4A, 0x80, 0x01, // 01001010 10000000 00000001
+    0x2A, 0xAA, 0xA8, // 00101010 10101010 10101000
+    0x2A, 0xAA, 0xA8, // 00101010 10101010 10101000
+    0x40, 0x00, 0x01  // 01000000 00000000 00000001
+};
+#endif
+
+/* Create an array of structures that link the data
+   characters to ASCII characters. The last entry 
+   must always be null so we can detect the end of 
+   the array. */    
+MAX7456_CUSTOM_CHAR custom_chars[] = {
+    { 0xE0, crosshair1_left },
+    { 0xE1, crosshair1_right },
+    { 0xE2, crosshair_centre },
+    { 0x4D, ascii_4d },
+    { 0xB0, ascii_b0 },
+    { 0xB3, ascii_b3 },
+    { 0xB4, ascii_b4 },
+    { 0xBF, ascii_bf },
+    { 0xC0, ascii_c0 },
+    { 0xC1, ascii_c1 },
+    { 0xC2, ascii_c2 },
+    { 0xC3, ascii_c3 },
+    { 0xC4, ascii_c4 },
+    { 0xC5, ascii_c5 },
+    { 0xD9, ascii_d9 },
+    { 0xDA, ascii_da },
+#ifdef FIX_CM2_SCREW_UP    
+    { 0x02, ascii_02 },
+#endif    
+    { 0x00, 0 }
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osd/MAX7456_chars.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,33 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef MAX7456_CHARS_H
+#define MAX7456_CHARS_H
+
+typedef struct _max7456_custom_char {
+    unsigned char         ascii;
+    const unsigned char   *map;
+} MAX7456_CUSTOM_CHAR;
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osd/osd.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,315 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "debug.h"
+#include "osd.h"
+#include "gps.h"
+#include "satapi.h"
+#include "utils.h"
+#include "nexstar.h"
+
+int test_counter = 0;
+
+/* Define the array of OSD dislay lines. */
+OSD_display_line osd_display_area[MAX7456_DISPLAY_LINES];
+
+/* Toggle between odd and even fields. */
+int video_field;
+
+/* The top two display lines have a special use case. This int
+   is used to select the mode in which it works. */
+int l01_mode;
+
+/* Handles whether and how the crosshair is displayed. */
+int crosshair_mode;
+
+
+/** osd_init
+ */
+void osd_init(void) {
+
+    DEBUG_INIT_START;
+    video_field = 0;
+    l01_mode = 0;
+    crosshair_mode = 1;
+    osd_clear();
+    DEBUG_INIT_END;
+}
+
+/** osd_clear
+ *
+ * Clear the display area buffer.
+ */
+void osd_clear(void) {
+    for (int i = 0; i < MAX7456_DISPLAY_LINES; i++) {
+        osd_clear_line(i);
+    }
+}
+
+/** osd_clear_line
+ *
+ * Clear a single line.
+ *
+ * @param int line The line to clear.
+ */
+void osd_clear_line(int line) {
+    for (int i = 0; i < MAX7456_DISPLAY_LINE_LEN; i++) {
+        osd_display_area[line].line_buffer[i] = '\0';
+    }
+    osd_display_area[line].update = true;
+}
+
+/** osd_string
+ *
+ * Write a null terminated string to a display line.
+ *
+ * @param int line The display line to write to.
+ * @param char *s The null terminated string.
+ */
+void osd_string(int line, char *s) {
+    for (int i = 0; *s; s++, i++) {
+        osd_display_area[line].line_buffer[i] = *s;
+    }
+    osd_display_area[line].update = true;
+}
+
+/** osd_string_xy
+ *
+ * Write a null terminated string to a display line at x y.
+ *
+ * @param int line The display line to write to.
+ * @param char *s The null terminated string.
+ */
+void osd_string_xy(int x, int y, char *s) {
+    for (int i = x; *s; s++, i++) {
+        osd_display_area[y].line_buffer[i] = *s;
+    }
+    osd_display_area[y].update = true;
+}
+
+/** osd_string_xyl
+ *
+ * Write a null terminated string to a display line at x y.
+ *
+ * @param int line The display line to write to.
+ * @param char *s The null terminated string.
+ * @param int len The length of the string to print.
+ */
+void osd_string_xyl(int x, int y, char *s, int len) {
+    for (int i = x; len; s++, i++, len--) {
+        osd_display_area[y].line_buffer[i] = *s;
+    }
+    osd_display_area[y].update = true;
+}
+
+/** osd_stringl
+ *
+ * Write a string of specified length to a display line.
+ *
+ * @param int line The display line to write to.
+ * @param char *s The string.
+ * @param int len The length to write.
+ */
+void osd_stringl(int line, char *s, int len) {
+    for (int i = 0; len; s++, i++, len--) {
+        osd_display_area[line].line_buffer[i] = *s;
+    }
+    osd_display_area[line].update = true;
+}
+
+/** osd_get_mode_l01
+ */
+int osd_get_mode_l01(void) {
+    return l01_mode;
+}
+
+/** osd_set_mode_l01
+ */
+void osd_set_mode_l01(int mode) {
+    l01_mode = mode;
+}
+
+/** osd_l01_next_mode
+ */
+void osd_l01_next_mode(void) {
+    int m = osd_get_mode_l01();
+    m++;
+    if (m > L01_MODE_D) m = L01_MODE_A;
+    osd_set_mode_l01(m);
+}
+
+/** osd_set_crosshair
+ */
+int osd_set_crosshair(int mode) {
+    if (mode > -1) {
+        crosshair_mode = mode;
+    }
+    return crosshair_mode;
+}
+
+/** osd_crosshair_toggle
+ */
+int osd_crosshair_toggle(void) {
+    crosshair_mode = crosshair_mode == 0 ? 1 : 0;
+    if (!crosshair_mode) osd_clear();
+    return crosshair_mode;
+}
+
+/** osd_write_buffers
+ *
+ * Write the line buffers to the display.
+ */
+static void osd_write_buffers(void) {
+    for (int i = 0; i < MAX7456_DISPLAY_LINES; i++) {
+        if (osd_display_area[i].update) {
+            MAX7456_cursor(0, i);
+            MAX7456_write_byte(0x04, 0x01); /* Enable 8bit write. */
+            for (int j = 0; j < MAX7456_DISPLAY_LINE_LEN; j++) {
+                MAX7456_write_byte(0x80, MAX7456_map_char(osd_display_area[i].line_buffer[j]));
+            } 
+            MAX7456_write_byte(0x80, 0xFF);
+            osd_display_area[i].update = false;            
+        }
+    }
+}
+
+void osd_l01_position(void) {
+    GPS_LOCATION_AVERAGE loc;
+    char buf[64], buf2[64];
+    double el, azm;
+    
+    gps_get_location_average(&loc);
+    
+    if (l01_mode != 0) {
+        if (IS_NEXSTAR_ALIGNED) {
+            nexstar_get_elazm(&el, &azm);
+            printDouble_3_2(buf, el);  osd_string_xy(12, 0, buf);
+            printDouble_3_2(buf, azm); osd_string_xy(12, 1, buf);
+        }
+        else {
+            strcpy(buf, "---.--");
+            osd_string_xy(12, 0, buf);
+            osd_string_xy(12, 1, buf);        
+        }
+    }
+    
+    switch(l01_mode) {                                                
+        case L01_MODE_C:
+        case L01_MODE_D:
+            double2dms(buf2, loc.latitude);  sprintf(buf, "%c%s", loc.north_south, buf2); osd_string_xy(18, 0, buf);
+            double2dms(buf2, loc.longitude); sprintf(buf, "%c%s", loc.east_west, buf2);   osd_string_xy(18, 1, buf);
+            break;
+        case L01_MODE_A:
+        case L01_MODE_B:
+            printDouble(buf2, loc.latitude);  sprintf(buf, " %c%c%s", loc.is_valid, loc.north_south, buf2); osd_string_xy(18, 0, buf);
+            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);
+            break;
+    }
+}
+
+/** osd_vsync
+ *
+ * A callback made when the MAX7456 vertical sync fires.
+ */
+void osd_vsync(void) {
+    GPS_TIME latched_time;
+    char buffer[32];
+    
+    /* captire the time at which this VSync pulse occured. */
+    gps_get_time(&latched_time);
+    
+    /* We don't actually know if this is an odd or even field.
+       All we can do is divide by two so each frame only displays
+       the time, otherwise it will "smudge" the display. We may
+       well add in an LM1881 device to the final design as that
+       has an odd/even field ttl output. */
+    if (!video_field) { video_field = 1; return; }
+    else { video_field = 0; }
+
+    /* If no mode is set, do not display line0/1. */
+    if (l01_mode == 0) return;
+    
+    /* Display lines 0 and 1 are used for a specific feature, i.e.
+       the display of the time, GPS position, telescope pointing
+       position, etc. Handle the "time" display portion now. */
+    osd_clear_line(0);
+    osd_clear_line(1);
+
+    char buf2[32];
+    double jd = gps_julian_date(&latched_time);
+    
+    if (crosshair_mode) {
+        osd_string_xy(13, 7, "\xE0\xE1");
+    }
+           
+    switch(l01_mode) {
+        case L01_MODE_D:    
+        case L01_MODE_B:
+            /* Display time as Julain Date. */
+            sprintf(buf2, "%.7f", jd - (long)jd);
+            memset(buffer, 0, 32); sprintf(buffer, "JDI %07ld", (long)jd); osd_string_xy(0, 0, buffer);
+            memset(buffer, 0, 32); sprintf(buffer, "JDF.%s",  buf2 + 2);   osd_string_xy(0, 1, buffer); 
+            break;
+        case L01_MODE_C:    
+        case L01_MODE_A:
+            /* Display time as UTC. */
+            memset(buffer, 0, 32); date_AsString(&latched_time, buffer); osd_string_xy(0, 0, buffer);
+            memset(buffer, 0, 32); time_AsString(&latched_time, buffer); osd_string_xy(0, 1, buffer);
+            break;        
+    }
+    
+    osd_l01_position();
+        
+    #ifdef NEVECOMPILETHIS    
+    /* TEST TEST TEST !!! */
+    /* Test failed. It actually worked, once. It seems the total math
+       involved in doing this is WAY to much to be inside what is effectively
+       an interrupt service routine. It does tell me lots, I need to move all
+       this to _process() but do it in a way that's fast enough for user output 
+       in "real time" as it would appear to the user. */
+    test_counter++;
+    if (test_counter == 1000) {
+        test_counter = 0;
+        SAT_POS_DATA data;
+        data.tsince = 0;
+        strcpy(data.elements[0], "ISS (ZARYA)");
+        strcpy(data.elements[1], "1 25544U 98067A   10249.33655722  .00010912  00000-0  87866-4 0  8417");
+        strcpy(data.elements[2], "2 25544 051.6459 175.3962 0008058 342.0418 161.2933 15.71504826676236");
+        gps_get_time(&data.t);
+        gps_get_location_average(&data.l);    
+        satallite_calculate(&data);
+        if (!isnan(data.elevation) && !isnan(data.azimuth) && !isnan(data.range)) {
+            sprintf(buffer, " ISS EL:%.1f AZM:%.1f RG:%.1f", data.elevation, data.azimuth, data.range);
+            osd_string_xy(0, 14, buffer);
+        }
+    }
+    /* TEST TEST TEST !!! */
+    #endif
+    
+    osd_write_buffers();
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osd/osd.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,65 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef OSD_H
+#define OSD_H
+
+#include "MAX7456.h"
+
+#define L01_MODE_A    1
+#define L01_MODE_B    2
+#define L01_MODE_C    3
+#define L01_MODE_D    4
+
+/* Define a structure that holds a OSD character line.
+   This is used to basically buffer the line so that it
+   can be displayed during the vertical sync period.
+   Additionally, we hold a binary flag to state whether
+   teh buffer has been updated. That way we know if we
+   don't need to send the buffer to the MAX7456 device
+   if no update to the buffer has occured. */
+   
+typedef struct {
+    bool update;
+    char line_buffer[MAX7456_DISPLAY_LINE_LEN];
+} OSD_display_line;
+
+
+void osd_init(void);
+void osd_clear(void);
+void osd_clear_line(int line);
+void osd_string(int line, char *s);
+void osd_string_xy(int x, int y, char *s);
+void osd_stringl(int line, char *s, int len);
+void osd_string_xyl(int x, int y, char *s, int len);
+
+void osd_set_mode_l01(int mode);
+void osd_l01_next_mode(void);
+int osd_set_crosshair(int mode);
+int osd_crosshair_toggle(void);
+
+void osd_vsync(void);
+
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pccomms/handlers/mode1.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,142 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/*
+MODE 1 Packet handler.
+
+This mode is used by the Host to send a file containing all the TLEs that
+SOWB needs to aquire satellites. The base packet payload itself conatins
+a sub packet as defined below. Note, we assign a number of flash pages to
+the TLE file. Each flash page is 256bytes in size. So, the host sends the
+file in 256byte blocks. The sub-packet header defines the block being sent.
+We add to this block the flash base page and write the 256byte sub-packet
+payload into the flash device. Note, TLE files are ascii characters so the
+sub-packet payload is ASCII itself and doesn't require any conversions.
+
+Subp-acket format   <BBBBCF>.........
+Where:-
+    < is the "start of packet header" character.
+    BBBB is a hex string representation of the uint16_t 256 char block.
+    C is a two's complement checksum of the header from < to > inclusive.
+    F is a char flag. Normally zero.
+    > is the "end of packet header" character.
+    .... is the packet payload, 256 bytes in length.
+
+*/
+
+#include "sowb.h"
+#include "user.h"
+#include "utils.h"
+#include "flash.h"
+#include "pccomms.h"
+
+#define FLASH_BASE_TLE_FILE 10
+
+/* Error flags to send back on failure. */
+#define FLAG_BAD_CHECKSUM   '1'
+#define FLAG_INVALID_LENGTH '2'
+
+/* Base packet payload to sub-packet header definition. */
+typedef struct _pccomms_mode1_header {
+    char        lead_char;
+    char        block[4];
+    char        csum;
+    char        flag;
+    char        trail_char;
+} PCCOMMS_MODE1_HEADER;
+
+/* Base packet payload to sub-packet overall definition. */
+typedef struct _pccomms_mode1 {
+    PCCOMMS_MODE1_HEADER    header;
+    char                    payload[256];
+} PCCOMMS_MODE1;
+
+
+/** pccomms_mode1_failed
+ *
+ * Used to send back a failed packet with a flag "reason for failure".
+ *
+ * @param BASE_PACKET_A *a The original ASCII version of the packet header.
+ * @param char flag The char flag to insert. 
+ */
+void pccomms_mode1_failed(BASE_PACKET_A *a, char flag) {
+    BASE_PACKET_A temp;
+    char *p;
+    int i;
+    
+    memcpy((char *)&temp, (char *)a, sizeof(BASE_PACKET_A));
+    temp.flag = flag;
+    temp.csum = 0;
+    temp.csum = strcsuml((char *)&temp, sizeof(BASE_PACKET_A));
+    for (p = (char *)&temp, i = 0; i < sizeof(BASE_PACKET_A); i++) {
+        Uart3_putc((char)p[i]);
+    }
+}
+
+/** pccomms_mode1_handler
+ *
+ * The packet handler for MODE 1.
+ *
+ * @param BASE_PACKET_B *b
+ * @param BASE_PACKET_A *a
+ * @return int 
+ */
+int pccomms_mode1_handler(BASE_PACKET_B *b, BASE_PACKET_A *a) {
+    PCCOMMS_MODE1 data;
+    char *p;
+    int page, c, i;
+        
+    /* Sanity check, should never fail, should really assert() */    
+    if (b->mode != 1) return PCCOMMS_PACKET_REJECTED;
+    
+    /* Sanity check, should never fail, should really assert() */    
+    if (b->length != sizeof(PCCOMMS_MODE1)) return PCCOMMS_PACKET_REJECTED;
+     
+    /* Copy the base packet payload into our internal data structure. */
+    for(p = (char *)&data, i = 0; i < sizeof(PCCOMMS_MODE1); i++) {
+        c = Uart3_getc(0);
+        if (c != -1) p[i] = (char)c;
+        else {
+            /* This shouldn't happen as once the IRQ system has detected the
+               end of the packet it no longer inserts serial chars into the 
+               buffer. So another sanity check really. Unless the Host did
+               in fact screw up somewhere. */
+            pccomms_mode1_failed(a, FLAG_INVALID_LENGTH);
+            return PCCOMMS_PACKET_REJECTED;
+        }
+    }
+
+    /* Run a checksum check. On failure, send back the Host's packet with "flag" set to "bad checksum". */
+    if (strsuml((char *)&data, sizeof(PCCOMMS_MODE1)) != 0) {
+        pccomms_mode1_failed(a, FLAG_BAD_CHECKSUM);
+        return PCCOMMS_PACKET_REJECTED;
+    }
+    
+    /* Get the block header and add the flash page offset. */
+    page = (int)hex2bin(data.header.block, 4) + FLASH_BASE_TLE_FILE;    
+    
+    /* Assuming we programmed the flash device ok, return packet accepted. */    
+    flash_page_write(page, data.payload);
+    while(flash_write_in_progress()) user_call_process();
+    return PCCOMMS_PACKET_ACCEPTED;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pccomms/pccomms.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,285 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/*
+Packet format   <MMMMLLLLCF>.........
+Where:-
+    < is the "start of packet header" character.
+    MMMM is a hex string representation of the uint16_t mode.
+    LLLL is a hex string representation of the uint16_t length (payload length).
+    C is a two's complement checksum of the header from < to > inclusive.
+    F is a char flag. Normally zero.
+    > is the "end of packet header" character.
+    .... is the packet payload, a series of bytes, the number defined by length LLLL
+    
+Note, the C checksum should be added by the sender. This is the two's complement of
+all the ascii chars from < to > inclusive. Once inserted by the sender, the header
+packet can be checked by summing all the charachers, from < to > inclusive and the
+result should be zero.
+    
+Once a complete header is received the IRQ is told how many bytes to read into the
+RX buffer before changing the state to PCCOMMS_PACKET_READ. After this any future
+characters received will be sent to dev/null until the current packet is handled.
+
+The handling is done by the _process() function. Basically, once we have a packet
+the MMMM mode decides what to do with it. The _process() function will call the list
+of handler functions passing a pointer to the packet header. Each handler can
+accept the header and then empty the payload RX buffer. Handlers can get the payload
+by simply calling Uart1_getc(), which will eventually return -1 when the RX buffer
+is empty (which should match the LLLL length of the payload.
+
+If a handler returns PCCOMMS_PACKET_ACCEPTED then we clear out the header and reset
+the serial system to begin listening for a new packet. Note, if a handler needs to
+keep a copy of any data (header or payload) it should do so before it returns 
+PCCOMMS_PACKET_ACCEPTED because the engine here will ensure all buffers get reset
+before going back into reception mode. 
+
+If no handler accepts the packet then the packet is dropped, the serial engine is
+reset and basically everything is reset to begin looking for a new packet header.  */
+
+#include "sowb.h"
+#include "debug.h"
+#include "pccomms.h"
+#include "utils.h"
+
+/* Globals used for the packet reception engine. */
+int            pccomms_state;
+BASE_PACKET_A  header_packet_ascii;
+unsigned char  header_packet_in;
+BASE_PACKET_B  header_packet;
+uint16_t       packet_char_counter;
+
+/* Payload buffers. */
+volatile char uart3txBuffer[UART3_TX_BUFFER_SIZE];
+volatile char uart3rxBuffer[UART3_RX_BUFFER_SIZE];
+volatile unsigned char uart3txBufferIn, uart3txBufferOut;
+volatile unsigned char uart3rxBufferIn, uart3rxBufferOut;
+volatile bool uart3txBufferFull, uart3rxBufferFull, uart3rxBufferOverflow;
+
+/* Used to reset the PC COMMS system. */
+static void pccomms_reset(void) {
+    pccomms_state = PCCOMMS_STATE_WAITING;
+    header_packet_in = 0;
+    uart3txBufferIn = uart3txBufferOut = 0;
+    memset((char *)uart3txBuffer, 0, UART3_TX_BUFFER_SIZE);
+    uart3rxBufferIn = uart3rxBufferOut = 0;
+    memset((char *)uart3txBuffer, 0, UART3_RX_BUFFER_SIZE);
+    uart3txBufferFull = uart3rxBufferFull = false;
+    uart3rxBufferOverflow = false;
+}
+
+/** pccomms_init
+ */
+void pccomms_init(void) {
+    DEBUG_INIT_START;
+    pccomms_reset();
+    Uart3_init();
+    DEBUG_INIT_END;
+}
+
+/* We declare the packet handler functions prototypes here. */
+int pccomms_mode1_handler(BASE_PACKET_B *b, BASE_PACKET_A *a);
+
+/** pccomms_process
+ */
+void pccomms_process(void) {
+    
+    /* If the IRQ system has flagged a packet reception complete handle it. */
+    if (pccomms_state == PCCOMMS_PACKET_READ) {
+        switch(header_packet.mode) {
+            case 1: 
+                pccomms_mode1_handler(&header_packet, &header_packet_ascii); 
+                break;
+        }
+        
+        pccomms_reset();
+    }
+}
+
+/** base_packet_a2b
+ *
+ * Convert a header packet in ASCII format to the internal
+ * binary form.
+ *
+ * @param BASE_PACKET_B *b The dst of the conversion
+ * @param BASE_PACKET_A *a The src of the conversion
+ */
+void base_packet_a2b(BASE_PACKET_B *b, BASE_PACKET_A *a) {
+    b->mode = (uint16_t)hex2bin(a->mode, 4);
+    b->length = (uint16_t)hex2bin(a->length, 4);
+}
+
+/** base_packet_b2a
+ *
+ * Convert an internal header packet in binary format to the external
+ * ASCII form.
+ *
+ * @param BASE_PACKET_A *a The dst of the conversion
+ * @param BASE_PACKET_B *b The src of the conversion
+ */
+void base_packet_b2a(BASE_PACKET_A *a, BASE_PACKET_B *b) {
+   bin2hex((uint32_t)b->mode, 4, a->mode);
+   bin2hex((uint32_t)b->length, 4, a->length);
+   a->lead_char = '<';
+   a->trail_char = '>';
+   a->csum = '\0';
+   a->csum = strcsuml((char *)a, BASE_PACKET_A_LEN);
+}
+
+/** Uart3_putc
+ *
+ * Put a character out the UART1 serial port. 
+ * Note, if the THR register is not empty AND the output buffer is not empty
+ * then place the character into the output buffer and enable interrupt to
+ * flush the buffer.
+ *
+ * Additionally, if the TX buffer is full this function will BLOCK!
+ * Be aware of this blocking!
+ *
+ * @param char c The character to send out of UART1.
+ */
+void Uart3_putc(char c) {
+    if ((LPC_UART3->LSR & 0x20) && (uart3txBufferIn == uart3txBufferOut && !uart3txBufferFull)) {
+        LPC_UART3->THR = (uint8_t)c;
+    }
+    else {  
+        while (uart3txBufferFull) ; /* Blocks!!! */    
+        uart3txBuffer[uart3txBufferIn++] = c;
+        uart3txBufferIn &= (UART3_TX_BUFFER_SIZE - 1);
+        if (uart3txBufferIn == uart3txBufferOut && !uart3txBufferFull) uart3txBufferFull = true;
+        LPC_UART3->IER = 0x3;
+    }
+}
+
+/** Uart3_getc
+ *
+ * Used to get a character from Uart1. If the passed arg "block" is non-zero
+ * then this function will block (wait) for user input. Otherwise if a char
+ * is available return it, otherwise return -1 to show buffer was empty.
+ *
+ * @param int block Should we block?
+ * @return int Cast char to int for char or -1 if non-blocking and no char.
+ */
+int Uart3_getc(int block) {
+    char c;
+    
+    if (block) while (uart3rxBufferOut == uart3rxBufferIn && !uart3rxBufferFull) ; /* Blocks! */    
+    else if (uart3rxBufferIn == uart3rxBufferOut && !uart3rxBufferFull) return -1;
+    
+    c = uart3rxBuffer[uart3rxBufferOut++];
+    uart3rxBufferOut &= (UART3_RX_BUFFER_SIZE - 1);
+    if (uart3rxBufferFull) uart3rxBufferFull = false;     
+    return (int)c;   
+}
+
+/** UART3_IRQHandler
+ */
+extern "C" void UART3_IRQHandler(void) __irq {
+    uint32_t iir;
+    char c, *p;
+    
+    iir = LPC_UART3->IIR;
+    
+    if (iir & 1) return;
+    
+    iir = (iir >> 1) & 0x3;
+    
+    if (iir == 2) {
+        c = (char)LPC_UART3->RBR;
+        if (pccomms_state == PCCOMMS_STATE_WAITING) {
+            p = (char *)&header_packet_ascii;
+            if (c == '<') {
+                header_packet_in = 0;
+                p[header_packet_in++] = c;
+                BASE_PACKET_WRAP;
+            }
+            else if (c == '>') {
+                p[header_packet_in++] = c;
+                BASE_PACKET_WRAP;
+                if (strsuml(p, BASE_PACKET_A_LEN) == 0) { 
+                    base_packet_a2b(&header_packet, &header_packet_ascii);
+                    packet_char_counter = header_packet.length;
+                    pccomms_state = PCCOMMS_BASE_PACKET_READ;
+                }
+                else {
+                    pccomms_state = PCCOMMS_BASE_PACKET_BAD_CSUM;
+                    header_packet_in = 0;
+                }
+            }
+            else {
+                p[header_packet_in++] = c;
+                BASE_PACKET_WRAP;
+            }
+        }
+        else if (pccomms_state == PCCOMMS_BASE_PACKET_READ) {
+            if (uart3rxBufferIn == uart3rxBufferOut && uart3rxBufferFull) {            
+                uart3rxBufferOverflow = true;
+            }
+            else {
+                uart3rxBuffer[uart3rxBufferIn++] = c;
+                uart3rxBufferIn &= (UART3_RX_BUFFER_SIZE - 1);
+                if (uart3rxBufferIn == uart3rxBufferOut) uart3rxBufferFull = true;
+                if (packet_char_counter) packet_char_counter--;
+                if (packet_char_counter == 0) {
+                    pccomms_state = PCCOMMS_PACKET_READ;
+                }
+            }
+            
+        }
+        else {
+            /* Unknown state, send char to /dev/null */          
+        }
+    }
+    
+    if (iir == 1) {
+        if (uart3txBufferIn != uart3txBufferOut || uart3txBufferFull) {
+            LPC_UART3->THR = (uint8_t)(uart3txBuffer[uart3txBufferOut++]);
+            uart3txBufferOut &= (UART3_TX_BUFFER_SIZE - 1);
+            uart3txBufferFull = false;
+        }
+        else {
+            LPC_UART3->IER = 0x1;
+        }
+    } 
+}
+
+/** Uart3_init
+ */
+void Uart3_init(void) {
+    
+    LPC_SC->PCONP       |=  (1UL << 25);
+    LPC_SC->PCLKSEL1    &= ~(3UL << 18);
+    LPC_SC->PCLKSEL1    |=  (1UL << 18);
+    LPC_PINCON->PINSEL0 &= ~((2UL << 0) | (2UL << 2));
+    LPC_PINCON->PINSEL0 |=  ((2UL << 0) | (2UL << 2));
+    LPC_UART1->LCR       = 0x80;
+    LPC_UART1->DLM       = 0x0;  // 0x00 for 115200 baud, for 9600 use 0x2;
+    LPC_UART1->DLL       = 0x34; // 0x34 for 115200 baud, for 9600 use 0x71;
+    LPC_UART1->LCR       = 0x3;
+    LPC_UART1->FCR       = 0x7;
+    
+    NVIC_SetVector(UART3_IRQn, (uint32_t)UART3_IRQHandler);
+    NVIC_EnableIRQ(UART3_IRQn);
+    
+    /* Enable UART1 RX and TX interrupt. */
+    LPC_UART3->IER = 0x3;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pccomms/pccomms.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,72 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef PCCOMMS_H
+#define PCCOMMS_H
+ 
+#include "sowb.h"
+
+#define PCCOMMS_STATE_WAITING           0
+#define PCCOMMS_BASE_PACKET_READ        1
+#define PCCOMMS_PACKET_READ             2
+#define PCCOMMS_BASE_PACKET_BAD_CSUM    3
+
+#define PCCOMMS_PACKET_ACCEPTED         1
+#define PCCOMMS_PACKET_REJECTED         2
+
+typedef struct _base_packet_bin {
+    uint16_t    mode;
+    uint16_t    length;
+} BASE_PACKET_B;
+
+#define BASE_PACKET_B_LEN   sizeof(BASE_PACKET_B)
+
+typedef struct _base_packet_ascii {
+    char        lead_char;
+    char        mode[4];
+    char        length[4];
+    char        csum;
+    char        flag;
+    char        trail_char;
+} BASE_PACKET_A;
+
+#define BASE_PACKET_A_LEN   sizeof(BASE_PACKET_A)
+
+#define BASE_PACKET_WRAP    if(header_packet_in>=BASE_PACKET_A_LEN)header_packet_in=0
+
+void pccomms_init(void);
+void pccomms_process(void);
+
+void Uart3_init(void);
+void Uart3_putc(char c);
+int Uart3_getc(int block);
+
+void base_packet_a2b(BASE_PACKET_B *b, BASE_PACKET_A *a);
+void base_packet_b2a(BASE_PACKET_A *a, BASE_PACKET_B *b);
+
+/* Buffer sizes MUST be a aligned 2^, for example 8, 16, 32, 64, 128, 256, 512, 1024, etc 
+   Do NOT use any other value or the buffer wrapping firmware won't work. */ 
+#define UART3_TX_BUFFER_SIZE   512
+#define UART3_RX_BUFFER_SIZE   512
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rit/rit.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,155 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "debug.h"
+#include "rit.h"
+#include "gps.h"
+#include "gpio.h"
+
+volatile uint32_t uptimeL;
+volatile uint32_t uptimeH;
+
+/* Declare "timer at zero" callback function prototypes. */
+void _gps_timer_tick_cb(int);
+void _user_wait_ms_cb(int);
+void _nexstar_timeout_callback(int);
+void _nexstar_one_second_timer(int index);
+void _nexstar_100th_timer(int index);
+void _flash_write_timer_callback(int index);
+void _main_test_callback(int index);
+void _sdcard_timer_callback(int index);
+
+/* Define an array of timers that the ISR should handle. */
+volatile RIT_TIMER timers[] = {
+    { 10, 10, _gps_timer_tick_cb            },      /* Index 0 */
+    {  0,  0, _user_wait_ms_cb              },      /* Index 1 */
+    {  0,  0, _nexstar_timeout_callback     },      /* Index 2 */
+    {  0,  0, _nexstar_one_second_timer     },      /* Index 3 */
+    {  0,  0, _nexstar_100th_timer          },      /* Index 4 */
+    {  0,  0, _flash_write_timer_callback   },      /* Index 5 */
+    {  0,  0, _sdcard_timer_callback        },      /* Index 6 */
+    {  0,  0, _main_test_callback           },      /* Index 7 */
+    {  0,  0, NULL                          }       /* Always the last entry. */
+};
+
+/** RIT_IRQHandler
+ *
+ * The ISR for the RIT.
+ */
+extern "C" static void RIT_IRQHandler(void) __irq {
+    if (++uptimeL == 0) uptimeH++;
+    for (int index = 0; timers[index].callback != NULL; index++) {
+        if (timers[index].counter > 0) {
+            timers[index].counter--;
+            if (timers[index].counter == 0) {
+                (timers[index].callback)(index);
+                if (timers[index].reload > 0) {
+                    timers[index].counter = timers[index].reload;
+                }
+            }
+        }
+    }
+    LPC_RIT->RICTRL |= 0x1; /* Dismiss the IRQ. */
+}
+
+/** rit_index_check
+ *
+ * Check that an index exists. Ensures that index into array is valid.
+ *
+ * @param int inex The index to check.
+ * @return int zero on non-existent index, non-zero otherwise.
+ */
+inline static bool rit_index_check(int index) {
+    for (int i = 0; timers[i].callback != NULL; i++) if (i == index) return true;
+    return false;
+}
+
+/** rit_timer_set_counter
+ */
+void rit_timer_set_counter(int index, uint32_t value) {
+    if (rit_index_check(index)) timers[index].counter = value;
+}
+
+/** rit_timer_set_reload
+ */
+void rit_timer_set_reload(int index, uint32_t value) {
+    if (rit_index_check(index)) timers[index].reload = value;
+}
+
+/** rit_timer_get_values
+ *
+ * Get the current counter/reload values of the specified timer.
+ *
+ * If the supplied "index" value is out of range the index value pointed to by
+ * the caller is set to -1 to signify an error has occured (subscript/index out
+ * of range).
+ *
+ * @param int * index A pointer to an int for the index value of the array to return.
+ * @param uint32_t * counter A pointer to variable to place the counter value into.
+ * @param uint32_t * counter A pointer to variable to place the reload value into.
+ */
+void rit_timer_get_values(int *index, uint32_t *counter, uint32_t *reload) {
+    if (rit_index_check(*(index))) {
+        *(counter) = timers[*(index)].counter;
+        *(reload)  = timers[*(index)].reload;
+    }
+    else *(index) = -1;
+}
+
+/** rit_get_uptime
+ */
+void rit_read_uptime(uint32_t *h, uint32_t *l) {
+    *(l) = uptimeL;
+    *(h) = uptimeH;
+}
+
+/** rit_init
+ */
+void rit_init(void) {
+    
+    DEBUG_INIT_START;
+    
+    uptimeL = uptimeH = 0;
+    
+    /* Start by switching power on to the peripheral */
+    LPC_SC->PCONP |= (1UL << 16); 
+    
+    /* The compare value depends on the PCLK frequency.
+       The following are based on a CCLK of 96Mhz to
+       achieve a 1ms timeout value. */
+    switch ((LPC_SC->PCLKSEL1 >> 26) & 0x3) {
+        case 0: LPC_RIT->RICOMPVAL = (96000000L / 4 / 1000); break; /* CCLK / 4 */
+        case 1: LPC_RIT->RICOMPVAL = (96000000L / 1 / 1000); break; /* CCLK / 1 */
+        case 2: LPC_RIT->RICOMPVAL = (96000000L / 2 / 1000); break; /* CCLK / 2 */
+        case 3: LPC_RIT->RICOMPVAL = (96000000L / 8 / 1000); break; /* CCLK / 8 */
+    }
+    
+    /* Set the ISR vector and enable interrupts for the RIT. */
+    NVIC_SetVector(RIT_IRQn, (uint32_t)RIT_IRQHandler);
+    NVIC_EnableIRQ(RIT_IRQn);
+    
+    /* Enable the RIT. */
+    LPC_RIT->RICTRL     = 0x0000000A;
+    
+    DEBUG_INIT_END;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rit/rit.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,49 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef RIT_H
+#define RIT_H
+
+#define RIT_TIMER_CB_GPS    0
+#define RIT_TIMER_CB_WAIT   1
+#define RIT_TIMER_NEXSTAR   2
+#define RIT_ONESEC_NEXSTAR  3
+#define RIT_100TH_NEXSTAR   4
+#define FLASH_WRITE_CB      5
+#define SDCARD_TIMER_CB     6
+#define MAIN_TEST_CB        7
+
+#include "sowb.h"
+
+typedef struct _rit_timer {
+    uint32_t    reload;         /* Value to reload for recurring mode. */
+    uint32_t    counter;        /* The acutal counter that "down counts" to zero. */
+    void      (*callback)(int); /* The function to call when zero is reached. */
+} RIT_TIMER;
+
+void rit_init(void);
+void rit_timer_set_counter(int index, uint32_t value);
+void rit_timer_set_reload(int index, uint32_t value);
+void rit_timer_get_values(int *, uint32_t *, uint32_t *);
+void rit_read_uptime(uint32_t *h, uint32_t *l);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/satapi/mbedfilesys.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,142 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+/* Sadly stung by the Mbed libraries again. The sheer number
+   of interrupts running on SOWB are incomp with the LocalFileSystem
+   library which simply crashes the entire project. 
+   
+   Need to get down to the electonics shop and buy myself some flash
+   and DIY my own solution again. Sigh... */
+   
+#ifdef NEVERCOMPILETHIS
+
+#include "mbed.h"
+#include "mbedfilesys.h"
+#include "user.h"
+#include "utils.h"
+#include "gpio.h"
+#include "debug.h"
+
+LocalFileSystem local("local");
+
+inline void disable_irqs(void) {
+    NVIC_DisableIRQ(EINT3_IRQn);
+    NVIC_DisableIRQ(RIT_IRQn);
+    NVIC_DisableIRQ(UART0_IRQn);
+    NVIC_DisableIRQ(UART1_IRQn);
+    NVIC_DisableIRQ(UART2_IRQn);
+    NVIC_DisableIRQ(USB_IRQn);
+}
+
+inline void enable_irqs(void) {
+    NVIC_EnableIRQ(USB_IRQn);
+    NVIC_EnableIRQ(EINT3_IRQn);
+    NVIC_EnableIRQ(RIT_IRQn);
+    NVIC_EnableIRQ(UART0_IRQn);
+    NVIC_EnableIRQ(UART1_IRQn);
+    NVIC_EnableIRQ(UART2_IRQn);
+}
+
+static int get_tle_from_file(const char *filename, int index, SAT_POS_DATA *sat) {
+    FILE *fp;
+    char *r, line[128];
+    int  line_count = 0, sat_count = 0;
+
+    fp = fopen(filename, "r");
+    if (!fp) {
+        return SOWB_FILE_NOT_FOUND;
+    }
+    else {
+	    while (!feof(fp)) {
+	        LED1_ON;
+            disable_irqs();
+            r = fgets(line, 127, fp);
+            enable_irqs();
+            LED1_OFF;
+	        if(!fgets(line, 127, fp)) {
+	            fclose(fp);
+	            return SOWB_FILE_EOF_REACHED;
+	        }
+	        else {
+		        switch(line_count) {
+		            case 0: strncpy(sat->elements[0], line, 80); break;
+		            case 1: strncpy(sat->elements[1], line, 80); break;
+		            case 2: strncpy(sat->elements[2], line, 80); break;
+		        }
+		        line_count++;
+		        if (line_count == 3) {
+		            if (sat_count == index) {
+		                fclose(fp);
+		                return SOWB_FILE_OK;
+		            }
+		            line_count = 0;
+		            sat_count++;
+		        }
+	        }
+	    }
+    }
+    
+    fclose(fp);
+    return SOWB_FILE_INDEX_NOT_FOUND;   
+}
+
+/* Used to hold the index across first/next calls. */
+int satllite_index;
+
+int get_first_tle_from_file(const char *filename, SAT_POS_DATA *sat) {
+    satllite_index = 0;
+    return get_tle_from_file(filename, satllite_index, sat);
+}
+
+int get_next_tle_from_file(const char *filename, SAT_POS_DATA *sat) {
+    satllite_index++;
+    return get_tle_from_file(filename, satllite_index, sat);
+}
+
+void process_tle(SAT_POS_DATA *sat) {
+    char line[128]; 
+
+    /* Wait until time and location are valid. */
+    do { 
+        observer_now(sat);    
+        user_call_process(); 
+    } 
+    while (!sat->time.is_valid || !sat->location.is_valid);
+
+    debug_printf(" A %d\r\n", sizeof(SAT_POS_DATA));
+    debug_printf(" A %s", sat->elements[0]);
+    debug_printf(" A %s", sat->elements[1]);
+    debug_printf(" A %s", sat->elements[2]);
+    time_AsString(&sat->time, line);
+    debug_printf(" A AT %s\r\n", line);
+    sprintf(line, " A LAT %.4f\r\n", sat->location.latitude);  debug_printf("%s", line);
+    sprintf(line, " A LON %.4f\r\n", sat->location.longitude); debug_printf("%s", line);
+    sprintf(line, " A HEI %.4f\r\n", sat->location.height);    debug_printf("%s", line);
+        
+    sat->tsince = 0;
+    satallite_calculate(sat);
+    debug_stringl(line, sprintf(line, "   Azmith %.1f Elevation %.1f\r\n", sat->azimuth, sat->elevation));
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/satapi/mbedfilesys.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,43 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifdef NEVERCOMPILETHIS
+
+#ifndef MBEDFILESYS_H
+#define MBEDFILESYS_H
+
+#include "satapi.h"
+
+#define SOWB_FILE_OK                1
+#define SOWB_FILE_NOT_FOUND         -1
+#define SOWB_FILE_INDEX_NOT_FOUND   -2
+#define SOWB_FILE_EOF_REACHED       -3
+
+int get_first_tle_from_file(const char *filename, SAT_POS_DATA *sat);
+int get_next_tle_from_file(const char *filename, SAT_POS_DATA *sat);
+
+void process_tle(SAT_POS_DATA *sat);
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/satapi/satapi.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,193 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "user.h"
+#include "satapi.h"
+#include "utils.h"
+#include "debug.h"
+#include "gpio.h"
+#include "osd.h"
+#include "nexstar.h"
+#include "utils.h"
+
+#ifndef M_PI
+#define M_PI 3.1415926535898
+#endif
+
+#define SCAN_INTERVAL 60 
+
+double satapi_aos(SAT_POS_DATA *q, bool goto_aos) {
+    double tsince;
+    char temp1[32], temp2[32];
+        
+    strcpy(q->elements[0], "Lacrosse 2");
+    strcpy(q->elements[1], "1 21147U 91017A   10269.82093092 0.00000020  00000-0  28786-5 0    05");
+    strcpy(q->elements[2], "2 21147  67.9820 220.2995 0002000 244.7811 115.2189 14.76261286    07");
+        
+    observer_now(q);
+    
+    P22_ASSERT;
+       
+    for (q->tsince = 0; q->tsince < (SCAN_INTERVAL * 90); q->tsince += SCAN_INTERVAL) {
+        KICK_WATCHDOG; /* We are busy! */
+        satallite_calculate(q);
+        if (q->elevation >= 10.) {
+            /* Above horizon viewing. Work back to AOS. */
+            for (tsince = q->tsince, q->tsince--; q->elevation > 10. ; tsince = q->tsince--) {
+                satallite_calculate(q);
+                if (q->elevation < 10.) {
+                    //sprintf(temp, "%03f Q AOS El:%.1f AZ:%.1f %dKm\r\n", q->tsince, q->elevation, q->azimuth, (int)q->range);
+                    //debug_printf(temp);
+                    q->tsince = tsince;
+                    satallite_calculate(q);
+                    sprintf(temp1, "%03f T AOS El:%.1f AZ:%.1f %dKm\r\n", q->tsince, q->elevation, q->azimuth, (int)q->range);
+                    debug_printf(temp1);
+                    P22_DEASSERT;
+                    if (goto_aos) {
+                        sprintf(temp1, "%s  T-%.2f", q->elements[0], tsince);                                     
+                        osd_string_xy(1, 12, temp1);                        
+                        sprintf(temp1, "AOS %.2f%c %s%c %dKm", q->elevation, 176, printDouble_3_2(temp2, q->azimuth), 176, (int)q->range);
+                        osd_string_xy(1, 13, temp1);
+                        _nexstar_goto((uint32_t)((q->elevation / 360.) * 65536), (uint32_t)((q->azimuth / 360.) * 65536));
+                    }
+                    return tsince;
+                }
+            }
+        }        
+    }
+           
+    P22_DEASSERT;
+    return 0.;     
+}
+
+int satallite_calculate(SAT_POS_DATA *q) {
+    double tsince;
+
+    /* Ensure the time and place are valid. */
+    if (!q->time.is_valid)      return -1;
+    if (!q->location.is_valid)  return -2;
+        
+    ClearFlag(ALL_FLAGS);
+    
+    Get_Next_Tle_Set(q->elements, &q->tle);
+
+    select_ephemeris(&q->tle);
+    
+    q->jd_utc = gps_julian_date(&q->time);
+    q->jd_epoch = Julian_Date_of_Epoch(q->tle.epoch);
+    
+    tsince = ((q->jd_utc + (q->tsince * (1 / 86400.))) - q->jd_epoch) * xmnpda;
+    
+    if (isFlagSet(DEEP_SPACE_EPHEM_FLAG)) {
+        SDP4(tsince, &q->tle, &q->pos, &q->vel, &q->phase);
+    }
+    else {
+        SGP4(tsince, &q->tle, &q->pos, &q->vel, &q->phase);
+    }
+
+    Convert_Sat_State(&q->pos, &q->vel);
+    SgpMagnitude(&q->vel); // scalar magnitude, not brightness...
+    q->velocity = q->vel.w;
+
+    /* Populate the geodetic_t struct from data supplied. */
+    q->observer.lat   = q->location.latitude  * de2ra;
+    q->observer.lon   = q->location.longitude * de2ra;
+    q->observer.alt   = q->location.height / 1000.;
+    if (q->location.north_south == 'S') q->observer.lat *= -1.;
+    if (q->location.east_west   == 'W') q->observer.lon *= -1.;
+    
+    Calculate_Obs(q->jd_utc, &q->pos, &q->vel, &q->observer, &q->obs_set);
+    Calculate_LatLonAlt(q->jd_utc, &q->pos, &q->sat_geodetic);
+
+    q->azimuth   = Degrees(q->obs_set.x);
+    q->elevation = Degrees(q->obs_set.y);
+    q->range     = q->obs_set.z;
+    q->rangeRate = q->obs_set.w;
+    q->height    = q->sat_geodetic.alt;
+        
+    return 0;
+}
+
+/** observer_now
+ *
+ * Fills the data structure with the observers time and position.
+ * 
+ * @param SAT_POS_DATA * A pointer to the data structure.
+ */
+SAT_POS_DATA * observer_now(SAT_POS_DATA *q) {
+    gps_get_time(&q->time);
+    gps_get_location_average(&q->location);
+    return q;    
+}
+
+AltAz * radec2altaz(double siderealDegrees, GPS_LOCATION_AVERAGE *location, RaDec *radec, AltAz *altaz) {
+    double HA, DEC, LAT, mul, altitude, azimuth;
+    
+    mul = location->north_south == 'S' ? -1.0 : 1.0;
+     
+    /* Convert to radians. */
+    HA = siderealDegrees * (M_PI / 180.0) - (radec->ra * (M_PI / 180));
+    DEC = radec->dec * (M_PI / 180.0);
+    LAT = (location->latitude * mul) * (M_PI / 180.0);
+    
+    altitude = atan2(- sin(HA) * cos(DEC), cos(LAT) * sin(DEC) - sin(LAT) * cos(DEC) * cos(HA));
+    azimuth = asin(sin(LAT) * sin(DEC) + cos(LAT) * cos(DEC) * cos(HA));
+
+    // Convert to degrees and swing azimuth around if needed.
+    altaz->alt = azimuth * 180.0 / M_PI;
+    altaz->azm = altitude * 180.0 / M_PI;
+    if (altaz->azm < 0) altaz->azm += 360.0;
+  
+    return altaz;
+}
+
+RaDec * altaz2radec(double siderealDegrees, GPS_LOCATION_AVERAGE *location, AltAz *altaz, RaDec *radec) {
+    double ALT, AZM, LAT, HA, DEC, mul;
+    
+    mul = location->north_south == 'S' ? -1.0 : 1.0;
+    
+    /* Convert to radians. */
+    LAT = (location->latitude * mul) * (M_PI / 180.0);
+    ALT = altaz->alt * (M_PI / 180.0);
+    AZM = altaz->azm * (M_PI / 180.0);
+    
+    /* Calculate the declination. */
+    DEC = asin( ( sin(ALT) * sin(LAT) ) + ( cos(ALT) * cos(LAT) * cos(AZM) ) );
+    radec->dec = DEC * 180.0 / M_PI;
+    while (radec->dec < 0.0)   radec->dec += 360.0;
+    while (radec->dec > 360.0) radec->dec -= 360.0;
+    
+    /* Calculate the hour angle. */
+    HA = ( acos((sin(ALT) - sin(LAT) * sin(DEC)) / (cos(LAT) * cos(DEC)))) * 180.0 / M_PI;
+    if (sin(AZM) > 0.0) HA = 360.0 - HA;
+    
+    /* Correct the HA for our sidereal time. */    
+    HA = (siderealDegrees / 360.0 * 24.0) - (HA / 15.0);
+    if (HA < 0.0) HA += 24.0;
+    
+    /* Convert the HA into degrees for the return. */
+    radec->ra = HA / 24.0 * 360.0;
+    
+    return radec;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/satapi/satapi.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,96 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef SATAPI_H
+#define SATAPI_H
+
+#include "gps.h"
+#include "sgp4sdp4.h"
+
+#define JD_SECOND   (1. / 86400.)
+#define JD_MINUTE   (JD_SECOND * 60.)
+#define JD_HOUR     (JD_MINUTE * 60.)
+#define JD_DAY      (JD_HOUR   * 24.)
+
+typedef struct _altaz {
+    double  alt;
+    double  azm;
+} AltAz;
+
+typedef struct _radec {
+    double  ra;
+    double  dec;
+} RaDec;
+
+typedef struct _eci {
+    double x;
+    double y;
+    double z;
+    double xdot;
+    double ydot;
+    double zdot;
+    double atTime;
+} Eci;
+
+typedef struct _sat_pos_data {
+
+    /* Inputs. */
+    char                    elements[3][80];
+    GPS_TIME                time;
+    GPS_LOCATION_AVERAGE    location;    
+    
+    /* Semi-intermediates. 
+       Set to zero for JD_UTC - SAT EPOCH.
+       If you want to know the satellite position say 5 seconds 
+       into the furture set this to 5.0  The "real" tsince is
+       calculated by JD_UTC + (tsince * (1 / 86400.)) - JD_SAT_EPOCH */
+    double      tsince;
+    
+    /* Intermediates. */
+    tle_t       tle;        /* Constructed from the elements arrays. */
+    geodetic_t  observer;   /* Derived from input observer's location. */
+    double      jd_epoch;   /* Computed from the TLE epoch time. */
+    double      jd_utc;     /* Computed from the GPS_TIME t */
+    double      phase;
+    vector_t    vel;
+    vector_t    pos;
+    vector_t    obs_set;
+    geodetic_t  sat_geodetic;
+    
+    /* Outputs. */
+    double azimuth;
+    double elevation;
+    double range;
+    double rangeRate;
+    double height;
+    double velocity;
+    
+} SAT_POS_DATA;
+
+double satapi_aos(SAT_POS_DATA *q, bool goto_aos);
+int satallite_calculate(SAT_POS_DATA *q);
+SAT_POS_DATA * observer_now(SAT_POS_DATA *q);
+
+AltAz * radec2altaz(double siderealDegrees, GPS_LOCATION_AVERAGE *location, RaDec *radec, AltAz *altaz);
+RaDec * altaz2radec(double siderealDegrees, GPS_LOCATION_AVERAGE *location, AltAz *altaz, RaDec *radec);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdcard/sdcard.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,126 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "user.h"
+#include "debug.h"
+#include "rit.h"
+#include "gps.h"
+#include "gpio.h"
+#include "ff.h"
+
+FATFS MyFileSystem;
+bool card_detected_A;
+bool card_detected_B;
+bool card_mounted;
+bool card_bad;
+uint32_t sdcard_detect_shift_register;
+
+/** sdcard_is_mounted
+ *
+ * Tell the caller if an SD card is mounted.
+ *
+ * @return bool True if a card is mounted, false otherwise.
+ */
+bool sdcard_is_mounted(void) {
+    return card_mounted;
+}
+
+/** sdcard_init()
+ */
+void sdcard_init(void) {
+    DEBUG_INIT_START;
+    card_bad        = false;
+    card_mounted    = false;
+    card_detected_A = false;
+    card_detected_B = false;
+    sdcard_detect_shift_register = 0;
+    rit_timer_set_counter(SDCARD_TIMER_CB, 10);
+    DEBUG_INIT_END;
+}
+
+/** sdcard_process()
+ */             
+void sdcard_process(void) {
+    int retry;
+    int f_return;
+    DIR root_directory;
+    
+    /* card_detected_A is set by the RIT timer callback below which performs
+       a rough debounce of the switch. So, if here we need to do a rising
+       edge detect so we only flag a card insertion once. */
+    if (card_detected_A && !card_detected_B && !card_mounted && !card_bad) {
+        card_detected_B = true;        
+        debug_printf("Card insertion detected.\r\n");
+        /* Have found that some cards require a "kick" to bring them to
+           life. So we retry 3 times to init the card. If after 3 tries
+           it fails we mark the card as "bad". */
+        for(retry = 0; retry < 3; retry++) {
+            KICK_WATCHDOG;
+            f_return = f_mount(0,&MyFileSystem);
+            if (f_return == FR_OK) {
+                f_return = f_opendir(&root_directory, "/");
+                if (f_return == FR_OK) {
+                    card_mounted = true;
+                    debug_printf("SD card mounted.\r\n");
+                    retry = 3; /* Break loop. */
+                }
+            }    
+        }
+        
+        if (!card_mounted) {
+            card_bad = true;
+            debug_printf("Failed to mount SD Card\r\n");
+        }
+    }
+}
+
+/** _sdcard_timer_callback
+ *
+ * RIT timer callback.
+ * @see rit.c
+ */
+void _sdcard_timer_callback(int index) {
+    
+    /* Shift left 1bit... */
+    sdcard_detect_shift_register = sdcard_detect_shift_register << 1;
+    
+    /* And then mask in bit0 position. */
+    if (SDCARD_DETECT != 0) {  
+        sdcard_detect_shift_register |= 1;
+    }
+
+    /* 16 consecutive 1s mean card detected. Rough debouncing of the
+       mechanical "card detect" switch in the SD card holder. */
+    if ((sdcard_detect_shift_register & 0x0000FFFFUL) == 0x0000FFFFUL) { 
+        card_detected_A = true; 
+    }
+    else {
+        card_bad        = false;
+        card_mounted    = false;
+        card_detected_A = false;
+        card_detected_B = false;
+    }
+    
+    /* Restart timer. */
+    rit_timer_set_counter(SDCARD_TIMER_CB, 10);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdcard/sdcard.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,30 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef SDCARD_H
+#define SDCARD_H
+
+bool sdcard_is_mounted(void);
+void sdcard_init(void);
+void sdcard_process(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sgp4sdp4/sgp4sdp4.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,1077 @@
+/*
+ *  Unit SGP4SDP4
+ *           Author:  Dr TS Kelso 
+ * Original Version:  1991 Oct 30
+ * Current Revision:  1992 Sep 03
+ *          Version:  1.50 
+ *        Copyright:  1991-1992, All Rights Reserved 
+ *
+ *   Ported to C by:  Neoklis Kyriazis  April 10  2001
+ */
+
+#include "sgp4sdp4.h"
+
+/* SGP4 */
+/* This function is used to calculate the position and velocity */
+/* of near-earth (period < 225 minutes) satellites. tsince is   */
+/* time since epoch in minutes, tle is a pointer to a tle_t     */
+/* structure with Keplerian orbital elements and pos and vel    */
+/* are vector_t structures returning ECI satellite position and */
+/* velocity. Use Convert_Sat_State() to convert to km and km/s.*/
+void
+SGP4(double tsince, tle_t *tle, vector_t *pos, vector_t *vel, double* phase)
+{
+  static double
+    aodp,aycof,c1,c4,c5,cosio,d2,d3,d4,delmo,omgcof,
+    eta,omgdot,sinio,xnodp,sinmo,t2cof,t3cof,t4cof,t5cof,
+    x1mth2,x3thm1,x7thm1,xmcof,xmdot,xnodcf,xnodot,xlcof;
+ 
+  double
+    cosuk,sinuk,rfdotk,vx,vy,vz,ux,uy,uz,xmy,xmx,
+    cosnok,sinnok,cosik,sinik,rdotk,xinck,xnodek,uk,
+    rk,cos2u,sin2u,u,sinu,cosu,betal,rfdot,rdot,r,pl,
+    elsq,esine,ecose,epw,cosepw,x1m5th,xhdot1,tfour,
+    sinepw,capu,ayn,xlt,aynl,xll,axn,xn,beta,xl,e,a,
+    tcube,delm,delomg,templ,tempe,tempa,xnode,tsq,xmp,
+    omega,xnoddf,omgadf,xmdf,a1,a3ovk2,ao,betao,betao2,
+    c1sq,c2,c3,coef,coef1,del1,delo,eeta,eosq,etasq,
+    perige,pinvsq,psisq,qoms24,s4,temp,temp1,temp2,
+    temp3,temp4,temp5,temp6,theta2,theta4,tsi;
+
+  int i;  
+
+  /* Initialization */
+  if (isFlagClear(SGP4_INITIALIZED_FLAG))
+    {
+      SetFlag(SGP4_INITIALIZED_FLAG);
+
+      /* Recover original mean motion (xnodp) and   */
+      /* semimajor axis (aodp) from input elements. */
+      a1 = pow(xke/tle->xno,tothrd);
+      cosio = cos(tle->xincl);
+      theta2 = cosio*cosio;
+      x3thm1 = 3*theta2-1.0;
+      eosq = tle->eo*tle->eo;
+      betao2 = 1-eosq;
+      betao = sqrt(betao2);
+      del1 = 1.5*ck2*x3thm1/(a1*a1*betao*betao2);
+      ao = a1*(1-del1*(0.5*tothrd+del1*(1+134/81*del1)));
+      delo = 1.5*ck2*x3thm1/(ao*ao*betao*betao2);
+      xnodp = tle->xno/(1+delo);
+      aodp = ao/(1-delo);
+
+      /* For perigee less than 220 kilometers, the "simple" flag is set */
+      /* and the equations are truncated to linear variation in sqrt a  */
+      /* and quadratic variation in mean anomaly.  Also, the c3 term,   */
+      /* the delta omega term, and the delta m term are dropped.        */
+      if((aodp*(1-tle->eo)/ae) < (220/xkmper+ae))
+    SetFlag(SIMPLE_FLAG);
+      else
+    ClearFlag(SIMPLE_FLAG);
+
+      /* For perigee below 156 km, the       */ 
+      /* values of s and qoms2t are altered. */
+      s4 = __s__;
+      qoms24 = qoms2t;
+      perige = (aodp*(1-tle->eo)-ae)*xkmper;
+      if(perige < 156)
+    {
+             if(perige <= 98)
+        s4 = 20;
+          else
+        s4 = perige-78;
+      qoms24 = pow((120-s4)*ae/xkmper,4);
+      s4 = s4/xkmper+ae;
+    }; /* End of if(perige <= 98) */
+
+      pinvsq = 1/(aodp*aodp*betao2*betao2);
+      tsi = 1/(aodp-s4);
+      eta = aodp*tle->eo*tsi;
+      etasq = eta*eta;
+      eeta = tle->eo*eta;
+      psisq = fabs(1-etasq);
+      coef = qoms24*pow(tsi,4);
+      coef1 = coef/pow(psisq,3.5);
+      c2 = coef1*xnodp*(aodp*(1+1.5*etasq+eeta*(4+etasq))+
+       0.75*ck2*tsi/psisq*x3thm1*(8+3*etasq*(8+etasq)));
+      c1 = tle->bstar*c2;
+      sinio = sin(tle->xincl);
+      a3ovk2 = -xj3/ck2*pow(ae,3);
+      c3 = coef*tsi*a3ovk2*xnodp*ae*sinio/tle->eo;
+      x1mth2 = 1-theta2;
+      c4 = 2*xnodp*coef1*aodp*betao2*(eta*(2+0.5*etasq)+
+       tle->eo*(0.5+2*etasq)-2*ck2*tsi/(aodp*psisq)*
+       (-3*x3thm1*(1-2*eeta+etasq*(1.5-0.5*eeta))+0.75*
+       x1mth2*(2*etasq-eeta*(1+etasq))*cos(2*tle->omegao)));
+      c5 = 2*coef1*aodp*betao2*(1+2.75*(etasq+eeta)+eeta*etasq);
+      theta4 = theta2*theta2;
+      temp1 = 3*ck2*pinvsq*xnodp;
+      temp2 = temp1*ck2*pinvsq;
+      temp3 = 1.25*ck4*pinvsq*pinvsq*xnodp;
+      xmdot = xnodp+0.5*temp1*betao*x3thm1+
+          0.0625*temp2*betao*(13-78*theta2+137*theta4);
+      x1m5th = 1-5*theta2;
+      omgdot = -0.5*temp1*x1m5th+0.0625*temp2*(7-114*theta2+
+           395*theta4)+temp3*(3-36*theta2+49*theta4);
+      xhdot1 = -temp1*cosio;
+      xnodot = xhdot1+(0.5*temp2*(4-19*theta2)+
+           2*temp3*(3-7*theta2))*cosio;
+      omgcof = tle->bstar*c3*cos(tle->omegao);
+      xmcof = -tothrd*coef*tle->bstar*ae/eeta;
+      xnodcf = 3.5*betao2*xhdot1*c1;
+      t2cof = 1.5*c1;
+      xlcof = 0.125*a3ovk2*sinio*(3+5*cosio)/(1+cosio);
+      aycof = 0.25*a3ovk2*sinio;
+      delmo = pow(1+eta*cos(tle->xmo),3);
+      sinmo = sin(tle->xmo);
+      x7thm1 = 7*theta2-1;
+      if (isFlagClear(SIMPLE_FLAG))
+    {
+      c1sq = c1*c1;
+      d2 = 4*aodp*tsi*c1sq;
+      temp = d2*tsi*c1/3;
+      d3 = (17*aodp+s4)*temp;
+      d4 = 0.5*temp*aodp*tsi*(221*aodp+31*s4)*c1;
+      t3cof = d2+2*c1sq;
+      t4cof = 0.25*(3*d3+c1*(12*d2+10*c1sq));
+      t5cof = 0.2*(3*d4+12*c1*d3+6*d2*d2+15*c1sq*(2*d2+c1sq));
+    }; /* End of if (isFlagClear(SIMPLE_FLAG)) */
+    }; /* End of SGP4() initialization */
+
+  /* Update for secular gravity and atmospheric drag. */
+  xmdf = tle->xmo+xmdot*tsince;
+  omgadf = tle->omegao+omgdot*tsince;
+  xnoddf = tle->xnodeo+xnodot*tsince;
+  omega = omgadf;
+  xmp = xmdf;
+  tsq = tsince*tsince;
+  xnode = xnoddf+xnodcf*tsq;
+  tempa = 1-c1*tsince;
+  tempe = tle->bstar*c4*tsince;
+  templ = t2cof*tsq;
+  if (isFlagClear(SIMPLE_FLAG))
+    {
+      delomg = omgcof*tsince;
+      delm = xmcof*(pow(1+eta*cos(xmdf),3)-delmo);
+      temp = delomg+delm;
+      xmp = xmdf+temp;
+      omega = omgadf-temp;
+      tcube = tsq*tsince;
+      tfour = tsince*tcube;
+      tempa = tempa-d2*tsq-d3*tcube-d4*tfour;
+      tempe = tempe+tle->bstar*c5*(sin(xmp)-sinmo);
+      templ = templ+t3cof*tcube+tfour*(t4cof+tsince*t5cof);
+    }; /* End of if (isFlagClear(SIMPLE_FLAG)) */
+
+  a = aodp*pow(tempa,2);
+  e = tle->eo-tempe;
+  xl = xmp+omega+xnode+xnodp*templ;
+  beta = sqrt(1-e*e);
+  xn = xke/pow(a,1.5);
+
+  /* Long period periodics */
+  axn = e*cos(omega);
+  temp = 1/(a*beta*beta);
+  xll = temp*xlcof*axn;
+  aynl = temp*aycof;
+  xlt = xl+xll;
+  ayn = e*sin(omega)+aynl;
+
+  /* Solve Kepler's' Equation */
+  capu = FMod2p(xlt-xnode);
+  temp2 = capu;
+
+  i = 0;
+  do
+    {
+      sinepw = sin(temp2);
+      cosepw = cos(temp2);
+      temp3 = axn*sinepw;
+      temp4 = ayn*cosepw;
+      temp5 = axn*cosepw;
+      temp6 = ayn*sinepw;
+      epw = (capu-temp4+temp3-temp2)/(1-temp5-temp6)+temp2;
+      if(fabs(epw-temp2) <= e6a) break;
+      temp2 = epw;
+    }
+  while( i++ < 10 );
+
+  /* Short period preliminary quantities */
+  ecose = temp5+temp6;
+  esine = temp3-temp4;
+  elsq = axn*axn+ayn*ayn;
+  temp = 1-elsq;
+  pl = a*temp;
+  r = a*(1-ecose);
+  temp1 = 1/r;
+  rdot = xke*sqrt(a)*esine*temp1;
+  rfdot = xke*sqrt(pl)*temp1;
+  temp2 = a*temp1;
+  betal = sqrt(temp);
+  temp3 = 1/(1+betal);
+  cosu = temp2*(cosepw-axn+ayn*esine*temp3);
+  sinu = temp2*(sinepw-ayn-axn*esine*temp3);
+  u = AcTan(sinu, cosu);
+  sin2u = 2*sinu*cosu;
+  cos2u = 2*cosu*cosu-1;
+  temp = 1/pl;
+  temp1 = ck2*temp;
+  temp2 = temp1*temp;
+
+  /* Update for short periodics */
+  rk = r*(1-1.5*temp2*betal*x3thm1)+0.5*temp1*x1mth2*cos2u;
+  uk = u-0.25*temp2*x7thm1*sin2u;
+  xnodek = xnode+1.5*temp2*cosio*sin2u;
+  xinck = tle->xincl+1.5*temp2*cosio*sinio*cos2u;
+  rdotk = rdot-xn*temp1*x1mth2*sin2u;
+  rfdotk = rfdot+xn*temp1*(x1mth2*cos2u+1.5*x3thm1);
+
+  /* Orientation vectors */
+  sinuk = sin(uk);
+  cosuk = cos(uk);
+  sinik = sin(xinck);
+  cosik = cos(xinck);
+  sinnok = sin(xnodek);
+  cosnok = cos(xnodek);
+  xmx = -sinnok*cosik;
+  xmy = cosnok*cosik;
+  ux = xmx*sinuk+cosnok*cosuk;
+  uy = xmy*sinuk+sinnok*cosuk;
+  uz = sinik*sinuk;
+  vx = xmx*cosuk-cosnok*sinuk;
+  vy = xmy*cosuk-sinnok*sinuk;
+  vz = sinik*cosuk;
+
+  /* Position and velocity */
+  pos->x = rk*ux;
+  pos->y = rk*uy;
+  pos->z = rk*uz;
+  vel->x = rdotk*ux+rfdotk*vx;
+  vel->y = rdotk*uy+rfdotk*vy;
+  vel->z = rdotk*uz+rfdotk*vz;
+
+  *phase = xlt-xnode-omgadf+twopi;
+  if(*phase < 0) *phase += twopi;
+  *phase = FMod2p(*phase);
+
+  tle->omegao1=omega;
+  tle->xincl1=xinck;
+  tle->xnodeo1=xnodek;
+
+} /*SGP4*/
+
+/*------------------------------------------------------------------*/
+
+/* SDP4 */
+/* This function is used to calculate the position and velocity */
+/* of deep-space (period > 225 minutes) satellites. tsince is   */
+/* time since epoch in minutes, tle is a pointer to a tle_t     */
+/* structure with Keplerian orbital elements and pos and vel    */
+/* are vector_t structures returning ECI satellite position and */
+/* velocity. Use Convert_Sat_State() to convert to km and km/s. */
+void 
+SDP4(double tsince, tle_t *tle, vector_t *pos, vector_t *vel, double* phase)
+{
+  int i;
+
+  static double
+    x3thm1,c1,x1mth2,c4,xnodcf,t2cof,xlcof,aycof,x7thm1;
+
+  double
+    a,axn,ayn,aynl,beta,betal,capu,cos2u,cosepw,cosik,
+    cosnok,cosu,cosuk,ecose,elsq,epw,esine,pl,theta4,
+    rdot,rdotk,rfdot,rfdotk,rk,sin2u,sinepw,sinik,
+    sinnok,sinu,sinuk,tempe,templ,tsq,u,uk,ux,uy,uz,
+    vx,vy,vz,xinck,xl,xlt,xmam,xmdf,xmx,xmy,xnoddf,
+    xnodek,xll,a1,a3ovk2,ao,c2,coef,coef1,x1m5th,
+    xhdot1,del1,r,delo,eeta,eta,etasq,perige,
+    psisq,tsi,qoms24,s4,pinvsq,temp,tempa,temp1,
+    temp2,temp3,temp4,temp5,temp6;
+
+  static deep_arg_t deep_arg;
+
+  /* Initialization */
+  if (isFlagClear(SDP4_INITIALIZED_FLAG))
+    {
+      SetFlag(SDP4_INITIALIZED_FLAG);
+
+      /* Recover original mean motion (xnodp) and   */
+      /* semimajor axis (aodp) from input elements. */
+      a1 = pow(xke/tle->xno,tothrd);
+      deep_arg.cosio = cos(tle->xincl);
+      deep_arg.theta2 = deep_arg.cosio*deep_arg.cosio;
+      x3thm1 = 3*deep_arg.theta2-1;
+      deep_arg.eosq = tle->eo*tle->eo;
+      deep_arg.betao2 = 1-deep_arg.eosq;
+      deep_arg.betao = sqrt(deep_arg.betao2);
+      del1 = 1.5*ck2*x3thm1/(a1*a1*deep_arg.betao*deep_arg.betao2);
+      ao = a1*(1-del1*(0.5*tothrd+del1*(1+134/81*del1)));
+      delo = 1.5*ck2*x3thm1/(ao*ao*deep_arg.betao*deep_arg.betao2);
+      deep_arg.xnodp = tle->xno/(1+delo);
+      deep_arg.aodp = ao/(1-delo);
+
+      /* For perigee below 156 km, the values */
+      /* of s and qoms2t are altered.         */
+      s4 = __s__;
+      qoms24 = qoms2t;
+      perige = (deep_arg.aodp*(1-tle->eo)-ae)*xkmper;
+      if(perige < 156)
+    {
+             if(perige <= 98)
+        s4 = 20;
+          else
+        s4 = perige-78;
+      qoms24 = pow((120-s4)*ae/xkmper,4);
+      s4 = s4/xkmper+ae;
+    }
+      pinvsq = 1/(deep_arg.aodp*deep_arg.aodp*
+               deep_arg.betao2*deep_arg.betao2);
+      deep_arg.sing = sin(tle->omegao);
+      deep_arg.cosg = cos(tle->omegao);
+      tsi = 1/(deep_arg.aodp-s4);
+      eta = deep_arg.aodp*tle->eo*tsi;
+      etasq = eta*eta;
+      eeta = tle->eo*eta;
+      psisq = fabs(1-etasq);
+      coef = qoms24*pow(tsi,4);
+      coef1 = coef/pow(psisq,3.5);
+      c2 = coef1*deep_arg.xnodp*(deep_arg.aodp*(1+1.5*etasq+eeta*
+       (4+etasq))+0.75*ck2*tsi/psisq*x3thm1*(8+3*etasq*(8+etasq)));
+      c1 = tle->bstar*c2;
+      deep_arg.sinio = sin(tle->xincl);
+      a3ovk2 = -xj3/ck2*pow(ae,3);
+      x1mth2 = 1-deep_arg.theta2;
+      c4 = 2*deep_arg.xnodp*coef1*deep_arg.aodp*deep_arg.betao2*
+           (eta*(2+0.5*etasq)+tle->eo*(0.5+2*etasq)-2*ck2*tsi/
+           (deep_arg.aodp*psisq)*(-3*x3thm1*(1-2*eeta+etasq*
+           (1.5-0.5*eeta))+0.75*x1mth2*(2*etasq-eeta*(1+etasq))*
+           cos(2*tle->omegao)));
+      theta4 = deep_arg.theta2*deep_arg.theta2;
+      temp1 = 3*ck2*pinvsq*deep_arg.xnodp;
+      temp2 = temp1*ck2*pinvsq;
+      temp3 = 1.25*ck4*pinvsq*pinvsq*deep_arg.xnodp;
+      deep_arg.xmdot = deep_arg.xnodp+0.5*temp1*deep_arg.betao*
+                   x3thm1+0.0625*temp2*deep_arg.betao*
+                       (13-78*deep_arg.theta2+137*theta4);
+      x1m5th = 1-5*deep_arg.theta2;
+      deep_arg.omgdot = -0.5*temp1*x1m5th+0.0625*temp2*
+                        (7-114*deep_arg.theta2+395*theta4)+
+                    temp3*(3-36*deep_arg.theta2+49*theta4);
+      xhdot1 = -temp1*deep_arg.cosio;
+      deep_arg.xnodot = xhdot1+(0.5*temp2*(4-19*deep_arg.theta2)+
+                2*temp3*(3-7*deep_arg.theta2))*deep_arg.cosio;
+      xnodcf = 3.5*deep_arg.betao2*xhdot1*c1;
+      t2cof = 1.5*c1;
+      xlcof = 0.125*a3ovk2*deep_arg.sinio*(3+5*deep_arg.cosio)/
+              (1+deep_arg.cosio);
+      aycof = 0.25*a3ovk2*deep_arg.sinio;
+      x7thm1 = 7*deep_arg.theta2-1;
+
+      /* initialize Deep() */
+      Deep(dpinit, tle, &deep_arg);
+    }; /*End of SDP4() initialization */
+
+  /* Update for secular gravity and atmospheric drag */
+  xmdf = tle->xmo+deep_arg.xmdot*tsince;
+  deep_arg.omgadf = tle->omegao+deep_arg.omgdot*tsince;
+  xnoddf = tle->xnodeo+deep_arg.xnodot*tsince;
+  tsq = tsince*tsince;
+  deep_arg.xnode = xnoddf+xnodcf*tsq;
+  tempa = 1-c1*tsince;
+  tempe = tle->bstar*c4*tsince;
+  templ = t2cof*tsq;
+  deep_arg.xn = deep_arg.xnodp;
+
+  /* Update for deep-space secular effects */
+  deep_arg.xll = xmdf;
+  deep_arg.t = tsince;
+
+  Deep(dpsec, tle, &deep_arg);
+
+  xmdf = deep_arg.xll;
+  a = pow(xke/deep_arg.xn,tothrd)*tempa*tempa;
+  deep_arg.em = deep_arg.em-tempe;
+  xmam = xmdf+deep_arg.xnodp*templ;
+
+  /* Update for deep-space periodic effects */
+  deep_arg.xll = xmam;
+
+  Deep(dpper, tle, &deep_arg);
+
+  xmam = deep_arg.xll;
+  xl = xmam+deep_arg.omgadf+deep_arg.xnode;
+  beta = sqrt(1-deep_arg.em*deep_arg.em);
+  deep_arg.xn = xke/pow(a,1.5);
+
+  /* Long period periodics */
+  axn = deep_arg.em*cos(deep_arg.omgadf);
+  temp = 1/(a*beta*beta);
+  xll = temp*xlcof*axn;
+  aynl = temp*aycof;
+  xlt = xl+xll;
+  ayn = deep_arg.em*sin(deep_arg.omgadf)+aynl;
+
+  /* Solve Kepler's Equation */
+  capu = FMod2p(xlt-deep_arg.xnode);
+  temp2 = capu;
+
+  i = 0;
+  do
+    {
+      sinepw = sin(temp2);
+      cosepw = cos(temp2);
+      temp3 = axn*sinepw;
+      temp4 = ayn*cosepw;
+      temp5 = axn*cosepw;
+      temp6 = ayn*sinepw;
+      epw = (capu-temp4+temp3-temp2)/(1-temp5-temp6)+temp2;
+      if(fabs(epw-temp2) <= e6a) break;
+      temp2 = epw;
+    }
+  while( i++ < 10 );
+
+  /* Short period preliminary quantities */
+  ecose = temp5+temp6;
+  esine = temp3-temp4;
+  elsq = axn*axn+ayn*ayn;
+  temp = 1-elsq;
+  pl = a*temp;
+  r = a*(1-ecose);
+  temp1 = 1/r;
+  rdot = xke*sqrt(a)*esine*temp1;
+  rfdot = xke*sqrt(pl)*temp1;
+  temp2 = a*temp1;
+  betal = sqrt(temp);
+  temp3 = 1/(1+betal);
+  cosu = temp2*(cosepw-axn+ayn*esine*temp3);
+  sinu = temp2*(sinepw-ayn-axn*esine*temp3);
+  u = AcTan(sinu,cosu);
+  sin2u = 2*sinu*cosu;
+  cos2u = 2*cosu*cosu-1;
+  temp = 1/pl;
+  temp1 = ck2*temp;
+  temp2 = temp1*temp;
+
+  /* Update for short periodics */
+  rk = r*(1-1.5*temp2*betal*x3thm1)+0.5*temp1*x1mth2*cos2u;
+  uk = u-0.25*temp2*x7thm1*sin2u;
+  xnodek = deep_arg.xnode+1.5*temp2*deep_arg.cosio*sin2u;
+  xinck = deep_arg.xinc+1.5*temp2*deep_arg.cosio*deep_arg.sinio*cos2u;
+  rdotk = rdot-deep_arg.xn*temp1*x1mth2*sin2u;
+  rfdotk = rfdot+deep_arg.xn*temp1*(x1mth2*cos2u+1.5*x3thm1);
+
+  /* Orientation vectors */
+  sinuk = sin(uk);
+  cosuk = cos(uk);
+  sinik = sin(xinck);
+  cosik = cos(xinck);
+  sinnok = sin(xnodek);
+  cosnok = cos(xnodek);
+  xmx = -sinnok*cosik;
+  xmy = cosnok*cosik;
+  ux = xmx*sinuk+cosnok*cosuk;
+  uy = xmy*sinuk+sinnok*cosuk;
+  uz = sinik*sinuk;
+  vx = xmx*cosuk-cosnok*sinuk;
+  vy = xmy*cosuk-sinnok*sinuk;
+  vz = sinik*cosuk;
+
+  /* Position and velocity */
+  pos->x = rk*ux;
+  pos->y = rk*uy;
+  pos->z = rk*uz;
+  vel->x = rdotk*ux+rfdotk*vx;
+  vel->y = rdotk*uy+rfdotk*vy;
+  vel->z = rdotk*uz+rfdotk*vz;
+
+ /* Phase in rads */
+  *phase = xlt-deep_arg.xnode-deep_arg.omgadf+twopi;
+  if(*phase < 0) *phase += twopi;
+  *phase = FMod2p(*phase);
+
+  tle->omegao1=deep_arg.omgadf;
+  tle->xincl1=deep_arg.xinc;
+  tle->xnodeo1=deep_arg.xnode;
+} /* SDP4 */
+
+/*------------------------------------------------------------------*/
+
+/* DEEP */
+/* This function is used by SDP4 to add lunar and solar */
+/* perturbation effects to deep-space orbit objects.    */
+void
+Deep(int ientry, tle_t *tle, deep_arg_t *deep_arg)
+{
+  static double
+    thgr,xnq,xqncl,omegaq,zmol,zmos,savtsn,ee2,e3,xi2,
+    xl2,xl3,xl4,xgh2,xgh3,xgh4,xh2,xh3,sse,ssi,ssg,xi3,
+    se2,si2,sl2,sgh2,sh2,se3,si3,sl3,sgh3,sh3,sl4,sgh4,
+    ssl,ssh,d3210,d3222,d4410,d4422,d5220,d5232,d5421,
+    d5433,del1,del2,del3,fasx2,fasx4,fasx6,xlamo,xfact,
+    xni,atime,stepp,stepn,step2,preep,pl,sghs,xli,
+    d2201,d2211,sghl,sh1,pinc,pe,shs,zsingl,zcosgl,
+    zsinhl,zcoshl,zsinil,zcosil;
+
+  double
+    a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,ainv2,alfdp,aqnv,
+    sgh,sini2,sinis,sinok,sh,si,sil,day,betdp,dalf,
+    bfact,c,cc,cosis,cosok,cosq,ctem,f322,zx,zy,
+    dbet,dls,eoc,eq,f2,f220,f221,f3,f311,f321,xnoh,
+    f330,f441,f442,f522,f523,f542,f543,g200,g201,
+    g211,pgh,ph,s1,s2,s3,s4,s5,s6,s7,se,sel,ses,xls,
+    g300,g310,g322,g410,g422,g520,g521,g532,g533,gam,
+    sinq,sinzf,sis,sl,sll,sls,stem,temp,temp1,x1,x2,
+    x2li,x2omi,x3,x4,x5,x6,x7,x8,xl,xldot,xmao,xnddt,
+    xndot,xno2,xnodce,xnoi,xomi,xpidot,z1,z11,z12,z13,
+    z2,z21,z22,z23,z3,z31,z32,z33,ze,zf,zm,/* zmo, (see below) */zn,
+    zsing,zsinh,zsini,zcosg,zcosh,zcosi,delt=0,ft=0;
+
+  /* Compiler complains defined but not used. I never like to
+     edit other peoples libraries but I also dislike compiler 
+     warnings. AjK, 7th Sep 2010. */
+  double zmo __attribute__((unused));
+  
+  switch(ientry)
+    {
+    case dpinit : /* Entrance for deep space initialization */
+      thgr = ThetaG(tle->epoch, deep_arg);
+      eq = tle->eo;
+      xnq = deep_arg->xnodp;
+      aqnv = 1/deep_arg->aodp;
+      xqncl = tle->xincl;
+      xmao = tle->xmo;
+      xpidot = deep_arg->omgdot+deep_arg->xnodot;
+      sinq = sin(tle->xnodeo);
+      cosq = cos(tle->xnodeo);
+      omegaq = tle->omegao;
+
+      /* Initialize lunar solar terms */
+      day = deep_arg->ds50+18261.5;  /*Days since 1900 Jan 0.5*/
+      if (day != preep)
+    {
+      preep = day;
+      xnodce = 4.5236020-9.2422029E-4*day;
+      stem = sin(xnodce);
+      ctem = cos(xnodce);
+      zcosil = 0.91375164-0.03568096*ctem;
+      zsinil = sqrt(1-zcosil*zcosil);
+      zsinhl = 0.089683511*stem/zsinil;
+      zcoshl = sqrt(1-zsinhl*zsinhl);
+      c = 4.7199672+0.22997150*day;
+      gam = 5.8351514+0.0019443680*day;
+      zmol = FMod2p(c-gam);
+      zx = 0.39785416*stem/zsinil;
+      zy = zcoshl*ctem+0.91744867*zsinhl*stem;
+      zx = AcTan(zx,zy);
+      zx = gam+zx-xnodce;
+      zcosgl = cos(zx);
+      zsingl = sin(zx);
+      zmos = 6.2565837+0.017201977*day;
+      zmos = FMod2p(zmos);
+    } /* End if(day != preep) */
+
+      /* Do solar terms */
+      savtsn = 1E20;
+      zcosg = zcosgs;
+      zsing = zsings;
+      zcosi = zcosis;
+      zsini = zsinis;
+      zcosh = cosq;
+      zsinh = sinq;
+      cc = c1ss;
+      zn = zns;
+      ze = zes;
+      zmo = zmos;
+      xnoi = 1/xnq;
+
+      /* Loop breaks when Solar terms are done a second */
+      /* time, after Lunar terms are initialized        */
+      for(;;) 
+    {
+      /* Solar terms done again after Lunar terms are done */
+      a1 = zcosg*zcosh+zsing*zcosi*zsinh;
+      a3 = -zsing*zcosh+zcosg*zcosi*zsinh;
+      a7 = -zcosg*zsinh+zsing*zcosi*zcosh;
+      a8 = zsing*zsini;
+      a9 = zsing*zsinh+zcosg*zcosi*zcosh;
+      a10 = zcosg*zsini;
+      a2 = deep_arg->cosio*a7+ deep_arg->sinio*a8;
+      a4 = deep_arg->cosio*a9+ deep_arg->sinio*a10;
+      a5 = -deep_arg->sinio*a7+ deep_arg->cosio*a8;
+      a6 = -deep_arg->sinio*a9+ deep_arg->cosio*a10;
+      x1 = a1*deep_arg->cosg+a2*deep_arg->sing;
+      x2 = a3*deep_arg->cosg+a4*deep_arg->sing;
+      x3 = -a1*deep_arg->sing+a2*deep_arg->cosg;
+      x4 = -a3*deep_arg->sing+a4*deep_arg->cosg;
+      x5 = a5*deep_arg->sing;
+      x6 = a6*deep_arg->sing;
+      x7 = a5*deep_arg->cosg;
+      x8 = a6*deep_arg->cosg;
+      z31 = 12*x1*x1-3*x3*x3;
+      z32 = 24*x1*x2-6*x3*x4;
+      z33 = 12*x2*x2-3*x4*x4;
+      z1 = 3*(a1*a1+a2*a2)+z31*deep_arg->eosq;
+      z2 = 6*(a1*a3+a2*a4)+z32*deep_arg->eosq;
+      z3 = 3*(a3*a3+a4*a4)+z33*deep_arg->eosq;
+      z11 = -6*a1*a5+deep_arg->eosq*(-24*x1*x7-6*x3*x5);
+      z12 = -6*(a1*a6+a3*a5)+ deep_arg->eosq*
+                (-24*(x2*x7+x1*x8)-6*(x3*x6+x4*x5));
+      z13 = -6*a3*a6+deep_arg->eosq*(-24*x2*x8-6*x4*x6);
+      z21 = 6*a2*a5+deep_arg->eosq*(24*x1*x5-6*x3*x7);
+      z22 = 6*(a4*a5+a2*a6)+ deep_arg->eosq*
+                (24*(x2*x5+x1*x6)-6*(x4*x7+x3*x8));
+      z23 = 6*a4*a6+deep_arg->eosq*(24*x2*x6-6*x4*x8);
+      z1 = z1+z1+deep_arg->betao2*z31;
+      z2 = z2+z2+deep_arg->betao2*z32;
+      z3 = z3+z3+deep_arg->betao2*z33;
+      s3 = cc*xnoi;
+      s2 = -0.5*s3/deep_arg->betao;
+      s4 = s3*deep_arg->betao;
+      s1 = -15*eq*s4;
+      s5 = x1*x3+x2*x4;
+      s6 = x2*x3+x1*x4;
+      s7 = x2*x4-x1*x3;
+      se = s1*zn*s5;
+      si = s2*zn*(z11+z13);
+      sl = -zn*s3*(z1+z3-14-6*deep_arg->eosq);
+      sgh = s4*zn*(z31+z33-6);
+      sh = -zn*s2*(z21+z23);
+      if (xqncl < 5.2359877E-2) sh = 0;
+      ee2 = 2*s1*s6;
+      e3 = 2*s1*s7;
+      xi2 = 2*s2*z12;
+      xi3 = 2*s2*(z13-z11);
+      xl2 = -2*s3*z2;
+      xl3 = -2*s3*(z3-z1);
+      xl4 = -2*s3*(-21-9*deep_arg->eosq)*ze;
+      xgh2 = 2*s4*z32;
+      xgh3 = 2*s4*(z33-z31);
+      xgh4 = -18*s4*ze;
+      xh2 = -2*s2*z22;
+      xh3 = -2*s2*(z23-z21);
+
+      if(isFlagSet(LUNAR_TERMS_DONE_FLAG)) break;
+
+      /* Do lunar terms */
+      sse = se;
+      ssi = si;
+      ssl = sl;
+      ssh = sh/deep_arg->sinio;
+      ssg = sgh-deep_arg->cosio*ssh;
+      se2 = ee2;
+      si2 = xi2;
+      sl2 = xl2;
+      sgh2 = xgh2;
+      sh2 = xh2;
+      se3 = e3;
+      si3 = xi3;
+      sl3 = xl3;
+      sgh3 = xgh3;
+      sh3 = xh3;
+      sl4 = xl4;
+      sgh4 = xgh4;
+      zcosg = zcosgl;
+      zsing = zsingl;
+      zcosi = zcosil;
+      zsini = zsinil;
+      zcosh = zcoshl*cosq+zsinhl*sinq;
+      zsinh = sinq*zcoshl-cosq*zsinhl;
+      zn = znl;
+      cc = c1l;
+      ze = zel;
+      zmo = zmol;
+      SetFlag(LUNAR_TERMS_DONE_FLAG);
+    } /* End of for(;;) */
+
+      sse = sse+se;
+      ssi = ssi+si;
+      ssl = ssl+sl;
+      ssg = ssg+sgh-deep_arg->cosio/deep_arg->sinio*sh;
+      ssh = ssh+sh/deep_arg->sinio;
+
+      /* Geopotential resonance initialization for 12 hour orbits */
+      ClearFlag(RESONANCE_FLAG);
+      ClearFlag(SYNCHRONOUS_FLAG);
+
+      if( !((xnq < 0.0052359877) && (xnq > 0.0034906585)) )
+    {
+      if( (xnq < 0.00826) || (xnq > 0.00924) ) return;
+      if (eq < 0.5) return;
+      SetFlag(RESONANCE_FLAG);
+      eoc = eq*deep_arg->eosq;
+      g201 = -0.306-(eq-0.64)*0.440;
+      if (eq <= 0.65)
+        {
+          g211 = 3.616-13.247*eq+16.290*deep_arg->eosq;
+          g310 = -19.302+117.390*eq-228.419*
+                      deep_arg->eosq+156.591*eoc;
+          g322 = -18.9068+109.7927*eq-214.6334*
+                     deep_arg->eosq+146.5816*eoc;
+          g410 = -41.122+242.694*eq-471.094*
+                     deep_arg->eosq+313.953*eoc;
+          g422 = -146.407+841.880*eq-1629.014*
+                     deep_arg->eosq+1083.435*eoc;
+          g520 = -532.114+3017.977*eq-5740*
+                     deep_arg->eosq+3708.276*eoc;
+        }
+      else
+        {
+          g211 = -72.099+331.819*eq-508.738*
+                     deep_arg->eosq+266.724*eoc;
+          g310 = -346.844+1582.851*eq-2415.925*
+                     deep_arg->eosq+1246.113*eoc;
+          g322 = -342.585+1554.908*eq-2366.899*
+                     deep_arg->eosq+1215.972*eoc;
+          g410 = -1052.797+4758.686*eq-7193.992*
+                     deep_arg->eosq+3651.957*eoc;
+          g422 = -3581.69+16178.11*eq-24462.77*
+                     deep_arg->eosq+ 12422.52*eoc;
+          if (eq <= 0.715)
+        g520 = 1464.74-4664.75*eq+3763.64*deep_arg->eosq;
+          else
+        g520 = -5149.66+29936.92*eq-54087.36*
+                       deep_arg->eosq+31324.56*eoc;
+        } /* End if (eq <= 0.65) */
+
+      if (eq < 0.7)
+        {
+          g533 = -919.2277+4988.61*eq-9064.77*
+                     deep_arg->eosq+5542.21*eoc;
+          g521 = -822.71072+4568.6173*eq-8491.4146*
+                     deep_arg->eosq+5337.524*eoc;
+          g532 = -853.666+4690.25*eq-8624.77*
+                     deep_arg->eosq+ 5341.4*eoc;
+        }
+      else
+        {
+          g533 = -37995.78+161616.52*eq-229838.2*
+                     deep_arg->eosq+109377.94*eoc;
+          g521 = -51752.104+218913.95*eq-309468.16*
+                     deep_arg->eosq+146349.42*eoc;
+         g532 = -40023.88+170470.89*eq-242699.48*
+                    deep_arg->eosq+115605.82*eoc;
+        } /* End if (eq <= 0.7) */
+
+      sini2 = deep_arg->sinio*deep_arg->sinio;
+      f220 = 0.75*(1+2*deep_arg->cosio+deep_arg->theta2);
+      f221 = 1.5*sini2;
+      f321 = 1.875*deep_arg->sinio*(1-2*\
+                 deep_arg->cosio-3*deep_arg->theta2);
+      f322 = -1.875*deep_arg->sinio*(1+2*
+                 deep_arg->cosio-3*deep_arg->theta2);
+      f441 = 35*sini2*f220;
+      f442 = 39.3750*sini2*sini2;
+      f522 = 9.84375*deep_arg->sinio*(sini2*(1-2*deep_arg->cosio-5*
+         deep_arg->theta2)+0.33333333*(-2+4*deep_arg->cosio+
+         6*deep_arg->theta2));
+      f523 = deep_arg->sinio*(4.92187512*sini2*(-2-4*
+         deep_arg->cosio+10*deep_arg->theta2)+6.56250012
+                 *(1+2*deep_arg->cosio-3*deep_arg->theta2));
+      f542 = 29.53125*deep_arg->sinio*(2-8*
+                 deep_arg->cosio+deep_arg->theta2*
+         (-12+8*deep_arg->cosio+10*deep_arg->theta2));
+      f543 = 29.53125*deep_arg->sinio*(-2-8*deep_arg->cosio+
+         deep_arg->theta2*(12+8*deep_arg->cosio-10*
+                 deep_arg->theta2));
+      xno2 = xnq*xnq;
+      ainv2 = aqnv*aqnv;
+      temp1 = 3*xno2*ainv2;
+      temp = temp1*root22;
+      d2201 = temp*f220*g201;
+      d2211 = temp*f221*g211;
+      temp1 = temp1*aqnv;
+      temp = temp1*root32;
+      d3210 = temp*f321*g310;
+      d3222 = temp*f322*g322;
+      temp1 = temp1*aqnv;
+      temp = 2*temp1*root44;
+      d4410 = temp*f441*g410;
+      d4422 = temp*f442*g422;
+      temp1 = temp1*aqnv;
+      temp = temp1*root52;
+      d5220 = temp*f522*g520;
+      d5232 = temp*f523*g532;
+      temp = 2*temp1*root54;
+      d5421 = temp*f542*g521;
+      d5433 = temp*f543*g533;
+      xlamo = xmao+tle->xnodeo+tle->xnodeo-thgr-thgr;
+      bfact = deep_arg->xmdot+deep_arg->xnodot+
+                  deep_arg->xnodot-thdt-thdt;
+      bfact = bfact+ssl+ssh+ssh;
+    } /* if( !(xnq < 0.0052359877) && (xnq > 0.0034906585) ) */
+      else
+    {
+      SetFlag(RESONANCE_FLAG);
+      SetFlag(SYNCHRONOUS_FLAG);
+      /* Synchronous resonance terms initialization */
+      g200 = 1+deep_arg->eosq*(-2.5+0.8125*deep_arg->eosq);
+      g310 = 1+2*deep_arg->eosq;
+      g300 = 1+deep_arg->eosq*(-6+6.60937*deep_arg->eosq);
+      f220 = 0.75*(1+deep_arg->cosio)*(1+deep_arg->cosio);
+      f311 = 0.9375*deep_arg->sinio*deep_arg->sinio*
+             (1+3*deep_arg->cosio)-0.75*(1+deep_arg->cosio);
+      f330 = 1+deep_arg->cosio;
+      f330 = 1.875*f330*f330*f330;
+      del1 = 3*xnq*xnq*aqnv*aqnv;
+      del2 = 2*del1*f220*g200*q22;
+      del3 = 3*del1*f330*g300*q33*aqnv;
+      del1 = del1*f311*g310*q31*aqnv;
+      fasx2 = 0.13130908;
+      fasx4 = 2.8843198;
+      fasx6 = 0.37448087;
+      xlamo = xmao+tle->xnodeo+tle->omegao-thgr;
+      bfact = deep_arg->xmdot+xpidot-thdt;
+      bfact = bfact+ssl+ssg+ssh;
+    } /* End if( !(xnq < 0.0052359877) && (xnq > 0.0034906585) ) */
+
+      xfact = bfact-xnq;
+
+      /* Initialize integrator */
+      xli = xlamo;
+      xni = xnq;
+      atime = 0;
+      stepp = 720;
+      stepn = -720;
+      step2 = 259200;
+      /* End case dpinit: */
+      return;
+
+    case dpsec: /* Entrance for deep space secular effects */
+      deep_arg->xll = deep_arg->xll+ssl*deep_arg->t;
+      deep_arg->omgadf = deep_arg->omgadf+ssg*deep_arg->t;
+      deep_arg->xnode = deep_arg->xnode+ssh*deep_arg->t;
+      deep_arg->em = tle->eo+sse*deep_arg->t;
+      deep_arg->xinc = tle->xincl+ssi*deep_arg->t;
+      if (deep_arg->xinc < 0)
+    {
+      deep_arg->xinc = -deep_arg->xinc;
+      deep_arg->xnode = deep_arg->xnode + pi;
+      deep_arg->omgadf = deep_arg->omgadf-pi;
+    }
+      if( isFlagClear(RESONANCE_FLAG) ) return;
+
+      do
+    {
+          if( (atime == 0) ||
+         ((deep_arg->t >= 0) && (atime < 0)) || 
+         ((deep_arg->t < 0) && (atime >= 0)) )
+        {
+          /* Epoch restart */
+          if( deep_arg->t >= 0 )
+        delt = stepp;
+          else
+        delt = stepn;
+
+          atime = 0;
+          xni = xnq;
+          xli = xlamo;
+        }
+      else
+        {      
+              if( fabs(deep_arg->t) >= fabs(atime) )
+        {
+          if ( deep_arg->t > 0 )
+            delt = stepp;
+          else
+            delt = stepn;
+        }
+        }
+
+          do 
+        {
+          if ( fabs(deep_arg->t-atime) >= stepp )
+        {
+          SetFlag(DO_LOOP_FLAG);
+          ClearFlag(EPOCH_RESTART_FLAG);
+        }
+          else
+        {
+          ft = deep_arg->t-atime;
+          ClearFlag(DO_LOOP_FLAG);
+        }
+
+          if( fabs(deep_arg->t) < fabs(atime) )
+        {
+          if (deep_arg->t >= 0)
+            delt = stepn;
+          else
+            delt = stepp;
+          SetFlag(DO_LOOP_FLAG | EPOCH_RESTART_FLAG);
+        }
+
+          /* Dot terms calculated */
+              if( isFlagSet(SYNCHRONOUS_FLAG) )
+        {
+          xndot = del1*sin(xli-fasx2)+del2*sin(2*(xli-fasx4))
+                  +del3*sin(3*(xli-fasx6));
+          xnddt = del1*cos(xli-fasx2)+2*del2*cos(2*(xli-fasx4))
+                  +3*del3*cos(3*(xli-fasx6));
+        }
+          else
+        {
+          xomi = omegaq+deep_arg->omgdot*atime;
+          x2omi = xomi+xomi;
+          x2li = xli+xli;
+          xndot = d2201*sin(x2omi+xli-g22)
+                  +d2211*sin(xli-g22)
+                  +d3210*sin(xomi+xli-g32)
+                  +d3222*sin(-xomi+xli-g32)
+                  +d4410*sin(x2omi+x2li-g44)
+                  +d4422*sin(x2li-g44)
+                  +d5220*sin(xomi+xli-g52)
+                  +d5232*sin(-xomi+xli-g52)
+                  +d5421*sin(xomi+x2li-g54)
+                  +d5433*sin(-xomi+x2li-g54);
+          xnddt = d2201*cos(x2omi+xli-g22)
+                  +d2211*cos(xli-g22)
+                  +d3210*cos(xomi+xli-g32)
+                  +d3222*cos(-xomi+xli-g32)
+                  +d5220*cos(xomi+xli-g52)
+                  +d5232*cos(-xomi+xli-g52)
+                  +2*(d4410*cos(x2omi+x2li-g44)
+                  +d4422*cos(x2li-g44)
+                  +d5421*cos(xomi+x2li-g54)
+                  +d5433*cos(-xomi+x2li-g54));
+        } /* End of if (isFlagSet(SYNCHRONOUS_FLAG)) */
+
+          xldot = xni+xfact;
+          xnddt = xnddt*xldot;
+
+          if(isFlagSet(DO_LOOP_FLAG))
+        {
+          xli = xli+xldot*delt+xndot*step2;
+          xni = xni+xndot*delt+xnddt*step2;
+          atime = atime+delt;
+        }
+        }
+      while(isFlagSet(DO_LOOP_FLAG) && isFlagClear(EPOCH_RESTART_FLAG));
+    }
+      while(isFlagSet(DO_LOOP_FLAG) && isFlagSet(EPOCH_RESTART_FLAG));
+
+      deep_arg->xn = xni+xndot*ft+xnddt*ft*ft*0.5;
+      xl = xli+xldot*ft+xndot*ft*ft*0.5;
+      temp = -deep_arg->xnode+thgr+deep_arg->t*thdt;
+
+      if (isFlagClear(SYNCHRONOUS_FLAG))
+    deep_arg->xll = xl+temp+temp;
+      else
+    deep_arg->xll = xl-deep_arg->omgadf+temp;
+
+      return;
+      /*End case dpsec: */
+
+    case dpper: /* Entrance for lunar-solar periodics */
+      sinis = sin(deep_arg->xinc);
+      cosis = cos(deep_arg->xinc);
+      if (fabs(savtsn-deep_arg->t) >= 30)
+    {
+      savtsn = deep_arg->t;
+      zm = zmos+zns*deep_arg->t;
+      zf = zm+2*zes*sin(zm);
+      sinzf = sin(zf);
+      f2 = 0.5*sinzf*sinzf-0.25;
+      f3 = -0.5*sinzf*cos(zf);
+      ses = se2*f2+se3*f3;
+      sis = si2*f2+si3*f3;
+      sls = sl2*f2+sl3*f3+sl4*sinzf;
+      sghs = sgh2*f2+sgh3*f3+sgh4*sinzf;
+      shs = sh2*f2+sh3*f3;
+      zm = zmol+znl*deep_arg->t;
+      zf = zm+2*zel*sin(zm);
+      sinzf = sin(zf);
+      f2 = 0.5*sinzf*sinzf-0.25;
+      f3 = -0.5*sinzf*cos(zf);
+      sel = ee2*f2+e3*f3;
+      sil = xi2*f2+xi3*f3;
+      sll = xl2*f2+xl3*f3+xl4*sinzf;
+      sghl = xgh2*f2+xgh3*f3+xgh4*sinzf;
+      sh1 = xh2*f2+xh3*f3;
+      pe = ses+sel;
+      pinc = sis+sil;
+      pl = sls+sll;
+    }
+
+      pgh = sghs+sghl;
+      ph = shs+sh1;
+      deep_arg->xinc = deep_arg->xinc+pinc;
+      deep_arg->em = deep_arg->em+pe;
+
+      if (xqncl >= 0.2)
+    {
+      /* Apply periodics directly */
+      ph = ph/deep_arg->sinio;
+      pgh = pgh-deep_arg->cosio*ph;
+      deep_arg->omgadf = deep_arg->omgadf+pgh;
+      deep_arg->xnode = deep_arg->xnode+ph;
+      deep_arg->xll = deep_arg->xll+pl;
+    }
+      else
+        {
+      /* Apply periodics with Lyddane modification */
+      sinok = sin(deep_arg->xnode);
+      cosok = cos(deep_arg->xnode);
+      alfdp = sinis*sinok;
+      betdp = sinis*cosok;
+      dalf = ph*cosok+pinc*cosis*sinok;
+      dbet = -ph*sinok+pinc*cosis*cosok;
+      alfdp = alfdp+dalf;
+      betdp = betdp+dbet;
+      deep_arg->xnode = FMod2p(deep_arg->xnode);
+      xls = deep_arg->xll+deep_arg->omgadf+cosis*deep_arg->xnode;
+      dls = pl+pgh-pinc*deep_arg->xnode*sinis;
+      xls = xls+dls;
+      xnoh = deep_arg->xnode;
+      deep_arg->xnode = AcTan(alfdp,betdp);
+
+          /* This is a patch to Lyddane modification */
+          /* suggested by Rob Matson. */
+      if(fabs(xnoh-deep_arg->xnode) > pi)
+        {
+          if(deep_arg->xnode < xnoh)
+        deep_arg->xnode +=twopi;
+          else
+        deep_arg->xnode -=twopi;
+        }
+
+      deep_arg->xll = deep_arg->xll+pl;
+      deep_arg->omgadf = xls-deep_arg->xll-cos(deep_arg->xinc)*
+                             deep_arg->xnode;
+    } /* End case dpper: */
+      return;
+
+    } /* End switch(ientry) */
+
+} /* End of Deep() */
+
+/*------------------------------------------------------------------*/
+
+/* Functions for testing and setting/clearing flags */
+
+/* An int variable holding the single-bit flags */
+static int Flags = 0;
+
+int
+isFlagSet(int flag)
+{
+  return (Flags & flag);
+}
+
+int
+isFlagClear(int flag)
+{
+  return (~Flags & flag);
+}
+
+void
+SetFlag(int flag)
+{
+  Flags |= flag;
+}
+
+void
+ClearFlag(int flag)
+{
+  Flags &= ~flag;
+}
+
+/*------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sgp4sdp4/sgp4sdp4.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,237 @@
+/*
+ *  kelso.h     April 9 2001
+ *
+ *  Header file for kelso
+ */
+
+#ifndef KELSO_H
+#define KELSO_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+/* #include <unistd.h> */
+
+/* from David Kaelbling <drk@sgi.com> */
+#define select duplicate_select
+//#include <unistd.h>
+#undef select
+
+
+
+/** Type definitions **/
+
+/* Two-line-element satellite orbital data */
+typedef struct
+{
+  double
+    epoch, xndt2o, xndd6o, bstar, 
+    xincl, xnodeo, eo, omegao, xmo, xno;
+  int
+    catnr,  /* Catalogue Number  */
+    elset,  /* Element Set       */
+    revnum; /* Revolution Number */
+  char
+    sat_name[25], /* Satellite name string    */
+    idesg[9];     /* International Designator */
+  /* values needed for squint calculations */
+  double xincl1, xnodeo1, omegao1;
+} tle_t; 
+
+
+/* Geodetic position structure */
+typedef struct
+{
+  double
+  lat, lon, alt, theta;
+} geodetic_t;
+
+/* General three-dimensional vector structure */
+typedef struct
+{
+  double
+  x, y, z, w;
+} vector_t;
+
+/* Common arguments between deep-space functions */
+typedef struct
+{
+  /* Used by dpinit part of Deep() */
+  double
+    eosq,sinio,cosio,betao,aodp,theta2,sing,cosg,
+    betao2,xmdot,omgdot,xnodot,xnodp;
+  /* Used by dpsec and dpper parts of Deep() */
+  double
+    xll,omgadf,xnode,em,xinc,xn,t;
+  /* Used by thetg and Deep() */
+  double
+    ds50;
+} deep_arg_t;
+
+/** Table of constant values **/
+#define de2ra    1.74532925E-2   /* Degrees to Radians */
+#define pi       3.1415926535898 /* Pi */
+#define pio2     1.5707963267949 /* Pi/2 */
+#define x3pio2   4.71238898      /* 3*Pi/2 */
+#define twopi    6.2831853071796 /* 2*Pi  */
+#define e6a      1.0E-6
+#define tothrd   6.6666667E-1    /* 2/3 */
+#define xj2      1.0826158E-3    /* J2 Harmonic */
+#define xj3     -2.53881E-6      /* J3 Harmonic */   
+#define xj4     -1.65597E-6      /* J4 Harmonic */
+#define xke      7.43669161E-2
+#define xkmper   6.378135E3      /* Earth radius km */
+#define xmnpda   1.44E3          /* Minutes per day */
+#define ae       1.0
+#define ck2      5.413079E-4
+#define ck4      6.209887E-7
+#define __f      3.352779E-3
+#define ge       3.986008E5 
+#define __s__    1.012229
+#define qoms2t   1.880279E-09
+#define secday   8.6400E4        /* Seconds per day */
+#define omega_E  1.0027379
+#define omega_ER 6.3003879
+#define zns      1.19459E-5
+#define c1ss     2.9864797E-6
+#define zes      1.675E-2
+#define znl      1.5835218E-4
+#define c1l      4.7968065E-7
+#define zel      5.490E-2
+#define zcosis   9.1744867E-1
+#define zsinis   3.9785416E-1
+#define zsings  -9.8088458E-1
+#define zcosgs   1.945905E-1
+#define zcoshs   1
+#define zsinhs   0
+#define q22      1.7891679E-6
+#define q31      2.1460748E-6
+#define q33      2.2123015E-7
+#define g22      5.7686396
+#define g32      9.5240898E-1
+#define g44      1.8014998
+#define g52      1.0508330
+#define g54      4.4108898
+#define root22   1.7891679E-6
+#define root32   3.7393792E-7
+#define root44   7.3636953E-9
+#define root52   1.1428639E-7
+#define root54   2.1765803E-9
+#define thdt     4.3752691E-3
+#define rho      1.5696615E-1
+#define mfactor  7.292115E-5
+#define __sr__       6.96000E5      /*Solar radius - kilometers (IAU 76)*/
+#define SGPAU       1.49597870E8   /*Astronomical unit - kilometers (IAU 76)*/
+
+/* Entry points of Deep() */
+#define dpinit   1 /* Deep-space initialization code */
+#define dpsec    2 /* Deep-space secular code        */
+#define dpper    3 /* Deep-space periodic code       */
+
+/* Carriage return and line feed */
+#define CR  0x0A
+#define LF  0x0D
+
+/* Flow control flag definitions */
+#define ALL_FLAGS              -1
+#define  SGP_INITIALIZED_FLAG  0x000001
+#define SGP4_INITIALIZED_FLAG  0x000002
+#define SDP4_INITIALIZED_FLAG  0x000004
+#define SGP8_INITIALIZED_FLAG  0x000008
+#define SDP8_INITIALIZED_FLAG  0x000010
+#define SIMPLE_FLAG            0x000020
+#define DEEP_SPACE_EPHEM_FLAG  0x000040
+#define LUNAR_TERMS_DONE_FLAG  0x000080
+#define NEW_EPHEMERIS_FLAG     0x000100
+#define DO_LOOP_FLAG           0x000200
+#define RESONANCE_FLAG         0x000400
+#define SYNCHRONOUS_FLAG       0x000800
+#define EPOCH_RESTART_FLAG     0x001000
+#define VISIBLE_FLAG           0x002000
+#define SAT_ECLIPSED_FLAG      0x004000
+
+
+/** Funtion prototypes **/
+
+/* main.c */
+/* int     main(void); */
+/* sgp4sdp4.c */
+void    SGP4(double tsince, tle_t *tle, vector_t *pos, vector_t *vel, double* phase);
+void    SDP4(double tsince, tle_t *tle, vector_t *pos, vector_t *vel, double* phase);
+void    Deep(int ientry, tle_t *tle, deep_arg_t *deep_arg);
+int     isFlagSet(int flag);
+int     isFlagClear(int flag);
+void    SetFlag(int flag);
+void    ClearFlag(int flag);
+/* sgp_in.c */
+int     Checksum_Good(char *tle_set);
+int     Good_Elements(char *tle_set);
+void    Convert_Satellite_Data(char *tle_set, tle_t *tle);
+int     Get_Next_Tle_Set( char lines[3][80], tle_t *tle );
+void    select_ephemeris(tle_t *tle);
+/* sgp_math.c */
+int     Sign(double arg);
+double  Sqr(double arg);
+double  Cube(double arg);
+double  Radians(double arg);
+double  Degrees(double arg);
+double  ArcSin(double arg);
+double  ArcCos(double arg);
+void    SgpMagnitude(vector_t *v);
+void    Vec_Add(vector_t *v1, vector_t *v2, vector_t *v3);
+void    Vec_Sub(vector_t *v1, vector_t *v2, vector_t *v3);
+void    Scalar_Multiply(double k, vector_t *v1, vector_t *v2);
+void    Scale_Vector(double k, vector_t *v);
+double  Dot(vector_t *v1, vector_t *v2);
+double  Angle(vector_t *v1, vector_t *v2);
+void    Cross(vector_t *v1, vector_t *v2, vector_t *v3);
+void    Normalize(vector_t *v);
+double  AcTan(double sinx, double cosx);
+double  FMod2p(double x);
+double  Modulus(double arg1, double arg2);
+double  Frac(double arg);
+int     Round(double arg);
+double  Int(double arg);
+void    Convert_Sat_State(vector_t *pos, vector_t *vel);
+/* sgp_obs.c */
+void    Calculate_User_PosVel(double _time, geodetic_t *geodetic,
+                              vector_t *obs_pos, vector_t *obs_vel);
+void    Calculate_LatLonAlt(double _time, vector_t *pos, geodetic_t *geodetic);
+void    Calculate_Obs(double _time, vector_t *pos, vector_t *vel,
+                      geodetic_t *geodetic, vector_t *obs_set);
+void    Calculate_RADec(double _time, vector_t *pos, vector_t *vel,
+                        geodetic_t *geodetic, vector_t *obs_set);
+/* sgp_time.c */
+double  Julian_Date_of_Epoch(double epoch);
+double  Epoch_Time(double jd);
+int     DOY(int yr, int mo, int dy);
+double  Fraction_of_Day(int hr, int mi, int se);
+void    Calendar_Date(double jd, struct tm *cdate);
+void    Time_of_Day(double jd, struct tm *cdate);
+double  Julian_Date(struct tm *cdate);
+void    Date_Time(double jd, struct tm *cdate);
+int     Check_Date(struct tm *cdate);
+struct tm Time_to_UTC(struct tm *cdate);
+struct tm Time_from_UTC(struct tm *cdate);
+double  JD_to_UTC(double jt);
+double  JD_from_UTC(double jt);
+double  Delta_ET(double year);
+double  Julian_Date_of_Year(double year);
+double  ThetaG(double epoch, deep_arg_t *deep_arg);
+double  ThetaG_JD(double jd);
+void    UTC_Calendar_Now(struct tm *cdate);
+/* solar.c */
+void    Calculate_Solar_Position(double _time, vector_t *solar_vector);
+int     Sat_Eclipsed(vector_t *pos, vector_t *sol, double *depth);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sgp4sdp4/sgp_in.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,251 @@
+/* Unit SGP_In */
+/*           Author:  Dr TS Kelso */
+/* Original Version:  1992 Jun 25 */
+/* Current Revision:  1999 Nov 27 */
+/*          Version:  2.10 */
+/*        Copyright:  1992-1999, All Rights Reserved */
+
+/* Ported to C by N. Kyriazis  April 6  2001 */
+
+#include "sgp4sdp4.h"
+
+/* Calculates the checksum mod 10 of a line from a TLE set and */
+/* returns 1 if it compares with checksum in column 68, else 0.*/
+/* tle_set is a character string holding the two lines read    */
+/* from a text file containing NASA format Keplerian elements. */
+int
+Checksum_Good( char *tle_set )
+{
+  int i, check_digit, value, checksum = 0;
+
+  for(i = 0; i < 68; i++)
+    {
+      if( (tle_set[i] >= '0') && (tle_set[i] <= '9') )
+    value = tle_set[i] - '0';
+      else if( tle_set[i] == '-' )
+    value = 1;
+      else
+    value = 0;
+
+      checksum += value;
+    } /* End for(i = 0; i < 68; i++) */
+
+  checksum %= 10;
+  check_digit = tle_set[68] - '0';
+
+  return( checksum == check_digit );
+} /* Function Checksums_Good */
+
+/*------------------------------------------------------------------*/
+
+/* Carries out various checks on a TLE set to verify its validity */
+/* tle_set is a character string holding the two lines read    */
+/* from a text file containing NASA format Keplerian elements. */
+int
+Good_Elements( char *tle_set )
+{
+  /* Verify checksum of both lines of a TLE set */
+  if( !Checksum_Good(&tle_set[0]) || !Checksum_Good(&tle_set[69]) )
+    return (0);
+  /* Check the line number of each line */
+  if( (tle_set[0] != '1') || (tle_set[69] != '2') )
+    return (0);
+  /* Verify that Satellite Number is same in both lines */
+  if( strncmp( &tle_set[2], &tle_set[71], 5 ) != 0 )
+    return (0);
+  /* Check that various elements are in the right place */
+  if( 
+     (tle_set[ 23] != '.') ||
+     (tle_set[ 34] != '.') ||
+     (tle_set[ 80] != '.') ||
+     (tle_set[ 89] != '.') ||
+     (tle_set[106] != '.') ||
+     (tle_set[115] != '.') ||
+     (tle_set[123] != '.') ||
+     (strncmp(&tle_set[61], " 0 ", 3) != 0)
+     )
+    return (0);
+
+  return(1);
+}  /* Function Good_Elements */
+
+/*------------------------------------------------------------------*/
+
+/* Converts the strings in a raw two-line element set  */
+/* to their intended numerical values. No processing   */
+/* of these values is done, e.g. from deg to rads etc. */
+/* This is done in the select_ephemeris() function.    */
+void
+Convert_Satellite_Data( char *tle_set, tle_t *tle )
+{ 
+  char buff[15];
+
+  /** Decode Card 1 **/
+  /* Satellite's catalogue number */
+  strncpy( buff, &tle_set[2],5 );
+  buff[5] = '\0';
+  tle->catnr = atoi(buff);
+
+  /* International Designator for satellite */
+  strncpy( tle->idesg, &tle_set[9],8 );
+  tle->idesg[8] = '\0';
+
+  /* Satellite's epoch */
+  strncpy( buff, &tle_set[18],14 );
+  buff[14] = '\0';
+  tle->epoch = atof(buff);
+
+  /* Satellite's First Time Derivative */
+  strncpy( buff, &tle_set[33],10 );
+  buff[10]='\0';
+  tle->xndt2o = atof(buff);
+
+  /* Satellite's Second Time Derivative */
+  strncpy( buff, &tle_set[44],1 );
+  buff[1] = '.';
+  strncpy( &buff[2], &tle_set[45],5 );
+  buff[7] = 'E';
+  strncpy( &buff[8], &tle_set[50],2 );
+  buff[10]='\0';
+  tle->xndd6o = atof(buff);
+
+  /* Satellite's bstar drag term */
+  strncpy( buff, &tle_set[53],1 );
+  buff[1] = '.';
+  strncpy( &buff[2], &tle_set[54],5 );
+  buff[7] = 'E';
+  strncpy( &buff[8], &tle_set[59],2 );
+  buff[10]='\0';
+  tle->bstar = atof(buff);
+
+  /* Element Number */
+  strncpy( buff, &tle_set[64],4 );
+  buff[4]='\0';
+  tle->elset = atoi(buff);
+
+  /** Decode Card 2 **/
+  /* Satellite's Orbital Inclination (degrees) */
+  strncpy( buff, &tle_set[77], 8 );
+  buff[8]='\0';
+  tle->xincl = atof(buff);
+
+  /* Satellite's RAAN (degrees) */
+  strncpy( buff, &tle_set[86], 8 );
+  buff[8]='\0';
+  tle->xnodeo = atof(buff);
+
+  /* Satellite's Orbital Eccentricity */
+  buff[0] = '.';
+  strncpy( &buff[1], &tle_set[95], 7 );
+  buff[8]='\0';
+  tle->eo = atof(buff);
+
+  /* Satellite's Argument of Perigee (degrees) */
+  strncpy( buff, &tle_set[103], 8 );
+  buff[8]='\0';
+  tle->omegao = atof(buff);
+
+  /* Satellite's Mean Anomaly of Orbit (degrees) */
+  strncpy( buff, &tle_set[112], 8 );
+  buff[8]='\0';
+  tle->xmo = atof(buff);
+
+  /* Satellite's Mean Motion (rev/day) */
+  strncpy( buff, &tle_set[121], 10 );
+  buff[10]='\0';
+  tle->xno = atof(buff);
+
+  /* Satellite's Revolution number at epoch */
+  strncpy( buff, &tle_set[132], 5 );
+  buff[5]='\0';
+  tle->revnum = atof(buff);
+
+} /* Procedure Convert_Satellite_Data */
+
+/*------------------------------------------------------------------*/
+
+int
+Get_Next_Tle_Set( char line[3][80], tle_t *tle)
+{
+  int idx,  /* Index for loops and arrays    */
+      chr;  /* Used for inputting characters */
+
+  char tle_set[139]; /* Two lines of a TLE set */
+
+  /* Read the satellite's name */
+  for (idx = 0 ; idx < 25; idx++)
+  {
+      if( ((chr = line[0][idx]) != CR) && (chr != LF) && (chr != '\0'))
+      tle->sat_name[idx] = chr;
+      else
+      {
+      /* strip off trailing spaces */
+      while ((chr = line[0][--idx]) == ' ');
+      tle->sat_name[++idx] = '\0';
+        break;
+      }
+  }
+
+  /* Read in first line of TLE set */
+  strncpy(tle_set, line[1], 70);
+  
+  /* Read in second line of TLE set and terminate string */
+  strncpy(&tle_set[69], line[2], 70);
+  tle_set[138]='\0';
+  
+  /* Check TLE set and abort if not valid */
+  if( !Good_Elements(tle_set) )
+    return(-2);
+
+  /* Convert the TLE set to orbital elements */
+  Convert_Satellite_Data( tle_set, tle );
+
+  return(1);
+}
+
+/*------------------------------------------------------------------*/
+
+/* Selects the apropriate ephemeris type to be used */
+/* for predictions according to the data in the TLE */
+/* It also processes values in the tle set so that  */
+/* they are apropriate for the sgp4/sdp4 routines   */
+void
+select_ephemeris(tle_t *tle)
+{
+  double ao,xnodp,dd1,dd2,delo,temp,a1,del1,r1;
+
+  /* Preprocess tle set */
+  tle->xnodeo *= de2ra;
+  tle-> omegao *= de2ra;
+  tle->xmo *= de2ra;
+  tle->xincl *= de2ra;
+  temp = twopi/xmnpda/xmnpda;
+  tle->xno = tle->xno*temp*xmnpda;
+  tle->xndt2o *= temp;
+  tle->xndd6o = tle->xndd6o*temp/xmnpda;
+  tle->bstar /= ae;
+
+  /* Period > 225 minutes is deep space */
+  dd1 = (xke/tle->xno);
+  dd2 = tothrd;
+  a1 = pow(dd1, dd2);
+  r1 = cos(tle->xincl);
+  dd1 = (1.0-tle->eo*tle->eo);
+  temp = ck2*1.5f*(r1*r1*3.0-1.0)/pow(dd1, 1.5);
+  del1 = temp/(a1*a1);
+  ao = a1*(1.0-del1*(tothrd*.5+del1*
+             (del1*1.654320987654321+1.0)));
+  delo = temp/(ao*ao);
+  xnodp = tle->xno/(delo+1.0);
+
+  /* Select a deep-space/near-earth ephemeris */
+  if (twopi/xnodp/xmnpda >= .15625)
+    SetFlag(DEEP_SPACE_EPHEM_FLAG);
+  else
+    ClearFlag(DEEP_SPACE_EPHEM_FLAG);
+
+  return;
+} /* End of select_ephemeris() */
+
+/*------------------------------------------------------------------*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sgp4sdp4/sgp_math.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,286 @@
+/*
+ * Unit SGP_Math
+ *       Author:  Dr TS Kelso
+ * Original Version:  1991 Oct 30
+ * Current Revision:  1998 Mar 17
+ *          Version:  3.00
+ *        Copyright:  1991-1998, All Rights Reserved
+ *
+ *   ported to C by:  Neoklis Kyriazis  April 9 2001
+ */
+
+#include "sgp4sdp4.h"
+
+/* Returns sign of a double */
+int
+Sign(double arg)
+{
+  if( arg > 0 )
+    return( 1 );
+  else if( arg < 0 )
+    return( -1 );
+  else
+    return( 0 );
+} /* Function Sign*/
+
+/*------------------------------------------------------------------*/
+
+/* Returns square of a double */
+double
+Sqr(double arg)
+{
+  return( arg*arg );
+} /* Function Sqr */
+
+/*------------------------------------------------------------------*/
+
+/* Returns cube of a double */
+double
+Cube(double arg)
+{
+  return( arg*arg*arg );
+} /*Function Cube*/
+
+/*------------------------------------------------------------------*/
+
+/* Returns angle in radians from arg id degrees */
+double
+Radians(double arg)
+{
+  return( arg*de2ra );
+} /*Function Radians*/
+
+/*------------------------------------------------------------------*/
+
+/* Returns angle in degrees from arg in rads */
+double
+Degrees(double arg)
+{
+  return( arg/de2ra );
+} /*Function Degrees*/
+
+/*------------------------------------------------------------------*/
+
+/* Returns the arcsine of the argument */
+double
+ArcSin(double arg)
+{
+  if( fabs(arg) >= 1 )
+    return( Sign(arg)*pio2 );
+  else
+    return( atan(arg/sqrt(1-arg*arg)) );
+} /*Function ArcSin*/
+
+/*------------------------------------------------------------------*/
+
+/* Returns orccosine of rgument */
+double
+ArcCos(double arg)
+{
+  return( pio2 - ArcSin(arg) );
+} /*Function ArcCos*/
+
+/*------------------------------------------------------------------*/
+
+/* Calculates scalar magnitude of a vector_t argument */
+void
+SgpMagnitude(vector_t *v)
+{
+  v->w = sqrt(Sqr(v->x) + Sqr(v->y) + Sqr(v->z));
+} /*Procedure SgpMagnitude*/
+
+/*------------------------------------------------------------------*/
+
+/* Adds vectors v1 and v2 together to produce v3 */
+void
+Vec_Add(vector_t *v1, vector_t *v2, vector_t *v3)
+{
+  v3->x = v1->x + v2->x;
+  v3->y = v1->y + v2->y;
+  v3->z = v1->z + v2->z;
+
+  SgpMagnitude(v3);
+} /*Procedure Vec_Add*/
+
+/*------------------------------------------------------------------*/
+
+/* Subtracts vector v2 from v1 to produce v3 */
+void
+Vec_Sub(vector_t *v1, vector_t *v2, vector_t *v3)
+{
+  v3->x = v1->x - v2->x;
+  v3->y = v1->y - v2->y;
+  v3->z = v1->z - v2->z;
+
+  SgpMagnitude(v3);
+} /*Procedure Vec_Sub*/
+
+/*------------------------------------------------------------------*/
+
+/* Multiplies the vector v1 by the scalar k to produce the vector v2 */
+void
+Scalar_Multiply(double k, vector_t *v1, vector_t *v2)
+{
+  v2->x = k * v1->x;
+  v2->y = k * v1->y;
+  v2->z = k * v1->z;
+  v2->w = fabs(k) * v1->w;
+} /*Procedure Scalar_Multiply*/
+
+/*------------------------------------------------------------------*/
+
+/* Multiplies the vector v1 by the scalar k */
+void
+Scale_Vector(double k, vector_t *v)
+{ 
+  v->x *= k;
+  v->y *= k;
+  v->z *= k;
+  SgpMagnitude(v);
+} /* Procedure Scale_Vector */
+
+/*------------------------------------------------------------------*/
+
+/* Returns the dot product of two vectors */
+double
+Dot(vector_t *v1, vector_t *v2)
+{
+  return( v1->x*v2->x + v1->y*v2->y + v1->z*v2->z );
+}  /*Function Dot*/
+
+/*------------------------------------------------------------------*/
+
+/* Calculates the angle between vectors v1 and v2 */
+double
+Angle(vector_t *v1, vector_t *v2)
+{
+  SgpMagnitude(v1);
+  SgpMagnitude(v2);
+  return( ArcCos(Dot(v1,v2)/(v1->w*v2->w)) );
+} /*Function Angle*/
+
+/*------------------------------------------------------------------*/
+
+/* Produces cross product of v1 and v2, and returns in v3 */
+void
+Cross(vector_t *v1, vector_t *v2 ,vector_t *v3)
+{
+  v3->x = v1->y*v2->z - v1->z*v2->y;
+  v3->y = v1->z*v2->x - v1->x*v2->z;
+  v3->z = v1->x*v2->y - v1->y*v2->x;
+  SgpMagnitude(v3);
+} /*Procedure Cross*/
+
+/*------------------------------------------------------------------*/
+
+/* Normalizes a vector */
+void
+Normalize( vector_t *v )
+{
+  v->x /= v->w;
+  v->y /= v->w;
+  v->z /= v->w;
+} /*Procedure Normalize*/
+
+/*------------------------------------------------------------------*/
+
+/* Four-quadrant arctan function */
+double
+AcTan(double sinx, double cosx)
+{
+  if(cosx == 0)
+    {
+      if(sinx > 0)
+    return (pio2);
+      else
+    return (x3pio2);
+    }
+  else
+    {
+      if(cosx > 0)
+    {
+      if(sinx > 0)
+        return ( atan(sinx/cosx) );
+      else
+        return ( twopi + atan(sinx/cosx) );
+    }
+      else
+    return ( pi + atan(sinx/cosx) );
+    }
+
+} /* Function AcTan */
+
+/*------------------------------------------------------------------*/
+
+/* Returns mod 2pi of argument */
+double
+FMod2p(double x)
+{
+  int i;
+  double ret_val;
+
+  ret_val = x;
+  i = ret_val/twopi;
+  ret_val -= i*twopi;
+  if (ret_val < 0) ret_val += twopi;
+
+  return (ret_val);
+} /* fmod2p */
+
+/*------------------------------------------------------------------*/
+
+/* Returns arg1 mod arg2 */
+double
+Modulus(double arg1, double arg2)
+{
+  int i;
+  double ret_val;
+
+  ret_val = arg1;
+  i = ret_val/arg2;
+  ret_val -= i*arg2;
+  if (ret_val < 0) ret_val += arg2;
+
+  return (ret_val);
+} /* modulus */
+
+/*------------------------------------------------------------------*/
+
+/* Returns fractional part of double argument */
+double
+Frac( double arg )
+{
+  return( arg - floor(arg) );
+} /* Frac */
+
+/*------------------------------------------------------------------*/
+
+/* Returns argument rounded up to nearest integer */
+int
+Round( double arg )
+{
+  return( (int) floor(arg + 0.5) );
+} /* Round */
+
+/*------------------------------------------------------------------*/
+
+/* Returns the floor integer of a double arguement, as double */
+double
+Int( double arg )
+{
+  return( floor(arg) );
+} /* Int */
+
+/*------------------------------------------------------------------*/
+
+/* Converts the satellite's position and velocity  */
+/* vectors from normalised values to km and km/sec */ 
+void
+Convert_Sat_State( vector_t *pos, vector_t *vel )
+{
+      Scale_Vector( xkmper, pos );
+      Scale_Vector( xkmper*xmnpda/secday, vel );
+
+} /* Procedure Convert_Sat_State */
+
+/*------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sgp4sdp4/sgp_obs.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,214 @@
+/*
+ * Unit SGP_Obs
+ *           Author:  Dr TS Kelso 
+ * Original Version:  1992 Jun 02 
+ * Current Revision:  1992 Sep 28 
+ *          Version:  1.40 
+ *        Copyright:  1992, All Rights Reserved 
+ *
+ *   Ported to C by:  Neoklis Kyriazis  April 9 2001
+ */
+
+#include "sgp4sdp4.h"
+
+/* Procedure Calculate_User_PosVel passes the user's geodetic position */
+/* and the time of interest and returns the ECI position and velocity  */
+/* of the observer. The velocity calculation assumes the geodetic      */
+/* position is stationary relative to the earth's surface.             */
+void
+Calculate_User_PosVel(double _time,
+                      geodetic_t *geodetic,
+                      vector_t *obs_pos,
+                      vector_t *obs_vel)
+{
+/* Reference:  The 1992 Astronomical Almanac, page K11. */
+
+  double c,sq,achcp;
+
+  geodetic->theta = FMod2p(ThetaG_JD(_time) + geodetic->lon);/*LMST*/
+  c = 1/sqrt(1 + __f*(__f - 2)*Sqr(sin(geodetic->lat)));
+  sq = Sqr(1 - __f)*c;
+  achcp = (xkmper*c + geodetic->alt)*cos(geodetic->lat);
+  obs_pos->x = achcp*cos(geodetic->theta);/*kilometers*/
+  obs_pos->y = achcp*sin(geodetic->theta);
+  obs_pos->z = (xkmper*sq + geodetic->alt)*sin(geodetic->lat);
+  obs_vel->x = -mfactor*obs_pos->y;/*kilometers/second*/
+  obs_vel->y =  mfactor*obs_pos->x;
+  obs_vel->z =  0;
+  SgpMagnitude(obs_pos);
+  SgpMagnitude(obs_vel);
+} /*Procedure Calculate_User_PosVel*/
+
+/*------------------------------------------------------------------*/
+
+/* Procedure Calculate_LatLonAlt will calculate the geodetic  */
+/* position of an object given its ECI position pos and time. */
+/* It is intended to be used to determine the ground track of */
+/* a satellite.  The calculations  assume the earth to be an  */
+/* oblate spheroid as defined in WGS '72.                     */
+void
+Calculate_LatLonAlt(double _time, vector_t *pos,  geodetic_t *geodetic)
+{
+  /* Reference:  The 1992 Astronomical Almanac, page K12. */
+
+  double r,e2,phi,c;
+
+  geodetic->theta = AcTan(pos->y,pos->x);/*radians*/
+  geodetic->lon = FMod2p(geodetic->theta - ThetaG_JD(_time));/*radians*/
+  r = sqrt(Sqr(pos->x) + Sqr(pos->y));
+  e2 = __f*(2 - __f);
+  geodetic->lat = AcTan(pos->z,r);/*radians*/
+
+  do
+    {
+      phi = geodetic->lat;
+      c = 1/sqrt(1 - e2*Sqr(sin(phi)));
+      geodetic->lat = AcTan(pos->z + xkmper*c*e2*sin(phi),r);
+    }
+  while(fabs(geodetic->lat - phi) >= 1E-10);
+
+  geodetic->alt = r/cos(geodetic->lat) - xkmper*c;/*kilometers*/
+
+  if( geodetic->lat > pio2 ) geodetic->lat -= twopi;
+  
+} /*Procedure Calculate_LatLonAlt*/
+
+/*------------------------------------------------------------------*/
+
+/* The procedures Calculate_Obs and Calculate_RADec calculate         */
+/* the *topocentric* coordinates of the object with ECI position,     */
+/* {pos}, and velocity, {vel}, from location {geodetic} at {time}.    */
+/* The {obs_set} returned for Calculate_Obs consists of azimuth,      */
+/* elevation, range, and range rate (in that order) with units of     */
+/* radians, radians, kilometers, and kilometers/second, respectively. */
+/* The WGS '72 geoid is used and the effect of atmospheric refraction */
+/* (under standard temperature and pressure) is incorporated into the */
+/* elevation calculation; the effect of atmospheric refraction on     */
+/* range and range rate has not yet been quantified.                  */
+
+/* The {obs_set} for Calculate_RADec consists of right ascension and  */
+/* declination (in that order) in radians.  Again, calculations are   */
+/* based on *topocentric* position using the WGS '72 geoid and        */
+/* incorporating atmospheric refraction.                              */
+
+void
+Calculate_Obs(double _time,
+                vector_t *pos,
+                vector_t *vel,
+                geodetic_t *geodetic,
+                vector_t *obs_set)
+  {
+   double
+     sin_lat,cos_lat,
+     sin_theta,cos_theta,
+     el,azim,
+     top_s,top_e,top_z;
+
+   vector_t
+     obs_pos,obs_vel,range,rgvel;
+
+  Calculate_User_PosVel(_time, geodetic, &obs_pos, &obs_vel);
+
+    range.x = pos->x - obs_pos.x;
+    range.y = pos->y - obs_pos.y;
+    range.z = pos->z - obs_pos.z;
+
+    rgvel.x = vel->x - obs_vel.x;
+    rgvel.y = vel->y - obs_vel.y;
+    rgvel.z = vel->z - obs_vel.z;
+
+  SgpMagnitude(&range);
+
+  sin_lat = sin(geodetic->lat);
+  cos_lat = cos(geodetic->lat);
+  sin_theta = sin(geodetic->theta);
+  cos_theta = cos(geodetic->theta);
+  top_s = sin_lat*cos_theta*range.x
+         + sin_lat*sin_theta*range.y
+         - cos_lat*range.z;
+  top_e = -sin_theta*range.x
+         + cos_theta*range.y;
+  top_z = cos_lat*cos_theta*range.x
+         + cos_lat*sin_theta*range.y
+         + sin_lat*range.z;
+  azim = atan(-top_e/top_s); /*Azimuth*/
+  if( top_s > 0 ) 
+    azim = azim + pi;
+  if( azim < 0 )
+    azim = azim + twopi;
+  el = ArcSin(top_z/range.w);
+  obs_set->x = azim;      /* Azimuth (radians)  */
+  obs_set->y = el;        /* Elevation (radians)*/
+  obs_set->z = range.w; /* Range (kilometers) */
+
+ /*Range Rate (kilometers/second)*/
+  obs_set->w = Dot(&range, &rgvel)/range.w;
+
+/* Corrections for atmospheric refraction */
+/* Reference:  Astronomical Algorithms by Jean Meeus, pp. 101-104    */
+/* Correction is meaningless when apparent elevation is below horizon */
+  obs_set->y = obs_set->y + Radians((1.02/tan(Radians(Degrees(el)+
+               10.3/(Degrees(el)+5.11))))/60);
+  if( obs_set->y >= 0 )
+    SetFlag(VISIBLE_FLAG);
+  else
+    {
+    obs_set->y = el;  /*Reset to true elevation*/
+    ClearFlag(VISIBLE_FLAG);
+    } /*else*/
+  } /*Procedure Calculate_Obs*/
+
+/*------------------------------------------------------------------*/
+
+void
+Calculate_RADec( double _time,
+                 vector_t *pos,
+                 vector_t *vel,
+                 geodetic_t *geodetic,
+                 vector_t *obs_set)
+{
+/* Reference:  Methods of Orbit Determination by  */
+/*                Pedro Ramon Escobal, pp. 401-402 */
+
+double
+    phi,theta,sin_theta,cos_theta,sin_phi,cos_phi,
+    az,el,Lxh,Lyh,Lzh,Sx,Ex,Zx,Sy,Ey,Zy,Sz,Ez,Zz,
+    Lx,Ly,Lz,cos_delta,sin_alpha,cos_alpha;
+
+  Calculate_Obs(_time,pos,vel,geodetic,obs_set);
+
+/*  if( isFlagSet(VISIBLE_FLAG) )
+    {*/
+    az = obs_set->x;
+    el = obs_set->y;
+    phi   = geodetic->lat;
+    theta = FMod2p(ThetaG_JD(_time) + geodetic->lon);
+    sin_theta = sin(theta);
+    cos_theta = cos(theta);
+    sin_phi = sin(phi);
+    cos_phi = cos(phi);
+    Lxh = -cos(az)*cos(el);
+    Lyh =  sin(az)*cos(el);
+    Lzh =  sin(el);
+    Sx = sin_phi*cos_theta;
+    Ex = -sin_theta;
+    Zx = cos_theta*cos_phi;
+    Sy = sin_phi*sin_theta;
+    Ey = cos_theta;
+    Zy = sin_theta*cos_phi;
+    Sz = -cos_phi;
+    Ez = 0;
+    Zz = sin_phi;
+    Lx = Sx*Lxh + Ex*Lyh + Zx*Lzh;
+    Ly = Sy*Lxh + Ey*Lyh + Zy*Lzh;
+    Lz = Sz*Lxh + Ez*Lyh + Zz*Lzh;
+    obs_set->y = ArcSin(Lz);  /*Declination (radians)*/
+    cos_delta = sqrt(1 - Sqr(Lz));
+    sin_alpha = Ly/cos_delta;
+    cos_alpha = Lx/cos_delta;
+    obs_set->x = AcTan(sin_alpha,cos_alpha); /*Right Ascension (radians)*/
+    obs_set->x = FMod2p(obs_set->x);
+    /*}*/  /*if*/
+  } /* Procedure Calculate_RADec */
+
+/*------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sgp4sdp4/sgp_time.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,428 @@
+/*
+ * Unit SGP_Time
+ *       Author:  Dr TS Kelso
+ * Original Version:  1992 Jun 02
+ * Current Revision:  2000 Jan 22
+ * Modified for Y2K:  1999 Mar 07
+ *          Version:  2.05
+ *        Copyright:  1992-1999, All Rights Reserved
+ * Version 1.50 added Y2K support. Due to limitations in the current
+ * format of the NORAD two-line element sets, however, only dates
+ * through 2056 December 31/2359 UTC are valid.
+ * Version 1.60 modifies Calendar_Date to ensure date matches time
+ * resolution and modifies Time_of_Day to make it more robust.
+ * Version 2.00 adds Julian_Date, Date_Time, and Check_Date to support
+ * checking for valid date/times, permitting the use of Time_to_UTC and
+ * Time_from_UTC for UTC/local time conversions.
+ * Version 2.05 modifies UTC_offset to allow non-integer offsets.
+ *
+ *   Ported to C by: Neoklis Kyriazis  April 9  2001
+ */
+
+#include "sgp4sdp4.h"
+
+/* The function Julian_Date_of_Epoch returns the Julian Date of     */
+/* an epoch specified in the format used in the NORAD two-line      */
+/* element sets. It has been modified to support dates beyond       */
+/* the year 1999 assuming that two-digit years in the range 00-56   */
+/* correspond to 2000-2056. Until the two-line element set format   */
+/* is changed, it is only valid for dates through 2056 December 31. */
+
+double
+Julian_Date_of_Epoch(double epoch)
+{ 
+  double year,day;
+
+  /* Modification to support Y2K */
+  /* Valid 1957 through 2056     */
+  day = modf(epoch*1E-3, &year)*1E3;
+  if( year < 57 )
+    year = year + 2000;
+  else
+    year = year + 1900;
+  /* End modification */
+
+  return( Julian_Date_of_Year(year) + day );
+} /*Function Julian_Date_of_Epoch*/
+
+/*------------------------------------------------------------------*/
+
+/* Converts a Julian epoch to NORAD TLE epoch format */
+double
+Epoch_Time(double jd)
+{  
+  double yr,_time,epoch_time;
+  struct tm edate;
+
+  Calendar_Date(jd, &edate);
+  yr = edate.tm_year - 100*(edate.tm_year/100) ;
+  _time = Frac(jd + 0.5);
+  epoch_time =  yr*1000
+                + DOY(edate.tm_year, edate.tm_mon, edate.tm_mday)
+                + _time;
+
+  return( epoch_time );
+} /*Function Epoch_Time*/
+
+/*------------------------------------------------------------------*/
+
+/* The function DOY calculates the day of the year for the specified */
+/* date. The calculation uses the rules for the Gregorian calendar   */
+/* and is valid from the inception of that calendar system.          */
+int
+DOY(int yr, int mo, int dy)
+{
+  const int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+  int i,day;
+
+  day = 0;
+  for( i = 0; i < mo-1; i++ )
+    day += days[i];
+  day = day + dy;
+
+  /* Leap year correction */
+  if( 
+     (yr%4 == 0) && ((yr%100 != 0) || (yr%400 == 0)) && (mo>2)
+     )
+    day++;
+
+  return( day );
+} /*Function DOY*/
+
+/*------------------------------------------------------------------*/
+
+/* Fraction_of_Day calculates the fraction of */
+/* a day passed at the specified input time.  */
+double
+Fraction_of_Day(int hr,int mi,int se)
+{
+  return( (hr + (mi + se/60.0)/60.0)/24.0 );
+} /*Function Fraction_of_Day*/
+
+/*------------------------------------------------------------------*/
+
+/* The function Calendar_Date converts a Julian Date to a struct tm.   */
+/* Only the members tm_year, tm_mon and tm_mday are calculated and set */
+void
+Calendar_Date(double jd, struct tm *cdate)
+{
+  /* Astronomical Formulae for Calculators, Jean Meeus, pages 26-27 */
+  int Z,month;
+  double A,B,C,D,E,F,alpha,day,year,factor;
+
+  factor = 0.5/secday/1000;
+  F = Frac(jd + 0.5);
+  if (F + factor >= 1.0)
+    {
+      jd = jd + factor;
+      F  = 0.0;
+    } /*if*/
+  Z = Round(jd);
+  if( Z < 2299161 )
+    A = Z;
+  else
+    {
+      alpha = Int((Z - 1867216.25)/36524.25);
+      A = Z + 1 + alpha - Int(alpha/4);
+    } /*else*/
+  B = A + 1524;
+  C = Int((B - 122.1)/365.25);
+  D = Int(365.25 * C);
+  E = Int((B - D)/30.6001);
+  day = B - D - Int(30.6001 * E) + F;
+
+  if( E < 13.5 )
+    month = Round(E - 1);
+  else
+    month = Round(E - 13);
+  if( month > 2.5 )
+    year = C - 4716;
+  else
+    year = C - 4715;
+
+  cdate->tm_year = (int) year;
+  cdate->tm_mon = month;
+  cdate->tm_mday = (int) floor(day);
+
+} /*Function Calendar_Date*/
+
+/*------------------------------------------------------------------*/
+
+/* Time_of_Day takes a Julian Date and calculates the clock time */
+/* portion of that date. Only tm_hour, tm_min and tm_sec are set */
+void
+Time_of_Day(double jd, struct tm *cdate)
+{
+  int hr,mn,sc;
+  double _time;
+
+  _time = Frac(jd - 0.5)*secday;
+  _time = Round(_time);
+  hr = floor(_time/3600.0);
+  _time = _time - 3600.0*hr;
+  if( hr == 24 ) hr = 0;
+  mn = floor(_time/60.0);
+  sc = _time - 60.0*mn;
+  cdate->tm_hour = hr;
+  cdate->tm_min = mn;
+  cdate->tm_sec = sc;
+
+} /*Function Time_of_Day*/
+
+/*------------------------------------------------------------------*/
+
+/* The function Julian_Date converts a standard calendar   */
+/* date and time to a Julian Date. The procedure Date_Time */
+/* performs the inverse of this function. */
+double
+Julian_Date(struct tm *cdate)
+{
+  double julian_date;
+
+  julian_date = Julian_Date_of_Year(cdate->tm_year) + 
+                DOY(cdate->tm_year,cdate->tm_mon,cdate->tm_mday) +
+                Fraction_of_Day(cdate->tm_hour,cdate->tm_min,cdate->tm_sec);
+
+  return( julian_date );
+} /*Function Julian_Date */
+
+/*------------------------------------------------------------------*/
+
+
+/*  Date_Time()
+ *
+ *  The function Date_Time() converts a Julian Date to
+ *  standard calendar date and time. The function
+ *  Julian_Date() performs the inverse of this function.
+ */
+
+void
+Date_Time(double julian_date, struct tm *cdate)
+{
+  time_t jtime;
+
+  jtime = (julian_date - 2440587.5)*86400.;
+  *cdate = *gmtime( &jtime );
+
+} /* End of Date_Time() */
+
+
+/*------------------------------------------------------------------*/
+
+/* The procedure Check_Date can be used as a check to see if a calendar    */
+/* date and time are valid. It works by first converting the calendar      */
+/* date and time to a Julian Date (which allows for irregularities, such   */
+/* as a time greater than 24 hours) and then converting back and comparing.*/
+int
+Check_Date(struct tm *cdate)
+{
+  double jt;
+  struct tm chkdate;
+
+  jt = Julian_Date(cdate);
+  Date_Time(jt, &chkdate);
+
+  if( (cdate->tm_year == chkdate.tm_year) &&
+      (cdate->tm_mon  == chkdate.tm_mon ) &&
+      (cdate->tm_mday == chkdate.tm_mday) &&
+      (cdate->tm_hour == chkdate.tm_hour) &&
+      (cdate->tm_min  == chkdate.tm_min ) &&
+      (cdate->tm_sec  == chkdate.tm_sec ) )
+    return ( 1 );
+  else
+    return( 0 );
+
+} /*Procedure Check_Date*/
+
+/*------------------------------------------------------------------*/
+
+/* Procedures Time_to_UTC and Time_from_UTC are used to  */
+/* convert 'struct tm' dates between UTC and local time. */
+/* The procedures JD_to_UTC and JD_from_UTC are used to  */
+/* do the same thing working directly with Julian dates. */
+
+struct tm
+Time_to_UTC(struct tm *cdate)
+{
+  time_t tdate;
+
+  tdate = mktime(cdate);
+  return( *gmtime(&tdate) );
+} /*Procedure Time_to_UTC*/
+
+/*------------------------------------------------------------------*/
+
+struct tm 
+Time_from_UTC(struct tm *cdate)
+{
+  time_t tdate;
+
+  tdate = mktime(cdate);
+  return( *localtime(&tdate) );
+} /*Procedure Time_from_UTC*/
+
+/*------------------------------------------------------------------*/
+
+/*
+ BSD systems don't define the timezone variable, so the following two
+ routines won't work.  They're not used anyway in the example main(),
+ so we might as well comment them out.  
+*/
+
+#if 0
+
+double
+JD_to_UTC(double jt)
+{
+  extern long timezone;
+  struct tm cdate;
+
+  time_t t = 0;
+
+  cdate = *localtime( &t );
+  jt = jt - timezone/secday;
+  if( cdate.tm_isdst )
+    jt= jt - 1.0/24.0;
+
+  return( jt );
+} /*Procedure JD_to_UTC*/
+
+/*------------------------------------------------------------------*/
+
+double
+JD_from_UTC(double jt)
+{
+  extern long timezone;
+  struct tm cdate;
+  time_t t = 0;
+
+  cdate = *localtime( &t );
+  jt = jt + timezone/secday;
+  if( cdate.tm_isdst )
+    jt= jt + 1.0/24.0;
+
+  return( jt );
+} /*Procedure JD_from_UTC*/
+
+#endif
+
+/*------------------------------------------------------------------*/
+
+/* The function Delta_ET has been added to allow calculations on   */
+/* the position of the sun.  It provides the difference between UT */
+/* (approximately the same as UTC) and ET (now referred to as TDT).*/
+/* This function is based on a least squares fit of data from 1950 */
+/* to 1991 and will need to be updated periodically. */
+
+double
+Delta_ET(double year)
+{
+  /* Values determined using data from 1950-1991 in the 1990 
+     Astronomical Almanac.  See DELTA_ET.WQ1 for details. */
+
+  double delta_et;
+
+  delta_et = 26.465 + 0.747622*(year - 1950) +
+             1.886913*sin(twopi*(year - 1975)/33);
+
+  return( delta_et );
+} /*Function Delta_ET*/
+
+/*------------------------------------------------------------------*/
+
+/* The function Julian_Date_of_Year calculates the Julian Date  */
+/* of Day 0.0 of {year}. This function is used to calculate the */
+/* Julian Date of any date by using Julian_Date_of_Year, DOY,   */
+/* and Fraction_of_Day. */
+
+double
+Julian_Date_of_Year(double year)
+{
+  /* Astronomical Formulae for Calculators, Jean Meeus, */
+  /* pages 23-25. Calculate Julian Date of 0.0 Jan year */
+
+  long A,B,i;
+  double jdoy;
+
+  year = year-1;
+  i = year/100;
+  A = i;
+  i = A/4;
+  B = 2-A+i;
+  i = 365.25*year;
+  i += 30.6001*14;
+  jdoy = i+1720994.5+B;
+
+  return (jdoy);
+}  /*Function Julian_Date_of_Year*/
+
+/*------------------------------------------------------------------*/
+
+/* The function ThetaG calculates the Greenwich Mean Sidereal Time */
+/* for an epoch specified in the format used in the NORAD two-line */
+/* element sets. It has now been adapted for dates beyond the year */
+/* 1999, as described above. The function ThetaG_JD provides the   */
+/* same calculation except that it is based on an input in the     */
+/* form of a Julian Date. */
+
+double
+ThetaG(double epoch, deep_arg_t *deep_arg)
+{
+/* Reference:  The 1992 Astronomical Almanac, page B6. */
+
+  double year,day,UT,jd,TU,GMST,_ThetaG;
+
+/* Modification to support Y2K */
+/* Valid 1957 through 2056     */
+  day = modf(epoch*1E-3,&year)*1E3;
+  if(year < 57)
+    year += 2000;
+  else
+    year += 1900;
+  /* End modification */
+
+  UT   = modf(day,&day);
+  jd   = Julian_Date_of_Year(year)+day;
+  TU   = (jd-2451545.0)/36525;
+  GMST = 24110.54841+TU*(8640184.812866+TU*(0.093104-TU* 6.2E-6));
+  GMST = Modulus(GMST+secday*omega_E*UT,secday);
+  _ThetaG = twopi*GMST/secday;
+  deep_arg->ds50 = jd-2433281.5+UT;
+  _ThetaG = FMod2p(6.3003880987*deep_arg->ds50+1.72944494);
+
+  return (_ThetaG);
+} /* Function ThetaG */
+
+/*------------------------------------------------------------------*/
+
+double
+ThetaG_JD(double jd)
+{
+/* Reference:  The 1992 Astronomical Almanac, page B6. */
+
+  double UT,TU,GMST;
+
+  UT   = Frac(jd + 0.5);
+  jd   = jd - UT;
+  TU   = (jd - 2451545.0)/36525;
+  GMST = 24110.54841 + TU * (8640184.812866 + TU * (0.093104 - TU * 6.2E-6));
+  GMST = Modulus(GMST + secday*omega_E*UT,secday);
+
+  return( twopi * GMST/secday );
+} /*Function ThetaG_JD*/
+
+/*------------------------------------------------------------------*/
+
+/* Gets calendar time from time() and produces a UTC calendar date */
+void
+UTC_Calendar_Now( struct tm *cdate )
+{
+  time_t t;
+
+  t = time(0);
+  *cdate = *gmtime(&t);
+  cdate->tm_year += 1900;
+  cdate->tm_mon += 1;
+
+} /* End UTC_Calendar_Now */
+/*------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sgp4sdp4/solar.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,69 @@
+/*
+ * Unit Solar
+ *           Author:  Dr TS Kelso
+ * Original Version:  1990 Jul 29
+ * Current Revision:  1999 Nov 27
+ *          Version:  1.30
+ *        Copyright:  1990-1999, All Rights Reserved
+ *
+ *   Ported to C by: Neoklis Kyriazis  April 1 2001
+ */
+
+#include "sgp4sdp4.h"
+
+/* Calculates solar position vector */
+void
+Calculate_Solar_Position(double _time, vector_t *solar_vector)
+{
+  double mjd,year,T,M,L,e,C,O,Lsa,nu,R,eps;
+
+  mjd = _time - 2415020.0;
+  year = 1900 + mjd/365.25;
+  T = (mjd + Delta_ET(year)/secday)/36525.0;
+  M = Radians(Modulus(358.47583 + Modulus(35999.04975*T,360.0)
+              - (0.000150 + 0.0000033*T)*Sqr(T),360.0));
+  L = Radians(Modulus(279.69668 + Modulus(36000.76892*T,360.0)
+              + 0.0003025*Sqr(T),360.0));
+  e = 0.01675104 - (0.0000418 + 0.000000126*T)*T;
+  C = Radians((1.919460 - (0.004789 + 0.000014*T)*T)*sin(M)
+          + (0.020094 - 0.000100*T)*sin(2*M) + 0.000293*sin(3*M));
+  O = Radians(Modulus(259.18 - 1934.142*T,360.0));
+  Lsa = Modulus(L + C - Radians(0.00569 - 0.00479*sin(O)),twopi);
+  nu = Modulus(M + C,twopi);
+  R = 1.0000002*(1 - Sqr(e))/(1 + e*cos(nu));
+  eps = Radians(23.452294 - (0.0130125 + (0.00000164 -
+        0.000000503*T)*T)*T + 0.00256*cos(O));
+  R = SGPAU*R;
+  solar_vector->x = R*cos(Lsa);
+  solar_vector->y = R*sin(Lsa)*cos(eps);
+  solar_vector->z = R*sin(Lsa)*sin(eps);
+  solar_vector->w = R;
+} /*Procedure Calculate_Solar_Position*/
+
+/*------------------------------------------------------------------*/
+
+/* Calculates stellite's eclipse status and depth */
+int
+Sat_Eclipsed(vector_t *pos, vector_t *sol, double *depth)
+{
+  double sd_sun, sd_earth, delta;
+  vector_t Rho, earth;
+
+  /* Determine partial eclipse */
+  sd_earth = ArcSin(xkmper/pos->w);
+  Vec_Sub(sol,pos,&Rho);
+  sd_sun = ArcSin(__sr__/Rho.w);
+  Scalar_Multiply(-1,pos,&earth);
+  delta = Angle(sol,&earth);
+  *depth = sd_earth - sd_sun - delta;
+  if( sd_earth < sd_sun )
+    return( 0 );
+  else
+    if( *depth >= 0 )
+      return( 1 );
+    else
+      return( 0 );
+
+} /*Function Sat_Eclipsed*/
+
+/*------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sowb.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,34 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef SOWB_H
+#define SOWB_H
+
+#include <LPC17xx.h>
+#include <cmsis_nvic.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/predict_th.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,117 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "string.h"
+#include "sowb.h"
+#include "osd.h"
+#include "sgp4sdp4.h"
+#include "predict_th.h"
+#include "gps.h"
+#include "gpio.h"
+#include "satapi.h"
+#include "debug.h"
+
+#ifdef PREDICT_TH_RUN
+
+tle_t       ISS_TLE;
+
+
+
+int sgp4sdp4_th_init(void) {
+    char buf[128];
+    GPS_TIME t;
+    double jd_epoch, jd_utc, tsince, phase;
+    vector_t vel = { 0, 0, 0 };
+    vector_t pos = { 0, 0, 0 };
+    vector_t obs_set;
+    geodetic_t obs_geodetic;
+    geodetic_t sat_geodetic;
+    tle_t tle, localtle;
+    char elements[3][80];
+
+    /* Prepare to begin ISS */
+    strcpy(elements[0], "ISS (ZARYA)");
+    strcpy(elements[1], "1 25544U 98067A   10278.19511664  .00012217  00000-0  97221-4 0   147");
+    strcpy(elements[2], "2 25544 051.6473 027.7875 0007506 064.6316 006.5147 15.71651651680777");
+    
+    debug_printf("SGP4SDP4 TH starting 1\r\n");
+    
+    ClearFlag(ALL_FLAGS);
+    Get_Next_Tle_Set(elements, &tle);
+    memcpy(&localtle, &tle, sizeof(tle_t));
+    select_ephemeris(&tle);
+    
+    gps_get_time(&t);
+    
+    if (!t.is_valid) {
+        debug_printf("SGP4SDP4 TH Abort, invalid time.\r\n");
+        return 0;
+    }
+    
+    jd_utc = gps_julian_date(&t);
+    jd_epoch = Julian_Date_of_Epoch(tle.epoch);
+    tsince = (jd_utc - jd_epoch) * xmnpda;
+    
+    if (isFlagSet(DEEP_SPACE_EPHEM_FLAG)) {
+        //debug_printf("Using SDP4\r\n");
+        SDP4(tsince, &tle, &pos, &vel, &phase);
+    }
+    else {
+        //debug_printf("Using SGP4\r\n");
+        SGP4(tsince, &tle, &pos, &vel, &phase);
+    }
+
+    Convert_Sat_State(&pos, &vel);
+    //SgpMagnitude(&vel); // scalar magnitude, not brightness...
+    //double velocity = vel.w;
+
+    GPS_LOCATION_AVERAGE loc;    
+    gps_get_location_average(&loc);
+    if (loc.east_west   == 'W') loc.longitude *= -1.;
+    if (loc.north_south == 'S') loc.latitude  *= -1.;
+
+    obs_geodetic.lat   = loc.latitude * de2ra; // * 56.1920;
+    obs_geodetic.lon   = loc.longitude * de2ra; // * -3.0339;
+    obs_geodetic.alt   = loc.height / 1000.;
+    
+    Calculate_Obs(jd_utc, &pos, &vel, &obs_geodetic, &obs_set);
+    Calculate_LatLonAlt(jd_utc, &pos, &sat_geodetic);
+
+    double azimuth     = Degrees(obs_set.x);
+    double elevation   = Degrees(obs_set.y);
+    double range       = obs_set.z;
+    //double rangeRate   = obs_set.w;
+    //double height      = sat_geodetic.alt;
+    
+    //sprintf(buf, "JD UTC : %.5f  JD SAT : %.5f  DIF : %f\r\n", jd_utc, jd_epoch, jd_utc - jd_epoch);
+    //debug_printf("%s", buf);
+    
+    sprintf(buf, "ISS El:%.1f AZ:%.1f %dKm\r\n\n", elevation, azimuth, (int)range);
+    osd_string_xy(0, 14, buf);
+    debug_printf("%s", buf);
+    return 1;
+    
+    
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/predict_th.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,34 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef PREDICT_TH_H
+#define PREDICT_TH_H
+
+#define PREDICT_TH_RUN
+
+#ifdef PREDICT_TH_RUN
+
+int sgp4sdp4_th_init(void);
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/th_xbox360gamepad.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,123 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef TH_XBOX360GAMEPAD_C
+#define TH_XBOX360GAMEPAD_C
+#endif
+
+#include "mbed.h"
+#include "usbeh.h"
+#include "usbeh_endpoint.h"
+#include "usbeh_device.h"
+#include "usbeh_controller.h"
+#include "usbeh_api.h"
+#include "xbox360gamepad.h"
+#include "th_xbox360gamepad.h"
+
+#include "main.h"
+#include "debug.h"
+
+
+const char *button_text[] = { "","LS","RS","XBOX","Unused","A","B","X","Y","DPAD UP","DPAD DOWN","DPAD LEFT","DPAG RIGHT","START","BACK","LEFT HAT","RIGHT HAT" };
+
+/* Define globals to hold Xbox360 stick data. */
+XBOX360_STICK *stick;
+XBOX360_STICK stick_left_previous;
+XBOX360_STICK stick_right_previous;   
+unsigned char trigger_left = 0, trigger_left_last = 0;
+unsigned char trigger_right = 0, trigger_right_last = 0;
+
+void th_xbox360gamepad_init(void) {
+    stick = xbox360gamepad_get_stick_left();
+    stick_left_previous.x = stick->x;
+    stick_left_previous.y = stick->y;
+    stick = xbox360gamepad_get_stick_right();
+    stick_right_previous.x = stick->x;
+    stick_right_previous.y = stick->y;    
+}
+        
+void th_xbox360gamepad(void) {
+    unsigned char button;
+    if ((button = xbox360gamepad_get_button()) != 0) {
+        if (button > 0) {
+            debug_printf("Button ");
+            if (button > (BUTT_RIGHT_HAT_PRESS + 16)) {
+                debug_printf("%s held\r\n", button_text[button - 32]);
+            }
+            else if (button > BUTT_RIGHT_HAT_PRESS) { 
+                debug_printf("%s released\r\n", button_text[button - 16]);
+            }
+            else {
+                debug_printf("%s pressed\r\n", button_text[button]);
+                switch (button) {
+                    case BUTT_A_PRESS:
+                        xbox360gamepad_led(LED_1_FLASH_THEN_ON);
+                        break;
+                    case BUTT_B_PRESS:
+                        xbox360gamepad_led(LED_2_FLASH_THEN_ON);
+                        break;
+                    case BUTT_X_PRESS:
+                        xbox360gamepad_led(LED_3_FLASH_THEN_ON);
+                        break;
+                    case BUTT_Y_PRESS:
+                        xbox360gamepad_led(LED_4_FLASH_THEN_ON);
+                        break;
+                }
+            }
+        }
+    }
+
+    if ((trigger_left = xbox360gamepad_get_trigger_left()) != trigger_left_last) {
+        debug_printf("Left trigger: %d\r\n", trigger_left);
+        trigger_left_last = trigger_left;
+    }
+
+    if ((trigger_right = xbox360gamepad_get_trigger_right()) != trigger_right_last) {
+        debug_printf("Right trigger: %d\r\n", trigger_right);
+        trigger_right_last = trigger_right;
+    }
+        
+    unsigned char xbox360gamepad_get_trigger_right(void);
+      
+    stick = xbox360gamepad_get_stick_left();
+    if (stick->x/STICK_DIVISOR != stick_left_previous.x/STICK_DIVISOR || stick->y/STICK_DIVISOR != stick_left_previous.y/STICK_DIVISOR) {
+        stick_left_previous.x = stick->x;
+        stick_left_previous.y = stick->y;
+        // Don't bother printing for now, the sticks are too sensitive!
+        int x = stick->x/STICK_DIVISOR, y = stick->y/STICK_DIVISOR;
+        if (1 || (x > 10 || x < -10) || (y > 10 || y < -10) ) {
+            debug_printf("New LEFT stick position x = %d y = %d\r\n", stick->x/STICK_DIVISOR, stick->y/STICK_DIVISOR);
+        }
+    }
+
+    stick = xbox360gamepad_get_stick_right();
+    if (stick->x/STICK_DIVISOR != stick_right_previous.x/STICK_DIVISOR || stick->y/STICK_DIVISOR != stick_right_previous.y/STICK_DIVISOR) {
+        stick_right_previous.x = stick->x;
+        stick_right_previous.y = stick->y;
+        // Don't bother printing for now, the sticks are too sensitive!
+        int x = stick->x/STICK_DIVISOR, y = stick->y/STICK_DIVISOR;
+        if (1 || (x > 10 || x < -10) || (y > 10 || y < -10) ) {
+            debug_printf("New RIGHT stick position x = %d y = %d\r\n", stick->x/STICK_DIVISOR, stick->y/STICK_DIVISOR);
+        }
+    }    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/th_xbox360gamepad.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,52 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef TH_XBOX360GAMEPAD_H
+#define TH_XBOX360GAMEPAD_H
+
+#ifndef BUTT_LS_PRESS
+#define BUTT_LS_PRESS                 1
+#define BUTT_RS_PRESS                 2
+#define BUTT_XBOX_PRESS               3
+#define BUTT_UNUSED_PRESS             4
+#define BUTT_A_PRESS                  5
+#define BUTT_B_PRESS                  6
+#define BUTT_X_PRESS                  7
+#define BUTT_Y_PRESS                  8
+#define BUTT_DPAD_UP_PRESS            9
+#define BUTT_DPAD_DOWN_PRESS          10
+#define BUTT_DPAD_LEFT_PRESS          11
+#define BUTT_DPAD_RIGHT_PRESS         12
+#define BUTT_START_PRESS              13
+#define BUTT_BACK_PRESS               14
+#define BUTT_LEFT_HAT_PRESS           15
+#define BUTT_RIGHT_HAT_PRESS          16
+#endif
+
+#define STICK_DIVISOR    1024
+
+
+void th_xbox360gamepad_init(void);
+void th_xbox360gamepad(void);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/readme.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,65 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ /**************************************************************************
+ 
+ The USB Embedded Host software is originally derived from the work of
+ Peter Barrett [1] and his BlueUSB project [2].
+ 
+ Although heavily re-styled, modified and revised for the SOWB project,
+ the "core" of the embedded host is based on Peter's work. Peter's
+ original copyright is acknowledge and reproduced below.
+ 
+ Thank you Peter for allowing others to stand on the shoulders of giants ;)
+ 
+ [1] http://mbed.org/users/peterbarrett1967/
+ [2] http://mbed.org/users/peterbarrett1967/programs/BlueUSB/5yn1q
+ 
+ Side note, I found some bugs that I fixed. I sent these back to Peter
+ to update his project. As yet I've had no reply and last time I looked
+ the bugs were still there. Basically, if a USB device has multiple
+ interfaces, in Peter's design only the even numbered interfaces will
+ be enumerated and assigned endpoints. All odd numbered interfaces are
+ skipped over and ignored.
+
+****************************************************************************/
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,366 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef USBEH_H
+#define USBEH_H
+
+#include "sowb.h"
+
+/* Definitions */
+#define USBEH_HcRevision            LPC_USB->HcRevision
+#define USBEH_HcControl             LPC_USB->HcControl
+#define USBEH_HcCommandStatus       LPC_USB->HcCommandStatus
+#define USBEH_HcInterruptStatus     LPC_USB->HcInterruptStatus
+#define USBEH_HcInterruptEnable     LPC_USB->HcInterruptEnable
+#define USBEH_HcInterruptDisable    LPC_USB->HcInterruptDisable
+#define USBEH_HcHCCA                LPC_USB->HcHCCA
+#define USBEH_entED                 LPC_USB->entED
+#define USBEH_HcControlHeadED       LPC_USB->HcControlHeadED
+#define USBEH_HcControlCurrentED    LPC_USB->HcControlCurrentED
+#define USBEH_HcBulkHeadED          LPC_USB->HcBulkHeadED
+#define USBEH_HcBulkCurrentED       LPC_USB->HcBulkCurrentED
+#define USBEH_HcDoneHead            LPC_USB->HcDoneHead
+#define USBEH_HcFmInterval          LPC_USB->HcFmInterval
+#define USBEH_HcFmRemaining         LPC_USB->HcFmRemaining
+#define USBEH_HcFmNumber            LPC_USB->HcFmNumber
+#define USBEH_HcPeriodicStart       LPC_USB->HcPeriodicStart
+#define USBEH_HcLSTreshold          LPC_USB->HcLSTreshold
+#define USBEH_HcRhDescriptorA       LPC_USB->HcRhDescriptorA
+#define USBEH_HcRhDescriptorB       LPC_USB->HcRhDescriptorB
+#define USBEH_HcRhStatus            LPC_USB->HcRhStatus
+#define USBEH_HcRhPortStatus1       LPC_USB->HcRhPortStatus1
+#define USBEH_HcRhPortStatus2       LPC_USB->HcRhPortStatus2
+#define USBEH_Module_ID             LPC_USB->Module_ID
+#define USBEH_OTGIntSt              LPC_USB->OTGIntSt
+#define USBEH_OTGIntEn              LPC_USB->OTGIntEn
+#define USBEH_OTGIntSet             LPC_USB->OTGIntSet
+#define USBEH_OTGIntClr             LPC_USB->OTGIntClr
+#define USBEH_OTGStCtrl             LPC_USB->OTGStCtrl
+#define USBEH_OTGTmr                LPC_USB->OTGTmr
+#define USBEH_USBDevIntSt           LPC_USB->USBDevIntSt
+#define USBEH_USBDevIntEn           LPC_USB->USBDevIntEn
+#define USBEH_USBDevIntClr          LPC_USB->USBDevIntClr
+#define USBEH_USBDevIntSet          LPC_USB->USBDevIntSet
+#define USBEH_USBCmdCode            LPC_USB->USBCmdCode
+#define USBEH_USBCmdData            LPC_USB->USBCmdData
+#define USBEH_USBRxData             LPC_USB->USBRxData
+#define USBEH_USBTxData             LPC_USB->USBTxData
+#define USBEH_USBRxPLen             LPC_USB->USBRxPLen
+#define USBEH_USBTxPLen             LPC_USB->USBTxPLen
+#define USBEH_USBCtrl               LPC_USB->USBCtrl
+#define USBEH_USBDevIntPri          LPC_USB->USBDevIntPri
+#define USBEH_USBEpIntSt            LPC_USB->USBEpIntSt
+#define USBEH_USBEpIntEn            LPC_USB->USBEpIntEn
+#define USBEH_USBEpIntClr           LPC_USB->USBEpIntClr
+#define USBEH_USBEpIntSet           LPC_USB->USBEpIntSet
+#define USBEH_USBEpIntPri           LPC_USB->USBEpIntPri
+#define USBEH_USBReEp               LPC_USB->USBReEp
+#define USBEH_USBEpInd              LPC_USB->USBEpInd
+#define USBEH_USBMaxPSize           LPC_USB->USBMaxPSize
+#define USBEH_USBDMARSt             LPC_USB->USBDMARSt
+#define USBEH_USBDMARClr            LPC_USB->USBDMARClr
+#define USBEH_USBDMARSet            LPC_USB->USBDMARSet
+#define USBEH_USBUDCAH              LPC_USB->USBUDCAH
+#define USBEH_USBEpDMASt            LPC_USB->USBEpDMASt
+#define USBEH_USBEpDMAEn            LPC_USB->USBEpDMAEn
+#define USBEH_USBEpDMADis           LPC_USB->USBEpDMADis
+#define USBEH_USBDMAIntSt           LPC_USB->USBDMAIntSt
+#define USBEH_USBDMAIntEn           LPC_USB->USBDMAIntEn
+#define USBEH_USBEoTIntSt           LPC_USB->USBEoTIntSt
+#define USBEH_USBEoTIntClr          LPC_USB->USBEoTIntClr
+#define USBEH_USBEoTIntSet          LPC_USB->USBEoTIntSet
+#define USBEH_USBNDDRIntSt          LPC_USB->USBNDDRIntSt
+#define USBEH_USBNDDRIntClr         LPC_USB->USBNDDRIntClr
+#define USBEH_USBNDDRIntSet         LPC_USB->USBNDDRIntSet
+#define USBEH_USBSysErrIntSt        LPC_USB->USBSysErrIntSt
+#define USBEH_USBSysErrIntClr       LPC_USB->USBSysErrIntClr
+#define USBEH_USBSysErrIntSet       LPC_USB->USBSysErrIntSet
+#define USBEH_I2C_RX                LPC_USB->I2C_RX
+#define USBEH_I2C_WO                LPC_USB->I2C_WO
+#define USBEH_I2C_STS               LPC_USB->I2C_STS
+#define USBEH_I2C_CTL               LPC_USB->I2C_CTL
+#define USBEH_I2C_CLKHI             LPC_USB->I2C_CLKHI
+#define USBEH_I2C_CLKLO             LPC_USB->I2C_CLKLO
+#define USBEH_USBClkCtrl            LPC_USB->USBClkCtrl
+#define USBEH_OTGClkCtrl            LPC_USB->OTGClkCtrl
+#define USBEH_USBClkSt              LPC_USB->USBClkSt
+#define USBEH_OTGClkSt              LPC_USB->OTGClkSt
+
+void user_wait_ms(uint32_t ms);
+//#define USBEH_OS_DELAY_MS(x)    wait_ms(x);
+#define USBEH_OS_DELAY_MS(x)    user_wait_ms(x);
+
+#define USBEH_U32   uint32_t
+#define USBEH_U16   unsigned short int
+#define USBEH_U08   unsigned char
+#define USBEH_S32   int32_t
+#define USBEH_S16   short int
+#define USBEH_S08   char
+
+#define USBEH_MAX_ENDPOINTS_TOTAL       16
+#define USBEH_MAX_DEVICES               8
+#define USBEH_MAX_ENDPOINTS_PER_DEVICE  8
+
+#define USBEH_ENDPOINT_CONTROL 0
+#define USBEH_ENDPOINT_ISOCRONOUS 1
+#define USBEH_ENDPOINT_BULK 2
+#define USBEH_ENDPOINT_INTERRUPT 3
+
+#define USBEH_DESCRIPTOR_TYPE_DEVICE        1
+#define USBEH_DESCRIPTOR_TYPE_CONFIGURATION 2
+#define USBEH_DESCRIPTOR_TYPE_STRING        3
+#define USBEH_DESCRIPTOR_TYPE_INTERFACE     4
+#define USBEH_DESCRIPTOR_TYPE_ENDPOINT      5
+
+#define USBEH_DESCRIPTOR_TYPE_HID         0x21
+#define USBEH_DESCRIPTOR_TYPE_REPORT      0x22
+#define USBEH_DESCRIPTOR_TYPE_PHYSICAL    0x23
+#define USBEH_DESCRIPTOR_TYPE_HUB         0x29
+
+#define USBEH_HOST_CLK_EN                       (1 << 0)
+#define USBEH_PORTSEL_CLK_EN                    (1 << 3)
+#define USBEH_AHB_CLK_EN                        (1 << 4)
+#define USBEH_CLOCK_MASK                        (USBEH_HOST_CLK_EN | USBEH_PORTSEL_CLK_EN | USBEH_AHB_CLK_EN)
+#define USBEH_FRAMEINTERVAL                     (12000-1)    // 1ms
+#define USBEH_DEFAULT_FMINTERVAL                ((((6 * (USBEH_FRAMEINTERVAL - 210)) / 7) << 16) | USBEH_FRAMEINTERVAL)
+#define USBEH_HOST_CONTROLLER_RESET             0x01
+#define USBEH_HOST_CONTROLLER_FUNCTIONAL_STATE  0xC0
+#define USBEH_OPERATIONAL_MASK                  0x80
+#define USBEH_SET_GLOBAL_POWER                  0x00010000
+
+#define USBEH_WRITEBACK_DONE_HEAD       0x00000002
+#define USBEH_START_OF_FRAME            0x00000004
+#define USBEH_RESUME_DETECTED           0x00000008
+#define USBEH_UNRECOVERABLE_ERROR       0x00000010
+#define USBEH_FRAME_NUMBER_OVERFLOW     0x00000020
+#define USBEH_ROOT_HUB_STATUS_CHANGE    0x00000040
+#define USBEH_OWNERSHIP_CHANGE          0x00000080
+#define USBEH_MASTER_IRQ_ENABLE         0x80000000
+    
+enum USB_CLASS_CODE {
+    CLASS_DEVICE,
+    CLASS_AUDIO,
+    CLASS_COMM_AND_CDC_CONTROL,
+    CLASS_HID,
+    CLASS_PHYSICAL = 0x05,
+    CLASS_STILL_IMAGING,
+    CLASS_PRINTER,
+    CLASS_MASS_STORAGE,
+    CLASS_HUB,
+    CLASS_CDC_DATA,
+    CLASS_SMART_CARD,
+    CLASS_CONTENT_SECURITY      = 0x0D,
+    CLASS_VIDEO                 = 0x0E,
+    CLASS_DIAGNOSTIC_DEVICE     = 0xDC,
+    CLASS_WIRELESS_CONTROLLER   = 0xE0,
+    CLASS_MISCELLANEOUS         = 0xEF,
+    CLASS_APP_SPECIFIC          = 0xFE,
+    CLASS_VENDOR_SPECIFIC       = 0xFF
+};
+
+#define USBEH_DEVICE_TO_HOST         0x80
+#define USBEH_HOST_TO_DEVICE         0x00
+#define USBEH_REQUEST_TYPE_CLASS     0x20
+#define USBEH_RECIPIENT_DEVICE       0x00
+#define USBEH_RECIPIENT_INTERFACE    0x01
+#define USBEH_RECIPIENT_ENDPOINT     0x02
+#define USBEH_RECIPIENT_OTHER        0x03
+
+#define USBEH_SETUP_TYPE_MASK_STANDARD  0x00
+#define USBEH_SETUP_TYPE_MASK_CLASS     0x20
+#define USBEH_SETUP_TYPE_MASK_VENDOR    0x40
+#define USBEH_SETUP_TYPE_MASK_RESERVED  0x60
+
+#define USBEH_GET_STATUS            0
+#define USBEH_CLEAR_FEATURE         1
+#define USBEH_SET_FEATURE           3
+#define USBEH_SET_ADDRESS           5
+#define USBEH_GET_DESCRIPTOR        6
+#define USBEH_SET_DESCRIPTOR        7
+#define USBEH_GET_CONFIGURATION     8
+#define USBEH_SET_CONFIGURATION     9
+#define USBEH_GET_INTERFACE         10
+#define USBEH_SET_INTERFACE         11
+#define USBEH_SYNCH_FRAME           11
+
+//    Status flags from hub
+#define USBEH_PORT_CONNECTION       0
+#define USBEH_PORT_ENABLE           1
+#define USBEH_PORT_SUSPEND          2
+#define USBEH_PORT_OVER_CURRENT     3
+#define USBEH_PORT_RESET            4
+#define USBEH_PORT_POWER            8
+#define USBEH_PORT_LOW_SPEED        9
+
+#define USBEH_C_PORT_CONNECTION     16
+#define USBEH_C_PORT_ENABLE         17
+#define USBEH_C_PORT_SUSPEND        18
+#define USBEH_C_PORT_OVER_CURRENT   19
+#define USBEH_C_PORT_RESET          20
+
+#define USBEH_IO_PENDING                -100
+#define USBEH_ERR_ENDPOINT_NONE_LEFT    -101
+#define USBEH_ERR_ENDPOINT_NOT_FOUND    -102
+#define USBEH_ERR_DEVICE_NOT_FOUND      -103
+#define USBEH_ERR_DEVICE_NONE_LEFT      -104
+#define USBEH_ERR_HUB_INIT_FAILED       -105
+#define USBEH_ERR_INTERFACE_NOT_FOUND   -106
+
+#define USBEH_TOKEN_SETUP   0
+#define USBEH_TOKEN_IN      1
+#define USBEH_TOKEN_OUT     2
+
+#define USBEH_TD_ROUNDING      (USBEH_U32)0x00040000
+#define USBEH_TD_SETUP         (USBEH_U32)0x00000000
+#define USBEH_TD_IN            (USBEH_U32)0x00100000
+#define USBEH_TD_OUT           (USBEH_U32)0x00080000
+#define USBEH_TD_DELAY_INT(x)  (USBEH_U32)((x) << 21)
+#define USBEH_TD_TOGGLE_0      (USBEH_U32)0x02000000
+#define USBEH_TD_TOGGLE_1      (USBEH_U32)0x03000000
+#define USBEH_TD_CC            (USBEH_U32)0xF0000000
+
+typedef struct {
+    USBEH_U08   bLength;
+    USBEH_U08   bDescriptorType;
+    USBEH_U16   bcdUSB;
+    USBEH_U08   bDeviceClass;
+    USBEH_U08   bDeviceSubClass;
+    USBEH_U08   bDeviceProtocol;
+    USBEH_U08   bMaxPacketSize;
+    USBEH_U16   idVendor;
+    USBEH_U16   idProduct;
+    USBEH_U16   bcdDevice;    
+    USBEH_U08   iManufacturer;
+    USBEH_U08   iProduct;
+    USBEH_U08   iSerialNumber;
+    USBEH_U08   bNumConfigurations;
+} USBEH_deviceDescriptor;
+
+typedef struct {
+    USBEH_U08   bLength;
+    USBEH_U08   bDescriptorType;
+    USBEH_U16   wTotalLength;
+    USBEH_U08   bNumInterfaces;
+    USBEH_U08   bConfigurationValue;
+    USBEH_U08   iConfiguration;
+    USBEH_U08   bmAttributes;
+    USBEH_U08   bMaxPower;
+} USBEH_configurationDescriptor;
+
+typedef struct {
+    USBEH_U08   bLength;
+    USBEH_U08   bDescriptorType;
+    USBEH_U08   bInterfaceNumber;
+    USBEH_U08   bAlternateSetting;
+    USBEH_U08   bNumEndpoints;
+    USBEH_U08   bInterfaceClass;
+    USBEH_U08   bInterfaceSubClass;
+    USBEH_U08   bInterfaceProtocol;
+    USBEH_U08   iInterface;
+} USBEH_interfaceDescriptor;
+
+typedef struct {
+    USBEH_U08   bLength;
+    USBEH_U08   bDescriptorType;
+    USBEH_U08   bEndpointAddress;
+    USBEH_U08   bmAttributes;
+    USBEH_U16   wMaxPacketSize;
+    USBEH_U08   bInterval;
+} USBEH_endpointDescriptor;
+
+typedef struct {
+  USBEH_U08 bLength;
+  USBEH_U08 bDescriptorType;
+  USBEH_U16 bcdHID;
+  USBEH_U08 bCountryCode;
+  USBEH_U08 bNumDescriptors;
+  USBEH_U08 bDescriptorType2;
+  USBEH_U16 wDescriptorLength;
+} USBEH_HIDDescriptor;
+
+typedef struct {
+    volatile USBEH_U32  control;
+    volatile USBEH_U32  tailTd;
+    volatile USBEH_U32  headTd;
+    volatile USBEH_U32  next;
+} USBEH_HCED;
+
+typedef struct {
+    volatile USBEH_U32  control;
+    volatile USBEH_U32  currentBufferPointer;
+    volatile USBEH_U32  next;
+    volatile USBEH_U32  bufferEnd;
+} USBEH_HCTD;
+
+typedef struct {
+    volatile USBEH_U32  interruptTable[32];
+    volatile USBEH_U16  frameNumber;
+    volatile USBEH_U16  frameNumberPad;
+    volatile USBEH_U32  doneHead;
+    volatile USBEH_U08  Reserved[120];
+} USBEH_HCCA;
+
+typedef struct {
+    USBEH_U08   bm_request_type;
+    USBEH_U08   b_request;
+    USBEH_U16   w_value;
+    USBEH_U16   w_index;
+    USBEH_U16   w_length;
+} USBEH_Setup;
+
+typedef void (*USBEH_callback)(int device, int endpoint, int status, USBEH_U08* data, int len, void* userData);
+
+#define USBEH_SOF_COUNTER_INC               1
+#define USBEH_SOF_COUNTER_DEC               2
+#define USBEH_SOF_COUNTER_DEC_HALT_AT_ZERO  4
+#define USBEH_SOF_COUNTER_RELOAD            8
+
+typedef struct _sof_counter {
+    USBEH_U08       mode;
+    USBEH_U08       flag;
+    USBEH_U32       counter;
+    USBEH_U32       reload;
+    USBEH_U32       userData;
+    void            (*callback)(struct _sof_counter *);
+    _sof_counter    *next;
+} USBEH_SOF_COUNTER;
+
+//typedef void (*USBCallback)(int device, int endpoint, int status, USBEH_U08* data, int len, void* userData);
+
+
+// Macros.
+
+#define USBEH_CURRENT_CONNECT_STATUS    0x01
+#define USBEH_CONNECT_STATUS_CHANGE     (USBEH_CURRENT_CONNECT_STATUS << 16)
+#define USBEH_PORT_RESET_STATUS         0x10
+#define USBEH_PORT_RESET_STATUS_CAHNGE  (USBEH_PORT_RESET_STATUS << 16)
+#define USBEH_CONTROL_LIST_ENABLE       0x10
+#define USBEH_CONTROL_LIST_FILLED       0x02;
+#define USBEH_BULK_LIST_ENABLE          0x20
+#define USBEH_BULK_LIST_FILLED          0x04
+#define USBEH_PERIODIC_LIST_ENABLE      0x04
+#define USBEH_PORT_RESET_STATUS         0x10
+#define USBEH_PORT_RESET_STATUS_CHANGE  (USBEH_PORT_RESET_STATUS << 16)
+#define USBEH_LOW_SPEED_DEVICE          0x200
+#define USBEH_HIGH_SPEED_DEVICE         0x400
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_api.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,290 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "usbeh_api.h"
+#include "usbeh_endpoint.h"
+#include "usbeh_device.h"
+#include "usbeh_controller.h"
+
+#include "main.h"
+#include "debug.h"
+
+/* Device driver headers. */
+#include "xbox360gamepad.h"
+
+#define DEBUG_USB_API 1
+
+USBEH_device_info_callback usb_devices_callback_map[] = {
+    (xbox360gamepad_onload_callback),
+    NULL
+};
+
+int usbeh_no_device_found(int device, USBEH_deviceDescriptor *deviceDesc, USBEH_interfaceDescriptor **interfaceDesc) {
+    USBEH_interfaceDescriptor *iface;
+    int interfaceCounter = 0;
+    debug_printf("%s CALLBACK ACTIVATED for device %d\r\n", __FUNCTION__, device);
+    debug_printf("  VendorId = %04X ProductId = %04X \r\n", deviceDesc->idVendor, deviceDesc->idProduct);
+    while ((iface = interfaceDesc[interfaceCounter]) != (USBEH_interfaceDescriptor *)NULL) { 
+        debug_printf("  interface%d:- \r\n", interfaceCounter);
+        debug_printf("    InterfaceClass    = %02X \r\n", iface->bInterfaceClass);
+        debug_printf("    InterfaceSubClass = %02X \r\n", iface->bInterfaceSubClass);
+        debug_printf("    InterfaceProtocol = %02X \r\n", iface->bInterfaceProtocol);
+        interfaceCounter++;
+    }
+    debug_printf("  No device driver loaded.\r\n");
+    return 0;
+}
+
+/* Create an instance of the USBEH controller and place
+   it within the AHB static ram area. */
+USBEH_Controller sys_usb_controller __attribute__((at(0x2007C000)));
+
+
+void usbeh_api_on_load_device(int device, USBEH_deviceDescriptor* deviceDesc, USBEH_interfaceDescriptor **interfaceDesc) {
+    int i, slen, driver_loaded = 0;
+    char s[3][128];
+    
+    memset((char *)s, 0, 3 * 128);
+    
+    /* Get device strings. */    
+    for (i = 1; i < 3; i++) {
+        slen = usbeh_api_get_string(device, i, s[i - 1], 128);
+        if (slen < 0) {
+            break;
+        }
+    }
+ 
+    /* Scan through the device driver onLoad callbacks to see who wants to claim it. */
+    for (i = 0; usb_devices_callback_map[i] != NULL && driver_loaded == 0; i++) {
+        driver_loaded = (usb_devices_callback_map[i])(device,deviceDesc,interfaceDesc);
+    }
+    
+    if (driver_loaded == 0) {
+        usbeh_no_device_found(device, deviceDesc, interfaceDesc);
+    }
+}
+
+int usbeh_api_init(void) {
+    DEBUG_INIT_START;
+    sys_usb_controller.init();
+    DEBUG_INIT_END;
+    return 0;
+}
+
+void usbeh_api_process(void) {
+    sys_usb_controller.process();
+}
+
+int usbeh_api_set_address(int device, int new_addr) {
+    return usbeh_api_control_transfer(device, USBEH_HOST_TO_DEVICE | USBEH_RECIPIENT_DEVICE, USBEH_SET_ADDRESS, new_addr, 0, 0, 0, 0, 0);
+}
+
+int usbeh_api_get_descriptor(int device, int descType,int descIndex, USBEH_U08* data, int length) {
+    return usbeh_api_control_transfer(device, USBEH_DEVICE_TO_HOST | USBEH_RECIPIENT_DEVICE, USBEH_GET_DESCRIPTOR, (descType << 8)|(descIndex), 0, data, length, 0, 0);
+}
+
+static USBEH_Setup* usbeh_api_get_setup(int device) {
+    if (device == 0) {
+        return &sys_usb_controller.setupZero;
+    }
+    
+    if (device < 1 || device > USBEH_MAX_DEVICES) {
+        return 0;
+    }
+    
+    return &sys_usb_controller.devices[device-1].setupBuffer;
+}
+
+static int usbeh_api_wait_IO_done(USBEH_Endpoint* endpoint) {
+
+    if (endpoint->currentState == USBEH_Endpoint::notQueued) {
+        return 0;
+    }
+    
+    while (endpoint->currentState != USBEH_Endpoint::idle) {
+        usbeh_api_process();
+    }
+    
+    int status = endpoint->status();
+    if (status == 0) {
+        return endpoint->length;
+    }
+
+    #ifdef DEBUG_USB_DRIVER
+    debug_printf("usbeh_api_wait_IO_done() error with 0x%x at line %d\r\n", status, __LINE__);
+    #endif
+    
+    return -status;
+}
+
+
+int usbeh_api_get_port_status(int device, int port, USBEH_U32 *status) {
+    return usbeh_api_control_transfer_short(device, USBEH_DEVICE_TO_HOST | USBEH_REQUEST_TYPE_CLASS | USBEH_RECIPIENT_OTHER, USBEH_GET_STATUS, 0, port, (USBEH_U08 *)status, 4);    
+}
+
+int usbeh_api_clear_port_feature(int device, int feature, int index) {
+    return usbeh_api_control_transfer(device, USBEH_HOST_TO_DEVICE | USBEH_REQUEST_TYPE_CLASS | USBEH_RECIPIENT_OTHER, USBEH_CLEAR_FEATURE, feature, index, 0, 0, 0, 0);
+}
+
+int usbeh_api_set_port_power(int device, int port) {
+    int result = usbeh_api_set_port_feature(device, USBEH_PORT_POWER, port);
+    USBEH_OS_DELAY_MS(20);
+    return result;
+}
+
+int usbeh_api_set_port_feature(int device, int feature, int index) {
+    return usbeh_api_control_transfer(device, USBEH_HOST_TO_DEVICE | USBEH_REQUEST_TYPE_CLASS | USBEH_RECIPIENT_OTHER, USBEH_SET_FEATURE, feature, index, 0, 0, 0, 0);
+}
+
+int usbeh_api_set_configuration(int device, int configNum) {
+    return usbeh_api_control_transfer(device, USBEH_HOST_TO_DEVICE | USBEH_RECIPIENT_DEVICE, USBEH_SET_CONFIGURATION, configNum, 0, 0, 0, 0, 0);
+}
+
+int usbeh_api_set_port_reset(int device, int port) {
+    return usbeh_api_set_port_feature(device, USBEH_PORT_RESET, port);
+}
+
+int usbeh_api_get_string(int device, int index, char *dst, int length) {
+    
+    USBEH_U08 buffer[255];
+    
+    int le = usbeh_api_get_descriptor(device, USBEH_DESCRIPTOR_TYPE_STRING, index, buffer, sizeof(buffer));
+    
+    if (le < 0) {
+        return le;
+    }
+    
+    if (length < 1) {
+        return -1;
+    }
+    
+    length <<= 1;
+    
+    if (le > length) {
+        le = length;
+    }
+    
+    for (int j = 2; j < le; j += 2) {
+        *dst++ = buffer[j];
+    }
+    
+    *dst = 0;
+    
+    return (le >> 1) - 1;
+}
+
+int usbeh_api_transfer(int device, int ep, USBEH_U08 flags, USBEH_U08 *data, int length, USBEH_callback callback, void *userData) {
+    USBEH_Endpoint *endpoint = sys_usb_controller.getEndpoint(device, ep);
+    if (!endpoint) {
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("sys_usb_controller.getEndpoint() failed at line %d\r\n", __LINE__);
+        #endif
+        return USBEH_ERR_ENDPOINT_NOT_FOUND;
+    }
+        
+    usbeh_api_wait_IO_done(endpoint);
+    
+    endpoint->flags = flags;
+    endpoint->data = data;
+    endpoint->length = length;
+    endpoint->callback = callback;
+    endpoint->userData = userData;
+    
+    if (ep == 0) {
+        sys_usb_controller.transfer(endpoint, USBEH_TOKEN_SETUP, (USBEH_U08 *)usbeh_api_get_setup(device), 8, USBEH_Endpoint::setupQueued);
+    }
+    else {
+        sys_usb_controller.transfer(endpoint, flags & 0x80 ? USBEH_TOKEN_IN : USBEH_TOKEN_OUT, data, length, USBEH_Endpoint::dataQueued);
+    }
+    
+    if (callback) {
+        return USBEH_IO_PENDING;
+    }
+    
+    return usbeh_api_wait_IO_done(endpoint);
+}
+
+int usbeh_api_interrupt_transfer(int device, int ep, USBEH_U08 *data, int length, USBEH_callback callback, void *userData) {
+    return usbeh_api_transfer(device, ep, (ep & 0x80) | USBEH_ENDPOINT_INTERRUPT, data, length, callback, userData);
+}
+
+int usbeh_api_control_transfer_short(int device, int request_type, int request, int value, int index, USBEH_U08 *data, int length) {
+    return usbeh_api_control_transfer(device, request_type, request, value, index, data, length, 0, 0);
+}
+
+int usbeh_api_control_transfer(int device, int request_type, int request, int value, int index, USBEH_U08 *data, int length, USBEH_callback callback, void *userData) {
+    USBEH_Setup* setup = usbeh_api_get_setup(device);
+    if (!setup) {
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("usbeh_api_get_setup() failed at line %d\r\n", __LINE__);
+        #endif
+        return USBEH_ERR_DEVICE_NOT_FOUND;
+    }
+        
+    usbeh_api_wait_IO_done(sys_usb_controller.getEndpoint(device,0));
+    
+    setup->bm_request_type = request_type;
+    setup->b_request = request;
+    setup->w_value = value;
+    setup->w_index = index;
+    setup->w_length = length;
+
+    return usbeh_api_transfer(device, 0, request_type & USBEH_DEVICE_TO_HOST, data, length, callback, userData);
+}
+
+void usbeh_sof_counter_init(USBEH_SOF_COUNTER *q, USBEH_U08 mode, USBEH_U32 count) {
+    q->mode     = mode;
+    q->flag     = 0;
+    q->counter  = count;
+    q->reload   = count;
+    q->callback = NULL;
+    q->next     = NULL;
+}
+
+extern USBEH_SOF_COUNTER   *sof_counter_head;
+void usbeh_sof_counter_register(USBEH_SOF_COUNTER *q) {
+    q->next = sof_counter_head;
+    sof_counter_head = q;
+}
+
+void usbeh_sof_counter_unregister(USBEH_SOF_COUNTER *q) {
+    USBEH_SOF_COUNTER *list;
+    for (list = sof_counter_head; list != NULL; list = list->next) {
+        if (list->next == q) {
+            list->next = q->next;
+            return;
+        }
+    }
+}
+
+
+void usbeh_api_list_endpoints(void) {
+    debug_printf("List system endpoints\r\n");
+    for (int i = 0; i < USBEH_MAX_ENDPOINTS_TOTAL; i++) {
+        printf("Index %d: 0x%02X Status:%02X State:%d\r\n", i, 
+            sys_usb_controller.endpoints[i].address(), 
+            sys_usb_controller.endpoints[i].status(), 
+            sys_usb_controller.endpoints[i].currentState
+        ); 
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_api.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,68 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef USBEH_API_H
+#define USBEH_API_H
+
+#include "usbeh.h"
+#include "usbeh_endpoint.h"
+#include "usbeh_device.h"
+#include "usbeh_controller.h"
+
+/* Define a callback for device driver OnLoad handlers. 
+   Cast *info as (USBEH_DEVICE_INFO *) as that's what 
+   will be passed. */
+typedef int (*USBEH_device_info_callback)(int device, USBEH_deviceDescriptor *deviceDesc, USBEH_interfaceDescriptor **interfaceDesc);
+
+/* Called for a device insertion. Define the driver in this function. */
+void usbeh_api_on_load_device(int device, USBEH_deviceDescriptor* deviceDesc, USBEH_interfaceDescriptor **interfaceDesc);
+
+/* Local statics. */
+static USBEH_Setup* usbeh_api_get_setup(int device);
+static int usbeh_api_wait_IO_done(USBEH_Endpoint* endpoint);
+
+/* The exported API. */
+int usbeh_api_init(void);
+void usbeh_api_process(void);
+int usbeh_api_set_address(int device, int new_addr);
+int usbeh_api_get_descriptor(int device, int descType,int descIndex, USBEH_U08* data, int length);
+int usbeh_api_get_string(int device, int index, char *dst, int length);
+int usbeh_api_get_port_status(int device, int port, USBEH_U32 *status);
+int usbeh_api_clear_port_feature(int device, int feature, int index);
+int usbeh_api_set_port_feature(int device, int feature, int index);
+int usbeh_api_set_port_power(int device, int port);
+int usbeh_api_set_configuration(int device, int configNum);
+int usbeh_api_set_port_reset(int device, int port);
+int usbeh_api_transfer(int device, int ep, USBEH_U08 flags, USBEH_U08 *data, int length, USBEH_callback callback, void* userData);
+int usbeh_api_interrupt_transfer(int device, int ep, USBEH_U08* data, int length, USBEH_callback callback, void* userData);
+int usbeh_api_control_transfer_short(int device, int request_type, int request, int value, int index, USBEH_U08 *data, int length);
+int usbeh_api_control_transfer(int device, int request_type, int request, int value, int index, USBEH_U08 *data, int length, USBEH_callback callback, void *userData);
+
+void usbeh_sof_counter_init(USBEH_SOF_COUNTER *q, USBEH_U08 mode, USBEH_U32 count);
+void usbeh_sof_counter_register(USBEH_SOF_COUNTER *q);
+void usbeh_sof_counter_unregister(USBEH_SOF_COUNTER *q);
+
+/* Debugging. */
+void usbeh_api_list_endpoints(void);
+
+// END #ifndef USBEH_API_H
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_controller.cpp	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,602 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "usbeh_endpoint.h"
+#include "usbeh_device.h"
+#include "usbeh_controller.h"
+#include "usbeh_api.h"
+
+#include "main.h"
+#include "debug.h"
+
+void USBEH_Controller::process(void) {
+    USBEH_Endpoint *endpoint;
+    USBEH_U16 elapsed = hcca.frameNumber - (USBEH_U16)this->frameNumber;
+    this->frameNumber += elapsed;
+    
+    while (this->callbacksPending) {
+        for (int i = 0; i < USBEH_MAX_ENDPOINTS_TOTAL; i++) {
+            endpoint = this->endpoints + i;
+            if (endpoint->currentState == USBEH_Endpoint::callbackPending) {
+                this->callbacksPending--;
+                endpoint->currentState = USBEH_Endpoint::idle;
+                endpoint->callback(
+                    endpoint->device(),
+                    endpoint->address(),
+                    endpoint->status(),
+                    (USBEH_U08 *)endpoint->userData,
+                    endpoint->length,
+                    endpoint->userData);
+            }
+        }
+    }
+    
+    if (this->rootHubStatusChange) {
+        USBEH_U32 status = USBEH_HcRhPortStatus1;
+        this->rootHubStatusChange = 0;
+        if (status >> 16) {
+            hubStatusChange(0, 1, status);
+            USBEH_HcRhPortStatus1 = status & 0xFFFF0000;
+        }
+    }
+    
+    if (this->connectCountdown) {
+        if (elapsed >= this->connectCountdown) {
+            this->connectCountdown = 0;
+            connect(this->connectHub, this->connectPort & 0x7F, this->connectPort & 0x80);
+        }
+        else {
+            this->connectCountdown -= elapsed;
+        }
+    } 
+}
+
+void USBEH_Controller::init(void) {
+    memset(this, 0, sizeof(USBEH_Controller));
+    endpointZero.currentState = USBEH_Endpoint::notQueued;
+    initHW(&hcca);
+    delayMS(10);
+}
+
+void USBEH_Controller::hubInterrupt(int device) {
+    USBEH_Device *dev = &devices[device - 1];
+    
+    for (int i = 0; i < dev->hubPortCount; i++) {
+        int port = i + 1;
+        if (dev->hubInterruptData * (1 << port)) {
+            USBEH_U32 status = 0;
+            usbeh_api_get_port_status(device, port, &status);
+            if (status >> 16) {
+                if (connectPending && (status & USBEH_CONNECT_STATUS_CHANGE)) {
+                    hubStatusChange(device, port, status);
+                    if (status & USBEH_CONNECT_STATUS_CHANGE) {
+                        usbeh_api_clear_port_feature(device, USBEH_C_PORT_CONNECTION, port);
+                    }    
+                    if (status & USBEH_PORT_RESET_STATUS_CAHNGE) {
+                        usbeh_api_clear_port_feature(device, USBEH_C_PORT_RESET, port);
+                    }
+                }
+            }
+        }
+    }
+}
+
+void USBEH_Controller::hubInterruptCallback(int device, int endpoint, int status, USBEH_U08 *data, int length, void *userData) {
+    USBEH_Controller *controller = (USBEH_Controller *)userData;
+    if (status == 0) {
+        controller->hubInterrupt(device);
+    }
+    usbeh_api_interrupt_transfer(device, endpoint, data, 1, hubInterruptCallback, userData);
+}
+
+int USBEH_Controller::initHub(int device) {
+    USBEH_U08 buffer[16];
+    int r = usbeh_api_control_transfer(device, USBEH_DEVICE_TO_HOST | USBEH_REQUEST_TYPE_CLASS | USBEH_RECIPIENT_DEVICE, USBEH_GET_DESCRIPTOR, (USBEH_DESCRIPTOR_TYPE_HUB << 8), 0, buffer, sizeof(buffer), 0, 0);
+    if (r < 0) return -1;
+    
+    USBEH_Device *dev = &this->devices[device - 1];
+    
+    int ports = buffer[2];
+    
+    for (int i = 0; i < ports; i++) {
+        usbeh_api_set_port_power(device, i + 1);
+    }
+    
+    return usbeh_api_interrupt_transfer(device, 0x81, &dev->hubInterruptData,1, hubInterruptCallback, this); 
+}
+
+int USBEH_Controller::transfer(USBEH_Endpoint *endpoint, int token, USBEH_U08 *data, int len, int state) {
+   
+    int toggle = 0;
+    
+    if (endpoint->address() == 0) {
+        toggle = (token == USBEH_TOKEN_SETUP) ? USBEH_TD_TOGGLE_0 : USBEH_TD_TOGGLE_1;
+    }
+    
+    if (token != USBEH_TOKEN_SETUP) {
+        token = (token == USBEH_TOKEN_IN ? USBEH_TD_IN : USBEH_TD_OUT);
+    }
+    
+    USBEH_HCTD *head = &endpoint->tdHead;
+    USBEH_HCTD *tail = &this->commonTail;
+    
+    head->control = USBEH_TD_ROUNDING | token | USBEH_TD_DELAY_INT(0) | toggle | USBEH_TD_CC;
+    head->currentBufferPointer = (USBEH_U32)data;
+    head->bufferEnd = (USBEH_U32)(data + len - 1);
+    head->next = (USBEH_U32)tail;
+   
+    USBEH_HCED *ed = &endpoint->endpointDescriptor;
+    ed->headTd = (USBEH_U32)head | (ed->headTd & 0x00000002);
+    ed->tailTd = (USBEH_U32)tail;
+    
+    switch (endpoint->flags & 3) {
+        case USBEH_ENDPOINT_CONTROL:
+            USBEH_HcControlHeadED = endpoint->queue(USBEH_HcControlHeadED);
+            endpoint->currentState = state;
+            USBEH_HcCommandStatus = USBEH_HcCommandStatus | USBEH_CONTROL_LIST_FILLED;
+            USBEH_HcControl |= USBEH_CONTROL_LIST_ENABLE;
+            break;
+        case USBEH_ENDPOINT_BULK:
+            USBEH_HcBulkHeadED = endpoint->queue(USBEH_HcBulkHeadED);
+            endpoint->currentState = state;
+            USBEH_HcCommandStatus = USBEH_HcCommandStatus | USBEH_BULK_LIST_FILLED;
+            USBEH_HcControl |= USBEH_BULK_LIST_ENABLE;
+            break;
+        case USBEH_ENDPOINT_INTERRUPT:
+            hcca.interruptTable[0] = endpoint->queue(hcca.interruptTable[0]);
+            endpoint->currentState = state;
+            USBEH_HcControl |= USBEH_PERIODIC_LIST_ENABLE;
+            break;
+    }
+    
+    return 0;
+}
+
+bool USBEH_Controller::remove(USBEH_HCED *ed, volatile USBEH_HCED **queue) {
+    if (*queue == 0) return false;
+    if (*queue == (volatile USBEH_HCED *)ed) {
+        *queue = (volatile USBEH_HCED *)ed->next;
+        return true;    
+    }
+    
+    volatile USBEH_HCED *head = *queue;
+    while (head) {
+        if (head->next == (USBEH_U32)ed) {
+            head->next = ed->next;
+            return true;
+        }
+        head = (volatile USBEH_HCED *)head->next;
+    }
+    
+    return false;
+}
+
+void USBEH_Controller::release(USBEH_Endpoint *endpoint) {
+    if (endpoint->currentState != USBEH_Endpoint::notQueued) {
+        USBEH_HCED *ed = (USBEH_HCED *)endpoint;
+        ed->control |= 0x4000;
+        switch (endpoint->flags & 0x3) {
+            case USBEH_ENDPOINT_CONTROL:
+                remove(ed, (volatile USBEH_HCED **)&USBEH_HcControlHeadED);
+                break;
+            case USBEH_ENDPOINT_BULK:
+                remove(ed, (volatile USBEH_HCED **)&USBEH_HcBulkHeadED);
+                break;
+            case USBEH_ENDPOINT_INTERRUPT:
+                for (int i = 0; i < 32; i++) {
+                    remove(ed, (volatile USBEH_HCED **)&hcca.interruptTable[i]);
+                }
+                break;
+        }
+        
+        USBEH_U16 fn = hcca.frameNumber;
+        while (fn == hcca.frameNumber) ;
+    }
+    
+    memset(endpoint, 0, sizeof(USBEH_Endpoint));
+}
+
+int USBEH_Controller::addEndpoint(int device, USBEH_endpointDescriptor *endpoint) {
+    return addEndpoint(device, endpoint->bEndpointAddress, endpoint->bmAttributes, endpoint->wMaxPacketSize, endpoint->bInterval);
+}
+
+int USBEH_Controller::addEndpoint(int device, int endpoint, int attributes, int maxPacketSize, int interval) {
+    USBEH_Device *dev = &this->devices[device - 1];
+    USBEH_Endpoint *ep = allocateEndpoint(device, endpoint, attributes, maxPacketSize);
+    if (!ep) {
+        return -1;
+    }
+    dev->setEndpointIndex(endpoint, ep - this->endpoints);
+    ep->endpointDescriptor.control |= dev->flags;
+    return 0;
+
+}
+
+USBEH_Endpoint * USBEH_Controller::allocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize) {
+    for (int i = 0; i < USBEH_MAX_ENDPOINTS_TOTAL; i++) {
+        USBEH_Endpoint *ep = &this->endpoints[i];
+        if (ep->currentState == 0) {
+            ep->flags = (endpointAddress & 0x80) | (type & 0x3);
+            ep->currentState = USBEH_Endpoint::notQueued;
+            ep->endpointDescriptor.control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device;
+            return ep;
+        }
+    }
+    return 0;
+}
+
+int USBEH_Controller::addDevice(int hub, int port, bool isLowSpeed) {
+    int device = addDeviceCore(hub, port, isLowSpeed);
+    if (device < 0) {
+        disconnect(hub, port);
+        resetPort(hub, port);
+        return -1;
+    }
+    return device;
+}
+
+int USBEH_Controller::addDeviceCore(int hub, int port, bool isLowSpeed) {
+    
+    int lowSpeed = isLowSpeed ? 0x2000 : 0;
+    
+    USBEH_deviceDescriptor desc;
+    
+    endpointZero.endpointDescriptor.control = (8 << 16) | lowSpeed;
+    
+    int result = usbeh_api_get_descriptor(0, USBEH_DESCRIPTOR_TYPE_DEVICE, 0, (USBEH_U08 *)&desc, 8);
+        
+    if (result < 0) {
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("usbeh_api_get_descriptor() failed with %d (0x%x) at line %d\r\n", result, result, __LINE__);
+        #endif
+        return result;
+    }
+    
+    endpointZero.endpointDescriptor.control = (desc.bMaxPacketSize << 16) | lowSpeed;
+    
+    result = usbeh_api_get_descriptor(0, USBEH_DESCRIPTOR_TYPE_DEVICE, 0, (USBEH_U08 *)&desc, sizeof(desc));
+    if (result < 0) {
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("usbeh_api_get_descriptor() failed with %d at line %d\r\n", result, __LINE__);
+        #endif
+        return result;
+    }
+    
+    int device = 0;
+    for (int i = 0; i < USBEH_MAX_DEVICES; i++) {
+        if (devices[i].port == 0) {
+            device = i + 1;
+            break;
+        }
+    }
+    
+    if (!device) {
+        return -1;
+    }
+    
+    result = usbeh_api_set_address(0, device);
+    if (result) {
+        return result;
+    }
+    
+    delayMS(2);
+    
+    USBEH_Device *dev = &devices[device - 1];
+    dev->init(&desc, hub, port, device, lowSpeed);
+    addEndpoint(device, 0, USBEH_ENDPOINT_CONTROL, desc.bMaxPacketSize, 0);
+    this->connectPending = 0;
+    
+    if ((result = usbeh_api_get_descriptor(device, USBEH_DESCRIPTOR_TYPE_DEVICE, 0, (USBEH_U08 *)&desc, sizeof(desc))) < 0) {
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("usbeh_api_get_descriptor() failed with %d at line %d\r\n", result, __LINE__);
+        #endif
+        return result;
+    }
+    
+    result = setConfigurationAndInterface(device, 1, -1, &desc);
+    
+    if (desc.bDeviceClass == CLASS_HUB) {
+        initHub(device);
+    }
+    
+    return device;
+}
+
+int USBEH_Controller::setConfigurationAndInterface(int device, int configuration, int interfaceNumber, USBEH_deviceDescriptor *desc) {
+    USBEH_U08 buffer[255];
+    USBEH_interfaceDescriptor *found[16];
+    USBEH_endpointDescriptor *ed;
+    
+    for (int i = 0; i < 16; i++) {
+        found[i] = (USBEH_interfaceDescriptor *)NULL;
+    }
+    
+    int err = usbeh_api_get_descriptor(device, USBEH_DESCRIPTOR_TYPE_CONFIGURATION, 0, buffer, sizeof(buffer));
+    if (err < 0) {
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("GET_DESCRIPTOR failed at line %d\r\n", __LINE__);
+        #endif
+        return err;
+    }
+    
+    err = usbeh_api_set_configuration(device, configuration);
+    if (err < 0) {
+        return err;
+    }
+    
+    int interfaceCounter = 0;
+    int len        = buffer[2] | (buffer[3] << 8);
+    USBEH_U08 *d   = buffer;
+    USBEH_U08 *end = d + len;
+    while (d < end) {
+        //printf("Testing descriptor type %02x\n\r", d[1]);
+        if (d[1] == USBEH_DESCRIPTOR_TYPE_INTERFACE) {
+            //printf("  Found interface descriptor type %02x\n\r", d[1]);
+            USBEH_interfaceDescriptor *id = (USBEH_interfaceDescriptor *)d;
+            if (interfaceNumber == -1 || id->bInterfaceNumber == interfaceNumber) {
+                found[interfaceCounter++] = id;
+                d += d[0];
+                while (d < end && d[1] != USBEH_DESCRIPTOR_TYPE_INTERFACE) {
+                    switch (d[1]) {
+                        case USBEH_DESCRIPTOR_TYPE_ENDPOINT:
+                            ed = (USBEH_endpointDescriptor *)d;
+                            //printf("  Adding endpoint 0x%02x for interface %d\r\n", ed->bEndpointAddress, id->bInterfaceNumber);
+                            addEndpoint(device, ed);
+                            break;
+                        default:
+                            // Skip unknown descriptor.
+                            //printf("  Unknown descriptor type: %02x\r\n", d[1]);
+                            break;
+                    }
+                    d += d[0];
+                }
+            }
+        }
+        else {
+            d += d[0];
+        }
+    }
+    
+    if (interfaceCounter == 0) {
+        return USBEH_ERR_INTERFACE_NOT_FOUND;
+    }
+    
+    usbeh_api_on_load_device(device, desc, found);
+    
+    return 0;
+}
+
+void USBEH_Controller::processDoneQueue(USBEH_U32 tdList) {
+    USBEH_Endpoint *endpoint;
+    USBEH_HCTD *list = reverse((USBEH_HCTD *)tdList);
+    while (list) {
+        endpoint = (USBEH_Endpoint *)(list - 1);
+        list = (USBEH_HCTD *)list->next;
+        int ep = endpoint->address();
+        bool in = endpoint->flags & 0x80;
+        int status = (endpoint->tdHead.control >> 28) & 0xF;
+        
+        if (status != 0) {
+            endpoint->currentState = USBEH_Endpoint::idle;
+        }
+        else {
+            switch (endpoint->currentState) {
+                case USBEH_Endpoint::setupQueued:
+                    if (endpoint->length == 0) {
+                        transfer(endpoint, in ? USBEH_TOKEN_OUT : USBEH_TOKEN_IN, 0, 0, USBEH_Endpoint::statusQueued);
+                    }
+                    else {
+                        transfer(endpoint, in ? USBEH_TOKEN_IN : USBEH_TOKEN_OUT, (USBEH_U08 *)endpoint->data, endpoint->length, USBEH_Endpoint::dataQueued);
+                    }
+                    break;
+                    
+                case USBEH_Endpoint::dataQueued:
+                    if (endpoint->tdHead.currentBufferPointer) {
+                        endpoint->length = endpoint->tdHead.currentBufferPointer - (USBEH_U32)endpoint->data;
+                    }
+                    
+                    if (ep == 0) {
+                        transfer(endpoint, in ? USBEH_TOKEN_OUT : USBEH_TOKEN_IN, 0, 0, USBEH_Endpoint::statusQueued);
+                    }
+                    else {
+                        endpoint->currentState = USBEH_Endpoint::idle;    
+                    }
+                    break;
+                    
+                case USBEH_Endpoint::statusQueued:
+                    endpoint->currentState = USBEH_Endpoint::idle;    
+                    break;
+            }
+        }
+        
+        if (endpoint->callback && endpoint->currentState == USBEH_Endpoint::idle) {
+            //if (endpoint->address() != 0x81) printf("\r\nCallback pending for 0x%02X\r\n", endpoint->address());
+            endpoint->currentState = USBEH_Endpoint::callbackPending;
+            this->callbacksPending++;
+        }
+    }
+}
+
+void USBEH_Controller::resetPort(int hub, int port) {
+    this->connectPending++;
+    if (hub == 0) {
+        USBEH_HcRhPortStatus1 = USBEH_PORT_RESET_STATUS;
+    }
+    else {
+        usbeh_api_set_port_reset(hub, port);
+    }
+}
+
+void USBEH_Controller::connect(int hub, int port, bool lowSpeed) {
+    #ifdef DEBUG_USB_DRIVER
+    debug_printf("%s called at line %d\r\n", __FUNCTION__, __LINE__);
+    #endif
+    addDevice(hub, port, lowSpeed);
+}
+
+void USBEH_Controller::disconnect(int hub, int port) {
+    for (int i = 0; i < USBEH_MAX_DEVICES; i++) {
+        USBEH_Device *dev = this->devices + i;
+        if (dev->port == port && dev->hub == hub) {
+            for (int p = 0; p < dev->hubPortCount; p++) {
+                disconnect(i + 1, p + 1);
+            }
+            for (int j = 1; j < USBEH_MAX_ENDPOINTS_PER_DEVICE * 2; j += 2) {
+                USBEH_U08 endpointIndex = dev->endpoints[j];
+                if (endpointIndex != 0xFF) {
+                    release(this->endpoints + endpointIndex);
+                }
+                dev->port = 0;
+                dev->flags = 0;
+                return;
+            }
+        }
+    }
+}
+
+void USBEH_Controller::hubStatusChange(int hub, int port, USBEH_U32 status) {
+    if (status & USBEH_CONNECT_STATUS_CHANGE) {
+        if (status & USBEH_CURRENT_CONNECT_STATUS) {
+            resetPort(hub, port);
+        }
+        else {
+            disconnect(hub, port);
+        }
+    }
+    
+    if (status & USBEH_PORT_RESET_STATUS_CHANGE) {
+        if (!(status & USBEH_PORT_RESET_STATUS)) {
+            this->connectCountdown = 200;
+            if (status & USBEH_LOW_SPEED_DEVICE) {
+                port |= 0x80;
+            }
+            this->connectHub = hub;
+            this->connectPort = port;
+        }
+    }
+}
+
+void USBEH_Controller::delayMS(int ms) {
+    USBEH_U16 f = ms + hcca.frameNumber;
+    while (f != hcca.frameNumber) ;
+}
+
+void USBEH_Controller::initHW(USBEH_HCCA *cca) {
+    NVIC_DisableIRQ(USB_IRQn);
+    
+    LPC_SC->PCONP           |= (1UL << 31);
+    LPC_USB->USBClkCtrl     |= USBEH_CLOCK_MASK;
+    while ((LPC_USB->USBClkSt & USBEH_CLOCK_MASK) != USBEH_CLOCK_MASK);
+    
+    USBEH_OTGStCtrl |= 1;
+    USBEH_USBClkCtrl &= ~USBEH_PORTSEL_CLK_EN;
+    
+    LPC_PINCON->PINSEL1 &= ~( (3<<26) | (3<<28) );    
+    LPC_PINCON->PINSEL1 |=  ( (1<<26) | (1<<28));
+    
+    USBEH_HcControl = 0;
+    USBEH_HcControlHeadED = 0;
+    USBEH_HcBulkHeadED = 0;
+    USBEH_HcCommandStatus = USBEH_HOST_CONTROLLER_RESET;
+    USBEH_HcFmInterval = USBEH_DEFAULT_FMINTERVAL;
+    USBEH_HcPeriodicStart = USBEH_FRAMEINTERVAL * 90 / 100;
+    
+    USBEH_HcControl = (USBEH_HcControl & (~USBEH_HOST_CONTROLLER_FUNCTIONAL_STATE)) | USBEH_OPERATIONAL_MASK;
+    USBEH_HcRhStatus = USBEH_SET_GLOBAL_POWER;
+    
+    USBEH_HcHCCA = (USBEH_U32)cca;
+    USBEH_HcInterruptStatus |= USBEH_HcInterruptStatus;
+    USBEH_HcInterruptEnable |= USBEH_MASTER_IRQ_ENABLE | USBEH_WRITEBACK_DONE_HEAD | USBEH_ROOT_HUB_STATUS_CHANGE | USBEH_FRAME_NUMBER_OVERFLOW | USBEH_START_OF_FRAME;
+    
+    NVIC_EnableIRQ(USB_IRQn);
+    while (cca->frameNumber < 10);
+}
+
+USBEH_HCTD * USBEH_Controller::reverse(USBEH_HCTD *current) {
+    USBEH_HCTD *result = NULL, *temp;
+    while (current) {
+        temp = (USBEH_HCTD *)current->next;
+        current->next = (USBEH_U32)result;
+        result = current;
+        current = temp;
+    }
+    return result;
+}
+
+USBEH_Endpoint * USBEH_Controller::getEndpoint(int device, int ep) {
+    if (device == 0) {
+        return &endpointZero;
+    }
+    if (device > USBEH_MAX_DEVICES) {
+        return 0;
+    }
+    int i = devices[device - 1].getEndpointIndex(ep);
+    if (i == -1) {
+        return 0;
+    }
+    return endpoints + i;
+}
+
+/* The controller is defined withinn the API section. */
+extern USBEH_Controller sys_usb_controller;
+
+USBEH_SOF_COUNTER   *sof_counter_head = NULL;
+
+/* The USB interrupt handler. */
+extern "C" void USB_IRQHandler (void) __irq {
+
+    USBEH_U32 int_status = USBEH_HcInterruptStatus;
+  
+    if (int_status & USBEH_ROOT_HUB_STATUS_CHANGE) {
+        sys_usb_controller.rootHubStatusChange++;  
+    }
+
+    USBEH_U32 head = 0;
+    
+    if (int_status & USBEH_WRITEBACK_DONE_HEAD) {
+        head = sys_usb_controller.hcca.doneHead;
+        sys_usb_controller.hcca.doneHead = 0;
+    }
+    
+    if (int_status & USBEH_START_OF_FRAME) {
+        for (USBEH_SOF_COUNTER *list = sof_counter_head; list != NULL; list = list->next) {
+            if (list->mode & USBEH_SOF_COUNTER_DEC && list->flag == 0) {
+                if (list->counter > 0) list->counter--;
+                if (list->counter == 0) {
+                    list->flag = 1;
+                    list->counter = list->reload;
+                    if (list->callback != NULL) {
+                        (list->callback)((struct _sof_counter *)list);
+                    }
+                }   
+            }
+        }
+    }
+                 
+    USBEH_HcInterruptStatus = int_status;
+
+    if (head) {
+        sys_usb_controller.processDoneQueue(head);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_controller.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,82 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef USBEH_CONTROLLER_H
+#define USBEH_CONTROLLER_H
+
+#include "usbeh.h"
+#include "usbeh_device.h"
+#include "usbeh_endpoint.h"
+
+class USBEH_Controller {
+
+    public:
+    
+    USBEH_HCCA      hcca;
+    USBEH_Endpoint  endpoints[USBEH_MAX_ENDPOINTS_TOTAL];
+    USBEH_Endpoint  endpointZero;
+    USBEH_HCTD      commonTail;
+    USBEH_Setup     setupZero;
+    USBEH_Device    devices[USBEH_MAX_DEVICES];
+    
+    USBEH_U32       frameNumber;
+    USBEH_U08       callbacksPending;
+    USBEH_U08       rootHubStatusChange;
+    USBEH_U08       unused0;
+    USBEH_U08       unused1;
+    USBEH_U08       connectPending;
+    USBEH_U08       connectCountdown;
+    USBEH_U08       connectHub;
+    USBEH_U08       connectPort;
+    
+    USBEH_U08       SRAM[0];
+    
+    // Methods.
+    void    init(void);
+    void    process(void);
+    int     initHub(int device);
+    int     transfer(USBEH_Endpoint *endpoint, int token, USBEH_U08 *data, int length, int state);
+    bool    remove(USBEH_HCED *ed, volatile USBEH_HCED **queue);
+    void    release(USBEH_Endpoint *endpoint);
+    int     addEndpoint(int device, USBEH_endpointDescriptor *endpoint);
+    int     addEndpoint(int device, int endpoint, int attributes, int maxPacketSize, int interval);
+    int     addDevice(int hub, int port, bool isLowSpeed);
+    int     addDeviceCore(int hub, int port, bool isLowSpeed);
+    int     setConfigurationAndInterface(int device, int configuration, int interfaceNumber, USBEH_deviceDescriptor *desc);
+    void    processDoneQueue(USBEH_U32 tdList);
+    void    resetPort(int hub, int port);
+    void    connect(int hub, int port, bool lowSpeed);
+    void    disconnect(int hub, int port);
+    void    hubStatusChange(int hub, int port, USBEH_U32 status);
+    void    delayMS(int ms);
+    void    initHW(USBEH_HCCA *cca);
+    void    hubInterrupt(int device);
+    static void hubInterruptCallback(int device, int endpoint, int status, USBEH_U08 *data, int length, void *userData);
+    USBEH_HCTD * reverse(USBEH_HCTD *current);
+    USBEH_Endpoint * getEndpoint(int device, int ep);
+    USBEH_Endpoint * allocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize);
+
+};
+
+
+// END #ifndef USBEH_CONTROLLER_H
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_device.cpp	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,55 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "usbeh.h"
+#include "usbeh_endpoint.h"
+#include "usbeh_device.h"
+
+int USBEH_Device::init(USBEH_deviceDescriptor *d, int hub, int port, int addr, int lowSpeed) {
+    this->hub  = hub;
+    this->port = port;
+    this->addr = addr;
+    this->flags = lowSpeed;
+    memset(endpoints,0xFF,sizeof(endpoints));
+    return 0;    
+}
+
+
+int USBEH_Device::setEndpointIndex (int endpoint, int endpointIndex) {
+    for (int i = 0; i < 16; i += 2) {
+        if (endpoints[i] == 0xFF) {
+            endpoints[i+0] = endpoint;
+            endpoints[i+1] = endpointIndex;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+int USBEH_Device::getEndpointIndex (int endpoint) {
+    for (int i = 0; i < 16; i += 2) {
+        if (endpoints[i] == endpoint) return endpoints[i+1];
+        if (endpoints[i] == 0xFF) break;
+    }
+    return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_device.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,57 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef USBEH_DEVICE_H
+#define USBEH_DEVICE_H
+
+#ifndef USBEH_H
+#include "usbeh.h"
+#endif
+
+class USBEH_Device {
+
+    public:
+    
+    USBEH_U08   endpoints[16 * 2];
+    USBEH_U08   hub;
+    USBEH_U08   port;
+    USBEH_U08   addr;
+    USBEH_U08   pad;
+    
+    USBEH_U08   hubPortCount;
+    USBEH_U08   hubInterruptData;
+    USBEH_U08   hubMap;
+    USBEH_U08   hubMask;
+    
+    int         flags;
+    USBEH_Setup setupBuffer;
+    
+    // Member functions.
+    int init(USBEH_deviceDescriptor *d, int hub, int port, int addr, int lowSpeed);
+    int setEndpointIndex (int endpoint, int endpointIndex);
+    int getEndpointIndex (int endpoint);
+    
+};
+
+
+// END #ifndef USBEH_DEVICE_H
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_endpoint.cpp	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,50 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "usbeh.h"
+#include "usbeh_endpoint.h"
+
+int USBEH_Endpoint::address(void) {
+    int address = (endpointDescriptor.control >> 7) & 0xf;
+    if (address) {
+        address |= flags & 0x80;
+    }
+    return address;    
+}
+
+int USBEH_Endpoint::device(void) {
+    return endpointDescriptor.control & 0x7f;
+}
+
+int USBEH_Endpoint::status(void) {
+    return (tdHead.control >> 28) & 0xF;
+}
+
+USBEH_U32 USBEH_Endpoint::queue(USBEH_U32 head) {
+    if (currentState == notQueued) {
+        endpointDescriptor.next = head;
+        head = (USBEH_U32)&endpointDescriptor;
+        currentState = idle;
+    }   
+    return head;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/usbeh_endpoint.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,63 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef USBEH_ENDPOINT_H
+#define USBEH_ENDPOINT_H
+
+#ifndef USBEH_H
+#include "usbeh.h"
+#endif
+
+class USBEH_Endpoint {
+
+    public:
+    USBEH_HCED  endpointDescriptor;
+    USBEH_HCTD  tdHead;
+    
+    // State definitions.
+    enum state {
+        free,               // 0
+        notQueued,          // 1
+        idle,               // 2
+        setupQueued,        // 3
+        dataQueued,         // 4
+        statusQueued,       // 5
+        callbackPending     // 6
+    };
+
+    // Local data.
+    volatile USBEH_U08  currentState;
+    USBEH_U08           flags;
+    USBEH_U16           length;
+    USBEH_U08           *data;
+    USBEH_callback      callback;
+    void                *userData;
+    
+    // Member functions.
+    int address(void);
+    int device(void);
+    int status(void);
+    USBEH_U32 queue(USBEH_U32);
+};
+
+// END #ifndef USBEH_ENDPOINT_H
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/xbox360gamepad.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,707 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "sowb.h"
+#include "debug.h"
+#include "usbeh_api.h"
+#include "usbeh_endpoint.h"
+#include "usbeh_device.h"
+#include "usbeh_controller.h"
+#include "xbox360gamepad.h"
+
+#include "main.h"
+
+/* Define an array of data structures for the buttons. */
+static XBOX360_BUTTON buttons[16];
+static unsigned char button_buffer[16];
+static unsigned char button_buffer_in;
+static unsigned char button_buffer_out;
+
+/* Place holders for left and right triggers. */
+static unsigned char trigger_left;
+static unsigned char trigger_right;
+
+static XBOX360_STICK stick_left;
+static XBOX360_STICK stick_right;
+
+/* A map of wired Xbox 360 controllers. 
+   Data copied from the Linux xboxdrv project, thx :) 
+   http://pingus.seul.org/~grumbel/xboxdrv */
+static XBOX360_DEVICE xbox360_devices[] = {
+    { 0x045e, 0x028e, "Microsoft Xbox 360 Controller" },
+    { 0x0738, 0x4716, "Mad Catz Xbox 360 Controller" },
+    { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller" },
+    { 0x0738, 0x4740, "Mad Catz Beat Pad" },
+    { 0x0738, 0xf738, "Super SFIV FightStick TE S" },
+    { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick" },
+    { 0x0f0d, 0x000d, "Hori Fighting Stick Ex2" },
+    { 0x0f0d, 0x0016, "Hori Real Arcade Pro Ex" },
+    { 0x162e, 0xbeef, "Joytech Neo-Se Take2" },
+    { 0x046d, 0xc242, "Logitech ChillStream" },
+    { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360" },
+    { 0x0e6f, 0x0201, "Pelican TSZ360 Pad" },
+    { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2" }, // Here's one I found that isn't in the Linux distro.
+    { 0x0000, 0x0000, "End of list" }
+};
+
+/* Although Microsoft has not published any data or specifications
+   regarding the Xbox360 gamepad/controller, it's basic makeup is
+   well known. Define here the pipes for the interfaces we are
+   interested in. */
+
+#define XBOX360_GAMEPAD_PIPE_BUFFER_SIZE    32
+
+typedef struct {
+    USBEH_U08   data_in[XBOX360_GAMEPAD_PIPE_BUFFER_SIZE]; 
+    USBEH_U08   data_out[XBOX360_GAMEPAD_PIPE_BUFFER_SIZE];
+    USBEH_U08   ep_number_in;
+    USBEH_U08   ep_number_out;
+} XBOX360_PIPE;
+
+typedef struct {
+    USBEH_U08   data_in[256]; 
+    USBEH_U08   data_out[256];
+    USBEH_U08   ep_number_in;
+    USBEH_U08   ep_number_out;
+} XBOX360_CONTROL_PIPE;
+
+struct _xbox360_gamepad_vendor {
+    XBOX360_CONTROL_PIPE    pipe[1];
+} IF_VENDOR __attribute__((aligned(256)));
+   
+struct _xbox360_gamepad_interface0 {
+    XBOX360_PIPE    pipe[1];
+} IF_ZERO __attribute__((aligned(256)));
+
+struct _xbox360_gamepad_interface1 {
+    XBOX360_PIPE    pipe[2];
+} IF_ONE __attribute__((aligned(256)));
+
+struct _xbox360_gamepad_interface2 {
+    XBOX360_PIPE    pipe[1];
+} IF_TWO __attribute__((aligned(256)));
+
+int deviceNumber;
+
+int xbox360gamepad_init(void) {
+    DEBUG_INIT_START;
+    for (int i = 0; i < 16; i++) {
+        buttons[i].state = BUTTON_RELEASED;
+        buttons[i].count = 0;
+        button_buffer[i] = 0xFF;
+        usbeh_sof_counter_init(&buttons[i].pressHold, USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, BUTTON_HOLD_TIME);
+        buttons[i].pressHold.userData = i;
+        buttons[i].pressHold.callback = xbox360gamepad_button_hold_callback;
+        usbeh_sof_counter_register(&buttons[i].pressHold);
+    }
+    button_buffer_in  = 0;
+    button_buffer_out = 0;
+    trigger_left      = 0;
+    trigger_right     = 0;
+    stick_left.x      = 0;
+    stick_left.y      = 0;
+    stick_right.x     = 0;
+    stick_right.y     = 0;
+    DEBUG_INIT_END;
+    return 0;
+}
+
+void xbox360gamepad_process(void) {
+    // This currently does nothing.  
+}
+
+void xbox360gamepad_button_press(unsigned char button) {
+    button_buffer[button_buffer_in] = button;
+    button_buffer_in++;
+    button_buffer_in &= 0x0F;
+}
+
+char xbox360gamepad_get_button(void) {
+    if (button_buffer_in == button_buffer_out) {
+        return 0;
+    }
+    
+    char button = button_buffer[button_buffer_out];
+    button_buffer_out++;
+    button_buffer_out &= 0x0F;
+    return button;
+}
+
+char xbox360gamepad_get_button_preview(void) {
+    if (button_buffer_in == button_buffer_out) {
+        return 0;
+    }
+    
+    char button = button_buffer[button_buffer_out];
+    return button;
+}
+
+unsigned char xbox360gamepad_get_trigger_left(void) {
+    return trigger_left;
+}
+
+unsigned char xbox360gamepad_get_trigger_right(void) {
+    return trigger_right;
+}
+
+XBOX360_STICK * xbox360gamepad_get_stick_left(void) {
+    return &stick_left;
+}
+
+XBOX360_STICK * xbox360gamepad_get_stick_right(void) {
+    return &stick_right;
+}
+
+void xbox360gamepad_button_hold_callback(USBEH_SOF_COUNTER *q) {
+    int i = (int)q->userData;
+    if (buttons[i].state == BUTTON_PRESSED) {
+        xbox360gamepad_button_press((char)(i + 1 + 32));
+    }
+}
+    
+/** 
+ * xbox360gamepad_interface_0_in
+ *
+ * A callback function to handle interface0 pipe0 data.
+ */
+void xbox360gamepad_interface_0_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) {
+    unsigned button_flags;
+    
+    /* Is this a button press report? */
+    if(IF_ZERO.pipe[(int)userData].data_in[0] == 0 && IF_ZERO.pipe[(int)userData].data_in[1] == 0x14) {
+        
+        /* Handle the button flags. */
+        button_flags = ((IF_ZERO.pipe[(int)userData].data_in[2] & 0xFF) << 8) | (IF_ZERO.pipe[(int)userData].data_in[3] & 0xFF);
+        for (int i = 0; i < 16; i++) {
+            if ((button_flags & (1 << i)) != 0) {
+                if (buttons[i].state == BUTTON_RELEASED) {
+                    buttons[i].state = BUTTON_PRESSED;
+                    buttons[i].count++;
+                    buttons[i].pressHold.flag = 0;
+                    xbox360gamepad_button_press((char)(i + 1));
+                }
+            }
+            else {
+                if (buttons[i].state == BUTTON_PRESSED) {
+                    buttons[i].state = BUTTON_RELEASED;
+                    buttons[i].pressHold.flag = 1;
+                    buttons[i].pressHold.counter = BUTTON_HOLD_TIME;
+                    buttons[i].count = 0;
+                    xbox360gamepad_button_press((char)(i + 1 + 16));
+                }
+            }
+        }
+        
+        /* Handle the analogue triggers. */
+        trigger_left  = (unsigned char)IF_ZERO.pipe[(int)userData].data_in[4];
+        trigger_right = (unsigned char)IF_ZERO.pipe[(int)userData].data_in[5];
+        
+        /* Handle the analogue sticks. */
+        {
+            short x, y;
+            x = (short)((IF_ZERO.pipe[(int)userData].data_in[6])  | IF_ZERO.pipe[(int)userData].data_in[7]  << 8);
+            y = (short)((IF_ZERO.pipe[(int)userData].data_in[8])  | IF_ZERO.pipe[(int)userData].data_in[9]  << 8);
+            if (x != stick_left.x_previous) {
+                stick_left.x_previous = stick_left.x;
+                stick_left.x = x;
+            }
+            if (y != stick_left.y_previous) {
+                stick_left.y_previous = stick_left.y;
+                stick_left.y = y;
+            }
+            x = (short)((IF_ZERO.pipe[(int)userData].data_in[10]) | IF_ZERO.pipe[(int)userData].data_in[11] << 8);
+            y = (short)((IF_ZERO.pipe[(int)userData].data_in[12]) | IF_ZERO.pipe[(int)userData].data_in[13] << 8);
+            if (x != stick_right.x_previous) {
+                stick_right.x_previous = stick_right.x;
+                stick_right.x = x;
+            }
+            if (y != stick_right.y_previous) {
+                stick_right.y_previous = stick_right.y;
+                stick_right.y = y;
+            }
+        }
+    }
+    else if(len == 3) {
+        /* Chatpad return? */
+        #ifdef DEBUG_USB_DRIVER_IF_0
+        debug_printf("Got %02x %02x %02x \r\n", buf[0], buf[1], buf[2]);
+        #endif
+    }
+    else {
+        #ifdef DEBUG_USB_DRIVER_IF_0
+        DEBUG_UNKNOWN_PACKET_IF_0
+        #endif
+    }
+    
+    /* Schedule another transfer to keep the IN flow of data coming. */
+    usbeh_api_interrupt_transfer(device, endpoint, IF_ZERO.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_0_in, userData);
+}
+
+void xbox360gamepad_interface_1_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) {
+    /* We don't currently do anything with Interface:1 */
+    #ifdef DEBUG_USB_DRIVER_IF_1
+    DEBUG_UNKNOWN_PACKET_IF_1
+    #endif
+    
+    /* Schedule another transfer to keep the IN flow of data coming. */
+    usbeh_api_interrupt_transfer(device, endpoint, IF_ONE.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_1_in, userData);
+}
+
+void xbox360gamepad_interface_2_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) {
+    /* We don't currently do anything with Interface:2 */
+    #ifdef DEBUG_USB_DRIVER_IF_2
+    DEBUG_UNKNOWN_PACKET_IF_2
+    #endif
+    
+    /* Schedule another transfer to keep the IN flow of data coming. */
+    usbeh_api_interrupt_transfer(device, endpoint, IF_TWO.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_2_in, userData);
+}
+
+int xbox360gamepad_add_interface(int device, USBEH_interfaceDescriptor *iface, USBEH_endpointDescriptor *ed) {
+    
+    /* Handle interrupt IN transfers. */
+    if ((ed->bmAttributes & 3) != USBEH_ENDPOINT_INTERRUPT) {
+        return 0;
+    }
+    
+    if (iface->bInterfaceNumber == 0) {
+        int pipe = 0;
+        if (ed->bEndpointAddress & 0x80) {
+            #ifdef DEBUG_USB_DRIVER
+            DEBUG_USB_MSG_ALLOCATION
+            #endif
+            IF_ZERO.pipe[pipe].ep_number_in = ed->bEndpointAddress;
+            usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_ZERO.pipe[0].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_0_in, (void *)pipe);
+        }
+        else {
+            #ifdef DEBUG_USB_DRIVER
+            DEBUG_USB_MSG_ALLOCATION
+            #endif
+            IF_ZERO.pipe[pipe].ep_number_out = ed->bEndpointAddress;
+        }
+    }
+    
+    if (iface->bInterfaceNumber == 1) {
+        int pipe = (IF_ONE.pipe[0].ep_number_in == 0) ? 0 : 1;
+        if (ed->bEndpointAddress & 0x80) {
+            IF_ONE.pipe[pipe].ep_number_in = ed->bEndpointAddress;
+            #ifdef DEBUG_USB_DRIVER
+            DEBUG_USB_MSG_ALLOCATION
+            #endif
+            usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_ONE.pipe[pipe].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_1_in, (void *)pipe);
+        }
+        else {
+            #ifdef DEBUG_USB_DRIVER
+            DEBUG_USB_MSG_ALLOCATION
+            #endif
+            IF_ONE.pipe[pipe].ep_number_out = ed->bEndpointAddress;
+        }
+    }
+    
+    
+    if (iface->bInterfaceNumber == 2) {
+        int pipe = (IF_TWO.pipe[0].ep_number_in == 0) ? 0 : 1;
+        if (ed->bEndpointAddress & 0x80) {
+            IF_TWO.pipe[pipe].ep_number_in = ed->bEndpointAddress;
+            #ifdef DEBUG_USB_DRIVER
+            DEBUG_USB_MSG_ALLOCATION
+            #endif
+            usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_TWO.pipe[pipe].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_2_in, (void *)pipe);
+        }
+        else {
+            #ifdef DEBUG_USB_DRIVER
+            DEBUG_USB_MSG_ALLOCATION
+            #endif
+            IF_TWO.pipe[pipe].ep_number_out = ed->bEndpointAddress;
+        }
+    }
+       
+    return 1;
+}
+
+static XBOX360_DEVICE * xbox360gamepad_vendor_product_check(uint16_t vendorId, uint16_t productId) {
+    for (int i = 0; xbox360_devices[i].idVendor != 0; i++) {
+        if (xbox360_devices[i].idVendor == vendorId && xbox360_devices[i].idProduct == productId) {
+            return &xbox360_devices[i];
+        }
+    }
+    return (XBOX360_DEVICE *)NULL;
+}
+
+void xbox360gamepad_led(int code) {
+    IF_ZERO.pipe[0].data_out[0] = 0x01;
+    IF_ZERO.pipe[0].data_out[1] = 0x03;
+    IF_ZERO.pipe[0].data_out[2] = code;
+    usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, IF_ZERO.pipe[0].data_out, 3, NULL, NULL);
+}
+
+USBEH_U08 noise[] = "\x0\x8\x0\x0\x0\x0\x0\x0";
+
+void xbox360_noise(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) {
+    usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, noise, 8, xbox360_noise, NULL);
+}
+
+int xbox360gamepad_onload_callback(int device, USBEH_deviceDescriptor *deviceDesc, USBEH_interfaceDescriptor **interfaceDesc) {
+    USBEH_interfaceDescriptor *iface;
+    int length, endpoint_count, interfaceCounter = 0;
+    USBEH_U08 *start, *end;
+    
+    /* Is this a Microsoft Xbox360 wired Gamepad? */
+    XBOX360_DEVICE *xd = xbox360gamepad_vendor_product_check(deviceDesc->idVendor, deviceDesc->idProduct);
+    if (!xd) {
+        /* If not, don't claim it. */
+        return 0;
+    }
+    
+    #ifdef DEBUG_USB_DRIVER
+    debug_printf("Found device '%s'\r\n", xd->name);
+    #endif
+    
+    /* Save our device number in a global. */
+    deviceNumber = device;
+    
+    memset((char *)&IF_VENDOR, 0, sizeof(IF_VENDOR));
+    memset((char *)&IF_ZERO, 0, sizeof(IF_ZERO));
+    memset((char *)&IF_ONE, 0, sizeof(IF_ONE));
+    memset((char *)&IF_TWO, 0, sizeof(IF_TWO));
+    
+    #ifdef DEBUG_USB_DRIVER
+    debug_printf("%s() ACTIVATED for device id = %d\r\n", __FUNCTION__, device);
+    debug_printf("  OnLoad VendorId = 0x%04x ProductId = 0x%04x \r\n", deviceDesc->idVendor, deviceDesc->idProduct);
+    #endif
+        
+    /* Parse the interface configuration and setup the endpoint handlers. */
+    while ((iface = interfaceDesc[interfaceCounter]) != (USBEH_interfaceDescriptor *)NULL) { 
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("  interface%d:- \r\n", interfaceCounter);
+        debug_printf("    InterfaceClass    = %02x \r\n", iface->bInterfaceClass);
+        debug_printf("    InterfaceSubClass = %02x \r\n", iface->bInterfaceSubClass);
+        debug_printf("    InterfaceProtocol = %02x \r\n", iface->bInterfaceProtocol);
+        #endif
+        start = (USBEH_U08 *)iface;
+        length = start[0];
+        end   = start + length; 
+        #ifdef DEBUG_USB_DRIVER
+        debug_printf("  Scanning at start:%08x length:%d end:%08x \r\n", start, length, end);
+        #endif
+        while (start < end) {
+            if (start[1] == USBEH_DESCRIPTOR_TYPE_INTERFACE) {
+                USBEH_interfaceDescriptor *id = (USBEH_interfaceDescriptor *)start;
+                //int interfaceNumber = (int)id->bInterfaceNumber;                
+                endpoint_count = (int)id->bNumEndpoints;
+                #ifdef DEBUG_USB_DRIVER
+                debug_printf("  found definition for if:%d with %d endpoints.\r\n", interfaceNumber, endpoint_count);
+                #endif
+                start += start[0];
+                while (endpoint_count > 0) { 
+                    if (start[1] == USBEH_DESCRIPTOR_TYPE_ENDPOINT) {
+                        USBEH_endpointDescriptor *ed = (USBEH_endpointDescriptor *)start;
+                        #ifdef DEBUG_USB_DRIVER
+                        debug_printf("  found endpoint 0x%02X\r\n", ed->bEndpointAddress);
+                        #endif
+                        xbox360gamepad_add_interface(device, id, ed);
+                        endpoint_count--;
+                    }
+                    else {
+                        #ifdef DEBUG_USB_DRIVER
+                        debug_printf("  no endpoint for interface, descriptor class: %02X\r\n", start[1]);
+                        #endif
+                    }                    
+                    start += start[0];
+                }
+            }
+            else {
+                #ifdef DEBUG_USB_DRIVER
+                debug_printf("  no IF descr found at %08x\r\n", start);
+                #endif
+                start += start[0];
+            } 
+        }
+        
+        interfaceCounter++;
+    }
+    
+    #ifdef DEBUG_USB_DRIVER
+    debug_printf("Device claimed by %s().\r\n\n", __FUNCTION__);
+    #endif
+            
+    /* When the gamepad boots up, the LED ring flashes after it's
+       configuration is set. Let's flash the led and go steady. */
+    xbox360gamepad_led(LED_1_FLASH_THEN_ON);
+    
+    /* Lets just send "noise" to the headset and see what happens. */
+    //usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, noise, 8, xbox360_noise, NULL);
+    
+    /* I give up, wtf is it with this chatpad that MS needs to keep so secret? */
+    //xbox360_chatpad_init();
+    
+    /* Tell the USB embedded host that we have claimed this device. */
+    return 1; 
+}
+
+#ifdef NEVERCOMPILETHISCODE
+/* 
+
+UPDATE: Everything below is ABANDONED when I basically figured out from one replay to the next
+that MS use the security channel to "handshake" init the chatpad. Many people believe
+the security device in the gamepad is to "tell the xbox I am a real auth MS gamepad". However,
+as I have discovered, it's "two-way". There also exists the "tell the gamepad that an auth
+Xbox360 is the host" and without that the chatpad will not function. I have no interest in
+trying to crack anyones security chips so no further work will be done on this.
+
+Everything below here is related to the chatpad attachment for the Xbox360 gamepad controller.
+Unlike the sticks, triggers and buttons, the chatpad appears to require some sort of initialization
+in order to start running. Since MS have not published any sort of USB protocol specifications
+for their gamepad, what we do here is basically a "replay attack" based on packets sent and received
+between an Xbox and a gamepad with a USB protocol analyser in the middle. A classic man-in-the-middle
+type of attack.
+
+Here's the basic sequence we attempt to follow:-
+
+ 1. -> Vendor request IN EP0 (0x01) 
+       -> SETUP C0 01 00 00 00 00 04 00
+       <- IN    80 03 0D 47
+ 2. -> Vendor request OUT EP0 (0xA9)
+       -> 40 A9 0C A3 23 44 00
+       <- Expect STALLED no data
+ 3. -> Vendor request OUT EP0 (0xA9)
+       -> 40 A9 44 23 03 7F 00 00
+       <- Expect STALLED no data
+ 4. -> Vendor request OUT EP0 (0xA9)
+       -> 40 A9 39 58 32 68 00 00
+       <- Expect STALLED no data
+ 5. <- IN IF:0 EP2 3 bytes 01 03 0E
+ 6. -> Vendor request IN EP0 (0xA1) 
+       -> SETUP C0 A1 00 00 16 E4 02 00
+       <- IN    01 00
+ 7. -> OUT IF:0 EP1 3 bytes 01 03 01
+ 8. -> Vendor request OUT EP0 (0xA1)
+       -> SETUP 40 A1 00 00 16 E4 02 00
+       -> OUT   09 00                    
+ 9. -> Vendor request IN EP0 (0xA1)
+       -> SETUP C0 A1 00 00 16 E4 02 00
+       -> IN    09 00                   (echo previous OUT?)
+10. <- IN IF:0 EP 1 3 bytes 02 03 00
+11. <- IN IF:0 EP 1 3 bytes 03 03 03
+12. <- IN IF:0 EP 1 3 bytes 08 03 00
+13. <- IN IF:0 EP 1 3 bytes 01 03 01
+14. -> Vendor request OUT EP0 (0x00)
+       -> SETUP 41 00 1F 00 02 00 00 00
+       -> IN No data
+15. -> Vendor request OUT EP0 (0x00)
+       -> SETUP 41 00 1E 00 02 00 00 00
+       -> IN No data
+
+Note that 14. and 15. are 1second apart and repeat continuely
+toggling between 1F and 1E each second.
+
+16. <- IN IF:2 EP4 (IF:2 PIPE1) 5 bytes F0 03 00 01 01
+17. -> Vendor request OUT EP0 (0x00)
+       -> SETUP 41 00 1B 00 02 00 00 00
+       -> IN No data
+18. <- IN IF:2 EP4 (IF:2 PIPE1) 5 bytes F0 03 00 01 01
+19. -> Vendor request OUT EP0 (0x00)
+       -> SETUP 41 00 1B 00 02 00 00 00
+       -> IN No data
+
+
+After this we start receiving data from IF:2 PIPE1
+  
+*/
+USBEH_U08 chatpad_trash_buffer[256];
+USBEH_U08 chatpad_toggle;
+USBEH_U08 chatpad_send_toggle;
+USBEH_U08 chatpad_toggle_1Bsent;
+USBEH_SOF_COUNTER chatpad_toggle_timer;
+
+void xbox360_chatpad_toggle(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) {
+    int result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 
+        0x00, 
+        (int)userData, 
+        0x0002, 
+        chatpad_trash_buffer, 
+        0, 
+        xbox360_chatpad_toggle, 
+        (userData == (void *)0x1E) ? (void *)0x001F : (void *)0x001E);
+    //debug.printf("TOGGLE = 0x%x\r\n", -result & 0xf);
+}
+
+void xbox360_chatpad_timed_toggle(USBEH_SOF_COUNTER *q) {
+    int result;
+   
+    debug_printf("%s() called.\r\n", __FUNCTION__);
+                
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 
+        0x00, 
+        (int)q->userData == 0x1F ? 0x001F : 0x001E, 
+        0x0002, 
+        chatpad_trash_buffer,
+        0, 
+        0, 0);
+    
+    debug_printf("repeat! 1F/E = 0x%x\r\n", -result & 0xf);
+    
+    if (1 && !chatpad_toggle_1Bsent) {
+        chatpad_toggle_1Bsent = 1;
+        
+        result = usbeh_api_control_transfer(deviceNumber, 
+            USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 
+            0x00, 
+            0x001B, 
+            0x0002, 
+            chatpad_trash_buffer, 
+            0, 
+            0, 0);
+    }
+    
+    debug_printf("repeat! 1B = 0x%x\r\n", -result & 0xf);
+    
+    //usbeh_sof_counter_unregister(&chatpad_toggle_timer);
+    //usbeh_sof_counter_init(&chatpad_toggle_timer,  USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, 1700);
+    //chatpad_toggle_timer.userData = (int)q->userData == 0x1F ? 0x001F : 0x001E;
+    //chatpad_toggle_timer.callback = xbox360_chatpad_timed;
+    //chatpad_toggle_timer.flag = 0;
+    //usbeh_sof_counter_register(&chatpad_toggle_timer);
+    
+    
+}
+
+void xbox360_chatpad_init(void) {
+    int result;
+    USBEH_U08   buffer[256];
+    USBEH_U08   data[256];
+    
+    // int usbeh_api_control_transfer(int device, 
+    //      int request_type, 
+    //      int request, 
+    //      int value, 
+    //      int index, 
+    //      USBEH_U08 *data, 
+    //      int length, 
+    //      USBEH_callback callback, void *userData) {
+    // int r = usbeh_api_control_transfer(device, USBEH_DEVICE_TO_HOST | USBEH_REQUEST_TYPE_CLASS | USBEH_RECIPIENT_DEVICE, USBEH_GET_DESCRIPTOR, (USBEH_DESCRIPTOR_TYPE_HUB << 8), 0, buffer, sizeof(buffer), 0, 0);
+    
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 
+        0x01, 
+        0x0000, 
+        0x0000, 
+        buffer, 
+        4, 
+        0, 0);
+    debug_printf("Step 1 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 
+        0xA9, 
+        0xA30C, 
+        0x4423, 
+        buffer, 
+        0, 
+        0, 0);
+    debug_printf("Step 2 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 
+        0xA9, 
+        0x2344, 
+        0x7F03, 
+        buffer, 
+        0, 
+        0, 0);
+    debug_printf("Step 3 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 
+        0xA9, 
+        0x5839, 
+        0x6832, 
+        buffer, 
+        0, 
+        0, 0);
+    debug_printf("Step 4 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 
+        0xA1, 
+        0x0000, 
+        0xE416, 
+        buffer, 
+        2, 
+        0, 0);
+    debug_printf("Step 5 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+    
+    data[0] = 9; data[1] = 0;
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 
+        0xA1, 
+        0x5839, 
+        0xE416, 
+        data, 
+        2, 
+        0, 0);
+    debug_printf("Step 6 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 
+        0xA1, 
+        0x0000, 
+        0xE416, 
+        buffer, 
+        2, 
+        0, 0);
+    debug_printf("Step 7 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+
+    // Now begin toggling 1F / 1E
+    chatpad_toggle = 0x1E;
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 
+        0x00, 
+        0x001F, 
+        0x0002, 
+        chatpad_trash_buffer, 
+        0, 
+        xbox360_chatpad_toggle, 
+        (void *)0x1E);
+    debug_printf("Step 8 TOGGLE = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+    
+    result = usbeh_api_control_transfer(deviceNumber, 
+        USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 
+        0x00, 
+        0x0003, 
+        0x0002, 
+        chatpad_trash_buffer, 
+        0, 
+        0, 
+        0);
+    debug_printf("Step 9 OUT 0x03 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]);
+    
+    //usbeh_sof_counter_init(&chatpad_toggle_timer,  USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, 1700);
+    //chatpad_toggle_timer.userData = (int)chatpad_toggle;
+    //chatpad_toggle_timer.callback = xbox360_chatpad_timed;
+    //usbeh_sof_counter_register(&chatpad_toggle_timer);
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbeh/xbox360gamepad.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,139 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef XBOX360GAMEPAD_H
+#define XBOX360GAMEPAD_H
+
+#include "usbeh_api.h"
+
+#define BUTTON_PRESSED      1
+#define BUTTON_RELEASED     0
+
+#define BUTTON_HOLD_TIME    3000
+
+#define BUTT_LS_PRESS                 1
+#define BUTT_RS_PRESS                 2
+#define BUTT_XBOX_PRESS               3
+#define BUTT_UNUSED_PRESS             4
+#define BUTT_A_PRESS                  5
+#define BUTT_B_PRESS                  6
+#define BUTT_X_PRESS                  7
+#define BUTT_Y_PRESS                  8
+#define BUTT_DPAD_UP_PRESS            9
+#define BUTT_DPAD_DOWN_PRESS          10
+#define BUTT_DPAD_LEFT_PRESS          11
+#define BUTT_DPAD_RIGHT_PRESS         12
+#define BUTT_START_PRESS              13
+#define BUTT_BACK_PRESS               14
+#define BUTT_LEFT_HAT_PRESS           15
+#define BUTT_RIGHT_HAT_PRESS          16
+
+#define BUTT_LS_RELEASE                 (BUTT_LS_PRESS + 16)
+#define BUTT_RS_RELEASE                 (BUTT_RS_PRESS + 16)
+#define BUTT_XBOX_RELEASE               (BUTT_XBOX_PRESS + 16)
+#define BUTT_UNUSED_RELEASE             (BUTT_UNUSED_PRESS + 16)
+#define BUTT_A_RELEASE                  (BUTT_A_PRESS + 16)
+#define BUTT_B_RELEASE                  (BUTT_B_PRESS + 16)
+#define BUTT_X_RELEASE                  (BUTT_X_PRESS + 16)
+#define BUTT_Y_RELEASE                  (BUTT_Y_PRESS + 16)
+#define BUTT_DPAD_UP_RELEASE            (BUTT_DPAD_UP_PRESS + 16)
+#define BUTT_DPAD_DOWN_RELEASE          (BUTT_DPAD_DOWN_PRESS + 16)
+#define BUTT_DPAD_LEFT_RELEASE          (BUTT_DPAD_LEFT_PRESS + 16)
+#define BUTT_DPAD_RIGHT_RELEASE         (BUTT_DPAD_RIGHT_PRESS + 16)
+#define BUTT_START_RELEASE              (BUTT_START_PRESS + 16)
+#define BUTT_BACK_RELEASE               (BUTT_BACK_PRESS + 16)
+#define BUTT_LEFT_HAT_RELEASE           (BUTT_LEFT_HAT_PRESS + 16)
+#define BUTT_RIGHT_HAT_RELEASE          (BUTT_RIGHT_HAT_PRESS + 16)
+
+#define BUTT_LS_HOLD                    (BUTT_LS_PRESS + 32)
+#define BUTT_RS_HOLD                    (BUTT_RS_PRESS + 32)
+#define BUTT_XBOX_HOLD                  (BUTT_XBOX_PRESS + 32)
+#define BUTT_UNUSED_HOLD                (BUTT_UNUSED_PRESS + 32)
+#define BUTT_A_HOLD                     (BUTT_A_PRESS + 32)
+#define BUTT_B_HOLD                     (BUTT_B_PRESS + 32)
+#define BUTT_X_HOLD                     (BUTT_X_PRESS + 32)
+#define BUTT_Y_HOLD                     (BUTT_Y_PRESS + 32)
+#define BUTT_DPAD_UP_HOLD               (BUTT_DPAD_UP_PRESS + 32)
+#define BUTT_DPAD_DOWN_HOLD             (BUTT_DPAD_DOWN_PRESS + 32)
+#define BUTT_DPAD_LEFT_HOLD             (BUTT_DPAD_LEFT_PRESS + 32)
+#define BUTT_DPAD_RIGHT_HOLD            (BUTT_DPAD_RIGHT_PRESS + 32)
+#define BUTT_START_HOLD                 (BUTT_START_PRESS + 32)
+#define BUTT_BACK_HOLD                  (BUTT_BACK_PRESS + 32)
+#define BUTT_LEFT_HAT_HOLD              (BUTT_LEFT_HAT_PRESS + 32)
+#define BUTT_RIGHT_HAT_HOLD             (BUTT_RIGHT_HAT_PRESS + 32)
+
+#define LED_ALL_OFF                     0x00
+#define LED_ALL_BLINKING                0x01
+#define LED_1_FLASH_THEN_ON             0x02
+#define LED_2_FLASH_THEN_ON             0x03
+#define LED_3_FLASH_THEN_ON             0x04
+#define LED_4_FLASH_THEN_ON             0x05
+#define LED_1_ON                        0x06
+#define LED_2_ON                        0x07
+#define LED_3_ON                        0x08
+#define LED_4_ON                        0x09
+#define LED_ROTATING                    0x0A
+#define LED_BLINKING                    0x0B
+#define LED_SLOW_BLINKING               0x0C
+#define LED_ALTERNATING                 0x0D
+
+typedef struct {
+  uint16_t    idVendor;
+  uint16_t    idProduct;
+  const char*       name;
+} XBOX360_DEVICE;
+
+typedef struct {
+    unsigned            state;
+    unsigned            mask;
+    unsigned            count;
+    USBEH_SOF_COUNTER   pressHold;
+} XBOX360_BUTTON;
+
+typedef struct {
+    short x;
+    short y;
+    short x_previous;
+    short y_previous;
+} XBOX360_STICK;
+
+/* API functions. */
+char xbox360gamepad_get_button(void);
+char xbox360gamepad_get_button_preview(void);
+unsigned char xbox360gamepad_get_trigger_left(void);
+unsigned char xbox360gamepad_get_trigger_right(void);
+void xbox360gamepad_led(int code);
+XBOX360_STICK * xbox360gamepad_get_stick_left(void);
+XBOX360_STICK * xbox360gamepad_get_stick_right(void);
+
+int xbox360gamepad_init(void);
+void xbox360gamepad_process(void);
+
+/* Button press and hold callback function. */
+void xbox360gamepad_button_hold_callback(USBEH_SOF_COUNTER *q);
+
+/* Onload callback function. */
+int xbox360gamepad_onload_callback(int device, USBEH_deviceDescriptor *deviceDesc, USBEH_interfaceDescriptor **interfaceDesc);
+
+void xbox360_chatpad_init(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/user.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,214 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "rit.h" 
+#include "gpio.h"
+#include "user.h"
+#include "nexstar.h"
+#include "xbox360gamepad.h"
+#include "debug.h"
+
+#define STICK_DIVISOR   4096.0
+
+void handle_stick_left(void);
+void handle_stick_right(void);
+
+typedef void (PROCESS_FUNC)();
+
+extern PROCESS_FUNC *process_callbacks[];
+
+USER_INPUT user_input;
+
+/** user_get_button
+ *
+ * Used to get a "button press" from the user. This is basically
+ * a read of the XBox360 gamepad interface via the USBEH system.
+ * However, this function is provided to abstract that so that
+ * other systems can "inject" button presses into the system.
+ * The intention here is for a virtual console on a PC to 
+ * control the SOWB system via the (to be done) pccomms.c module.
+ * This is just a conveinent way to get user IO into the SOWB.
+ *
+ * Note, this fnction calls all the module _process() functions
+ * in it's loop (ie while no user IO is occuring). That gives the
+ * SOWB modules a chance to get work done outside of time critical
+ * interrupts. _process() functions should NEVER block and should 
+ * also be "fast" so as to avoid any user IO perseptive delay.
+ *
+ * Note, if arg peek is true, we return the next button press in
+ * the buffer without actually removing that event from the buffer.
+ * Allows us to look to see if an pending button press is within
+ * the buffer awaiting being handled.
+ *
+ * @param bool peek
+ * @return char The button pressed.
+ */
+char user_get_button(bool peek) {
+    char c;
+    
+    if (peek) {
+        /* Make a call to all _process()'s just in case we find 
+           ourselves stuck in a tight loop waiting for an event. */
+        for (c = 0; process_callbacks[c] != NULL; c++) (process_callbacks[c])();
+        return xbox360gamepad_get_button_preview();
+    }
+    
+    do {
+        /* Call all module _process functions. */
+        for (c = 0; process_callbacks[c] != NULL; c++) {
+            KICK_WATCHDOG;
+            (process_callbacks[c])();
+        }
+        
+        handle_stick_left();
+        handle_stick_right();
+        
+        /* Get a button press from the user or go round again. */
+        c = xbox360gamepad_get_button();
+    }
+    while (c == 0);
+    
+    return c;
+}
+
+/* A flag to signify a timeout has occured. */
+volatile int user_wait_ms_flag;
+
+/** _user_wait_ms_cb
+ *
+ * Called by the RIT system to signal a timer timeout.
+ *
+ * @param int t_index The timer index value (handle).
+ */
+void _user_wait_ms_cb(int t_index) {
+    user_wait_ms_flag = 0;
+}
+
+/** user_wait_ms
+ *
+ * Used to "wait" for a specified time interval. 
+ * Note, while "waiting" for the timeout, it will
+ * call all the modules _process() functions to 
+ * allow modules to perform non-time critical work
+ * outside of interrupts.
+ *
+ * @param uint32_t ms The delay amount.
+ */
+void user_wait_ms(uint32_t ms) {
+    rit_timer_set_counter(RIT_TIMER_CB_WAIT, ms);
+    user_wait_ms_flag = 1;
+    while (user_wait_ms_flag) 
+        for (int c = 0; process_callbacks[c] != NULL; c++) { 
+            KICK_WATCHDOG;
+            (process_callbacks[c])();
+        }
+}
+
+/** user_wait_ms
+ *
+ * Used to "wait" for a specified time interval. 
+ * Note, unlike the function above, NO _process()
+ * functions are called. This really is a blocking
+ * delay and should be used with care!
+ *
+ * @param uint32_t ms The delay amount.
+ */
+void user_wait_ms_blocking(uint32_t ms) {
+    rit_timer_set_counter(RIT_TIMER_CB_WAIT, ms);
+    user_wait_ms_flag = 1;
+    while (user_wait_ms_flag) KICK_WATCHDOG;
+}
+
+/** user_call_process
+ */
+void user_call_process(void) {
+    for (int c = 0; process_callbacks[c] != NULL; c++) {
+        KICK_WATCHDOG; 
+        (process_callbacks[c])();
+    }
+}
+
+void handle_stick_left(void) {
+    static XBOX360_STICK stick_left_previous;
+    XBOX360_STICK *stick;
+    int x, y;
+    double rate;
+    
+    stick = xbox360gamepad_get_stick_left();
+    if (stick->x/STICK_DIVISOR != stick_left_previous.x/STICK_DIVISOR || stick->y/STICK_DIVISOR != stick_left_previous.y/STICK_DIVISOR) {
+        stick_left_previous.x = stick->x;
+        stick_left_previous.y = stick->y;
+        x = stick->x/STICK_DIVISOR;
+        y = stick->y/STICK_DIVISOR;
+        
+        if (x > 2 || x < -2) {
+            rate = 6.0 * (double)((double)stick->x/STICK_DIVISOR / 16.0);
+            _nexstar_set_azmith_rate_coarse(rate);
+        }
+        else {
+            _nexstar_set_azmith_rate_coarse(0.0);
+        }
+        
+        if (y > 2 || y < -2) {
+            rate = 6.0 * (double)((double)stick->y/STICK_DIVISOR / 16.0);
+            _nexstar_set_elevation_rate_coarse(rate);
+        }
+        else {
+            _nexstar_set_elevation_rate_coarse(0.0);
+        }
+    }    
+}
+
+void handle_stick_right(void) {
+    static XBOX360_STICK stick_previous;
+    XBOX360_STICK *stick;
+    int x, y;
+    double rate;
+    
+    stick = xbox360gamepad_get_stick_right();
+    if (stick->x/STICK_DIVISOR != stick_previous.x/STICK_DIVISOR || stick->y/STICK_DIVISOR != stick_previous.y/STICK_DIVISOR) {
+        stick_previous.x = stick->x;
+        stick_previous.y = stick->y;
+        x = stick->x/STICK_DIVISOR; 
+        y = stick->y/STICK_DIVISOR;
+        
+        if (x > 2 || x < -2) {
+            //debug_printf("New RIGHT stick position x = %d y = %d\r\n", stick->x/STICK_DIVISOR, stick->y/STICK_DIVISOR);
+            rate = 0.4 * (double)((double)stick->x/STICK_DIVISOR / 16.0);
+            _nexstar_set_azmith_rate_fine(rate);
+        }
+        else {
+            _nexstar_set_azmith_rate_fine(0.0);
+        }
+        
+        if (y > 2 || y < -2) {
+            rate = 0.4 * (double)((double)stick->y/STICK_DIVISOR / 16.0);
+            _nexstar_set_elevation_rate_fine(rate);
+        }
+        else {
+            _nexstar_set_elevation_rate_fine(0.0);
+        }
+    }    
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/user.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,46 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef USER_H
+#define USER_H
+
+#include "xbox360gamepad.h"
+
+#define WHILE_WAITING_DO_PROCESS_FUNCTIONS user_call_process();
+
+#define KICK_WATCHDOG   { LPC_WDT->WDFEED = 0xAA; LPC_WDT->WDFEED = 0x55; }
+
+typedef struct _user_input {
+    char            xbox_button;
+    unsigned char   trigger_left;
+    unsigned char   trigger_right;    
+    XBOX360_STICK * stick_left;
+    XBOX360_STICK * stick_right;
+} USER_INPUT;
+
+
+char user_get_button(bool peek);
+void user_wait_ms(uint32_t ms);
+void user_wait_ms_blocking(uint32_t ms);
+void user_call_process(void);
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/star.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,2358 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#include "sowb.h"
+#include "debug.h"
+#include "satapi.h"
+#include "star.h"
+
+
+basicStarData * star_closest(RaDec *radec, basicStarData *star) {    
+    const basicStarData *bright_star;
+    float raHigh, raLow, decHigh, decLow;
+    char test_buffer[64];
+    int i = 0, once = 0;
+    
+    raHigh  = radec->ra  + 5.0;
+    if (raHigh >= 360.0) raHigh  -= 360.0;
+    raLow   = radec->ra  - 5.0;
+    if (raLow <= 0.0)   raHigh   += 360.0;
+    decHigh = radec->dec + 5.0;
+    if (decHigh >= 90.0) 90.0 - decHigh;
+    decLow  = radec->dec - 5.0;
+    if (decLow <= -90.0) 90.0 + decLow;
+    
+    do {
+        bright_star = get_bright_star(i);
+        if (bright_star->ra < raHigh && bright_star->ra > raLow) {
+            if (bright_star->dec < decHigh && bright_star->dec > decLow) {
+                sprintf(test_buffer, "%d Candidate HR %d %f %f %f\r\n", once, bright_star->hr, bright_star->ra, bright_star->dec, bright_star->mag);
+                if (once == 0) {
+                    once++;
+                    memcpy(star, bright_star, sizeof(basicStarData));
+                    sprintf(test_buffer, "%d HR %d %f %f %f\r\n", once, star->hr, star->ra, star->dec, star->mag);
+                    debug_printf(test_buffer);
+                }
+                else {
+                    if (bright_star->mag < star->mag) {
+                        once++;
+                        memcpy(star, bright_star, sizeof(basicStarData));
+                        sprintf(test_buffer, "%d HR %d %f %f %f\r\n", once, star->hr, star->ra, star->dec, star->mag);
+                        debug_printf(test_buffer);
+                    }
+                }
+            }
+        }
+        i++;
+    }
+    while(bright_star->hr != 0);
+   
+    if (!once) return (basicStarData *)NULL;
+    return star;
+}
+
+
+const basicStarData brightstars[] = {
+ {    1,   1.2913, +45.2292, 6.70 }, {    2,   1.2658,  +0.5031, 6.29 }, {    3,   1.3338,  -4.2925, 4.61 }, {    4,   1.4250, +13.3961, 5.51 },
+ {    5,   1.5667, +58.4367, 5.96 }, {    6,   1.5792, -48.9250, 5.70 }, {    7,   1.6104, +64.1961, 5.59 }, {    8,   1.6533, +29.0214, 6.13 },
+ {    9,   1.7088, -22.8925, 6.18 }, {   10,   1.8258, -16.6136, 6.19 }, {   11,   1.9338,  -1.4511, 6.43 }, {   12,   1.9450, -21.4911, 5.94 },
+ {   13,   2.0146, -32.4706, 5.68 }, {   14,   2.0504,  -1.5522, 6.07 }, {   15,   2.0971, +29.0906, 2.06 }, {   16,   2.0725,  -7.1761, 5.99 },
+ {   17,   2.1708, +36.6267, 6.19 }, {   18,   2.1392, -16.4225, 6.06 }, {   19,   2.2175, +25.4628, 6.23 }, {   20,   2.3342, +79.7147, 6.01 },
+ {   21,   2.2946, +59.1497, 2.27 }, {   22,   2.2600, +18.2119, 5.53 }, {   23,   2.2600, -53.9981, 6.33 }, {   24,   2.3375, -26.0122, 5.42 },
+ {   25,   2.3529, -44.2525, 3.88 }, {   26,   2.5096, +11.1456, 5.51 }, {   27,   2.5804, +46.0722, 5.03 }, {   28,   2.6237, +57.1656, 6.74 },
+ {   29,   2.5783,  -4.7514, 5.84 }, {   30,   2.5088, -81.7761, 5.28 }, {   31,   2.6783, -11.4200, 5.85 }, {   32,   2.6608, -72.7756, 6.64 },
+ {   33,   2.8163, -14.5319, 4.89 }, {   34,   2.8933, -26.2003, 5.41 }, {   35,   2.9333, -34.8669, 5.25 }, {   36,   2.9962, +48.1525, 6.16 },
+ {   37,   3.0417, -16.0617, 5.25 }, {   38,   3.2100, +37.6933, 6.73 }, {   39,   3.3092, +15.1836, 2.83 }, {   40,   3.3500, +26.9872, 6.30 },
+ {   41,   3.3783, +41.0353, 5.72 }, {   42,   3.4254, -25.9781, 5.94 }, {   43,   3.4342, -25.7153, 6.31 }, {   44,   3.5096, +33.2061, 6.25 },
+ {   45,   3.6508, +20.2067, 4.80 }, {   46,   3.6150,  -6.2194, 5.12 }, {   47,   3.3308, -83.0058, 5.77 }, {   48,   3.6600, -17.0672, 4.44 },
+ {   49,   3.7338, +22.2842, 6.24 }, {   50,   3.7450,  +8.8208, 5.79 }, {   51,   3.7271,  -8.4303, 5.75 }, {   52,   3.7792, +31.5358, 6.45 },
+ {   53,   3.7942, +27.2831, 6.35 }, {   54,   3.7425, -33.0956, 6.17 }, {   55,   4.0583, +76.9508, 6.35 }, {   56,   4.0900, +43.5947, 6.15 },
+ {   57,   4.0371, -30.5536, 5.67 }, {   58,   3.9800, -74.0886, 6.49 }, {   59,   4.1421,  +8.2400, 6.11 }, {   60,   4.2379, +61.5333, 5.74 },
+ {   61,   4.1771, -19.7894, 6.47 }, {   62,   4.2879, +47.9475, 5.89 }, {   63,   4.2729, +38.6817, 4.61 }, {   64,   4.2042, -77.2194, 6.77 },
+ {   65,   4.4292, +51.4331, 6.14 }, {   66,   4.3858, -18.9489, 6.45 }, {   67,   4.4488,  +1.6889, 6.17 }, {   68,   4.5821, +36.7853, 4.52 },
+ {   69,   4.5717, +11.2058, 6.05 }, {   70,   4.6754, +43.7911, 6.11 }, {   71,   4.6596, +31.5172, 5.87 }, {   72,   4.6742,  -7.9472, 6.46 },
+ {   73,   4.6775, -42.7647, 6.33 }, {   74,   4.8571,  -7.1761, 3.56 }, {   75,   4.9233, +40.7297, 6.33 }, {   76,   5.0217, +48.8653, 6.52 },
+ {   77,   5.0179, -63.1253, 4.23 }, {   78,   5.1017, +30.9358, 5.90 }, {   79,   5.1896, +32.9114, 5.79 }, {   80,   5.1496,  +8.1903, 5.37 },
+ {   81,   5.2271, +10.9769, 6.56 }, {   82,   5.2804, +37.9686, 5.18 }, {   83,   5.1625, -68.3750, 5.51 }, {   84,   5.3800, -27.0183, 5.18 },
+ {   85,   5.4429, -19.9422, 5.12 }, {   86,   5.6063, +13.4825, 6.23 }, {   87,   5.3692, -76.5731, 5.97 }, {   88,   5.7158, -11.7906, 6.39 },
+ {   89,   5.8025, -30.9639, 6.55 }, {   90,   6.0083, +38.5772, 7.39 }, {   91,   6.0650, +52.0200, 5.57 }, {   92,   0.0000,  +0.0000, 0.00 },
+ {   93,   6.1979, +61.8311, 5.40 }, {   94,   6.1238,  -1.7808, 6.07 }, {   95,   0.0000,  +0.0000, 0.00 }, {   96,   6.2767, +53.0469, 5.74 },
+ {   97,   6.3508,  +1.9397, 5.77 }, {   98,   6.4379, -76.7458, 2.80 }, {   99,   6.5708, -41.6939, 2.39 }, {  100,   6.5508, -42.3200, 3.94 },
+ {  101,   6.6558,  +0.0497, 6.19 }, {  102,   6.8113, -24.4528, 5.98 }, {  103,   7.0121, +17.8931, 5.06 }, {  104,   7.0571, +44.3944, 5.17 },
+ {  105,   6.9821, -32.9928, 4.81 }, {  106,   7.0529, +16.4450, 6.06 }, {  107,   7.0838, +10.1897, 6.04 }, {  108,   7.0879, -19.6650, 6.43 },
+ {  109,   7.1100, -38.0850, 5.43 }, {  110,   7.2358, +36.9000, 6.26 }, {  111,   7.1796, -49.4672, 6.26 }, {  112,   7.7292, +77.0194, 6.21 },
+ {  113,   7.5829, +59.9772, 5.94 }, {  114,   7.5304, +29.7517, 5.23 }, {  115,   7.4662, -13.1358, 6.14 }, {  116,   7.4538, -31.8833, 6.57 },
+ {  117,   7.5100,  -2.0428, 5.72 }, {  118,   7.5946, -22.2122, 5.19 }, {  119,   7.6158, -39.0606, 6.19 }, {  120,   7.6087, -47.7850, 5.69 },
+ {  121,   7.8554, +66.5194, 6.18 }, {  122,   7.8567, +33.5817, 5.87 }, {  123,   7.9433, +54.5222, 4.73 }, {  124,   7.9217, +52.8394, 5.60 },
+ {  125,   7.8542, -47.1964, 4.77 }, {  126,   7.8863, -61.0419, 4.37 }, {  127,   7.8900, -61.0342, 4.54 }, {  128,   8.1117, +43.4947, 6.70 },
+ {  129,   8.3304, +70.9817, 6.42 }, {  130,   8.2500, +62.9317, 4.16 }, {  131,   8.1479, +20.2944, 5.38 }, {  132,   8.0992,  +6.9556, 5.67 },
+ {  133,   8.1438, +27.5806, 6.67 }, {  134,   8.2046, +28.2803, 6.30 }, {  135,   8.2933, +54.8950, 5.93 }, {  136,   8.1825, -62.9689, 5.09 },
+ {  137,   8.6037, +66.7503, 6.48 }, {  138,   8.4213, -28.4417, 5.55 }, {  139,   8.3471, -70.7339, 6.13 }, {  140,   8.6158, -51.6269, 5.57 },
+ {  141,   8.7304, +13.3711, 6.40 }, {  142,   8.8121,  -2.4072, 5.20 }, {  143,   8.8867,  +0.5056, 5.93 }, {  144,   9.0346, +54.1686, 5.08 },
+ {  145,   8.9779, +13.2067, 6.41 }, {  146,   9.1137, +60.3261, 5.79 }, {  147,   8.9213, -47.9992, 5.51 }, {  148,   8.8892, -53.1781, 6.06 },
+ {  149,   9.0833, +27.2547, 6.50 }, {  150,   9.0125, -13.0264, 6.45 }, {  151,   9.0288, -21.1575, 6.06 }, {  152,   9.1942, +44.4886, 5.13 },
+ {  153,   9.2429, +53.8969, 3.66 }, {  154,   9.2204, +33.7194, 4.36 }, {  155,   9.1971, +15.2317, 5.89 }, {  156,   9.2800, +24.0142, 6.47 },
+ {  157,   9.3379, +35.3994, 5.48 }, {  158,   9.9471, +82.4939, 6.40 }, {  159,   9.3362, -23.2328, 5.57 }, {  160,   9.1558, -64.8753, 6.42 },
+ {  161,   9.3771,  +3.1353, 6.39 }, {  162,   9.3254, -53.6058, 6.41 }, {  163,   9.6387, +29.3117, 4.37 }, {  164,   9.7912, +49.3544, 5.43 },
+ {  165,   9.8321, +30.8608, 3.27 }, {  166,   9.8408, +21.2506, 5.87 }, {  167,   9.9817, +21.4383, 5.36 }, {  168,  10.1271, +56.5372, 2.23 },
+ {  169,   9.6700, -72.8628, 6.85 }, {  170,   9.9913, -32.0383, 6.69 }, {  171,   9.9667, -43.2033, 6.01 }, {  172,  10.1192, -15.4831, 6.49 },
+ {  173,  10.1371, -22.1956, 6.14 }, {  174,  10.1767,  -3.6481, 5.91 }, {  175,  10.2800, +39.4586, 5.33 }, {  176,  10.1100, -58.5456, 5.89 },
+ {  177,  10.5142, +66.1475, 5.83 }, {  178,  10.4000, +24.6292, 6.04 }, {  179,  10.5162, +50.5125, 4.80 }, {  180,  10.3317, -45.9150, 4.59 },
+ {  181,  10.6296, +58.7533, 6.17 }, {  182,   0.0000,  +0.0000, 0.00 }, {  183,  10.4433, -55.4983, 5.70 }, {  184,  10.8671, +47.0247, 4.94 },
+ {  185,  10.6788, -37.5367, 6.06 }, {  186,  10.6742, -59.7375, 5.98 }, {  187,  10.6183, -64.5319, 5.39 }, {  188,  10.8975, -16.0133, 2.04 },
+ {  189,  11.1100, +47.8642, 5.67 }, {  190,  10.9592, -11.9883, 6.02 }, {  191,  10.8383, -56.5369, 4.36 }, {  192,  11.4125, +74.9881, 5.66 },
+ {  193,  11.1813, +48.2844, 4.54 }, {  194,  11.0475,  -9.3906, 4.76 }, {  195,  11.0504, -37.5783, 5.90 }, {  196,  11.3217, +55.2217, 5.42 },
+ {  197,  11.1850, -21.9939, 5.24 }, {  198,  11.2379, -41.3233, 5.94 }, {  199,  11.1346, -61.5022, 6.07 }, {  200,  11.6625, +69.3250, 6.33 },
+ {  201,  11.3504,  -3.3708, 6.15 }, {  202,  11.2500, -52.2850, 6.15 }, {  203,  11.3696, -11.1192, 6.15 }, {  204,  11.5629, +55.3053, 6.52 },
+ {  205,  11.5454, +44.8614, 6.05 }, {  206,  11.4238, -15.5758, 6.47 }, {  207,  11.6767, +59.5744, 6.39 }, {  208,  11.9421, +74.8475, 5.41 },
+ {  209,  11.4400, -46.4483, 5.80 }, {  210,  11.5492, -21.4781, 5.50 }, {  211,  11.6375, +15.4756, 5.38 }, {  212,  12.0379, +72.6750, 5.87 },
+ {  213,  11.7563, +11.9739, 5.50 }, {  214,  11.8067, +19.5789, 6.13 }, {  215,  11.8346, +24.2672, 4.06 }, {  216,  11.8483,  +6.7408, 5.99 },
+ {  217,  11.9783, +20.9253, 6.54 }, {  218,  11.9304, -17.9386, 5.70 }, {  219,  12.2750, +57.8158, 3.44 }, {  220,  12.0046, -20.2775, 5.57 },
+ {  221,  12.0725,  +7.3000, 5.93 }, {  222,  12.0958,  +5.2806, 5.75 }, {  223,  12.2088, +50.9683, 4.89 }, {  224,  12.1708,  +7.5850, 4.43 },
+ {  225,  12.2446, +16.9406, 5.07 }, {  226,  12.4533, +41.0789, 4.53 }, {  227,  12.3567, -12.4386, 5.59 }, {  228,  12.3079, -23.8636, 5.90 },
+ {  229,  12.2363, -45.3022, 6.27 }, {  230,  12.4700, +27.7108, 7.00 }, {  231,  12.4717, +27.7103, 7.10 }, {  232,  12.3892, -22.6383, 6.28 },
+ {  233,  12.6817, +64.2475, 5.39 }, {  234,  12.5763, +45.0022, 6.15 }, {  235,  12.5317,  -9.3556, 5.19 }, {  236,  12.1475, -73.0767, 5.07 },
+ {  237,  12.8183, +61.8058, 6.07 }, {  238,  12.7392, +51.5081, 6.39 }, {  239,  12.5154, -42.6053, 6.48 }, {  240,  13.7213, +83.7072, 5.62 },
+ {  241,  12.8904, +51.5711, 6.21 }, {  242,  12.6717, -49.0131, 5.22 }, {  243,  12.8263,  +3.3850, 6.37 }, {  244,  13.2671, +61.1242, 4.82 },
+ {  245,  12.9671, -42.2908, 6.90 }, {  246,  13.2225, +38.5486, 6.69 }, {  247,  13.1692, -23.9942, 5.46 }, {  248,  13.2521,  -0.8558, 4.77 },
+ {  249,  13.3675, +37.4181, 6.06 }, {  250,  13.4483, +52.6892, 6.27 }, {  251,  13.3017, -23.2231, 6.46 }, {  252,  13.1013, -68.4956, 6.22 },
+ {  253,  13.7504, +58.9728, 4.83 }, {  254,  13.6467, +19.1883, 5.74 }, {  255,  13.5733,  -7.2592, 6.16 }, {  256,  13.7717, +48.6786, 6.27 },
+ {  257,  13.4079, -61.1286, 5.70 }, {  258,  13.7417, +23.6283, 5.47 }, {  259,  13.8112, +24.5569, 6.20 }, {  260,  14.0538, +57.9967, 6.21 },
+ {  261,  14.2317, +68.7761, 6.37 }, {  262,  13.9938, +27.2094, 6.09 }, {  263,  13.9267,  -6.6528, 5.85 }, {  264,  14.1771, +60.7167, 2.47 },
+ {  265,  14.1658, +59.1811, 4.63 }, {  266,  14.1962, +60.3628, 5.55 }, {  267,  14.0063, -10.7333, 5.31 }, {  268,  13.9812, -26.2244, 6.10 },
+ {  269,  14.1883, +38.4994, 3.87 }, {  270,  13.7513, -68.4731, 5.45 }, {  271,  14.3017, +23.4175, 4.42 }, {  272,  14.4154, +45.8397, 6.12 },
+ {  273,  14.6296, +66.3522, 5.97 }, {  274,  14.4592, +28.9922, 5.42 }, {  275,  14.5592, +33.9508, 5.98 }, {  276,  14.4771, +13.6958, 6.32 },
+ {  277,  14.5787, +21.4044, 6.37 }, {  278,  15.1292, +70.9831, 6.39 }, {  279,  14.6829, -10.6200, 5.61 }, {  280,  14.6517, -28.6425, 4.31 },
+ {  281,  14.5933, -59.3036, 6.23 }, {  282,  15.0142, +44.7111, 6.84 }, {  283,  15.0150, +44.7133, 6.04 }, {  284,  14.9571,  +6.4831, 6.11 },
+ {  285,  17.1863, +86.2569, 4.25 }, {  286,  23.4600, +89.0156, 6.46 }, {  287,  15.5767, +51.0350, 6.47 }, {  288,  15.3263, -37.0833, 5.59 },
+ {  289,  15.7563, +47.3761, 6.45 }, {  290,  15.7263, +41.3450, 5.98 }, {  291,  15.7046, +31.8044, 5.50 }, {  292,  15.9042, +61.0750, 5.92 },
+ {  293,  15.6100, -30.4481, 5.50 }, {  294,  15.7358,  +7.8900, 4.28 }, {  295,  15.5075, -56.9975, 6.11 }, {  296,  15.7608,  -3.1633, 5.43 },
+ {  297,  16.0817, +61.5803, 5.84 }, {  298,  16.0100, +52.5022, 5.99 }, {  299,  15.7050, -45.6025, 5.36 }, {  300,  15.8233, -28.4742, 6.29 },
+ {  301,  15.9542,  +1.3667, 6.04 }, {  302,  16.1950, +51.0100, 6.54 }, {  303,  16.1150, +29.6586, 6.19 }, {  304,  15.6788, -64.5439, 6.21 },
+ {  305,  16.1517, +39.9911, 6.72 }, {  306,  19.0562, +87.1453, 6.25 }, {  307,  16.2192,  +5.6564, 6.00 }, {  308,  16.2725, +14.9461, 5.68 },
+ {  309,  16.5950, +62.7617, 6.54 }, {  310,  16.4204, +21.4733, 5.34 }, {  311,  16.4237, +21.4653, 5.56 }, {  312,  17.3013, +80.0117, 6.29 },
+ {  313,  16.4550,  +4.9083, 6.35 }, {  314,  16.4642,  +4.9094, 7.25 }, {  315,  16.4033,  -8.0208, 6.12 }, {  316,  16.7508, +56.9350, 6.43 },
+ {  317,  16.5212,  -8.1606, 5.58 }, {  318,  16.7896, +53.4983, 6.38 }, {  319,  16.6400, +12.9561, 6.12 }, {  320,  16.5321, -22.0075, 6.14 },
+ {  321,  17.0683, +54.9203, 5.17 }, {  322,  16.5208, -45.2814, 3.31 }, {  323,  16.6104, -34.3392, 6.61 }, {  324,  17.0038, +43.9419, 5.03 },
+ {  325,  16.8046, -22.0036, 6.37 }, {  326,  17.1388, +58.2636, 5.79 }, {  327,  17.0054, +32.0122, 6.25 }, {  328,  16.9883, +20.7392, 5.55 },
+ {  329,  16.9425,  -8.2144, 5.82 }, {  330,  17.0925,  +5.6497, 5.52 }, {  331,  16.9496, -40.5131, 5.21 }, {  332,  16.8279, -60.2247, 5.37 },
+ {  333,  18.0696, +79.6739, 5.64 }, {  334,  17.1475,  -9.8178, 3.45 }, {  335,  17.3758, +47.2419, 4.25 }, {  336,  17.6638, +68.7786, 5.29 },
+ {  337,  17.4329, +35.6206, 2.06 }, {  338,  17.0963, -54.7542, 3.92 }, {  339,  17.4550, +19.6586, 5.55 }, {  340,  17.5783, +42.0814, 5.65 },
+ {  341,  17.5808, +25.4578, 5.80 }, {  342,  17.8567, +64.2028, 5.55 }, {  343,  17.7758, +55.1497, 4.33 }, {  344,  17.5479, +15.6742, 6.06 },
+ {  345,  17.9225, +65.0189, 5.57 }, {  346,  17.5500,  -7.0939, 6.40 }, {  347,  17.6400,  +2.4456, 5.95 }, {  348,  17.7929, +37.7242, 5.81 },
+ {  349,  17.7783, +31.4247, 5.16 }, {  350,  17.5308, -56.3056, 6.41 }, {  351,  17.8633, +21.0347, 4.66 }, {  352,  17.9150, +30.0897, 4.51 },
+ {  353,  17.9312,  -1.7489, 5.94 }, {  354,  18.2913, +61.7058, 6.41 }, {  355,  18.1417, +45.3378, 6.11 }, {  356,  18.2479, +30.0642, 6.19 },
+ {  357,  19.1279, +79.9100, 6.26 }, {  358,  18.0975, -29.1978, 6.52 }, {  359,  18.1892, -36.1436, 5.92 }, {  360,  18.4371, +24.5836, 4.65 },
+ {  361,  18.4329,  +7.5753, 5.24 }, {  362,  18.4387,  +7.5783, 6.30 }, {  363,  18.5208, +28.5297, 6.43 }, {  364,  18.5317, +16.1336, 5.98 },
+ {  365,  19.0504, +71.7439, 7.83 }, {  366,  18.6000,  -6.0769, 5.13 }, {  367,  18.6767,  +6.9953, 6.03 }, {  368,  18.7050,  +0.9739, 5.70 },
+ {  369,  19.1021, +48.0822, 6.61 }, {  370,  18.7963, -44.4686, 4.96 }, {  371,  19.0783, +33.1147, 6.02 }, {  372,  19.2712, +44.9019, 6.34 },
+ {  373,  19.1513,  -1.4997, 5.41 }, {  374,  19.3504, +31.7447, 6.73 }, {  375,  20.0813, +77.5706, 6.31 }, {  376,  19.5425, +47.4197, 6.25 },
+ {  377,  18.9421, -67.1239, 4.86 }, {  378,  19.4500,  +3.6144, 5.16 }, {  379,  19.6958, +37.3861, 6.46 }, {  380,  19.2650, -65.6019, 6.24 },
+ {  381,  20.4963, +76.2389, 6.38 }, {  382,  20.0204, +58.2317, 4.98 }, {  383,  19.8667, +27.2642, 4.76 }, {  384,  20.2717, +64.6583, 6.34 },
+ {  385,  19.9513,  +0.5089, 5.87 }, {  386,  20.9450, +78.7258, 6.07 }, {  387,  20.1438,  -2.7531, 6.23 }, {  388,  20.1158, -10.7611, 6.15 },
+ {  389,  20.2808, +28.7381, 5.23 }, {  390,  20.5850, +45.5289, 4.88 }, {  391,  20.8400, +58.1431, 6.45 }, {  392,  20.6542,  +1.7264, 6.20 },
+ {  393,  20.6450,  +0.4497, 6.49 }, {  394,  20.6271, -18.9186, 6.35 }, {  395,  20.9192, +37.7150, 5.58 }, {  396,  20.9063, +34.2458, 6.29 },
+ {  397,  20.8538, +20.4689, 5.97 }, {  398,  21.4438, +70.9800, 6.49 }, {  399,  21.4833, +68.1300, 4.74 }, {  400,  20.8792, -29.0544, 5.84 },
+ {  401,  21.0104,  -7.9925, 6.21 }, {  402,  21.0058,  -7.8167, 3.60 }, {  403,  21.4542, +60.2353, 2.68 }, {  404,  21.0858,  -5.0853, 5.91 },
+ {  405,  21.1658, -14.3397, 6.14 }, {  406,  21.2029,  -1.1514, 6.15 }, {  407,  21.3988, +23.5117, 6.18 }, {  408,  21.1700, -40.5075, 5.42 },
+ {  409,  21.5775, +43.4578, 5.96 }, {  410,  21.5362, +34.5797, 6.31 }, {  411,  21.1746, -43.4717, 6.26 }, {  412,  21.4050, -13.4011, 4.90 },
+ {  413,  21.5637, +19.1722, 5.38 }, {  414,  21.6737, +19.2403, 5.50 }, {  415,  21.7758, +34.3775, 6.27 }, {  416,  21.6138,  +0.3986, 6.41 },
+ {  417,  21.9142, +45.4067, 4.83 }, {  418,  21.8608, +41.1006, 6.46 }, {  419,  21.7229,  +3.5353, 6.58 }, {  420,  21.2721, -63.6306, 5.93 },
+ {  421,  21.7150, -12.9433, 5.66 }, {  422,  21.9458, +40.3356, 6.60 }, {  423,  21.7421, -31.4569, 5.79 }, {  424,  37.9529, +89.2642, 2.02 },
+ {  425,  21.9442,  -9.0983, 6.13 }, {  426,  22.0954,  +7.9614, 6.20 }, {  427,  22.8075, +70.2647, 5.81 }, {  428,  22.7179, +66.0981, 6.14 },
+ {  429,  22.0912, -42.6817, 3.41 }, {  430,  22.5258, +47.0072, 5.27 }, {  431,  22.1804, -32.2364, 6.58 }, {  432,  22.4704, +18.3556, 6.02 },
+ {  433,  22.4004, -20.3706, 5.12 }, {  434,  22.5463,  +6.1439, 4.84 }, {  435,  22.3767, -45.2436, 6.31 }, {  436,  22.5954, -25.7922, 5.93 },
+ {  437,  22.8708, +15.3458, 3.62 }, {  438,  23.0317, +34.8000, 6.39 }, {  439,  23.3575, +58.3275, 5.70 }, {  440,  22.8129, -48.9272, 3.95 },
+ {  441,  22.9304, -29.7167, 5.82 }, {  442,  23.4829, +59.2319, 4.71 }, {  443,  22.9129, -44.4244, 6.17 }, {  444,  23.2646,  -8.9853, 6.59 },
+ {  445,  23.2333, -35.1347, 5.51 }, {  446,  23.5692, +37.2372, 5.88 }, {  447,  23.1513, -48.2722, 6.28 }, {  448,  23.4288,  -6.9747, 5.76 },
+ {  449,  24.3438, +74.3008, 6.58 }, {  450,  23.7046, +18.4606, 5.89 }, {  451,  23.6575, -14.3239, 5.63 }, {  452,  23.9688, +41.0764, 6.38 },
+ {  453,  23.7113, -30.1078, 6.12 }, {  454,  24.1133, +48.7228, 5.92 }, {  455,  23.9433, +14.6614, 6.22 }, {  456,  24.6288, +73.0400, 5.28 },
+ {  457,  23.9783, +17.4336, 5.80 }, {  458,  24.1992, +41.4056, 4.09 }, {  459,  23.9958, -14.5997, 5.42 }, {  460,  23.8133, -57.8606, 6.01 },
+ {  461,  24.5317, +57.9775, 5.56 }, {  462,  24.0350, -28.0925, 5.69 }, {  463,  24.2746, +12.1417, 5.57 }, {  464,  24.4983, +48.6283, 3.57 },
+ {  465,  24.6321, +45.4000, 6.36 }, {  466,  24.4071,  -8.5961, 6.24 }, {  467,  23.4133, -77.4953, 6.11 }, {  468,  24.1867, -57.7292, 6.18 },
+ {  469,  24.8375, +44.3861, 4.98 }, {  470,  25.0546, +53.8683, 6.39 }, {  471,  24.6142, -35.4717, 5.94 }, {  472,  24.4288, -56.7633, 0.46 },
+ {  473,  24.7158, -20.7247, 5.58 }, {  474,  24.7083, -24.9781, 6.70 }, {  475,  24.9200, +16.4058, 5.97 }, {  476,  25.1658, +43.2978, 5.61 },
+ {  477,  25.1450, +40.5769, 4.94 }, {  478,  25.5854, +68.0431, 5.59 }, {  479,  24.7008, -52.5611, 6.84 }, {  480,  25.7329, +70.6225, 5.18 },
+ {  481,  25.5125, +61.0383, 6.71 }, {  482,  25.5742, +58.6278, 6.37 }, {  483,  25.4467, +42.6136, 4.95 }, {  484,  25.3267, +25.7458, 6.17 },
+ {  485,  25.4133, +30.0472, 5.99 }, {  486,  24.9475, -55.8019, 5.87 }, {  487,  24.9492, -55.8053, 5.76 }, {  488,  25.7433, +61.4217, 6.34 },
+ {  489,  25.3579,  +5.4875, 4.44 }, {  490,  25.5146, +35.2456, 5.64 }, {  491,  25.8321, +60.5511, 5.78 }, {  492,  25.4363, -10.6753, 5.75 },
+ {  493,  25.6242, +20.2686, 5.24 }, {  494,  25.3638, -37.8669, 6.17 }, {  495,  25.8188, +45.3222, 6.34 }, {  496,  25.9150, +50.6886, 4.07 },
+ {  497,  25.5358, -31.6731, 5.25 }, {  498,  25.5125, -35.1675, 5.72 }, {  499,  26.0746, +57.5364, 6.21 }, {  500,  25.6812,  -2.3097, 4.99 },
+ {  501,  25.4213, -49.9611, 6.64 }, {  502,  26.1921, +57.0892, 6.25 }, {  503,  25.9583, +32.1917, 6.34 }, {  504,  26.1104, +46.1397, 6.35 },
+ {  505,  25.4500, -59.2106, 5.71 }, {  506,  25.6221, -52.2594, 5.52 }, {  507,  25.9783,  -3.2344, 6.19 }, {  508,  26.2325, +20.0831, 6.27 },
+ {  509,  26.0171, -14.0625, 3.50 }, {  510,  26.3483,  +9.1578, 4.26 }, {  511,  26.9367, +63.8522, 5.63 }, {  512,  24.4817, -81.0250, 5.87 },
+ {  513,  26.4971,  -4.2667, 5.34 }, {  514,  26.4117, -24.9475, 5.31 }, {  515,  26.6471, +17.4131, 6.55 }, {  516,  25.3388, -78.8517, 6.33 },
+ {  517,  26.5042, -26.6508, 6.39 }, {  518,  26.9500, +46.2297, 6.32 }, {  519,  26.5242, -49.1836, 5.49 }, {  520,  26.5263, -52.4781, 5.04 },
+ {  521,  27.1621, +37.9528, 5.94 }, {  522,  27.0454, +16.9556, 5.84 }, {  523,  27.1733, +32.6903, 5.79 }, {  524,  26.8200, -40.2400, 6.18 },
+ {  525,  24.3667, -83.2303, 5.69 }, {  526,  27.3154, +47.8969, 5.82 }, {  527,  27.1083,  +3.6856, 5.91 }, {  528,  26.9492, -36.8403, 6.32 },
+ {  529,  27.7379, +51.9333, 5.90 }, {  530,  27.5354, +22.2753, 5.86 }, {  531,  27.3962,  -9.3136, 4.67 }, {  532,  27.3313, -30.9272, 6.34 },
+ {  533,  27.9971, +55.1475, 5.52 }, {  534,  27.7167, +11.0433, 5.94 }, {  535,  27.4533, -37.5961, 6.37 }, {  536,  28.0392, +50.7928, 5.79 },
+ {  537,  27.5842, -46.1836, 6.14 }, {  538,  28.2117, +51.4747, 6.26 }, {  539,  27.8650,  -9.6650, 3.73 }, {  540,  28.4521, +55.5981, 6.45 },
+ {  541,  27.7271, -49.7939, 5.94 }, {  542,  28.5987, +63.6700, 3.38 }, {  543,  28.3221, +40.7297, 5.40 }, {  544,  28.2704, +29.5789, 3.41 },
+ {  545,  28.3825, +19.2958, 4.83 }, {  546,  28.3825, +19.2936, 4.75 }, {  547,  28.2171, -15.0708, 5.80 }, {  548,  29.0000, +68.6853, 4.99 },
+ {  549,  28.3888,  +3.1875, 4.62 }, {  550,  26.9438, -79.8233, 6.06 }, {  551,  28.7242, +40.7019, 6.24 }, {  552,  28.7396, +37.1283, 6.26 },
+ {  553,  28.6600, +20.8081, 2.64 }, {  554,  28.3467, -37.4053, 6.10 }, {  555,  28.4117, -45.6975, 4.41 }, {  556,  28.9767, +37.2778, 5.89 },
+ {  557,  29.0388, +37.2517, 5.67 }, {  558,  28.5917, -41.5031, 5.11 }, {  559,  28.9625, +23.5772, 5.74 }, {  560,  28.9742,  +1.8497, 6.01 },
+ {  561,  29.6388, +61.6981, 6.02 }, {  562,  29.4850, +41.6944, 6.78 }, {  563,  29.3379, +17.8175, 5.10 }, {  564,  29.4325, +27.8044, 5.82 },
+ {  565,  29.1675, -21.4731, 4.85 }, {  566,  28.9896, -50.3911, 3.70 }, {  567,  29.9083, +64.6214, 5.26 }, {  568,  29.6400, +49.2042, 5.69 },
+ {  569,  29.4821, +23.5961, 4.79 }, {  570,  28.7338, -66.3528, 4.69 }, {  571,  28.9433, -59.1386, 6.06 }, {  572,  30.7383, +77.9164, 6.04 },
+ {  573,  29.2504, -50.2339, 6.10 }, {  574,  29.2917, -46.6150, 4.83 }, {  575,  30.4892, +70.9069, 4.54 }, {  576,  29.6112, -32.9333, 6.35 },
+ {  577,  29.8988, +21.0583, 5.87 }, {  578,  29.8579, +12.2947, 6.09 }, {  579,  30.7937, +73.8506, 6.23 }, {  580,  30.8588, +72.4214, 3.98 },
+ {  581,  31.2808, +77.2814, 5.38 }, {  582,  30.0383,  +3.0972, 5.88 }, {  583,  29.9421, -19.1756, 5.41 }, {  584,  29.4733, -64.5753, 6.37 },
+ {  585,  30.0012, -20.9222, 4.00 }, {  586,  30.7196, +64.9014, 6.00 }, {  587,  30.1121,  -7.4764, 5.51 }, {  588,  29.9117, -41.9694, 5.57 },
+ {  589,  30.7512, +64.3900, 5.58 }, {  590,  30.5754, +54.4875, 5.04 }, {  591,  29.6925, -60.4303, 2.86 }, {  592,  31.3800, +76.1150, 5.22 },
+ {  593,  28.9604, -77.6517, 6.16 }, {  594,  30.3113, -29.9983, 5.35 }, {  595,  30.5117,  +2.7636, 5.23 }, {  596,  30.5117,  +2.7636, 4.33 },
+ {  597,  32.3554, +81.2958, 6.05 }, {  598,  31.1671, +65.1033, 6.52 }, {  599,  30.7417, +33.2839, 5.50 }, {  600,  29.9213, -65.9336, 6.10 },
+ {  601,  30.6467, +13.4767, 5.94 }, {  602,  30.4267, -43.2864, 5.14 }, {  603,  30.9750, +42.3297, 2.26 }, {  604,  30.9779, +42.3308, 4.84 },
+ {  605,  30.9138, +25.9356, 5.63 }, {  606,  30.6171, -28.3350, 6.42 }, {  607,  30.7987,  +0.1283, 5.43 }, {  608,  30.7442, -14.6942, 5.86 },
+ {  609,  30.9275, +18.2533, 6.21 }, {  610,  30.9508,  +0.3403, 5.93 }, {  611,  30.9187,  -3.8964, 5.62 }, {  612,  31.1225, -28.7031, 4.69 },
+ {  613,  31.6412, +22.6483, 5.03 }, {  614,  31.5513,  +8.2475, 6.31 }, {  615,  31.7050, +25.7047, 6.15 }, {  616,  31.6221,  +0.0350, 6.28 },
+ {  617,  31.7933, +23.4625, 2.00 }, {  618,  32.1688, +58.4236, 5.67 }, {  619,  32.1400, +44.4594, 6.42 }, {  620,  32.1221, +37.8592, 4.82 },
+ {  621,  32.5325, +53.8431, 6.31 }, {  622,  32.3858, +34.9872, 3.00 }, {  623,  32.3554, +25.9397, 4.98 }, {  624,  32.3462, +17.2244, 6.43 },
+ {  625,  32.1904, -16.2206, 6.10 }, {  626,  33.3383, +74.0278, 6.29 }, {  627,  32.8708, +57.6458, 6.36 }, {  628,  32.7200, +39.0394, 5.63 },
+ {  629,  32.7238, +39.0431, 6.10 }, {  630,  32.3950, -23.6542, 6.48 }, {  631,  32.6567, +19.5003, 5.70 }, {  632,  32.2888, -42.4833, 5.85 },
+ {  633,  32.8000, +25.9369, 6.02 }, {  634,  32.8542, +31.5264, 6.23 }, {  635,  32.8379,  +8.5697, 5.63 }, {  636,  32.5204, -42.1844, 6.32 },
+ {  637,  32.6067, -49.1756, 6.12 }, {  638,  32.8425,  -9.9478, 6.01 }, {  639,  32.8992,  -0.1747, 5.93 }, {  640,  33.6213, +66.5244, 6.07 },
+ {  641,  33.4229, +58.5611, 6.44 }, {  642,  33.0929, +30.3031, 4.94 }, {  643,  33.3054, +44.2317, 4.83 }, {  644,  33.1563, +24.1678, 5.96 },
+ {  645,  33.4012, +51.0658, 5.31 }, {  646,  33.2004, +21.2108, 5.27 }, {  647,  33.5108, +47.4842, 6.06 }, {  648,  33.2638, +15.2797, 5.71 },
+ {  649,  33.2500,  +8.8467, 4.37 }, {  650,  33.1979,  -1.6064, 5.54 }, {  651,  33.2537, -20.9997, 5.86 }, {  652,  33.2271, -29.2761, 5.28 },
+ {  653,  33.9913, +47.8114, 6.33 }, {  654,  34.2154, +57.0553, 6.48 }, {  655,  33.9842, +33.3589, 5.28 }, {  656,  33.9417, +25.7831, 5.79 },
+ {  657,  33.9283, +25.0431, 5.58 }, {  658,  33.8679,  -8.5344, 6.55 }, {  659,  33.6333, -40.8333, 5.91 }, {  660,  34.2633, +34.2242, 4.87 },
+ {  661,  34.4996, +57.8997, 5.75 }, {  662,  34.5187, +57.5167, 5.98 }, {  663,  34.3892, +44.3069, 6.70 }, {  664,  34.3287, +33.8472, 4.01 },
+ {  665,  34.2933, +23.7678, 6.55 }, {  666,  34.2458,  -5.5778, 5.51 }, {  667,  33.5613, -66.1583, 5.55 }, {  668,  35.0538, +64.3372, 6.60 },
+ {  669,  34.5313, +19.9011, 5.62 }, {  670,  34.8200, +47.3800, 5.30 }, {  671,  34.7954, +46.4725, 6.21 }, {  672,  34.5058,  +1.7578, 5.58 },
+ {  673,  34.8446, +48.9553, 6.37 }, {  674,  34.1275, -50.4878, 3.56 }, {  675,  34.7375, +28.6425, 5.03 }, {  676,  34.7417, +23.1678, 6.46 },
+ {  677,  34.9054, +39.8350, 6.63 }, {  678,  33.8687, -66.2536, 5.69 }, {  679,  35.1725, +47.3108, 6.11 }, {  680,  35.0183, +30.1883, 6.47 },
+ {  681,  34.8363,  -1.0225, 3.04 }, {  682,  35.2425, +50.1514, 5.59 }, {  683,  34.7437, -24.0544, 6.34 }, {  684,  34.9200,  -3.6544, 6.50 },
+ {  685,  35.5892, +55.8456, 5.17 }, {  686,  34.8529, -40.1517, 6.37 }, {  687,  35.7096, +41.3964, 5.82 }, {  688,  34.9763, -54.0553, 5.81 },
+ {  689,  35.4858,  +0.3958, 5.28 }, {  690,  35.9658, +55.3644, 6.28 }, {  691,  35.5517,  +0.8850, 5.42 }, {  692,  35.5058,  -9.2222, 5.46 },
+ {  693,  35.5208, -16.3378, 5.87 }, {  694,  36.1037, +50.0067, 5.19 }, {  695,  35.6358, -22.1836, 5.20 }, {  696,  36.3167, +56.6100, 6.25 },
+ {  697,  35.7408, -17.6456, 6.22 }, {  698,  35.5492, -42.8000, 6.31 }, {  699,  36.4058, +50.2786, 4.71 }, {  700,  35.7771, -36.4236, 6.53 },
+ {  701,  35.7275, -50.9078, 5.92 }, {  702,  36.2042, +10.6106, 5.47 }, {  703,  36.0838, -24.1525, 6.44 }, {  704,  36.2433,  -1.2200, 6.33 },
+ {  705,  35.4371, -67.3406, 4.09 }, {  706,  36.1408, -39.1594, 6.18 }, {  707,  37.2667, +67.4025, 4.52 }, {  708,  36.4875, -11.7094, 4.89 },
+ {  709,  36.9658, +50.5697, 6.12 }, {  710,  36.5012, -14.6589, 5.83 }, {  711,  36.7792, +27.0133, 6.18 }, {  712,  36.8654, +31.8014, 5.54 },
+ {  713,  36.6467, -19.9572, 5.88 }, {  714,  36.2246, -59.6881, 5.35 }, {  715,  35.7179, -72.3542, 5.01 }, {  716,  37.3542, +55.5364, 6.51 },
+ {  717,  37.0417, +29.6694, 5.29 }, {  718,  37.0396,  +8.4600, 4.28 }, {  719,  37.0000,  +1.9608, 6.45 }, {  720,  37.2021, +29.9319, 5.89 },
+ {  721,  36.7463, -46.2961, 4.25 }, {  722,  36.3596, -65.5053, 6.41 }, {  723,  37.3067, +23.4689, 6.19 }, {  724,  37.0071, -32.1889, 5.14 },
+ {  725,  37.3971,  +9.5658, 6.07 }, {  726,  37.5692, +33.8339, 6.25 }, {  727,  37.1475, -30.8975, 6.11 }, {  728,  37.6350, +25.2350, 5.92 },
+ {  729,  37.6600, +19.8553, 6.15 }, {  730,  37.4808, -21.3172, 6.77 }, {  731,  37.7267, +17.7039, 6.23 }, {  732,  37.6883,  +0.2553, 6.00 },
+ {  733,  37.5575, -24.8136, 6.51 }, {  734,  37.0183, -63.7003, 6.37 }, {  735,  37.6367, -21.4544, 6.10 }, {  736,  38.0258, +36.1472, 5.15 },
+ {  737,  37.8754,  +2.2672, 5.25 }, {  738,  38.2188, +34.5425, 5.83 }, {  739,  38.0392,  -0.9650, 5.35 }, {  740,  38.0217, -14.7553, 4.75 },
+ {  741,  38.2254, +15.0347, 6.04 }, {  742,  38.0617, -35.5725, 6.30 }, {  743,  39.5083, +72.8183, 5.16 }, {  744,  38.2792, -33.3500, 5.90 },
+ {  745,  38.4175, -19.9981, 6.21 }, {  746,  38.8663, +39.6644, 6.36 }, {  747,  39.4004, +65.7456, 5.78 }, {  748,  38.9117, +37.3122, 5.71 },
+ {  749,  38.4613, -27.7675, 4.90 }, {  750,  38.9450, +34.6875, 5.35 }, {  751,  38.7671,  +7.4714, 6.18 }, {  752,  38.6779,  -6.1406, 5.75 },
+ {  753,  39.0204,  +6.8869, 5.82 }, {  754,  38.9688,  +5.5933, 4.86 }, {  755,  38.4775, -50.9064, 6.24 }, {  756,  39.2383, +38.7328, 5.90 },
+ {  757,  39.1788, +31.6075, 6.10 }, {  758,  39.2604, +34.2639, 5.30 }, {  759,  39.0000,  -6.1683, 5.53 }, {  760,  39.3367, +39.8958, 6.54 },
+ {  761,  39.2767, +32.8919, 6.25 }, {  762,  38.3900, -61.4131, 6.77 }, {  763,  39.1579, +12.4475, 5.68 }, {  764,  39.2404, +24.6483, 7.09 },
+ {  765,  39.2521, +24.6475, 6.50 }, {  766,  39.1463,  +7.7297, 5.81 }, {  767,  39.0388, -29.9553, 5.75 }, {  768,  39.5742, +37.7267, 6.18 },
+ {  769,  39.6158, +38.0894, 6.30 }, {  770,  39.5033,  +7.6953, 6.39 }, {  771,  39.4242,  -2.6039, 5.65 }, {  772,  39.2442, -33.4217, 5.79 },
+ {  773,  39.7042, +21.9614, 5.43 }, {  774,  41.9483, +81.4483, 5.78 }, {  775,  39.6538,  +3.4431, 6.21 }, {  776,  37.9188, -78.8906, 5.28 },
+ {  777,  39.5779, -29.8058, 5.83 }, {  778,  39.3517, -51.4569, 5.31 }, {  779,  39.8708,  +0.3286, 4.07 }, {  780,  39.6033, -36.0094, 6.49 },
+ {  781,  39.8908, -10.1278, 4.84 }, {  782,  40.1713, +27.0608, 5.30 }, {  783,  40.0654,  +6.1119, 6.25 }, {  784,  40.0513,  -8.5469, 5.78 },
+ {  785,  40.7617, +55.1058, 5.77 }, {  786,  40.0104, -29.3661, 6.52 }, {  787,  40.7488, +53.5261, 5.84 }, {  788,  40.5621, +40.1939, 4.91 },
+ {  789,  39.9500, -41.1083, 4.75 }, {  790,  40.3079,  +0.6958, 5.71 }, {  791,  41.2071, +67.8247, 5.95 }, {  792,  40.7579, +48.2656, 6.48 },
+ {  793,  40.5917, +20.0117, 5.69 }, {  794,  40.1667, -38.1444, 4.11 }, {  795,  40.4513,  -2.7867, 6.05 }, {  796,  40.3917, -13.4506, 5.98 },
+ {  797,  40.6204, +10.7417, 6.30 }, {  798,  39.8821, -63.7181, 6.55 }, {  799,  41.0500, +49.2283, 4.12 }, {  800,  41.0217, +44.2969, 5.43 },
+ {  801,  40.8629, +27.7072, 4.66 }, {  802,  40.1650, -53.4500, 5.21 }, {  803,  40.9633, +25.6381, 6.35 }, {  804,  40.8250,  +3.2358, 3.47 },
+ {  805,  40.5275, -37.6161, 6.01 }, {  806,  39.8975, -67.7331, 4.11 }, {  807,  40.5354, -45.4756, 6.10 }, {  808,  41.0796, +17.7639, 6.46 },
+ {  809,  41.1371, +15.3117, 5.77 }, {  810,  40.6396, -49.1997, 5.41 }, {  811,  41.0308, -12.1414, 4.25 }, {  812,  41.2400, +12.4458, 5.18 },
+ {  813,  41.2354, +10.1142, 4.27 }, {  814,  40.8346, -39.4725, 6.36 }, {  815,  42.2313, +69.6342, 6.18 }, {  816,  41.3371,  +4.7117, 6.03 },
+ {  817,  41.0854, -31.4750, 6.22 }, {  818,  41.2758, -17.4275, 4.47 }, {  819,  41.7429, +35.9836, 6.25 }, {  820,  41.7646, +35.5550, 6.30 },
+ {  821,  41.0446, -51.4294, 6.15 }, {  822,  41.3188, -45.7128, 6.85 }, {  823,  40.8608, -65.2856, 6.26 }, {  824,  41.9771, +29.2472, 4.51 },
+ {  825,  42.3783, +57.0842, 6.25 }, {  826,  41.6883, -20.3603, 6.49 }, {  827,  41.7967, -21.5144, 6.47 }, {  828,  42.1337, +18.2836, 5.82 },
+ {  829,  42.9946, +68.8886, 5.80 }, {  830,  42.1912, +25.1881, 5.86 }, {  831,  42.3629, +37.3261, 6.45 }, {  832,  41.9833, -11.5394, 6.90 },
+ {  833,  41.3646, -62.2956, 5.74 }, {  834,  42.6742, +55.8956, 3.76 }, {  835,  41.8904, -34.4492, 6.51 }, {  836,  42.3229, +17.4642, 5.22 },
+ {  837,  41.3858, -66.3833, 4.84 }, {  838,  42.4958, +27.2606, 3.63 }, {  839,  42.9396, +58.3147, 6.45 }, {  840,  42.6463, +38.3186, 4.23 },
+ {  841,  42.2725, -31.5942, 4.46 }, {  842,  42.9237, +46.8419, 5.88 }, {  843,  42.8783, +35.0597, 4.53 }, {  844,  42.4625, -23.4397, 6.14 },
+ {  845,  42.4758, -26.0583, 5.39 }, {  846,  43.2167, +52.9978, 6.36 }, {  847,  42.8733, +15.0819, 5.49 }, {  848,  42.5617, -34.1564, 5.92 },
+ {  849,  43.3383, +48.5694, 6.26 }, {  850,  42.7596, -20.9958, 4.75 }, {  851,  42.6683, -34.3239, 5.47 }, {  852,  42.2563, -61.1933, 5.26 },
+ {  853,  42.6996, -38.0683, 6.36 }, {  854,  43.5646, +52.7625, 3.95 }, {  855,  43.4275, +38.3375, 5.33 }, {  856,  43.2987, +16.4833, 6.31 },
+ {  857,  43.1337, -11.2306, 6.04 }, {  858,  42.9804, -29.1856, 6.40 }, {  859,  43.2104,  -8.5589, 6.32 }, {  860,  43.9871, +61.5211, 5.59 },
+ {  861,  44.1033, +64.3325, 6.24 }, {  862,  43.3971, -21.6236, 5.95 }, {  863,  43.3933, -37.5631, 5.92 }, {  864,  44.2108, +51.2608, 6.22 },
+ {  865,  44.1392, +47.1639, 6.02 }, {  866,  43.0800, -61.0903, 6.03 }, {  867,  43.9521, +18.3317, 5.91 }, {  868,  43.4704, -48.1097, 4.00 },
+ {  869,  44.1088, +18.0231, 5.63 }, {  870,  44.0575,  +8.3817, 5.97 }, {  871,  43.5271, -49.1286, 6.21 }, {  872,  42.6187, -74.9331, 4.75 },
+ {  873,  44.3221, +31.9342, 5.11 }, {  874,  44.1071,  -7.1019, 3.89 }, {  875,  44.1558,  -2.2878, 5.17 }, {  876,  44.5096, +38.6150, 6.04 },
+ {  877,  44.2692,  +4.5011, 6.11 }, {  878,  44.5217, +20.6686, 5.80 }, {  879,  44.6904, +39.6628, 4.70 }, {  880,  43.5871, -63.5644, 6.56 },
+ {  881,  46.5325, +79.4186, 5.49 }, {  882,  44.7654, +35.1831, 4.93 }, {  883,  44.3488, -22.1381, 5.45 }, {  884,  44.3046, -28.1447, 6.29 },
+ {  885,  44.9579, +47.2208, 5.47 }, {  886,  44.9162, +41.0331, 5.89 }, {  887,  44.8029, +21.3403, 4.63 }, {  888,  44.8029, +21.3403, 4.63 },
+ {  889,  44.5238, -22.3939, 5.84 }, {  890,  45.2175, +52.3517, 5.28 }, {  891,  45.2225, +52.3522, 6.74 }, {  892,  44.6750,  -1.2175, 5.23 },
+ {  893,  44.3862, -37.8089, 6.41 }, {  894,  45.0492, +38.1317, 6.11 }, {  895,  44.6975,  -8.2236, 6.14 }, {  896,  44.9288,  +8.9075, 4.70 },
+ {  897,  44.5654, -39.6953, 3.24 }, {  898,  44.5679, -39.6956, 4.35 }, {  899,  44.9217,  -1.5350, 5.56 }, {  900,  44.7775, -27.0931, 6.14 },
+ {  901,  44.9004, -24.7258, 5.71 }, {  902,  45.1838, +10.8703, 5.95 }, {  903,  44.9096, -31.4928, 6.31 }, {  904,  45.2125,  -1.1214, 6.11 },
+ {  905,  45.4754, +26.4622, 5.90 }, {  906,  47.9283, +81.4706, 5.95 }, {  907,  45.2917,  -6.3372, 5.75 }, {  908,  45.4679,  +5.3361, 6.25 },
+ {  909,  44.6992, -63.9286, 4.99 }, {  910,  45.5938,  +4.3528, 5.61 }, {  911,  45.5700,  +4.0897, 2.53 }, {  912,  45.4838,  -8.0386, 5.83 },
+ {  913,  45.5388,  -5.5053, 6.19 }, {  914,  45.4071, -27.9083, 5.89 }, {  915,  46.1992, +53.5064, 2.93 }, {  916,  45.8762, +28.2697, 6.36 },
+ {  917,  45.6763,  -6.3147, 5.32 }, {  918,  46.3850, +56.7058, 4.76 }, {  919,  45.5979, -22.3756, 4.09 }, {  920,  46.4162, +56.0686, 6.11 },
+ {  921,  46.2942, +38.8403, 3.39 }, {  922,  46.8292, +64.0578, 5.89 }, {  923,  46.3367, +40.5825, 6.05 }, {  924,  46.1696, +15.8561, 6.49 },
+ {  925,  46.0683,  -6.3992, 5.26 }, {  926,  46.1587,  +1.8636, 6.05 }, {  927,  46.3612, +25.2553, 6.80 }, {  928,  46.3612, +25.2553, 7.00 },
+ {  929,  45.7329, -45.0250, 5.82 }, {  930,  47.0162, +52.2133, 6.31 }, {  931,  46.5988, +13.1872, 5.62 }, {  932,  47.9846, +74.3936, 4.87 },
+ {  933,  46.9475, +47.3083, 6.41 }, {  934,  45.9033, -58.2622, 5.11 }, {  935,  46.6396,  -5.9114, 5.27 }, {  936,  47.0421, +40.9556, 2.12 },
+ {  937,  47.2667, +49.6133, 4.05 }, {  938,  46.8571, +17.8800, 6.11 }, {  939,  45.5642, -70.0975, 5.53 }, {  940,  47.0883, +18.7950, 6.27 },
+ {  941,  47.3742, +44.8572, 3.80 }, {  942,  47.1613,  +8.4708, 6.28 }, {  943,  46.9621, -26.1689, 6.19 }, {  944,  47.4029, +29.0769, 5.72 },
+ {  945,  47.5367, +27.8200, 6.42 }, {  946,  47.6125, +26.8964, 6.02 }, {  947,  47.8225, +39.6117, 4.63 }, {  948,  47.6621, +11.8725, 5.98 },
+ {  949,  48.1100, +47.7258, 6.33 }, {  950,  48.0400, +42.3761, 6.15 }, {  951,  47.9075, +19.7267, 4.35 }, {  952,  47.8413, +13.0478, 6.12 },
+ {  953,  47.6475, -22.2617, 6.38 }, {  954,  48.0592, +27.2569, 5.79 }, {  955,  47.8283,  -2.1883, 6.05 }, {  956,  48.3500, +48.1769, 5.90 },
+ {  957,  47.8200, -15.9747, 6.26 }, {  958,  48.1100,  +6.6608, 5.56 }, {  959,  46.9550, -68.7344, 6.15 }, {  960,  47.6142, -47.2658, 6.12 },
+ {  961,  50.0821, +77.7347, 5.45 }, {  962,  48.1933,  -0.8039, 5.06 }, {  963,  48.0179, -27.0131, 3.87 }, {  964,  48.9500, +57.1408, 5.79 },
+ {  965,  53.0838, +84.9111, 5.61 }, {  966,  48.7362, +42.5039, 6.07 }, {  967,  49.3817, +65.6586, 6.36 }, {  968,  48.1075, -43.5803, 5.93 },
+ {  969,  49.0508, +50.9378, 5.03 }, {  970,  48.2563, -34.0561, 6.27 }, {  971,  48.8354, +30.5567, 5.52 }, {  972,  48.7254, +21.0444, 4.89 },
+ {  973,  49.0196, +45.3458, 6.16 }, {  974,  48.4083, -28.1958, 6.16 }, {  975,  48.9458, +32.8564, 6.31 }, {  976,  49.0079, +34.6886, 6.25 },
+ {  977,  48.1383, -56.6783, 5.74 }, {  978,  49.1463, +32.1836, 6.06 }, {  979,  49.2975, +40.4833, 6.45 }, {  980,  48.7508, -25.8997, 6.25 },
+ {  981,  46.8833, -77.0106, 5.57 }, {  982,  49.4475, +44.0250, 5.47 }, {  983,  49.0037,  -4.0814, 6.17 }, {  984,  48.9583,  -7.1803, 4.80 },
+ {  985,  49.9975, +65.6522, 4.84 }, {  986,  49.4408, +39.2833, 5.96 }, {  987,  49.6575, +50.2222, 5.15 }, {  988,  49.1488,  -8.8456, 6.14 },
+ {  989,  49.7817, +50.0950, 5.03 }, {  990,  49.0471, -29.1725, 6.65 }, {  991,  49.6825, +34.2228, 4.82 }, {  992,  49.5933,  +0.9303, 5.38 },
+ {  993,  49.5117, -27.2031, 5.91 }, {  994,  49.5921, -21.4886, 4.88 }, {  995,  49.9825, +27.0711, 5.90 }, {  996,  49.8404,  +3.3703, 4.83 },
+ {  997,  49.6717, -17.4403, 5.71 }, {  998,  49.3608, -46.2483, 5.85 }, {  999,  50.0850, +29.0483, 4.47 }, { 1000,  50.1067, +25.6628, 6.12 },
+ { 1001,  50.4692, +49.0708, 5.93 }, { 1002,  50.3604, +43.3294, 4.95 }, { 1003,  49.8792, -20.2422, 3.69 }, { 1004,  49.8950, -23.8769, 5.61 },
+ { 1005,  50.3067, +21.1469, 5.28 }, { 1006,  49.4425, -61.4247, 5.54 }, { 1007,  50.2783,  +3.6756, 5.69 }, { 1008,  49.9821, -42.9303, 4.27 },
+ { 1009,  51.1688, +64.5861, 5.23 }, { 1010,  49.5538, -61.4936, 5.24 }, { 1011,  50.8050, +49.2133, 5.29 }, { 1012,  50.5496, +27.6075, 5.52 },
+ { 1013,  50.1883, -25.3936, 6.39 }, { 1014,  49.4958, -65.0731, 6.05 }, { 1015,  50.6883, +20.7419, 5.09 }, { 1016,  50.3500, -22.3647, 5.52 },
+ { 1017,  51.0808, +49.8611, 1.79 }, { 1018,  50.5679, -24.4122, 6.35 }, { 1019,  51.1238, +33.5358, 5.61 }, { 1020,  51.4517, +53.9217, 6.51 },
+ { 1021,  50.3888, -46.2231, 6.39 }, { 1022,  51.0771, +24.7242, 5.50 }, { 1023,  50.9129,  +4.8819, 6.38 }, { 1024,  50.8242,  -6.2058, 6.20 },
+ { 1025,  48.9900, -76.6117, 5.52 }, { 1026,  51.2892, +41.2572, 6.51 }, { 1027,  51.1088, +20.8036, 6.08 }, { 1028,  51.0421, +12.6294, 6.04 },
+ { 1029,  51.4892, +49.1208, 6.09 }, { 1030,  51.2033,  +9.0289, 3.60 }, { 1031,  50.9358, -31.2928, 6.50 }, { 1032,  52.5812, +71.8639, 6.32 },
+ { 1033,  52.0983, +60.2556, 6.49 }, { 1034,  52.0129, +49.0628, 4.98 }, { 1035,  52.2671, +59.9403, 4.21 }, { 1036,  51.7633, +18.7564, 6.57 },
+ { 1037,  52.2183, +49.8483, 5.58 }, { 1038,  51.7925,  +9.7328, 3.74 }, { 1039,  51.8279, +12.7350, 6.28 }, { 1040,  52.4787, +58.8786, 4.54 },
+ { 1041,  52.0867, +33.8075, 5.61 }, { 1042,  51.4825, -34.0792, 6.39 }, { 1043,  52.5471, +59.3661, 6.13 }, { 1044,  52.3421, +49.5089, 4.67 },
+ { 1045,  51.5938, -26.6825, 5.93 }, { 1046,  52.5008, +55.4519, 5.09 }, { 1047,  52.3592, +46.9378, 6.24 }, { 1048,  52.1108, +22.8042, 6.03 },
+ { 1049,  51.5487, -40.3631, 6.32 }, { 1050,  52.0042, -10.7133, 5.73 }, { 1051,  52.6542, +48.1036, 5.82 }, { 1052,  52.6437, +47.9953, 4.36 },
+ { 1053,  51.0104, -68.3753, 6.15 }, { 1054,  51.8892, -34.3186, 5.71 }, { 1055,  53.8017, +73.3469, 6.57 }, { 1056,  52.8725, +49.2097, 6.29 },
+ { 1057,   0.0000,  +0.0000, 0.00 }, { 1058,  52.0479, -34.1467, 6.50 }, { 1059,  52.9546, +49.4008, 6.39 }, { 1060,  52.4129,  -5.1950, 5.99 },
+ { 1061,  52.6021, +11.3364, 5.14 }, { 1062,  52.4000, -11.3253, 5.59 }, { 1063,  53.0358, +48.0236, 5.47 }, { 1064,  51.4008, -68.6636, 5.96 },
+ { 1065,  52.8367, +27.5719, 5.96 }, { 1066,  52.7183, +12.9367, 4.11 }, { 1067,  52.6892,  +6.1886, 5.94 }, { 1068,  53.3837, +58.7650, 6.40 },
+ { 1069,  53.1096, +46.0569, 5.31 }, { 1070,  52.6546,  -4.9247, 4.73 }, { 1071,  53.4217, +57.8689, 6.37 }, { 1072,  53.1629, +44.8556, 6.41 },
+ { 1073,  53.4125, +54.9747, 5.98 }, { 1074,  53.1667, +35.4617, 5.90 }, { 1075,  52.4792, -41.3658, 5.78 }, { 1076,  52.5567, -40.6300, 6.12 },
+ { 1077,  53.7533, +60.0411, 6.46 }, { 1078,  53.3963, +39.8994, 5.81 }, { 1079,  53.1500,  +9.3736, 5.77 }, { 1080,  54.8533, +75.7397, 6.27 },
+ { 1081,  52.6542, -46.6247, 5.99 }, { 1082,  52.9746, -24.3858, 6.38 }, { 1083,  52.3446, -61.0625, 4.72 }, { 1084,  53.2325,  -8.5417, 3.73 },
+ { 1085,  53.5346, +17.8328, 6.17 }, { 1086,  53.6108, +24.4644, 5.92 }, { 1087,  54.1225, +48.1928, 4.23 }, { 1088,  53.4471, -20.3672, 4.27 },
+ { 1089,  53.7050,  +6.4178, 6.49 }, { 1090,  53.1450, -49.6214, 5.68 }, { 1091,  53.6558,  -8.1314, 6.25 }, { 1092,  52.7150, -65.5103, 5.83 },
+ { 1093,  53.4867, -30.9197, 6.20 }, { 1094,  54.5821, +56.9328, 6.30 }, { 1095,  53.6396, -30.1253, 6.40 }, { 1096,  53.2150, -60.9831, 6.41 },
+ { 1097,  54.5008, +42.5831, 6.42 }, { 1098,  53.9904, -10.8064, 5.57 }, { 1099,  54.1971,  +0.5878, 5.71 }, { 1100,  54.0725, -16.5331, 5.23 },
+ { 1101,  54.2183,  +0.4017, 4.28 }, { 1102,  54.4492, +15.4308, 6.39 }, { 1103,  54.7504, +20.9158, 6.50 }, { 1104,  53.6029, -64.2356, 6.75 },
+ { 1105,  55.5388, +63.2167, 5.10 }, { 1106,  54.2738, -39.7253, 4.58 }, { 1107,  62.5063, +86.6261, 5.86 }, { 1108,  54.6217,  -6.6083, 5.85 },
+ { 1109,  52.4950, -77.6481, 5.70 }, { 1110,  54.8571, +16.5367, 6.16 }, { 1111,  54.7546,  -4.3739, 5.96 }, { 1112,  55.6779, +59.9694, 5.76 },
+ { 1113,  55.2829, +37.5800, 5.57 }, { 1114,  54.6987, -26.0569, 6.01 }, { 1115,  54.9629,  +3.0569, 5.57 }, { 1116,  54.9096,  -2.6069, 6.23 },
+ { 1117,  54.8558,  -9.5628, 6.19 }, { 1118,  55.1929, +25.3294, 6.11 }, { 1119,  54.9979,  -0.8794, 6.12 }, { 1120,  55.0475, -14.7733, 6.33 },
+ { 1121,  55.1596,  -4.7894, 5.53 }, { 1122,  55.7313, +47.7875, 3.01 }, { 1123,  55.5938, +33.9650, 4.97 }, { 1124,  56.5037, +67.2017, 5.80 },
+ { 1125,  55.3075, -10.1969, 6.49 }, { 1126,  55.5787, +19.7003, 5.69 }, { 1127,  56.0267, +48.5236, 6.06 }, { 1128,  55.3433, -18.4153, 6.59 },
+ { 1129,  56.5096, +63.3450, 4.80 }, { 1130,  56.1704, +46.0997, 6.11 }, { 1131,  56.0796, +32.2883, 3.83 }, { 1132,  55.9467, +19.6650, 6.14 },
+ { 1133,  56.1308, +36.4600, 5.59 }, { 1134,  55.5621, -30.0617, 5.00 }, { 1135,  56.2983, +42.5786, 3.77 }, { 1136,  55.8121,  -8.2367, 3.54 },
+ { 1137,  56.1171, +20.9286, 6.10 }, { 1138,  57.3075, +70.8711, 5.44 }, { 1139,  55.8908,  -9.5144, 5.60 }, { 1140,  56.2008, +24.2894, 5.46 },
+ { 1141,  56.4971, +45.6819, 5.66 }, { 1142,  56.2188, +24.1133, 3.70 }, { 1143,  55.7088, -36.6864, 4.59 }, { 1144,  56.2904, +24.8392, 5.64 },
+ { 1145,  56.3021, +24.4672, 4.30 }, { 1146,  56.1271,  -0.8369, 5.25 }, { 1147,  56.8842, +55.9225, 6.10 }, { 1148,  57.5896, +71.3322, 4.63 },
+ { 1149,  56.4567, +24.3678, 3.87 }, { 1150,  56.2354,  +0.2967, 5.55 }, { 1151,  56.4767, +24.5547, 5.76 }, { 1152,  56.5121, +24.5281, 6.43 },
+ { 1153,  56.4183,  +6.0500, 5.35 }, { 1154,  54.1250, -77.6769, 6.29 }, { 1155,  57.3800, +65.5261, 4.47 }, { 1156,  56.5817, +23.9483, 4.18 },
+ { 1157,  56.0258, -39.3397, 6.45 }, { 1158,  57.4029, +63.2972, 5.85 }, { 1159,  56.5396,  +6.8031, 5.91 }, { 1160,  57.0763, +50.7367, 6.14 },
+ { 1161,  57.3317, +57.1181, 6.46 }, { 1162,  56.5354, -11.8983, 4.42 }, { 1163,  56.9692, +33.6000, 6.57 }, { 1164,  56.9537, +32.1950, 6.25 },
+ { 1165,  56.8713, +24.1050, 2.87 }, { 1166,  57.9242, +68.5075, 6.32 }, { 1167,  56.2108, -47.9386, 6.49 }, { 1168,  56.1408, -53.7261, 6.30 },
+ { 1169,  56.3158, -46.6403, 5.73 }, { 1170,  57.2842, +43.9631, 6.02 }, { 1171,  56.6142, -28.6619, 5.90 }, { 1172,  57.0871, +23.4211, 5.45 },
+ { 1173,  56.7121, -22.7503, 4.23 }, { 1174,  57.0679, +11.1433, 5.07 }, { 1175,  56.0500, -63.1931, 3.85 }, { 1176,  57.5187, +44.9678, 5.66 },
+ { 1177,  57.3858, +33.0914, 5.11 }, { 1178,  57.2904, +24.0533, 3.63 }, { 1179,  56.8338, -28.0981, 6.55 }, { 1180,  57.2967, +24.1367, 5.09 },
+ { 1181,  56.9150, -22.1253, 5.24 }, { 1182,  57.1621,  +0.2278, 5.91 }, { 1183,  57.4312, +23.7117, 6.17 }, { 1184,  56.9833, -29.8322, 5.54 },
+ { 1185,  57.4792, +22.2444, 6.07 }, { 1186,  56.9567, -35.8942, 6.21 }, { 1187,  57.1492, -19.0969, 5.81 }, { 1188,  57.5787, +25.5794, 5.26 },
+ { 1189,  57.1475, -36.3778, 5.40 }, { 1190,  57.1496, -36.3794, 4.73 }, { 1191,  57.9738, +34.3592, 5.77 }, { 1192,  58.4304, +57.9750, 5.80 },
+ { 1193,  57.9025, +22.0317, 6.83 }, { 1194,  57.8158, +13.0458, 6.30 }, { 1195,  57.3638, -35.7997, 4.17 }, { 1196,  59.1258, +71.8217, 6.34 },
+ { 1197,  58.0179, +31.1683, 6.25 }, { 1198,  58.4113, +48.6506, 5.76 }, { 1199,  58.0008,  +6.5347, 5.67 }, { 1200,  57.6567, -35.5747, 6.86 },
+ { 1201,  58.2917, +17.3269, 5.97 }, { 1202,  58.1733,  -4.6386, 5.48 }, { 1203,  58.5329, +31.8836, 2.85 }, { 1204,  59.3563, +63.0722, 5.03 },
+ { 1205,  59.2846, +61.1089, 5.00 }, { 1206,  58.3042, -17.5656, 6.22 }, { 1207,  58.9925, +47.8714, 5.37 }, { 1208,  56.8096, -73.7611, 3.24 },
+ { 1209,  58.8458, +31.0458, 6.10 }, { 1210,  59.1521, +50.6953, 5.28 }, { 1211,  58.5725,  -1.0472, 6.14 }, { 1212,  58.5729,  -1.0453, 4.79 },
+ { 1213,  58.4275, -23.3875, 4.65 }, { 1214,  58.4121, -33.2678, 5.11 }, { 1215,  59.1196, +35.0811, 5.49 }, { 1216,  58.3888, -45.1064, 5.93 },
+ { 1217,  58.8179, -11.9008, 6.00 }, { 1218,  59.2171, +22.4781, 5.63 }, { 1219,  58.5967, -39.6428, 5.71 }, { 1220,  59.4633, +40.0103, 2.89 },
+ { 1221,  59.2658, +23.1756, 6.06 }, { 1222,  59.3600, +24.4619, 6.16 }, { 1223,  59.5129, +34.8144, 6.53 }, { 1224,  59.2571,  +6.0400, 6.09 },
+ { 1225,  59.1579,  -8.2492, 6.19 }, { 1226,  59.6213, +38.8403, 6.30 }, { 1227,  58.6417, -51.3094, 6.46 }, { 1228,  59.7413, +35.7911, 4.04 },
+ { 1229,  59.9167, +38.8206, 6.38 }, { 1230,  62.5117, +80.6986, 5.10 }, { 1231,  59.5075, -12.4914, 2.95 }, { 1232,  59.7179,  -4.5300, 5.83 },
+ { 1233,  59.9196, +10.3308, 6.37 }, { 1234,  60.3113, +36.9900, 6.41 }, { 1235,  59.8754, -11.4258, 5.60 }, { 1236,  59.0167, -62.5364, 6.14 },
+ { 1237,  60.1538, +17.2967, 6.32 }, { 1238,  60.2033, +18.1939, 5.89 }, { 1239,  60.1700, +12.4903, 3.47 }, { 1240,  59.9813, -23.9836, 4.66 },
+ { 1241,  61.5129, +68.6800, 5.87 }, { 1242,  61.1133, +59.1556, 5.06 }, { 1243,  60.4421,  +9.9978, 5.67 }, { 1244,  60.3833,  -0.4503, 5.28 },
+ { 1245,  59.6788, -56.8975, 6.05 }, { 1246,  60.1696, -29.5092, 5.93 }, { 1247,  59.6863, -60.5997, 4.56 }, { 1248,  61.6625, +65.5208, 6.17 },
+ { 1249,  60.6529,  +0.2689, 5.38 }, { 1250,  60.0654, -50.4353, 6.51 }, { 1251,  60.7892,  +5.9892, 3.91 }, { 1252,  61.0904, +24.1058, 5.47 },
+ { 1253,  60.9358,  +5.4356, 5.33 }, { 1254,  60.9858,  +8.1972, 5.46 }, { 1255,  61.6525, +54.0086, 6.31 }, { 1256,  61.1737, +22.0819, 4.36 },
+ { 1257,  61.0412,  +2.8269, 5.36 }, { 1258,  60.8529, -19.8558, 6.46 }, { 1259,  60.9033, -19.8417, 7.01 }, { 1260,  61.9629, +62.3300, 6.99 },
+ { 1261,  61.6458, +50.3514, 4.29 }, { 1262,  61.3342, +22.0089, 5.90 }, { 1263,  61.0363, -15.4111, 6.39 }, { 1264,  60.2242, -61.8406, 4.51 },
+ { 1265,  61.0946, -11.2075, 5.61 }, { 1266,  60.3258, -60.9211, 4.97 }, { 1267,  61.1708, -19.6183, 6.13 }, { 1268,  61.6517, +27.6000, 5.20 },
+ { 1269,  61.7521, +29.0014, 5.23 }, { 1270,  62.3650, +59.9081, 6.28 }, { 1271,  55.6337, -84.7378, 6.41 }, { 1272,  61.4854,  -7.1439, 6.26 },
+ { 1273,  62.1654, +47.7125, 4.04 }, { 1274,  61.4446, -19.4878, 6.34 }, { 1275,  61.4058, -26.3483, 5.59 }, { 1276,  62.3433, +54.8289, 6.18 },
+ { 1277,  62.0637, +37.7278, 6.09 }, { 1278,  62.1525, +38.0397, 5.51 }, { 1279,  61.9250, +15.1628, 6.01 }, { 1280,  61.9975, +17.3397, 5.89 },
+ { 1281,  63.4371, +72.1264, 6.03 }, { 1282,  63.2150, +68.5017, 6.32 }, { 1283,  62.2917, +19.6092, 5.50 }, { 1284,  62.2567, +13.3983, 5.95 },
+ { 1285,  61.8546, -41.0831, 6.59 }, { 1286,  62.7458, +33.5867, 5.72 }, { 1287,  62.7079, +26.4808, 5.41 }, { 1288,  62.3242, -15.6142, 5.37 },
+ { 1289,  67.0542, +83.8078, 5.57 }, { 1290,  62.5938,  -5.0761, 5.44 }, { 1291,  62.1412, -44.1353, 6.59 }, { 1292,  62.8346,  +5.5231, 5.72 },
+ { 1293,  62.6987,  -7.1803, 5.70 }, { 1294,  61.8400, -63.7775, 6.38 }, { 1295,  63.1308, +17.2775, 6.09 }, { 1296,  63.7575, +57.4603, 6.08 },
+ { 1297,  63.2133, +22.4136, 6.12 }, { 1298,  62.9663,  -5.1625, 4.04 }, { 1299,  62.6908, -34.7261, 6.44 }, { 1300,  62.9008, -19.6439, 5.79 },
+ { 1301,  63.4983, +37.9669, 6.45 }, { 1302,  62.7108, -40.0064, 4.93 }, { 1303,  63.7246, +48.4094, 4.14 }, { 1304,  67.5004, +83.3406, 5.46 },
+ { 1305,  64.2233, +61.8503, 5.70 }, { 1306,  63.7221, +40.4836, 4.71 }, { 1307,  63.3950, +10.2122, 6.23 }, { 1308,  63.3804,  +8.8906, 6.51 },
+ { 1309,  63.3879,  +7.7161, 5.29 }, { 1310,  63.4579, +12.7533, 6.25 }, { 1311,  63.4850,  +9.2636, 4.84 }, { 1312,  63.4092,  -0.8503, 6.44 },
+ { 1313,  64.2842, +57.8606, 5.71 }, { 1314,  64.1796, +53.6119, 5.19 }, { 1315,  63.6512, +10.0111, 5.22 }, { 1316,  63.1317, -43.6317, 6.71 },
+ { 1317,  66.7617, +80.8242, 5.43 }, { 1318,  63.5988,  -9.7436, 4.87 }, { 1319,  63.9429, +15.4006, 6.32 }, { 1320,  63.8837,  +8.8922, 4.29 },
+ { 1321,  63.8575,  +6.1997, 6.93 }, { 1322,  63.8717,  +6.1867, 6.31 }, { 1323,  63.3988, -39.6422, 6.37 }, { 1324,  64.5608, +50.2956, 4.61 },
+ { 1325,  63.8179,  -6.3472, 4.43 }, { 1326,  63.5004, -41.7056, 3.86 }, { 1327,  65.1679, +65.1406, 5.27 }, { 1328,  64.5342, +42.1411, 6.22 },
+ { 1329,  64.3150, +20.5786, 4.94 }, { 1330,  64.8054, +50.0489, 5.45 }, { 1331,  64.5967, +21.5792, 5.65 }, { 1332,  64.3300,  -5.5281, 5.94 },
+ { 1333,  65.0479, +50.9208, 5.55 }, { 1334,  64.6021,  +9.4867, 6.54 }, { 1335,  65.4483, +60.7356, 5.39 }, { 1336,  63.6063, -61.5261, 3.35 },
+ { 1337,  65.0600, +41.8081, 5.92 }, { 1338,  64.0067, -50.5133, 4.25 }, { 1339,  64.8588, +21.1422, 5.35 }, { 1340,  63.7029, -61.8081, 5.45 },
+ { 1341,  64.9029, +21.7736, 5.38 }, { 1342,  65.4658, +56.5067, 5.88 }, { 1343,  65.1025, +34.5667, 4.93 }, { 1344,  65.0417, +31.9533, 6.16 },
+ { 1345,  64.5662, -19.2844, 6.00 }, { 1346,  64.9483, +15.6275, 3.65 }, { 1347,  64.4737, -32.2017, 3.56 }, { 1348,  65.0888, +27.3508, 4.95 },
+ { 1349,  64.9063, +10.1214, 6.31 }, { 1350,  65.3883, +46.4989, 4.85 }, { 1351,  64.9904, +14.0353, 5.59 }, { 1352,  65.7412, +59.6164, 6.19 },
+ { 1353,  64.6558, -21.0297, 6.07 }, { 1354,  65.1046, +18.7425, 6.12 }, { 1355,  64.1204, -58.6981, 4.44 }, { 1356,  65.1513, +15.0953, 5.26 },
+ { 1357,  64.0879, -59.0514, 6.37 }, { 1358,  65.2200, +13.8642, 6.17 }, { 1359,  64.7625, -32.0950, 6.37 }, { 1360,  65.1717,  +6.1308, 5.77 },
+ { 1361,  65.2042,  +9.2256, 6.53 }, { 1362,  65.1612,  -5.7544, 6.27 }, { 1363,  65.1783,  -6.4075, 5.85 }, { 1364,  64.8192, -43.7319, 5.34 },
+ { 1365,  64.6667, -51.1400, 6.09 }, { 1366,  65.3629,  +0.0981, 5.86 }, { 1367,  65.1625, -19.3603, 5.38 }, { 1368,  65.5146, +14.0772, 5.72 },
+ { 1369,  65.6454, +25.6292, 5.37 }, { 1370,  65.5950, +20.8214, 5.91 }, { 1371,  65.8996, +42.4281, 6.23 }, { 1372,  64.4175, -62.7444, 5.87 },
+ { 1373,  65.7338, +17.5425, 3.76 }, { 1374,  65.3804, -24.2717, 6.01 }, { 1375,  65.8850, +20.9822, 5.99 }, { 1376,  65.8542, +16.7772, 5.64 },
+ { 1377,  66.1217, +34.1306, 5.73 }, { 1378,  65.9992, +24.3011, 6.36 }, { 1379,  66.1558, +33.9597, 5.76 }, { 1380,  66.0242, +17.4439, 4.80 },
+ { 1381,  65.9663,  +9.4608, 5.12 }, { 1382,  66.7537, +57.5853, 6.32 }, { 1383,  65.9200,  -2.2544, 5.17 }, { 1384,  65.7738, -23.1078, 5.83 },
+ { 1385,  66.2379, +19.0417, 5.98 }, { 1386,  65.7821, -34.4550, 6.39 }, { 1387,  66.3421, +22.2939, 4.22 }, { 1388,  66.3542, +22.1997, 5.28 },
+ { 1389,  66.3725, +17.9281, 4.29 }, { 1390,  66.5263, +31.4389, 5.28 }, { 1391,  66.4054, +15.9408, 6.46 }, { 1392,  66.5771, +22.8136, 4.28 },
+ { 1393,  66.0092, -33.9831, 3.96 }, { 1394,  66.5867, +15.6183, 4.49 }, { 1395,  65.4721, -62.6136, 5.24 }, { 1396,  66.6517, +14.7136, 4.69 },
+ { 1397,  66.5879,  +8.5903, 6.06 }, { 1398,  66.2350, -33.2422, 6.55 }, { 1399,  66.8229, +22.9964, 5.53 }, { 1400,  66.7529,  +2.0794, 6.23 },
+ { 1401,  68.3779, +72.5286, 5.94 }, { 1402,  66.8700, +11.2125, 5.88 }, { 1403,  67.0033, +21.6200, 5.72 }, { 1404,  66.3296, -43.8392, 6.39 },
+ { 1405,  66.0508, -56.9286, 6.29 }, { 1406,  67.2163, +30.3614, 6.40 }, { 1407,  67.1100, +16.3597, 4.97 }, { 1408,  67.0975, +14.7408, 5.90 },
+ { 1409,  67.1542, +19.1803, 3.53 }, { 1410,  66.7375, -23.9186, 6.11 }, { 1411,  67.1437, +15.9622, 3.84 }, { 1412,  67.1654, +15.8708, 3.40 },
+ { 1413,  67.0150,  +1.8586, 6.15 }, { 1414,  67.2092, +13.0475, 5.03 }, { 1415,  67.1338,  +1.3808, 5.55 }, { 1416,  66.2721, -60.7617, 5.94 },
+ { 1417,  68.0075, +53.9108, 5.77 }, { 1418,  66.7750, -45.0525, 6.10 }, { 1419,  67.6596, +32.4581, 6.21 }, { 1420,  67.4287, +10.5217, 6.79 },
+ { 1421,  67.1625, -18.5417, 5.96 }, { 1422,  67.5358, +15.6381, 5.58 }, { 1423,  67.2788, -12.9517, 5.60 }, { 1424,  67.8500, +40.0103, 6.26 },
+ { 1425,  67.5100, +10.2625, 6.48 }, { 1426,  64.4963, -79.7861, 5.69 }, { 1427,  67.6404, +16.1939, 4.78 }, { 1428,  67.6621, +15.6919, 5.48 },
+ { 1429,  67.0392, -40.0400, 6.44 }, { 1430,  67.6554, +13.7244, 5.40 }, { 1431,  67.5404, -12.4078, 6.24 }, { 1432,  67.9658, +15.8517, 6.02 },
+ { 1433,  67.3333, -45.4847, 6.16 }, { 1434,  68.3538, +43.0639, 6.09 }, { 1435,  66.9412, -61.4792, 5.75 }, { 1436,  68.0200,  +5.4100, 6.39 },
+ { 1437,  67.9696,  +0.0439, 4.91 }, { 1438,  67.8579, -12.3550, 6.21 }, { 1439,  67.6679, -34.3464, 5.96 }, { 1440,  69.1008, +64.2617, 5.94 },
+ { 1441,  68.1558,  -2.7908, 5.81 }, { 1442,  68.3871, +18.0167, 6.25 }, { 1443,  67.7087, -43.0461, 5.07 }, { 1444,  68.4621, +14.8444, 4.65 },
+ { 1445,  68.6583, +28.9611, 5.88 }, { 1446,  68.4504,  +9.4131, 6.01 }, { 1447,  68.3417,  -9.2142, 6.06 }, { 1448,  68.5346,  +5.5686, 5.68 },
+ { 1449,  68.4783,  -5.2611, 5.72 }, { 1450,  68.5592,  -5.1622, 6.09 }, { 1451,  68.5483,  -7.7686, 5.11 }, { 1452,  68.5487,  -7.0297, 5.26 },
+ { 1453,  68.3775, -28.2333, 4.51 }, { 1454,  69.1725, +41.2647, 4.25 }, { 1455,  68.9279, +19.8817, 6.36 }, { 1456,  65.2412, -80.4200, 5.79 },
+ { 1457,  68.9800, +16.5092, 0.85 }, { 1458,  68.9137, +10.1608, 4.25 }, { 1459,  69.1217, +23.3408, 6.02 }, { 1460,  68.8083,  -8.2633, 6.37 },
+ { 1461,  68.7521, -18.0794, 6.13 }, { 1462,  69.0067,  -2.3881, 6.33 }, { 1463,  69.0796,  -2.6475, 3.93 }, { 1464,  68.8875, -29.4378, 3.82 },
+ { 1465,  68.4992, -54.9550, 3.27 }, { 1466,  69.9921, +53.4731, 5.35 }, { 1467,  69.9779, +53.0797, 5.05 }, { 1468,  71.5012, +76.6111, 6.49 },
+ { 1469,  69.3071,  +0.9983, 5.31 }, { 1470,  69.6233, +26.9400, 6.47 }, { 1471,  69.5658, +20.6847, 5.92 }, { 1472,  69.5392, +16.0333, 5.79 },
+ { 1473,  69.5396, +12.5108, 4.27 }, { 1474,  69.4004,  -1.5267, 5.23 }, { 1475,  68.3917, -61.1764, 5.79 }, { 1476,  69.2121, -29.2833, 6.30 },
+ { 1477,  69.8462, +25.2183, 6.22 }, { 1478,  69.7883, +15.7997, 5.07 }, { 1479,  69.8187, +15.9181, 4.69 }, { 1480,  69.7758,  +7.8708, 5.39 },
+ { 1481,  69.5450, -13.6961, 3.87 }, { 1482,  70.3504, +48.3008, 5.67 }, { 1483,  69.7233, -11.8769, 5.01 }, { 1484,  70.0142, +12.1978, 5.46 },
+ { 1485,  65.7121, -81.1008, 6.76 }, { 1486,  70.8254, +59.5208, 6.50 }, { 1487,  69.8321, -13.6408, 5.45 }, { 1488,  69.9467,  -0.9472, 6.10 },
+ { 1489,  70.4596, +38.2803, 5.99 }, { 1490,  70.3325, +28.6150, 5.78 }, { 1491,  72.2096, +75.9411, 6.06 }, { 1492,  69.1900, -61.9225, 5.40 },
+ { 1493,  70.8400, +49.9739, 5.87 }, { 1494,  70.7262, +43.3650, 5.29 }, { 1495,  70.0283, -23.5175, 5.58 }, { 1496,  70.1104, -18.3283, 4.32 },
+ { 1497,  70.5613, +22.9569, 4.28 }, { 1498,  69.7679, -50.3272, 6.44 }, { 1499,  70.8075, +24.0889, 6.13 }, { 1500,  71.0537, +40.7869, 6.08 },
+ { 1501,  70.9513, +32.8653, 6.45 }, { 1502,  70.1404, -40.1361, 4.45 }, { 1503,  70.5146, -36.8556, 5.05 }, { 1504,  70.0763, -57.0564, 6.53 },
+ { 1505,  70.8942,  -7.2064, 6.82 }, { 1506,  70.8962,  -7.2039, 6.70 }, { 1507,  71.1075, +11.1461, 5.40 }, { 1508,  71.0221,  -7.4964, 5.90 },
+ { 1509,  70.7887, -29.2344, 5.68 }, { 1510,  72.6517, +70.9417, 6.37 }, { 1511,  72.0012, +56.7572, 5.30 }, { 1512,  71.4271, +23.6281, 6.35 },
+ { 1513,  71.0333, -17.3333, 5.53 }, { 1514,  71.6850, +40.3128, 5.97 }, { 1515,  72.0292, +55.6025, 6.26 }, { 1516,  70.6933, -49.5186, 5.31 },
+ { 1517,  71.5700, +18.7350, 6.01 }, { 1518,  70.9342, -40.9353, 6.25 }, { 1519,  71.5071, +11.7056, 5.37 }, { 1520,  71.3754,  -2.7453, 4.02 },
+ { 1521,  71.2675, -20.7164, 5.72 }, { 1522,  71.6004,  -1.0456, 6.33 }, { 1523,  75.0863, +81.1939, 5.07 }, { 1524,  71.4567, -33.9950, 6.86 },
+ { 1525,  71.6075, -27.9125, 6.19 }, { 1526,  71.4808, -38.6433, 6.05 }, { 1527,  73.0217, +63.5053, 5.44 }, { 1528,  72.3292, +32.5883, 5.86 },
+ { 1529,  72.3033, +31.4372, 5.58 }, { 1530,  71.0879, -58.2672, 5.27 }, { 1531,  69.5904, -76.3439, 6.05 }, { 1532,  71.9013, -15.0656, 5.51 },
+ { 1533,  72.4775, +37.4883, 4.88 }, { 1534,  72.1858,  +3.5883, 6.03 }, { 1535,  72.7887, +48.7408, 5.66 }, { 1536,  72.1513,  -4.3261, 5.78 },
+ { 1537,  72.4338, +15.9042, 6.08 }, { 1538,  72.1354, -15.6706, 5.77 }, { 1539,  71.9567, -29.9797, 6.37 }, { 1540,  71.2412, -62.7703, 6.46 },
+ { 1541,  70.7662, -69.0689, 5.54 }, { 1542,  73.5125, +66.3428, 4.29 }, { 1543,  72.4600,  +6.9614, 3.19 }, { 1544,  72.6529,  +8.9003, 4.36 },
+ { 1545,  72.4258, -12.2303, 6.26 }, { 1546,  73.2908, +52.8408, 6.41 }, { 1547,  72.8438, +18.8397, 5.10 }, { 1548,  72.1408, -42.0200, 6.72 },
+ { 1549,  72.5483, -15.7828, 5.03 }, { 1550,  73.1992, +42.5867, 5.71 }, { 1551,  73.1583, +36.7031, 4.78 }, { 1552,  72.8017,  +5.6050, 3.69 },
+ { 1553,  72.9308,  +9.9750, 6.11 }, { 1554,  73.1963, +27.8975, 5.97 }, { 1555,  73.7629, +55.2592, 5.52 }, { 1556,  73.1333, +14.2506, 4.74 },
+ { 1557,  72.5675, -40.6792, 6.07 }, { 1558,  73.7138, +44.0608, 6.08 }, { 1559,  72.8675, -33.0936, 5.86 }, { 1560,  73.2237,  -4.5472, 4.39 },
+ { 1561,  74.0296, +52.8694, 5.75 }, { 1562,  73.3450,  +2.5081, 5.33 }, { 1563,  72.7300, -52.5386, 5.61 }, { 1564,  72.7346, -52.5403, 6.42 },
+ { 1565,  73.4825,  +1.5694, 6.61 }, { 1566,  73.7429, +19.4853, 6.37 }, { 1567,  73.5629,  +2.4406, 3.72 }, { 1568,  74.3217, +53.7522, 4.47 },
+ { 1569,  73.6954, +11.4261, 5.19 }, { 1570,  73.7242, +10.1508, 4.65 }, { 1571,  73.6992,  +7.7792, 5.33 }, { 1572,  75.5837, +74.2692, 6.06 },
+ { 1573,  74.0829, +36.1689, 6.07 }, { 1574,  73.7113,  +0.4675, 5.99 }, { 1575,  74.0650, +24.5922, 6.37 }, { 1576,  73.9596, +15.0400, 5.81 },
+ { 1577,  74.2483, +33.1661, 2.69 }, { 1578,  73.9933,  +5.3992, 6.50 }, { 1579,  73.7783, -15.2594, 5.70 }, { 1580,  74.0929, +13.5144, 4.07 },
+ { 1581,  73.8275, -15.5822, 5.72 }, { 1582,  74.1008,  -4.8286, 5.51 }, { 1583,  73.8758, -24.2722, 6.72 }, { 1584,  73.7283, -38.3714, 6.10 },
+ { 1585,  74.3429, +17.1536, 5.48 }, { 1586,  74.4529, +23.9486, 5.79 }, { 1587,  76.0542, +73.7639, 6.66 }, { 1588,  74.9429, +53.1556, 6.08 },
+ { 1589,  76.1658, +74.0669, 5.96 }, { 1590,  74.5392, +25.0503, 5.81 }, { 1591,  74.3217,  -0.9328, 6.23 }, { 1592,  74.8142, +37.8903, 4.94 },
+ { 1593,  75.3996, +61.0781, 6.03 }, { 1594,  75.7100, +66.8228, 6.19 }, { 1595,  74.4367, -13.7686, 6.15 }, { 1596,  74.5450,  -1.7875, 6.35 },
+ { 1597,  73.7208, -57.4528, 6.12 }, { 1598,  73.3771, -65.3244, 6.41 }, { 1599,  75.0763, +39.3947, 5.95 }, { 1600,  74.7475, +14.5428, 6.09 },
+ { 1601,  74.6371,  +1.7142, 4.47 }, { 1602,  75.0967, +39.6550, 6.58 }, { 1603,  75.8546, +60.4422, 4.03 }, { 1604,  74.7554, -15.6242, 5.66 },
+ { 1605,  75.4921, +43.8233, 2.99 }, { 1606,  73.2729, -71.5925, 6.28 }, { 1607,  74.9021, -13.1942, 7.71 }, { 1608,  74.9600,  -9.7367, 5.38 },
+ { 1609,  75.1358,  +3.6153, 7.03 }, { 1610,  75.1412,  +3.6161, 6.66 }, { 1611,  74.9825, -11.4625, 4.79 }, { 1612,  75.6196, +41.0758, 3.75 },
+ { 1613,  75.1658,  -1.9344, 6.32 }, { 1614,  75.2042,  -4.2467, 6.22 }, { 1615,  75.8275, +41.4417, 6.14 }, { 1616,  82.9500, +85.9386, 6.51 },
+ { 1617,  75.3596,  -6.8261, 4.81 }, { 1618,  75.4596,  +0.7222, 5.92 }, { 1619,  75.5000,  +1.6089, 6.24 }, { 1620,  75.7738, +21.5900, 4.64 },
+ { 1621,  75.3567, -19.9481, 4.91 }, { 1622,  76.5354, +58.9725, 5.08 }, { 1623,  76.5508, +59.0211, 6.08 }, { 1624,  76.6238, +61.1700, 6.04 },
+ { 1625,  75.6896,  -3.7903, 5.85 }, { 1626,  76.0604, +30.4947, 6.14 }, { 1627,  76.1538, +32.3203, 6.62 }, { 1628,  75.5408, -25.7250, 5.02 },
+ { 1629,  73.7967, -73.0631, 5.47 }, { 1630,  76.5917, +54.4058, 7.24 }, { 1631,  75.3937, -38.2819, 6.03 }, { 1632,  76.1579, +27.6961, 6.60 },
+ { 1633,  76.0900, +21.2781, 6.19 }, { 1634,  75.6871, -21.2050, 5.75 }, { 1635,  75.5950, -30.2286, 5.94 }, { 1636,  77.4029, +69.6394, 6.41 },
+ { 1637,  76.6692, +51.5978, 5.00 }, { 1638,  76.1421, +15.4042, 4.68 }, { 1639,  76.5037, +35.9364, 6.52 }, { 1640,  75.9667, -13.6306, 6.41 },
+ { 1641,  76.6287, +41.2344, 3.17 }, { 1642,  76.3838, +19.8064, 6.44 }, { 1643,  78.0933, +73.9467, 5.43 }, { 1644,  76.7067, +43.1747, 6.20 },
+ { 1645,  75.9721, -23.6122, 5.61 }, { 1646,  76.2271,  -2.9603, 6.05 }, { 1647,  77.4354, +64.9194, 6.41 }, { 1648,  76.3487,  +1.1775, 6.17 },
+ { 1649,  75.7025, -48.8486, 5.38 }, { 1650,  78.6483, +76.4728, 6.37 }, { 1651,  75.9750, -40.2550, 6.31 }, { 1652,  76.1017, -34.5167, 4.55 },
+ { 1653,  76.1088, -34.2947, 6.34 }, { 1654,  76.3654, -21.6289, 3.19 }, { 1655,  76.3175, -25.8475, 5.73 }, { 1656,  76.8625, +18.6450, 5.00 },
+ { 1657,  76.6904,  -3.3450, 5.12 }, { 1658,  76.9517, +20.4183, 5.30 }, { 1659,  77.0275, +24.2653, 5.50 }, { 1660,  76.9813, +21.7047, 5.89 },
+ { 1661,  76.6529, -12.8781, 6.05 }, { 1662,  76.9096,  +9.4719, 6.17 }, { 1663,  76.2417, -48.4222, 5.03 }, { 1664,  76.9704,  +8.4983, 5.34 },
+ { 1665,  76.8542, -11.5094, 5.97 }, { 1666,  76.9625,  -4.9136, 2.79 }, { 1667,  76.2525, -53.5925, 6.27 }, { 1668,  77.6787, +46.9622, 5.68 },
+ { 1669,  77.5787, +37.3019, 6.02 }, { 1670,  77.4379, +28.0306, 6.01 }, { 1671,  77.0842,  -7.3350, 5.78 }, { 1672,  77.3317,  +9.8294, 5.43 },
+ { 1673,  77.1817,  -3.5439, 5.12 }, { 1674,  76.3775, -56.5272, 4.72 }, { 1675,  78.2633, +61.8500, 6.17 }, { 1676,  77.4250, +15.5972, 4.82 },
+ { 1677,  75.6792, -70.6856, 5.31 }, { 1678,  78.3804, +62.6914, 6.50 }, { 1679,  77.2867,  -7.2458, 4.27 }, { 1680,  77.0617, -34.2817, 6.52 },
+ { 1681,  77.5133,  +0.5653, 6.10 }, { 1682,  75.0550, -77.6997, 6.29 }, { 1683,  79.5554, +73.2681, 5.74 }, { 1684,  77.9233, +16.0456, 5.18 },
+ { 1685,  77.7417,  -1.7461, 6.25 }, { 1686,  80.6396, +79.2311, 5.05 }, { 1687,  77.8300,  -1.5092, 5.90 }, { 1688,  78.7971, +59.4056, 6.15 },
+ { 1689,  78.3571, +38.4844, 4.86 }, { 1690,  77.9225,  +0.5147, 6.67 }, { 1691,  77.9387,  +1.0369, 5.89 }, { 1692,  78.6846, +53.2139, 6.20 },
+ { 1693,  77.8450, -10.1508, 5.68 }, { 1694,  77.6854, -24.0906, 6.41 }, { 1695,  76.8917, -62.6003, 5.20 }, { 1696,  78.0746, -10.1308, 4.45 },
+ { 1697,  78.2008,  -5.9428, 5.91 }, { 1698,  78.3229,  +2.8611, 4.46 }, { 1699,  77.8996, -36.6047, 6.57 }, { 1700,  76.5387, -72.9622, 6.27 },
+ { 1701,  78.3817,  +1.9681, 6.09 }, { 1702,  78.2329, -15.7944, 3.31 }, { 1703,  78.4467,  +0.5603, 6.32 }, { 1704,  78.3888,  -7.8522, 6.37 },
+ { 1705,  78.3079, -11.0586, 4.36 }, { 1706,  78.8517, +32.6878, 5.02 }, { 1707,  79.3242, +53.5861, 6.50 }, { 1708,  79.1725, +45.9981, 0.08 },
+ { 1709,  78.6838,  +5.1561, 5.50 }, { 1710,  78.4996, -13.3933, 6.21 }, { 1711,  78.8654, +22.2847, 6.27 }, { 1712,  79.0758, +34.3119, 5.96 },
+ { 1713,  78.6346,  -7.7983, 0.12 }, { 1714,  85.9529, +85.6681, 6.60 }, { 1715,  78.4437, -34.1744, 6.98 }, { 1716,  74.7121, -81.5294, 5.85 },
+ { 1717,  78.8267,  -0.5908, 6.15 }, { 1718,  79.0171, +11.3414, 5.56 }, { 1719,  79.8658, +58.1172, 6.13 }, { 1720,  80.0942, +62.6536, 5.61 },
+ { 1721,  78.6200, -34.0228, 5.76 }, { 1722,  79.5662, +42.7922, 5.48 }, { 1723,  78.8512, -25.0567, 5.07 }, { 1724,  79.1713,  +1.9472, 6.42 },
+ { 1725,  79.6683, +40.4650, 6.18 }, { 1726,  79.5446, +33.3717, 4.54 }, { 1727,  78.4721, -51.9689, 6.05 }, { 1728,  79.5787, +33.7672, 6.14 },
+ { 1729,  79.7854, +40.0992, 4.71 }, { 1730,  78.9458, -33.0733, 6.66 }, { 1731,  79.2004, -16.8583, 6.56 }, { 1732,  79.7500, +33.7483, 5.41 },
+ { 1733,  80.0096, +44.4256, 6.62 }, { 1734,  79.8483, +33.9856, 6.49 }, { 1735,  79.4017,  -5.1556, 3.60 }, { 1736,  80.1637, +46.9639, 6.54 },
+ { 1737,  79.4175, -12.4803, 5.50 }, { 1738,  80.0617, +41.0861, 5.52 }, { 1739,  79.8192, +22.0964, 4.94 }, { 1740,  80.0037, +33.9581, 5.03 },
+ { 1741,  79.8113, +20.1347, 6.08 }, { 1742,  78.9121, -51.8181, 6.49 }, { 1743,  79.3713, -33.1047, 4.83 }, { 1744,  78.4392, -66.8147, 4.83 },
+ { 1745,  82.3571, +77.9775, 6.56 }, { 1746,  79.7967,  +2.5958, 5.34 }, { 1747,  79.7100, -17.8700, 5.96 }, { 1748,  79.8967,  -0.5878, 6.34 },
+ { 1749,  80.4517, +41.8044, 5.23 }, { 1750,  80.2471, +27.9572, 6.33 }, { 1751,  80.8658, +57.5444, 5.28 }, { 1752,  80.3029, +29.5700, 5.76 },
+ { 1753,  79.8229, -17.4800, 6.36 }, { 1754,  79.8263, -17.4903, 6.54 }, { 1755,  80.2358, +19.8142, 6.18 }, { 1756,  79.8937, -12.8233, 4.29 },
+ { 1757,  79.9963, -11.6844, 5.30 }, { 1758,  79.8487, -26.6311, 5.99 }, { 1759,  80.1100,  -4.6333, 6.39 }, { 1760,  80.7096, +41.0294, 5.54 },
+ { 1761,  80.3304,  +4.0119, 6.57 }, { 1762,  80.1121, -20.7606, 4.71 }, { 1763,  80.4317,  +8.4286, 5.80 }, { 1764,  80.3825,  +0.4164, 5.68 },
+ { 1765,  80.4404,  +0.3825, 4.73 }, { 1766,  80.0858, -33.3011, 6.34 }, { 1767,  79.8421, -49.3939, 5.45 }, { 1768,  80.8454, +28.9367, 6.46 },
+ { 1769,  80.4625, -12.2439, 6.56 }, { 1770,  80.7083,  +3.5444, 5.00 }, { 1771,  80.4425, -23.2269, 5.06 }, { 1772,  80.3204, -33.6547, 6.09 },
+ { 1773,  81.1633, +37.3856, 4.99 }, { 1774,  80.9071, +16.6994, 6.08 }, { 1775,  81.1596, +31.2239, 6.28 }, { 1776,  81.1604, +31.1431, 5.94 },
+ { 1777,  80.8796,  +5.3225, 6.35 }, { 1778,  80.8271,  -7.5842, 5.90 }, { 1779,  81.3042, +34.8553, 6.55 }, { 1780,  81.1058, +17.3833, 4.99 },
+ { 1781,  80.9262,  +0.1597, 5.70 }, { 1782,  80.9642,  +0.8672, 6.11 }, { 1783,  80.8758, -12.0728, 5.25 }, { 1784,  80.9867,  -6.1919, 4.14 },
+ { 1785,  80.8000, -25.2942, 6.49 }, { 1786,  81.1508,  +2.3528, 6.32 }, { 1787,  81.1204,  +0.8914, 5.08 }, { 1788,  81.1192,  -1.6031, 3.36 },
+ { 1789,  81.1867,  +1.8464, 4.95 }, { 1790,  81.2829,  +6.3497, 1.64 }, { 1791,  81.5729, +28.6075, 1.65 }, { 1792,  81.1183, -15.0239, 5.65 },
+ { 1793,  80.8500, -38.3214, 5.71 }, { 1794,  81.7262, +35.4572, 6.15 }, { 1795,  81.7037, +34.3917, 5.94 }, { 1796,  81.7138, +33.2628, 6.15 },
+ { 1797,  80.9125, -36.6633, 6.82 }, { 1798,  81.5238, +16.7003, 6.25 }, { 1799,  81.2567,  -9.6708, 5.61 }, { 1800,  81.3800,  +0.5442, 6.57 },
+ { 1801,  80.5921, -55.8656, 6.11 }, { 1802,  82.5425, +63.0672, 5.42 }, { 1803,  81.4458,  +0.5208, 6.16 }, { 1804,  81.7846, +30.2086, 5.74 },
+ { 1805,  81.9121, +34.4758, 5.07 }, { 1806,  81.5100,  -4.4817, 6.23 }, { 1807,  81.6617,  +6.8692, 6.42 }, { 1808,  81.7921, +17.9622, 5.42 },
+ { 1809,  81.8075, +15.2578, 6.16 }, { 1810,  81.9087, +21.9369, 4.88 }, { 1811,  81.7092,  +3.0956, 4.59 }, { 1812,  81.4992, -18.3044, 5.89 },
+ { 1813,  81.2317, -43.7742, 6.08 }, { 1814,  81.9400, +15.8742, 5.50 }, { 1815,  78.1071, -80.4583, 6.51 }, { 1816,  82.0067, +17.2389, 5.77 },
+ { 1817,  81.7700, -10.0992, 6.35 }, { 1818,  81.1925, -51.6836, 6.27 }, { 1819,  82.1450, +13.6789, 6.35 }, { 1820,  82.0067,  +1.2983, 6.41 },
+ { 1821,  82.3187, +25.1506, 5.47 }, { 1822,  82.4192, +29.1864, 6.24 }, { 1823,  81.9021, -20.6244, 6.07 }, { 1824,  82.7025, +41.4619, 6.00 },
+ { 1825,  82.6879, +39.8258, 6.37 }, { 1826,  82.2362,  -2.6925, 6.39 }, { 1827,  81.7721, -39.0564, 5.87 }, { 1828,  83.1408, +57.2211, 6.48 },
+ { 1829,  82.0613, -19.2406, 2.84 }, { 1830,  82.3483,  -2.5536, 5.79 }, { 1831,  82.6808, +22.4625, 6.29 }, { 1832,  82.6088, +15.3603, 5.94 },
+ { 1833,  82.4783,  +1.7892, 5.78 }, { 1834,  82.4333,  -0.9078, 4.71 }, { 1835,  82.0637, -36.7694, 5.57 }, { 1836,  81.5804, -57.0875, 5.14 },
+ { 1837,  82.5825,  +4.2042, 6.21 }, { 1838,  82.2779, -29.8833, 6.75 }, { 1839,  82.6963,  +5.9481, 4.20 }, { 1840,  82.5863,  -6.5653, 6.33 },
+ { 1841,   0.0000,  +0.0000, 0.00 }, { 1842,  82.8104,  +3.2922, 5.46 }, { 1843,  83.1821, +32.1919, 4.76 }, { 1844,  84.9321, +75.0439, 6.17 },
+ { 1845,  83.0533, +18.5944, 4.38 }, { 1846,  83.3696, +42.1089, 6.55 }, { 1847,  83.0592, +17.0581, 5.46 }, { 1848,  82.8371,  -5.2917, 6.22 },
+ { 1849,  82.7817, -19.1364, 5.55 }, { 1850,  83.3646, +32.8011, 6.48 }, { 1851,  83.0021,  +0.2844, 6.85 }, { 1852,  83.0017,  +0.2992, 2.23 },
+ { 1853,  84.3175, +66.6961, 6.26 }, { 1854,  83.4083, +34.7258, 6.27 }, { 1855,  82.9825,  -6.6986, 4.62 }, { 1856,  82.5396, -46.9222, 5.46 },
+ { 1857,  84.3129, +64.1547, 6.15 }, { 1858,  83.3817, +18.5403, 5.69 }, { 1859,  81.7500, -67.3772, 6.03 }, { 1860,  83.4117, +20.4742, 6.18 },
+ { 1861,  83.1721,  -0.4081, 5.35 }, { 1862,  82.8029, -34.5294, 3.87 }, { 1863,  83.2800,  -0.2817, 6.46 }, { 1864,  83.4762, +14.3056, 5.64 },
+ { 1865,  83.1825, -16.1778, 2.58 }, { 1866,  84.1467, +54.4289, 5.73 }, { 1867,  82.3225, -61.6856, 6.59 }, { 1868,  83.3808,  -0.8439, 5.34 },
+ { 1869,  84.0662, +47.7153, 6.11 }, { 1870,  82.9004, -44.0747, 5.86 }, { 1871,  83.4900,  +1.4078, 6.59 }, { 1872,  83.5696,  +3.7669, 5.36 },
+ { 1873,  83.5162,  -0.9644, 6.22 }, { 1874,  83.5167,  -0.5294, 5.93 }, { 1875,  83.8629, +24.0394, 5.38 }, { 1876,  83.7050,  +9.4894, 4.41 },
+ { 1877,  83.2138, -37.4869, 5.48 }, { 1878,  83.9813, +27.6622, 6.27 }, { 1879,  83.7846,  +9.9342, 3.54 }, { 1880,  83.7854,  +9.9350, 5.61 },
+ { 1881,  83.2808, -34.8603, 5.78 }, { 1882,  82.5662, -62.0722, 6.19 }, { 1883,  83.8058, +10.2400, 5.60 }, { 1884,  84.2183, +40.1822, 6.09 },
+ { 1885,  90.3342, +85.1822, 6.11 }, { 1886,  83.7537,  -5.9908, 5.67 }, { 1887,  83.7613,  -5.9981, 4.78 }, { 1888,  83.4671, -28.1511, 6.53 },
+ { 1889,  84.1258, +25.9394, 6.49 }, { 1890,  83.8408,  -3.5067, 6.56 }, { 1891,  83.8438,  -3.5747, 6.24 }, { 1892,  83.8467,  -3.1617, 4.59 },
+ { 1893,  83.8162,  -4.6128, 6.73 }, { 1894,  83.8171,  -4.6147, 7.96 }, { 1895,  83.8187,  -4.6103, 5.13 }, { 1896,  83.8221,  -4.6122, 6.70 },
+ { 1897,  83.8454,  -4.5839, 5.08 }, { 1898,  83.8796,  -3.6353, 6.38 }, { 1899,  83.8583,  -4.0900, 2.77 }, { 1900,  83.8992,  -2.7472, 6.40 },
+ { 1901,  83.9146,  -3.1442, 5.26 }, { 1902,  84.2867, +26.9242, 5.83 }, { 1903,  84.0533,  -0.7981, 1.70 }, { 1904,  84.4404, +33.5592, 6.33 },
+ { 1905,  84.2658, +17.0403, 5.54 }, { 1906,  84.0625,  -4.3519, 6.54 }, { 1907,  84.2262,  +9.2906, 4.09 }, { 1908,  84.2683, +11.0350, 5.94 },
+ { 1909,  83.8142, -32.9200, 5.78 }, { 1910,  84.4112, +21.1425, 3.00 }, { 1911,  84.1488,  -5.9350, 5.72 }, { 1912,  83.4350, -53.0978, 6.43 },
+ { 1913,  84.3304,  +8.9519, 6.12 }, { 1914,  84.6587, +30.4925, 5.40 }, { 1915,  84.0429, -27.2922, 6.26 }, { 1916,  85.6100, +65.6978, 5.60 },
+ { 1917,  83.2483, -63.7725, 5.34 }, { 1918,  84.3642,  -4.0617, 6.05 }, { 1919,  84.2867, -10.2244, 6.11 }, { 1920,  84.5046,  +7.5414, 5.88 },
+ { 1921,  84.7392, +26.6178, 6.37 }, { 1922,  83.4063, -61.5103, 3.76 }, { 1923,  84.4725,  -3.1864, 6.19 }, { 1924,  84.8267, +29.2153, 5.96 },
+ { 1925,  85.3346, +53.4811, 6.23 }, { 1926,  84.3187, -26.1286, 6.16 }, { 1927,  84.0113, -46.6861, 6.11 }, { 1928,  84.9342, +25.8969, 5.18 },
+ { 1929,  84.8625, +21.7628, 6.34 }, { 1930,  83.7600, -57.1289, 6.75 }, { 1931,  84.6867,  -1.4000, 3.81 }, { 1932,  84.6963,  -1.4058, 6.65 },
+ { 1933,  84.6575,  -5.4261, 5.96 }, { 1934,  84.7963,  +4.1214, 4.57 }, { 1935,  84.4358, -27.3106, 5.31 }, { 1936,  83.7400, -60.8242, 6.32 },
+ { 1937,  84.7212,  -6.7869, 4.80 }, { 1938,  85.1496, +31.3581, 6.04 }, { 1939,  85.1754, +31.9208, 6.11 }, { 1940,  84.8800,  -2.4353, 6.00 },
+ { 1941,  85.7567, +56.5817, 6.05 }, { 1942,  84.8783,  -8.2933, 6.50 }, { 1943,  86.0358, +61.4767, 6.15 }, { 1944,  84.8179, -16.1506, 6.38 },
+ { 1945,  85.3375, +29.4875, 6.43 }, { 1946,  85.3238, +16.5339, 4.86 }, { 1947,  84.6817, -39.2925, 5.82 }, { 1948,  85.1896,  -0.0572, 2.05 },
+ { 1949,  85.1900,  -0.0572, 4.21 }, { 1950,  85.1554,  -1.1750, 6.22 }, { 1951,  85.4775, +23.3264, 6.59 }, { 1952,  85.2108,  -0.8711, 4.95 },
+ { 1953,  82.9704, -75.6589, 5.19 }, { 1954,  85.5162, +22.6603, 6.36 }, { 1955,  85.2733,  +0.3378, 5.93 }, { 1956,  84.9121, -33.9258, 2.64 },
+ { 1957,  85.1917,  -9.5906, 6.52 }, { 1958,  84.9575, -31.3708, 5.45 }, { 1959,  85.4179,  -1.1039, 6.42 }, { 1960,  84.2279, -65.4397, 6.31 },
+ { 1961,  85.8312, +23.2042, 6.21 }, { 1962,  85.4229, -15.2744, 6.21 }, { 1963,  85.6192,  +1.4747, 4.91 }, { 1964,  83.6863, -72.2586, 5.78 },
+ { 1965,  85.5596, -16.4697, 6.15 }, { 1966,  85.3625, -32.5994, 6.34 }, { 1967,  85.7242,  -5.2039, 6.02 }, { 1968,  85.5579, -21.6264, 5.87 },
+ { 1969,  86.6267, +56.1156, 5.94 }, { 1970,  85.7887,  -0.3869, 6.31 }, { 1971,  86.4750, +49.8264, 5.47 }, { 1972,  85.5483, -29.4644, 6.19 },
+ { 1973,  85.5629, -33.3322, 5.29 }, { 1974,  86.4562, +40.5072, 6.58 }, { 1975,  85.8400, -17.4425, 5.73 }, { 1976,  87.2704, +62.8081, 6.13 },
+ { 1977,  86.4142, +20.6950, 6.95 }, { 1978,  86.2579,  +4.0081, 6.09 }, { 1979,  86.8113, +42.5267, 6.29 }, { 1980,  86.1183, -19.8736, 6.34 },
+ { 1981,  85.8758, -38.5931, 6.25 }, { 1982,  86.1104, -21.5783, 6.15 }, { 1983,  86.1158, -21.5517, 3.60 }, { 1984,  85.9213, -44.1669, 6.39 },
+ { 1985,  86.6896, +15.8225, 6.00 }, { 1986,  86.5117,  -3.7317, 6.34 }, { 1987,  86.7171,  +9.5222, 5.79 }, { 1988,  86.6458,  +1.1681, 5.95 },
+ { 1989,  86.8050, +14.4883, 5.72 }, { 1990,  86.8592, +17.7292, 5.49 }, { 1991,  83.9013, -77.1792, 6.05 }, { 1992,  87.6417, +56.9189, 6.54 },
+ { 1993,  86.9287, +13.8997, 5.29 }, { 1994,  88.2313, +68.4714, 6.20 }, { 1995,  87.2938, +39.1811, 4.52 }, { 1996,  86.4996, -31.6936, 5.17 },
+ { 1997,  87.0933, +20.8694, 6.07 }, { 1998,  86.7387, -13.1781, 3.55 }, { 1999,  87.0008,  +6.4542, 5.27 }, { 2000,  86.7817, -15.7622, 6.17 },
+ { 2001,  86.8612,  -9.4669, 6.03 }, { 2002,  87.2542, +24.5675, 4.86 }, { 2003,  87.7350, +51.5147, 6.29 }, { 2004,  86.9392,  -8.3303, 2.06 },
+ { 2005,  86.7696, -27.3608, 6.22 }, { 2006,  88.0725, +58.9642, 6.14 }, { 2007,  87.1454,  -3.9053, 5.97 }, { 2008,  86.6142, -45.4028, 5.31 },
+ { 2009,  86.8275, -34.3253, 6.32 }, { 2010,  87.3871, +12.6511, 4.91 }, { 2011,  87.7600, +37.3056, 4.74 }, { 2012,  87.8725, +39.1486, 3.97 },
+ { 2013,  87.7421, +27.9678, 5.56 }, { 2014,  87.5108,  +9.8711, 5.80 }, { 2015,  86.1933, -64.2644, 4.35 }, { 2016,  87.6204, +14.3056, 5.52 },
+ { 2017,  86.9921, -39.3475, 6.61 }, { 2018,  87.8571, +32.1250, 6.25 }, { 2019,  87.5546,  +4.4233, 5.97 }, { 2020,  86.8213, -50.9336, 3.85 },
+ { 2021,  87.4021, -13.5164, 5.49 }, { 2022,  84.2908, -79.5308, 5.65 }, { 2023,  86.8042, -53.6392, 6.18 }, { 2024,  87.6250,  +2.0244, 5.98 },
+ { 2025,  88.1646, +39.5744, 6.45 }, { 2026,  87.4729, -21.0283, 5.87 }, { 2027,  88.7408, +59.8883, 5.20 }, { 2028,  88.1671, +33.9175, 5.98 },
+ { 2029,  88.7117, +55.7069, 4.99 }, { 2030,  88.0975, +19.8681, 6.06 }, { 2031,  87.8417,  -6.4819, 5.35 }, { 2032,  87.3921, -43.1247, 6.38 },
+ { 2033,  88.0929, +14.1717, 5.59 }, { 2034,  88.3317, +27.6122, 4.58 }, { 2035,  87.8304, -19.1208, 3.81 }, { 2036,  87.8692, -21.0739, 6.17 },
+ { 2037,  88.1100,  +1.8550, 4.78 }, { 2038,  88.3296, +20.2992, 6.71 }, { 2039,  88.0317,  -8.9586, 5.97 }, { 2040,  87.7400, -34.2317, 3.12 },
+ { 2041,  89.3958, +66.0961, 6.25 }, { 2042,  87.4571, -55.8333, 4.51 }, { 2043,  87.9979, -28.5514, 6.45 }, { 2044,  87.6192, -51.2322, 6.35 },
+ { 2045,  89.0600, +51.8039, 6.49 }, { 2046,  88.7458, +31.7017, 5.90 }, { 2047,  88.5954, +20.2761, 4.41 }, { 2048,  88.5558, +10.5869, 6.12 },
+ { 2049,  87.7217, -51.8911, 5.17 }, { 2050,  88.6342, +11.7625, 6.59 }, { 2051,  88.5654,  +3.2253, 6.31 }, { 2052,  88.7362, +19.7497, 5.92 },
+ { 2053,  88.1383, -36.3689, 5.63 }, { 2054,  89.2704, +49.0294, 6.47 }, { 2055,  88.1988, -37.4742, 6.70 }, { 2056,  88.2788, -32.1986, 4.87 },
+ { 2057,  88.6838,  +0.9683, 6.00 }, { 2058,  88.6446,  -3.9361, 6.57 }, { 2059,  82.5579, -83.2150, 6.20 }, { 2060,  88.4892, -18.3617, 6.69 },
+ { 2061,  88.7929,  +7.4069, 0.50 }, { 2062,  86.9504, -71.2978, 6.53 }, { 2063,  88.9554, +20.1750, 5.40 }, { 2064,  87.4733, -65.0989, 5.11 },
+ { 2065,  88.6817, -10.2261, 5.66 }, { 2066,  89.1408, +28.9422, 6.32 }, { 2067,  89.0146, +13.9253, 6.60 }, { 2068,  88.5588, -28.8522, 6.36 },
+ { 2069,  88.3454, -41.0786, 6.55 }, { 2070,  88.8762,  -3.3836, 5.87 }, { 2071,  88.8975,  -3.2117, 6.28 }, { 2072,  88.0846, -56.8439, 5.94 },
+ { 2073,  87.8458, -63.9664, 6.36 }, { 2074,  89.2338, +24.2497, 6.02 }, { 2075,  89.1167,  +9.5097, 5.99 }, { 2076,  89.2062, +11.5211, 5.87 },
+ { 2077,  89.8817, +54.2847, 3.72 }, { 2078,  91.2887, +75.5858, 6.40 }, { 2079,  89.9404, +55.3208, 6.44 }, { 2080,  89.9504, +54.5472, 6.14 },
+ { 2081,  89.8408, +49.9244, 5.89 }, { 2082,  88.7188, -38.0419, 5.57 }, { 2083,  88.5446, -49.6381, 6.52 }, { 2084,  89.4988, +25.9539, 4.82 },
+ { 2085,  89.1012, -13.8322, 3.71 }, { 2086,  89.0596, -21.1597, 5.96 }, { 2087,  88.8746, -36.8792, 4.97 }, { 2088,  89.8821, +44.9475, 1.90 },
+ { 2089,  88.6713, -48.3731, 6.10 }, { 2090,  89.1437, -22.7844, 6.36 }, { 2091,  89.9838, +45.9369, 4.26 }, { 2092,  89.0871, -30.6175, 5.50 },
+ { 2093,  89.4758,  +1.2244, 6.22 }, { 2094,  88.7092, -51.3647, 5.29 }, { 2095,  89.9304, +37.2125, 2.62 }, { 2096,  90.0792, +44.5919, 6.22 },
+ { 2097,  89.5487,  +0.9942, 6.22 }, { 2098,  89.2042, -30.0239, 6.44 }, { 2099,  89.7217, +12.8086, 5.70 }, { 2100,  89.6017,  +1.8369, 5.90 },
+ { 2101,  90.2442, +47.9019, 5.73 }, { 2102,  88.5254, -62.9100, 4.65 }, { 2103,  89.7067,  +0.5531, 5.22 }, { 2104,  88.5496, -63.5178, 6.63 },
+ { 2105,  90.4296, +48.9594, 5.96 }, { 2106,  89.3842, -34.7167, 4.36 }, { 2107,  89.7542,  -8.6178, 6.12 }, { 2108,  89.7679,  -8.4417, 5.03 },
+ { 2109,  89.9071,  -0.5556, 6.63 }, { 2110,  90.2925, +31.0347, 5.98 }, { 2111,  90.2517, +27.5722, 6.05 }, { 2112,  90.7029, +49.9056, 6.05 },
+ { 2113,  90.0142,  -2.9258, 4.53 }, { 2114,  89.3100, -52.5739, 6.45 }, { 2115,  90.7233, +43.3786, 6.42 }, { 2116,  90.4233, +22.4008, 6.37 },
+ { 2117,  89.6567, -43.9656, 5.81 }, { 2118,  90.0738, -11.1003, 6.22 }, { 2119,  90.8250, +42.9117, 6.10 }, { 2120,  89.7867, -41.1847, 3.96 },
+ { 2121,  91.2846, +59.3931, 6.34 }, { 2122,  90.7296, +32.6358, 6.24 }, { 2123,  91.1213, +51.5733, 6.45 }, { 2124,  90.5958,  +9.6475, 4.12 },
+ { 2125,  87.5696, -78.6386, 5.47 }, { 2126,  91.6633, +63.4536, 6.39 }, { 2127,  90.5713,  +1.6944, 6.59 }, { 2128,  90.4600,  -9.4019, 4.95 },
+ { 2129,  90.3046, -24.5822, 6.05 }, { 2130,  90.8637, +19.6906, 5.14 }, { 2131,  90.3183, -32.0883, 5.55 }, { 2132,  91.2642, +42.9817, 5.87 },
+ { 2133,  90.8529, +11.6808, 6.08 }, { 2134,  91.0300, +23.2633, 4.16 }, { 2135,  90.9800, +20.1383, 4.63 }, { 2136,  90.6408, -13.5028, 6.20 },
+ { 2137,  91.2608, +37.9642, 6.34 }, { 2138,  90.2050, -50.7836, 5.67 }, { 2139,  91.3917, +33.5992, 6.23 }, { 2140,  90.8146, -25.7156, 5.04 },
+ { 2141,  91.5354, +35.3875, 6.12 }, { 2142,  91.0563,  -5.2908, 5.21 }, { 2143,  91.6462, +38.4828, 5.36 }, { 2144,  91.2425,  +5.4200, 5.67 },
+ { 2145,  91.2433,  +4.1586, 5.63 }, { 2146,  91.5938, +29.5125, 6.08 }, { 2147,  91.8621, +41.8542, 6.12 }, { 2148,  91.2463, -15.5156, 4.93 },
+ { 2149,  91.0846, -31.8275, 5.65 }, { 2150,  91.3625,  -9.7572, 5.87 }, { 2151,  90.5383, -59.9031, 6.45 }, { 2152,  92.4963, +58.9358, 5.36 },
+ { 2153,  92.0958, +41.0556, 6.36 }, { 2154,  91.6612,  -3.8061, 5.38 }, { 2155,  91.5387, -13.0647, 4.67 }, { 2156,  91.4404, -23.8044, 6.95 },
+ { 2157,  91.1183, -44.9633, 6.35 }, { 2158,  91.1675, -44.9211, 5.93 }, { 2159,  91.8929, +14.7683, 4.42 }, { 2160,  91.3629, -34.4864, 5.80 },
+ { 2161,  91.7163, -10.8264, 6.66 }, { 2162,  91.1954, -47.5414, 6.58 }, { 2163,  91.6333, -22.8894, 5.47 }, { 2164,  91.5229, -28.2414, 5.81 },
+ { 2165,  93.2129, +65.7183, 5.32 }, { 2166,  91.7400, -20.1872, 5.78 }, { 2167,  92.1967,  +8.6700, 6.55 }, { 2168,  91.9233, -18.8342, 5.31 },
+ { 2169,  92.3850, +22.1900, 5.93 }, { 2170,  91.7654, -33.6881, 5.83 }, { 2171,  91.6708, -41.7014, 6.12 }, { 2172,  92.9417, +52.6472, 6.30 },
+ { 2173,  92.4333, +23.1133, 5.75 }, { 2174,  92.2412,  +2.4994, 5.73 }, { 2175,  92.9021, +48.7131, 6.82 }, { 2176,  92.9025, +48.7111, 6.09 },
+ { 2177,  91.8817, -36.7469, 5.02 }, { 2178,  91.7579, -44.9086, 6.51 }, { 2179,  92.4008,  -4.2889, 6.17 }, { 2180,  92.2412, -21.5725, 5.50 },
+ { 2181,  91.9704, -41.8461, 5.50 }, { 2182,  92.3346, -17.8739, 6.35 }, { 2183,  92.3929, -13.4158, 5.56 }, { 2184,  92.7575, +18.1294, 6.33 },
+ { 2185,  92.8846, +24.4203, 5.80 }, { 2186,  92.4496, -21.2258, 5.71 }, { 2187,  92.1442, -43.6439, 6.27 }, { 2188,  93.4387, +51.1725, 6.04 },
+ { 2189,  93.0837, +32.6933, 5.78 }, { 2190,  92.9642, +21.8686, 6.56 }, { 2191,  92.8662, +13.6386, 6.04 }, { 2192,  92.4467, -25.2992, 6.27 },
+ { 2193,  93.0054, +19.7906, 5.75 }, { 2194,  91.5392, -65.9603, 5.71 }, { 2195,  92.7554,  -5.2458, 6.15 }, { 2196,  91.7642, -61.8453, 5.05 },
+ { 2197,  93.0796, +22.9083, 6.39 }, { 2198,  93.0138, +16.1306, 4.95 }, { 2199,  92.9850, +14.2089, 4.48 }, { 2200,  92.6442, -26.8458, 5.72 },
+ { 2201,  93.9192, +59.9992, 5.35 }, { 2202,  92.9321,  -3.3344, 6.18 }, { 2203,  92.5429, -39.6464, 5.58 }, { 2204,  92.3471, -48.4372, 6.49 },
+ { 2205,  92.9658,  -5.4497, 5.05 }, { 2206,  92.8063, -25.5178, 6.09 }, { 2207,  93.3892, +18.6803, 6.58 }, { 2208,  93.3025, +10.6275, 6.45 },
+ { 2209,  94.7117, +69.3197, 4.80 }, { 2210,  93.1850,  -1.4956, 6.62 }, { 2211,  92.6663, -44.7181, 6.31 }, { 2212,  92.5746, -53.0314, 4.81 },
+ { 2213,  93.1929, -16.2369, 6.52 }, { 2214,  93.6192, +17.9064, 5.88 }, { 2215,  94.4783, +61.5153, 4.98 }, { 2216,  93.7192, +22.5067, 3.28 },
+ { 2217,  93.9125, +36.1486, 6.92 }, { 2218,  93.4762,  -2.2586, 5.83 }, { 2219,  93.8446, +29.4981, 4.35 }, { 2220,  93.7121, +19.1564, 5.20 },
+ { 2221,  92.1842, -67.1567, 5.06 }, { 2222,  93.7854, +13.8511, 5.91 }, { 2223,  93.8546, +16.1431, 5.30 }, { 2224,  93.6529,  -3.4317, 5.83 },
+ { 2225,  93.4379, -22.1381, 6.39 }, { 2226,  93.3888, -28.6039, 6.54 }, { 2227,  93.7138,  -5.7253, 3.98 }, { 2228,  94.3946, +46.4242, 6.52 },
+ { 2229,  93.9375, +12.5511, 5.33 }, { 2230,  94.0792, +23.9700, 6.08 }, { 2231,  93.9171,  +6.0661, 6.07 }, { 2232,  93.9458,  +4.2836, 6.64 },
+ { 2233,  93.8929,  +0.5122, 5.65 }, { 2234,  93.8738,  -3.0847, 5.99 }, { 2235,  94.0992, +17.1814, 6.39 }, { 2236,  93.9750,  +1.1692, 6.37 },
+ { 2237,  93.8583,  -8.9647, 6.10 }, { 2238,  94.9058, +59.0108, 4.48 }, { 2239,  94.5704, +46.3606, 6.38 }, { 2240,  94.2446, +23.7408, 6.25 },
+ { 2241,  94.1108, +12.2722, 5.04 }, { 2242,  93.7850, -19.7278, 5.91 }, { 2243,  93.8229, -17.5233, 5.99 }, { 2244,  93.9371, -12.2817, 5.01 },
+ { 2245,  92.8125, -64.4106, 5.01 }, { 2246,  94.0883,  +1.0803, 6.63 }, { 2247,  94.2775,  +9.9425, 5.39 }, { 2248,  94.2433,  +7.0531, 6.57 },
+ { 2249,  94.0321, -15.3822, 5.92 }, { 2250,  94.3888, +14.0583, 6.59 }, { 2251,  94.3171,  +5.1003, 5.71 }, { 2252,  93.9883, -28.2117, 6.67 },
+ { 2253,  94.5233, +14.3828, 6.16 }, { 2254,  94.2646, -21.2850, 6.07 }, { 2255,  94.3967,  -9.2747, 6.75 }, { 2256,  94.1379, -34.8594, 4.37 },
+ { 2257,  95.5150, +59.3722, 5.94 }, { 2258,  94.7575, +17.3250, 6.32 }, { 2259,  94.6688,  +9.0472, 6.24 }, { 2260,  94.4237, -15.1842, 5.14 },
+ { 2261,  92.5600, -73.2469, 5.09 }, { 2262,  94.1483, -38.7356, 6.00 }, { 2263,  94.2550, -36.2625, 5.53 }, { 2264,  95.4421, +53.4522, 5.36 },
+ { 2265,  94.2896, -36.7469, 5.87 }, { 2266,  94.5571, -18.0331, 5.52 }, { 2267,  94.7108,  -8.6097, 5.36 }, { 2268,  94.7033, -14.9753, 6.06 },
+ { 2269,  95.0175, +14.6511, 5.69 }, { 2270,  94.7829,  -7.4136, 6.22 }, { 2271,  94.7458, -19.0739, 5.81 }, { 2272,  95.3004, +29.5411, 6.43 },
+ { 2273,  94.9283,  -6.1769, 5.27 }, { 2274,  94.0771, -58.7864, 6.43 }, { 2275,  94.9983,  -1.0556, 4.90 }, { 2276,  95.2179, +11.7564, 6.54 },
+ { 2277,  95.3579, +17.7636, 6.35 }, { 2278,  94.4654, -51.2669, 6.41 }, { 2279,  94.9208, -33.6033, 5.78 }, { 2280,  95.3575,  +2.2686, 6.31 },
+ { 2281,  94.6950, -49.6408, 7.04 }, { 2282,  95.0783, -29.9367, 3.02 }, { 2283,  93.7746, -70.2972, 6.64 }, { 2284,  95.3529, -10.2267, 5.64 },
+ { 2285,  97.0608, +70.5356, 5.97 }, { 2286,  95.7400, +22.5136, 2.88 }, { 2287,  95.6521, +12.5700, 6.00 }, { 2288,  95.1513, -33.8561, 5.53 },
+ { 2289,  96.2246, +49.2881, 4.91 }, { 2290,  95.0254, -47.2589, 6.60 }, { 2291,  96.6075, +56.2850, 5.64 }, { 2292,  95.8271,  +3.7644, 6.40 },
+ { 2293,  96.7037, +58.4172, 5.21 }, { 2294,  95.6750, -16.0442, 1.98 }, { 2295,  95.8446,  -3.3128, 6.67 }, { 2296,  95.5283, -32.5636, 3.85 },
+ { 2297,  96.2192, +29.7072, 6.71 }, { 2298,  95.9421,  +4.5928, 4.44 }, { 2299,  95.9437,  +4.5956, 6.72 }, { 2300,  96.0096,  +8.8847, 6.26 },
+ { 2301,  95.9000,  -8.1256, 6.19 }, { 2302,  96.2204, +16.0569, 6.33 }, { 2303,  95.9417, -14.9283, 6.24 }, { 2304,  96.3871, +23.3269, 6.06 },
+ { 2305,  96.0429, -10.4697, 5.22 }, { 2306,  95.9483, -18.2147, 6.60 }, { 2307,  95.8100, -30.2100, 6.34 }, { 2308,  96.3671, +14.7219, 6.24 },
+ { 2309,  96.0854, -11.0375, 6.12 }, { 2310,  96.3046,  +7.0858, 5.98 }, { 2311,  95.9829, -24.4222, 5.63 }, { 2312,  96.3267,  +1.5011, 6.66 },
+ { 2313,  96.3183,  +0.9461, 5.87 }, { 2314,  96.9629, +47.4053, 6.56 }, { 2315,  96.4442,  +2.2722, 6.51 }, { 2316,  96.0042, -35.2922, 5.62 },
+ { 2317,  96.4463,  -2.1108, 6.35 }, { 2318,  96.1829, -27.2200, 6.39 }, { 2319,  96.8979, +32.5631, 6.43 }, { 2320,  95.7325, -55.6300, 5.61 },
+ { 2321,  96.4950,  -6.1058, 6.40 }, { 2322,  95.9071, -51.8189, 5.98 }, { 2323,  96.1854, -39.7158, 6.31 }, { 2324,  96.6650,  -0.4928, 5.87 },
+ { 2325,  96.6437,  -3.4028, 6.15 }, { 2326,  95.9879, -51.3042, -0.72 }, { 2327,  96.7446,  +0.8408, 6.71 }, { 2328,  96.6871,  -6.4886, 6.27 },
+ { 2329,  96.3746, -34.9361, 6.25 }, { 2330,  96.9858, +20.4961, 6.22 }, { 2331,  97.6967, +58.1628, 5.88 }, { 2332,  97.1421, +30.4931, 5.55 },
+ { 2333,  96.8350,  +2.9081, 5.55 }, { 2334,  96.8075,  +0.2992, 5.20 }, { 2335,  96.8150,  +0.2761, 5.55 }, { 2336,  95.9454, -57.4561, 6.48 },
+ { 2337,  95.7554, -62.3169, 6.27 }, { 2338,  97.5125, +46.6856, 5.90 }, { 2339,  97.2358, +26.9678, 6.47 }, { 2340,  97.1167, +16.2383, 6.23 },
+ { 2341,  96.2008, -51.1936, 6.51 }, { 2342,  97.0783, +10.3039, 6.15 }, { 2343,  97.2408, +20.2122, 4.15 }, { 2344,  96.9900,  -3.2378, 5.06 },
+ { 2345,  96.0571, -59.7189, 5.80 }, { 2346, 100.0700, +79.5994, 6.54 }, { 2347,  97.0700,  +1.9122, 6.48 }, { 2348,  96.4317, -47.8228, 5.76 },
+ { 2349,  96.7967, -24.1433, 6.07 }, { 2350, 101.1258, +82.1153, 6.65 }, { 2351,  97.2500, +11.0194, 6.59 }, { 2352,  95.6592, -68.0158, 5.56 },
+ { 2353,  96.7813, -36.1044, 6.48 }, { 2354,  96.1096, -62.5711, 6.46 }, { 2355,  97.3121,  +2.6461, 6.16 }, { 2356,  97.2042,  -6.9672, 4.60 },
+ { 2357,  97.2062,  -6.9656, 5.40 }, { 2358,  97.2062,  -6.9656, 5.60 }, { 2359,  97.1554, -16.5339, 5.77 }, { 2360,  96.2317, -62.1722, 6.27 },
+ { 2361,  97.0421, -31.4200, 4.48 }, { 2362,  97.5229,  +9.0292, 6.57 }, { 2363, 100.1200, +77.9958, 5.73 }, { 2364,  97.1633, -31.6289, 5.74 },
+ { 2365,  99.4788, +73.6956, 6.24 }, { 2366,  97.7921, +16.9386, 6.20 }, { 2367,  97.5471,  -9.9186, 5.93 }, { 2368,  97.1762, -40.9256, 6.32 },
+ { 2369,  96.7667, -57.9978, 5.82 }, { 2370,  97.7896, +11.2508, 6.14 }, { 2371,  97.9058, +15.9033, 6.40 }, { 2372,  98.1133, +32.4547, 5.87 },
+ { 2373,  97.6446, -12.8519, 6.16 }, { 2374,  97.9133, +11.7922, 6.65 }, { 2375,  97.9513, +11.5444, 5.23 }, { 2376,  98.6367, +55.3531, 6.45 },
+ { 2377,  96.3692, -68.3097, 5.38 }, { 2378,  98.0971, +11.6736, 6.03 }, { 2379,  97.8458, -11.6083, 5.15 }, { 2380,  97.6929, -26.2306, 5.93 },
+ { 2381,  97.9587,  -7.8419, 5.43 }, { 2382,  98.0800,  +4.8558, 5.84 }, { 2383,  98.4279, +33.0242, 6.42 }, { 2384,  97.4546, -49.7608, 5.27 },
+ { 2385,  98.2258,  +7.3331, 4.50 }, { 2386,  98.0962,  -4.1311, 5.60 }, { 2387,  97.9638, -22.5817, 4.33 }, { 2388,  97.8042, -34.7408, 5.84 },
+ { 2389,  97.3688, -55.1472, 5.22 }, { 2390,  97.7492, -39.0836, 6.20 }, { 2391,  98.4004, +14.1553, 5.53 }, { 2392,  98.1954, -10.8336, 6.24 },
+ { 2393,  97.8958, -35.0600, 6.34 }, { 2394,  99.4225, +61.4811, 5.94 }, { 2395,  98.4079,  -0.7797, 5.10 }, { 2396, 100.1342, +71.7489, 5.92 },
+ { 2397,  98.1625, -31.9694, 5.69 }, { 2398,  98.8004, +28.0222, 5.27 }, { 2399,  98.0888, -36.3033, 5.24 }, { 2400,  97.8263, -50.1739, 5.60 },
+ { 2401, 101.5588, +79.5647, 5.45 }, { 2402,  99.4104, +56.8575, 5.85 }, { 2403,  98.3608, -19.0761, 6.40 }, { 2404,  98.6933,  +7.5725, 6.45 },
+ { 2405,  99.1371, +38.4453, 5.29 }, { 2406,  98.8233,  +9.9883, 5.88 }, { 2407,  98.2929, -37.3747, 6.44 }, { 2408,  97.5125, -64.4317, 6.29 },
+ { 2409,  98.8158,  +0.8900, 5.80 }, { 2410,  97.7942, -60.1203, 6.15 }, { 2411,  98.4562, -35.7678, 5.42 }, { 2412,  97.9933, -57.2458, 5.70 },
+ { 2413,  99.0000,  +4.4975, 6.55 }, { 2414,  98.7642, -21.0353, 4.54 }, { 2415,  98.6471, -31.2836, 5.62 }, { 2416,  98.3588, -51.6711, 6.19 },
+ { 2417,  99.3633, +24.5908, 6.44 }, { 2418,  99.1471,  -4.7889, 5.52 }, { 2419,  99.6646, +39.3908, 5.69 }, { 2420,  99.7050, +39.9025, 5.20 },
+ { 2421,  99.4279, +16.3992, 1.93 }, { 2422,  99.3504,  +6.1353, 6.06 }, { 2423,  99.0950, -17.3400, 5.70 }, { 2424,  98.8504, -35.2200, 5.59 },
+ { 2425,  99.5958, +28.9842, 5.79 }, { 2426,  99.4038, +10.8531, 6.38 }, { 2427,  99.8329, +42.4889, 4.79 }, { 2428,  99.1946, -12.6792, 5.97 },
+ { 2429,  99.1708, -18.7442, 3.95 }, { 2430,  99.4179,  +2.7042, 6.17 }, { 2431,  98.9750, -35.9111, 6.35 }, { 2432,  99.4696,  +4.9572, 6.15 },
+ { 2433,  99.1704, -21.3850, 6.35 }, { 2434,  99.9917, +44.0139, 6.41 }, { 2435,  98.7442, -51.0244, 4.39 }, { 2436,  99.7721, +22.0308, 6.04 },
+ { 2437,  99.4204, -11.0150, 6.12 }, { 2438,  99.8879, +28.2631, 6.03 }, { 2439,  99.8808, +24.6000, 6.38 }, { 2440,  99.5854,  -1.4564, 6.14 },
+ { 2441,  99.7062,  +4.7006, 6.57 }, { 2442,  99.6587,  +1.6136, 6.21 }, { 2443,  99.4725, -17.7625, 4.43 }, { 2444,  99.2579, -37.8533, 6.04 },
+ { 2445,  99.2138, -40.4431, 6.34 }, { 2446,  99.3075, -35.0094, 5.71 }, { 2447,  99.4483, -31.6603, 5.27 }, { 2448,  99.6475, -15.1264, 6.03 },
+ { 2449,  99.9483, +12.9831, 5.97 }, { 2450,  99.8196, -13.8542, 4.82 }, { 2451,  99.4404, -42.8039, 3.17 }, { 2452, 100.4071, +35.9319, 6.46 },
+ { 2453, 100.3375, +28.1964, 6.42 }, { 2454, 100.1325,  +6.3717, 6.51 }, { 2455,  99.9013, -22.3044, 6.05 }, { 2456, 100.2446,  +9.8956, 4.66 },
+ { 2457, 100.3408, +16.3975, 6.28 }, { 2458, 100.3217, +11.0033, 6.11 }, { 2459, 100.7708, +44.5244, 5.02 }, { 2460,  99.9279, -29.5297, 5.71 },
+ { 2461, 100.2725,  +0.4953, 5.79 }, { 2462,  99.6567, -47.7797, 4.93 }, { 2463, 101.0483, +53.2964, 6.27 }, { 2464, 100.8075, +37.1469, 6.19 },
+ { 2465,  99.9871, -37.8411, 6.58 }, { 2466, 100.6012, +17.6453, 5.21 }, { 2467, 100.4971,  +6.3450, 6.37 }, { 2468,  99.5025, -60.4669, 6.18 },
+ { 2469, 100.4850,  -8.8328, 5.19 }, { 2470, 101.5588, +59.4417, 4.87 }, { 2471, 101.0525, +36.1097, 6.31 }, { 2472,   0.0000,  +0.0000, 0.00 },
+ { 2473, 100.9829, +25.1311, 2.98 }, { 2474, 100.7771,  +3.0333, 6.19 }, { 2475, 100.3088, -39.6503, 6.12 }, { 2476, 100.2054, -46.3253, 6.65 },
+ { 2477, 101.7063, +57.1692, 5.35 }, { 2478, 100.9971, +13.2278, 4.49 }, { 2479, 100.9113,  +3.9322, 5.90 }, { 2480, 101.1896, +28.9708, 5.44 },
+ { 2481, 100.6908, -21.5508, 6.13 }, { 2482, 100.5683, -37.6014, 6.29 }, { 2483, 101.6846, +43.5775, 5.25 }, { 2484, 101.3225, +12.8956, 3.36 },
+ { 2485, 102.0537, +55.7044, 6.33 }, { 2486, 102.0513, +55.7044, 6.28 }, { 2487, 101.9150, +48.7894, 5.22 }, { 2488, 100.8471, -38.8067, 6.30 },
+ { 2489, 101.4758, +12.6936, 6.46 }, { 2490, 102.7379, +67.5719, 5.14 }, { 2491, 101.2871, -15.2839, -1.46 }, { 2492, 101.1183, -30.9294, 5.20 },
+ { 2493, 101.2163, -26.6586, 6.45 }, { 2494, 101.6350,  +8.5872, 5.93 }, { 2495, 101.3471, -22.5381, 6.05 }, { 2496,   0.0000,  +0.0000, 0.00 },
+ { 2497, 101.2600, -29.4139, 6.54 }, { 2498, 101.4971, -13.2039, 5.32 }, { 2499, 101.8479, +18.1933, 6.20 }, { 2500, 101.3450, -30.2064, 5.92 },
+ { 2501, 101.3804, -29.0511, 5.80 }, { 2502, 101.6625,  -9.8928, 5.66 }, { 2503, 101.8325,  +8.0372, 4.77 }, { 2504, 101.7129, -13.5742, 5.29 },
+ { 2505, 100.2408, -70.2244, 6.51 }, { 2506, 101.9650,  +2.4122, 4.47 }, { 2507, 101.5138, -38.4600, 6.62 }, { 2508, 101.9046,  -7.0017, 5.07 },
+ { 2509, 101.7562, -20.9844, 6.08 }, { 2510, 101.5504, -36.2244, 6.21 }, { 2511, 103.4258, +68.8883, 5.12 }, { 2512, 102.4221, +32.6067, 5.71 },
+ { 2513, 101.3588, -51.7989, 6.57 }, { 2514, 102.0792,  -0.6808, 5.75 }, { 2515, 101.4738, -51.5900, 5.80 }, { 2516, 102.6913, +41.7814, 5.02 },
+ { 2517, 102.2654,  +1.0019, 6.15 }, { 2518, 101.8392, -36.0703, 5.26 }, { 2519, 102.4575, +16.2028, 5.85 }, { 2520, 103.2712, +59.4486, 5.33 },
+ { 2521, 102.3183,  -1.7281, 5.74 }, { 2522, 102.2408, -14.8553, 5.39 }, { 2523, 101.7200, -50.7342, 5.40 }, { 2524, 101.6729, -53.3053, 6.46 },
+ { 2525, 102.6063, +13.4133, 5.65 }, { 2526, 101.8279, -54.4600, 5.61 }, { 2527, 105.0167, +76.9775, 4.55 }, { 2528, 102.4333, -23.9242, 6.33 },
+ { 2529, 102.8875, +21.7611, 5.27 }, { 2530, 102.7079,  +0.5408, 5.77 }, { 2531, 100.9033, -72.8819, 6.37 }, { 2532, 103.2817, +44.8394, 6.26 },
+ { 2533, 103.0000, +23.6017, 5.65 }, { 2534, 102.6763,  -7.9589, 6.29 }, { 2535, 102.5913, -16.9161, 5.79 }, { 2536, 101.2338, -69.5661, 6.11 },
+ { 2537, 102.5250, -26.6661, 7.04 }, { 2538, 102.4604, -31.4914, 3.96 }, { 2539, 103.2562, +38.8692, 6.12 }, { 2540, 103.1971, +33.9611, 3.60 },
+ { 2541, 103.3058, +38.4381, 6.30 }, { 2542, 103.2642, +35.7886, 6.01 }, { 2543, 102.9137,  +3.0417, 6.38 }, { 2544, 102.6538, -24.2219, 6.33 },
+ { 2545, 102.5971, -30.2939, 5.70 }, { 2546, 102.4908, -44.5500, 6.55 }, { 2547, 103.4875, +38.5050, 6.48 }, { 2548, 102.4775, -45.3853, 5.14 },
+ { 2549, 102.7183, -33.6328, 4.99 }, { 2550, 102.0475, -60.0586, 3.27 }, { 2551, 103.2058,  +8.3803, 5.77 }, { 2552, 103.0954,  -4.6839, 6.30 },
+ { 2553, 102.4842, -49.3853, 2.93 }, { 2554, 102.4638, -52.3778, 4.40 }, { 2555, 103.3438, +10.9964, 6.24 }, { 2556, 103.8133, +45.8264, 6.34 },
+ { 2557, 103.8113, +43.9100, 6.13 }, { 2558, 102.9263, -35.7697, 5.96 }, { 2559, 100.0113, -79.1864, 5.64 }, { 2560, 104.3187, +58.4225, 4.35 },
+ { 2561, 104.3050, +57.5633, 6.05 }, { 2562, 102.5046, -59.7508, 6.11 }, { 2563, 102.8867, -47.7075, 6.42 }, { 2564, 103.6613, +13.1778, 4.65 },
+ { 2565, 103.3283, -18.9672, 5.64 }, { 2566, 103.3404, -17.0667, 6.14 }, { 2567, 103.2504, -25.0425, 6.40 }, { 2568, 104.1346, +46.2742, 5.87 },
+ { 2569, 103.8275, +25.3756, 5.73 }, { 2570, 103.5354,  -4.1475, 6.41 }, { 2571, 103.3871, -19.7758, 4.83 }, { 2572, 103.6025,  -0.8731, 5.45 },
+ { 2573, 104.2333, +46.7050, 5.86 }, { 2574, 103.5475, -11.9614, 4.07 }, { 2575, 103.1654, -41.4956, 6.52 }, { 2576, 103.3913, -27.4603, 6.04 },
+ { 2577, 103.6754,  -0.2436, 6.21 }, { 2578, 103.4804, -23.4608, 6.21 }, { 2579, 103.1963, -42.0242, 6.46 }, { 2580, 103.5329, -23.8161, 3.87 },
+ { 2581, 105.3396, +70.8081, 5.68 }, { 2582, 103.7450,  -1.1964, 6.04 }, { 2583, 103.5542, -22.0717, 6.91 }, { 2584, 103.8942,  +8.3247, 6.29 },
+ { 2585, 104.4046, +45.0942, 4.90 }, { 2586, 104.2521, +33.6811, 5.89 }, { 2587, 103.1954, -53.9100, 6.57 }, { 2588, 103.7613, -19.5953, 5.74 },
+ { 2589, 104.1075,  +9.9564, 5.92 }, { 2590, 103.9058, -19.8636, 4.68 }, { 2591, 103.6113, -41.6344, 6.32 }, { 2592, 103.1892, -58.6589, 6.41 },
+ { 2593, 104.0275, -13.9564, 5.00 }, { 2594, 103.5096, -49.3883, 6.26 }, { 2595, 103.9450, -21.0586, 5.30 }, { 2596, 104.0342, -16.9458, 4.37 },
+ { 2597, 104.3571, +11.9075, 6.27 }, { 2598, 103.9783, -30.2100, 6.36 }, { 2599, 104.2504,  -7.8211, 6.34 }, { 2600, 104.7617, +38.0522, 6.00 },
+ { 2601, 104.6975, +26.0811, 6.10 }, { 2602, 102.8625, -69.0367, 5.40 }, { 2603, 104.3117, -21.7967, 6.61 }, { 2604, 104.1904, -34.6583, 6.29 },
+ { 2605, 104.8662, +25.9142, 6.40 }, { 2606, 104.6625,  +7.6219, 6.27 }, { 2607, 104.3913, -23.3694, 5.46 }, { 2608, 104.0667, -47.2789, 4.95 },
+ { 2609, 115.1271, +87.0200, 5.07 }, { 2610, 104.7375,  +3.6022, 5.97 }, { 2611, 104.4267, -26.4625, 6.23 }, { 2612, 104.3233, -34.4925, 6.23 },
+ { 2613, 104.8337,  +7.3169, 6.35 }, { 2614, 104.5317, -26.8353, 6.37 }, { 2615, 105.0658, +16.0789, 5.68 }, { 2616, 104.6496, -24.5861, 5.59 },
+ { 2617, 106.4658, +70.7319, 6.50 }, { 2618, 104.6563, -27.0278, 1.50 }, { 2619, 104.6046, -33.8883, 5.06 }, { 2620, 105.3217, +32.4144, 6.59 },
+ { 2621, 104.6825, -29.0022, 6.42 }, { 2622, 105.0750,  -4.6331, 6.30 }, { 2623, 104.9137, -20.3967, 6.26 }, { 2624, 105.0988,  -7.5931, 5.96 },
+ { 2625, 105.0338, -19.8411, 6.31 }, { 2626, 104.6742, -44.2319, 6.22 }, { 2627, 105.1637,  -8.7969, 6.49 }, { 2628, 105.0804, -21.8806, 6.53 },
+ { 2629, 105.4225,  +4.8181, 6.63 }, { 2630, 105.6033, +24.2153, 5.18 }, { 2631, 105.6063, +17.7556, 5.94 }, { 2632, 105.5725, +15.3361, 5.74 },
+ { 2633, 105.4792,  +5.5575, 6.59 }, { 2634, 104.6650, -54.2706, 6.27 }, { 2635, 105.6396, +16.6742, 5.82 }, { 2636, 105.4704,  -0.6544, 6.17 },
+ { 2637, 105.1775, -27.5106, 6.27 }, { 2638, 104.6508, -55.6053, 6.45 }, { 2639, 105.4850,  -4.2778, 5.20 }, { 2640, 105.2746, -24.7847, 5.63 },
+ { 2641, 105.2075, -32.5347, 6.40 }, { 2642, 106.5054, +59.8019, 6.44 }, { 2643, 105.8767, +29.3372, 5.93 }, { 2644, 106.4158, +52.7581, 6.12 },
+ { 2645, 106.2875, +47.7750, 6.38 }, { 2646, 105.4296, -26.0653, 3.47 }, { 2647, 105.8246,  +9.1383, 5.97 }, { 2648, 105.7283,  -3.7608, 4.99 },
+ { 2649, 105.9083, +10.9517, 5.13 }, { 2650, 106.0271, +20.5703, 3.79 }, { 2651, 105.9650, +12.5944, 5.98 }, { 2652, 105.2146, -50.5975, 5.14 },
+ { 2653, 105.7562, -22.1667, 3.02 }, { 2654, 106.0842,  +1.4883, 6.57 }, { 2655, 106.0217,  -4.6764, 5.62 }, { 2656, 105.9888,  -9.8758, 6.45 },
+ { 2657, 105.9396, -14.3667, 4.12 }, { 2658, 105.5650, -42.5958, 6.43 }, { 2659, 106.3267, +22.6372, 6.02 }, { 2660, 106.5483, +34.4739, 5.55 },
+ { 2661, 105.2712, -57.0600, 6.02 }, { 2662, 104.9604, -66.0839, 5.17 }, { 2663, 106.4129,  +9.1858, 5.78 }, { 2664, 106.1963, -21.9678, 6.09 },
+ { 2665, 106.8429, +34.0094, 5.91 }, { 2666, 106.0117, -41.6628, 5.20 }, { 2667, 105.9888, -42.3919, 5.54 }, { 2668, 105.9950, -42.3883, 6.79 },
+ { 2669, 106.8542, +28.1772, 6.48 }, { 2670, 106.4571,  -9.3389, 6.49 }, { 2671, 106.8392, +22.7036, 7.68 }, { 2672, 105.9738, -48.4161, 4.93 },
+ { 2673, 107.0554, +33.8322, 6.28 }, { 2674, 105.8150, -58.8219, 5.50 }, { 2675, 107.1513, +37.4450, 6.16 }, { 2676, 106.7767,  +4.9103, 6.11 },
+ { 2677, 106.3833, -33.2222, 6.14 }, { 2678, 106.6696, -10.7058, 5.39 }, { 2679, 106.6496, -11.6061, 6.48 }, { 2680, 106.5025, -29.3444, 6.34 },
+ { 2681, 108.4921, +71.8167, 6.35 }, { 2682, 106.9563,  +7.4711, 5.75 }, { 2683, 106.0763, -55.2503, 5.17 }, { 2684, 107.0917, +15.9308, 5.44 },
+ { 2685, 106.5096, -37.6172, 6.11 }, { 2686, 106.7179, -23.0394, 6.08 }, { 2687, 106.3187, -49.6397, 6.46 }, { 2688, 106.7504, -25.3422, 6.62 },
+ { 2689, 104.1433, -78.5797, 5.45 }, { 2690, 106.8442, -22.1597, 5.71 }, { 2691, 106.7796, -39.1067, 5.79 }, { 2692, 107.5279, +21.2469, 6.43 },
+ { 2693, 107.0979, -25.6067, 1.84 }, { 2694, 107.3346,  -9.6528, 6.21 }, { 2695, 107.2054, -23.9558, 6.65 }, { 2696, 107.9137, +39.3206, 4.90 },
+ { 2697, 107.7850, +30.2453, 4.41 }, { 2698, 106.8054, -50.0322, 5.96 }, { 2699, 107.3883, -15.7653, 6.03 }, { 2700, 107.8463, +26.8567, 5.78 },
+ { 2701, 107.5571,  -3.7628, 4.92 }, { 2702, 107.2129, -38.3442, 4.83 }, { 2703, 108.3475, +51.4289, 5.47 }, { 2704, 107.4287, -24.7689, 5.69 },
+ { 2705, 107.5387, -17.3147, 6.23 }, { 2706, 108.1100, +24.1283, 5.85 }, { 2707, 107.8483,  +0.3019, 5.45 }, { 2708, 107.5808, -26.5086, 5.46 },
+ { 2709, 111.3413, +81.2575, 6.31 }, { 2710, 107.9638,  +5.6547, 6.09 }, { 2711, 108.2042, +27.2247, 6.43 }, { 2712, 106.5588, -67.1628, 6.47 },
+ { 2713, 108.0308,  +5.4747, 6.16 }, { 2714, 107.9663,  +0.4928, 4.15 }, { 2715, 108.9788, +59.6375, 5.20 }, { 2716, 107.9233, -19.1169, 5.84 },
+ { 2717, 108.3429, +16.1589, 5.00 }, { 2718, 108.0508, -24.0575, 5.92 }, { 2719, 107.6979, -47.0678, 5.14 }, { 2720, 108.0171, -29.1783, 6.10 },
+ { 2721, 108.9587, +47.2400, 5.58 }, { 2722, 108.6108, +24.7108, 6.89 }, { 2723, 108.2800, -10.7486, 5.78 }, { 2724, 108.1004, -26.5258, 6.59 },
+ { 2725, 108.6746, +24.8850, 5.82 }, { 2726, 108.1071, -35.4556, 5.96 }, { 2727, 108.0658, -39.5011, 5.31 }, { 2728, 108.6358, +12.1158, 5.62 },
+ { 2729, 108.5833,  +3.1114, 5.35 }, { 2730, 108.3496, -21.3267, 6.01 }, { 2731, 108.5458,  -2.0986, 5.75 }, { 2732, 108.5646,  -8.0525, 5.90 },
+ { 2733, 108.4513, -21.0936, 6.36 }, { 2734, 108.4013, -26.6436, 6.12 }, { 2735, 107.1758, -69.5028, 5.69 }, { 2736, 107.1871, -69.5011, 3.78 },
+ { 2737, 109.3904, +52.1308, 5.92 }, { 2738, 108.9879, +27.8975, 5.71 }, { 2739, 108.6175,  -9.6833, 6.03 }, { 2740, 108.1400, -45.2406, 4.49 },
+ { 2741, 108.4463, -30.9161, 6.60 }, { 2742, 112.7683, +82.4114, 4.96 }, { 2743, 108.4883, -29.6600, 6.33 }, { 2744, 108.8304,  +0.1614, 6.41 },
+ { 2745, 108.5633, -25.6475, 4.66 }, { 2746, 108.3058, -44.8169, 4.89 }, { 2747, 108.9142,  +7.9778, 5.82 }, { 2748, 108.3850, -43.3603, 5.10 },
+ { 2749, 108.7029, -25.2272, 3.85 }, { 2750, 108.7129, -26.9619, 5.58 }, { 2751, 109.6329, +49.4650, 5.05 }, { 2752, 108.9296,  -9.4161, 5.95 },
+ { 2753, 109.5092, +40.8833, 5.78 }, { 2754, 108.0083, -62.8100, 6.02 }, { 2755, 108.9479, -22.2594, 6.32 }, { 2756, 108.8375, -29.3136, 5.36 },
+ { 2757, 109.5171, +30.9558, 6.24 }, { 2758, 109.0604, -14.4142, 5.46 }, { 2759, 108.7379, -40.5742, 5.94 }, { 2760, 109.3242,  +6.6806, 6.65 },
+ { 2761, 108.6913, -45.1503, 5.72 }, { 2762, 108.6592, -47.7283, 4.76 }, { 2763, 109.5233, +16.5403, 3.58 }, { 2764, 109.1533, -22.6844, 4.79 },
+ { 2765, 109.3821,  -5.3200, 6.29 }, { 2766, 109.1458, -26.1189, 4.64 }, { 2767, 108.8375, -51.5003, 5.97 }, { 2768, 109.2383, -29.1033, 6.32 },
+ { 2769, 109.1325, -37.6811, 5.80 }, { 2770, 109.2063, -35.4072, 5.03 }, { 2771, 109.0646, -45.2256, 5.66 }, { 2772, 110.5717, +59.9019, 6.35 },
+ { 2773, 109.2858, -36.9025, 2.70 }, { 2774, 109.4496, -25.2025, 6.46 }, { 2775, 110.2629, +42.6556, 6.35 }, { 2776, 110.3229, +45.2281, 5.77 },
+ { 2777, 110.0308, +21.9822, 3.53 }, { 2778, 109.8433,  +2.7406, 5.89 }, { 2779, 109.9483,  +7.1428, 5.91 }, { 2780, 110.0288, +15.1428, 6.45 },
+ { 2781, 109.6679, -23.4411, 4.98 }, { 2782, 109.6767, -23.0458, 4.40 }, { 2783, 110.7121, +55.2844, 6.53 }, { 2784, 110.7171, +55.2814, 5.45 },
+ { 2785, 109.7583, -18.7197, 6.09 }, { 2786, 109.7133, -25.4142, 5.28 }, { 2787, 109.5767, -35.2658, 4.66 }, { 2788, 109.8671, -15.6050, 5.70 },
+ { 2789, 109.5175, -42.0133, 5.85 }, { 2790, 109.6592, -35.2572, 5.11 }, { 2791, 109.6400, -38.7897, 5.25 }, { 2792, 110.5558, +38.9961, 6.40 },
+ { 2793, 110.5108, +36.7606, 5.13 }, { 2794, 109.8071, -32.2728, 6.30 }, { 2795, 110.4867, +20.4436, 5.10 }, { 2796, 110.2425, -13.6400, 5.45 },
+ { 2797, 113.6654, +80.8967, 6.41 }, { 2798, 110.3204,  -7.1217, 6.55 }, { 2799, 110.2217, -21.1483, 6.61 }, { 2800, 110.2292, -25.0364, 6.01 },
+ { 2801, 110.5146,  +0.1772, 5.99 }, { 2802, 110.2679, -24.1086, 5.87 }, { 2803, 109.2075, -66.0428, 3.98 }, { 2804, 111.2383, +51.8872, 5.80 },
+ { 2805, 111.0354, +40.6722, 5.19 }, { 2806, 110.5083,  -7.0208, 6.43 }, { 2807, 110.5771,  -1.0211, 6.23 }, { 2808, 110.8688, +25.0506, 5.03 },
+ { 2809, 111.8575, +66.3317, 6.47 }, { 2810, 110.8675, +22.9453, 6.02 }, { 2811, 110.6058,  -4.0172, 5.82 }, { 2812, 110.5563, -18.9833, 4.96 },
+ { 2813, 110.0892, -51.6883, 6.05 }, { 2814, 110.0904, -51.6903, 6.60 }, { 2815, 110.1613, -51.9139, 5.39 }, { 2816, 111.1392, +27.6381, 5.76 },
+ { 2817, 111.1154, +15.5172, 6.41 }, { 2818, 111.6783, +49.2114, 4.64 }, { 2819, 110.7525, -30.0761, 5.43 }, { 2820, 111.2425, +11.6697, 5.30 },
+ { 2821, 111.4317, +27.7981, 3.79 }, { 2822, 110.8713, -26.1658, 5.38 }, { 2823, 110.8829, -31.7978, 5.39 }, { 2824, 110.9762, -29.7831, 6.60 },
+ { 2825, 111.1671, -15.7989, 5.33 }, { 2826, 111.0717, -21.0872, 6.19 }, { 2827, 111.0238, -28.6969, 2.45 }, { 2828, 111.4121,  +9.2761, 4.99 },
+ { 2829, 110.9929, -34.1622, 6.31 }, { 2830, 112.7196, +68.4656, 5.64 }, { 2831, 111.2113, -18.9878, 6.24 }, { 2832, 111.2846, -12.2481, 5.78 },
+ { 2833, 111.4625,  -4.2250, 5.97 }, { 2834, 111.1825, -30.1911, 5.35 }, { 2835, 111.7092, +21.5358, 6.54 }, { 2836, 111.6162, +10.6083, 6.37 },
+ { 2837, 111.7346, +20.2572, 5.93 }, { 2838, 111.5146,  -3.4625, 6.76 }, { 2839, 111.3329, -20.0172, 6.05 }, { 2840, 111.6721, +11.0092, 6.41 },
+ { 2841, 111.3554, -24.7822, 5.78 }, { 2842, 111.1967, -36.7100, 6.97 }, { 2843, 111.1971, -36.7092, 6.84 }, { 2844, 112.2150, +48.1839, 5.72 },
+ { 2845, 111.7875,  +8.2894, 2.90 }, { 2846, 111.9350, +21.4450, 5.22 }, { 2847, 111.4292, -30.2614, 6.31 }, { 2848, 101.7446, -86.9750, 6.47 },
+ { 2849, 112.4833, +49.6725, 5.36 }, { 2850, 111.6696, -22.2878, 6.56 }, { 2851, 112.0088,  +6.9419, 5.25 }, { 2852, 112.2779, +31.7844, 4.18 },
+ { 2853, 111.7833, -16.1356, 5.63 }, { 2854, 112.0408,  +8.9256, 4.32 }, { 2855, 111.7475, -22.9139, 5.61 }, { 2856, 111.6763, -33.8592, 5.90 },
+ { 2857, 112.3350, +28.1181, 5.05 }, { 2858, 112.1971, +15.1094, 6.22 }, { 2859, 111.9654, -10.4431, 5.79 }, { 2860, 111.9287, -21.1403, 5.95 },
+ { 2861, 112.4529, +27.9161, 5.01 }, { 2862, 111.5913, -50.9817, 5.10 }, { 2863, 111.9967, -28.8442, 5.54 }, { 2864, 112.4492, +12.0067, 4.54 },
+ { 2865, 112.3279,  -0.0947, 5.59 }, { 2866, 112.3571,  -6.4489, 5.86 }, { 2867, 112.3421,  -9.6733, 5.75 }, { 2868, 112.3413, -13.0008, 6.05 },
+ { 2869, 112.0950, -36.1897, 6.58 }, { 2870, 112.2138, -30.1517, 6.38 }, { 2871, 112.2146, -30.1531, 7.13 }, { 2872, 112.9821, +38.8964, 6.54 },
+ { 2873, 112.2704, -30.5436, 5.77 }, { 2874, 112.4642, -22.9756, 4.85 }, { 2875, 112.2738, -37.1878, 5.43 }, { 2876, 112.7129,  -4.7736, 6.24 },
+ { 2877, 112.9517, +17.0861, 5.42 }, { 2878, 112.3075, -42.6986, 3.25 }, { 2879, 113.2108, +22.8878, 6.54 }, { 2880, 113.0246,  +1.9144, 5.25 },
+ { 2881, 112.6771, -29.0378, 4.65 }, { 2882, 112.6767, -36.6603, 6.65 }, { 2883, 113.0242,  -7.1192, 5.90 }, { 2884, 112.4983, -51.3489, 5.87 },
+ { 2885, 112.8575, -35.8472, 6.68 }, { 2886, 113.4021, +15.8267, 5.25 }, { 2887, 113.2983,  +3.2903, 5.59 }, { 2888, 112.2138, -63.4900, 6.39 },
+ { 2889, 112.9283, -34.1122, 6.61 }, { 2890, 113.6500, +31.8886, 2.88 }, { 2891, 113.6500, +31.8883, 1.98 }, { 2892, 112.6288, -53.6006, 5.96 },
+ { 2893, 113.5212, +10.5683, 6.28 }, { 2894, 114.1958, +55.7553, 5.92 }, { 2895, 113.0929, -34.0386, 6.30 }, { 2896, 113.7863, +30.9611, 5.33 },
+ { 2897, 113.3421, -13.6617, 6.21 }, { 2898, 113.9833, +43.0311, 6.30 }, { 2899, 113.3313, -18.5875, 5.66 }, { 2900, 113.2904, -23.2892, 5.85 },
+ { 2901, 113.5658,  +3.3714, 5.81 }, { 2902, 113.4496, -13.4761, 4.97 }, { 2903, 114.1317, +46.1803, 5.65 }, { 2904, 113.6917,  +2.7250, 6.55 },
+ { 2905, 113.9804, +26.8958, 4.06 }, { 2906, 113.5133, -21.7039, 4.45 }, { 2907, 113.3063, -39.9411, 6.26 }, { 2908, 113.3054, -42.9136, 6.52 },
+ { 2909, 113.5775, -22.5264, 5.83 }, { 2910, 113.5796, -22.5253, 5.87 }, { 2911, 113.4625, -35.6617, 5.54 }, { 2912, 113.6200, -25.8833, 6.65 },
+ { 2913, 113.5533, -32.5367, 6.11 }, { 2914, 114.4746, +48.7736, 5.92 }, { 2915, 114.3242, +40.0253, 6.38 }, { 2916, 113.6454, -26.9881, 5.77 },
+ { 2917, 113.4938, -38.0942, 6.76 }, { 2918, 114.1446,  +5.8617, 5.91 }, { 2919, 111.4083, -78.9058, 5.53 }, { 2920, 114.0692,  -7.6886, 6.27 },
+ { 2921, 114.0163, -13.5072, 5.70 }, { 2922, 113.8450, -27.6306, 4.64 }, { 2923, 114.0325, -21.8394, 6.34 }, { 2924, 114.6367, +35.0486, 5.56 },
+ { 2925, 113.6646, -50.5253, 6.28 }, { 2926, 114.5604, +24.3603, 6.27 }, { 2927, 114.3196,  -3.8889, 5.13 }, { 2928, 114.1708, -18.2978, 5.74 },
+ { 2929, 115.2063, +57.0828, 6.06 }, { 2930, 114.7913, +34.5842, 4.90 }, { 2931, 114.7996, +24.2225, 6.17 }, { 2932, 114.4121, -13.5589, 6.53 },
+ { 2933, 114.3200, -22.2250, 6.37 }, { 2934, 113.9154, -51.4661, 4.94 }, { 2935, 115.0608, +38.3444, 5.73 }, { 2936, 114.9754, +32.0097, 6.17 },
+ { 2937, 114.3421, -33.0314, 4.53 }, { 2938, 114.8692, +17.6747, 5.05 }, { 2939, 115.3017, +48.1317, 5.56 }, { 2940, 114.1829, -47.1697, 5.72 },
+ { 2941, 114.0071, -54.1125, 6.39 }, { 2942, 114.4367, -34.7228, 6.60 }, { 2943, 114.8254,  +5.2250, 0.38 }, { 2944, 114.5750, -24.6353, 4.70 },
+ { 2945, 114.4383, -37.9894, 6.38 }, { 2946, 115.7517, +58.7103, 4.99 }, { 2947, 114.7796, -17.3208, 6.72 }, { 2948, 114.7054, -25.1983, 4.50 },
+ { 2949, 114.7075, -25.1964, 4.62 }, { 2950, 115.0292,  +5.2308, 6.02 }, { 2951, 115.2438, +23.0186, 5.89 }, { 2952, 114.6008, -38.0086, 6.59 },
+ { 2953, 115.1971, +13.7708, 6.24 }, { 2954, 114.6829, -35.5031, 5.80 }, { 2955, 114.6358, -37.2189, 6.19 }, { 2956, 114.8621, -25.1369, 6.50 },
+ { 2957, 114.5758, -47.3989, 5.68 }, { 2958, 115.1479,  -7.8142, 6.01 }, { 2959, 115.0967, -14.7364, 4.94 }, { 2960, 115.0567, -18.3392, 5.93 },
+ { 2961, 114.8642, -37.6917, 4.84 }, { 2962, 115.6813, +34.0003, 6.02 }, { 2963, 114.9325, -37.8606, 5.73 }, { 2964, 114.9492, -37.7392, 5.76 },
+ { 2965, 115.4658, +13.4806, 5.77 }, { 2966, 115.3967,  +3.6247, 5.94 }, { 2967, 115.5133, +14.2083, 5.56 }, { 2968, 114.9917, -36.4206, 6.00 },
+ { 2969, 116.0175, +50.4339, 5.27 }, { 2970, 115.3117,  -8.4489, 3.93 }, { 2971, 114.7517, -52.7267, 6.06 }, { 2972, 115.1808, -26.0542, 6.76 },
+ { 2973, 115.8279, +28.8836, 4.28 }, { 2974, 115.2196, -30.3392, 6.56 }, { 2975, 116.6671, +65.4558, 5.92 }, { 2976, 115.3483, -21.6628, 6.18 },
+ { 2977, 116.6142, +62.8306, 6.49 }, { 2978, 115.8425, +22.3994, 6.21 }, { 2979, 113.8404, -73.7244, 7.16 }, { 2980, 113.8408, -73.7244, 7.26 },
+ { 2981, 115.3158, -37.4664, 5.42 }, { 2982, 115.7725,  +0.1894, 6.19 }, { 2983, 116.0288, +25.7842, 5.31 }, { 2984, 115.3408, -43.3678, 6.41 },
+ { 2985, 116.1117, +24.3981, 3.57 }, { 2986, 115.4917, -37.4711, 6.54 }, { 2987, 116.0583, +12.8594, 6.43 }, { 2988, 115.7004, -25.6489, 5.64 },
+ { 2989, 116.0308,  +2.4050, 6.47 }, { 2990, 116.3288, +28.0261, 1.14 }, { 2991, 116.2887, +20.3164, 6.33 }, { 2992, 115.9129, -24.4961, 6.55 },
+ { 2993, 115.8850, -27.5889, 4.59 }, { 2994, 115.8000, -35.9497, 5.60 }, { 2995, 115.7792, -37.1358, 6.89 }, { 2996, 115.9521, -27.0453, 3.96 },
+ { 2997, 119.0721, +80.2656, 6.56 }, { 2998, 115.7383, -44.8267, 5.06 }, { 2999, 116.6637, +37.5175, 5.18 }, { 3000, 114.0175, -76.3658, 6.18 },
+ { 3001, 115.9287, -37.7981, 6.40 }, { 3002, 115.9246, -39.0661, 5.17 }, { 3003, 116.5308, +18.5100, 4.88 }, { 3004, 116.1417, -23.3261, 5.62 },
+ { 3005, 115.7788, -48.0072, 6.57 }, { 3006, 115.5425, -57.3692, 6.43 }, { 3007, 116.0400, -35.9372, 5.80 }, { 3008, 116.5675, +10.7683, 5.30 },
+ { 3009, 116.3696, -13.3139, 6.89 }, { 3010, 116.3713, -13.3092, 6.07 }, { 3011, 116.1425, -36.0569, 5.88 }, { 3012, 115.7221, -57.7700, 6.21 },
+ { 3013, 116.8763, +33.4156, 5.14 }, { 3014, 116.5092,  -5.2275, 5.49 }, { 3015, 116.4871, -13.4361, 5.04 }, { 3016, 116.2692, -36.1122, 6.54 },
+ { 3017, 116.3138, -36.0314, 3.61 }, { 3018, 116.3958, -33.8269, 5.37 }, { 3019, 116.6871, -11.3247, 6.39 }, { 3020, 116.3254, -42.2478, 6.03 },
+ { 3021, 117.1400, +23.1411, 6.18 }, { 3022, 116.5433, -36.0661, 5.88 }, { 3023, 116.8021, -21.4803, 5.90 }, { 3024, 115.4550, -71.3939, 3.95 },
+ { 3025, 116.6392, -39.9403, 6.57 }, { 3026, 116.9104, -14.0092, 6.34 }, { 3027, 116.9383, -15.9856, 6.43 }, { 3028, 117.7738, +54.1292, 6.02 },
+ { 3029, 116.9863, -11.8069, 5.48 }, { 3030, 117.2583, +13.3708, 6.04 }, { 3031, 116.3983, -55.2775, 6.12 }, { 3032, 116.7742, -38.6686, 6.31 },
+ { 3033, 117.2454,  +4.3328, 6.53 }, { 3034, 117.0217, -24.0628, 4.50 }, { 3035, 116.8542, -37.4889, 5.08 }, { 3036, 116.1829, -65.9281, 6.38 },
+ { 3037, 116.8812, -45.3914, 5.23 }, { 3038, 116.0542, -68.1786, 6.18 }, { 3039, 118.1525, +55.2094, 6.38 }, { 3040, 117.7596, +33.2336, 6.03 },
+ { 3041, 117.0354, -39.3478, 6.14 }, { 3042, 117.3692, -12.6467, 6.23 }, { 3043, 117.2571, -23.0878, 5.33 }, { 3044, 117.4217, -16.7717, 5.18 },
+ { 3045, 117.3238, -23.1403, 3.34 }, { 3046, 117.0846, -46.9222, 4.71 }, { 3047, 117.5442,  -8.8167, 5.61 }, { 3048, 117.4383, -19.7931, 6.56 },
+ { 3049, 117.3113, -34.7567, 5.93 }, { 3050, 117.6975,  +3.2772, 6.18 }, { 3051, 117.5238, -18.4764, 6.12 }, { 3052, 117.3975, -32.7111, 5.60 },
+ { 3053, 117.9863, +19.3253, 5.99 }, { 3054, 117.7300, -10.8714, 6.16 }, { 3055, 117.3096, -45.6267, 4.11 }, { 3056, 117.0800, -55.5289, 6.33 },
+ { 3057, 117.3675, -43.2481, 6.32 }, { 3058, 117.3037, -45.1422, 5.84 }, { 3059, 117.9250,  +1.7669, 5.14 }, { 3060, 117.7500, -23.4717, 6.45 },
+ { 3061, 118.0300,  +3.2772, 6.31 }, { 3062, 117.2779, -55.5894, 5.59 }, { 3063, 117.9204, -11.1806, 6.36 }, { 3064, 117.9429, -12.1019, 5.17 },
+ { 3065, 118.6221, +47.3861, 6.25 }, { 3066, 118.6779, +47.5647, 5.45 }, { 3067, 118.3742, +26.7658, 4.97 }, { 3068, 117.9287, -20.8261, 5.63 },
+ { 3069, 117.6767, -43.4203, 6.45 }, { 3070, 117.3037, -59.7164, 5.78 }, { 3071, 117.5996, -49.4903, 5.91 }, { 3072, 118.1996,  -4.5719, 5.76 },
+ { 3073, 118.0788, -13.1536, 5.69 }, { 3074, 117.8354, -42.9044, 6.32 }, { 3075, 120.0488, +73.9181, 5.41 }, { 3076, 117.4783, -59.9489, 6.72 },
+ { 3077, 119.1117, +56.5044, 6.72 }, { 3078, 117.9179, -41.1117, 6.04 }, { 3079, 118.0654, -33.2947, 5.01 }, { 3080, 118.0542, -39.4242, 3.73 },
+ { 3081, 117.4208, -65.8042, 5.79 }, { 3082, 121.1963, +79.4797, 5.42 }, { 3083, 118.9200, +35.4128, 6.23 }, { 3084, 118.1613, -37.1369, 4.49 },
+ { 3085, 118.2646, -35.6361, 5.43 }, { 3086, 118.9163, +19.8839, 5.35 }, { 3087, 118.8808,  +8.8628, 5.86 }, { 3088, 118.1238, -53.6328, 5.70 },
+ { 3089, 118.2654, -48.3869, 4.63 }, { 3090, 118.3258, -47.8969, 4.24 }, { 3091, 118.5458, -34.1225, 5.49 }, { 3092, 118.6663, -33.1531, 6.15 },
+ { 3093, 119.0996,  +4.4858, 6.17 }, { 3094, 119.5692, +43.9775, 6.34 }, { 3095, 119.2475, +15.7903, 5.78 }, { 3096, 118.8071, -29.0825, 6.44 },
+ { 3097, 119.3163,  +8.6414, 6.05 }, { 3098, 119.3175,  +1.1269, 6.35 }, { 3099, 119.0950, -29.7147, 6.33 }, { 3100, 118.7521, -51.4169, 6.38 },
+ { 3101, 118.9437, -42.1550, 6.02 }, { 3102, 119.2146, -21.1200, 4.20 }, { 3103, 119.5242,  +7.2136, 6.41 }, { 3104, 119.6312, +16.5186, 5.99 },
+ { 3105, 118.7217, -56.6969, 5.63 }, { 3106, 120.3363, +59.0475, 5.77 }, { 3107, 119.1012, -39.2636, 6.78 }, { 3108, 124.2242, +84.0578, 6.49 },
+ { 3109, 120.4267, +60.3244, 6.01 }, { 3110, 119.5858,  +2.2247, 5.29 }, { 3111, 119.2412, -41.5939, 6.09 }, { 3112, 120.6283, +63.0903, 6.40 },
+ { 3113, 119.4171, -29.6653, 4.79 }, { 3114, 119.2412, -42.4997, 5.35 }, { 3115, 119.8962, +13.2422, 6.02 }, { 3116, 119.3267, -43.8903, 5.09 },
+ { 3117, 119.1946, -51.0178, 3.47 }, { 3118, 119.3333, -46.1097, 6.22 }, { 3119, 120.6492, +57.2736, 6.49 }, { 3120, 119.0775, -59.4736, 5.74 },
+ { 3121, 119.4658, -44.4222, 5.17 }, { 3122, 119.9338,  -2.3203, 4.93 }, { 3123, 119.7738, -22.6894, 5.11 }, { 3124, 120.2329, +25.3928, 5.83 },
+ { 3125, 120.2000, +19.8161, 6.25 }, { 3126, 119.2113, -58.8736, 6.25 }, { 3127, 120.2529, +23.5831, 6.34 }, { 3128, 120.1971, +17.3086, 5.55 },
+ { 3129, 119.5600, -48.7550, 4.41 }, { 3130, 120.4796, +35.4131, 6.34 }, { 3131, 119.9667, -17.6008, 4.61 }, { 3132, 120.4325, +25.0897, 6.31 },
+ { 3133, 119.5892, -50.5514, 6.44 }, { 3134, 120.3763, +16.4553, 5.99 }, { 3135, 120.1838,  -1.1183, 6.51 }, { 3136, 120.3075,  +4.8797, 5.65 },
+ { 3137, 119.7575, -44.7839, 5.99 }, { 3138, 119.4454, -59.6967, 5.60 }, { 3139, 119.3021, -62.7031, 6.14 }, { 3140, 119.8683, -38.7028, 5.24 },
+ { 3141, 120.3054,  -0.6075, 4.68 }, { 3142, 119.8013, -48.0233, 6.32 }, { 3143, 119.8058, -48.0264, 6.34 }, { 3144, 120.4613,  +8.9139, 6.22 },
+ { 3145, 120.5663,  +2.3344, 4.39 }, { 3146, 120.0817, -44.5431, 6.61 }, { 3147, 119.7104, -59.1756, 5.81 }, { 3148, 120.0621, -47.0186, 6.02 },
+ { 3149, 120.8796, +27.7942, 4.94 }, { 3150, 120.6083,  -5.6628, 6.33 }, { 3151, 120.1204, -47.1286, 6.12 }, { 3152, 119.9175, -59.7925, 6.33 },
+ { 3153, 119.9067, -59.4131, 5.17 }, { 3154, 120.4058, -36.7164, 5.95 }, { 3155, 120.5258, -36.9494, 6.34 }, { 3156, 120.2079, -53.8486, 5.87 },
+ { 3157, 120.3454, -53.4850, 6.10 }, { 3158, 121.1883, +18.8422, 6.15 }, { 3159, 120.0833, -62.4325, 4.82 }, { 3160, 120.7671, -31.5361, 5.82 },
+ { 3161, 120.3812, -54.5450, 6.28 }, { 3162, 120.6867, -40.6900, 5.52 }, { 3163, 121.2688, +13.1181, 5.12 }, { 3164, 121.4042, +27.5297, 6.21 },
+ { 3165, 120.8962, -39.9967, 2.25 }, { 3166, 120.8729, -41.0514, 6.29 }, { 3167, 121.7913, +43.2603, 6.26 }, { 3168, 121.1729, -18.2719, 6.13 },
+ { 3169, 121.5767, +22.6356, 5.99 }, { 3170, 121.0675, -31.3250, 5.31 }, { 3171, 119.8171, -72.7553, 6.34 }, { 3172, 121.4567,  +0.5736, 6.41 },
+ { 3173, 122.1142, +51.5067, 4.84 }, { 3174, 121.6146,  -8.7550, 6.23 }, { 3175, 122.5158, +58.2481, 5.93 }, { 3176, 121.9408, +21.5817, 5.30 },
+ { 3177, 121.4371, -32.4308, 6.14 }, { 3178, 121.1767, -49.4094, 5.95 }, { 3179, 121.3350, -45.0211, 6.19 }, { 3180, 121.2667, -52.8919, 5.53 },
+ { 3181, 122.3463, +42.4306, 6.27 }, { 3182, 123.2033, +68.4742, 5.32 }, { 3183, 121.8250, -19.4453, 5.38 }, { 3184, 122.1767, +13.6408, 6.27 },
+ { 3185, 121.8858, -23.6958, 2.81 }, { 3186, 121.1787, -61.1639, 6.30 }, { 3187, 121.6683, -44.7336, 5.05 }, { 3188, 122.1483,  -1.0161, 4.34 },
+ { 3189, 122.2371, -10.6603, 6.32 }, { 3190, 122.1813, -19.6369, 6.36 }, { 3191, 122.6133, +25.5072, 5.73 }, { 3192, 122.2567, -18.7550, 4.40 },
+ { 3193, 122.8400, +38.7314, 6.58 }, { 3194, 122.3688, -15.7511, 5.68 }, { 3195, 122.1567, -36.3186, 6.37 }, { 3196, 122.2779, -29.6775, 6.65 },
+ { 3197, 126.1371, +82.4308, 6.32 }, { 3198, 122.7450, +14.6294, 6.23 }, { 3199, 122.2925, -34.5450, 6.20 }, { 3200, 123.4592, +56.4522, 5.85 },
+ { 3201, 122.8192,  +9.8211, 6.07 }, { 3202, 122.6658, -12.2008, 5.54 }, { 3203, 122.2900, -47.3156, 5.70 }, { 3204, 122.3996, -43.8772, 5.21 },
+ { 3205, 122.4488, -41.3594, 6.26 }, { 3206, 122.3721, -46.6542, 4.27 }, { 3207, 122.3833, -46.6633, 1.78 }, { 3208, 123.0529, +17.6478, 5.63 },
+ { 3209, 123.0529, +17.6478, 6.02 }, { 3210, 123.0554, +17.6478, 6.20 }, { 3211, 122.8179, -11.0731, 4.72 }, { 3212, 122.8875,  -6.2275, 5.36 },
+ { 3213, 122.4300, -46.0625, 5.23 }, { 3214, 123.0921, +14.0039, 6.54 }, { 3215, 123.2871, +29.6567, 5.64 }, { 3216, 124.8842, +75.7569, 5.54 },
+ { 3217, 122.1021, -62.1989, 6.28 }, { 3218, 122.3900, -55.9144, 5.66 }, { 3219, 122.7567, -36.7078, 6.44 }, { 3220, 122.2529, -60.6975, 4.76 },
+ { 3221, 123.9604, +60.3806, 6.45 }, { 3222, 123.2492, +16.5142, 6.01 }, { 3223, 121.9825, -67.3828, 4.35 }, { 3224, 123.4238, +23.1378, 6.56 },
+ { 3225, 122.8396, -38.3814, 4.45 }, { 3226, 122.8579, -41.0128, 4.75 }, { 3227, 122.7963, -47.5381, 5.82 }, { 3228, 123.5463, +17.6758, 6.47 },
+ { 3229, 123.3333, -14.2117, 4.99 }, { 3230, 123.1917, -28.0892, 6.52 }, { 3231, 123.5875, +13.0483, 6.38 }, { 3232, 123.0000, -45.3558, 5.76 },
+ { 3233, 123.2146, -36.0756, 6.43 }, { 3234, 123.1288, -45.7358, 6.03 }, { 3235, 124.4600, +59.5711, 5.64 }, { 3236, 125.1679, +72.4072, 5.98 },
+ { 3237, 123.3733, -34.1003, 4.78 }, { 3238, 123.4213, -32.4308, 6.37 }, { 3239, 123.5458, -31.8592, 6.06 }, { 3240, 123.4933, -35.6775, 5.08 },
+ { 3241, 123.4950, -35.6589, 6.11 }, { 3242, 123.5550, -34.5094, 5.78 }, { 3243, 123.5121, -39.6519, 4.44 }, { 3244, 123.4008, -45.0081, 5.13 },
+ { 3245, 124.8221, +62.5072, 5.71 }, { 3246, 124.5658, +54.1436, 6.27 }, { 3247, 123.3921, -49.8039, 5.51 }, { 3248, 124.1413, +11.7264, 7.13 },
+ { 3249, 124.1288,  +9.1856, 3.52 }, { 3250, 123.5996, -44.1656, 5.83 }, { 3251, 123.9688, -29.0742, 6.21 }, { 3252, 124.3821,  +8.8661, 6.29 },
+ { 3253, 123.9954, -34.0972, 6.16 }, { 3254, 125.1088, +57.7433, 5.89 }, { 3255, 124.2258, -20.6797, 6.60 }, { 3256, 123.8471, -49.5506, 6.44 },
+ { 3257, 124.3463, -15.7150, 6.16 }, { 3258, 125.1213, +53.5744, 6.49 }, { 3259, 124.5996, -11.3681, 5.98 }, { 3260, 123.8163, -61.0842, 5.16 },
+ { 3261, 124.4929, -29.9967, 6.45 }, { 3262, 125.0163, +27.2178, 5.14 }, { 3263, 125.6838, +60.6311, 6.41 }, { 3264, 125.0875, +20.7478, 5.83 },
+ { 3265, 124.8129,  -9.8342, 6.32 }, { 3266, 124.5725, -34.5483, 5.58 }, { 3267, 124.5525, -36.6258, 6.70 }, { 3268, 125.1338, +24.0222, 5.98 },
+ { 3269, 124.9579,  +3.9478, 6.05 }, { 3270, 124.6388, -35.3406, 4.45 }, { 3271, 125.0546,  +0.9094, 6.18 }, { 3272, 125.0713,  -4.6708, 6.13 },
+ { 3273, 124.8725, -33.4097, 6.43 }, { 3274, 124.4825, -58.8331, 6.42 }, { 3275, 125.7087, +43.1881, 4.25 }, { 3276, 125.1142, -21.0753, 6.13 },
+ { 3277, 125.9521, +53.2197, 5.51 }, { 3278, 125.3342,  -0.3978, 6.50 }, { 3279, 125.3383, -19.9208, 5.58 }, { 3280, 124.5788, -64.3867, 5.07 },
+ { 3281, 125.4775, -16.4136, 5.75 }, { 3282, 125.3458, -32.9456, 4.83 }, { 3283, 125.3375, -35.5156, 5.20 }, { 3284, 125.8408, +18.3322, 5.95 },
+ { 3285, 125.6258,  -5.8208, 6.15 }, { 3286, 125.3508, -38.3792, 6.16 }, { 3287, 126.1783, +42.0050, 6.02 }, { 3288, 125.7250,  -6.4567, 5.96 },
+ { 3289, 125.6950, -12.9453, 6.11 }, { 3290, 125.9800, +10.6319, 6.08 }, { 3291, 125.7079, -25.6519, 5.90 }, { 3292, 126.2704, +35.0114, 6.06 },
+ { 3293, 125.3000, -56.0269, 5.97 }, { 3294, 125.6317, -47.5097, 4.82 }, { 3295, 126.1517,  -3.2831, 6.01 }, { 3296, 125.8217, -37.7142, 6.32 },
+ { 3297, 126.1458,  -2.2489, 5.61 }, { 3298, 125.2821, -63.8939, 6.12 }, { 3299, 126.4579, +17.0461, 6.14 }, { 3300, 125.7300, -51.8761, 5.85 },
+ { 3301, 124.9542, -70.4850, 5.37 }, { 3302, 125.0029, -70.4947, 5.65 }, { 3303, 127.4425, +67.2975, 5.88 }, { 3304, 126.6154, +27.8936, 5.57 },
+ { 3305, 126.3979,  +2.1022, 5.73 }, { 3306, 126.4783,  +7.5644, 5.13 }, { 3307, 125.6283, -58.4903, 1.86 }, { 3308, 126.2296, -22.8464, 5.68 },
+ { 3309, 126.9033, +45.6531, 6.32 }, { 3310, 126.6950, +26.9344, 6.32 }, { 3311, 126.6958, +26.9353, 6.30 }, { 3312, 126.6658, +24.5342, 7.02 },
+ { 3313, 126.6671, +24.5353, 7.81 }, { 3314, 126.4150,  -2.0936, 3.90 }, { 3315, 126.2654, -23.9539, 5.28 }, { 3316, 126.3296, -20.9542, 6.01 },
+ { 3317, 126.4142, -16.5606, 6.44 }, { 3318, 124.6317, -75.0803, 4.07 }, { 3319, 126.6829, +12.6544, 5.50 }, { 3320, 126.4817, -13.0703, 5.98 },
+ { 3321, 126.6133,  -2.0125, 5.59 }, { 3322, 126.2383, -41.2306, 5.98 }, { 3323, 127.5663, +60.7181, 3.36 }, { 3324, 126.6746, -11.4656, 5.54 },
+ { 3325, 126.8217,  -5.5903, 6.59 }, { 3326, 126.4663, -41.8467, 5.47 }, { 3327, 126.5733, -38.9406, 6.53 }, { 3328, 126.5758, -38.9397, 7.25 },
+ { 3329, 127.1533, +24.1447, 6.10 }, { 3330, 126.3792, -50.2719, 5.17 }, { 3331, 126.7117, -28.7847, 6.73 }, { 3332, 128.2225, +69.3200, 6.31 },
+ { 3333, 127.1554, +14.2108, 5.95 }, { 3334, 125.5183, -72.6000, 5.29 }, { 3335, 126.8888, -19.1561, 6.56 }, { 3336, 126.8183, -30.3269, 6.33 },
+ { 3337, 127.1217,  -1.4828, 6.39 }, { 3338, 127.0821,  -7.1839, 6.43 }, { 3339, 126.9729, -25.8675, 6.62 }, { 3340, 125.1604, -76.5156, 4.35 },
+ { 3341, 126.6050, -51.1925, 6.05 }, { 3342, 127.2121,  -8.2517, 6.00 }, { 3343, 126.9971, -34.8861, 5.75 }, { 3344, 127.1496, -22.9283, 6.51 },
+ { 3345, 127.2221, -19.0497, 6.67 }, { 3346, 126.4650, -63.3992, 5.97 }, { 3347, 126.4342, -65.8631, 3.77 }, { 3348, 127.8329, +37.2658, 6.18 },
+ { 3349, 126.8642, -54.9883, 6.53 }, { 3350, 126.9021, -52.9114, 5.09 }, { 3351, 128.1396, +53.1147, 6.24 }, { 3352, 129.2029, +74.7236, 6.31 },
+ { 3353, 127.3650, -26.6675, 6.70 }, { 3354, 128.6508, +65.1450, 5.47 }, { 3355, 127.8771, +24.0811, 5.75 }, { 3356, 127.2817, -43.8394, 5.79 },
+ { 3357, 127.8988, +18.0944, 5.35 }, { 3358, 127.2696, -46.0708, 5.33 }, { 3359, 127.3650, -43.2750, 4.99 }, { 3360, 128.2292, +38.0164, 5.90 },
+ { 3361, 127.9775,  +9.8144, 6.83 }, { 3362, 127.6192, -31.8406, 5.65 }, { 3363, 127.4400, -45.6681, 5.99 }, { 3364, 127.6233, -35.2789, 6.69 },
+ { 3365, 128.3408, +36.4364, 6.24 }, { 3366, 128.1771, +20.4411, 5.33 }, { 3367, 127.8788, -18.4225, 5.42 }, { 3368, 127.4013, -54.8089, 6.36 },
+ { 3369, 128.2504, +24.0847, 6.36 }, { 3370, 126.8204, -69.9067, 5.53 }, { 3371, 127.6633, -43.2628, 6.30 }, { 3372, 128.1662, +10.0661, 6.46 },
+ { 3373, 127.8525, -38.9358, 6.31 }, { 3374, 128.1387, -14.9706, 6.38 }, { 3375, 127.7950, -46.1333, 6.39 }, { 3376, 128.4379, +13.2572, 6.28 },
+ { 3377, 128.6825, +36.4194, 5.78 }, { 3378, 128.4313,  +4.7567, 5.87 }, { 3379, 129.9275, +73.6297, 6.15 }, { 3380, 128.5554,  +8.4519, 6.03 },
+ { 3381, 128.2700, -23.3936, 6.19 }, { 3382, 127.8733, -53.6058, 6.34 }, { 3383, 128.5067,  -1.8483, 5.81 }, { 3384, 128.2146, -30.4992, 6.38 },
+ { 3385, 128.2442, -33.3661, 6.36 }, { 3386, 128.0200, -52.7878, 5.69 }, { 3387, 128.8308, +19.5900, 6.58 }, { 3388, 128.3329, -37.6289, 6.49 },
+ { 3389, 128.4096, -37.1511, 5.96 }, { 3390, 128.3767, -45.0289, 6.24 }, { 3391, 129.7988, +65.0208, 5.64 }, { 3392, 128.8537,  +2.7436, 6.33 },
+ { 3393, 126.0825, -79.0858, 5.69 }, { 3394, 129.0321, +15.3136, 6.32 }, { 3395, 128.9625,  +6.6200, 5.99 }, { 3396, 128.9638,  +6.6225, 7.25 },
+ { 3397, 128.6321, -31.4014, 6.43 }, { 3398, 128.8675,  -6.0178, 5.72 }, { 3399, 128.6221, -36.3886, 6.30 }, { 3400, 129.5925, +53.4014, 5.66 },
+ { 3401, 129.7925, +59.9394, 6.48 }, { 3402, 128.8700, -25.1564, 5.96 }, { 3403, 130.0533, +64.3278, 4.60 }, { 3404, 128.8025, -38.0300, 6.47 },
+ { 3405, 129.7500, +52.9250, 6.42 }, { 3406, 129.2742,  +9.6556, 5.88 }, { 3407, 128.6817, -48.0558, 5.01 }, { 3408, 129.8233, +52.7117, 5.91 },
+ { 3409, 129.5792, +32.8019, 5.94 }, { 3410, 129.4142,  +5.7036, 4.16 }, { 3411, 129.3629,  -3.0664, 6.19 }, { 3412, 129.5217,  +9.5747, 6.53 },
+ { 3413, 128.9671, -49.0300, 5.80 }, { 3414, 128.8317, -57.9908, 4.86 }, { 3415, 128.8142, -57.7750, 5.26 }, { 3416, 129.5846,  -5.3375, 6.51 },
+ { 3417, 128.1758, -72.6433, 6.12 }, { 3418, 129.6892,  +3.3414, 4.44 }, { 3419, 129.3738, -32.2542, 6.48 }, { 3420, 129.4675, -25.7450, 5.27 },
+ { 3421, 129.3329, -39.8525, 6.55 }, { 3422, 130.2546, +45.8339, 5.37 }, { 3423, 130.0762, +31.9419, 6.10 }, { 3424, 129.8525,  +8.0172, 6.45 },
+ { 3425, 129.6679, -18.2631, 6.33 }, { 3426, 129.4113, -41.0108, 4.14 }, { 3427, 130.0267, +20.0078, 6.39 }, { 3428, 130.0921, +19.6700, 6.44 },
+ { 3429, 130.1125, +19.5450, 6.30 }, { 3430, 129.7833, -21.3381, 5.05 }, { 3431, 130.0062, -11.5247, 4.98 }, { 3432, 129.3283, -61.1464, 5.47 },
+ { 3433, 129.9271, -28.4389, 4.89 }, { 3434, 129.8421, -35.3931, 6.13 }, { 3435, 129.6871, -52.9094, 6.47 }, { 3436, 130.7508, +46.9011, 6.22 },
+ { 3437, 130.2567,  -8.9481, 6.63 }, { 3438, 130.0258, -34.6917, 3.97 }, { 3439, 130.0804, -39.7358, 5.20 }, { 3440, 129.8492, -52.5603, 5.48 },
+ { 3441, 130.4304, -14.0567, 4.88 }, { 3442, 129.9900, -52.9450, 5.19 }, { 3443, 129.8050, -59.6828, 6.36 }, { 3444, 130.1471, -44.8086, 5.71 },
+ { 3445, 130.1567, -45.3511, 3.84 }, { 3446, 130.5408, -10.0339, 6.45 }, { 3447, 130.0733, -51.0781, 3.62 }, { 3448, 130.0725, -52.9847, 5.61 },
+ { 3449, 130.8212, +21.4686, 4.66 }, { 3450, 130.8013, +12.6808, 5.64 }, { 3451, 131.0421, +36.9181, 6.33 }, { 3452, 130.3046, -46.6831, 4.77 },
+ { 3453, 130.2721, -47.0775, 5.90 }, { 3454, 130.8063,  +3.3986, 4.30 }, { 3455, 130.1817, -56.4547, 6.34 }, { 3456, 130.4871, -44.5892, 5.23 },
+ { 3457, 130.1542, -58.2389, 4.33 }, { 3458, 130.9988,  +4.3347, 6.37 }, { 3459, 130.9183,  -6.7664, 4.62 }, { 3460, 129.7717, -69.6131, 5.20 },
+ { 3461, 131.1712, +18.1542, 3.94 }, { 3462, 130.5667, -47.9008, 5.51 }, { 3463, 130.7375, -34.0567, 6.42 }, { 3464, 131.3392, +30.6978, 6.13 },
+ { 3465, 131.1875, +10.0817, 5.66 }, { 3466, 130.5788, -52.9000, 5.52 }, { 3467, 130.6062, -52.8861, 4.86 }, { 3468, 130.8979, -32.8136, 3.68 },
+ { 3469, 131.2554,  +5.6806, 6.13 }, { 3470, 132.2058, +66.7081, 6.20 }, { 3471, 130.5871, -54.2258, 6.29 }, { 3472, 131.3367,  -1.3992, 6.41 },
+ { 3473, 131.2300, -20.8322, 6.11 }, { 3474, 131.6667, +28.7653, 6.57 }, { 3475, 131.6742, +28.7600, 4.02 }, { 3476, 130.9179, -48.1772, 5.16 },
+ { 3477, 131.1000, -41.3508, 4.07 }, { 3478, 131.5104,  -1.9511, 5.70 }, { 3479, 131.2163, -36.8528, 5.76 }, { 3480, 131.5288, -10.9936, 6.25 },
+ { 3481, 131.7333, +12.1100, 5.87 }, { 3482, 131.6942,  +6.4189, 3.38 }, { 3483, 131.4554, -24.6125, 6.10 }, { 3484, 131.5938, -12.4522, 4.32 },
+ { 3485, 131.1758, -53.2917, 1.96 }, { 3486, 131.8125,  -0.1028, 5.29 }, { 3487, 131.5071, -45.9583, 3.91 }, { 3488, 131.5992, -40.8744, 6.21 },
+ { 3489, 131.2721, -57.2750, 6.21 }, { 3490, 131.7050, -33.3772, 6.37 }, { 3491, 130.9762, -67.7883, 6.32 }, { 3492, 132.1083,  +5.8378, 4.36 },
+ { 3493, 132.0204,  -5.4414, 6.09 }, { 3494, 131.6275, -44.0872, 5.46 }, { 3495, 131.1250, -64.1744, 6.05 }, { 3496, 131.8288, -45.8444, 5.75 },
+ { 3497, 131.9187, -40.2628, 6.36 }, { 3498, 131.6771, -55.2303, 4.49 }, { 3499, 132.6342, +33.2853, 6.25 }, { 3500, 132.3404,  -2.5569, 5.31 },
+ { 3501, 132.0367, -41.5361, 6.43 }, { 3502, 130.3313, -77.0367, 5.47 }, { 3503, 132.0008, -51.1494, 6.30 }, { 3504, 132.6879, +18.8322, 6.16 },
+ { 3505, 133.3442, +61.9622, 5.73 }, { 3506, 133.2746, +59.0561, 6.25 }, { 3507, 132.4371, -20.9514, 6.47 }, { 3508, 132.9867, +43.7267, 5.15 },
+ { 3509, 133.0483, +45.3125, 5.99 }, { 3510, 132.7562, +15.3506, 6.38 }, { 3511, 133.0417, +42.0025, 5.99 }, { 3512, 132.4646, -31.2194, 5.21 },
+ { 3513, 132.5092, -28.5369, 5.87 }, { 3514, 132.4133, -39.6794, 5.48 }, { 3515,   0.0000,  +0.0000, 0.00 }, { 3516, 132.5900, -27.3819, 6.17 },
+ { 3517, 132.4683, -38.8583, 6.39 }, { 3518, 132.6329, -26.2900, 4.01 }, { 3519, 133.1442, +32.4742, 5.66 }, { 3520, 132.4487, -44.6919, 4.93 },
+ { 3521, 133.1192, +28.2592, 6.23 }, { 3522, 133.1492, +28.3308, 5.95 }, { 3523, 132.8938,  -6.8228, 5.54 }, { 3524, 130.8017, -78.9303, 6.05 },
+ { 3525, 132.5875, -41.9100, 6.00 }, { 3526, 133.1008,  +5.3400, 6.33 }, { 3527, 132.6396, -45.4708, 5.10 }, { 3528, 133.4821, +35.5383, 6.14 },
+ { 3529, 133.1279, -12.7664, 6.13 }, { 3530, 132.8663, -41.4956, 6.55 }, { 3531, 134.1563, +64.6039, 5.58 }, { 3532, 133.5613, +30.5794, 5.39 },
+ { 3533, 133.1087, -31.4908, 6.50 }, { 3534, 133.1608, -35.4544, 6.42 }, { 3535, 133.2000, -37.2758, 5.82 }, { 3536, 132.9025, -56.3664, 5.59 },
+ { 3537, 132.6450, -65.2069, 5.35 }, { 3538, 133.5746,  -4.5656, 6.00 }, { 3539, 133.1608, -47.6408, 5.91 }, { 3540, 133.9154, +27.9275, 5.22 },
+ { 3541, 133.8454, +17.2314, 6.64 }, { 3542, 133.1700, -51.8708, 6.39 }, { 3543, 131.4800, -78.4956, 5.79 }, { 3544, 132.4596, -71.4492, 6.11 },
+ { 3545, 134.2083, +45.6319, 5.74 }, { 3546, 134.1271, +40.2017, 5.89 }, { 3547, 133.8483,  +5.9456, 3.11 }, { 3548, 133.4613, -39.5525, 6.47 },
+ { 3549, 133.2658, -55.3506, 6.03 }, { 3550, 133.9817, +11.6261, 5.41 }, { 3551, 133.4613, -46.4792, 5.33 }, { 3552, 133.8729,  -6.0297, 6.91 },
+ { 3553, 133.8733,  -6.0289, 6.67 }, { 3554, 133.8017, -17.7586, 5.75 }, { 3555, 134.2358, +32.9103, 5.45 }, { 3556, 133.8812, -26.3181, 4.89 },
+ { 3557, 134.1538,  +4.2367, 6.14 }, { 3558, 134.2842, +17.1439, 6.17 }, { 3559, 133.9829, -22.1817, 6.39 }, { 3560, 133.4529, -59.6458, 5.78 },
+ { 3561, 134.3121, +15.3228, 5.20 }, { 3562, 133.8304, -44.9583, 6.26 }, { 3563, 134.4946, +30.2336, 6.29 }, { 3564, 134.1421, -15.2906, 5.96 },
+ { 3565, 134.3967, +15.5814, 5.67 }, { 3566, 134.6146, +35.8025, 6.51 }, { 3567, 134.4250,  +9.3878, 6.19 }, { 3568, 133.7250, -57.7600, 6.38 },
+ { 3569, 134.8017, +48.0417, 3.14 }, { 3570, 133.7996, -53.0344, 5.71 }, { 3571, 133.7617, -59.3553, 3.84 }, { 3572, 134.6217, +11.8578, 4.25 },
+ { 3573, 134.5342,  +1.5417, 6.59 }, { 3574, 134.0808, -51.2764, 4.69 }, { 3575, 134.8858, +32.4186, 5.20 }, { 3576, 135.6362, +67.6297, 4.76 },
+ { 3577, 134.7950, +18.1347, 6.38 }, { 3578, 134.6829, -15.8672, 5.86 }, { 3579, 135.1600, +41.7828, 3.97 }, { 3580, 135.1283, +37.6044, 6.44 },
+ { 3581, 138.8383, +84.1811, 6.33 }, { 3582, 134.2433, -58.7706, 4.92 }, { 3583, 134.4825, -47.4267, 5.87 }, { 3584, 134.9162, -18.7919, 6.18 },
+ { 3585, 134.8154, -27.1939, 6.25 }, { 3586, 135.4192, +39.7133, 6.36 }, { 3587, 135.3504, +32.2525, 5.82 }, { 3588, 134.7179, -46.7653, 5.18 },
+ { 3589, 135.4538, +27.9028, 6.07 }, { 3590, 135.3808,  +5.6408, 6.07 }, { 3591, 135.0225, -40.7461, 4.45 }, { 3592, 136.0017, +54.2839, 5.75 },
+ { 3593, 135.0925, -42.8267, 6.07 }, { 3594, 135.9063, +47.1567, 3.60 }, { 3595, 135.6846, +24.4528, 5.45 }, { 3596, 135.4917,  +0.4828, 5.67 },
+ { 3597, 135.2975, -25.3361, 6.20 }, { 3598, 134.8504, -58.9164, 5.16 }, { 3599, 135.6867,  +7.2981, 5.85 }, { 3600, 135.3367, -40.1356, 5.55 },
+ { 3601, 136.0412, +27.8983, 6.38 }, { 3602, 135.5267, -38.5975, 6.27 }, { 3603, 136.3504, +48.5303, 5.95 }, { 3604, 135.1904, -59.0361, 5.79 },
+ { 3605, 135.4358, -51.8117, 5.23 }, { 3606, 136.2300, +32.3769, 6.46 }, { 3607, 135.7867, -24.4956, 6.74 }, { 3608, 136.6796, +59.3444, 6.45 },
+ { 3609, 137.0983, +66.8733, 5.14 }, { 3610, 135.2854, -67.3161, 5.88 }, { 3611, 135.7717, -52.4503, 6.40 }, { 3612, 136.6325, +38.4522, 4.56 },
+ { 3613, 136.4933,  +5.0922, 4.97 }, { 3614, 136.0387, -46.9022, 3.75 }, { 3615, 135.6117, -65.6039, 4.00 }, { 3616, 137.5967, +67.1347, 4.80 },
+ { 3617, 136.8621, +22.9811, 6.40 }, { 3618, 136.7496,  +1.4628, 6.17 }, { 3619, 137.2179, +51.6047, 4.48 }, { 3620, 137.0171, +32.5406, 6.50 },
+ { 3621, 137.0004, +29.6542, 5.43 }, { 3622, 136.2000, -56.1475, 6.44 }, { 3623, 136.9367, +10.6681, 5.24 }, { 3624, 137.7296, +63.5136, 4.67 },
+ { 3625, 137.2129, +33.8822, 5.93 }, { 3626, 137.1971, +26.6292, 5.98 }, { 3627, 137.3396, +22.0456, 5.14 }, { 3628, 137.0121, -24.1417, 4.58 },
+ { 3629, 136.6417, -54.1967, 6.11 }, { 3630, 137.1758,  -7.4106, 5.60 }, { 3631, 136.8113, -50.7881, 6.73 }, { 3632, 136.5317, -63.5003, 6.37 },
+ { 3633, 138.5133, +71.6558, 6.55 }, { 3634, 136.9992, -42.5675, 2.21 }, { 3635, 137.4433, +11.5644, 6.48 }, { 3636, 137.2979, -11.6422, 5.77 },
+ { 3637, 137.1813, -25.2322, 6.15 }, { 3638, 137.2679, -17.6714, 5.73 }, { 3639, 137.6613, +30.9631, 5.95 }, { 3640, 137.5871, +21.9964, 6.01 },
+ { 3641, 137.3979,  -7.2122, 5.46 }, { 3642, 136.4096, -69.4611, 4.71 }, { 3643, 136.2867, -71.3972, 4.48 }, { 3644, 137.4850, -29.6347, 5.59 },
+ { 3645, 138.9692, +72.9461, 5.96 }, { 3646, 137.5958, -22.8233, 6.53 }, { 3647, 137.4379, -48.5753, 6.48 }, { 3648, 138.5858, +61.4233, 5.13 },
+ { 3649, 137.9817,  +5.4683, 6.35 }, { 3650, 138.0733, +14.9961, 6.51 }, { 3651, 138.0538,  +3.8672, 6.14 }, { 3652, 138.4508, +43.2178, 5.32 },
+ { 3653, 137.9946, -18.2522, 5.73 }, { 3654, 137.7683, -43.1319, 5.00 }, { 3655, 138.1083,  -6.8903, 6.11 }, { 3656, 137.9208, -38.7411, 6.00 },
+ { 3657, 138.4054, +21.2833, 6.48 }, { 3658, 137.8883, -45.4161, 5.79 }, { 3659, 137.7417, -57.0331, 3.44 }, { 3660, 138.9579, +56.7414, 5.27 },
+ { 3661, 138.1275, -42.3864, 5.57 }, { 3662, 139.0471, +54.0219, 4.83 }, { 3663, 137.8192, -61.6828, 3.97 }, { 3664, 138.8096, +34.6336, 5.97 },
+ { 3665, 138.5913,  +2.3142, 3.88 }, { 3666, 139.9825, +74.0164, 6.50 }, { 3667, 138.3579, -37.3836, 6.31 }, { 3668, 138.3275, -41.7264, 6.29 },
+ { 3669, 138.8075, +14.9414, 5.34 }, { 3670, 138.3938, -46.6614, 5.92 }, { 3671,   0.0000,  +0.0000, 0.00 }, { 3672, 138.5342, -43.8542, 5.85 },
+ { 3673, 138.2317, -58.5856, 5.54 }, { 3674, 138.6021, -42.7725, 5.25 }, { 3675, 138.8537, -14.9753, 6.35 }, { 3676, 139.3800, +46.8172, 5.97 },
+ { 3677, 138.7383, -36.3975, 5.86 }, { 3678, 134.1712, -84.3369, 5.42 }, { 3679, 138.5750, -54.4303, 5.27 }, { 3680, 138.8108, -44.4444, 6.25 },
+ { 3681, 139.1738,  -5.6469, 5.24 }, { 3682, 138.9029, -37.4300, 4.94 }, { 3683, 139.1721,  -7.2553, 5.47 }, { 3684, 138.9379, -36.5867, 4.62 },
+ { 3685, 138.3000, -68.2828, 1.68 }, { 3686, 139.6083, +35.3642, 5.75 }, { 3687, 139.2813, -13.4264, 5.84 }, { 3688, 139.0175, -43.1014, 6.04 },
+ { 3689, 139.4642, +11.5011, 6.41 }, { 3690, 139.7113, +36.8025, 3.82 }, { 3691, 138.8229, -57.6114, 6.02 }, { 3692, 139.0963, -43.7342, 5.12 },
+ { 3693, 138.8958, -56.4219, 6.32 }, { 3694, 139.2383, -38.5986, 5.33 }, { 3695, 138.0513, -75.3369, 6.14 }, { 3696, 139.0508, -56.4586, 4.34 },
+ { 3697, 140.1825, +51.2661, 6.13 }, { 3698, 140.4304, +56.6992, 5.47 }, { 3699, 139.2725, -58.7247, 2.25 }, { 3700, 139.4263, -53.5047, 6.33 },
+ { 3701, 140.2471, +38.1883, 6.12 }, { 3702, 139.8904, -10.6858, 6.62 }, { 3703, 139.5242, -50.9489, 5.26 }, { 3704, 139.8883, -14.1656, 5.78 },
+ { 3705, 140.2637, +34.3925, 3.13 }, { 3706, 139.9433, -10.0250, 4.79 }, { 3707, 140.3633, +32.9019, 6.16 }, { 3708, 139.6758, -50.4394, 5.87 },
+ { 3709, 140.1208,  -8.4442, 4.80 }, { 3710, 139.9496, -33.8967, 6.39 }, { 3711, 140.3142, +15.3711, 6.53 }, { 3712, 139.3217, -67.3106, 5.39 },
+ { 3713, 139.4654, -66.9492, 6.11 }, { 3714, 140.2312, -14.3822, 6.33 }, { 3715, 140.1842, -30.2394, 6.82 }, { 3716, 140.1233, -36.4186, 6.05 },
+ { 3717, 139.8858, -54.8133, 6.28 }, { 3718, 140.3733, -24.0344, 4.72 }, { 3719, 141.9650, +75.0983, 6.29 }, { 3720, 139.3558, -73.1056, 5.29 },
+ { 3721, 139.3642, -73.2653, 5.86 }, { 3722, 141.4342, +63.9408, 6.28 }, { 3723, 140.8825, +25.1831, 6.41 }, { 3724, 140.7121,  -8.1611, 6.53 },
+ { 3725, 141.2321, +51.5739, 6.31 }, { 3726, 140.4621, -41.8050, 5.58 }, { 3727, 141.0938, +36.5869, 6.67 }, { 3728, 140.2367, -61.5953, 4.81 },
+ { 3729, 140.6529, -38.2253, 6.54 }, { 3730, 140.6000, -45.9525, 5.75 }, { 3731, 141.1637, +26.1822, 4.46 }, { 3732, 140.4583, -54.4850, 5.63 },
+ { 3733, 140.8013, -27.1661, 4.69 }, { 3734, 140.5283, -54.9892, 2.50 }, { 3735, 140.9367, -36.2428, 6.48 }, { 3736, 141.3854, +16.5856, 6.29 },
+ { 3737, 141.0679, -38.5742, 6.06 }, { 3738, 141.3500,  -4.8825, 5.59 }, { 3739, 140.9979, -50.2628, 6.08 }, { 3740, 140.8642, -59.6975, 6.30 },
+ { 3741, 141.5929,  -0.5361, 6.01 }, { 3742, 141.0238, -60.3511, 5.99 }, { 3743, 142.1667, +45.6014, 5.41 }, { 3744, 141.8108,  -8.7764, 6.54 },
+ { 3745, 141.6867, -27.2125, 6.10 }, { 3746, 141.6188, -39.4981, 6.20 }, { 3747, 142.4483, +55.7456, 6.45 }, { 3748, 141.8967,  -7.3414, 1.98 },
+ { 3749, 141.8267, -21.6561, 4.69 }, { 3750, 141.9450,  -5.9289, 5.38 }, { 3751, 144.2717, +81.3264, 4.29 }, { 3752, 141.3629, -60.0497, 5.77 },
+ { 3753, 141.5754, -52.6208, 5.11 }, { 3754, 142.1146,  +9.0567, 5.41 }, { 3755, 142.1217,  +8.1883, 5.71 }, { 3756, 141.9100, -34.9922, 6.65 },
+ { 3757, 142.8821, +63.0619, 3.67 }, { 3758, 142.2592,  -0.7431, 6.27 }, { 3759, 142.2871,  -1.2311, 4.60 }, { 3760, 142.3521,  -1.7947, 6.14 },
+ { 3761, 141.6842, -63.0703, 6.05 }, { 3762, 142.3850,  -3.7528, 6.26 }, { 3763, 142.3025, -19.2514, 5.66 }, { 3764, 142.6800, +33.6556, 5.85 },
+ { 3765, 142.3113, -34.0486, 4.51 }, { 3766, 142.3179, -37.5961, 6.19 }, { 3767, 142.4579, -22.6547, 6.24 }, { 3768, 143.7233, +72.2056, 5.72 },
+ { 3769, 142.8850, +35.1031, 5.37 }, { 3770, 142.4771, -25.4103, 5.48 }, { 3771, 143.6204, +69.8303, 4.56 }, { 3772, 142.5942, -14.4228, 5.85 },
+ { 3773, 142.9300, +22.9681, 4.31 }, { 3774, 144.0283, +74.3178, 6.46 }, { 3775, 143.2142, +51.6772, 3.17 }, { 3776, 142.1958, -61.7269, 5.92 },
+ { 3777, 141.7767, -70.3978, 5.47 }, { 3778, 143.2800, +49.4386, 6.76 }, { 3779, 142.9900,  +9.7158, 5.07 }, { 3780, 142.6892, -30.1086, 7.00 },
+ { 3781, 142.6921, -30.1106, 6.18 }, { 3782, 142.9863, +11.2997, 4.97 }, { 3783, 142.1275, -65.2981, 5.91 }, { 3784, 142.5217, -50.4828, 5.45 },
+ { 3785, 142.9121,  -9.4478, 6.14 }, { 3786, 142.6750, -39.5333, 3.60 }, { 3787, 142.9954,  -0.8150, 4.57 }, { 3788, 142.9825,  -9.6294, 6.13 },
+ { 3789, 142.8842, -30.1281, 5.93 }, { 3790, 142.8871, -34.2850, 5.87 }, { 3791, 143.3763, +36.4869, 6.18 }, { 3792, 143.3262, +28.3681, 6.53 },
+ { 3793, 142.5975, -57.6383, 5.88 }, { 3794, 143.1725,  +1.8642, 6.11 }, { 3795, 141.0379, -79.2131, 5.36 }, { 3796, 143.0850, -18.5997, 5.74 },
+ { 3797, 143.5817, +46.9022, 6.52 }, { 3798, 143.0771, -27.3719, 6.46 }, { 3799, 143.7063, +52.0514, 4.50 }, { 3800, 143.5558, +36.3975, 4.55 },
+ { 3801, 143.2587,  -7.4947, 6.12 }, { 3802, 143.2325, -12.4831, 5.94 }, { 3803, 142.8054, -56.9656, 3.13 }, { 3804, 143.4963, +23.4539, 6.25 },
+ { 3805, 143.3338,  -6.8100, 6.24 }, { 3806, 144.4842, +73.0806, 6.42 }, { 3807, 143.0804, -39.3506, 5.35 }, { 3808, 143.3021, -20.8842, 5.01 },
+ { 3809, 143.7658, +39.6214, 4.81 }, { 3810, 143.3592, -21.1361, 5.91 }, { 3811, 143.8433, +39.9633, 6.76 }, { 3812, 143.2825, -38.8711, 6.43 },
+ { 3813, 142.8871, -65.2806, 6.27 }, { 3814, 143.6362,  -4.0850, 5.56 }, { 3815, 143.9150, +35.8103, 5.41 }, { 3816, 143.0608, -61.2111, 6.10 },
+ { 3817, 143.4354, -48.9950, 5.12 }, { 3818, 143.9704, +14.3797, 6.36 }, { 3819, 143.5367, -50.7447, 5.01 }, { 3820, 144.1788, +31.1617, 5.56 },
+ { 3821, 142.9013, -72.9192, 5.47 }, { 3822, 143.8904, -18.4164, 6.31 }, { 3823, 143.7992, -34.1761, 6.49 }, { 3824, 144.8663, +67.2722, 5.94 },
+ { 3825, 143.6113, -58.7706, 4.08 }, { 3826, 144.2608, +16.4378, 5.69 }, { 3827, 144.3029,  +6.8358, 5.00 }, { 3828, 144.1404, -23.2972, 6.53 },
+ { 3829, 144.5904, +40.2397, 5.25 }, { 3830, 144.2508, -24.7033, 5.70 }, { 3831, 144.1054, -47.2486, 6.17 }, { 3832, 144.4646,  -8.5756, 6.40 },
+ { 3833, 144.2912, -31.8214, 5.63 }, { 3834, 144.6138,  +4.6492, 4.68 }, { 3835, 144.3679, -35.9042, 5.98 }, { 3836, 144.2067, -48.6447, 4.35 },
+ { 3837, 144.1929, -51.0558, 6.19 }, { 3838, 145.5617, +69.2375, 5.69 }, { 3839, 145.7383, +72.2525, 5.17 }, { 3840, 144.3013, -52.3314, 5.45 },
+ { 3841, 144.0213, -63.0494, 6.56 }, { 3842, 144.5062, -42.8089, 5.50 }, { 3843, 146.3783, +78.1347, 6.23 }, { 3844, 144.6696, -38.3858, 6.70 },
+ { 3845, 144.9642,  -0.8572, 3.91 }, { 3846, 144.9475,  -9.4297, 6.31 }, { 3847, 146.8250, +79.1367, 6.17 }, { 3848, 145.0838,  -9.2308, 6.37 },
+ { 3849, 145.0767, -13.6678, 5.06 }, { 3850, 145.3967, +31.2781, 5.89 }, { 3851, 145.5013, +39.7578, 5.62 }, { 3852, 145.2875,  +9.8922, 3.52 },
+ { 3853, 145.4104, +25.9128, 6.24 }, { 3854, 145.6796, +48.4311, 6.39 }, { 3855, 145.7792, +54.3636, 6.47 }, { 3856, 144.8375, -60.6719, 4.52 },
+ { 3857, 145.6779, +35.0933, 6.14 }, { 3858, 145.3208, -22.4083, 4.77 }, { 3859, 146.1529, +64.9839, 6.17 }, { 3860, 143.4717, -79.0586, 5.11 },
+ { 3861, 145.8887, +29.9744, 5.64 }, { 3862, 145.5600, -22.0844, 4.94 }, { 3863, 145.1771, -56.0164, 5.32 }, { 3864, 145.2592, -56.7403, 5.80 },
+ { 3865, 146.4808, +63.6533, 6.34 }, { 3866, 145.9329, +14.0217, 5.35 }, { 3867, 145.6725, -34.4983, 6.41 }, { 3868, 145.4492, -54.7858, 6.00 },
+ { 3869, 146.1250, +18.8636, 6.50 }, { 3870, 146.6321, +57.1281, 5.20 }, { 3871, 146.0504, -26.2306, 4.79 }, { 3872, 145.8646, -50.7717, 6.15 },
+ { 3873, 146.4629, +23.7742, 2.98 }, { 3874, 146.0658, -38.4289, 6.82 }, { 3875, 145.9258, -52.1083, 5.56 }, { 3876, 146.5417,  +6.7086, 5.79 },
+ { 3877, 146.5971, +11.8100, 5.63 }, { 3878, 146.3408, -29.7972, 6.45 }, { 3879, 146.5983,  +1.7856, 5.65 }, { 3880, 146.8579, +11.5683, 6.45 },
+ { 3881, 147.1475, +46.0211, 5.09 }, { 3882, 146.8896, +11.4289, 6.02 }, { 3883, 146.4187, -56.8144, 6.46 }, { 3884, 146.3117, -61.4922, 3.69 },
+ { 3885, 147.5988, +65.5933, 6.31 }, { 3886, 146.6267, -43.2450, 5.55 }, { 3887, 146.4808, -57.2058, 6.22 }, { 3888, 147.7475, +59.0386, 3.80 },
+ { 3889, 147.4588, +21.1794, 6.09 }, { 3890, 146.7754, -64.9281, 3.01 }, { 3891, 146.7779, -64.9275, 6.26 }, { 3892, 147.3671, -36.8136, 5.97 },
+ { 3893, 147.6254,  +4.3436, 6.24 }, { 3894, 148.0267, +54.0644, 4.59 }, { 3895, 147.1667, -55.5881, 6.06 }, { 3896, 147.7583, +13.0661, 6.46 },
+ { 3897, 147.4638, -35.7314, 6.37 }, { 3898, 147.4879, -44.2672, 5.08 }, { 3899, 147.8083,  -3.7567, 6.01 }, { 3900, 147.9708, +24.3953, 5.32 },
+ { 3901, 147.8400,  -5.8183, 6.42 }, { 3902, 146.5858, -75.2239, 5.45 }, { 3903, 147.8696, -13.1533, 4.12 }, { 3904, 147.6750, -45.0656, 5.73 },
+ { 3905, 148.1908, +26.0069, 3.88 }, { 3906, 148.0508,  +2.4542, 6.02 }, { 3907, 148.0500,  +0.0756, 6.35 }, { 3908, 147.9983, -15.4653, 6.08 },
+ { 3909, 148.1267,  -7.8950, 5.05 }, { 3910, 147.8325, -45.8061, 5.62 }, { 3911, 148.7642, +61.1161, 6.27 }, { 3912, 147.9200, -45.4522, 4.58 },
+ { 3913, 147.8004, -58.5742, 5.79 }, { 3914, 147.7321, -61.2547, 5.57 }, { 3915, 148.4288,  +5.9583, 5.95 }, { 3916, 148.2417, -26.6678, 6.30 },
+ { 3917, 148.9292, +49.8200, 5.27 }, { 3918, 149.5950, +72.8794, 5.83 }, { 3919, 148.5513, -24.0675, 4.88 }, { 3920, 148.2500, -54.6267, 6.48 },
+ { 3921, 148.6321, -21.5117, 6.24 }, { 3922, 149.3067, +57.4183, 5.93 }, { 3923, 148.7175, -18.9906, 4.94 }, { 3924, 148.4592, -50.8531, 5.93 },
+ { 3925, 148.5733, -44.7161, 5.71 }, { 3926, 149.1083,  +8.9331, 5.85 }, { 3927, 148.7138, -49.7561, 5.72 }, { 3928, 149.4212, +41.0556, 5.14 },
+ { 3929, 149.4871, +45.4144, 6.30 }, { 3930, 149.0225, -39.1753, 6.41 }, { 3931, 149.1937, -25.4497, 6.28 }, { 3932, 149.1479, -32.5814, 5.84 },
+ { 3933, 149.2250, -26.5250, 6.32 }, { 3934, 152.1429, +83.9183, 6.37 }, { 3935, 149.0913, -50.6639, 6.37 }, { 3936, 149.6087, +27.7589, 6.30 },
+ { 3937, 149.5558, +12.4447, 5.26 }, { 3938, 149.5317,  +8.3142, 6.04 }, { 3939, 149.9654, +56.8119, 5.48 }, { 3940, 149.2158, -53.4322, 3.54 },
+ { 3941, 149.2954, -51.3611, 6.12 }, { 3942, 149.9008, +29.6453, 5.73 }, { 3943, 149.4271, -47.5856, 6.05 }, { 3944, 149.0404, -70.6106, 6.35 },
+ { 3945, 149.9296,  +3.3847, 6.70 }, { 3946, 149.7754, -22.0497, 6.21 }, { 3947, 149.7179, -34.1089, 5.23 }, { 3948, 149.3133, -63.5106, 6.58 },
+ { 3949, 149.2488, -68.8981, 6.20 }, { 3950, 150.0533,  +8.0442, 4.70 }, { 3951, 150.2529, +31.9236, 5.36 }, { 3952, 150.7038, +21.9492, 5.66 },
+ { 3953, 150.1433, -55.0533, 6.52 }, { 3954, 151.1513, +53.8917, 5.74 }, { 3955, 150.4187, -52.6356, 6.20 }, { 3956, 150.7054, -29.4225, 6.54 },
+ { 3957, 150.4917, -56.6503, 6.20 }, { 3958, 151.2937, +52.3708, 6.14 }, { 3959, 150.9208,  -8.4261, 6.12 }, { 3960, 150.5000, -59.5792, 5.94 },
+ { 3961, 151.0350,  +3.2011, 6.45 }, { 3962, 150.9225, -24.6833, 6.70 }, { 3963, 151.0121, -17.8983, 5.86 }, { 3964, 150.8354, -45.3639, 6.12 },
+ { 3965, 151.0875, -23.7144, 5.70 }, { 3966, 150.7496, -59.8214, 6.19 }, { 3967, 150.7058, -61.8436, 6.42 }, { 3968, 151.0975, -38.0242, 6.43 },
+ { 3969, 151.4204, +15.7575, 6.37 }, { 3970, 151.2813, -12.9353, 4.60 }, { 3971, 150.8929, -60.1161, 6.14 }, { 3972, 151.3133, -35.6161, 6.27 },
+ { 3973, 151.6975,  +5.6114, 6.21 }, { 3974, 151.8575, +35.2447, 4.48 }, { 3975, 151.8333, +16.7628, 3.52 }, { 3976, 151.5471, -46.6300, 5.08 },
+ { 3977, 151.7896, -16.8583, 5.60 }, { 3978, 151.5296, -51.8119, 6.52 }, { 3979, 152.0663, +31.6042, 6.24 }, { 3980, 151.9762,  +9.9975, 4.37 },
+ { 3981, 151.9846,  +0.3717, 4.49 }, { 3982, 152.0929, +11.9672, 1.35 }, { 3983, 150.1821, -81.7853, 5.52 }, { 3984, 152.0071, -36.6664, 6.36 },
+ { 3985, 152.1904,  -9.1153, 6.53 }, { 3986, 152.1479, -14.3883, 6.27 }, { 3987, 152.7454, +40.6614, 6.32 }, { 3988, 152.4854, -11.9042, 6.24 },
+ { 3989, 152.5313,  -7.5917, 5.91 }, { 3990, 152.2346, -50.1889, 4.86 }, { 3991, 152.5246, -11.1839, 5.31 }, { 3992, 152.3825, -34.1433, 6.13 },
+ { 3993, 152.8033, +37.4019, 5.85 }, { 3994, 152.6471, -11.6458, 3.61 }, { 3995, 152.1775, -64.1847, 5.28 }, { 3996, 152.7325,  -7.5817, 5.65 },
+ { 3997, 151.0317, -80.4342, 6.60 }, { 3998, 152.9092, +13.3550, 6.44 }, { 3999, 152.3413, -60.4508, 5.60 }, { 4000, 152.8242,  -6.6833, 6.25 },
+ { 4001, 152.6579, -40.2850, 5.98 }, { 4002, 152.3771, -67.3167, 5.81 }, { 4003, 153.0121, -27.3936, 6.28 }, { 4004, 153.2012,  +4.6147, 5.77 },
+ { 4005, 153.1575, -18.8464, 6.44 }, { 4006, 153.4575, +27.1358, 6.04 }, { 4007, 152.8967, -57.1719, 6.40 }, { 4008, 153.7821, +59.9856, 6.25 },
+ { 4009, 152.9437, -57.9394, 5.72 }, { 4010, 153.0958, -51.8367, 6.16 }, { 4011, 153.3308, -26.9711, 6.25 }, { 4012, 153.6238, +21.1678, 6.02 },
+ { 4013, 153.3533, -32.9681, 6.38 }, { 4014, 153.7763, +31.4681, 6.46 }, { 4015, 153.4413, -39.6542, 5.90 }, { 4016, 154.5046, +73.0733, 6.40 },
+ { 4017, 153.3450, -50.7667, 5.28 }, { 4018, 153.2554, -58.0819, 6.10 }, { 4019, 153.4858, -39.6894, 6.35 }, { 4020, 153.3667, -50.2439, 5.78 },
+ { 4021, 154.4608, +71.0606, 6.66 }, { 4022, 153.3383, -60.3411, 6.41 }, { 4023, 153.6842, -41.8781, 3.85 }, { 4024, 154.0600, +29.3106, 5.35 },
+ { 4025, 153.3775, -65.6269, 5.16 }, { 4026, 154.5083, +65.1083, 5.82 }, { 4027, 154.1171, +28.6825, 6.49 }, { 4028, 154.0671, +17.7403, 6.55 },
+ { 4029, 153.8371, -35.4819, 6.19 }, { 4030, 154.1346, +23.5031, 5.97 }, { 4031, 154.1725, +23.4172, 3.44 }, { 4032, 154.1746, +25.3714, 5.84 },
+ { 4033, 154.2742, +42.9144, 3.45 }, { 4034, 154.0379, -10.7967, 6.08 }, { 4035, 154.1696, +13.7283, 5.41 }, { 4036, 153.8812, -42.8875, 5.60 },
+ { 4037, 153.4342, -69.9619, 3.32 }, { 4038, 153.8192, -53.0258, 6.16 }, { 4039, 154.3108, +23.1061, 5.82 }, { 4040, 154.1900, -19.3294, 6.57 },
+ { 4041, 154.5429, +27.4153, 6.52 }, { 4042, 154.4075,  -7.9311, 5.24 }, { 4043, 154.0129, -58.0967, 6.22 }, { 4044, 154.7458, +46.7608, 6.43 },
+ { 4045, 154.1675, -50.7950, 6.30 }, { 4046, 154.8617, +48.3969, 6.00 }, { 4047, 155.2642, +68.7475, 5.96 }, { 4048, 154.7529, +24.7117, 6.40 },
+ { 4049, 154.5317, -27.0081, 5.34 }, { 4050, 154.2708, -60.6678, 3.40 }, { 4051, 155.0617, +53.7792, 6.45 }, { 4052, 155.1300, +54.2169, 6.00 },
+ { 4053, 154.6575, -35.1953, 6.30 }, { 4054, 154.9338, +19.4708, 4.79 }, { 4055, 154.8200, -11.4719, 6.00 }, { 4056, 154.6175, -40.3317, 5.96 },
+ { 4057, 154.9929, +19.8417, 2.61 }, { 4058, 154.9942, +19.8406, 3.80 }, { 4059, 154.8842,  -4.8942, 6.37 }, { 4060, 154.9975,  -8.9411, 6.32 },
+ { 4061, 154.6567, -55.8900, 5.81 }, { 4062, 157.4229, +84.2522, 5.50 }, { 4063, 154.9033, -54.9706, 4.57 }, { 4064, 155.2583,  +2.2897, 6.66 },
+ { 4065, 154.7700, -63.3236, 5.67 }, { 4066, 155.0696, -46.3008, 5.65 }, { 4067, 155.5437, +41.2294, 5.76 }, { 4068, 155.2825, -16.0150, 6.51 },
+ { 4069, 155.5821, +41.4994, 3.05 }, { 4070, 155.4596, +14.9756, 6.12 }, { 4071, 155.3696, -22.2892, 6.50 }, { 4072, 156.0329, +65.5664, 4.97 },
+ { 4073, 155.4000, -21.4717, 6.51 }, { 4074, 155.2283, -55.9569, 4.50 }, { 4075, 155.7763, +33.9081, 5.90 }, { 4076, 155.5538, -18.1331, 6.13 },
+ { 4077, 155.7517,  +6.5425, 6.07 }, { 4078, 155.9242, +29.6158, 6.39 }, { 4079, 155.8108,  +5.6942, 6.54 }, { 4080, 155.5817, -40.3500, 4.83 },
+ { 4081, 156.0358, +33.7186, 5.50 }, { 4082, 155.8604,  -3.9258, 5.97 }, { 4083, 155.8046, -29.8378, 6.27 }, { 4084, 157.7692, +82.5586, 5.26 },
+ { 4085, 156.0546,  +2.3681, 6.32 }, { 4086, 155.8721, -37.9900, 5.33 }, { 4087, 155.9183, -40.0467, 6.27 }, { 4088, 156.3133,  +8.7847, 5.61 },
+ { 4089, 155.7421, -65.0983, 4.99 }, { 4090, 156.4787, +33.7961, 4.74 }, { 4091, 155.9621, -56.0461, 6.35 }, { 4092, 156.4346,  -6.9403, 5.57 },
+ { 4093, 156.3217, -41.5319, 6.18 }, { 4094, 156.5225, -15.1636, 3.81 }, { 4095, 156.2475, -57.4236, 5.95 }, { 4096, 156.8667, +41.6008, 6.02 },
+ { 4097, 156.7521, +19.3644, 6.15 }, { 4098, 157.0158, +48.7847, 6.44 }, { 4099, 156.5396, -41.2611, 6.13 }, { 4100, 156.9708, +36.7072, 4.21 },
+ { 4101, 156.9125,  +9.7625, 6.04 }, { 4102, 156.0988, -73.9683, 4.00 }, { 4103, 157.1521, +45.2122, 6.35 }, { 4104, 156.7879, -30.9322, 4.25 },
+ { 4105, 156.1846, -72.0283, 6.19 }, { 4106, 157.4762, +65.6261, 6.32 }, { 4107, 156.7042, -53.1225, 5.58 }, { 4108, 157.6108, +64.2575, 6.12 },
+ { 4109, 157.1833,  -2.2575, 6.05 }, { 4110, 156.8517, -56.3611, 4.66 }, { 4111, 157.0079, -48.5944, 6.10 }, { 4112, 157.6567, +55.9806, 4.84 },
+ { 4113, 157.5267, +38.9253, 5.77 }, { 4114, 156.9696, -57.2606, 3.82 }, { 4115, 156.8554, -64.2953, 6.01 }, { 4116, 157.3696,  -1.2608, 5.21 },
+ { 4117, 157.3708, -28.3364, 5.58 }, { 4118, 157.3975, -29.3928, 5.56 }, { 4119, 157.5729,  +0.6369, 5.09 }, { 4120, 157.2192, -63.8278, 5.29 },
+ { 4121, 159.0071, +80.4944, 6.52 }, { 4122, 157.7446,  -6.3625, 6.20 }, { 4123, 157.7492, -12.4117, 5.58 }, { 4124, 157.9642, +32.3794, 5.90 },
+ { 4125, 157.7142, -25.5161, 6.51 }, { 4126, 158.7729, +75.7131, 4.84 }, { 4127, 158.0492, +14.1372, 5.46 }, { 4128, 157.6633, -60.6439, 6.43 },
+ { 4129, 157.5363, -65.0150, 6.19 }, { 4130, 157.9525, -27.7625, 6.05 }, { 4131, 158.4317, +53.4975, 6.45 }, { 4132, 158.3079, +40.4256, 4.75 },
+ { 4133, 158.2029,  +9.3067, 3.85 }, { 4134, 157.8408, -52.2844, 4.89 }, { 4135, 157.9896, -44.9333, 5.74 }, { 4136, 157.9858, -44.9306, 6.09 },
+ { 4137, 158.3788, +34.9886, 5.58 }, { 4138, 157.5838, -70.0069, 4.74 }, { 4139, 158.1400, -43.3811, 5.91 }, { 4140, 158.0058, -60.3147, 3.32 },
+ { 4141, 158.7904, +57.0828, 5.16 }, { 4142, 157.7583, -72.7783, 4.93 }, { 4143, 158.2371, -46.9967, 5.02 }, { 4144, 158.1983, -57.3331, 6.00 },
+ { 4145, 158.5038, -22.2547, 5.08 }, { 4146, 158.7000,  +6.9536, 5.08 }, { 4147, 158.3554, -57.8097, 6.14 }, { 4148, 158.7592,  +8.6503, 5.67 },
+ { 4149, 158.7404, -22.8239, 6.10 }, { 4150, 159.0892, +36.3269, 6.28 }, { 4151, 158.5538, -59.0122, 6.23 }, { 4152, 158.9121, -17.4308, 6.49 },
+ { 4153, 158.8038, -38.4372, 5.38 }, { 4154, 158.7937, -42.3353, 6.08 }, { 4155, 159.0725,  -9.4167, 6.57 }, { 4156, 159.0696, -15.6556, 6.03 },
+ { 4157, 159.0192, -25.3250, 6.29 }, { 4158, 159.1350, -11.7697, 5.70 }, { 4159, 158.8971, -56.4422, 4.45 }, { 4160, 159.2983, -10.2514, 6.52 },
+ { 4161, 157.9625, -80.0789, 7.07 }, { 4162, 159.3071, -26.5875, 4.89 }, { 4163, 159.3883, -12.6156, 4.82 }, { 4164, 159.0846, -58.4353, 5.08 },
+ { 4165, 159.7738, +53.6683, 5.52 }, { 4166, 159.6800, +31.9761, 4.71 }, { 4167, 159.3254, -47.7742, 3.84 }, { 4168, 159.7817, +37.9100, 5.85 },
+ { 4169, 159.3617, -57.2667, 5.45 }, { 4170, 158.8533, -75.6908, 6.30 }, { 4171, 159.6458, -15.1233, 4.91 }, { 4172, 159.7100, -11.5564, 6.04 },
+ { 4173, 159.5104, -56.7436, 5.91 }, { 4174, 158.8671, -77.3922, 4.11 }, { 4175, 159.7096, -41.2464, 6.11 }, { 4176, 160.4512, +68.4433, 5.75 },
+ { 4177, 159.6879, -58.8169, 4.66 }, { 4178, 160.4858, +65.7164, 5.12 }, { 4179, 159.7475, -57.1831, 5.92 }, { 4180, 159.8267, -54.3967, 4.28 },
+ { 4181, 160.7671, +69.0761, 5.00 }, { 4182, 160.3508,  -0.2583, 6.26 }, { 4183, 160.2150, -34.2583, 6.37 }, { 4184, 160.5471, +31.6969, 6.02 },
+ { 4185, 160.0471, -64.8994, 5.52 }, { 4186, 159.8192, -73.5064, 6.07 }, { 4187, 160.9304, +57.1992, 5.80 }, { 4188, 160.3233, -58.3231, 6.42 },
+ { 4189, 160.7575, +26.3256, 5.51 }, { 4190, 160.6304, -12.0250, 6.24 }, { 4191, 160.8871, +46.2039, 5.18 }, { 4192, 160.8542, +23.1883, 5.08 },
+ { 4193, 160.8371,  +4.7478, 5.79 }, { 4194, 160.6800, -31.2842, 5.64 }, { 4195, 161.2667, +67.4114, 6.00 }, { 4196, 160.5583, -63.5336, 4.82 },
+ { 4197, 161.0604, +19.7586, 6.27 }, { 4198, 160.6692, -58.7842, 5.38 }, { 4199, 160.7392, -63.6056, 2.76 }, { 4200, 160.8837, -59.4333, 4.57 },
+ { 4201, 161.2892,  +2.4881, 6.28 }, { 4202, 161.5938, +57.3658, 6.34 }, { 4203, 161.4663, +30.6822, 5.24 }, { 4204, 160.9633, -63.7511, 5.77 },
+ { 4205, 161.0288, -62.0389, 4.82 }, { 4206, 160.4638, -78.2167, 5.97 }, { 4207, 161.5238,  +6.3731, 6.37 }, { 4208, 161.6021, +18.8914, 5.49 },
+ { 4209, 161.6054, +14.1947, 5.48 }, { 4210, 161.2650, -58.3158, 6.21 }, { 4211, 161.0808, -69.1400, 6.26 }, { 4212, 161.1337, -69.1450, 6.46 },
+ { 4213, 161.1104, -71.5561, 6.27 }, { 4214, 161.7167, -16.7033, 5.42 }, { 4215, 162.2083, +65.1322, 6.39 }, { 4216, 161.6925, -48.5800, 2.69 },
+ { 4217, 161.5700, -59.3967, 6.25 }, { 4218, 161.9083, -14.7381, 6.67 }, { 4219, 161.5687, -63.4850, 5.34 }, { 4220, 161.6238, -63.7367, 5.23 },
+ { 4221, 161.7396, -55.2428, 5.23 }, { 4222, 161.7133, -63.6167, 4.85 }, { 4223, 162.2383, +29.4158, 6.15 }, { 4224, 162.1692,  -0.0411, 5.93 },
+ { 4225, 162.0592, -30.3117, 5.88 }, { 4226, 161.9113, -56.5322, 6.36 }, { 4227, 162.3142, +10.5453, 5.34 }, { 4228, 162.0225, -58.0808, 6.00 },
+ { 4229, 162.3221,  -3.9758, 6.61 }, { 4230, 162.4738, +27.9739, 6.04 }, { 4231, 161.3154, -79.5303, 5.47 }, { 4232, 162.4063, -15.8064, 3.11 },
+ { 4233, 162.4313,  -8.1472, 5.86 }, { 4234, 161.4450, -79.4597, 4.45 }, { 4235, 162.7962, +56.5822, 5.67 }, { 4236, 162.8488, +59.3200, 5.58 },
+ { 4237, 162.5754,  -7.1022, 5.79 }, { 4238, 162.4875, -33.9419, 5.61 }, { 4239, 162.3504, -58.6764, 5.91 }, { 4240, 162.7725,  -2.9075, 5.95 },
+ { 4241, 163.1283, +52.5653, 6.65 }, { 4242, 163.1329, +52.5036, 6.44 }, { 4243, 163.3779, +69.8539, 5.93 }, { 4244, 163.0571,  +1.0253, 6.38 },
+ { 4245, 163.1504,  +0.2014, 6.31 }, { 4246, 163.3938, +54.5850, 5.10 }, { 4247, 163.3279, +34.2150, 3.83 }, { 4248, 163.4946, +43.1900, 4.71 },
+ { 4249, 163.3537,  -1.7447, 6.12 }, { 4250, 163.1288, -56.7594, 5.25 }, { 4251, 163.3729, -19.8611, 5.24 }, { 4252, 163.3871, -14.5544, 6.38 },
+ { 4253, 163.4321,  -1.8708, 5.45 }, { 4254, 163.6758, +25.4908, 6.20 }, { 4255, 163.5742, -12.2419, 5.66 }, { 4256, 163.7425, +34.0347, 5.72 },
+ { 4257, 163.3733, -57.1467, 3.78 }, { 4258, 163.9350, +33.5069, 5.03 }, { 4259, 163.9033, +24.7497, 4.50 }, { 4260, 163.9054, +24.7489, 6.30 },
+ { 4261, 163.7983, -19.3350, 6.44 }, { 4262, 163.4250, -69.2797, 5.99 }, { 4263, 163.7542, -41.7489, 6.11 }, { 4264, 164.0604, +42.0083, 6.03 },
+ { 4265, 163.9267,  +0.7369, 5.91 }, { 4266, 163.6233, -60.1733, 5.93 }, { 4267, 164.0062,  +6.1853, 5.81 }, { 4268, 163.1146, -78.4406, 6.33 },
+ { 4269, 164.0704, +22.3517, 6.14 }, { 4270, 164.1433, +25.5000, 6.35 }, { 4271, 163.8217, -59.4831, 5.92 }, { 4272, 164.9867, +77.7700, 6.20 },
+ { 4273, 164.1796, -36.8622, 4.60 }, { 4274, 164.2829, -49.2350, 5.91 }, { 4275, 164.8246, +51.8822, 6.17 }, { 4276, 164.4517, -58.2681, 6.11 },
+ { 4277, 164.8667, +40.4303, 5.05 }, { 4278, 164.8867, +36.0931, 6.00 }, { 4279, 164.3154, -74.9003, 6.13 }, { 4280, 165.0613, +45.5261, 5.47 },
+ { 4281, 164.9212, +11.7058, 6.55 }, { 4282, 164.8079, -32.2628, 5.71 }, { 4283, 165.1067, +51.5019, 6.43 }, { 4284, 164.8788, -15.6461, 5.89 },
+ { 4285, 165.0858, +42.9114, 6.02 }, { 4286, 165.2742, +63.4211, 6.39 }, { 4287, 164.9437, -17.7011, 4.08 }, { 4288, 165.2100, +39.2122, 5.08 },
+ { 4289, 165.0483, -13.9167, 5.88 }, { 4290, 164.8083, -60.6797, 6.16 }, { 4291, 165.1400,  +3.6175, 4.84 }, { 4292, 164.9975, -42.1928, 5.81 },
+ { 4293, 165.0387, -41.7742, 4.39 }, { 4294, 165.1867,  +6.1014, 4.99 }, { 4295, 165.4604, +56.3825, 2.37 }, { 4296, 165.0358, -50.1822, 6.15 },
+ { 4297, 165.2383, -14.2072, 6.34 }, { 4298, 165.1700, -30.1606, 6.07 }, { 4299, 165.4571,  -1.5153, 4.74 }, { 4300, 165.5825, +20.1797, 4.42 },
+ { 4301, 165.9321, +61.7508, 1.79 }, { 4302, 165.6017, -25.1686, 6.23 }, { 4303, 165.8108,  +0.7525, 6.14 }, { 4304, 164.8038, -80.4439, 6.71 },
+ { 4305, 165.8121, -10.6964, 5.50 }, { 4306, 165.9025,  +0.0008, 5.95 }, { 4307, 165.8171, -30.0392, 6.46 }, { 4308, 165.9021, -12.5656, 6.34 },
+ { 4309, 166.1300, +38.2414, 6.00 }, { 4310, 166.2542,  +7.3361, 4.63 }, { 4311, 166.1300, -46.3208, 5.67 }, { 4312, 164.8075, -83.4061, 6.19 },
+ { 4313, 166.2258, -34.1953, 5.43 }, { 4314, 166.3329, -26.7064, 4.94 }, { 4315, 166.3917, -10.9111, 6.09 }, { 4316, 166.2675, -48.6075, 6.13 },
+ { 4317, 166.4900, -26.7122, 5.71 }, { 4318, 166.5242, -50.7875, 6.30 }, { 4319, 166.7258,  +1.9556, 5.52 }, { 4320, 166.6613, -27.2722, 6.77 },
+ { 4321, 166.6142, -49.0433, 6.32 }, { 4322, 166.9154, +23.3236, 6.46 }, { 4323, 166.6221, -57.3247, 6.02 }, { 4324, 166.7850, -31.4128, 6.59 },
+ { 4325, 166.6350, -61.5758, 4.61 }, { 4326, 166.6008, -63.1603, 6.41 }, { 4327, 166.8192, -41.3614, 5.15 }, { 4328, 166.9767, -29.8253, 6.54 },
+ { 4329, 166.7079, -69.1219, 5.57 }, { 4330, 167.4162, +67.2103, 6.06 }, { 4331, 167.0658, -28.0272, 6.49 }, { 4332, 167.2046, +24.6583, 5.68 },
+ { 4333, 167.3296, +36.3094, 5.74 }, { 4334, 167.1829, -27.9194, 5.44 }, { 4335, 167.4158, +44.4986, 3.01 }, { 4336, 167.4104, +43.2075, 5.89 },
+ { 4337, 167.1475, -57.0250, 3.91 }, { 4338, 167.1417, -60.0528, 5.13 }, { 4339, 167.4725, -31.6325, 5.81 }, { 4340, 168.0458, +68.2719, 6.40 },
+ { 4341, 167.9321, +14.4003, 6.30 }, { 4342, 167.7279, -57.5447, 6.88 }, { 4343, 167.9146, -21.1742, 4.48 }, { 4344, 168.1854, +54.8942, 6.63 },
+ { 4345, 168.1342, +35.8136, 6.41 }, { 4346, 168.0617, -31.5661, 6.38 }, { 4347, 168.1267, -17.5000, 6.13 }, { 4348, 168.1442, -20.2508, 6.40 },
+ { 4349, 167.8729, -70.5636, 6.35 }, { 4350, 168.1379, -48.8989, 5.36 }, { 4351, 168.4175, +41.0886, 6.33 }, { 4352, 168.1500, -59.6825, 4.60 },
+ { 4353, 168.2371, -48.2636, 6.11 }, { 4354, 168.3113, -43.6278, 5.80 }, { 4355, 168.1883, -63.8303, 5.23 }, { 4356, 168.4400,  +0.0697, 5.42 },
+ { 4357, 168.5271, +20.5236, 2.56 }, { 4358, 168.5075,  +8.0606, 5.79 }, { 4359, 168.5600, +15.4294, 3.34 }, { 4360, 168.4137, -52.7683, 5.76 },
+ { 4361, 168.3783, -58.3806, 5.74 }, { 4362, 168.8008, +23.0956, 4.63 }, { 4363, 169.0167, +52.7731, 6.50 }, { 4364, 168.7250, -42.2658, 6.21 },
+ { 4365, 168.9663, +13.3075, 5.32 }, { 4366, 168.9908, +12.8447, 6.67 }, { 4367, 169.1746, +49.4764, 5.88 }, { 4368, 169.1654,  -2.3483, 4.47 },
+ { 4369, 169.2425,  -6.8653, 6.14 }, { 4370, 169.1154, -44.1200, 6.31 }, { 4371, 169.3225,  +2.0106, 5.18 }, { 4372, 169.2992, -37.9856, 6.27 },
+ { 4373, 169.4133, -33.2628, 6.45 }, { 4374, 169.5454, +31.5292, 4.87 }, { 4375, 169.5458, +31.5292, 4.41 }, { 4376, 169.4292, -35.4656, 6.68 },
+ { 4377, 169.6196, +33.0942, 3.48 }, { 4378, 169.5875, +11.9847, 6.66 }, { 4379, 169.3292, -66.1764, 6.06 }, { 4380, 169.7829, +38.1856, 4.78 },
+ { 4381, 169.7292,  +1.6506, 5.91 }, { 4382, 169.8354, -13.2214, 3.56 }, { 4383, 170.2242, +67.1006, 6.21 }, { 4384, 169.8187, -63.4175, 5.99 },
+ { 4385, 169.6429, -78.3314, 6.35 }, { 4386, 170.2842,  +6.0294, 4.05 }, { 4387, 169.9013, -74.8575, 6.27 }, { 4388, 170.4554, +57.0750, 6.43 },
+ { 4389, 170.0163, -70.0056, 6.41 }, { 4390, 170.2517, -53.5089, 3.89 }, { 4391, 170.7138, +64.3306, 6.02 }, { 4392, 170.7067, +43.4828, 4.99 },
+ { 4393, 170.5963, -43.3542, 6.12 }, { 4394, 170.8250,  +0.1317, 6.05 }, { 4395, 170.8413, -17.2200, 5.09 }, { 4396, 170.8029, -35.8353, 5.00 },
+ { 4397, 170.4879, -76.3917, 6.43 }, { 4398, 170.7838, -55.2206, 5.79 }, { 4399, 170.9812, +10.5292, 3.94 }, { 4400, 171.0096,  +1.4078, 5.39 },
+ { 4401, 170.8408, -63.0450, 5.11 }, { 4402, 171.1525,  -9.1406, 4.83 }, { 4403, 171.0921, -41.3308, 6.12 }, { 4404, 171.2454, +11.4303, 5.80 },
+ { 4405, 171.2204, -16.3161, 4.08 }, { 4406, 171.0462, -71.7433, 5.59 }, { 4407, 171.4879, +55.8506, 5.75 }, { 4408, 171.4017, +16.4564, 5.57 },
+ { 4409, 171.3725, -35.9369, 5.22 }, { 4410, 171.4583,  +3.8600, 6.37 }, { 4411, 171.3879, -36.2522, 5.89 }, { 4412, 171.6062, +33.4506, 6.32 },
+ { 4413, 171.4300, -62.0272, 5.17 }, { 4414, 171.6888,  +3.0131, 6.50 }, { 4415, 171.6471, -60.8847, 5.30 }, { 4416, 171.7896, -11.6433, 5.94 },
+ { 4417, 171.6971, -52.8400, 5.81 }, { 4418, 171.9842,  +2.8561, 4.95 }, { 4419, 171.9738,  -0.3000, 6.25 }, { 4420, 171.9938, -34.6714, 6.45 },
+ { 4421, 172.2692, +61.7783, 5.83 }, { 4422, 172.2675, +39.3369, 5.31 }, { 4423, 172.1463, -41.3258, 5.08 }, { 4424, 172.4313, +56.7375, 6.28 },
+ { 4425, 172.0758, -71.5256, 6.09 }, { 4426, 172.4246, +15.4133, 5.74 }, { 4427, 172.5538, +54.3617, 6.41 }, { 4428, 172.4108, -23.5367, 5.76 },
+ { 4429, 172.9600, +81.1272, 6.15 }, { 4430, 172.6042, +46.6575, 6.35 }, { 4431, 172.6296, +43.1733, 5.94 }, { 4432, 172.5788,  -2.9964, 4.77 },
+ { 4433, 172.6208, +18.4097, 5.52 }, { 4434, 172.8508, +69.3311, 3.84 }, { 4435, 172.7204, +47.9292, 6.42 }, { 4436, 172.7925, +48.7892, 6.56 },
+ { 4437, 172.9371, +14.3644, 6.20 }, { 4438, 172.8125, -60.7217, 6.38 }, { 4439, 173.0867, +61.0825, 5.48 }, { 4440, 172.9483, -19.2233, 6.24 },
+ { 4441, 172.9421, -58.5578, 5.13 }, { 4442, 172.9533, -58.4842, 5.15 }, { 4443, 173.0671, -28.7367, 5.81 }, { 4444, 173.0679, -28.7389, 5.64 },
+ { 4445, 173.0971, -25.2533, 6.16 }, { 4446, 173.1979,  -6.1725, 5.95 }, { 4447, 173.2004, -39.5636, 5.64 }, { 4448, 173.0829, -65.0378, 5.90 },
+ { 4449, 173.2254, -30.9128, 5.04 }, { 4450, 173.2504, -30.1422, 3.54 }, { 4451, 173.3108, -15.7194, 6.05 }, { 4452, 173.4846, +36.8156, 6.40 },
+ { 4453, 173.4054, -39.4131, 5.39 }, { 4454, 173.5417, +11.0236, 6.55 }, { 4455, 173.5917,  +3.0600, 5.77 }, { 4456, 173.6771, +16.7969, 5.95 },
+ { 4457, 173.7704, +54.7853, 5.63 }, { 4458, 173.6229, -31.1686, 5.98 }, { 4459, 173.7658, +20.4414, 6.45 }, { 4460, 173.6904, -53.7358, 4.62 },
+ { 4461, 174.0117, +69.3228, 5.20 }, { 4462, 173.7367, -48.8633, 5.50 }, { 4463, 173.8050, -46.6275, 5.71 }, { 4464, 173.9308, +10.9111, 6.56 },
+ { 4465, 174.0746, +27.7811, 5.80 }, { 4466, 173.9817, -46.3583, 5.25 }, { 4467, 173.9450, -62.9803, 3.13 }, { 4468, 174.1704,  -8.1978, 4.70 },
+ { 4469, 174.1458, -32.4300, 5.74 }, { 4470, 174.1700, -36.7622, 6.31 }, { 4471, 174.2371,  +0.8239, 4.30 }, { 4472, 174.0929, -60.9478, 5.83 },
+ { 4473, 174.2550, -31.0119, 6.29 }, { 4474, 174.4708, +50.6183, 6.14 }, { 4475, 174.2525, -60.7167, 5.15 }, { 4476, 174.3913, -46.2528, 5.44 },
+ { 4477, 174.5858, +43.6256, 5.59 }, { 4478, 174.5408,  +8.8842, 6.17 }, { 4479, 174.3150, -74.1033, 5.65 }, { 4480, 174.6396, +46.8342, 6.10 },
+ { 4481, 174.7050, +64.3469, 6.46 }, { 4482, 174.6342, +33.6256, 6.27 }, { 4483, 174.6150,  +8.1342, 5.36 }, { 4484, 174.6004,  -1.5639, 6.22 },
+ { 4485, 174.4517, -66.3797, 5.96 }, { 4486, 174.6871, +45.1086, 6.44 }, { 4487, 174.5304, -60.1736, 5.15 }, { 4488, 174.6671, -12.7981, 5.48 },
+ { 4489, 174.7517, -23.2789, 6.42 }, { 4490, 174.9629, -13.5314, 6.21 }, { 4491, 174.9600, -15.3797, 6.19 }, { 4492, 174.8725, -64.6022, 5.17 },
+ { 4493, 175.1142, +57.9706, 6.37 }, { 4494, 175.0533, -33.2553, 4.70 }, { 4495, 175.1962, +21.3528, 5.26 }, { 4496, 175.2625, +34.2017, 5.33 },
+ { 4497, 175.1775, -52.0314, 5.96 }, { 4498, 175.2850, -28.8036, 6.44 }, { 4499, 175.2233, -61.9100, 4.94 }, { 4500, 175.4317, +55.1725, 6.27 },
+ { 4501, 175.3929, +31.7461, 5.73 }, { 4502, 175.3325, -42.9042, 5.55 }, { 4503, 175.4333, -31.5003, 5.22 }, { 4504, 175.6183, +66.7450, 5.30 },
+ { 4505, 175.5217, +22.2108, 6.59 }, { 4506, 175.5146, -19.7061, 6.22 }, { 4507, 175.2550, -82.9000, 6.33 }, { 4508, 175.8633, -36.8097, 5.98 },
+ { 4509, 175.7308, -78.6936, 6.39 }, { 4510, 175.9796,  -5.3228, 6.07 }, { 4511, 175.8800, -61.5106, 5.03 }, { 4512, 176.0550, +25.2183, 6.02 },
+ { 4513, 175.9704, -61.1217, 6.10 }, { 4514, 176.1908, -17.6492, 4.73 }, { 4515, 176.3212,  +8.2583, 4.85 }, { 4516, 176.3025, -48.9303, 6.26 },
+ { 4517, 176.4650,  +6.5294, 4.03 }, { 4518, 176.5125, +47.7794, 3.71 }, { 4519, 176.4329, -44.3100, 5.29 }, { 4520, 176.4017, -65.2714, 3.64 },
+ { 4521, 176.7317, +55.6283, 5.27 }, { 4522, 176.6283, -60.8217, 4.11 }, { 4523, 176.6296, -39.4994, 4.91 }, { 4524, 176.7792, -34.0931, 6.17 },
+ { 4525, 176.8154, -29.7131, 6.48 }, { 4526, 176.8296, -56.3036, 5.41 }, { 4527, 176.9963, +20.2189, 4.53 }, { 4528, 176.9787,  +8.2458, 5.32 },
+ { 4529, 177.0979,  -9.6867, 6.26 }, { 4530, 177.0596, -65.1853, 4.72 }, { 4531, 177.1613, +14.2842, 5.88 }, { 4532, 177.1879, -25.2503, 5.11 },
+ { 4533, 177.2550,  +0.3186, 6.15 }, { 4534, 177.2650, +14.5719, 2.14 }, { 4535, 177.3121, +16.2428, 6.04 }, { 4536, 177.4238, +34.9317, 5.70 },
+ { 4537, 177.4212, -62.2117, 4.32 }, { 4538, 177.4858, -69.7742, 4.97 }, { 4539, 177.5813, -14.1361, 6.13 }, { 4540, 177.6738,  +1.7647, 3.61 },
+ { 4541, 177.6133, -61.3506, 5.70 }, { 4542, 177.6546, -26.7222, 6.48 }, { 4543, 177.7304, +12.2789, 6.35 }, { 4544, 177.7592,  -4.6667, 5.64 },
+ { 4545, 177.7892, +33.3750, 6.27 }, { 4546, 177.7863, -44.8264, 4.46 }, { 4547, 177.8413, -11.8122, 6.35 }, { 4548, 177.9233, -29.1650, 5.85 },
+ { 4549, 177.9633, -64.7939, 4.90 }, { 4550, 178.2450, +37.7186, 6.45 }, { 4551, 178.0421, -55.0122, 5.57 }, { 4552, 178.2275, -32.0919, 4.28 },
+ { 4553, 178.3617, -34.9333, 6.17 }, { 4554, 178.4575, +53.6947, 2.44 }, { 4555, 178.4596,  +0.5519, 6.30 }, { 4556, 178.5479, -56.5900, 6.06 },
+ { 4557, 178.6075, -36.2511, 6.46 }, { 4558, 178.6771, -24.2861, 5.30 }, { 4559, 178.7629,  +8.4439, 5.58 }, { 4560, 178.7738, +46.4769, 6.54 },
+ { 4561, 178.7967, +46.4697, 7.03 }, { 4562, 178.8088, +36.7564, 6.49 }, { 4563, 178.7492, -62.7211, 5.91 }, { 4564, 178.9187, +15.6467, 5.53 },
+ { 4565, 178.9171, -27.5231, 5.93 }, { 4566, 178.9933, +56.5986, 5.84 }, { 4567, 179.0038, -16.8492, 5.18 }, { 4568, 178.9779, -38.3108, 6.13 },
+ { 4569, 179.2217, +61.5492, 6.22 }, { 4570, 179.1829, -46.9275, 6.26 }, { 4571, 179.2654, -32.6847, 6.21 }, { 4572, 179.3108, +40.3436, 6.62 },
+ { 4573, 179.4171, -61.5511, 5.57 }, { 4574, 179.5300, +32.2739, 6.42 }, { 4575, 179.5858, +61.4647, 6.76 }, { 4576, 179.5633, -55.6828, 5.44 },
+ { 4577, 179.5846, -39.0528, 6.79 }, { 4578, 179.6987, -63.6608, 5.61 }, { 4579, 179.7267, -24.0911, 6.43 }, { 4580, 179.7642,  +0.5306, 6.17 },
+ { 4581, 179.8233, +33.1675, 5.96 }, { 4582, 179.7954, -50.3033, 6.05 }, { 4583, 179.9054, -77.7781, 4.91 }, { 4584, 179.9883, +34.0350, 6.50 },
+ { 4585, 179.9871,  +3.6553, 5.37 }, { 4586, 180.0775, +80.8531, 6.17 }, { 4587, 180.1854,  -9.5539, 5.55 }, { 4588, 180.1771, -20.1628, 6.28 },
+ { 4589, 180.2183,  +6.6142, 4.66 }, { 4590, 180.2133, -18.3411, 5.26 }, { 4591, 180.2575,  -0.2319, 6.31 }, { 4592, 180.3708, -56.4964, 6.16 },
+ { 4593, 180.4146, +36.0419, 5.59 }, { 4594, 180.5283, +43.0456, 5.21 }, { 4595, 180.5838, -84.3683, 6.05 }, { 4596, 180.6192, -70.5111, 6.42 },
+ { 4597, 180.6571, -68.8078, 5.89 }, { 4598, 180.7150,  -6.3164, 6.22 }, { 4599, 180.7562, -62.6872, 4.33 }, { 4600, 180.9150, -41.5658, 5.15 },
+ { 4601, 180.9346, -73.7861, 6.44 }, { 4602, 181.0692, +21.4592, 5.87 }, { 4603, 181.0800, -62.8344, 4.72 }, { 4604, 181.1613, -67.6708, 5.35 },
+ { 4605, 181.1937, -75.4808, 5.04 }, { 4606, 181.1171, +85.5872, 6.27 }, { 4607, 181.2379, -59.0308, 5.96 }, { 4608, 181.3021,  +8.7331, 4.12 },
+ { 4609, 181.3129, +76.9058, 5.80 }, { 4610, 181.4154, +62.9331, 6.13 }, { 4611, 181.4717, -64.4528, 6.33 }, { 4612, 181.4863, -34.3061, 6.23 },
+ { 4613, 181.4992,  -2.8683, 6.37 }, { 4614, 181.5825, -67.3492, 6.23 }, { 4615, 181.5963, -64.2908, 6.06 }, { 4616, 181.7204, -63.3864, 4.15 },
+ { 4617, 181.9575, -74.6331, 5.18 }, { 4618, 182.0217, -49.3386, 4.47 }, { 4619, 182.0200, -49.2367, 6.37 }, { 4620, 182.0613, -47.3072, 5.34 },
+ { 4621, 182.0896, -49.2775, 2.60 }, { 4622, 182.1025, -59.1528, 6.22 }, { 4623, 182.1033, -23.2711, 4.02 }, { 4624, 182.2242, -43.6739, 5.75 },
+ { 4625, 182.2271, -40.7686, 5.48 }, { 4626, 182.4221,  +1.8978, 5.95 }, { 4627, 182.4471, +74.6614, 6.35 }, { 4628, 182.5104, -33.2950, 6.17 },
+ { 4629, 182.5142,  +5.8069, 5.72 }, { 4630, 182.5313, -21.3803, 3.00 }, { 4631, 182.6408, -36.1297, 6.06 }, { 4632, 182.6317, +16.8092, 6.39 },
+ { 4633, 182.6921, +27.2814, 6.01 }, { 4634, 182.7704, -60.7225, 6.08 }, { 4635, 182.7663, -22.3975, 5.46 }, { 4636, 182.7621, -44.5772, 6.61 },
+ { 4637, 182.8808, -50.6406, 6.23 }, { 4638, 182.9129, -51.6314, 3.96 }, { 4639, 182.7500, +81.7100, 6.00 }, { 4640, 182.9633, +25.8703, 5.66 },
+ { 4641, 182.9371, +57.0544, 6.43 }, { 4642, 183.0050, +28.5361, 6.49 }, { 4643, 183.0387, +20.5419, 5.57 }, { 4644, 183.0917, -61.0492, 5.92 },
+ { 4645, 183.1950, -69.8481, 6.17 }, { 4646, 183.0496, +77.6164, 5.14 }, { 4647, 183.3042, -33.8744, 6.50 }, { 4648, 183.3554, -37.0708, 5.76 },
+ { 4649, 183.4821, -77.4264, 6.35 }, { 4650, 183.3579, +10.2622, 5.85 }, { 4651, 183.4029, -32.2072, 6.33 }, { 4652, 183.5108, -44.2761, 5.31 },
+ { 4653, 183.5700, -63.5914, 6.22 }, { 4654, 183.6808, +53.4347, 6.16 }, { 4655, 183.7483, -19.1558, 5.83 }, { 4656, 183.7863, -57.2511, 2.80 },
+ { 4657, 183.7942,  -9.6875, 6.11 }, { 4658, 183.8771, -40.0869, 6.26 }, { 4659, 183.7854, +70.2000, 5.71 }, { 4660, 183.8567, +57.0325, 3.31 },
+ { 4661, 183.9458, -22.6464, 6.54 }, { 4662, 183.9517, -16.4581, 2.59 }, { 4663, 184.0008, +14.8989, 5.10 }, { 4664, 184.0979, -71.3853, 6.22 },
+ { 4665, 183.9225, +72.5508, 6.29 }, { 4666, 184.0317, +40.6603, 5.66 }, { 4667, 184.0854, +23.9453, 4.95 }, { 4668, 184.1254, +33.0614, 5.00 },
+ { 4669, 184.2750, -64.3072, 6.06 }, { 4670, 184.2637, -15.3064, 6.05 }, { 4671, 184.3921, -66.0392, 4.11 }, { 4672, 184.3729, +53.1911, 5.81 },
+ { 4673, 184.3771, +28.9372, 5.70 }, { 4674, 184.5863, -78.6878, 4.26 }, { 4675, 184.4471, -35.9061, 6.15 }, { 4676, 184.4346, +15.1442, 6.34 },
+ { 4677, 184.5379,  -2.0456, 6.99 }, { 4678, 184.5400,  -2.0514, 6.54 }, { 4679, 184.6087, -63.9969, 4.04 }, { 4680, 184.6317, +30.2492, 6.23 },
+ { 4681, 184.6679,  +0.7872, 5.90 }, { 4682, 184.7488, -54.8569, 5.00 }, { 4683, 184.2142, +86.4361, 6.33 }, { 4684, 184.7587, +26.0078, 6.48 },
+ { 4685, 184.8296, +23.0347, 6.27 }, { 4686, 183.8346, +87.7000, 6.28 }, { 4687, 184.7079, +75.1606, 5.38 }, { 4688, 184.8733, +28.1569, 6.33 },
+ { 4689, 184.9767,  +0.6669, 3.89 }, { 4690, 184.9529, +48.9842, 5.29 }, { 4691, 185.0446, -21.8244, 5.97 }, { 4692, 185.1167, -64.1572, 6.21 },
+ { 4693, 185.0821, +26.6194, 5.54 }, { 4694, 185.0737, +26.0019, 6.15 }, { 4695, 185.0875,  +3.3125, 4.96 }, { 4696, 185.1404, -21.7842, 5.21 },
+ { 4697, 185.1792, +17.7928, 4.74 }, { 4698, 185.1721, +27.0547, 7.13 }, { 4699, 185.2321, -12.4344, 5.14 }, { 4700, 185.3400, -59.5989, 3.59 },
+ { 4701, 185.2117, +57.8639, 5.55 }, { 4702, 185.4896, -55.6253, 5.92 }, { 4703, 185.5304, -66.4781, 5.15 }, { 4704, 185.5496, -67.6925, 5.74 },
+ { 4705, 185.5450, +24.7739, 6.19 }, { 4706, 185.7054, -56.3239, 5.39 }, { 4707, 185.6263, +25.8461, 4.81 }, { 4708, 185.6333,  +5.3056, 6.40 },
+ { 4709, 186.4063, -85.8494, 6.33 }, { 4710, 185.8075, -66.3683, 6.36 }, { 4711, 185.8400, -23.1594, 5.68 }, { 4712, 185.8975, -34.5872, 5.32 },
+ { 4713, 185.9038, -38.6969, 6.40 }, { 4714, 185.9371, -37.0889, 5.79 }, { 4715, 185.9458, +42.5428, 6.06 }, { 4716, 186.0062, +51.5622, 4.80 },
+ { 4717, 186.0771, +26.0986, 5.18 }, { 4718, 186.1863, -40.6158, 6.25 }, { 4719, 186.1113, +25.5828, 6.42 }, { 4720, 186.3221, -64.2294, 6.30 },
+ { 4721, 186.2854, -41.4856, 6.11 }, { 4722, 186.2988, -10.3897, 5.95 }, { 4723, 186.3267, -26.2508, 6.09 }, { 4724, 186.3408, -34.8136, 5.73 },
+ { 4725, 186.3129, +23.9261, 6.03 }, { 4726, 186.2633, +56.7775, 5.81 }, { 4727, 186.2767, +63.8028, 6.32 }, { 4728, 186.4621, +39.0186, 5.02 },
+ { 4729, 186.6288, -62.8775, 4.86 }, { 4730, 186.6496, -62.9008, 1.33 }, { 4731, 186.6521, -62.9006, 1.73 }, { 4732, 186.6317, -50.5492, 4.82 },
+ { 4733, 186.6004, +27.2683, 4.95 }, { 4734, 186.7008, -47.0867, 6.26 }, { 4735, 186.7154, -31.1700, 5.55 }, { 4736, 186.8525, -62.2108, 6.00 },
+ { 4737, 186.7346, +28.2683, 4.36 }, { 4738, 186.7471, +26.8256, 5.00 }, { 4739, 186.8696, -57.0081, 5.50 }, { 4740, 186.6008, +71.9297, 6.24 },
+ { 4741, 186.9254,  +8.6103, 6.37 }, { 4742, 186.9558, -15.3681, 6.35 }, { 4743, 187.0100, -49.7694, 3.91 }, { 4744, 187.0788, -63.6586, 6.04 },
+ { 4745, 186.8963, +55.7128, 5.70 }, { 4746, 186.9650,  -3.3847, 6.22 }, { 4747, 187.1062, -60.2047, 6.22 }, { 4748, 187.0938, -38.9586, 5.44 },
+ { 4749, 187.1392, -55.5922, 6.15 }, { 4750, 187.1588, +26.2267, 6.54 }, { 4751, 187.1858, +25.8992, 6.65 }, { 4752, 187.2279, +25.9128, 5.29 },
+ { 4753, 187.3621, +24.1089, 5.48 }, { 4754, 187.4746, -55.4753, 5.80 }, { 4755, 187.4913, -40.2639, 6.02 }, { 4756, 187.4300, +20.8961, 5.69 },
+ { 4757, 187.4663, -15.4844, 2.95 }, { 4758, 187.5200, -12.6069, 6.35 }, { 4759, 187.5729, -22.3033, 5.63 }, { 4760, 187.4888, +58.4058, 5.35 },
+ { 4761, 187.5121, +51.5356, 6.21 }, { 4762, 187.5179, +58.7675, 6.08 }, { 4763, 187.7912, -56.8867, 1.63 }, { 4764, 187.8196, -56.9189, 6.42 },
+ { 4765, 187.5279, +69.2011, 4.95 }, { 4766, 187.7525, +24.5672, 5.46 }, { 4767, 187.7088, +53.0767, 6.21 }, { 4768, 187.9179, -58.5761, 5.48 },
+ { 4769, 188.0417, -72.9983, 5.88 }, { 4770, 187.8392,  +7.6042, 6.05 }, { 4771, 187.9825, -62.4939, 5.95 }, { 4772, 187.9113,  -4.9475, 6.19 },
+ { 4773, 188.1167, -71.8669, 3.87 }, { 4774, 188.0188, -31.4664, 6.46 }, { 4775, 188.0175, -15.8039, 4.31 }, { 4776, 188.1500, -12.1408, 5.74 },
+ { 4777, 188.2621, +10.2956, 6.26 }, { 4778, 188.3433, -18.2081, 6.26 }, { 4779, 188.3929, -11.1697, 5.58 }, { 4780, 188.3925, +24.2831, 6.29 },
+ { 4781, 188.4450,  -8.5481, 5.48 }, { 4782, 188.4967, -48.0906, 6.38 }, { 4783, 188.4121, +33.2475, 5.42 }, { 4784, 188.4475, +33.3847, 6.24 },
+ { 4785, 188.4354, +41.3575, 4.26 }, { 4786, 188.5967, -22.6033, 2.65 }, { 4787, 188.3708, +69.7883, 3.87 }, { 4788, 188.6763, -43.3267, 5.77 },
+ { 4789, 188.7129, +22.6292, 4.81 }, { 4790, 188.8708, -60.1581, 6.22 }, { 4791, 188.7763, +18.3772, 6.56 }, { 4792, 188.7825, +18.3769, 5.02 },
+ { 4793, 188.7838, +21.8814, 5.85 }, { 4794, 188.9396, -40.9781, 5.13 }, { 4795, 188.6833, +70.0219, 4.94 }, { 4796, 189.0050, -38.1300, 5.80 },
+ { 4797, 188.9942, -19.4728, 6.20 }, { 4798, 189.2958, -68.8644, 2.69 }, { 4799, 189.1975,  -4.1681, 5.87 }, { 4800, 189.0971, +59.4869, 5.50 },
+ { 4801, 189.2429, +17.0894, 5.68 }, { 4802, 189.4258, -47.4589, 3.86 }, { 4803, 189.4258, -26.8611, 5.45 }, { 4804, 189.8104, -74.6306, 6.49 },
+ { 4805, 189.5183,  +3.2825, 6.33 }, { 4806, 189.7188, -66.8069, 6.25 }, { 4807, 189.5933,  +1.8547, 5.71 }, { 4808, 189.6250,  +6.9883, 7.08 },
+ { 4809, 189.6858, -17.7497, 6.00 }, { 4810, 189.7646, -29.5778, 5.89 }, { 4811, 189.6929, +40.8744, 6.37 }, { 4812, 189.7587, +22.6594, 6.38 },
+ { 4813, 189.8117,  -6.0044, 4.66 }, { 4814, 189.9817, -65.4883, 6.26 }, { 4815, 189.7804, +21.0625, 5.46 }, { 4816, 189.8204, +35.9519, 6.45 },
+ { 4817, 189.9688, -38.0125, 4.64 }, { 4818, 190.3458, -45.8544, 5.84 }, { 4819, 190.3792, -47.0403, 2.17 }, { 4820, 190.5213, -68.5925, 6.33 },
+ { 4821, 190.3167, -12.9864, 6.08 }, { 4822, 190.3175, -12.9850, 5.98 }, { 4823, 190.4858, -58.3142, 4.93 }, { 4824, 190.3933, +10.4264, 6.19 },
+ { 4825, 190.4150,  -0.5506, 3.65 }, { 4826, 190.4150,  -0.5506, 3.68 }, { 4827, 190.4550, -18.2414, 6.03 }, { 4828, 190.4713, +10.2356, 4.88 },
+ { 4829, 190.4879,  +6.8067, 5.59 }, { 4830, 190.7096, -62.9414, 5.31 }, { 4831, 190.6475, -47.1869, 4.66 }, { 4832, 190.7067, -54.0528, 6.08 },
+ { 4833, 190.3913, +62.7131, 6.07 }, { 4834, 190.7879, -55.8239, 6.00 }, { 4835, 190.8675, -57.0969, 6.40 }, { 4836, 190.8596, -39.8222, 6.44 },
+ { 4837, 190.9088,  -0.4231, 5.93 }, { 4838, 190.9946, -35.6508, 6.39 }, { 4839, 191.0021, -27.6761, 5.48 }, { 4840, 190.7675, +61.1556, 6.38 },
+ { 4841, 191.2571, -67.1689, 6.16 }, { 4842, 191.4079, -59.0189, 4.69 }, { 4843, 191.1129, +44.1031, 6.33 }, { 4844, 191.5704, -67.8919, 3.05 },
+ { 4845, 191.2479, +39.2789, 5.95 }, { 4846, 191.2825, +45.4403, 4.99 }, { 4847, 191.4046,  +7.6733, 5.22 }, { 4848, 191.5946, -55.5111, 4.65 },
+ { 4849, 191.5938,  +9.5400, 5.67 }, { 4850, 191.6917, -32.6844, 5.86 }, { 4851, 191.6613, +16.5775, 5.12 }, { 4852, 191.1083, +80.6211, 6.40 },
+ { 4853, 191.9300, -58.3114, 1.25 }, { 4854, 191.7596,  +5.9508, 6.34 }, { 4855, 191.8067, +11.9581, 6.07 }, { 4856, 191.8892,  -5.6981, 6.26 },
+ { 4857, 191.9738, -23.1483, 6.44 }, { 4858, 191.9642,  +3.5728, 6.41 }, { 4859, 191.8288, +62.7808, 5.89 }, { 4860, 192.1100, -26.4025, 5.66 },
+ { 4861, 192.0596, +13.5531, 6.56 }, { 4862, 192.4371, -70.0136, 5.55 }, { 4863, 191.8933, +66.7903, 5.43 }, { 4864, 192.1958, +24.8403, 6.31 },
+ { 4865, 192.2258, +14.1225, 5.70 }, { 4866, 192.1742, +48.4669, 6.27 }, { 4867, 192.1642, +60.3200, 5.85 }, { 4868, 192.5500, -59.5992, 6.75 },
+ { 4869, 192.3225, +27.5522, 5.78 }, { 4870, 193.7442, -84.8767, 5.46 }, { 4871, 192.5817, -47.5403, 6.24 }, { 4872, 192.7413, -51.2125, 5.73 },
+ { 4873, 192.5725, +22.8633, 6.43 }, { 4874, 192.6717, -32.0006, 4.91 }, { 4875, 192.5446, +37.5169, 5.89 }, { 4876, 192.8242, -59.6703, 5.72 },
+ { 4877, 192.8454,  -9.6617, 6.41 }, { 4878, 192.9038,  +3.0567, 6.02 }, { 4879, 192.9867, -38.3192, 5.98 }, { 4880, 193.0221, -47.9058, 6.33 },
+ { 4881, 192.9913, -25.2619, 6.15 }, { 4882, 193.1025, -52.1706, 6.24 }, { 4883, 192.9246, +27.5406, 4.94 }, { 4884, 193.0513, +17.0739, 6.32 },
+ { 4885, 193.2663, -53.0475, 5.93 }, { 4886, 193.1150, +16.1225, 6.30 }, { 4887, 193.3408, -59.6714, 5.76 }, { 4888, 193.2788, -47.0567, 4.33 },
+ { 4889, 193.3592, -39.8211, 4.27 }, { 4890, 193.4546, -59.6231, 5.90 }, { 4891, 193.2967,  -2.4469, 6.11 }, { 4892, 192.2775, +83.4181, 5.85 },
+ { 4893, 192.3067, +83.4128, 5.28 }, { 4894, 193.3242, +21.2450, 4.90 }, { 4895, 193.5917, -57.5694, 6.58 }, { 4896, 193.4088,  -3.7761, 6.44 },
+ { 4897, 193.6633, -58.8533, 4.62 }, { 4898, 193.6483, -56.8222, 4.03 }, { 4899, 193.6533, -56.8317, 5.17 }, { 4900, 193.4571, +12.4186, 6.25 },
+ { 4901, 193.5779, -10.3514, 6.00 }, { 4902, 193.5883,  -8.4611, 4.79 }, { 4903, 193.7438, -43.8481, 5.89 }, { 4904, 193.5546, +33.5344, 6.26 },
+ { 4905, 193.5071, +55.9597, 1.77 }, { 4906, 193.8308, -41.0842, 5.47 }, { 4907, 194.1312, -71.8147, 5.93 }, { 4908, 193.9875, -55.1639, 5.32 },
+ { 4909, 193.7354, +47.1967, 5.84 }, { 4910, 193.9008,  +3.3975, 3.38 }, { 4911, 193.9721, -14.6731, 6.17 }, { 4912, 194.1254, -25.5397, 6.62 },
+ { 4913, 194.2683, -50.8014, 5.16 }, { 4914, 194.0017, +38.3147, 5.60 }, { 4915, 194.0071, +38.3183, 2.90 }, { 4916, 193.8688, +65.4386, 5.24 },
+ { 4917, 194.0733, +54.0994, 5.82 }, { 4918, 194.3883, -21.2461, 6.31 }, { 4919, 194.2821, +46.1769, 6.12 }, { 4920, 194.7308, +17.4094, 4.78 },
+ { 4921, 194.9146,  -2.1881, 5.79 }, { 4922, 195.1358, -32.4947, 6.02 }, { 4923, 195.5675, -70.4511, 3.62 }, { 4924, 195.0687, +30.7850, 4.90 },
+ { 4925, 195.1496,  -2.6314, 5.99 }, { 4926, 195.1617, +18.3731, 6.20 }, { 4927, 194.6971, +75.4725, 6.01 }, { 4928, 194.9796, +66.5972, 5.32 },
+ { 4929, 195.2900, +17.1231, 5.96 }, { 4930, 195.7717, -70.5239, 6.03 }, { 4931, 195.1825, +56.3664, 4.93 }, { 4932, 195.5442, +10.9592, 2.83 },
+ { 4933, 195.8883, -48.4728, 4.85 }, { 4934, 195.4450, +63.6103, 6.00 }, { 4935, 195.9421, -19.4169, 5.58 }, { 4936, 195.6683, +59.7161, 6.53 },
+ { 4937, 195.9767,  -2.3367, 6.59 }, { 4938, 196.2004, -40.8033, 6.26 }, { 4939, 196.3783, -51.8850, 6.43 }, { 4940, 196.5696, -47.5364, 4.71 },
+ { 4941, 196.6463, -40.4114, 5.59 }, { 4942, 196.7275, -48.0939, 4.27 }, { 4943, 196.4354, +35.7989, 5.25 }, { 4944, 196.8508, -58.1394, 5.99 },
+ { 4945, 196.4679, +45.2686, 5.63 }, { 4946, 196.5883, +21.1533, 5.99 }, { 4947, 196.7262, -34.1381, 6.54 }, { 4948, 196.5425, +29.0294, 6.54 },
+ { 4949, 196.5942, +22.6161, 5.60 }, { 4950, 196.2071, +73.0253, 6.31 }, { 4951, 196.9096, -52.5403, 5.71 }, { 4952, 197.0292, -64.6936, 5.51 },
+ { 4953, 196.5946, +62.0419, 6.14 }, { 4954, 196.7946, +27.6247, 4.80 }, { 4955, 196.9742,  -9.2597, 5.19 }, { 4956, 196.9733, +27.5558, 6.19 },
+ { 4957, 197.1354,  -7.0156, 5.55 }, { 4958, 197.2637, -22.8819, 4.95 }, { 4959, 197.3100,  -8.4617, 6.32 }, { 4960, 197.3017, +10.0222, 5.78 },
+ { 4961, 197.4388,  -9.6706, 5.94 }, { 4962, 197.4492, +16.8486, 5.91 }, { 4963, 197.4875,  -4.4611, 4.38 }, { 4964, 197.4113, +37.4231, 6.02 },
+ { 4965, 197.7433, -51.4331, 6.06 }, { 4966, 197.9650, -68.0581, 5.91 }, { 4967, 197.4250, +38.5339, 6.28 }, { 4968, 197.4971, +17.5294, 5.22 },
+ { 4969, 197.4971, +17.5294, 5.22 }, { 4970, 197.7867, -41.7669, 5.79 }, { 4971, 197.5133, +38.4989, 5.91 }, { 4972, 197.9713, -62.6972, 6.33 },
+ { 4973, 197.8467, -42.6311, 5.25 }, { 4974, 197.4592, +62.2292, 6.54 }, { 4975, 198.0725, -58.0792, 4.60 }, { 4976, 198.5717, -77.5528, 5.85 },
+ { 4977, 198.2038, -65.7731, 5.90 }, { 4978, 197.9133, -25.4483, 6.50 }, { 4979, 198.0133, -36.1969, 4.85 }, { 4980, 198.2333, -58.1833, 6.16 },
+ { 4981, 198.0146, -15.8014, 5.04 }, { 4982, 198.2121, -41.3003, 6.22 }, { 4983, 197.9683, +27.8781, 4.26 }, { 4984, 198.0350, +24.2581, 6.33 },
+ { 4985, 198.3479, -49.3000, 5.89 }, { 4986, 198.1371, +11.5561, 5.77 }, { 4987, 198.1496, +18.7517, 6.53 }, { 4988, 198.5504, -57.3161, 5.89 },
+ { 4989, 198.5617, -58.8967, 4.92 }, { 4990, 198.3617, -17.1733, 6.28 }, { 4991, 198.4896, -42.8611, 6.16 }, { 4992, 198.3017, +18.7269, 6.11 },
+ { 4993, 198.8121, -66.1056, 4.80 }, { 4994, 198.8571, -68.3203, 6.37 }, { 4995, 198.5454, -18.0692, 5.33 }, { 4996, 198.6796, -47.0433, 5.89 },
+ { 4997, 198.4292, +40.1528, 4.92 }, { 4998, 198.6304, +11.3317, 5.67 }, { 4999, 198.7904, -35.6289, 6.19 }, { 5000, 199.1867, -64.8617, 6.07 },
+ { 5001, 198.9950, -18.0569, 5.22 }, { 5002, 199.3042, -65.2164, 4.87 }, { 5003, 198.3833, +72.7989, 6.59 }, { 5004, 198.8833, +40.8553, 5.79 },
+ { 5005, 199.1062,  -0.6094, 6.68 }, { 5006, 199.2213, -30.4939, 5.10 }, { 5007, 199.0596, +19.0517, 6.45 }, { 5008, 199.3079, -42.0206, 5.84 },
+ { 5009, 198.1058, +80.4714, 6.25 }, { 5010, 199.1346, +19.7853, 6.45 }, { 5011, 199.1937,  +9.4242, 5.22 }, { 5012, 199.8288, -71.9644, 6.04 },
+ { 5013, 199.3150, +13.6756, 5.33 }, { 5014, 199.3746,  +0.6767, 6.37 }, { 5015, 199.4013,  +5.4697, 4.80 }, { 5016, 199.6442, -50.7139, 6.19 },
+ { 5017, 199.3854, +40.5725, 4.73 }, { 5018, 199.1192, +68.4081, 6.20 }, { 5019, 199.6012, -17.6886, 4.74 }, { 5020, 199.7304, -22.8283, 3.00 },
+ { 5021, 199.7129,  +3.6878, 6.62 }, { 5022, 199.6158, +34.0981, 5.82 }, { 5023, 199.5604, +49.6819, 5.15 }, { 5024, 200.1454, -58.2267, 6.18 },
+ { 5025, 199.7675, +35.1281, 6.02 }, { 5026, 200.1575, -51.2519, 5.48 }, { 5027, 200.2012, -54.1994, 6.02 }, { 5028, 200.1492, -35.2878, 2.75 },
+ { 5029, 200.2404, -45.1194, 5.77 }, { 5030, 200.7192, -71.8533, 6.05 }, { 5031, 200.1733,  +2.9417, 6.26 }, { 5032, 200.0792, +40.1506, 5.60 },
+ { 5033, 200.3746, -18.5111, 6.21 }, { 5034, 200.6488, -59.0278, 6.18 }, { 5035, 200.6579, -59.0117, 4.53 }, { 5036, 200.5675, -51.8169, 5.83 },
+ { 5037, 200.4233,  +2.0872, 5.69 }, { 5038, 200.7196, -46.0569, 6.16 }, { 5039, 200.7608, -47.4372, 6.38 }, { 5040, 200.5404,  +5.1547, 5.87 },
+ { 5041, 201.0021, -63.4642, 4.53 }, { 5042, 201.2796, -73.1122, 5.05 }, { 5043, 200.7863, -32.8100, 6.22 }, { 5044, 200.7546, -16.2647, 5.37 },
+ { 5045, 200.5158, +43.9031, 6.35 }, { 5046, 200.9679, -48.1769, 6.48 }, { 5047, 200.8288,  -3.0756, 5.89 }, { 5048, 201.3079, -63.5147, 5.31 },
+ { 5049, 201.4588, -69.3725, 5.67 }, { 5050, 201.1383,  -4.8361, 5.75 }, { 5051, 201.8262, -73.3081, 6.63 }, { 5052, 200.9750, +37.0339, 6.07 },
+ { 5053, 201.1271, +12.4319, 6.44 }, { 5054, 200.9812, +54.9253, 2.27 }, { 5055, 200.9850, +54.9217, 3.95 }, { 5056, 201.2983, -10.8386, 0.98 },
+ { 5057, 201.2779, +23.8544, 5.78 }, { 5058, 201.5325, -38.2447, 5.09 }, { 5059, 201.5475,  -0.8075, 5.97 }, { 5060, 201.7337, -40.5019, 5.69 },
+ { 5061, 201.7763, -48.8561, 6.31 }, { 5062, 201.3063, +54.9881, 4.01 }, { 5063, 201.8367, -48.6192, 6.28 }, { 5064, 201.6800, -11.2922, 5.25 },
+ { 5065, 201.8113, -39.8369, 6.40 }, { 5066, 202.1933, -68.3719, 6.20 }, { 5067, 201.5692, +46.0281, 5.88 }, { 5068, 201.8633, -14.0264, 4.76 },
+ { 5069, 202.2817, -63.3242, 6.11 }, { 5070, 201.4996, +63.2611, 6.50 }, { 5071, 202.3550, -50.8347, 5.06 }, { 5072, 202.1075, +13.7789, 4.98 },
+ { 5073, 201.5338, +72.3914, 5.79 }, { 5074, 201.7692, +64.7356, 6.66 }, { 5075, 201.7946, +64.7194, 7.04 }, { 5076, 201.9979, +52.7458, 6.34 },
+ { 5077, 202.1092, +40.7297, 6.47 }, { 5078, 202.3121,  -0.6356, 6.43 }, { 5079, 202.0488, +50.5872, 6.80 }, { 5080, 202.4283, -22.7186, 4.97 },
+ { 5081, 202.3042, +10.8183, 5.65 }, { 5082, 203.3117, -76.4317, 6.48 }, { 5083, 202.1904, +50.7183, 6.43 }, { 5084, 205.2312, -84.2139, 5.58 },
+ { 5085, 202.1129, +59.9458, 5.40 }, { 5086, 202.5004,  +7.1789, 6.17 }, { 5087, 202.4900,  +6.0133, 6.51 }, { 5088, 202.6071,  -5.5297, 6.09 },
+ { 5089, 202.7612, -38.5925, 3.88 }, { 5090, 202.8887, -27.8872, 6.47 }, { 5091, 201.7363, +78.6439, 5.77 }, { 5092, 203.0221, -37.6008, 6.16 },
+ { 5093, 203.3988, -64.3675, 6.37 }, { 5094, 203.0117, -17.2711, 6.01 }, { 5095, 202.9913,  -5.7442, 4.69 }, { 5096, 202.8158, +42.1061, 6.08 },
+ { 5097, 203.1496, -27.3072, 5.69 }, { 5098, 203.1438, -28.4347, 6.45 }, { 5099, 203.2154, -14.6369, 5.55 }, { 5100, 203.2421,  -9.8350, 5.21 },
+ { 5101, 203.2529,  -6.8050, 6.68 }, { 5102, 203.2004, +24.3464, 6.11 }, { 5103, 203.6204, -47.7278, 6.33 }, { 5104, 203.6817, -32.6892, 6.44 },
+ { 5105, 203.5329,  +3.6589, 4.94 }, { 5106, 203.6687, -12.7856, 5.91 }, { 5107, 203.6733,  +0.5958, 3.37 }, { 5108, 203.5908, +38.7892, 6.37 },
+ { 5109, 203.5304, +55.3486, 5.60 }, { 5110, 203.6992, +37.1825, 4.98 }, { 5111, 203.8804,  -4.6039, 5.73 }, { 5112, 203.6138, +49.0161, 4.70 },
+ { 5113, 204.3008, -60.3081, 5.63 }, { 5114, 203.8887, +10.2047, 6.49 }, { 5115, 204.7996, -74.3161, 6.34 }, { 5116, 203.8088, +44.1969, 6.84 },
+ { 5117, 204.2104, -33.5322, 6.50 }, { 5118, 204.2750, -43.8567, 5.98 }, { 5119, 204.6904, -69.5550, 6.10 }, { 5120, 204.2017, -25.5050, 5.78 },
+ { 5121, 204.3488, -45.5717, 5.90 }, { 5122, 204.5317, -57.5850, 6.42 }, { 5123, 204.2463, +24.6133, 5.74 }, { 5124, 204.7046, -56.3769, 6.01 },
+ { 5125, 205.0025, -69.2117, 6.59 }, { 5126, 204.1658, +49.4867, 6.49 }, { 5127, 204.3650, +36.2950, 4.82 }, { 5128, 204.6750, -28.4392, 5.83 },
+ { 5129, 204.5329, +14.3017, 6.52 }, { 5130, 205.0454, -63.4231, 5.79 }, { 5131, 203.6783, +76.5467, 6.57 }, { 5132, 204.9717, -52.5336, 2.30 },
+ { 5133, 204.4292, +50.7147, 6.48 }, { 5134, 204.9988, -48.0497, 6.00 }, { 5135, 204.9200, -38.2519, 6.27 }, { 5136, 204.9525, -39.9481, 5.60 },
+ { 5137, 204.7596, +18.2653, 6.48 }, { 5138, 204.8942, +10.7461, 5.57 }, { 5139, 204.2958, +71.2422, 5.50 }, { 5140, 205.5046, -57.2128, 5.38 },
+ { 5141, 205.4363, -53.4400, 5.01 }, { 5142, 204.8767, +52.9214, 5.46 }, { 5143, 205.0650, +31.0119, 6.21 }, { 5144, 205.1687, +19.9556, 5.75 },
+ { 5145, 205.1629, +28.0653, 6.23 }, { 5146, 205.3788, -22.5503, 6.59 }, { 5147, 205.4404, -32.4031, 6.05 }, { 5148, 205.0967, +50.5194, 6.32 },
+ { 5149, 205.2596, +22.4958, 5.62 }, { 5150, 205.4033,  -7.2969, 5.01 }, { 5151, 205.7337, -55.2319, 6.00 }, { 5152, 205.7275, -49.2094, 6.41 },
+ { 5153, 205.0888, +57.2075, 6.29 }, { 5154, 205.1846, +54.6817, 4.66 }, { 5155, 205.7292, -40.5989, 5.98 }, { 5156, 205.5529,  +8.3883, 6.16 },
+ { 5157, 205.9167, -41.9325, 5.98 }, { 5158, 206.0663, -50.9869, 6.47 }, { 5159, 205.7654,  +3.5381, 5.36 }, { 5160, 205.6200, +41.6742, 6.30 },
+ { 5161, 205.6808, +34.9889, 5.98 }, { 5162, 205.3746, +64.8225, 5.85 }, { 5163, 205.9762,  -4.5011, 6.51 }, { 5164, 205.9383, +22.7003, 6.13 },
+ { 5165, 206.1242, -15.8208, 5.60 }, { 5166, 206.1904, -24.4992, 6.21 }, { 5167, 206.4038, -25.8839, 5.81 }, { 5168, 206.4217, -32.9561, 4.23 },
+ { 5169, 205.9779, +52.0644, 6.02 }, { 5170, 206.3963, -14.2325, 6.19 }, { 5171, 206.7946, -61.4100, 6.51 }, { 5172, 206.6637, -50.5672, 4.65 },
+ { 5173, 206.4846, -11.5733, 5.51 }, { 5174, 206.7350, -35.7481, 5.15 }, { 5175, 206.8650, -49.7506, 5.91 }, { 5176, 206.9100, -49.6789, 5.45 },
+ { 5177, 206.3050, +55.8794, 6.50 }, { 5178, 206.8063,  -8.2908, 6.05 }, { 5179, 206.5563, +41.0886, 5.87 }, { 5180, 206.5792, +38.5039, 5.94 },
+ { 5181, 206.8558, -16.1400, 5.43 }, { 5182, 206.6804, +25.7022, 5.95 }, { 5183, 206.7379,  +6.3506, 6.33 }, { 5184, 205.6637, +78.0644, 5.91 },
+ { 5185, 206.8154, +17.4567, 4.50 }, { 5186, 206.7492, +38.5428, 5.50 }, { 5187, 206.6488, +54.4328, 5.70 }, { 5188, 208.9113, -81.3339, 5.95 },
+ { 5189, 207.2296, -34.2961, 6.53 }, { 5190, 207.3763, -40.3122, 3.41 }, { 5191, 206.8850, +49.3133, 1.86 }, { 5192, 207.3613, -33.5492, 4.19 },
+ { 5193, 207.4042, -41.5261, 3.04 }, { 5194, 207.9475, -68.5986, 5.75 }, { 5195, 207.1613, +31.1903, 5.62 }, { 5196, 207.4679, -17.8658, 4.97 },
+ { 5197, 207.5271, -28.9186, 6.18 }, { 5198, 207.5808, -38.0989, 6.44 }, { 5199, 207.2383, +39.5428, 7.40 }, { 5200, 207.3692, +15.7978, 4.07 },
+ { 5201, 207.4283, +21.2642, 4.91 }, { 5202, 207.6438, -18.1028, 6.53 }, { 5203, 205.5963, +82.7525, 5.98 }, { 5204, 207.4375, +36.6328, 6.38 },
+ { 5205, 207.6029,  +5.4972, 6.01 }, { 5206, 207.9467, -45.1008, 5.77 }, { 5207, 208.0200, -51.1883, 5.25 }, { 5208, 207.9025, -35.5667, 6.35 },
+ { 5209, 207.8350, -23.6092, 6.45 }, { 5210, 207.9567, -31.0056, 4.56 }, { 5211, 207.9588, -31.0053, 6.06 }, { 5212, 208.0038, -30.3806, 6.12 },
+ { 5213, 207.4396, +61.4892, 5.96 }, { 5214, 207.7688, +34.7725, 6.65 }, { 5215, 207.7883, +34.6644, 5.87 }, { 5216, 207.6154, +58.5394, 6.46 },
+ { 5217, 208.4296, -52.6264, 5.89 }, { 5218, 208.7038, -66.3475, 5.71 }, { 5219, 207.9479, +34.4442, 4.74 }, { 5220, 208.0767, +12.1653, 6.04 },
+ { 5221, 208.3021, -30.0722, 4.73 }, { 5222, 208.3867, -34.3358, 5.54 }, { 5223, 208.4871, -46.8719, 6.10 }, { 5224, 208.4675, -34.6856, 6.19 },
+ { 5225, 208.3038, +17.9328, 5.70 }, { 5226, 207.8579, +64.7233, 4.65 }, { 5227, 207.7467, +68.3153, 6.40 }, { 5228, 208.5692, -27.4303, 6.04 },
+ { 5229, 208.2929, +28.6481, 5.90 }, { 5230, 208.8008, -51.8389, 5.71 }, { 5231, 208.8850, -46.7117, 2.55 }, { 5232, 208.6754,  -0.4969, 5.15 },
+ { 5233, 208.7425,  -7.9411, 6.19 }, { 5234, 209.0825, -53.8681, 6.14 }, { 5235, 208.6712, +18.3978, 2.68 }, { 5236, 209.1375, -53.2956, 6.00 },
+ { 5237, 208.9354, -30.7150, 6.51 }, { 5238, 208.4625, +53.7286, 5.70 }, { 5239, 209.0813, -45.4075, 5.83 }, { 5240, 210.1367, -77.4100, 6.09 },
+ { 5241, 209.4121, -62.3133, 4.71 }, { 5242, 209.6300, -64.1994, 6.20 }, { 5243, 208.9583, +14.0564, 6.16 }, { 5244, 209.1163,  +1.0506, 5.91 },
+ { 5245, 209.0437, +32.0325, 6.32 }, { 5246, 209.3654, -22.9772, 6.14 }, { 5247, 209.1425, +27.4919, 5.01 }, { 5248, 209.5679, -41.8992, 3.83 },
+ { 5249, 209.6700, -43.1964, 3.87 }, { 5250, 209.6296, -23.0278, 5.15 }, { 5251, 209.8221, -49.6300, 5.91 }, { 5252, 210.0721, -60.5186, 6.49 },
+ { 5253, 210.2175, -65.7314, 5.97 }, { 5254, 209.6662, +14.6494, 6.00 }, { 5255, 209.6621, +21.6961, 5.76 }, { 5256, 209.3837, +61.4928, 6.37 },
+ { 5257, 210.0004, -24.9897, 5.77 }, { 5258, 209.9554,  -2.4503, 6.40 }, { 5259, 210.3292, -39.7778, 6.13 }, { 5260, 210.4308, -44.3964, 4.34 },
+ { 5261, 211.3325, -75.2033, 5.50 }, { 5262, 210.3350,  +8.8947, 5.99 }, { 5263, 210.2937, +27.3867, 6.23 }, { 5264, 210.4117,  +1.5444, 4.26 },
+ { 5265, 210.5950, -26.5700, 5.48 }, { 5266, 210.8592, -55.7864, 5.92 }, { 5267, 210.9558, -59.6269, 0.61 }, { 5268, 210.7571, -30.3161, 6.18 },
+ { 5269, 210.8646, -40.5767, 6.11 }, { 5270, 210.6325,  +9.6864, 6.20 }, { 5271, 210.5508, +45.7536, 6.27 }, { 5272, 210.9713, -21.5783, 6.30 },
+ { 5273, 210.8846, +10.7867, 6.30 }, { 5274, 210.9033,  +7.5464, 6.26 }, { 5275, 210.9825,  +4.9008, 6.24 }, { 5276, 211.0608,  -4.6186, 6.39 },
+ { 5277, 211.1125, -13.0283, 6.28 }, { 5278, 211.4437, -53.3306, 6.17 }, { 5279, 212.1129, -73.1497, 6.02 }, { 5280, 210.7488, +50.9719, 6.15 },
+ { 5281, 211.6046, -58.2844, 6.42 }, { 5282, 210.4608, +68.6786, 6.34 }, { 5283, 211.1563,  +2.2975, 6.28 }, { 5284, 211.3083, -15.6642, 6.56 },
+ { 5285, 211.5117, -40.8203, 4.36 }, { 5286, 211.5454, -42.9081, 6.20 }, { 5287, 211.5929, -25.3175, 3.27 }, { 5288, 211.6708, -35.6300, 2.06 },
+ { 5289, 212.0596, -62.7919, 6.40 }, { 5290, 211.6783,  -8.6867, 5.46 }, { 5291, 211.0971, +64.3758, 3.65 }, { 5292, 212.2346, -58.7233, 6.34 },
+ { 5293, 212.6288, -69.6944, 6.05 }, { 5294, 212.2163, -42.5289, 6.17 }, { 5295, 212.7579, -68.2803, 6.06 }, { 5296, 212.3958, -50.4953, 6.00 },
+ { 5297, 212.4783, -52.5608, 4.75 }, { 5298, 212.2525,  -9.6656, 6.47 }, { 5299, 211.9825, +43.8544, 5.27 }, { 5300, 212.0721, +49.4581, 5.25 },
+ { 5301, 212.7104, -15.6981, 4.91 }, { 5302, 212.1917, +59.3378, 6.46 }, { 5303, 214.5575, -80.9922, 4.91 }, { 5304, 212.5996, +25.0917, 4.83 },
+ { 5305, 211.7350, +74.5936, 6.45 }, { 5306, 214.2287, -76.3361, 6.47 }, { 5307, 212.8800,  +1.3622, 6.43 }, { 5308, 213.3183, -52.3342, 5.56 },
+ { 5309, 213.1021, -23.6358, 6.34 }, { 5310, 212.8129, +32.2956, 6.11 }, { 5311, 213.4162, -53.3742, 6.11 }, { 5312, 213.1917, -26.7389, 5.08 },
+ { 5313, 213.0658,  +2.4094, 5.01 }, { 5314, 213.3050, -25.3878, 6.24 }, { 5315, 213.2242,  -9.7264, 4.19 }, { 5316, 213.7375, -56.9142, 5.07 },
+ { 5317, 213.4200,  +0.8456, 5.91 }, { 5318, 213.6775, -40.1625, 5.61 }, { 5319, 213.8383, -52.4903, 6.39 }, { 5320, 214.1608, -65.4122, 5.75 },
+ { 5321, 212.2121, +77.5475, 4.82 }, { 5322, 213.5888,  -4.0525, 6.36 }, { 5323, 213.5217, +12.9594, 5.54 }, { 5324, 213.7554, -28.7181, 6.08 },
+ { 5325, 213.9117, -44.9992, 6.31 }, { 5326, 214.1425, -58.0861, 6.39 }, { 5327, 216.0971, -81.1514, 6.42 }, { 5328, 213.3654, +51.7878, 6.69 },
+ { 5329, 213.3708, +51.7903, 4.54 }, { 5330, 213.7117, +10.1006, 5.29 }, { 5331, 213.7208,  +3.3361, 6.45 }, { 5332, 213.8504, -17.7992, 5.43 },
+ { 5333, 213.6708, +21.8733, 6.39 }, { 5334, 213.0167, +69.4325, 5.24 }, { 5335, 213.5979, +41.5189, 6.24 }, { 5336, 215.5946, -79.8911, 5.06 },
+ { 5337, 214.0762, -32.7586, 6.55 }, { 5338, 214.0038,  -5.9994, 4.08 }, { 5339, 216.7287, -82.3322, 4.32 }, { 5340, 213.9154, +19.1825, -0.04 },
+ { 5341, 214.0896,  -5.3781, 6.44 }, { 5342, 214.1254,  -2.8036, 6.15 }, { 5343, 214.0175, +18.9119, 5.98 }, { 5344, 214.2658, -17.4147, 6.22 },
+ { 5345, 213.8204, +52.5358, 6.58 }, { 5346, 214.1367, +20.1214, 6.25 }, { 5347, 214.1008, +39.7447, 6.38 }, { 5348, 214.5992, -32.7794, 6.54 },
+ { 5349, 214.9646, -60.7269, 5.23 }, { 5350, 214.0412, +51.3672, 4.75 }, { 5351, 214.0958, +46.0883, 4.18 }, { 5352, 214.3683, +15.2633, 5.80 },
+ { 5353, 214.5025,  -6.4575, 6.47 }, { 5354, 214.8508, -45.9422, 3.55 }, { 5355, 214.6596, -17.2839, 5.90 }, { 5356, 214.7533, -24.1844, 5.87 },
+ { 5357, 214.8496, -36.9964, 5.94 }, { 5358, 215.0813, -55.6133, 4.33 }, { 5359, 214.7775, -12.6289, 4.52 }, { 5360, 214.3379, +51.3072, 6.20 },
+ { 5361, 214.4992, +35.5094, 4.81 }, { 5362, 215.0404, -42.9411, 5.56 }, { 5363, 214.4550, +48.0017, 6.32 }, { 5364, 215.1771, -44.8128, 4.77 },
+ { 5365, 214.8179, +13.0042, 5.41 }, { 5366, 214.8854,  -1.7344, 5.14 }, { 5367, 215.1392, -36.1147, 4.05 }, { 5368, 214.9204,  +0.3842, 6.19 },
+ { 5369, 214.7321, +38.7675, 6.86 }, { 5370, 214.9383, +16.3069, 4.86 }, { 5371, 215.6542, -57.5406, 4.92 }, { 5372, 214.7325, +54.8642, 6.53 },
+ { 5373, 214.9487, +38.7939, 6.33 }, { 5374, 215.0363, +30.4292, 6.44 }, { 5375, 215.6613, -47.6797, 6.09 }, { 5376, 215.5821, -33.2131, 5.56 },
+ { 5377, 215.8346, -49.2278, 6.02 }, { 5378, 215.7592, -38.4878, 4.42 }, { 5379, 216.2763, -67.8047, 5.61 }, { 5380, 215.9517, -52.8233, 6.00 },
+ { 5381, 215.7742, -26.2461, 4.77 }, { 5382, 216.4146, -65.8267, 6.36 }, { 5383, 215.8567, -10.2858, 6.21 }, { 5384, 215.8138,  +1.2417, 6.27 },
+ { 5385, 215.8442,  +8.4450, 6.86 }, { 5386, 215.8446,  +8.4467, 5.12 }, { 5387, 215.7783, +25.3381, 6.22 }, { 5388, 216.0038,  +8.2436, 5.95 },
+ { 5389, 217.4033, -75.2708, 6.07 }, { 5390, 216.2025, -23.1936, 5.32 }, { 5391, 216.7796, -64.1783, 5.85 }, { 5392, 216.0471,  +5.8200, 5.10 },
+ { 5393, 216.1704, -10.3303, 6.49 }, { 5394, 216.0762,  +8.0850, 6.19 }, { 5395, 216.5342, -44.7786, 4.56 }, { 5396, 216.5450, -44.6206, 4.35 },
+ { 5397, 216.3742, -18.0303, 6.61 }, { 5398, 216.5558, -41.6808, 6.32 }, { 5399, 216.4487, -25.1475, 6.48 }, { 5400, 216.7079, -38.1261, 6.35 },
+ { 5401, 216.8008, -45.8656, 5.83 }, { 5402, 216.3717, +38.3931, 6.27 }, { 5403, 217.1813, -58.8022, 6.45 }, { 5404, 216.2992, +51.8508, 4.05 },
+ { 5405, 216.6142, +19.2269, 5.39 }, { 5406, 216.8517,  -5.8797, 6.17 }, { 5407, 217.0433, -28.5083, 4.97 }, { 5408, 217.8187, -66.2828, 5.83 },
+ { 5409, 217.0504,  -1.7719, 4.81 }, { 5410, 217.1738,  -5.0994, 5.42 }, { 5411, 216.8638, +41.0250, 6.63 }, { 5412, 217.5358, -44.6783, 5.50 },
+ { 5413, 217.5871, -48.4808, 5.37 }, { 5414, 217.1312, +28.2892, 7.62 }, { 5415, 217.1387, +28.2908, 7.12 }, { 5416, 217.0683, +36.1969, 6.10 },
+ { 5417, 217.7354, -39.1550, 6.39 }, { 5418, 217.4604,  +0.8289, 5.94 }, { 5419, 217.7950, -37.1303, 5.97 }, { 5420, 217.1575, +49.8447, 5.59 },
+ { 5421, 218.1371, -55.1122, 6.93 }, { 5422, 217.4571, +31.7911, 6.06 }, { 5423, 217.4033, +41.7958, 6.35 }, { 5424, 217.6892,  +4.7722, 6.02 },
+ { 5425, 218.1538, -49.5431, 4.42 }, { 5426, 218.3850, -53.0017, 5.87 }, { 5427, 218.3746, -51.3200, 5.87 }, { 5428, 218.2900, -29.2858, 6.09 },
+ { 5429, 217.9575, +30.3714, 3.58 }, { 5430, 216.8812, +75.6961, 4.25 }, { 5431, 218.5333, -41.9003, 6.60 }, { 5432, 218.8217, -59.9842, 6.40 },
+ { 5433, 218.0842, +26.6772, 6.01 }, { 5434, 218.1354, +22.2600, 5.92 }, { 5435, 218.0196, +38.3083, 3.03 }, { 5436, 217.6921, +63.1856, 6.09 },
+ { 5437, 217.9283, +60.2256, 6.27 }, { 5438, 218.7113, -19.5608, 6.50 }, { 5439, 218.8812, -40.4828, 5.87 }, { 5440, 218.8767, -41.8422, 2.31 },
+ { 5441, 218.3346, +36.9594, 6.43 }, { 5442, 218.1288, +55.3978, 5.76 }, { 5443, 219.4429, -66.0678, 6.04 }, { 5444, 219.0792, -45.7547, 5.55 },
+ { 5445, 218.5488, +32.5344, 6.33 }, { 5446, 219.1008, -38.4028, 6.13 }, { 5447, 218.6700, +29.7450, 4.46 }, { 5448, 218.6604, +36.6258, 6.03 },
+ { 5449, 219.1842, -39.7883, 5.74 }, { 5450, 219.3338, -45.8661, 5.41 }, { 5451, 218.5663, +57.0653, 6.48 }, { 5452, 218.6650, +49.3683, 5.74 },
+ { 5453, 219.4717, -48.5742, 4.05 }, { 5454, 219.0288, +23.2503, 6.38 }, { 5455, 219.2492, -11.6947, 6.20 }, { 5456, 219.5817, -37.2058, 6.02 },
+ { 5457, 219.7958, -45.4158, 6.07 }, { 5458, 219.8529, -48.9444, 6.39 }, { 5459, 219.8996, -59.1647, -0.01 }, { 5460, 219.9004, -59.1644, 1.33 },
+ { 5461, 220.1367, -55.5592, 6.30 }, { 5462, 219.5583, +18.2983, 5.91 }, { 5463, 220.6267, -63.0247, 3.19 }, { 5464, 219.5521, +43.6419, 5.70 },
+ { 5465, 220.4821, -57.3839, 6.22 }, { 5466, 220.2558, -35.8650, 5.67 }, { 5467, 219.5633, +54.0233, 5.85 }, { 5468, 219.7092, +44.4044, 5.39 },
+ { 5469, 220.4825, -46.6117, 2.30 }, { 5470, 221.9650, -78.9553, 3.83 }, { 5471, 220.4900, -36.2064, 4.00 }, { 5472, 220.0913, +21.9756, 6.10 },
+ { 5473, 220.1767, +13.5342, 5.91 }, { 5474, 220.4629, -29.0667, 6.37 }, { 5475, 220.1817, +16.4183, 4.94 }, { 5476, 220.1829, +16.4178, 5.88 },
+ { 5477, 220.2871, +13.7283, 4.83 }, { 5478, 220.2871, +13.7283, 4.43 }, { 5479, 218.4096, +79.6603, 6.26 }, { 5480, 220.4117,  +8.1617, 4.86 },
+ { 5481, 220.4313, +11.6606, 5.56 }, { 5482, 221.3221, -61.1242, 5.36 }, { 5483, 220.4758, +21.1236, 6.38 }, { 5484, 220.8067, -23.0025, 5.73 },
+ { 5485, 220.9142, -34.8264, 4.05 }, { 5486, 221.2312, -57.5222, 6.11 }, { 5487, 220.7650,  -4.3417, 3.88 }, { 5488, 221.2954, -54.3981, 6.10 },
+ { 5489, 221.2467, -34.8081, 4.92 }, { 5490, 220.8558, +26.5278, 4.81 }, { 5491, 232.0796, -87.8669, 6.48 }, { 5492, 220.5133, +61.2619, 6.25 },
+ { 5493, 220.9350, +40.4592, 5.73 }, { 5494, 221.6213, -46.5589, 5.74 }, { 5495, 221.7554, -51.6164, 5.21 }, { 5496, 221.2988,  -0.5822, 6.07 },
+ { 5497, 221.5004, -24.5569, 4.94 }, { 5498, 221.8013, -51.7944, 6.07 }, { 5499, 221.5283, -22.8469, 5.81 }, { 5500, 222.1850, -65.4061, 5.91 },
+ { 5501, 221.3758,  +0.7172, 5.69 }, { 5502, 221.3104, +16.9644, 4.60 }, { 5503, 221.4908, -14.5403, 6.33 }, { 5504, 221.5454, -20.8239, 6.40 },
+ { 5505, 221.2467, +27.0750, 5.12 }, { 5506, 221.2467, +27.0742, 2.70 }, { 5507, 221.3363, +18.8847, 6.13 }, { 5508, 221.7713, -37.7092, 5.94 },
+ { 5509, 221.8837, -42.4425, 6.30 }, { 5510, 221.3071, +32.7883, 6.28 }, { 5511, 221.5621,  +1.8928, 3.72 }, { 5512, 221.5250, +15.1319, 5.63 },
+ { 5513, 221.8071, -20.6753, 6.06 }, { 5514, 221.8438, -24.3756, 5.63 }, { 5515, 222.2788, -55.3322, 6.23 }, { 5516, 221.9367, -25.9125, 5.24 },
+ { 5517, 221.9896, -25.3536, 5.77 }, { 5518, 221.9787, -11.1603, 6.35 }, { 5519, 222.1588, -35.3653, 6.04 }, { 5520, 223.3071, -72.8100, 5.60 },
+ { 5521, 222.3279, -23.7483, 5.68 }, { 5522, 222.2254,  +0.8478, 6.14 }, { 5523, 222.3296, -13.8511, 5.31 }, { 5524, 222.0971, +24.3667, 6.14 },
+ { 5525, 225.4617, -82.7722, 5.65 }, { 5526, 222.5721, -26.0397, 4.41 }, { 5527, 223.1458, -62.1900, 5.87 }, { 5528, 222.9100, -42.4244, 4.32 },
+ { 5529, 222.2779, +37.8111, 6.16 }, { 5530, 222.6717, -14.0028, 5.15 }, { 5531, 222.7196, -15.9583, 2.75 }, { 5532, 222.4933, +28.6158, 5.80 },
+ { 5533, 222.3279, +46.1161, 5.74 }, { 5534, 222.5658, +23.9119, 5.85 }, { 5535, 222.7542,  -1.7008, 4.94 }, { 5536, 222.7504,  +0.2572, 6.18 },
+ { 5537, 222.3846, +51.3747, 6.51 }, { 5538, 222.4221, +48.7206, 5.69 }, { 5539, 223.6767, -64.0086, 6.09 }, { 5540, 224.4704, -75.3372, 5.34 },
+ { 5541, 222.6233, +37.2719, 5.48 }, { 5542, 223.1379, -29.4231, 6.29 }, { 5543, 223.2129, -36.1967, 5.03 }, { 5544, 222.8471, +19.1011, 4.55 },
+ { 5545, 226.1946, -82.9617, 5.65 }, { 5546, 223.8942, -59.8858, 5.20 }, { 5547, 225.0492, -76.8397, 5.93 }, { 5548, 223.5838, -23.3578, 5.30 },
+ { 5549, 223.6583, -32.6994, 5.82 }, { 5550, 223.3471, +15.7044, 6.40 }, { 5551, 224.1833, -61.2192, 5.11 }, { 5552, 222.8600, +59.2939, 5.46 },
+ { 5553, 223.3488, +19.1528, 6.01 }, { 5554, 223.5954, -10.1017, 5.80 }, { 5555, 224.9833, -74.9675, 6.20 }, { 5556, 224.0721, -51.1903, 5.38 },
+ { 5557, 227.7846, -83.2125, 5.91 }, { 5558, 223.9363, -32.1442, 5.32 }, { 5559, 224.1333, -46.1208, 5.64 }, { 5560, 224.2558, -50.5531, 6.64 },
+ { 5561, 224.1492, -38.5839, 6.36 }, { 5562, 224.1288, -31.3633, 6.06 }, { 5563, 222.6763, +74.1556, 2.08 }, { 5564, 224.1921, -10.5903, 5.46 },
+ { 5565, 224.3067, -28.8422, 6.29 }, { 5566, 224.5367, -47.1369, 6.35 }, { 5567, 224.0550, +14.4464, 5.77 }, { 5568, 224.3667, -20.5844, 5.74 },
+ { 5569, 223.9946, +32.3003, 6.12 }, { 5570, 224.2958,  -3.6536, 4.49 }, { 5571, 224.6329, -42.8661, 2.68 }, { 5572, 224.6533, -38.0933, 6.15 },
+ { 5573, 224.3887,  +0.1675, 5.53 }, { 5574, 224.2650, +21.5553, 6.49 }, { 5575, 224.2988, +16.3883, 5.71 }, { 5576, 224.7904, -41.8958, 3.13 },
+ { 5577, 224.6633, -26.3428, 5.65 }, { 5578, 224.5558, -10.8450, 6.60 }, { 5579, 224.8079, -36.1186, 6.47 }, { 5580, 224.8629, -42.8400, 6.10 },
+ { 5581, 224.0958, +49.6286, 5.63 }, { 5582, 224.7233, -10.8558, 5.87 }, { 5583, 224.7200,  -3.0108, 6.09 }, { 5584, 224.8463,  +4.5678, 5.93 },
+ { 5585, 225.3042, -37.9417, 5.89 }, { 5586, 225.2433,  -7.4811, 4.92 }, { 5587, 225.4921, -33.6411, 6.22 }, { 5588, 224.9038, +39.2653, 5.64 },
+ { 5589, 224.3958, +65.9325, 4.60 }, { 5590, 225.3325,  -1.2450, 5.52 }, { 5591, 225.5267, -27.9394, 5.85 }, { 5592, 225.2183, +22.0456, 6.38 },
+ { 5593, 226.2008, -63.9683, 5.17 }, { 5594, 225.4538,  +0.1406, 5.71 }, { 5595, 225.7471, -31.3567, 5.44 }, { 5596, 222.5850, +82.5119, 5.64 },
+ { 5597, 225.1613, +47.2778, 6.37 }, { 5598, 226.7863, -70.0947, 6.52 }, { 5599, 225.6871,  -2.9686, 6.61 }, { 5600, 225.5271, +25.0081, 4.81 },
+ { 5601, 225.7250,  +2.0914, 4.40 }, { 5602, 225.4867, +40.3906, 3.50 }, { 5603, 226.0175, -24.7181, 3.29 }, { 5604, 226.1788, -39.1386, 6.41 },
+ { 5605, 226.2800, -46.9489, 4.72 }, { 5606, 226.2800, -46.9489, 4.82 }, { 5607, 226.3296, -40.9328, 5.15 }, { 5608, 225.3629, +60.2044, 5.93 },
+ { 5609, 225.7754, +35.2058, 5.51 }, { 5610, 226.0267,  +5.4925, 6.50 }, { 5611, 226.9867, -64.7244, 6.17 }, { 5612, 225.7775, +44.6444, 6.65 },
+ { 5613, 225.9021, +34.5661, 6.59 }, { 5614, 226.4487, -24.2103, 6.67 }, { 5615, 226.5579, -35.7358, 6.27 }, { 5616, 226.1113, +26.9475, 4.54 },
+ { 5617, 226.8579, -48.9117, 5.77 }, { 5618, 225.9475, +47.6544, 4.76 }, { 5619, 226.6387, -29.0811, 5.96 }, { 5620, 226.6129, -21.9681, 6.17 },
+ { 5621, 227.3746, -66.9158, 5.76 }, { 5622, 226.6567, -15.7431, 5.20 }, { 5623, 227.3562, -62.3572, 6.28 }, { 5624, 227.0504, -39.4161, 5.79 },
+ { 5625, 227.1629, -41.1322, 5.85 }, { 5626, 227.2108, -44.7203, 4.05 }, { 5627, 226.3575, +48.1511, 5.57 }, { 5628, 228.1408, -71.2297, 6.01 },
+ { 5629, 225.9908, +65.9197, 6.13 }, { 5630, 226.6463, +36.4556, 6.35 }, { 5631, 226.9179,  +5.4981, 6.16 }, { 5632, 227.6858, -60.5775, 6.30 },
+ { 5633, 226.8350, +18.4417, 6.02 }, { 5634, 226.8254, +24.8692, 4.93 }, { 5635, 226.5696, +54.5564, 5.25 }, { 5636, 227.5313, -37.2075, 5.98 },
+ { 5637, 227.8167, -54.6539, 5.54 }, { 5638, 227.0992, +26.3011, 5.67 }, { 5639, 227.2225, +13.2350, 6.10 }, { 5640, 227.1479, +25.1086, 5.81 },
+ { 5641, 227.5775, -25.6672, 5.76 }, { 5642, 227.8954, -44.7225, 6.44 }, { 5643, 227.8829, -44.7206, 7.39 }, { 5644, 228.5796, -69.9206, 5.81 },
+ { 5645, 228.2542, -60.2561, 6.32 }, { 5646, 227.9837, -47.2622, 3.87 }, { 5647, 227.9900, -47.2564, 5.69 }, { 5648, 227.0813, +50.0550, 6.39 },
+ { 5649, 228.0712, -51.9008, 3.41 }, { 5650, 228.1304, -47.7814, 6.33 }, { 5651, 228.2063, -43.4994, 4.82 }, { 5652, 228.0554, -18.2083, 4.54 },
+ { 5653, 228.2808, -35.9086, 6.10 }, { 5654, 228.0179, +18.9758, 5.89 }, { 5655, 228.3229, -23.9917, 6.47 }, { 5656, 228.3300, -18.3525, 6.08 },
+ { 5657, 228.3696, -24.6908, 6.45 }, { 5658, 228.4721, -25.8064, 5.84 }, { 5659, 228.1813, +19.2858, 6.68 }, { 5660, 228.6554, -30.4808, 4.91 },
+ { 5661, 229.1517, -59.0961, 5.73 }, { 5662, 228.6404, -16.2314, 6.17 }, { 5663, 228.9742, -47.9258, 5.95 }, { 5664, 229.2363, -59.0425, 5.09 },
+ { 5665, 228.3829, +22.9833, 6.30 }, { 5666, 229.4121, -62.3894, 4.86 }, { 5667, 229.0167, -40.5089, 5.16 }, { 5668, 229.0437, -42.5153, 6.04 },
+ { 5669, 228.7113,  -4.4972, 6.28 }, { 5670, 229.3783, -57.1989, 4.07 }, { 5671, 229.7275, -67.3206, 2.89 }, { 5672, 227.6838, +67.7814, 6.17 },
+ { 5673, 228.3983, +38.2647, 6.20 }, { 5674, 228.5254, +31.7881, 5.99 }, { 5675, 228.7975,  +4.9394, 5.33 }, { 5676, 228.6217, +29.1642, 5.26 },
+ { 5677, 228.5429, +42.1714, 6.13 }, { 5678, 229.0958, -21.6006, 5.50 }, { 5679, 228.9546,  +0.3722, 5.63 }, { 5680, 229.7038, -59.5036, 5.46 },
+ { 5681, 228.8758, +33.3147, 3.47 }, { 5682, 229.5392, -40.9392, 6.28 }, { 5683, 229.6333, -46.1250, 4.27 }, { 5684, 230.1696, -66.5186, 6.28 },
+ { 5685, 229.2517,  -8.6169, 2.61 }, { 5686, 229.4579, -29.8511, 4.34 }, { 5687, 229.7350, -39.2117, 5.59 }, { 5688, 229.6721, -30.7906, 6.18 },
+ { 5689, 229.8817, -36.9033, 6.20 }, { 5690, 229.6092,  +0.4614, 5.89 }, { 5691, 228.6596, +67.3467, 5.13 }, { 5692, 229.6021, +20.5728, 5.70 },
+ { 5693, 228.7163, +68.9453, 6.51 }, { 5694, 229.8283,  +1.7653, 5.06 }, { 5695, 230.3429, -39.3525, 3.22 }, { 5696, 230.3971, -39.2503, 6.20 },
+ { 5697, 230.3754, -37.7808, 6.48 }, { 5698, 230.5346, -46.0722, 5.00 }, { 5699, 230.4508, -47.6822, 5.65 }, { 5700, 230.7933, -59.3431, 5.67 },
+ { 5701, 230.2238, -17.8414, 6.17 }, { 5702, 229.8758, +32.5153, 6.32 }, { 5703, 230.2558, -14.4517, 6.30 }, { 5704, 230.8446, -58.6792, 4.51 },
+ { 5705, 230.4517, -35.7386, 3.56 }, { 5706, 230.1962,  -1.5867, 6.35 }, { 5707, 230.2817,  -4.1753, 5.54 }, { 5708, 230.6704, -43.3106, 3.37 },
+ { 5709, 230.0354, +29.6161, 5.51 }, { 5710, 230.2583,  +0.7153, 5.35 }, { 5711, 230.2788, +24.9578, 6.39 }, { 5712, 230.7892, -35.1414, 4.54 },
+ { 5713, 231.5613, -67.6908, 5.89 }, { 5714, 229.2746, +71.8239, 5.02 }, { 5715, 230.0217, +51.9586, 5.66 }, { 5716, 230.1733, +44.4342, 6.19 },
+ { 5717, 230.5967, +12.5675, 6.28 }, { 5718, 230.4525, +32.9339, 5.37 }, { 5719, 231.1871, -38.2897, 5.37 }, { 5720, 230.9675, -11.6306, 5.72 },
+ { 5721, 230.9321,  -0.9775, 6.12 }, { 5722, 231.2775, -37.8306, 7.03 }, { 5723, 231.0496,  -9.6778, 4.94 }, { 5724, 231.3342, -37.2664, 4.60 },
+ { 5725, 231.8879, -63.4686, 5.71 }, { 5726, 230.6558, +39.5814, 5.50 }, { 5727, 230.8013, +30.2878, 5.58 }, { 5728, 230.8013, +30.2878, 6.08 },
+ { 5729, 235.8200, -83.5347, 5.57 }, { 5730, 232.8783, -72.6106, 5.49 }, { 5731, 230.6554, +62.0472, 5.98 }, { 5732, 231.0213, +45.2711, 6.01 },
+ { 5733, 231.1225, +37.3772, 4.31 }, { 5734, 231.1288, +37.3478, 6.50 }, { 5735, 230.1821, +71.8339, 3.05 }, { 5736, 231.8258, -35.2322, 5.45 },
+ { 5737, 230.6600, +63.3414, 5.79 }, { 5738, 232.1133, -50.4025, 6.10 }, { 5739, 231.4475, +15.4281, 5.17 }, { 5740, 231.4721, +19.4808, 6.27 },
+ { 5741, 231.5725, +34.3358, 5.46 }, { 5742, 232.3512, -45.2672, 5.24 }, { 5743, 232.0642, -15.2836, 5.64 }, { 5744, 231.2325, +58.9661, 3.29 },
+ { 5745, 231.9121, +25.1017, 6.02 }, { 5746, 232.1592,  +1.8422, 5.17 }, { 5747, 231.9571, +29.1058, 3.68 }, { 5748, 231.6354, +54.0200, 6.45 },
+ { 5749, 232.6513, -19.2717, 6.22 }, { 5750, 232.6683, -15.3906, 5.82 }, { 5751, 233.0183, -37.3769, 6.25 }, { 5752, 232.1854, +47.2014, 6.15 },
+ { 5753, 232.9596, -31.1189, 6.46 }, { 5754, 231.9200, +62.2756, 6.50 }, { 5755, 231.9642, +60.6703, 5.90 }, { 5756, 232.9308, -19.8353, 6.22 },
+ { 5757, 234.8262, -76.0819, 6.18 }, { 5758, 232.7308,  +8.5792, 6.57 }, { 5759, 232.2367, +55.1950, 6.43 }, { 5760, 232.5946, +31.2861, 6.46 },
+ { 5761, 232.6163, +36.8042, 6.37 }, { 5762, 233.1529, -18.3294, 5.52 }, { 5763, 232.7325, +40.8331, 5.02 }, { 5764, 233.2300, -15.1472, 5.50 },
+ { 5765, 233.2879, -23.5106, 7.00 }, { 5766, 234.0725, -64.3867, 6.51 }, { 5767, 233.5067, -39.9339, 5.82 }, { 5768, 232.3383, +62.0997, 6.38 },
+ { 5769, 232.8433, +36.6164, 6.38 }, { 5770, 233.0404, +16.0561, 6.22 }, { 5771, 234.1800, -65.6831, 4.11 }, { 5772, 233.2413,  -0.8136, 5.51 },
+ { 5773, 233.5871, -38.6506, 6.36 }, { 5774, 232.9458, +40.8994, 5.02 }, { 5775, 233.6554, -27.9531, 5.15 }, { 5776, 233.7854, -40.8331, 2.78 },
+ { 5777, 233.5446,  -9.9356, 4.62 }, { 5778, 233.2325, +31.3592, 4.14 }, { 5779, 233.5867,  -4.3050, 6.51 }, { 5780, 233.6108,  -8.8167, 5.17 },
+ { 5781, 233.9717, -43.0414, 4.54 }, { 5782, 235.0883, -72.5533, 5.65 }, { 5783, 233.4700, +17.1378, 6.45 }, { 5784, 234.0504, -43.6031, 5.43 },
+ { 5785, 232.7321, +64.2086, 5.79 }, { 5786, 235.4775, -75.9181, 5.95 }, { 5787, 233.8817, -13.2106, 3.91 }, { 5788, 233.7004, +10.5375, 3.80 },
+ { 5789, 233.7004, +10.5392, 3.80 }, { 5790, 234.0475, -32.9072, 6.24 }, { 5791, 233.7692,  +1.6689, 6.56 }, { 5792, 235.0479, -69.7722, 6.44 },
+ { 5793, 233.6721, +26.7147, 2.23 }, { 5794, 234.2562, -27.8650, 3.58 }, { 5795, 233.8883, +17.6556, 6.12 }, { 5796, 233.9725, +11.2656, 6.07 },
+ { 5797, 234.5133, -41.4325, 4.33 }, { 5798, 234.7063, -51.6272, 5.44 }, { 5799, 234.1404,  +0.5617, 6.51 }, { 5800, 233.8125, +39.0100, 5.11 },
+ { 5801, 234.3688, -25.7200, 6.19 }, { 5802, 234.1233, +10.0100, 5.26 }, { 5803, 234.9854, -58.0917, 5.95 }, { 5804, 234.1221, +16.1189, 5.93 },
+ { 5805, 234.6362, -38.8392, 6.57 }, { 5806, 234.4504, -22.8583, 5.78 }, { 5807, 234.6763, -38.8719, 6.04 }, { 5808, 233.9554, +38.3739, 6.42 },
+ { 5809, 234.5654, -27.7933, 6.32 }, { 5810, 234.5679, -20.9839, 5.84 }, { 5811, 233.8179, +53.9219, 5.97 }, { 5812, 234.6642, -28.2222, 3.66 },
+ { 5813, 234.2225, +29.9911, 6.52 }, { 5814, 234.7271, -18.6981, 5.38 }, { 5815, 234.6667,  -7.2056, 6.50 }, { 5816, 234.6671,  -7.2089, 6.48 },
+ { 5817, 234.0171, +52.0697, 6.74 }, { 5818, 233.9879, +54.6306, 5.74 }, { 5819, 234.8388, -22.8497, 6.34 }, { 5820, 234.9417, -33.5881, 4.67 },
+ { 5821, 235.2429, -46.2644, 6.23 }, { 5822, 235.0642, -30.7864, 6.34 }, { 5823, 234.4567, +40.3533, 5.24 }, { 5824, 235.0704, -22.1819, 4.96 },
+ { 5825, 235.2971, -43.3389, 4.64 }, { 5826, 232.8537, +77.3494, 4.96 }, { 5827, 234.7038, +34.6750, 6.11 }, { 5828, 234.3833, +54.5089, 5.87 },
+ { 5829, 232.2958, +80.4486, 6.58 }, { 5830, 234.5675, +46.7978, 5.75 }, { 5831, 235.0433, +12.0531, 6.25 }, { 5832, 235.6550, -48.5106, 6.04 },
+ { 5833, 234.8425, +36.6367, 6.00 }, { 5834, 234.8446, +36.6358, 5.07 }, { 5835, 234.6429, +50.4233, 5.84 }, { 5836, 235.9796, -59.7128, 6.48 },
+ { 5837, 235.6596, -36.5750, 5.24 }, { 5838, 235.4867, -18.3211, 4.74 }, { 5839, 235.6708, -33.2894, 4.75 }, { 5840, 235.2467, +16.0247, 6.01 },
+ { 5841, 234.7896, +57.9244, 6.45 }, { 5842, 235.3879, +19.6703, 4.52 }, { 5843, 235.4475, +12.8475, 5.33 }, { 5844, 234.4129, +69.2833, 5.62 },
+ { 5845, 235.4779, +18.4639, 5.81 }, { 5846, 236.0942, -40.1806, 5.94 }, { 5847, 235.8537, -14.9567, 6.31 }, { 5848, 236.0183, -14.3272, 5.41 },
+ { 5849, 235.6858, +26.2956, 3.84 }, { 5850, 235.7942, +13.6678, 6.48 }, { 5851, 236.9733, -64.5575, 6.18 }, { 5852, 236.9738, -64.5575, 6.39 },
+ { 5853, 236.0075,  +2.5150, 5.88 }, { 5854, 236.0671,  +6.4256, 2.65 }, { 5855, 235.9971, +32.5158, 5.56 }, { 5856, 236.5533, -27.9383, 6.51 },
+ { 5857, 235.7113, +52.3608, 5.51 }, { 5858, 236.1754, +17.2642, 6.14 }, { 5859, 236.3479,  +5.4469, 5.58 }, { 5860, 236.6842, -33.3175, 5.61 },
+ { 5861, 236.4154,  +0.8914, 6.33 }, { 5862, 236.8558, -39.8058, 6.42 }, { 5863, 236.5233,  -0.1956, 5.40 }, { 5864, 236.8708, -36.0836, 6.01 },
+ { 5865, 237.2096, -51.5619, 6.07 }, { 5866, 236.6892,  -5.8797, 6.24 }, { 5867, 236.5471, +15.4219, 3.67 }, { 5868, 236.6108,  +7.3531, 4.43 },
+ { 5869, 237.5288, -52.7906, 5.77 }, { 5870, 236.8221, +14.1153, 5.71 }, { 5871, 237.4896, -47.0881, 5.84 }, { 5872, 237.5679, -44.5983, 6.12 },
+ { 5873, 237.7783, -54.9442, 5.73 }, { 5874, 237.0554, +13.7886, 6.00 }, { 5875, 237.2367,  -2.1814, 5.53 }, { 5876, 238.2363, -64.8475, 6.54 },
+ { 5877, 237.0083, +31.7358, 6.44 }, { 5878, 236.6450, +55.4747, 5.92 }, { 5879, 237.1850, +18.1417, 4.09 }, { 5880, 237.1433, +28.1567, 5.85 },
+ { 5881, 237.4050,  -2.5697, 3.53 }, { 5882, 237.8812, -46.9394, 6.01 }, { 5883, 237.7396, -32.3728, 3.95 }, { 5884, 238.3450, -61.3931, 6.19 },
+ { 5885, 237.7446, -24.2486, 4.64 }, { 5886, 236.6667, +62.5994, 5.19 }, { 5887, 236.9083, +55.3767, 5.86 }, { 5888, 237.5729,  +2.1964, 5.23 },
+ { 5889, 237.3988, +26.0683, 4.63 }, { 5890, 238.2146, -49.3847, 6.60 }, { 5891, 238.8733, -67.3969, 5.09 }, { 5892, 237.7042,  +4.4778, 3.71 },
+ { 5893, 238.0533, -28.1133, 6.40 }, { 5894, 237.6738, +15.1336, 5.20 }, { 5895, 237.8150,  -2.9094, 5.11 }, { 5896, 237.9100, -13.8664, 6.19 },
+ { 5897, 238.7854, -62.5694, 2.85 }, { 5898, 238.7192, -59.2567, 6.15 }, { 5899, 237.8163, +20.9778, 4.76 }, { 5900, 238.8846, -59.8222, 5.77 },
+ { 5901, 237.8079, +35.6575, 4.82 }, { 5902, 238.3338, -19.8328, 5.03 }, { 5903, 236.0146, +77.7944, 4.32 }, { 5904, 238.4029, -24.6728, 4.59 },
+ { 5905, 239.0250, -59.5172, 5.76 }, { 5906, 238.4742, -23.4669, 5.39 }, { 5907, 238.4825, -22.0219, 5.42 }, { 5908, 238.4563, -15.2706, 4.15 },
+ { 5909, 238.2342, +17.4036, 6.36 }, { 5910, 238.6250, -26.6614, 6.14 }, { 5911, 238.3004, +13.1967, 6.10 }, { 5912, 238.6646, -24.7564, 5.87 },
+ { 5913, 238.3954, +16.0750, 6.09 }, { 5914, 238.1687, +42.4517, 4.62 }, { 5915, 238.7513, -18.6169, 5.94 }, { 5916, 238.8767, -30.9164, 6.21 },
+ { 5917, 238.8754, -25.7342, 5.62 }, { 5918, 239.0271, -38.1358, 6.03 }, { 5919, 238.6679,  +8.5803, 6.29 }, { 5920, 239.7421, -64.9622, 5.75 },
+ { 5921, 239.2658, -47.8378, 6.31 }, { 5922, 238.0692, +55.8267, 5.81 }, { 5923, 239.0579, -30.2142, 6.29 }, { 5924, 238.6442, +20.3108, 5.44 },
+ { 5925, 239.2229, -32.0336, 5.12 }, { 5926, 239.2258, -32.0358, 5.62 }, { 5927, 239.0600, -13.6006, 6.37 }, { 5928, 239.2213, -28.7858, 3.88 },
+ { 5929, 239.3388, -35.8150, 5.80 }, { 5930, 239.1392, -13.1708, 6.13 }, { 5931, 238.9158, +18.6206, 6.26 }, { 5932, 238.6579, +43.1386, 5.37 },
+ { 5933, 239.1133, +15.6617, 3.85 }, { 5934, 239.4183, -19.0169, 5.85 }, { 5935, 239.6279, -36.4969, 6.31 }, { 5936, 238.9483, +37.9469, 5.45 },
+ { 5937, 239.9750, -53.9789, 6.10 }, { 5938, 238.8775, +42.5661, 5.75 }, { 5939, 240.2946, -62.2233, 6.41 }, { 5940, 239.3108, +14.4144, 5.54 },
+ { 5941, 239.5475, -13.7206, 4.88 }, { 5942, 239.6450, -23.1686, 5.43 }, { 5943, 239.8763, -40.2556, 4.99 }, { 5944, 239.7129, -25.8858, 2.89 },
+ { 5945, 239.9917, -39.3472, 6.49 }, { 5946, 240.2767, -53.4222, 6.13 }, { 5947, 239.3971, +26.8778, 4.15 }, { 5948, 240.0304, -37.6031, 3.41 },
+ { 5949, 238.9571, +58.9117, 6.31 }, { 5950, 239.3746, +39.6953, 6.31 }, { 5951, 240.7183, -61.4583, 6.25 }, { 5952, 240.2238, -39.5647, 6.21 },
+ { 5953, 240.0833, -21.3783, 2.32 }, { 5954, 240.0817, -15.4667, 5.47 }, { 5955, 241.4825, -71.5992, 5.70 }, { 5956, 240.3313, -30.1106, 6.33 },
+ { 5957, 239.7404, +36.6439, 5.62 }, { 5958, 239.8758, +25.9203, 2.00 }, { 5959, 240.1983,  -7.5886, 5.55 }, { 5960, 239.4475, +54.7497, 4.95 },
+ { 5961, 240.8829, -56.2247, 4.63 }, { 5962, 240.8038, -48.7703, 4.65 }, { 5963, 240.2129,  +4.4275, 5.83 }, { 5964, 239.7683, +49.8811, 6.05 },
+ { 5965, 240.6642, -28.8642, 6.03 }, { 5966, 240.3096, +17.8183, 5.12 }, { 5967, 240.8508, -37.3975, 4.89 }, { 5968, 240.2612, +33.3036, 5.41 },
+ { 5969, 240.8358, -24.1347, 5.00 }, { 5970, 240.8929, -31.9994, 6.01 }, { 5971, 240.3608, +29.8511, 4.99 }, { 5972, 240.5737, +22.8044, 4.83 },
+ { 5973, 240.9779, -23.2736, 6.21 }, { 5974, 241.0742, -32.7856, 6.10 }, { 5975, 241.1529, -36.1369, 5.90 }, { 5976, 240.9404,  +4.9867, 6.08 },
+ { 5977, 241.0921, -10.6269, 5.07 }, { 5978, 241.0921, -10.6269, 4.77 }, { 5979, 241.8500, -55.8086, 6.16 }, { 5980, 241.6225, -44.8267, 4.72 },
+ { 5981, 240.5229, +52.9158, 5.93 }, { 5982, 240.6996, +46.0367, 4.76 }, { 5983, 240.8308, +36.6317, 5.83 }, { 5984, 241.3592, -18.1944, 2.62 },
+ { 5985, 241.3604, -18.1981, 4.92 }, { 5986, 240.4721, +58.5653, 4.01 }, { 5987, 241.6479, -35.1978, 4.23 }, { 5988, 241.5263, -22.3936, 5.92 },
+ { 5989, 241.4354,  -5.7083, 6.53 }, { 5990, 241.4992,  -5.8606, 6.41 }, { 5991, 241.8183, -35.2444, 5.73 }, { 5992, 241.4075,  +8.0961, 6.29 },
+ { 5993, 241.7017, -19.3308, 3.96 }, { 5994, 242.3275, -56.0656, 5.57 }, { 5995, 240.7887, +59.4108, 6.19 }, { 5996, 241.7642, -13.9292, 6.32 },
+ { 5997, 241.8512, -19.1314, 4.32 }, { 5998, 241.9663, -23.5381, 6.33 }, { 5999, 242.1425, -38.8947, 7.05 }, { 6000, 242.1433, -38.9069, 6.65 },
+ { 6001, 242.0317, -25.6733, 5.38 }, { 6002, 241.9017, -11.2544, 5.78 }, { 6003, 242.1821, -22.3144, 5.88 }, { 6004, 241.9063,  +9.8917, 5.63 },
+ { 6005, 241.8425, +21.8225, 6.14 }, { 6006, 242.3821, -31.3503, 6.19 }, { 6007, 242.4692, -32.4542, 5.54 }, { 6008, 242.0188, +17.0469, 5.00 },
+ { 6009, 242.0204, +17.0544, 6.25 }, { 6010, 242.1167,  +8.5342, 5.73 }, { 6011, 242.2454,  +3.4544, 5.91 }, { 6012, 242.4800, -17.6592, 6.47 },
+ { 6013, 242.1942, +17.2058, 6.14 }, { 6014, 242.2967,  +6.3789, 5.97 }, { 6015, 242.8237, -40.8803, 5.86 }, { 6016, 242.4604,  -2.5331, 5.37 },
+ { 6017, 242.7583, -28.5836, 5.13 }, { 6018, 242.2429, +36.4908, 4.76 }, { 6019, 243.3442, -54.4592, 5.81 }, { 6020, 245.0867, -77.3042, 4.68 },
+ { 6021, 245.1117, -77.3328, 5.27 }, { 6022, 243.3200, -52.3283, 5.83 }, { 6023, 242.1925, +44.9350, 4.26 }, { 6024, 243.3696, -53.3694, 4.94 },
+ { 6025, 241.5821, +67.8103, 5.44 }, { 6026, 242.9942, -18.5503, 6.30 }, { 6027, 242.9988, -18.5394, 4.01 }, { 6028, 243.0758, -26.0736, 4.59 },
+ { 6029, 243.0663, -27.5825, 5.67 }, { 6030, 243.8596, -62.3144, 3.85 }, { 6031, 243.0000,  -9.9358, 4.94 }, { 6032, 242.8738,  +9.7125, 6.53 },
+ { 6033, 243.0304,  -7.4525, 5.43 }, { 6034, 240.8804, +76.7936, 5.56 }, { 6035, 242.8696, +16.6656, 6.08 }, { 6036, 242.2621, +57.9378, 6.33 },
+ { 6037, 244.2729, -66.0586, 5.75 }, { 6038, 242.3583, +55.8289, 6.49 }, { 6039, 242.9083, +23.4947, 5.70 }, { 6040, 243.9571, -56.0878, 5.63 },
+ { 6041, 243.2354,  -3.7792, 6.25 }, { 6042, 243.4404, -23.5781, 6.41 }, { 6043, 242.9154, +33.3425, 6.29 }, { 6044, 243.5929, -32.9886, 5.92 },
+ { 6045, 243.8138, -46.6278, 5.14 }, { 6046, 242.9500, +36.4250, 5.63 }, { 6047, 243.3142,  +5.0211, 5.48 }, { 6048, 243.4621, -10.1625, 5.22 },
+ { 6049, 243.8500, -41.1003, 6.14 }, { 6050, 242.9483, +42.3744, 5.87 }, { 6051, 243.6200, -20.8925, 6.41 }, { 6052, 243.1888, +26.6708, 6.50 },
+ { 6053, 243.6629, -17.4647, 6.32 }, { 6054, 243.7233, -24.5231, 6.05 }, { 6055, 244.1796, -52.1889, 5.44 }, { 6056, 243.5863,  -2.3056, 2.74 },
+ { 6057, 243.5563,  +5.9019, 6.31 }, { 6058, 244.2538, -49.9317, 4.99 }, { 6059, 244.3371, -52.9133, 6.33 }, { 6060, 243.9054,  -7.6306, 5.50 },
+ { 6061, 243.9646, -13.1508, 6.09 }, { 6062, 244.7163, -56.1003, 6.49 }, { 6063, 243.6700, +33.8586, 5.64 }, { 6064, 243.6700, +33.8583, 6.66 },
+ { 6065, 243.8696, +18.8083, 5.69 }, { 6066, 244.2450, -20.6961, 6.61 }, { 6067, 244.2304,  -2.0467, 6.18 }, { 6068, 243.9475, +27.4222, 6.14 },
+ { 6069, 243.1046, +67.1442, 6.21 }, { 6070, 244.5746, -27.3861, 4.78 }, { 6071, 244.8237, -41.3261, 5.45 }, { 6072, 244.9600, -49.8444, 4.02 },
+ { 6073, 245.1050, -54.8600, 5.77 }, { 6074, 244.1867, +29.1503, 5.78 }, { 6075, 244.5804,  -3.3075, 3.24 }, { 6076, 244.7821, -19.7822, 6.29 },
+ { 6077, 244.8862, -29.0933, 5.49 }, { 6078, 244.7517, -13.1275, 5.94 }, { 6079, 242.7063, +75.8775, 5.48 }, { 6080, 245.1358, -38.5692, 6.12 },
+ { 6081, 245.1592, -23.8306, 4.55 }, { 6082, 243.1342, +75.2106, 6.39 }, { 6083, 245.6167, -48.4278, 5.33 }, { 6084, 245.2971, -24.4072, 2.89 },
+ { 6085, 245.6204, -42.0878, 5.88 }, { 6086, 244.3138, +59.7550, 5.40 }, { 6087, 245.0179, +21.1325, 6.05 }, { 6088, 243.6396, +73.3950, 5.98 },
+ { 6089, 246.3417, -62.8753, 6.15 }, { 6090, 244.7967, +49.0381, 5.91 }, { 6091, 244.9796, +39.7086, 5.46 }, { 6092, 244.9350, +46.3133, 3.89 },
+ { 6093, 245.5183,  +1.0292, 4.82 }, { 6094, 246.0054, -38.8069, 5.40 }, { 6095, 245.4800, +19.1531, 3.75 }, { 6096, 245.6621,  -1.9203, 6.23 },
+ { 6097, 245.9863, -32.8006, 6.47 }, { 6098, 247.1171, -69.9156, 4.91 }, { 6099, 246.2258, -44.6508, 6.33 }, { 6100, 246.1321, -36.4342, 5.42 },
+ { 6101, 244.5392, +68.5544, 6.41 }, { 6102, 248.3625, -77.1028, 3.89 }, { 6103, 245.5242, +30.8919, 4.85 }, { 6104, 246.0258, -19.9625, 4.50 },
+ { 6105, 246.1650, -28.2967, 6.63 }, { 6106, 246.1654, -28.2953, 5.84 }, { 6107, 245.5892, +33.7992, 5.20 }, { 6108, 245.6217, +33.7036, 5.39 },
+ { 6109, 246.9888, -63.9419, 5.27 }, { 6110, 245.7354, +32.3331, 6.40 }, { 6111, 246.0450,  +6.9481, 5.85 }, { 6112, 246.3967, -22.5528, 5.02 },
+ { 6113, 246.3963, -22.5539, 5.92 }, { 6114, 247.0633, -57.4003, 5.69 }, { 6115, 246.7962, -46.4450, 4.47 }, { 6116, 244.3763, +75.7553, 4.95 },
+ { 6117, 246.3542, +14.0333, 4.57 }, { 6118, 246.7558, -17.5436, 4.42 }, { 6119, 246.4487, +18.8925, 6.70 }, { 6120, 247.4375, -56.2442, 6.06 },
+ { 6121, 246.5479, +11.4075, 6.11 }, { 6122, 247.0613, -36.8206, 5.79 }, { 6123, 246.3508, +37.3939, 5.54 }, { 6124, 246.7088,  +2.3475, 6.07 },
+ { 6125, 247.7058, -60.3664, 5.20 }, { 6126, 245.4529, +69.1094, 5.25 }, { 6127, 246.1054, +55.2050, 5.74 }, { 6128, 246.9313,  -6.4019, 5.23 },
+ { 6129, 246.9504,  -7.6283, 4.63 }, { 6130, 245.9458, +61.6967, 5.67 }, { 6131, 247.4263, -45.7567, 5.35 }, { 6132, 245.9979, +61.5142, 2.74 },
+ { 6133, 258.9971, -86.4336, 6.57 }, { 6134, 247.3517, -25.5681, 0.96 }, { 6135, 248.5804, -69.0119, 5.50 }, { 6136, 247.1417,  +0.6650, 5.39 },
+ { 6137, 247.2038,  -7.8711, 6.48 }, { 6138, 251.4733, -82.7611, 6.57 }, { 6139, 255.2438, -85.6356, 6.04 }, { 6140, 247.4454, -13.4492, 5.68 },
+ { 6141, 247.5517, -24.8850, 4.79 }, { 6142, 247.9238, -40.1831, 5.33 }, { 6143, 247.8454, -33.2956, 4.23 }, { 6144, 247.6246,  -6.4850, 6.50 },
+ { 6145, 247.8450, -25.4622, 6.10 }, { 6146, 247.1604, +41.8817, 5.04 }, { 6147, 247.7846, -15.3872, 4.28 }, { 6148, 247.5550, +21.4897, 2.77 },
+ { 6149, 247.7283,  +1.9839, 3.82 }, { 6150, 247.1808, +51.4078, 6.29 }, { 6151, 248.9367, -64.5047, 5.52 }, { 6152, 247.6400, +20.4792, 5.25 },
+ { 6153, 248.0342, -20.5336, 4.45 }, { 6154, 247.8058, +22.1953, 5.76 }, { 6155, 248.5208, -43.9547, 4.94 }, { 6156, 247.5250, +48.9608, 6.45 },
+ { 6157, 247.7617, +35.2250, 6.25 }, { 6158, 248.1488,  +5.5211, 5.63 }, { 6159, 248.1513, +11.4881, 4.84 }, { 6160, 248.7829, -44.7553, 6.46 },
+ { 6161, 246.9958, +68.7681, 5.00 }, { 6162, 247.9471, +45.5983, 5.65 }, { 6163, 250.7692, -76.4825, 4.24 }, { 6164, 249.0938, -41.1411, 5.47 },
+ { 6165, 248.9708, -27.7839, 2.82 }, { 6166, 249.0938, -34.7444, 4.16 }, { 6167, 249.7196, -59.0097, 6.18 }, { 6168, 248.5258, +42.4369, 4.20 },
+ { 6169, 248.8596, +17.0572, 6.41 }, { 6170, 248.1071, +60.8233, 5.94 }, { 6171, 249.0896,  -1.6753, 5.75 }, { 6172, 250.3471, -67.7039, 5.91 },
+ { 6173, 246.4296, +78.9639, 5.56 }, { 6174, 249.6092, -42.6014, 5.83 }, { 6175, 249.2896,  -9.4328, 2.56 }, { 6176, 249.1792, +15.4981, 6.30 },
+ { 6177, 250.2104, -59.5539, 6.18 }, { 6178, 249.7717, -36.7825, 5.91 }, { 6179, 249.5067,  -5.4619, 6.09 }, { 6180, 247.8671, +72.6119, 6.30 },
+ { 6181, 249.4500, +13.6869, 6.31 }, { 6182, 250.8421, -66.5675, 6.03 }, { 6183, 249.0467, +46.6133, 5.79 }, { 6184, 249.0479, +52.9003, 5.53 },
+ { 6185, 249.0571, +52.9244, 5.08 }, { 6186, 249.0588, +52.9242, 6.53 }, { 6187, 250.3346, -47.2369, 5.65 }, { 6188, 250.4175, -48.3483, 5.65 },
+ { 6189, 249.9129,  -8.4456, 6.35 }, { 6190, 250.1438, -19.5914, 6.26 }, { 6191, 247.6617, +77.4467, 6.34 }, { 6192, 250.4396, -32.8536, 5.87 },
+ { 6193, 250.4008, -23.5319, 6.09 }, { 6194, 250.1463,  +4.2072, 6.93 }, { 6195, 250.1613,  +4.2197, 5.77 }, { 6196, 250.3933, -16.2578, 4.96 },
+ { 6197, 250.7642, -45.9294, 6.23 }, { 6198, 249.2292, +63.0728, 6.16 }, { 6199, 249.5017, +56.0156, 5.29 }, { 6200, 249.6871, +48.9283, 4.90 },
+ { 6201, 250.2979,  -0.9994, 6.24 }, { 6202, 250.4738, -18.0756, 5.57 }, { 6203, 250.2142, +12.3950, 6.08 }, { 6204, 251.6667, -66.8903, 5.13 },
+ { 6205, 250.4271,  +1.1811, 5.74 }, { 6206, 250.9396, -40.8811, 6.20 }, { 6207, 251.1658, -52.8475, 5.96 }, { 6208, 250.2525, +24.8586, 6.06 },
+ { 6209, 250.9746, -40.8869, 6.12 }, { 6210, 250.9483, -37.8433, 6.05 }, { 6211, 250.9113, -31.8939, 6.46 }, { 6212, 250.3217, +31.6031, 2.81 },
+ { 6213, 250.4029, +26.9169, 5.92 }, { 6214, 251.1775, -39.1603, 5.71 }, { 6215, 251.5883, -57.4964, 5.74 }, { 6216, 251.0721, -26.5439, 6.58 },
+ { 6217, 252.1662, -68.9722, 1.92 }, { 6218, 251.2508, -27.4903, 6.02 }, { 6219, 251.8313, -57.6586, 5.58 }, { 6220, 250.7242, +38.9222, 3.53 },
+ { 6221, 251.6992, -38.6228, 5.48 }, { 6222, 250.9654, +34.0389, 5.99 }, { 6223, 250.2296, +64.5892, 4.83 }, { 6224, 251.3738,  +1.0203, 6.03 },
+ { 6225, 251.7138, -24.4714, 6.71 }, { 6226, 250.7433, +55.6903, 6.16 }, { 6227, 251.3438, +15.7453, 5.56 }, { 6228, 251.4579,  +8.5825, 5.15 },
+ { 6229, 252.4462, -58.9586, 3.76 }, { 6230, 251.2988, +43.2172, 6.05 }, { 6231, 253.0725, -66.3181, 6.32 }, { 6232, 251.7908,  +2.0644, 6.10 },
+ { 6233, 252.9746, -64.6244, 6.13 }, { 6234, 251.9433,  +5.2467, 5.24 }, { 6235, 252.1125, -13.0906, 6.03 }, { 6236, 252.6496, -49.9544, 6.47 },
+ { 6237, 251.3242, +56.7819, 4.85 }, { 6238, 249.4704, +78.9183, 6.32 }, { 6239, 252.0371, +13.5906, 6.35 }, { 6240, 252.3658, -14.3325, 6.10 },
+ { 6241, 252.5408, -33.7067, 2.29 }, { 6242, 251.8325, +42.2389, 5.87 }, { 6243, 252.4583,  -9.2169, 4.65 }, { 6244, 252.7492, -36.4856, 6.11 },
+ { 6245, 252.8904, -40.7694, 5.22 }, { 6246, 252.3942, +13.2614, 5.91 }, { 6247, 252.9675, -37.9525, 3.08 }, { 6248, 252.5929,  -1.3461, 6.32 },
+ { 6249, 253.0796, -40.1456, 6.49 }, { 6250, 252.5808,  +7.2478, 5.49 }, { 6251, 253.5021, -56.0906, 5.94 }, { 6252, 253.0838, -37.9825, 3.57 },
+ { 6253, 253.8529, -62.7303, 6.02 }, { 6254, 252.3092, +45.9833, 4.82 }, { 6255, 252.8537,  +1.2161, 5.51 }, { 6256, 252.4187, +43.4306, 6.13 },
+ { 6257, 253.4271, -42.9492, 5.96 }, { 6258, 252.6625, +29.8067, 5.72 }, { 6259, 252.6796, +32.5536, 6.13 }, { 6260, 253.5075, -40.1936, 5.45 },
+ { 6261, 253.4950, -40.0053, 6.32 }, { 6262, 253.4988, -41.6378, 4.73 }, { 6263, 253.5492, -40.1497, 6.45 }, { 6264, 252.6504, +41.8967, 6.29 },
+ { 6265, 253.5817, -40.1800, 6.59 }, { 6266, 253.6121, -41.5211, 5.88 }, { 6267, 250.7750, +77.5142, 5.98 }, { 6268, 253.0204, +14.9742, 6.52 },
+ { 6269, 253.3550, -19.5844, 5.88 }, { 6270, 252.9388, +24.6564, 5.04 }, { 6271, 253.6458, -41.6386, 3.62 }, { 6272, 253.7433, -40.8489, 5.77 },
+ { 6273, 253.6500, -29.4128, 6.35 }, { 6274, 254.0371, -49.3250, 6.33 }, { 6275, 254.1196, -51.7161, 5.94 }, { 6276, 254.8908, -68.7317, 5.79 },
+ { 6277, 253.5442,  -0.3878, 6.25 }, { 6278, 253.6679, -10.2075, 6.57 }, { 6279, 253.2421, +31.7017, 5.32 }, { 6280, 253.6488,  -5.8461, 5.25 },
+ { 6281, 253.5021, +10.1653, 4.38 }, { 6282, 253.9908, -32.4928, 6.37 }, { 6283, 254.1500, -39.1764, 6.15 }, { 6284, 254.0075, -15.1939, 6.37 },
+ { 6285, 254.6550, -54.0097, 3.13 }, { 6286, 253.3233, +47.4169, 6.00 }, { 6287, 253.7300, +20.9586, 5.41 }, { 6288, 254.2962, -32.7406, 5.48 },
+ { 6289, 254.5750, -49.3589, 5.55 }, { 6290, 253.8167, +13.6197, 6.34 }, { 6291, 254.2000, -22.8500, 5.58 }, { 6292, 253.7587, +25.7306, 6.08 },
+ { 6293, 253.8425, +18.4333, 5.35 }, { 6294, 254.2667, -18.4600, 6.27 }, { 6295, 254.8963, -52.8394, 4.06 }, { 6296, 254.3587,  -9.0367, 6.19 },
+ { 6297, 255.0258, -53.4031, 5.65 }, { 6298, 254.7183, -36.3789, 6.09 }, { 6299, 254.4171,  +9.3750, 3.20 }, { 6300, 255.1129, -47.3522, 6.00 },
+ { 6301, 254.3833, +13.8842, 6.37 }, { 6302, 254.6733, -13.1303, 6.59 }, { 6303, 255.1346, -44.5483, 6.65 }, { 6304, 255.4475, -57.0417, 6.11 },
+ { 6305, 254.3792, +25.3528, 6.28 }, { 6306, 254.0267, +50.0389, 6.56 }, { 6307, 254.4263, +24.3814, 6.32 }, { 6308, 254.9900, -24.9081, 5.86 },
+ { 6309,   0.0000,  +0.0000, 0.00 }, { 6310, 255.0396, -23.0108, 5.75 }, { 6311, 255.1538, -34.0658, 5.97 }, { 6312, 255.4421, -50.8692, 6.45 },
+ { 6313, 254.4592, +42.5125, 6.34 }, { 6314, 255.7867, -52.7631, 5.29 }, { 6315, 254.0071, +65.1347, 4.89 }, { 6316, 255.4696, -31.8564, 5.03 },
+ { 6317, 255.1225,  +6.5836, 6.59 }, { 6318, 255.2650,  -3.7775, 4.82 }, { 6319, 254.1050, +65.0392, 6.41 }, { 6320, 256.1029, -56.2878, 5.73 },
+ { 6321, 255.4633, -17.1144, 6.26 }, { 6322, 251.4921, +82.0372, 4.23 }, { 6323, 255.9238, -46.8400, 6.06 }, { 6324, 255.0725, +30.9264, 3.92 },
+ { 6325, 255.2421, +22.6322, 5.65 }, { 6326, 255.3875, +14.9494, 6.31 }, { 6327, 255.9617, -37.8478, 5.91 }, { 6328, 255.2900, +27.1964, 6.55 },
+ { 6329, 255.4963,  +8.4506, 6.33 }, { 6330, 254.8396, +56.6886, 6.03 }, { 6331, 256.2721, -44.4983, 6.28 }, { 6332, 255.4017, +33.5683, 5.25 },
+ { 6333, 255.5779, +25.5056, 5.75 }, { 6334, 256.2058, -33.8772, 4.87 }, { 6335, 254.0700, +73.1278, 6.30 }, { 6336, 255.5717, +31.8847, 6.36 },
+ { 6337, 255.7825, +14.0919, 4.98 }, { 6338, 256.4525, -43.8950, 6.19 }, { 6339, 255.7933, +14.5111, 6.52 }, { 6340, 256.1888, -19.5053, 6.30 },
+ { 6341, 255.9137, +13.6053, 5.93 }, { 6342, 255.9917, +13.5675, 6.08 }, { 6343, 255.9696, +19.6906, 6.35 }, { 6344, 256.5846, -36.7725, 5.98 },
+ { 6345, 254.7608, +69.1864, 6.40 }, { 6346, 255.8758, +35.4142, 6.69 }, { 6347, 256.6183, -34.5489, 6.13 }, { 6348, 255.3196, +60.6492, 6.13 },
+ { 6349, 256.3204,  +0.7025, 6.01 }, { 6350, 256.5492, -20.4353, 6.30 }, { 6351, 255.9729, +34.7903, 6.04 }, { 6352, 256.1721, +19.5992, 6.17 },
+ { 6353, 256.3846,  +0.8919, 5.64 }, { 6354, 256.7217, -25.4869, 6.29 }, { 6355, 256.3446, +12.7408, 4.91 }, { 6356, 257.5263, -60.3244, 6.39 },
+ { 6357, 258.0825, -69.2789, 6.22 }, { 6358, 256.5404,  +9.7333, 6.37 }, { 6359, 256.5546, +10.4542, 6.37 }, { 6360, 255.5638, +64.6006, 6.10 },
+ { 6361, 256.7204,  -0.3436, 6.38 }, { 6362, 256.2708, +43.8122, 6.43 }, { 6363, 256.2075, +48.8042, 6.09 }, { 6364, 256.5754, +22.0842, 5.56 },
+ { 6365, 257.0621, -16.3908, 5.99 }, { 6366, 257.1979, -29.5964, 5.97 }, { 6367, 257.0567,  -0.9206, 6.06 }, { 6368, 258.3229, -66.8033, 5.89 },
+ { 6369, 256.3325, +54.4703, 5.83 }, { 6370, 256.3321, +54.4703, 5.80 }, { 6371, 257.6762, -43.4425, 5.08 }, { 6372, 257.2271,  -2.1172, 6.36 },
+ { 6373, 259.1483, -73.4669, 6.25 }, { 6374, 257.9121, -47.1258, 5.84 }, { 6375, 257.4500,  -9.4767, 5.56 }, { 6376, 256.9446, +40.5161, 6.34 },
+ { 6377, 257.0083, +35.9353, 5.39 }, { 6378, 257.5946, -14.2753, 2.43 }, { 6379, 255.4175, +75.2972, 6.21 }, { 6380, 258.0383, -42.7608, 3.33 },
+ { 6381, 258.0675, -38.4931, 5.67 }, { 6382, 258.0688, -37.1778, 6.30 }, { 6383, 257.0713, +50.8422, 6.46 }, { 6384, 258.5550, -55.1117, 6.09 },
+ { 6385, 257.6908, +12.4672, 6.57 }, { 6386, 258.0567, -24.7453, 6.54 }, { 6387, 258.1042, -26.2381, 6.14 }, { 6388, 257.3888, +40.7772, 5.08 },
+ { 6389, 258.2446, -31.5614, 6.01 }, { 6390, 257.9383,  +7.8947, 6.33 }, { 6391, 257.7633, +24.2378, 6.19 }, { 6392, 258.6154, -38.2331, 6.60 },
+ { 6393, 258.1158, +10.5853, 5.33 }, { 6394, 258.2267,  +0.3519, 6.65 }, { 6395, 257.6275, +52.4089, 6.29 }, { 6396, 257.1967, +65.7147, 3.17 },
+ { 6397, 258.8304, -32.4517, 5.53 }, { 6398, 258.8996, -37.4061, 5.96 }, { 6399, 257.9175, +49.7467, 6.04 }, { 6400, 260.0533, -69.9544, 6.53 },
+ { 6401, 258.8375, -25.3972, 5.11 }, { 6402, 258.8367, -25.3986, 5.07 }, { 6403, 258.9646, -29.7894, 6.21 }, { 6404, 258.8346, -13.4161, 5.99 },
+ { 6405, 259.0896, -34.2506, 6.12 }, { 6406, 258.6621, +14.3903, 3.48 }, { 6407, 258.6633, +14.3900, 5.39 }, { 6408, 259.8017, -58.3056, 5.91 },
+ { 6409, 259.2654, -31.3372, 5.55 }, { 6410, 258.7579, +24.8392, 3.14 }, { 6411, 260.5246, -69.8767, 5.41 }, { 6412, 259.0592,  +2.1861, 6.17 },
+ { 6413, 259.1783,  -5.7550, 6.09 }, { 6414, 259.1321,  +1.2106, 5.88 }, { 6415, 259.1529,  +0.4453, 4.73 }, { 6416, 259.7633, -45.3661, 5.48 },
+ { 6417, 260.4975, -66.2294, 4.78 }, { 6418, 258.7617, +36.8092, 3.16 }, { 6419, 258.9233, +23.7428, 5.96 }, { 6420, 259.7000, -43.8703, 5.76 },
+ { 6421, 258.1358, +62.8744, 5.56 }, { 6422, 259.5850, -31.4467, 6.36 }, { 6423, 259.8763, -49.9367, 6.27 }, { 6424, 259.5029, -23.7131, 5.20 },
+ { 6425, 259.5021, -23.7158, 6.80 }, { 6426, 259.7383, -33.0103, 5.91 }, { 6427, 259.8521, -43.7769, 6.65 }, { 6428, 259.5800, -15.6881, 6.43 },
+ { 6429, 262.8637, -79.1408, 5.88 }, { 6430, 259.3996, +23.0908, 6.45 }, { 6431, 259.3313, +33.1000, 4.82 }, { 6432, 259.5208, +17.3181, 6.00 },
+ { 6433, 259.6542, +10.8644, 5.03 }, { 6434, 259.7200,  +6.0853, 6.51 }, { 6435, 259.9721, -16.2436, 6.02 }, { 6436, 259.4179, +37.2917, 4.65 },
+ { 6437, 259.2025, +49.6911, 7.48 }, { 6438, 260.7292, -57.9897, 5.88 }, { 6439, 259.9979,  -4.0828, 6.32 }, { 6440, 261.0046, -61.1358, 5.70 },
+ { 6441, 260.1425, -18.6672, 6.52 }, { 6442, 260.7788, -55.4747, 5.80 }, { 6443, 259.7021, +28.8231, 5.65 }, { 6444, 259.5971, +38.8114, 5.94 },
+ { 6445, 260.2508, -20.8872, 4.39 }, { 6446, 260.2071, -11.1531, 4.33 }, { 6447, 261.0779, -59.3264, 5.77 }, { 6448, 259.1225, +60.6706, 6.32 },
+ { 6449, 260.2196,  -9.3039, 6.46 }, { 6450, 260.6642, -36.1950, 6.41 }, { 6451, 260.8171, -46.5317, 5.25 }, { 6452, 260.0788, +18.0572, 5.00 },
+ { 6453, 260.5025, -23.0006, 3.27 }, { 6454, 260.6583, -34.0900, 6.47 }, { 6455, 260.0408, +25.5375, 5.38 }, { 6456, 260.7287, -36.7794, 5.93 },
+ { 6457, 260.2258, +24.4994, 5.12 }, { 6458, 260.1650, +32.4678, 5.39 }, { 6459, 260.8400, -27.8569, 5.35 }, { 6460, 261.0542, -43.8375, 5.12 },
+ { 6461, 261.3250, -54.4700, 2.85 }, { 6462, 261.3483, -55.6225, 3.34 }, { 6463, 260.3892, +16.7308, 6.35 }, { 6464, 260.0879, +46.2408, 5.59 },
+ { 6465, 260.7138,  -1.6117, 6.29 }, { 6466, 260.3800, +28.7581, 6.35 }, { 6467, 260.1400, +48.1883, 6.43 }, { 6468, 261.5000, -49.3664, 5.23 },
+ { 6469, 260.4317, +39.9744, 5.51 }, { 6470, 261.2613, -33.3036, 6.16 }, { 6471, 262.0321, -62.9636, 6.24 }, { 6472, 261.1750, -20.5583, 5.85 },
+ { 6473, 261.1546, -17.5542, 6.21 }, { 6474, 261.2758, -23.7564, 6.19 }, { 6475, 261.7346, -50.0508, 6.19 }, { 6476, 260.9900,  +8.8528, 5.77 },
+ { 6477, 261.7146, -44.1564, 5.29 }, { 6478, 261.8017, -49.3697, 5.92 }, { 6479, 260.4392, +53.4206, 5.67 }, { 6480, 261.0275, +22.9603, 5.74 },
+ { 6481, 261.1313, +16.3011, 5.71 }, { 6482, 261.1408, +15.6061, 6.35 }, { 6483, 261.9900, -51.7028, 5.75 }, { 6484, 260.9196, +37.1467, 5.47 },
+ { 6485, 260.9208, +37.1458, 4.52 }, { 6486, 261.5925, -23.8247, 4.17 }, { 6487, 262.1613, -54.8303, 5.94 }, { 6488, 261.0092, +38.5828, 6.49 },
+ { 6489, 261.4912,  -0.3483, 6.44 }, { 6490, 261.7300, -24.0567, 6.44 }, { 6491, 261.1129, +36.9519, 6.28 }, { 6492, 261.8388, -28.1331, 4.29 },
+ { 6493, 261.6579,  -4.9133, 4.54 }, { 6494, 261.9063, -28.2756, 6.00 }, { 6495, 261.4767, +16.9175, 5.98 }, { 6496, 261.7588, -11.4875, 6.21 },
+ { 6497, 261.5792,  +7.5956, 6.06 }, { 6498, 261.6288,  +4.1403, 4.34 }, { 6499, 261.5038, +26.8789, 6.41 }, { 6500, 262.7746, -59.3161, 3.62 },
+ { 6501, 262.2337, -35.2217, 6.02 }, { 6502, 261.7046, +20.0808, 5.54 }, { 6503, 262.3571, -37.4833, 6.39 }, { 6504, 262.0096,  -7.7917, 6.37 },
+ { 6505, 262.8458, -55.0794, 5.95 }, { 6506, 261.6925, +34.6958, 5.94 }, { 6507, 262.2071,  +0.3306, 5.44 }, { 6508, 262.6908, -36.7042, 2.69 },
+ { 6509, 261.6842, +48.2600, 5.85 }, { 6510, 262.9604, -48.1239, 2.95 }, { 6511, 261.4221, +60.0483, 5.65 }, { 6512, 262.4475,  -4.0803, 6.37 },
+ { 6513, 262.9546, -45.9636, 6.03 }, { 6514, 261.5204, +58.6519, 6.51 }, { 6515,   0.0000,  +0.0000, 0.00 }, { 6516, 262.5992,  -0.9375, 5.31 },
+ { 6517, 262.9475, -32.2972, 6.44 }, { 6518, 261.2508, +67.3064, 6.43 }, { 6519, 262.8542, -22.0372, 4.81 }, { 6520, 262.9350, -25.7303, 6.05 },
+ { 6521, 262.5933, +11.9250, 6.39 }, { 6522, 263.1021, -33.7203, 6.17 }, { 6523, 263.2808, -40.8264, 5.84 }, { 6524, 262.8388,  +2.7244, 5.59 },
+ { 6525, 263.8954, -58.1539, 6.28 }, { 6526, 262.6846, +26.1106, 4.41 }, { 6527, 263.4021, -36.8961, 1.63 }, { 6528, 262.7308, +31.1583, 5.61 },
+ { 6529, 259.9042, +80.1364, 5.72 }, { 6530, 263.8333, -52.6472, 6.10 }, { 6531, 262.6679, +38.8822, 6.43 }, { 6532, 263.0625, +11.9303, 6.42 },
+ { 6533, 262.9567, +28.4075, 5.62 }, { 6534, 263.3746,  -4.2553, 5.62 }, { 6535, 263.6771, -31.4183, 5.70 }, { 6536, 262.6083, +52.3014, 2.79 },
+ { 6537, 263.9150, -45.4944, 4.59 }, { 6538, 263.0046, +34.2708, 6.56 }, { 6539, 263.9292, -36.5600, 6.48 }, { 6540, 262.6825, +57.8764, 6.40 },
+ { 6541, 263.3450, +19.2567, 5.64 }, { 6542, 263.4142, +16.3175, 5.69 }, { 6543, 263.4283, +14.8417, 6.48 }, { 6544, 263.6933, -10.7581, 5.55 },
+ { 6545, 263.8271, -21.9561, 6.57 }, { 6546, 264.1367, -37.3647, 4.29 }, { 6547, 264.3633, -49.9400, 5.93 }, { 6548, 263.6529,  +9.5867, 5.81 },
+ { 6549, 264.5233, -53.4997, 5.25 }, { 6550, 263.2804, +41.2436, 5.74 }, { 6551, 263.6133, +16.5039, 6.40 }, { 6552, 270.3921, -84.7853, 6.45 },
+ { 6553, 264.3300, -41.0022, 1.87 }, { 6554, 263.0442, +55.1842, 4.88 }, { 6555, 263.0667, +55.1731, 4.87 }, { 6556, 263.7337, +12.5600, 2.08 },
+ { 6557, 264.3617, -37.9344, 6.26 }, { 6558, 264.5354, -41.1194, 6.10 }, { 6559, 263.9983, +20.9961, 6.10 }, { 6560, 263.3821, +57.5589, 6.17 },
+ { 6561, 264.3967, -14.6014, 3.54 }, { 6562, 264.4008, -14.4289, 5.94 }, { 6563, 263.9267, +37.3017, 6.10 }, { 6564, 264.0329, +28.1847, 6.38 },
+ { 6565, 266.0821, -71.7792, 6.49 }, { 6566, 262.9912, +68.1350, 5.05 }, { 6567, 264.4613,  -7.8811, 4.62 }, { 6568, 264.5396,  -9.0736, 5.75 },
+ { 6569, 265.0983, -48.5844, 4.77 }, { 6570, 264.1529, +30.7853, 6.02 }, { 6571, 264.3796, +24.3100, 5.77 }, { 6572, 265.3179, -45.0781, 5.79 },
+ { 6573, 263.7479, +61.8750, 5.23 }, { 6574, 264.1567, +48.5856, 5.37 }, { 6575, 264.7854,  +2.0281, 6.26 }, { 6576, 265.5163, -49.4894, 6.24 },
+ { 6577, 264.7408, +13.3292, 6.12 }, { 6578, 265.0492,  -1.8475, 6.19 }, { 6579, 264.7071, +32.7394, 6.37 }, { 6580, 265.6221, -38.9700, 2.41 },
+ { 6581, 265.3537, -11.1247, 4.26 }, { 6582, 266.4333, -63.2761, 3.62 }, { 6583, 265.7125, -35.0542, 5.54 }, { 6584, 264.9896, +31.2025, 6.03 },
+ { 6585, 266.0363, -50.1658, 5.15 }, { 6586, 266.2325, -56.4547, 6.01 }, { 6587, 265.7788, -32.9489, 6.40 }, { 6588, 264.8662, +46.0064, 3.80 },
+ { 6589, 265.2958, +15.1781, 6.34 }, { 6590, 265.3846,  +6.3128, 5.95 }, { 6591, 265.1717, +31.2875, 6.28 }, { 6592, 265.2729, +24.5133, 6.36 },
+ { 6593, 265.8242, -26.1158, 6.36 }, { 6594, 265.4946, +15.9519, 5.52 }, { 6595, 265.8575, -20.3167, 4.87 }, { 6596, 264.2379, +68.7581, 4.80 },
+ { 6597, 266.1750, -41.2711, 5.87 }, { 6598, 264.1654, +69.5708, 6.42 }, { 6599, 265.1567, +43.4708, 6.59 }, { 6600, 265.9525, -12.4914, 6.39 },
+ { 6601, 265.9458,  -6.9206, 6.30 }, { 6602, 265.6183, +24.5642, 5.52 }, { 6603, 265.8683,  +4.5672, 2.77 }, { 6604, 265.8417, +14.2950, 6.24 },
+ { 6605, 265.1508, +57.3103, 6.77 }, { 6606, 264.2867, +72.4558, 5.86 }, { 6607, 265.3408, +51.8181, 5.99 }, { 6608, 265.8400, +24.3278, 5.71 },
+ { 6609, 266.1417,  +2.5794, 6.17 }, { 6610, 266.1475,  +2.5789, 6.56 }, { 6611, 266.0721, +14.4103, 6.19 }, { 6612, 265.7733, +44.0844, 6.34 },
+ { 6613, 266.7804, -37.8883, 6.43 }, { 6614, 267.1588, -54.5983, 6.11 }, { 6615, 266.8963, -39.8731, 3.03 }, { 6616, 266.8900, -26.1692, 4.54 },
+ { 6617, 266.9400, -21.5219, 6.18 }, { 6618, 265.9971, +53.8017, 5.75 }, { 6619, 266.4179, +31.5047, 6.23 }, { 6620, 266.9033, -13.2742, 5.94 },
+ { 6621, 267.1158, -25.0250, 6.35 }, { 6622, 267.6175, -52.3878, 5.92 }, { 6623, 266.6146, +27.7206, 3.42 }, { 6624, 267.8979, -59.8356, 5.78 },
+ { 6625, 266.4738, +38.8814, 6.52 }, { 6626, 266.4937, +39.3225, 6.68 }, { 6627, 266.7833, +17.6972, 5.72 }, { 6628, 267.2937, -30.2967, 4.83 },
+ { 6629, 266.9733,  +2.7072, 3.75 }, { 6630, 267.4646, -36.9567, 3.21 }, { 6631, 267.5467, -39.9094, 4.81 }, { 6632, 267.7958, -52.8694, 6.09 },
+ { 6633, 267.0842,  +3.8042, 6.22 }, { 6634, 268.3267, -64.5108, 6.49 }, { 6635, 269.4242, -75.8225, 6.07 }, { 6636, 265.4846, +72.1489, 4.58 },
+ { 6637, 265.4917, +72.1569, 5.79 }, { 6638, 267.1033, +20.5656, 5.69 }, { 6639, 267.3288,  +1.9611, 6.47 }, { 6640, 267.9354, -44.3994, 6.11 },
+ { 6641, 266.7838, +47.6122, 6.43 }, { 6642, 267.1996, +19.2553, 6.12 }, { 6643, 267.8867, -39.2275, 5.96 }, { 6644, 267.2050, +25.6228, 5.12 },
+ { 6645, 267.8021, -29.4428, 6.66 }, { 6646, 271.3612, -80.5136, 6.35 }, { 6647, 268.0567, -33.2008, 5.90 }, { 6648, 268.0821, -33.5833, 5.84 },
+ { 6649, 268.2196, -40.0033, 6.20 }, { 6650, 267.6812, +11.9467, 6.17 }, { 6651, 268.2050, -33.8858, 6.06 }, { 6652, 268.2329, -34.9814, 6.45 },
+ { 6653, 268.2412, -34.3758, 6.03 }, { 6654, 267.5954, +29.3222, 5.50 }, { 6655, 267.7017, +22.3164, 5.98 }, { 6656, 267.2679, +50.7811, 5.02 },
+ { 6657, 268.3317, -33.2694, 6.17 }, { 6658, 268.3471, -33.1047, 5.60 }, { 6659, 267.9979,  -0.7633, 6.35 }, { 6660, 268.4396, -33.2142, 6.38 },
+ { 6661, 268.1617,  -5.8564, 6.21 }, { 6662, 268.4787, -33.2475, 5.96 }, { 6663, 268.4921, -33.1683, 6.42 }, { 6664, 267.5138, +48.3942, 6.68 },
+ { 6665, 267.9937, +15.3258, 6.46 }, { 6666, 268.2650,  -9.1003, 6.18 }, { 6667, 268.1475,  +1.3050, 5.95 }, { 6668, 268.6133, -33.5336, 5.96 },
+ { 6669, 267.8083, +40.0725, 6.46 }, { 6670, 268.3092,  +6.1014, 5.77 }, { 6671, 268.7829, -35.5242, 6.06 }, { 6672, 268.7250, -23.1128, 6.20 },
+ { 6673, 268.0196, +39.9822, 6.04 }, { 6674, 268.0042, +46.6433, 6.38 }, { 6675, 269.1975, -43.6578, 4.86 }, { 6676, 268.5592, +11.1306, 6.38 },
+ { 6677, 268.3254, +40.0081, 5.16 }, { 6678, 269.2325, -39.6944, 6.43 }, { 6679, 268.9792, -17.1978, 6.52 }, { 6680, 269.1746, -27.9347, 5.80 },
+ { 6681, 269.0792, -14.1875, 5.89 }, { 6682, 269.4488, -40.2839, 4.88 }, { 6683, 269.4908, -38.8631, 6.29 }, { 6684, 269.0767,  +0.6703, 5.82 },
+ { 6685, 268.8550, +26.0500, 5.46 }, { 6686, 269.1988,  -3.9181, 5.47 }, { 6687, 268.9617, +22.4642, 5.58 }, { 6688, 268.3821, +56.8728, 3.75 },
+ { 6689, 269.2679,  +0.0664, 5.97 }, { 6690, 269.2333,  +6.4878, 6.29 }, { 6691, 269.7317, -35.1417, 5.74 }, { 6692, 269.6629, -27.2408, 6.01 },
+ { 6693, 269.7717, -29.7469, 5.16 }, { 6694, 269.7729, -29.7467, 7.04 }, { 6695, 269.0633, +37.2506, 3.86 }, { 6696, 269.3621, +11.0442, 6.36 },
+ { 6697, 269.3096, +23.9958, 6.30 }, { 6698, 269.7567,  -8.2264, 3.34 }, { 6699, 268.8488, +55.9714, 6.10 }, { 6700, 269.9483, -22.1839, 4.76 },
+ { 6701, 267.3625, +76.9628, 5.04 }, { 6702, 269.2017, +45.3508, 6.02 }, { 6703, 269.4413, +29.2478, 3.70 }, { 6704, 270.0004, -19.6608, 6.21 },
+ { 6705, 269.1517, +51.4889, 2.23 }, { 6706, 269.9029,  -3.1786, 5.87 }, { 6707, 269.6258, +30.1894, 4.41 }, { 6708, 270.4513, -35.6222, 6.30 },
+ { 6709, 270.0646,  +0.6294, 6.37 }, { 6710, 270.1208,  -2.3097, 4.62 }, { 6711, 269.6762, +36.2878, 6.00 }, { 6712, 270.0658,  +4.3686, 4.64 },
+ { 6713, 270.0142, +16.7508, 4.67 }, { 6714, 270.1613,  +2.9317, 3.97 }, { 6715, 270.3463, -16.8431, 6.28 }, { 6716, 270.4767, -21.2194, 5.77 },
+ { 6717, 267.5437, +78.3067, 6.24 }, { 6718, 269.7179, +45.4761, 6.48 }, { 6719, 270.2204,  +6.2683, 6.34 }, { 6720, 270.1154, +19.5058, 6.50 },
+ { 6721, 283.6954, -86.3942, 5.28 }, { 6722, 270.2383, +15.0933, 6.26 }, { 6723, 270.4383,  +1.3053, 4.45 }, { 6724, 270.7129, -23.7178, 5.34 },
+ { 6725, 268.7967, +72.0050, 5.45 }, { 6726, 270.1517, +33.2139, 5.99 }, { 6727, 270.7571, -21.2817, 6.74 }, { 6728, 269.9842, +45.5014, 5.67 },
+ { 6729, 270.3746, +21.5953, 5.18 }, { 6730, 270.3767, +21.5956, 4.96 }, { 6731, 272.8154, -74.1086, 5.86 }, { 6732, 270.6929,  -4.6414, 6.76 },
+ { 6733, 270.7708,  -7.8197, 5.94 }, { 6734, 270.7704,  -7.8194, 5.24 }, { 6735, 268.6108, +75.1708, 6.36 }, { 6736, 270.9683, -23.6394, 5.97 },
+ { 6737, 270.3996, +33.3114, 6.15 }, { 6738, 270.5963, +20.8336, 5.28 }, { 6739, 271.2100, -34.0986, 6.00 }, { 6740, 271.9513, -63.4500, 6.41 },
+ { 6741, 270.6254, +22.9231, 6.21 }, { 6742, 271.2554, -28.4200, 4.69 }, { 6743, 271.6579, -49.9083, 3.66 }, { 6744, 270.8112, +19.6131, 6.50 },
+ { 6745, 272.1450, -62.3317, 4.35 }, { 6746, 271.4521, -29.5758, 2.99 }, { 6747, 271.1554,  +1.9192, 6.14 }, { 6748, 271.5988, -35.9803, 5.95 },
+ { 6749, 271.7075, -42.5753, 5.77 }, { 6750, 271.7075, -42.5753, 5.77 }, { 6751, 273.1438, -72.3283, 5.85 }, { 6752, 271.3637,  +2.4994, 4.03 },
+ { 6753, 270.7875, +48.4644, 6.21 }, { 6754, 271.1675, +23.9425, 6.34 }, { 6755, 271.5308,  -7.6761, 5.85 }, { 6756, 271.5633,  -3.2486, 5.77 },
+ { 6757, 271.5308,  +0.4467, 6.34 }, { 6758, 271.4304, +12.0039, 7.04 }, { 6759, 272.1254, -44.2328, 6.15 }, { 6760, 272.4900, -58.9600, 6.38 },
+ { 6761, 272.6087, -61.9978, 5.49 }, { 6762, 271.7975, -20.5561, 6.28 }, { 6763, 271.3758, +21.6469, 6.15 }, { 6764, 271.1800, +40.0842, 6.52 },
+ { 6765, 271.5079, +22.2189, 5.06 }, { 6766, 272.0208, -27.5428, 4.57 }, { 6767, 271.2533, +41.9467, 6.34 }, { 6768, 271.4567, +32.2306, 5.71 },
+ { 6769, 271.9517, -16.8458, 5.52 }, { 6770, 271.8267,  +8.7339, 4.64 }, { 6771, 271.8375,  +9.5639, 3.73 }, { 6772, 272.3433, -35.3275, 6.58 },
+ { 6773, 272.2254, -24.5275, 6.61 }, { 6774, 273.6004, -69.2486, 6.73 }, { 6775, 271.7563, +30.5619, 5.04 }, { 6776, 271.9517, +13.0711, 6.63 },
+ { 6777, 272.4996, -31.2803, 6.43 }, { 6778, 272.7688, -46.4869, 6.07 }, { 6779, 271.8858, +28.7625, 3.83 }, { 6780, 272.5238, -29.2714, 5.53 },
+ { 6781, 271.9563, +26.1014, 5.86 }, { 6782, 271.9563, +26.0975, 5.90 }, { 6783, 272.8075, -44.0456, 4.53 }, { 6784, 272.1404, +14.2847, 6.37 },
+ { 6785, 272.4308, -12.0656, 6.39 }, { 6786, 272.7733, -40.6408, 5.86 }, { 6787, 272.1896, +20.8144, 4.36 }, { 6788, 272.7300, -32.2003, 6.16 },
+ { 6789, 263.0537, +86.5864, 4.36 }, { 6790, 271.7229, +50.8228, 6.29 }, { 6791, 271.8700, +43.4617, 5.00 }, { 6792, 271.7763, +49.7106, 6.32 },
+ { 6793, 272.0092, +36.4014, 5.48 }, { 6794, 272.2204, +20.0453, 5.10 }, { 6795, 272.3908,  +3.9933, 5.73 }, { 6796, 273.5675, -62.3106, 6.47 },
+ { 6797, 272.4750,  +3.1197, 5.69 }, { 6798, 272.8117, -18.1578, 6.36 }, { 6799, 272.2925, +30.4694, 6.38 }, { 6800, 272.6679,  +3.3242, 5.51 },
+ { 6801, 272.9308, -22.2989, 4.98 }, { 6802, 272.9925, -27.0986, 6.51 }, { 6803, 272.5363, +16.4767, 6.09 }, { 6804, 273.3025, -40.6639, 5.47 },
+ { 6805, 273.9204, -62.9444, 5.60 }, { 6806, 272.4063, +38.4575, 6.40 }, { 6807, 272.4958, +36.4664, 5.58 }, { 6808, 274.5038, -67.7708, 6.33 },
+ { 6809, 270.0142, +80.0008, 6.04 }, { 6810, 270.0383, +80.0042, 5.68 }, { 6811, 262.7000, +86.9681, 5.79 }, { 6812, 273.4408, -20.9411, 3.86 },
+ { 6813, 273.2917,  -3.9883, 6.59 }, { 6814, 272.9379, +33.4469, 5.88 }, { 6815, 272.9758, +31.4053, 4.97 }, { 6816, 273.5663, -20.2869, 5.44 },
+ { 6817, 272.6317, +54.2867, 5.95 }, { 6818, 273.9696, -43.7933, 5.46 }, { 6819, 274.2813, -55.9767, 5.33 }, { 6820, 273.3188, +21.8803, 6.12 },
+ { 6821, 274.2538, -50.9317, 6.06 }, { 6822, 273.8037, -19.2717, 5.38 }, { 6823, 273.8037, -19.6119, 5.95 }, { 6824, 273.1775, +41.1469, 6.36 },
+ { 6825, 273.8783, -17.3386, 6.07 }, { 6826, 273.2700, +38.7736, 6.04 }, { 6827, 272.7796, +60.4094, 6.49 }, { 6828, 274.9175, -62.1131, 6.18 },
+ { 6829, 275.9004, -74.9558, 5.47 }, { 6830, 273.9917,  -2.3825, 6.36 }, { 6831, 273.6833, +29.2072, 6.56 }, { 6832, 274.4067, -35.2383, 3.11 },
+ { 6833, 274.4004, -33.8928, 6.16 }, { 6834, 274.0233,  +2.3778, 6.01 }, { 6835, 274.3500, -27.3475, 6.19 }, { 6836, 274.3488, -27.7108, 6.40 },
+ { 6837, 277.3313, -79.7672, 5.95 }, { 6838, 274.2983, -16.6261, 5.75 }, { 6839, 274.6667, -41.7117, 6.30 }, { 6840, 274.2213,  -2.9928, 6.00 },
+ { 6841, 274.3687, -17.5367, 6.54 }, { 6842, 274.5133, -26.9575, 4.65 }, { 6843, 274.3508,  -8.2414, 6.31 }, { 6844, 274.2700,  +1.0058, 6.63 },
+ { 6845, 273.9117, +42.1594, 5.59 }, { 6846, 274.6737, -24.3953, 6.51 }, { 6847, 273.8858, +45.2094, 6.29 }, { 6848, 274.6804, -17.3806, 6.84 },
+ { 6849, 273.6712, +56.5883, 6.37 }, { 6850, 273.4742, +64.3972, 5.03 }, { 6851, 274.5121, +13.7769, 6.30 }, { 6852, 274.5321, +18.1314, 5.99 },
+ { 6853, 274.2783, +40.9367, 6.11 }, { 6854, 274.5321, +23.2967, 6.63 }, { 6855, 275.8067, -60.5061, 4.36 }, { 6856, 275.2304, -36.5125, 6.45 },
+ { 6857, 274.7896,  +7.2597, 5.39 }, { 6858, 275.0367, -14.1683, 5.39 }, { 6859, 275.2487, -28.1719, 2.70 }, { 6860, 274.7946, +24.4461, 5.27 },
+ { 6861, 275.3808, -23.0850, 6.25 }, { 6862, 275.5775, -37.3431, 5.10 }, { 6863, 275.3463, -17.1400, 5.75 }, { 6864, 275.5008, -27.5700, 6.16 },
+ { 6865, 273.8208, +68.7558, 5.95 }, { 6866, 275.2171,  +3.3772, 4.86 }, { 6867, 274.9671, +29.6661, 5.99 }, { 6868, 275.0746, +21.9614, 4.95 },
+ { 6869, 275.3275,  -1.1011, 3.26 }, { 6870, 275.7213, -35.3306, 5.34 }, { 6871, 276.3813, -62.9786, 6.14 }, { 6872, 274.9654, +36.0644, 4.33 },
+ { 6873, 275.3687,  +5.4358, 6.13 }, { 6874, 275.8704, -35.7617, 5.55 }, { 6875, 276.0758, -43.8897, 5.25 }, { 6876, 275.2379, +29.8589, 5.63 },
+ { 6877, 275.2542, +28.8700, 5.12 }, { 6878, 275.7592,  -9.7814, 6.33 }, { 6879, 276.0429, -33.6153, 1.85 }, { 6880, 274.9837, +51.3478, 6.30 },
+ { 6881, 275.8008, -11.9853, 5.73 }, { 6882, 275.5363, +23.2853, 5.41 }, { 6883, 275.6471, +12.0289, 5.89 }, { 6884, 275.9146,  -7.0658, 4.68 },
+ { 6885, 275.7042, +17.8267, 5.25 }, { 6886, 275.2796, +49.7256, 6.40 }, { 6887, 275.7621, +16.6881, 6.22 }, { 6888, 276.2563, -29.2433, 5.60 },
+ { 6889, 276.3404, -34.0083, 6.15 }, { 6890, 276.0146,  -2.4167, 6.38 }, { 6891, 275.3863, +49.1217, 5.05 }, { 6892, 276.1754,  -6.9247, 6.31 },
+ { 6893, 276.4775, -32.0547, 6.30 }, { 6894, 276.7246, -47.8831, 5.46 }, { 6895, 275.9246, +21.7697, 3.84 }, { 6896, 276.3375, -19.4583, 4.81 },
+ { 6897, 276.7433, -44.0317, 3.51 }, { 6898, 276.2375,  -0.4206, 6.15 }, { 6899, 278.2304, -72.0344, 5.89 }, { 6900, 276.2867,  +5.0847, 6.74 },
+ { 6901, 275.9892, +38.7392, 6.36 }, { 6902, 276.4117,  +8.0319, 5.65 }, { 6903, 276.0575, +39.5072, 5.12 }, { 6904, 276.2437, +27.3953, 6.27 },
+ { 6905, 277.2079, -48.9292, 4.13 }, { 6906, 276.4808, +14.9667, 6.37 }, { 6907, 276.9563, -28.1836, 5.92 }, { 6908, 277.4862, -56.4769, 5.76 },
+ { 6909, 276.9325, -25.3653, 6.31 }, { 6910, 277.1129, -37.0044, 5.64 }, { 6911, 275.9492, +53.3008, 6.32 }, { 6912, 280.5587, -80.1922, 6.27 },
+ { 6913, 276.9925, -24.5783, 2.81 }, { 6914, 277.0258, -25.2428, 6.27 }, { 6915, 277.3037, -42.1542, 6.36 }, { 6916, 277.8433, -61.7217, 4.64 },
+ { 6917, 276.4950, +29.8289, 5.83 }, { 6918, 276.8021,  +0.1961, 5.21 }, { 6919, 276.9854, -16.2000, 6.20 }, { 6920, 275.1896, +71.3378, 4.22 },
+ { 6921, 277.3200, -37.1489, 6.63 }, { 6922, 277.4825, -46.7797, 5.70 }, { 6923, 275.9771, +58.8006, 4.98 }, { 6924, 276.6704, +26.4494, 6.53 },
+ { 6925, 276.9596,  +3.7486, 6.07 }, { 6926, 277.2392, -25.4183, 6.50 }, { 6927, 275.2642, +72.7328, 3.57 }, { 6928, 276.9950,  +6.1942, 5.73 },
+ { 6929, 277.3417, -24.7436, 6.59 }, { 6930, 277.2996, -13.4342, 4.70 }, { 6931, 277.7625, -40.0864, 6.04 }, { 6932, 277.4450, -13.4183, 5.96 },
+ { 6933, 277.5496, -17.2711, 5.66 }, { 6934, 277.9392, -44.0850, 4.96 }, { 6935, 277.4208,  -0.0147, 5.39 }, { 6936, 277.7700, -31.0108, 5.34 },
+ { 6937, 277.9842, -42.4922, 5.72 }, { 6938, 278.0083, -44.2428, 5.07 }, { 6939, 278.3729, -57.2908, 6.44 }, { 6940, 277.5596,  -4.2758, 6.28 },
+ { 6941, 277.5213,  +4.0653, 6.69 }, { 6942, 278.0892, -38.2961, 5.16 }, { 6943, 277.3988, +23.8661, 5.90 }, { 6944, 277.8596, -17.5972, 5.14 },
+ { 6945, 276.4962, +65.5636, 4.82 }, { 6946, 277.8571,  -9.2042, 5.72 }, { 6947, 277.9721, -18.8750, 6.68 }, { 6948, 278.2538, -38.1078, 6.22 },
+ { 6949, 276.9262, +59.5492, 6.43 }, { 6950, 277.6733, +20.8153, 6.50 }, { 6951, 278.3758, -41.6875, 4.64 }, { 6952, 278.3471, -37.2797, 6.32 },
+ { 6953, 278.3463, -37.2739, 5.65 }, { 6954, 278.6300, -51.1081, 6.22 }, { 6955, 277.7683, +16.9286, 5.77 }, { 6956, 278.0867, -13.3558, 6.37 },
+ { 6957, 277.9875,  -0.9969, 5.94 }, { 6958, 278.0292,  +3.6597, 6.43 }, { 6959, 278.1804, -13.1344, 5.50 }, { 6960, 278.4908, -32.9833, 5.28 },
+ { 6961, 278.4729, -23.9675, 5.49 }, { 6962, 278.4125, -13.1464, 5.76 }, { 6963, 278.3454,  -4.0886, 6.36 }, { 6964, 282.9912, -82.6836, 7.16 },
+ { 6965, 278.6367, -23.7775, 6.51 }, { 6966, 278.1925, +23.6169, 5.84 }, { 6967, 278.3471,  +8.2683, 6.42 }, { 6968, 278.2079, +30.5542, 5.48 },
+ { 6969, 278.8388, -19.1592, 6.48 }, { 6970, 278.7600,  -9.0228, 5.14 }, { 6971, 278.3463, +30.8925, 6.59 }, { 6972, 278.9987, -28.3008, 6.37 },
+ { 6973, 278.8017,  -7.7558, 3.85 }, { 6974, 278.0475, +52.1156, 6.56 }, { 6975, 278.5817, +20.4664, 6.57 }, { 6976, 278.6979, +10.8917, 6.40 },
+ { 6977, 278.8025, +18.2033, 5.78 }, { 6978, 278.1438, +57.0456, 4.77 }, { 6979, 277.8117, +65.4361, 6.59 }, { 6980, 278.8767, +23.6056, 5.61 },
+ { 6981, 278.9717, +16.9756, 6.21 }, { 6982, 280.7588, -70.5719, 4.01 }, { 6983, 278.4862, +52.3536, 5.36 }, { 6984, 278.8062, +34.4578, 6.10 },
+ { 6985, 279.1158,  +9.1225, 5.39 }, { 6986, 279.8096, -46.0903, 5.86 }, { 6987, 279.1629,  +6.6719, 5.45 }, { 6988, 279.4767, -20.6022, 5.94 },
+ { 6989, 279.5192, -13.9953, 6.47 }, { 6990, 279.6279, -22.4950, 5.81 }, { 6991, 279.8958, -42.8139, 5.37 }, { 6992, 279.3025, +11.4217, 6.42 },
+ { 6993, 279.4000,  +0.3094, 5.75 }, { 6994, 281.9558, -76.1328, 6.39 }, { 6995, 279.2875, +16.1983, 6.29 }, { 6996, 280.5938, -63.3569, 6.37 },
+ { 6997, 279.1550, +33.4689, 5.42 }, { 6998, 279.7225, -20.9481, 5.86 }, { 6999, 279.5988,  -2.8064, 6.49 }, { 7000, 279.5796,  -0.8867, 6.66 },
+ { 7001, 279.2346, +38.7836, 0.03 }, { 7002, 279.5875,  +8.8339, 6.40 }, { 7003, 279.1900, +43.2219, 6.20 }, { 7004, 280.9050, -63.4489, 5.78 },
+ { 7005, 280.3775, -47.9050, 6.49 }, { 7006, 277.4371, +77.5469, 5.64 }, { 7007, 280.0021,  -6.2094, 5.84 }, { 7008, 279.9038,  +5.2642, 6.38 },
+ { 7009, 279.5271, +39.6681, 6.04 }, { 7010, 279.9650,  +7.3583, 6.28 }, { 7011, 280.4650, -22.1667, 6.23 }, { 7012, 281.3621, -63.1286, 4.79 },
+ { 7013, 279.0554, +65.4886, 6.06 }, { 7014, 280.4271, -13.4358, 6.42 }, { 7015, 281.2979, -60.9050, 6.04 }, { 7016, 280.0083, +30.8494, 6.36 },
+ { 7017, 279.8879, +40.9350, 6.25 }, { 7018, 279.3896, +62.5267, 5.74 }, { 7019, 280.0508, +38.3672, 6.45 }, { 7020, 280.5683,  -8.9475, 4.72 },
+ { 7021, 280.9454, -37.6764, 5.13 }, { 7022, 281.3488, -55.1183, 6.22 }, { 7023, 280.7300, -18.7161, 6.35 }, { 7024, 280.6504,  -6.9267, 6.15 },
+ { 7025, 276.0383, +83.1753, 6.17 }, { 7026, 281.0321, -35.2814, 6.32 }, { 7027, 282.4312, -71.0053, 6.06 }, { 7028, 279.9700, +52.1961, 6.00 },
+ { 7029, 281.0808, -34.3581, 4.87 }, { 7030, 280.4221, +31.6178, 6.41 }, { 7031, 281.2383, -38.3136, 5.43 }, { 7032, 280.8804,  -7.7247, 4.90 },
+ { 7033, 280.5338, +34.7467, 6.47 }, { 7034, 280.9642,  -5.1814, 6.31 }, { 7035, 281.2067, -24.9889, 5.83 }, { 7036, 282.1575, -64.9222, 5.73 },
+ { 7037, 281.7462, -49.9056, 6.54 }, { 7038, 281.3279, -20.9986, 6.36 }, { 7039, 281.4142, -25.0092, 3.17 }, { 7040, 281.2079,  +2.0600, 5.02 },
+ { 7041, 280.8196, +39.3003, 6.45 }, { 7042, 280.2346, +62.7497, 6.09 }, { 7043, 280.9004, +36.5567, 6.01 }, { 7044, 280.9650, +31.9267, 5.70 },
+ { 7045, 281.5050, -18.3936, 6.42 }, { 7046, 281.5858, -21.6078, 5.37 }, { 7047, 281.1675, +23.5897, 6.31 }, { 7048, 281.3683,  +5.4997, 5.83 },
+ { 7049, 280.6579, +55.5394, 5.04 }, { 7050, 281.9358, -39.5939, 5.24 }, { 7051, 281.0850, +39.6700, 5.06 }, { 7052, 281.0846, +39.6711, 6.02 },
+ { 7053, 281.0954, +39.6131, 5.14 }, { 7054, 281.0954, +39.6128, 5.37 }, { 7055, 281.6804,  -9.8750, 5.71 }, { 7056, 281.1933, +37.6050, 4.36 },
+ { 7057, 281.2008, +37.5944, 5.73 }, { 7058, 281.3988, +21.9850, 6.51 }, { 7059, 281.6187,  +0.9617, 5.90 }, { 7060, 280.8708, +53.8719, 6.11 },
+ { 7061, 281.4154, +20.5464, 4.19 }, { 7062, 282.2104, -42.3200, 5.49 }, { 7063, 281.7937,  -3.2522, 4.22 }, { 7064, 281.5188, +26.6622, 4.83 },
+ { 7065, 282.3642, -44.1897, 5.81 }, { 7066, 281.8708,  -4.2950, 5.20 }, { 7067, 281.6725, +18.7058, 6.17 }, { 7068, 282.3958, -42.5661, 5.61 },
+ { 7069, 281.7554, +18.1814, 4.36 }, { 7070, 282.3217, -33.2514, 6.62 }, { 7071, 281.2308, +54.8967, 6.23 }, { 7072, 282.1888, -17.3986, 6.47 },
+ { 7073, 281.5542, +41.4417, 6.07 }, { 7074, 283.0542, -61.8125, 4.22 }, { 7075, 281.0758, +61.0481, 5.99 }, { 7076, 282.0113,  +4.2414, 6.21 },
+ { 7077, 282.3979, -18.8578, 6.75 }, { 7078, 282.4171, -19.6753, 5.24 }, { 7079, 282.0683, +23.5142, 6.15 }, { 7080, 281.7458, +46.3150, 6.52 },
+ { 7081, 281.9896, +31.7569, 6.06 }, { 7082, 280.7925, +70.7928, 6.44 }, { 7083, 282.4208,  -4.0872, 5.99 }, { 7084, 281.6796, +52.9881, 5.88 },
+ { 7085, 282.4046,  +0.8358, 6.25 }, { 7086, 282.2225, +19.3286, 5.88 }, { 7087, 283.1650, -51.8925, 5.17 }, { 7088, 282.7104, -21.8378, 6.61 },
+ { 7089, 282.5833,  -6.0925, 6.80 }, { 7090, 281.9167, +49.0750, 6.40 }, { 7091, 282.3100, +25.0464, 6.59 }, { 7092, 283.1129, -45.4047, 5.54 },
+ { 7093, 283.3004, -50.0689, 6.31 }, { 7094, 282.7437,  -8.2258, 5.83 }, { 7095, 283.2604, -47.6400, 6.19 }, { 7096, 282.0671, +48.7675, 6.12 },
+ { 7097, 283.2483, -45.4142, 6.19 }, { 7098, 282.4333, +31.6292, 6.64 }, { 7099, 282.6900, +10.9764, 6.55 }, { 7100, 282.4413, +32.8128, 5.91 },
+ { 7101, 282.8421,  -2.6822, 6.10 }, { 7102, 282.4704, +32.5508, 5.25 }, { 7103, 283.1187, -25.3497, 6.29 }, { 7104, 283.1542, -28.6206, 6.13 },
+ { 7105, 283.1737, -29.2658, 6.63 }, { 7106, 282.5200, +33.3628, 3.45 }, { 7107, 284.2375, -66.7664, 4.44 }, { 7108, 283.6346, -48.1214, 6.60 },
+ { 7109, 283.0079, +13.9656, 6.14 }, { 7110, 283.2579,  -8.4239, 6.34 }, { 7111, 284.2279, -61.1989, 6.48 }, { 7112, 282.8996, +28.7836, 6.18 },
+ { 7113, 283.0683, +21.4253, 5.48 }, { 7114, 283.5004, -20.6403, 5.69 }, { 7115, 282.9021, +36.5386, 6.09 }, { 7116, 283.5425, -21.2550, 4.83 },
+ { 7117, 281.4446, +74.0856, 5.27 }, { 7118, 283.0296, +41.3833, 6.28 }, { 7119, 283.6796, -14.3969, 5.10 }, { 7120, 283.7796, -21.3286, 4.99 },
+ { 7121, 283.8163, -25.7033, 2.02 }, { 7122, 284.0704, -41.2894, 5.36 }, { 7123, 282.8958, +52.9750, 5.51 }, { 7124, 281.5925, +75.4339, 5.35 },
+ { 7125, 282.8004, +59.3883, 4.66 }, { 7126, 283.8792, -15.6233, 5.79 }, { 7127, 284.6517, -59.7994, 5.14 }, { 7128, 284.0025, -22.8264, 5.93 },
+ { 7129, 284.1687, -36.6567, 5.38 }, { 7130, 285.0146, -65.3467, 6.01 }, { 7131, 283.4317, +36.9717, 5.58 }, { 7132, 283.5550, +27.9094, 5.62 },
+ { 7133, 283.6871, +22.6450, 4.59 }, { 7134, 284.6154, -51.0614, 4.87 }, { 7135, 283.8646,  +6.6153, 5.57 }, { 7136, 284.3946, -38.1767, 6.31 },
+ { 7137, 283.3067, +50.7083, 4.92 }, { 7138, 283.5596, +41.2256, 7.30 }, { 7139, 283.6258, +36.8989, 4.30 }, { 7140, 283.7188, +33.9686, 6.02 },
+ { 7141, 284.0550,  +4.2036, 4.62 }, { 7142, 284.0608,  +4.2019, 4.98 }, { 7143, 284.0946,  -0.2000, 6.22 }, { 7144, 284.1067,  +2.4711, 6.15 },
+ { 7145, 284.3354, -19.3436, 5.08 }, { 7146, 283.7175, +41.6028, 5.44 }, { 7147, 284.0163, +17.9950, 6.63 }, { 7148, 284.0258, +18.1053, 5.69 },
+ { 7149, 284.2654,  -4.1539, 4.83 }, { 7150, 284.4325, -20.8933, 3.51 }, { 7151, 284.5888, -30.9639, 6.12 }, { 7152, 284.6808, -36.8925, 4.87 },
+ { 7153, 283.4429, +57.4869, 6.22 }, { 7154, 283.6963, +48.8597, 5.77 }, { 7155, 284.5854, -23.1233, 6.62 }, { 7156, 284.7962, -38.4653, 6.49 },
+ { 7157, 283.8338, +43.9461, 4.04 }, { 7158, 284.3192,  +2.5353, 5.57 }, { 7159, 284.6025, -21.4706, 6.14 }, { 7160, 281.4088, +79.9425, 6.39 },
+ { 7161, 285.8737, -67.2447, 5.88 }, { 7162, 284.2567, +32.9014, 5.22 }, { 7163, 284.5992,  +6.2403, 6.21 }, { 7164, 284.8617, -17.4331, 6.37 },
+ { 7165, 284.5612, +17.3608, 5.38 }, { 7166, 284.8492, -11.1594, 5.53 }, { 7167, 284.6954, +13.9067, 5.89 }, { 7168, 285.1033, -23.0578, 6.36 },
+ { 7169, 285.2633, -36.9392, 6.69 }, { 7170, 285.2679, -36.9381, 6.40 }, { 7171, 284.6879, +19.7942, 6.50 }, { 7172, 284.7738, +13.6225, 5.23 },
+ { 7173, 284.8229, +10.1408, 6.75 }, { 7174, 284.5079, +38.2661, 5.89 }, { 7175, 284.1875, +57.8150, 5.66 }, { 7176, 284.9058, +15.0683, 4.02 },
+ { 7177, 285.5363, -40.0900, 6.23 }, { 7178, 284.7358, +32.6894, 3.24 }, { 7179, 284.6942, +40.6792, 6.22 }, { 7180, 283.5996, +71.2972, 4.82 },
+ { 7181, 284.9396, +26.2306, 5.27 }, { 7182, 285.4075, -21.3044, 6.24 }, { 7183, 284.9921, +22.8147, 6.29 }, { 7184, 284.3683, +58.2253, 6.46 },
+ { 7185, 284.8012, +39.2178, 6.41 }, { 7186, 285.3896, -14.7175, 6.32 }, { 7187, 284.1067, +65.2581, 5.63 }, { 7188, 285.7788, -41.9047, 4.75 },
+ { 7189,   0.0000,  +0.0000, 0.00 }, { 7190, 285.9892, -50.9814, 5.93 }, { 7191, 284.3225, +62.3967, 6.45 }, { 7192, 285.0038, +32.1456, 4.93 },
+ { 7193, 285.4200,  -4.2611, 4.02 }, { 7194, 285.6529, -28.1197, 2.60 }, { 7195, 285.6154, -23.1531, 5.65 }, { 7196, 284.7483, +50.8094, 6.30 },
+ { 7197, 285.8238, -37.7467, 5.74 }, { 7198, 285.2729, +19.3097, 6.39 }, { 7199, 283.3883, +75.7875, 6.22 }, { 7200, 285.3442, +20.8336, 6.69 },
+ { 7201, 285.0792, +40.6842, 6.65 }, { 7202, 285.3225, +26.2914, 5.69 }, { 7203, 285.7658, -18.7547, 6.05 }, { 7204, 285.2300, +33.8022, 6.01 },
+ { 7205, 285.7792, -18.8967, 6.37 }, { 7206, 285.3954, +25.0258, 6.72 }, { 7207, 285.4563, +22.2639, 6.40 }, { 7208, 285.5900,  +8.3742, 6.30 },
+ { 7209, 285.7271,  -2.3011, 5.42 }, { 7210, 285.0571, +50.5336, 5.38 }, { 7211, 286.1046, -30.9531, 5.50 }, { 7212, 285.4513, +33.6214, 6.39 },
+ { 7213, 286.5829, -51.6592, 5.16 }, { 7214, 285.8842,  +1.8189, 5.83 }, { 7215, 285.3600, +46.9347, 5.01 }, { 7216, 285.7192, +19.6611, 6.09 },
+ { 7217, 286.1708, -20.2583, 3.77 }, { 7218, 285.1808, +55.6583, 5.48 }, { 7219, 286.0446,  +3.3306, 6.73 }, { 7220, 286.1008,  -4.3150, 6.90 },
+ { 7221, 287.4696, -67.5753, 5.33 }, { 7222, 285.9271, +21.2678, 6.52 }, { 7223, 286.7317, -47.7008, 5.97 }, { 7224, 284.7192, +69.5311, 6.52 },
+ { 7225, 286.2400,  -3.9686, 5.42 }, { 7226, 286.6046, -36.9367, 4.93 }, { 7227, 286.6046, -36.9367, 4.99 }, { 7228, 317.1925, -87.0436, 5.47 },
+ { 7229, 285.5292, +52.2611, 6.31 }, { 7230, 286.4217, -14.3397, 5.97 }, { 7231, 286.3275,  -0.4872, 6.53 }, { 7232, 286.7188, -36.1897, 6.16 },
+ { 7233, 287.2171, -54.2797, 6.49 }, { 7234, 286.7350, -26.3294, 3.32 }, { 7235, 286.3525, +13.8633, 2.99 }, { 7236, 286.5621,  -3.1175, 3.44 },
+ { 7237, 286.2412, +31.7444, 5.56 }, { 7238, 286.2429, +30.7333, 6.06 }, { 7239, 286.7179, -15.7711, 6.03 }, { 7240, 286.8788, -27.3631, 6.04 },
+ { 7241, 286.7854, -17.2622, 6.29 }, { 7242, 287.0871, -39.5033, 4.59 }, { 7243, 286.5925,  +8.2300, 6.09 }, { 7244, 286.4463, +29.9217, 6.31 },
+ { 7245, 286.7879,  +0.6417, 6.56 }, { 7246, 287.0608, -23.3431, 6.30 }, { 7247, 284.4883, +77.0508, 6.54 }, { 7248, 286.7442, +11.0714, 5.09 },
+ { 7249, 287.0696, -18.7100, 5.54 }, { 7250, 286.6600, +24.2508, 5.77 }, { 7251, 286.2300, +53.3967, 5.38 }, { 7252, 286.2912, +49.9233, 6.43 },
+ { 7253, 286.6571, +28.6286, 5.55 }, { 7254, 287.3679, -36.0956, 4.11 }, { 7255, 287.4154, -38.1719, 6.46 }, { 7256, 287.4017, -35.8353, 6.56 },
+ { 7257, 287.4908, -40.1075, 5.88 }, { 7258, 286.5708, +41.4139, 6.49 }, { 7259, 287.5071, -38.6592, 4.11 }, { 7260, 286.9887, +16.8533, 6.07 },
+ { 7261, 286.8567, +32.5017, 5.23 }, { 7262, 286.8254, +36.1003, 5.28 }, { 7263, 287.0150, +21.6989, 6.23 }, { 7264, 287.4408, -20.9764, 2.89 },
+ { 7265, 287.4504, -18.1964, 6.13 }, { 7266, 287.2496,  +6.0733, 5.22 }, { 7267, 287.1675, +16.8514, 6.48 }, { 7268, 287.7575, -38.9950, 6.36 },
+ { 7269, 287.4650,  +0.4281, 6.34 }, { 7270, 287.8288, -28.4978, 6.30 }, { 7271, 288.1921, -49.5136, 6.13 }, { 7272, 287.2683, +34.6006, 6.74 },
+ { 7273, 288.0408, -36.4172, 6.57 }, { 7274, 289.1187, -68.8094, 6.27 }, { 7275, 287.1075, +52.4256, 5.81 }, { 7276, 288.1167, -20.3419, 6.41 },
+ { 7277, 288.3071, -24.0933, 5.80 }, { 7278, 289.3000, -65.3386, 5.53 }, { 7279, 288.1696,  -6.0606, 5.34 }, { 7280, 287.8788, +26.7358, 6.36 },
+ { 7281, 288.6654, -44.8067, 5.92 }, { 7282, 288.3146, -11.7175, 5.51 }, { 7283, 287.9417, +31.2833, 5.98 }, { 7284, 287.8463, +40.4292, 6.18 },
+ { 7285, 288.1433, +16.8464, 6.73 }, { 7286, 288.1529, +21.5544, 5.93 }, { 7287, 288.4279,  +2.2936, 5.15 }, { 7288, 288.4337,  +5.5158, 6.49 },
+ { 7289, 289.0904, -44.5336, 5.40 }, { 7290, 287.4408, +65.9786, 6.25 }, { 7291, 288.8883, -23.8208, 6.25 }, { 7292, 288.8850, -24.7433, 4.85 },
+ { 7293, 288.0192, +49.8542, 6.75 }, { 7294, 288.0208, +49.8561, 6.57 }, { 7295, 287.9187, +56.8592, 5.12 }, { 7296, 289.1367, -32.4783, 6.25 },
+ { 7297, 289.5392, -52.6133, 6.38 }, { 7298, 288.4396, +39.1461, 4.39 }, { 7299, 288.7608, +20.2033, 6.00 }, { 7300, 288.8338, +15.0836, 5.57 },
+ { 7301, 288.8225, +21.2322, 5.64 }, { 7302, 288.8533, +30.5264, 5.85 }, { 7303, 289.1292,  +4.8347, 5.59 }, { 7304, 289.4088, -17.0469, 4.96 },
+ { 7305, 288.9875, +27.4556, 6.54 }, { 7306, 289.0542, +21.3903, 4.77 }, { 7307, 289.1117, +14.5447, 5.63 }, { 7308, 288.9975, +27.9269, 6.16 },
+ { 7309, 288.4800, +57.7050, 4.99 }, { 7310, 288.1388, +67.6617, 3.07 }, { 7311, 288.8304, +50.0708, 6.27 }, { 7312, 287.2908, +76.5606, 5.13 },
+ { 7313, 289.4508,  +2.0317, 6.19 }, { 7314, 289.0921, +38.1336, 4.36 }, { 7315, 289.4542, +11.5953, 5.28 }, { 7316, 289.9167, -34.5786, 5.59 },
+ { 7317, 289.7504, -14.4636, 6.06 }, { 7318, 289.4317, +23.0256, 5.43 }, { 7319, 289.6354,  +1.0853, 5.10 }, { 7320, 291.0225, -67.6289, 6.34 },
+ { 7321, 289.7121,  +0.3392, 6.41 }, { 7322, 289.2142, +46.9992, 6.00 }, { 7323, 290.1092, -30.1822, 6.58 }, { 7324, 289.5033, +31.0222, 6.68 },
+ { 7325, 289.7196,  +9.6181, 6.32 }, { 7326, 289.7021, +19.6106, 6.58 }, { 7327, 290.1588, -21.5975, 5.58 }, { 7328, 289.2758, +53.3686, 3.77 },
+ { 7329, 290.7129, -53.5764, 5.05 }, { 7330, 290.3746, -33.0161, 6.48 }, { 7331, 289.9137, +12.3747, 5.53 }, { 7332, 289.9708, +11.5350, 6.02 },
+ { 7333, 290.1371,  -4.5842, 5.01 }, { 7334, 290.5400, -41.9839, 6.34 }, { 7335, 289.7658, +33.3889, 6.60 }, { 7336, 290.1488,  +0.8922, 5.49 },
+ { 7337, 290.6596, -43.5411, 4.01 }, { 7338, 289.7550, +37.4453, 6.22 }, { 7339, 290.4046, -18.7658, 6.26 }, { 7340, 290.4183, -16.1528, 3.93 },
+ { 7341, 289.6571, +49.5697, 6.31 }, { 7342, 290.4317, -14.0450, 4.61 }, { 7343, 290.8050, -43.2003, 4.29 }, { 7344, 290.4621, -17.6917, 5.87 },
+ { 7345, 289.9121, +37.3306, 6.31 }, { 7346, 290.1379, +35.1861, 6.31 }, { 7347, 290.5863,  -7.7989, 6.31 }, { 7348, 290.9717, -39.3839, 3.97 },
+ { 7349, 290.5896,  +0.2525, 5.83 }, { 7350, 291.0892, -42.2769, 6.17 }, { 7351, 289.9021, +54.3761, 6.26 }, { 7352, 288.8875, +73.3556, 4.45 },
+ { 7353, 290.7692,  -6.5997, 6.32 }, { 7354, 290.7017,  +9.9131, 6.35 }, { 7355, 291.1254, -26.1344, 6.04 }, { 7356, 290.0671, +57.6453, 5.91 },
+ { 7357, 290.7842, +14.9211, 6.64 }, { 7358, 290.7121, +26.2625, 5.18 }, { 7359, 290.6392, +33.5181, 6.06 }, { 7360, 291.2671, -28.6908, 5.93 },
+ { 7361, 289.9421, +64.3908, 6.52 }, { 7362, 291.3188, -23.4914, 5.03 }, { 7363, 291.3737, -22.0378, 5.43 }, { 7364, 290.9454, +20.2644, 6.40 },
+ { 7365, 290.3558, +57.7669, 6.43 }, { 7366, 291.2567,  -3.1158, 6.52 }, { 7367, 291.3400, -12.1031, 5.69 }, { 7368, 290.8917, +33.2222, 6.37 },
+ { 7369, 291.0921, +16.9378, 6.25 }, { 7370, 291.9504, -53.6747, 5.69 }, { 7371, 290.1671, +65.7147, 4.59 }, { 7372, 291.0317, +29.6214, 4.97 },
+ { 7373, 291.2425, +11.9444, 5.16 }, { 7374, 291.0933, +28.0878, 6.53 }, { 7375, 291.5800, -20.2233, 5.59 }, { 7376, 291.0254, +36.4519, 6.36 },
+ { 7377, 291.3746,  +3.1147, 3.36 }, { 7378, 291.5462, -14.9469, 5.72 }, { 7379, 291.6025, -13.4489, 6.70 }, { 7380, 291.7354, -28.2567, 5.67 },
+ { 7381, 290.8492, +50.2714, 6.51 }, { 7382, 290.9854, +43.3881, 5.84 }, { 7383, 292.7954, -67.5661, 5.96 }, { 7384, 291.3433, +20.2714, 6.31 },
+ { 7385, 291.3692, +19.7986, 5.16 }, { 7386, 291.3575, +24.9128, 6.19 }, { 7387, 291.6296,  +0.3386, 4.66 }, { 7388, 292.4692, -54.5586, 6.13 },
+ { 7389, 291.6004, +13.0239, 5.74 }, { 7390, 291.5550, +20.0978, 5.63 }, { 7391, 291.6196, +19.8914, 5.81 }, { 7392, 292.3496, -42.5542, 5.71 },
+ { 7393, 292.6438, -54.8900, 6.30 }, { 7394, 259.2367, +89.0378, 6.38 }, { 7395, 291.5379, +36.3178, 5.15 }, { 7396, 291.8913, +14.2825, 6.32 },
+ { 7397, 292.0867,  +2.9303, 5.85 }, { 7398, 292.4675, -25.0144, 5.52 }, { 7399, 292.5612, -31.9078, 6.60 }, { 7400, 292.2542,  +1.9503, 5.80 },
+ { 7401, 291.4446, +58.0272, 6.60 }, { 7402, 292.3396,  -6.9561, 6.61 }, { 7403, 291.9021, +37.9411, 6.34 }, { 7404, 292.3250,  +0.2461, 6.25 },
+ { 7405, 292.1762, +24.6650, 4.44 }, { 7406, 292.2375, +24.7686, 5.81 }, { 7407, 292.3421, +14.5958, 5.56 }, { 7408, 291.8579, +52.3206, 5.75 },
+ { 7409, 292.3371, +20.2797, 6.33 }, { 7410, 292.7250, -20.6878, 6.13 }, { 7411, 293.2242, -52.8142, 5.75 }, { 7412, 292.5437,  +2.9042, 6.09 },
+ { 7413, 291.6104, +62.5572, 6.38 }, { 7414, 292.6658,  -1.2111, 5.03 }, { 7415, 292.6379,  +3.4444, 6.05 }, { 7416, 293.3400, -44.7281, 5.61 },
+ { 7417, 292.6804, +27.9597, 3.08 }, { 7418, 292.6888, +27.9653, 5.11 }, { 7419, 292.6954, +36.2286, 6.25 }, { 7420, 292.4262, +51.7297, 3.79 },
+ { 7421, 292.8408, +26.6172, 5.87 }, { 7422, 293.5354, -39.9653, 5.89 }, { 7423, 290.4175, +79.6028, 6.05 }, { 7424, 293.8042, -47.9008, 4.90 },
+ { 7425, 288.7825, +83.4628, 6.53 }, { 7426, 292.9429, +34.4531, 4.74 }, { 7427, 292.8304, +50.3067, 5.53 }, { 7428, 292.8067, +55.7319, 6.37 },
+ { 7429, 293.5225,  +7.3789, 4.45 }, { 7430, 293.7804,  -9.4397, 5.12 }, { 7431, 294.0071, -23.2808, 5.65 }, { 7432, 293.8742,  -6.5397, 6.34 },
+ { 7433, 293.8900, -11.7472, 6.27 }, { 7434, 294.6079, -56.0167, 6.18 }, { 7435, 294.9671, -65.3144, 6.39 }, { 7436, 293.4017, +38.7622, 6.61 },
+ { 7437, 293.6454, +19.7733, 5.00 }, { 7438, 293.8550,  +2.9133, 6.38 }, { 7439, 294.1087, -17.1472, 6.11 }, { 7440, 294.1767, -23.1164, 4.60 },
+ { 7441, 293.7121, +29.4631, 5.38 }, { 7442, 293.4233, +49.2625, 5.96 }, { 7443, 294.2638, -17.7689, 5.64 }, { 7444, 293.6717, +42.4128, 5.35 },
+ { 7445, 294.0333, +11.1500, 6.68 }, { 7446, 294.2229,  -6.9725, 4.95 }, { 7447, 294.1804,  -0.7136, 4.36 }, { 7448, 293.2921, +60.1586, 6.29 },
+ { 7449, 294.0658, +14.3917, 6.38 }, { 7450, 292.7508, +70.9894, 6.07 }, { 7451, 293.5825, +51.2367, 5.73 }, { 7452, 294.0346, +22.5858, 6.32 },
+ { 7453, 293.6662, +48.1647, 6.67 }, { 7454, 294.3933, -13.6983, 5.47 }, { 7455, 295.4063, -64.1458, 6.09 }, { 7456, 294.2188, +11.2733, 5.98 },
+ { 7457, 293.9513, +36.9444, 6.05 }, { 7458, 294.1571, +20.3328, 7.14 }, { 7459, 295.0763, -53.5825, 6.26 }, { 7460, 294.4471,  -3.3525, 5.46 },
+ { 7461, 294.9250, -44.7219, 6.25 }, { 7462, 293.0900, +69.6611, 4.68 }, { 7463, 294.3225, +16.4628, 5.66 }, { 7464, 294.9821, -38.5667, 6.61 },
+ { 7465, 293.9829, +50.2386, 6.52 }, { 7466, 294.2892, +29.3336, 6.43 }, { 7467, 294.2358, +38.3839, 6.50 }, { 7468, 294.1579, +44.6950, 5.17 },
+ { 7469, 294.1104, +50.2211, 4.48 }, { 7470, 294.9558, -22.5722, 6.34 }, { 7471, 294.7042,  +3.3817, 6.35 }, { 7472, 294.5729, +20.7828, 6.48 },
+ { 7473, 295.0296, -22.5714, 5.97 }, { 7474, 294.7983,  +5.3978, 5.17 }, { 7475, 294.8558, +16.5714, 6.38 }, { 7476, 295.1808, -15.7067, 6.20 },
+ { 7477, 294.4862, +49.2844, 6.47 }, { 7478, 294.8442, +30.1533, 4.69 }, { 7479, 295.0242, +18.0139, 4.37 }, { 7480, 295.1804,  +0.6211, 5.67 },
+ { 7481, 294.9375, +33.9792, 6.10 }, { 7482, 295.1179, +20.4767, 6.50 }, { 7483, 294.8604, +42.8183, 5.40 }, { 7484, 294.6717, +54.9739, 5.82 },
+ { 7485, 295.1654, +23.7175, 6.64 }, { 7486, 295.2729, +13.8156, 6.01 }, { 7487, 294.8933, +45.9581, 6.20 }, { 7488, 295.2621, +17.4761, 4.37 },
+ { 7489, 295.6296, -15.8761, 5.06 }, { 7490, 295.3121, +22.4528, 6.36 }, { 7491, 295.9067, -36.4611, 6.16 }, { 7492, 295.1717, +43.0778, 6.16 },
+ { 7493, 295.5533, +12.1933, 6.34 }, { 7494, 299.0063, -80.6503, 6.39 }, { 7495, 295.2092, +45.5250, 5.06 }, { 7496, 295.8896, -14.5300, 5.49 },
+ { 7497, 295.6417, +11.8267, 5.27 }, { 7498, 297.3554, -71.4967, 5.41 }, { 7499, 295.4896, +40.2539, 6.23 }, { 7500, 295.0542, +60.5072, 6.51 },
+ { 7501, 295.7046, +29.3317, 6.49 }, { 7502, 295.6858, +32.4267, 5.94 }, { 7503, 295.4538, +50.5253, 5.96 }, { 7504, 295.4667, +50.5175, 6.20 },
+ { 7505, 295.7896, +30.6786, 6.05 }, { 7506, 295.9287, +25.7719, 5.49 }, { 7507, 296.5050, -30.0914, 5.52 }, { 7508, 295.9829, +27.1356, 6.28 },
+ { 7509, 295.5171, +55.4633, 6.48 }, { 7510, 297.0050, -55.6375, 5.35 }, { 7511, 296.1421, +13.3028, 6.26 }, { 7512, 295.9642, +34.1625, 6.05 },
+ { 7513, 297.4721, -65.1872, 6.45 }, { 7514, 295.9375, +41.7731, 5.84 }, { 7515, 296.5904, -18.2389, 4.86 }, { 7516, 296.4675,  -1.1167, 6.48 },
+ { 7517, 296.0692, +37.3544, 4.89 }, { 7518, 296.2029, +29.2647, 6.82 }, { 7519, 296.4162,  +7.6133, 5.91 }, { 7520, 296.1592, +34.4139, 6.57 },
+ { 7521, 297.2296, -51.1119, 6.25 }, { 7522, 295.8108, +58.0164, 6.22 }, { 7523, 296.2042, +40.7167, 6.34 }, { 7524, 297.7554, -64.3950, 6.05 },
+ { 7525, 296.5650, +10.6133, 2.72 }, { 7526, 295.9150, +57.0425, 6.27 }, { 7527, 297.5904, -60.9386, 6.21 }, { 7528, 296.2437, +45.1308, 2.87 },
+ { 7529, 296.4150, +36.0911, 6.43 }, { 7530, 296.4642, +35.0128, 6.09 }, { 7531, 297.6867, -58.8069, 5.42 }, { 7532, 297.0125, -12.2967, 6.11 },
+ { 7533, 296.6646, +25.1339, 6.62 }, { 7534, 296.6067, +33.7278, 4.99 }, { 7535, 296.6458, +32.8886, 6.18 }, { 7536, 296.8471, +18.5342, 3.82 },
+ { 7537, 297.5575, -46.4428, 5.94 }, { 7538, 297.2983, -27.2111, 6.05 }, { 7539,   0.0000,  +0.0000, 0.00 }, { 7540, 296.9525, +25.3839, 5.95 },
+ { 7541, 297.2592,  -9.1292, 6.04 }, { 7542, 297.1267, +10.6942, 6.44 }, { 7543, 296.8658, +38.4075, 5.77 }, { 7544, 297.1754, +11.8158, 5.72 },
+ { 7545, 296.0771, +69.3369, 5.92 }, { 7546, 297.2446, +19.1422, 5.00 }, { 7547, 296.8617, +47.9078, 6.12 }, { 7548, 298.1567, -53.0289, 5.74 },
+ { 7549, 298.1625, -53.0233, 6.50 }, { 7550, 297.1829, +35.3114, 6.53 }, { 7551, 297.2108, +33.4372, 6.44 }, { 7552, 297.9608, -38.1256, 5.33 },
+ { 7553, 297.6950,  -9.2364, 5.39 }, { 7554, 297.5729,  +7.9025, 6.51 }, { 7555, 297.3646, +38.7100, 6.11 }, { 7556, 297.4775, +28.4406, 6.38 },
+ { 7557, 297.6958,  +8.8683, 0.77 }, { 7558, 298.6683, -60.8292, 6.24 }, { 7559, 297.7962,  -1.5392, 6.13 }, { 7560, 297.7567, +10.4156, 5.11 },
+ { 7561, 298.0500, -18.9550, 5.92 }, { 7562, 297.8238,  +9.6303, 6.25 }, { 7563, 296.6862, +68.4383, 6.34 }, { 7564, 297.6413, +32.9142, 4.23 },
+ { 7565, 297.7671, +22.6100, 4.95 }, { 7566, 297.6417, +38.7225, 5.12 }, { 7567, 297.6554, +40.5997, 5.69 }, { 7568, 297.6958, +37.8264, 6.06 },
+ { 7569, 298.0146, +11.6289, 6.13 }, { 7570, 298.1183,  +1.0056, 3.90 }, { 7571, 298.2767, -13.3969, 6.48 }, { 7572, 298.0650, +10.3514, 6.54 },
+ { 7573, 298.0067, +24.9922, 5.57 }, { 7574, 298.0908, +18.6719, 6.23 }, { 7575, 298.3279,  -2.8856, 5.65 }, { 7576, 297.6571, +52.9881, 5.03 },
+ { 7577, 297.8308, +47.3772, 6.20 }, { 7578, 298.5738, -22.0589, 6.18 }, { 7579, 299.6721, -68.8361, 5.75 }, { 7580, 298.3442,  +4.4006, 6.53 },
+ { 7581, 298.8154, -40.1317, 4.13 }, { 7582, 297.0433, +70.2678, 3.83 }, { 7583, 298.0679, +36.4322, 6.10 }, { 7584, 298.5342,  -7.4258, 5.79 },
+ { 7585, 298.7713, -32.9536, 6.46 }, { 7586, 299.2404, -56.0744, 6.53 }, { 7587, 299.2758, -57.0986, 5.26 }, { 7588, 299.7208, -67.2378, 6.39 },
+ { 7589, 297.9962, +47.0275, 5.62 }, { 7590, 300.1479, -71.0894, 3.96 }, { 7591, 298.0300, +47.9319, 5.91 }, { 7592, 298.3654, +24.0797, 4.58 },
+ { 7593, 298.6567,  -7.7728, 5.71 }, { 7594, 298.6588,  -7.7628, 6.49 }, { 7595, 298.5621,  +8.4614, 4.71 }, { 7596, 298.6867,  +0.2736, 5.61 },
+ { 7597, 298.9600, -25.7006, 4.70 }, { 7598, 298.6679,  +7.1403, 6.15 }, { 7599, 298.8317,  -5.2658, 6.51 }, { 7600, 298.2550, +47.8075, 6.29 },
+ { 7601, 298.6296, +24.3194, 5.52 }, { 7602, 298.8283,  +6.4067, 3.71 }, { 7603, 300.0958, -65.0506, 5.76 }, { 7604, 299.2367, -26.8300, 4.52 },
+ { 7605, 299.4221, -37.9417, 6.55 }, { 7606, 298.7013, +36.9961, 5.76 }, { 7607, 298.7771, +30.1953, 6.57 }, { 7608, 298.3225, +57.5236, 5.14 },
+ { 7609, 299.0054, +16.6347, 5.36 }, { 7610, 299.0596, +11.4239, 5.28 }, { 7611, 298.3975, +59.7089, 6.06 }, { 7612, 300.4683, -65.0558, 5.31 },
+ { 7613, 298.9654, +38.4867, 4.94 }, { 7614, 299.4875, -14.5086, 5.02 }, { 7615, 299.0767, +35.0833, 3.89 }, { 7616, 299.2508, +20.9981, 6.48 },
+ { 7617, 299.7350, -29.4619, 6.28 }, { 7618, 299.7383, -25.8044, 4.83 }, { 7619, 298.9075, +52.4389, 4.92 }, { 7620, 299.1842, +36.2508, 6.02 },
+ { 7621, 300.1054, -48.6489, 6.17 }, { 7622, 299.4392, +16.7892, 5.53 }, { 7623, 299.9342, -34.7236, 4.37 }, { 7624, 299.9638, -33.3022, 5.30 },
+ { 7625, 300.4362, -58.6239, 5.13 }, { 7626, 298.8421, +58.2503, 6.09 }, { 7627, 300.1104, -42.9567, 6.14 }, { 7628, 299.3079, +40.3681, 5.45 },
+ { 7629, 300.0663, -36.2978, 5.95 }, { 7630, 300.2013, -44.8869, 5.81 }, { 7631, 300.0846, -32.2961, 5.66 }, { 7632, 299.1879, +50.9025, 6.43 },
+ { 7633, 298.9808, +58.8461, 4.96 }, { 7634, 299.0792, +56.6869, 6.12 }, { 7635, 299.6892, +19.4922, 3.47 }, { 7636, 299.8446,  +1.3778, 6.17 },
+ { 7637, 299.9475,  -8.0417, 5.88 }, { 7638, 299.4842, +42.2608, 6.43 }, { 7639, 300.3600, -39.1858, 6.29 }, { 7640, 299.6583, +30.9836, 5.49 },
+ { 7641, 299.7937, +23.1014, 5.67 }, { 7642, 299.6433, +38.1056, 6.32 }, { 7643, 300.3496, -21.2628, 6.01 }, { 7644, 301.3867, -66.6792, 6.07 },
+ { 7645, 300.0138, +17.5167, 5.37 }, { 7646, 299.8354, +45.7722, 5.92 }, { 7647, 299.9800, +37.0428, 5.19 }, { 7648, 300.2454,  +8.5581, 5.91 },
+ { 7649, 300.4942, -12.3631, 5.71 }, { 7650, 300.6646, -26.2903, 4.58 }, { 7651, 299.8142, +52.0558, 6.15 }, { 7652, 300.8896, -36.0592, 4.77 },
+ { 7653, 300.2754, +27.7536, 4.64 }, { 7654, 299.6196, +63.5342, 5.96 }, { 7655, 300.3138, +37.0989, 6.20 }, { 7656, 300.4362, +24.8003, 5.88 },
+ { 7657, 300.5058, +24.9381, 5.22 }, { 7658, 300.9346, -21.4044, 6.45 }, { 7659, 301.0817, -31.9436, 4.99 }, { 7660, 300.3400, +50.1047, 5.05 },
+ { 7661, 301.0050,  -6.5303, 6.72 }, { 7662, 300.8183, +18.5006, 5.96 }, { 7663, 302.0854, -65.6453, 6.45 }, { 7664, 300.8750, +16.0314, 5.67 },
+ { 7665, 302.1817, -65.8181, 3.56 }, { 7666, 299.6746, +70.3669, 6.33 }, { 7667, 301.0967,  +0.7094, 5.68 }, { 7668, 301.3838, -33.0000, 6.53 },
+ { 7669, 301.0346,  +7.2781, 5.52 }, { 7670, 300.9058, +29.8967, 5.71 }, { 7671, 301.2725, -10.4006, 6.34 }, { 7672, 301.0258, +17.0700, 5.80 },
+ { 7673, 301.8467, -51.1192, 4.94 }, { 7674, 301.8963, -54.9836, 6.26 }, { 7675, 301.3600, -11.3347, 6.55 }, { 7676, 300.3687, +64.8211, 5.27 },
+ { 7677, 301.2442, +23.2103, 6.45 }, { 7678, 301.1504, +32.2186, 5.64 }, { 7679, 301.2896, +19.9911, 5.10 }, { 7680, 301.3604, +15.5003, 6.34 },
+ { 7681, 301.5508,  -3.9217, 6.47 }, { 7682, 300.5846, +64.6344, 6.57 }, { 7683, 301.2908, +38.4783, 6.19 }, { 7684, 301.1200, +48.2297, 6.16 },
+ { 7685, 300.7046, +67.8736, 4.51 }, { 7686, 299.9025, +76.4814, 6.20 }, { 7687, 301.2779, +51.8394, 6.14 }, { 7688, 301.7225, +23.6144, 5.07 },
+ { 7689, 301.5908, +35.9725, 5.36 }, { 7690, 302.0075,  +0.6783, 5.99 }, { 7691, 302.7800, -56.4761, 6.37 }, { 7692, 301.3396, +56.3414, 6.21 },
+ { 7693, 301.9596,  +9.3997, 6.43 }, { 7694, 302.1304,  -9.9372, 6.18 }, { 7695, 301.1858, +63.8906, 6.26 }, { 7696, 302.0271, +16.6642, 6.42 },
+ { 7697, 301.5575, +53.1658, 5.85 }, { 7698, 306.2267, -82.6894, 6.17 }, { 7699, 301.9225, +34.4231, 6.11 }, { 7700, 302.1596, +10.7258, 6.31 },
+ { 7701, 301.3867, +61.9956, 5.39 }, { 7702, 301.7979, +50.2292, 6.54 }, { 7703, 302.7996, -35.8989, 5.32 }, { 7704, 301.2221, +68.0272, 6.28 },
+ { 7705, 302.4858, +20.9153, 6.48 }, { 7706, 303.0996, -41.2194, 6.22 }, { 7707, 303.6121, -62.5842, 6.09 }, { 7708, 302.3567, +36.8397, 4.93 },
+ { 7709, 302.7921,  -7.1578, 6.49 }, { 7710, 302.8263,  +0.8214, 3.23 }, { 7711, 302.6396, +26.9042, 5.52 }, { 7712, 302.9912, -11.6075, 6.34 },
+ { 7713, 302.7646, +21.1347, 6.22 }, { 7714, 303.5792, -51.5544, 5.65 }, { 7715, 303.1079, -11.3825, 5.85 }, { 7716, 302.8379, +21.8756, 6.26 },
+ { 7717, 303.1467,  +0.8675, 6.27 }, { 7718, 302.9500, +26.8089, 5.49 }, { 7719, 303.0029, +26.4789, 5.92 }, { 7720, 303.3079,  -0.9906, 5.47 },
+ { 7721, 303.0158, +47.7369, 6.92 }, { 7722, 303.8225, -26.9672, 5.73 }, { 7723, 303.4192, +24.2389, 6.56 }, { 7724, 303.5692, +15.1975, 4.95 },
+ { 7725, 303.9608, -29.9947, 6.30 }, { 7726, 303.1325, +51.4636, 6.01 }, { 7727, 302.8954, +62.0786, 5.75 }, { 7728, 304.0988, -35.5456, 6.39 },
+ { 7729, 304.1104, -34.8022, 6.53 }, { 7730, 303.3250, +46.8158, 4.83 }, { 7731, 303.5604, +28.6947, 5.18 }, { 7732, 304.7625, -62.7689, 6.27 },
+ { 7733, 303.4283, +43.3792, 6.14 }, { 7734, 303.5208, +36.6053, 6.45 }, { 7735, 303.4079, +46.7414, 3.79 }, { 7736, 303.6333, +36.8064, 4.97 },
+ { 7737, 303.5900, +42.1036, 6.71 }, { 7738, 304.0950, -11.6631, 6.32 }, { 7739, 303.8163, +25.5919, 4.78 }, { 7740, 303.3496, +56.5678, 4.30 },
+ { 7741, 303.8758, +23.5086, 5.15 }, { 7742, 303.3654, +60.6406, 5.79 }, { 7743, 303.8488, +33.7294, 5.66 }, { 7744, 303.9421, +27.8142, 4.52 },
+ { 7745, 304.7333, -46.2892, 6.31 }, { 7746, 304.0821, +21.5986, 6.13 }, { 7747, 304.4121, -11.4917, 4.24 }, { 7748, 304.5058, -20.1900, 5.87 },
+ { 7749, 304.8246, -46.4197, 6.13 }, { 7750, 302.2221, +77.7114, 4.39 }, { 7751, 303.8679, +47.7144, 3.98 }, { 7752, 304.0142, +38.8978, 6.27 },
+ { 7753, 304.1963, +24.6711, 5.32 }, { 7754, 304.5138, -11.4553, 3.57 }, { 7755, 303.9308, +50.2328, 6.31 }, { 7756, 304.0025, +45.5794, 5.91 },
+ { 7757, 304.1175, +37.0564, 6.48 }, { 7758, 305.1346, -54.9492, 6.27 }, { 7759, 304.2304, +40.3650, 5.24 }, { 7760, 304.3813, +29.1481, 6.22 },
+ { 7761, 304.8483, -18.8814, 5.28 }, { 7762, 304.3712, +42.7219, 6.29 }, { 7763, 304.4467, +38.0331, 4.81 }, { 7764, 305.1171, -28.8028, 6.30 },
+ { 7765, 305.2163, -34.3264, 6.46 }, { 7766, 305.4208, -48.0006, 6.27 }, { 7767, 304.5292, +40.7322, 5.84 }, { 7768, 304.9304,  -0.9214, 6.06 },
+ { 7769, 304.6192, +37.0000, 5.58 }, { 7770, 304.6629, +34.9828, 5.17 }, { 7771, 304.8717, +13.2169, 6.21 }, { 7772, 305.1087,  -5.6383, 6.63 },
+ { 7773, 305.1658, -11.2408, 4.76 }, { 7774, 305.0008, +13.5481, 5.95 }, { 7775, 305.1942, -13.2150, 6.10 }, { 7776, 305.2529, -13.2186, 3.08 },
+ { 7777, 304.7067, +46.3228, 6.45 }, { 7778, 305.0854, +14.5692, 6.13 }, { 7779, 305.6146, -41.9503, 5.59 }, { 7780, 305.0892, +17.7931, 5.80 },
+ { 7781, 304.6033, +55.3972, 5.76 }, { 7782, 304.9513, +37.1325, 6.57 }, { 7783, 304.3804, +66.8539, 5.93 }, { 7784, 305.0633, +39.4033, 6.23 },
+ { 7785, 308.3229, -79.0350, 5.77 }, { 7786, 304.9837, +46.8375, 6.50 }, { 7787, 305.9717, -41.5772, 5.64 }, { 7788, 305.7533,  -8.3453, 6.30 },
+ { 7789, 305.5142, +24.4461, 5.54 }, { 7790, 306.4121, -55.2650, 1.94 }, { 7791, 305.1267, +53.5961, 6.18 }, { 7792, 304.9029, +62.2575, 5.72 },
+ { 7793, 305.7179, +14.5514, 6.17 }, { 7794, 305.7946,  +5.3431, 5.31 }, { 7795, 305.5125, +41.1314, 6.39 }, { 7796, 305.5571, +40.2567, 2.20 },
+ { 7797, 305.6558, +31.2650, 6.09 }, { 7798, 305.5225, +45.7950, 5.58 }, { 7799, 306.4496, -39.2036, 6.09 }, { 7800, 305.6888, +41.0261, 5.93 },
+ { 7801, 306.3617, -27.3367, 5.85 }, { 7802, 305.7312, +42.9833, 6.20 }, { 7803, 306.1563,  +1.0686, 6.15 }, { 7804, 305.0250, +68.8803, 5.55 },
+ { 7805, 305.2975, +63.9803, 5.69 }, { 7806, 305.9654, +32.1900, 4.43 }, { 7807, 305.9350, +37.4764, 5.90 }, { 7808, 306.7208, -36.5969, 6.25 },
+ { 7809, 306.4271,  -1.1997, 6.11 }, { 7810, 306.4333, +10.0564, 6.33 }, { 7811, 306.4187, +21.4097, 5.66 }, { 7812, 309.5775, -80.7111, 5.91 },
+ { 7813, 306.5050, +19.8650, 6.41 }, { 7814, 306.8300, -17.7883, 5.25 }, { 7815, 306.1350, +53.5519, 6.51 }, { 7816, 306.5967, +17.3156, 6.22 },
+ { 7817, 307.1946, -34.4042, 6.10 }, { 7818, 306.2713, +59.6000, 6.44 }, { 7819, 307.1817, -14.2583, 6.41 }, { 7820, 307.0313,  +8.4375, 6.25 },
+ { 7821, 307.1037,  -2.6422, 6.13 }, { 7822, 307.2150, -16.1864, 4.78 }, { 7823, 306.7821, +34.3289, 6.39 }, { 7824, 307.0700,  +2.9369, 6.21 },
+ { 7825, 307.3804, -21.6083, 6.16 }, { 7826, 306.8929, +38.4403, 5.62 }, { 7827, 306.5979, +56.6389, 6.36 }, { 7828, 306.7596, +49.3833, 5.69 },
+ { 7829, 307.4688, -17.4133, 6.74 }, { 7830, 307.4746, -17.4167, 5.94 }, { 7831, 307.4125,  -1.1144, 4.91 }, { 7832, 307.7367, -28.8875, 6.39 },
+ { 7833, 307.3379, +20.0878, 6.55 }, { 7834, 307.3488, +30.3686, 4.01 }, { 7835, 307.3350, +36.4547, 5.88 }, { 7836, 307.5750, +10.8958, 6.08 },
+ { 7837, 307.7679, -14.9436, 6.12 }, { 7838, 308.9654, -68.3889, 6.11 }, { 7839, 307.7421, +20.6058, 6.18 }, { 7840, 307.8042, +11.2606, 7.11 },
+ { 7841, 307.4996, +45.9286, 6.41 }, { 7842, 308.2183, -23.0561, 6.36 }, { 7843, 307.3629, +56.0681, 5.91 }, { 7844, 307.5146, +48.9517, 4.95 },
+ { 7845, 308.0988,  -8.1467, 5.65 }, { 7846, 308.4796, -43.4839, 5.11 }, { 7847, 307.7467, +36.9358, 6.19 }, { 7848, 308.8950, -59.4183, 4.76 },
+ { 7849, 307.9925, +25.8044, 6.34 }, { 7850, 307.3954, +62.9942, 4.22 }, { 7851, 307.8283, +49.2203, 5.44 }, { 7852, 308.3033, +11.3033, 4.03 },
+ { 7853, 308.7312, -37.9103, 6.44 }, { 7854, 307.8379, +52.3097, 6.18 }, { 7855, 308.5487, -12.2789, 6.13 }, { 7856, 308.6975, -29.5264, 6.40 },
+ { 7857, 308.4733, +10.0597, 6.56 }, { 7858, 308.4875, +13.0272, 5.38 }, { 7859, 309.3971, -60.4700, 4.88 }, { 7860, 307.9438, +56.7800, 6.14 },
+ { 7861, 308.2179, +43.1917, 6.60 }, { 7862, 308.5417, +20.9853, 6.48 }, { 7863, 310.5121, -75.8194, 6.00 }, { 7864, 310.4321, -74.6494, 6.55 },
+ { 7865, 308.8842, -15.4742, 6.19 }, { 7866, 308.4758, +35.2508, 4.61 }, { 7867, 308.4517, +41.7722, 6.49 }, { 7868, 307.5029, +72.5317, 6.27 },
+ { 7869, 309.3917, -46.7086, 3.11 }, { 7870, 308.4787, +46.6939, 5.78 }, { 7871, 308.8271, +14.6742, 4.68 }, { 7872, 309.9642, -61.0922, 6.22 },
+ { 7873, 309.1817,  -1.4500, 4.89 }, { 7874, 309.0346, +25.8825, 6.41 }, { 7875, 310.0108, -59.4511, 5.12 }, { 7876, 308.7100, +51.8542, 6.11 },
+ { 7877, 309.4671, -24.8911, 6.36 }, { 7878, 309.3263,  +0.0969, 6.22 }, { 7879, 307.8767, +74.9547, 5.20 }, { 7880, 309.2696, +26.4619, 5.59 },
+ { 7881, 310.4879, -65.2392, 5.15 }, { 7882, 309.3875, +14.5953, 3.63 }, { 7883, 309.4546, +11.3778, 5.43 }, { 7884, 309.5846,  -0.8947, 4.32 },
+ { 7885, 309.3825, +31.5725, 6.32 }, { 7886, 309.4775, +18.2692, 6.25 }, { 7887, 309.3858, +31.5219, 6.49 }, { 7888, 309.3483, +38.3286, 6.20 },
+ { 7889, 309.8183, -13.0453, 5.22 }, { 7890, 309.8050,  -1.5872, 6.22 }, { 7891, 309.6304, +21.2011, 4.82 }, { 7892, 309.6829, +13.3150, 5.72 },
+ { 7893, 310.0825, -32.5681, 5.47 }, { 7894, 309.6329, +24.1161, 5.04 }, { 7895, 309.6463, +23.6806, 5.91 }, { 7896, 309.7825, +10.0861, 5.05 },
+ { 7897, 309.8537,  +0.4864, 5.16 }, { 7898, 310.0487, -22.2261, 6.37 }, { 7899, 309.7708, +15.8381, 5.97 }, { 7900, 310.0125, -17.8614, 5.10 },
+ { 7901, 307.0608, +81.4228, 5.46 }, { 7902, 310.1500, -25.3550, 6.51 }, { 7903, 309.7942, +21.8172, 6.08 }, { 7904, 309.7479, +30.3344, 5.68 },
+ { 7905, 310.1354, -15.8758, 5.80 }, { 7906, 309.9096, +15.9119, 3.77 }, { 7907, 309.9658, +11.2497, 6.42 }, { 7908, 307.3646, +81.0914, 5.96 },
+ { 7909, 310.3488, -30.4017, 5.76 }, { 7910, 310.3504, -26.0000, 6.28 }, { 7911, 309.8888, +40.5794, 6.06 }, { 7912, 309.8463, +45.6669, 6.58 },
+ { 7913, 311.2396, -65.7969, 3.42 }, { 7914, 310.1883, +19.9353, 6.45 }, { 7915, 310.7208, -38.4414, 6.29 }, { 7916, 309.7508, +56.0050, 6.48 },
+ { 7917, 310.1508, +29.8053, 6.08 }, { 7918, 310.3175, +14.5831, 5.99 }, { 7919, 310.0129, +43.4586, 5.95 }, { 7920, 311.0096, -50.0789, 4.51 },
+ { 7921, 310.2608, +32.3072, 5.51 }, { 7922, 310.2517, +39.0822, 6.51 }, { 7923, 310.4925, +17.5214, 6.22 }, { 7924, 310.3579, +45.2803, 1.25 },
+ { 7925, 310.0746, +60.5053, 6.01 }, { 7926, 310.4854, +41.7169, 5.67 }, { 7927, 310.5925, +35.4561, 6.66 }, { 7928, 310.8646, +15.0744, 4.43 },
+ { 7929, 310.5525, +50.3400, 5.39 }, { 7930, 307.2629, +83.6256, 6.19 }, { 7931, 311.3050, -26.7528, 6.50 }, { 7932, 310.8508, +35.5878, 6.47 },
+ { 7933, 311.5838, -38.8008, 5.50 }, { 7934, 312.3254, -67.2236, 5.41 }, { 7935, 311.5775, -35.8797, 6.49 }, { 7936, 311.5238, -24.7292, 4.14 },
+ { 7937, 311.5417, -20.4858, 5.93 }, { 7938, 310.6654, +60.6014, 6.15 }, { 7939, 311.2188, +25.2706, 4.91 }, { 7940, 310.8062, +57.1142, 6.32 },
+ { 7941, 311.3675, +18.0903, 6.38 }, { 7942, 311.4154, +30.7197, 4.22 }, { 7943, 312.1217, -42.0114, 5.11 }, { 7944, 311.0917, +56.4881, 5.78 },
+ { 7945, 310.7958, +66.6575, 5.58 }, { 7946, 311.7650,  -1.5133, 6.27 }, { 7947, 311.6613, +16.1244, 5.14 }, { 7948, 311.6646, +16.1242, 4.27 },
+ { 7949, 311.5529, +33.9703, 2.46 }, { 7950, 311.9192,  -8.5042, 3.77 }, { 7951, 311.9342,  -4.9722, 4.42 }, { 7952, 312.3708, -45.7731, 4.89 },
+ { 7953, 311.9513,  +6.0083, 5.58 }, { 7954, 311.9492,  +3.3067, 6.40 }, { 7955, 311.3379, +57.5797, 4.51 }, { 7956, 311.7950, +34.3742, 4.92 },
+ { 7957, 311.3225, +61.8389, 3.43 }, { 7958, 311.6604, +46.5317, 6.30 }, { 7959, 312.9096, -61.5708, 6.28 }, { 7960, 312.9117, -61.5708, 6.59 },
+ { 7961, 312.3233, -24.2186, 5.86 }, { 7962, 311.5883, +52.9953, 6.33 }, { 7963, 311.8521, +36.4908, 4.53 }, { 7964, 312.3354, -17.9642, 6.21 },
+ { 7965, 312.4921, -32.2203, 4.90 }, { 7966, 311.8367, +45.5797, 6.40 }, { 7967, 311.1379, +69.7519, 6.41 }, { 7968, 312.8754, -50.3917, 5.05 },
+ { 7969, 311.9554, +47.8319, 5.57 }, { 7970, 312.6963, -31.9456, 6.36 }, { 7971, 312.7529, -36.0867, 5.52 }, { 7972, 311.9700, +52.4072, 6.27 },
+ { 7973, 312.4075, +12.5453, 5.98 }, { 7974, 312.4513,  +7.8642, 6.33 }, { 7975, 312.4962,  +5.5447, 6.21 }, { 7976, 312.6742, -11.4550, 5.88 },
+ { 7977, 312.2346, +46.1142, 4.84 }, { 7978, 312.1779, +51.9106, 6.29 }, { 7979, 312.9950, -32.8228, 6.04 }, { 7980, 312.9554, -25.0808, 4.11 },
+ { 7981, 312.6542, +18.0514, 6.52 }, { 7982, 312.8571,  -4.3736, 5.99 }, { 7983, 312.4779, +46.6611, 6.33 }, { 7984, 312.5204, +44.0594, 5.04 },
+ { 7985, 313.0363,  -4.4931, 5.55 }, { 7986, 313.7025, -57.5458, 3.65 }, { 7987, 313.4175, -38.1900, 5.35 }, { 7988, 312.8675, +28.2506, 5.77 },
+ { 7989, 313.2550, -22.2169, 6.33 }, { 7990, 313.1633,  -7.0167, 4.73 }, { 7991, 313.3542, -29.2814, 6.35 }, { 7992, 313.6458, -49.2722, 6.24 },
+ { 7993, 312.3225, +64.0422, 6.45 }, { 7994, 313.2733, -10.4264, 6.38 }, { 7995, 313.0321, +27.0969, 4.59 }, { 7996, 313.0013, +32.8492, 6.44 },
+ { 7997, 313.5283, -26.0744, 6.41 }, { 7998, 313.4933,  -5.1103, 6.44 }, { 7999, 313.2808, +29.6494, 6.34 }, { 8000, 313.6996, -16.0769, 5.78 },
+ { 8001, 313.3117, +44.3872, 4.78 }, { 8002, 310.6467, +82.5311, 5.75 }, { 8003, 313.3275, +45.1819, 5.45 }, { 8004, 313.3600, +42.4103, 6.66 },
+ { 8005, 313.4746, +33.4378, 5.47 }, { 8006, 313.7838,  -0.6267, 6.55 }, { 8007, 313.5933, +28.5219, 6.56 }, { 8008, 313.6400, +28.0575, 5.01 },
+ { 8009, 313.5929, +40.7031, 6.70 }, { 8010, 313.9196,  +4.5328, 6.05 }, { 8011, 313.9029, +13.7214, 5.17 }, { 8012, 313.9108, +12.5686, 5.58 },
+ { 8013, 314.1971, -25.7036, 5.70 }, { 8014, 314.0763,  -2.4386, 6.57 }, { 8015, 314.2250,  -8.3025, 5.51 }, { 8016, 311.8892, +80.5522, 5.39 },
+ { 8017, 314.2942,  +0.4636, 6.05 }, { 8018, 314.4192, -15.9683, 5.87 }, { 8019, 315.3671, -67.7903, 6.37 }, { 8020, 313.9575, +47.4178, 5.67 },
+ { 8021, 316.1792, -76.9761, 5.15 }, { 8022, 314.0537, +51.0750, 6.63 }, { 8023, 314.1446, +44.9250, 5.96 }, { 8024, 314.6746, -13.5172, 6.01 },
+ { 8025, 314.1062, +50.7286, 5.81 }, { 8026, 314.1079, +49.1958, 5.90 }, { 8027, 315.0896, -50.7347, 5.76 }, { 8028, 314.2933, +41.1672, 3.94 },
+ { 8029, 314.0708, +56.8875, 6.23 }, { 8030, 314.6079, +10.8392, 5.48 }, { 8031, 314.9987, -35.8703, 6.11 }, { 8032, 314.5683, +22.3258, 5.31 },
+ { 8033, 314.9004, -18.9647, 6.25 }, { 8034, 314.7683,  +4.2936, 5.23 }, { 8035, 314.5813, +44.4717, 5.55 }, { 8036, 314.6283, +41.9403, 6.16 },
+ { 8037, 314.9617, +16.8242, 6.66 }, { 8038, 315.0163,  +7.5164, 5.99 }, { 8039, 315.3229, -31.7422, 4.67 }, { 8040, 314.6254, +50.4622, 5.61 },
+ { 8041, 315.1408,  -3.2697, 6.21 }, { 8042, 315.5525, -42.9981, 6.64 }, { 8043, 313.6846, +75.9256, 6.05 }, { 8044, 315.1154, +19.3294, 5.65 },
+ { 8045, 315.4388, -25.1189, 6.05 }, { 8046, 315.6133, -37.4694, 5.94 }, { 8047, 314.9567, +47.5211, 4.74 }, { 8048, 315.7417, -37.3683, 5.30 },
+ { 8049, 314.8558, +59.4386, 5.51 }, { 8050, 315.7925, -26.2681, 6.25 }, { 8051, 315.3037, +36.0261, 5.97 }, { 8052, 317.1996, -75.7875, 6.58 },
+ { 8053, 315.2954, +46.1558, 5.37 }, { 8054, 315.7483,  +0.9247, 6.50 }, { 8055, 316.3092, -53.2728, 5.16 }, { 8056, 315.7625,  +1.5319, 6.25 },
+ { 8057, 315.7575, +14.7300, 6.31 }, { 8058, 316.0192,  -4.1767, 7.31 }, { 8059, 316.0196,  -4.1769, 5.89 }, { 8060, 316.1012, -18.1450, 4.84 },
+ { 8061, 317.3429, -72.8269, 5.68 }, { 8062, 315.6004, +44.7911, 6.19 }, { 8063, 315.7700, +38.6575, 6.07 }, { 8064, 315.7021, +45.8489, 6.48 },
+ { 8065, 315.5379, +56.6697, 5.83 }, { 8066, 316.1446,  +5.5028, 5.61 }, { 8067, 316.1737,  +2.9419, 6.42 }, { 8068, 316.1892,  +2.2697, 6.33 },
+ { 8069, 316.6062, -40.6139, 5.53 }, { 8070, 316.5050, -29.8750, 5.68 }, { 8071, 315.9671, +41.6281, 6.33 }, { 8072, 315.8583, +50.3519, 6.37 },
+ { 8073, 317.1371, -62.0711, 5.76 }, { 8074, 315.9304, +46.8619, 6.32 }, { 8075, 316.4867, -16.7672, 4.07 }, { 8076, 316.6029, -31.6583, 5.18 },
+ { 8077, 316.3612,  +5.9583, 5.94 }, { 8078, 315.9483, +53.2861, 5.90 }, { 8079, 316.2329, +43.9278, 3.72 }, { 8080, 316.7821, -24.9942, 4.50 },
+ { 8081, 317.8363, -71.4558, 6.20 }, { 8082, 316.5979, +26.9244, 6.12 }, { 8083, 316.9358, -16.5447, 6.17 }, { 8084, 316.6263, +31.1847, 5.82 },
+ { 8085, 316.7275, +38.7458, 5.21 }, { 8086, 316.7304, +38.7433, 6.03 }, { 8087, 317.1400, -20.8064, 5.30 }, { 8088, 316.8900, +15.6586, 6.34 },
+ { 8089, 316.6504, +47.6483, 4.55 }, { 8090, 317.1175,  +6.9894, 6.15 }, { 8091, 317.3875, -19.4436, 6.25 }, { 8092, 318.3354, -69.8736, 5.02 },
+ { 8093, 317.3988, -10.6283, 4.51 }, { 8094, 317.1621, +30.2058, 5.59 }, { 8095, 317.4929,  +2.9433, 6.45 }, { 8096, 317.6954,  -8.6461, 6.27 },
+ { 8097, 317.5854, +10.1317, 4.69 }, { 8098, 317.6300, +10.0489, 6.07 }, { 8099, 316.5971, +71.4319, 5.87 }, { 8100, 318.0567, -39.7306, 5.83 },
+ { 8101, 317.6333, +22.4547, 6.68 }, { 8102, 317.9221, -13.5278, 6.48 }, { 8103, 317.4942, +45.5025, 6.63 }, { 8104, 318.2629, -38.5747, 5.26 },
+ { 8105, 317.7663, +36.2992, 6.54 }, { 8106, 317.5650, +53.5633, 5.73 }, { 8107, 317.6292, +47.6919, 6.46 }, { 8108, 318.3288, -35.5761, 5.96 },
+ { 8109, 317.3704, +63.2956, 6.54 }, { 8110, 318.3221, -26.3806, 5.42 }, { 8111, 319.5671, -74.6533, 6.63 }, { 8112, 316.3721, +78.1264, 5.91 },
+ { 8113, 317.3833, +68.4903, 7.33 }, { 8114, 318.9413, -52.7369, 5.75 }, { 8115, 318.2342, +30.2269, 3.20 }, { 8116, 318.3700, +15.9825, 6.27 },
+ { 8117, 318.8112, -39.4936, 6.21 }, { 8118, 318.5696,  -9.3947, 6.77 }, { 8119, 317.9508, +59.9864, 5.64 }, { 8120, 318.3596, +36.6336, 6.05 },
+ { 8121, 318.6542,  +0.0922, 6.38 }, { 8122, 318.7775, -16.6550, 6.04 }, { 8123, 318.6204, +10.0069, 4.49 }, { 8124, 318.9450, -35.7892, 6.12 },
+ { 8125, 319.5013, -63.3183, 6.31 }, { 8126, 318.5429, +29.9011, 6.17 }, { 8127, 318.9079, -19.3483, 5.24 }, { 8128, 318.9371, -14.8286, 5.28 },
+ { 8129, 323.0175, -83.1900, 6.45 }, { 8130, 318.6979, +38.0456, 3.72 }, { 8131, 318.9558,  +5.2478, 3.92 }, { 8132, 319.1650,  -0.3922, 6.48 },
+ { 8133, 318.4275, +64.4039, 6.39 }, { 8134, 319.3062, -12.7211, 6.40 }, { 8135, 319.4846, -31.8275, 4.71 }, { 8136, 318.9033, +47.9736, 6.46 },
+ { 8137, 319.4887, -16.0147, 5.43 }, { 8138, 319.1233, +42.2514, 6.43 }, { 8139, 319.5654, -16.5378, 7.05 }, { 8140, 319.9667, -52.5503, 4.39 },
+ { 8141, 319.5462,  -3.4806, 5.82 }, { 8142, 319.7267, -27.2344, 6.40 }, { 8143, 319.3542, +39.3947, 4.23 }, { 8144, 319.3467, +42.6833, 6.19 },
+ { 8145, 320.0396, -44.9778, 6.00 }, { 8146, 319.4796, +34.8969, 4.43 }, { 8147, 319.2583, +53.9975, 6.13 }, { 8148, 319.9408, -25.6469, 6.56 },
+ { 8149, 319.7167, +11.2033, 5.96 }, { 8150, 319.3096, +55.7981, 5.98 }, { 8151, 320.1900, -39.1903, 4.82 }, { 8152, 320.3183, -48.0622, 6.38 },
+ { 8153, 319.3283, +58.6117, 6.42 }, { 8154, 319.6133, +43.9458, 5.00 }, { 8155, 319.7304, +41.0408, 6.15 }, { 8156, 321.0696, -68.2658, 6.41 },
+ { 8157, 319.8425, +38.2375, 5.83 }, { 8158, 320.0583, +22.0264, 6.29 }, { 8159, 321.3254, -70.2006, 6.09 }, { 8160, 320.2679,  -3.4400, 5.87 },
+ { 8161, 319.8700, +49.5103, 5.76 }, { 8162, 319.6450, +62.5856, 2.44 }, { 8163, 320.2700,  +7.3544, 5.82 }, { 8164, 319.8158, +58.6236, 5.66 },
+ { 8165, 320.2683, +23.8558, 5.57 }, { 8166, 320.2088, +32.4528, 5.68 }, { 8167, 320.5617, -15.1656, 4.28 }, { 8168, 318.9258, +77.0122, 5.95 },
+ { 8169, 320.3417, +32.6128, 6.04 }, { 8170, 320.2558, +40.3456, 6.40 }, { 8171, 319.8425, +64.8719, 5.18 }, { 8172, 320.7521, -21.3311, 5.60 },
+ { 8173, 320.5217, +19.8044, 4.08 }, { 8174, 318.3396, +81.2308, 6.15 }, { 8175, 320.7346,  -8.6806, 5.99 }, { 8176, 323.4767, -81.3169, 6.38 },
+ { 8177, 321.0867, -45.3850, 6.31 }, { 8178, 320.7233,  +6.8111, 5.16 }, { 8179, 320.1396, +60.7569, 6.11 }, { 8180, 321.1033, -40.9933, 5.77 },
+ { 8181, 321.6108, -64.6339, 4.22 }, { 8182, 320.6746, +30.3097, 6.05 }, { 8183, 321.0400, -19.1481, 5.41 }, { 8184, 321.0329, -21.2531, 6.38 },
+ { 8185, 320.5017, +49.3889, 5.69 }, { 8186, 320.6954, +38.6342, 6.63 }, { 8187, 321.0479, -11.1219, 5.49 }, { 8188, 321.5642, -53.3394, 6.12 },
+ { 8189, 320.8458, +37.4067, 6.58 }, { 8190, 320.9950, +24.2742, 5.71 }, { 8191, 321.1025, +10.1742, 6.35 }, { 8192, 321.2154,  -2.6017, 6.36 },
+ { 8193, 320.9513, +37.3514, 6.47 }, { 8194, 321.0308, +25.3122, 6.15 }, { 8195, 321.3046,  -8.2514, 5.70 }, { 8196, 322.1871, -68.4947, 5.34 },
+ { 8197, 321.0963, +24.5289, 6.32 }, { 8198, 321.1417, +26.1744, 5.68 }, { 8199, 321.3208,  -2.4433, 5.49 }, { 8200, 321.5954, -36.1706, 5.63 },
+ { 8201, 323.3358, -79.9608, 6.47 }, { 8202, 321.7567, -41.4522, 5.51 }, { 8203, 321.4646,  +0.5344, 6.46 }, { 8204, 321.6667, -21.5886, 3.74 },
+ { 8205, 321.6171,  +1.1033, 6.13 }, { 8206, 321.2312, +49.3233, 6.58 }, { 8207, 321.8117, -20.8039, 5.78 }, { 8208, 321.3317, +46.7144, 5.60 },
+ { 8209, 321.4458, +36.6675, 5.94 }, { 8210, 321.6112, +19.3756, 6.07 }, { 8211, 322.2513, -52.2942, 6.39 }, { 8212, 322.0579, -10.4317, 6.61 },
+ { 8213, 322.1808, -20.1928, 4.51 }, { 8214, 322.2658, -30.7614, 6.50 }, { 8215, 321.8392, +37.1167, 5.31 }, { 8216, 321.7150, +48.8350, 5.31 },
+ { 8217, 321.9171, +27.6086, 5.41 }, { 8218, 321.6875, +52.8986, 6.03 }, { 8219, 322.1033,  +8.1956, 6.40 }, { 8220, 322.0346, +32.2253, 5.80 },
+ { 8221, 322.2496, +17.9058, 6.44 }, { 8222, 322.4983, -18.8522, 6.57 }, { 8223, 322.2496, +22.1794, 5.93 }, { 8224, 321.8554, +59.7500, 6.10 },
+ { 8225, 322.4871, +23.6389, 4.57 }, { 8226, 322.2196, +55.4186, 6.12 }, { 8227, 321.9421, +66.8092, 5.44 }, { 8228, 322.3625, +46.5406, 5.24 },
+ { 8229, 323.0246, -40.8208, 5.29 }, { 8230, 323.0608, -32.0553, 5.97 }, { 8231, 322.7900, +12.1375, 6.08 }, { 8232, 322.8896,  -4.4289, 2.91 },
+ { 8233, 323.3238, -51.2625, 6.41 }, { 8234, 324.7342, -78.5575, 6.18 }, { 8235, 323.1388, -23.4094, 6.43 }, { 8236, 323.3479, -43.1514, 5.57 },
+ { 8237, 322.5850, +52.9581, 6.02 }, { 8238, 322.1650, +70.5608, 3.23 }, { 8239, 321.2071, +80.5247, 5.97 }, { 8240, 323.1129, +23.3944, 6.70 },
+ { 8241, 323.5708, -41.0750, 6.32 }, { 8242, 322.8646, +52.6200, 6.16 }, { 8243, 322.7471, +60.4594, 5.53 }, { 8244, 323.7208, -28.3039, 6.41 },
+ { 8245, 323.7125, -19.9156, 5.69 }, { 8246, 323.2358, +49.9778, 5.75 }, { 8247, 323.8163, -22.5458, 6.40 }, { 8248, 323.3246, +45.8542, 6.25 },
+ { 8249, 324.5121, -63.1758, 6.20 }, { 8250, 323.6417, +22.7547, 6.47 }, { 8251, 323.8233,  -2.0169, 5.77 }, { 8252, 323.4954, +45.5919, 4.02 },
+ { 8253, 324.0458, -25.8286, 5.73 }, { 8254, 325.3687, -76.6100, 3.76 }, { 8255, 323.6942, +38.5342, 4.90 }, { 8256, 324.2038, -32.9519, 6.11 },
+ { 8257, 323.8292, +28.1972, 6.31 }, { 8258, 323.8625, +24.4522, 6.11 }, { 8259, 323.6146, +51.6983, 6.15 }, { 8260, 324.2700, -18.5339, 4.68 },
+ { 8261, 324.0579, +30.0556, 6.36 }, { 8262, 324.0100, +45.3747, 5.53 }, { 8263, 324.3908,  +0.3903, 6.25 }, { 8264, 324.4379,  -6.1458, 4.69 },
+ { 8265, 324.4321,  +6.6183, 6.18 }, { 8266, 324.2375, +40.4136, 5.01 }, { 8267, 324.4392, +19.3186, 5.45 }, { 8268, 324.7754, -32.3208, 6.28 },
+ { 8269, 324.9987, -51.6408, 6.21 }, { 8270, 324.6329,  +5.7717, 5.67 }, { 8271, 325.1400, -54.2625, 6.33 }, { 8272, 324.3662, +44.6967, 6.20 },
+ { 8273, 324.8671,  -9.4231, 6.08 }, { 8274, 324.6875, +25.4989, 6.16 }, { 8275, 324.4113, +54.0422, 6.15 }, { 8276, 324.7546, +20.2653, 5.85 },
+ { 8277, 324.8888,  +2.2436, 5.10 }, { 8278, 325.0229, -15.3378, 3.68 }, { 8279, 324.4800, +62.0819, 4.73 }, { 8280, 327.7262, -81.2808, 5.29 },
+ { 8281, 324.7400, +57.4892, 5.62 }, { 8282, 325.4421, -24.8981, 6.49 }, { 8283, 325.3871, -13.9525, 5.18 }, { 8284, 325.0462, +43.2739, 5.11 },
+ { 8285, 325.5033, -22.7372, 5.24 }, { 8286, 326.3700, -70.9911, 6.01 }, { 8287, 325.5421,  +1.2853, 5.67 }, { 8288, 325.6646, -17.1336, 4.73 },
+ { 8289, 325.5646,  +5.6800, 5.30 }, { 8290, 325.1804, +54.8722, 6.20 }, { 8291, 325.3929, +40.8053, 6.11 }, { 8292, 325.6375, +10.8247, 6.09 },
+ { 8293, 325.8062, -18.3792, 6.22 }, { 8294, 341.3692, -87.1817, 6.57 }, { 8295, 325.7683, -13.6003, 5.88 }, { 8296,   0.0000,  +0.0000, 0.00 },
+ { 8297, 325.5046, +35.5103, 6.07 }, { 8298, 325.5350, +45.7658, 6.17 }, { 8299, 326.1229, -37.4475, 6.30 }, { 8300, 325.5954, +41.0772, 5.69 },
+ { 8301, 325.5238, +51.1897, 4.67 }, { 8302, 326.0042, -13.2506, 5.99 }, { 8303, 326.3292, -48.5014, 6.45 }, { 8304, 325.6621, +49.6003, 6.09 },
+ { 8305, 326.2367, -32.9742, 4.34 }, { 8306, 325.7767, +41.1550, 5.49 }, { 8307, 325.8571, +38.2839, 5.65 }, { 8308, 326.0467,  +9.8750, 2.39 },
+ { 8309, 326.0358, +28.7428, 4.73 }, { 8310, 326.0346, +28.7431, 6.08 }, { 8311, 326.2513,  -8.9175, 5.09 }, { 8312, 325.6892, +59.2711, 6.08 },
+ { 8313, 326.1279, +17.3500, 4.34 }, { 8314, 326.1304, +14.7719, 5.94 }, { 8315, 326.1613, +25.6450, 4.13 }, { 8316, 325.8767, +58.7800, 4.08 },
+ { 8317, 325.4804, +71.3114, 4.56 }, { 8318, 326.5679,  -8.7242, 6.00 }, { 8319, 326.6338, -10.6342, 5.58 }, { 8320, 326.4354, +35.8572, 6.40 },
+ { 8321, 326.5183, +22.9489, 5.29 }, { 8322, 326.7600, -15.8728, 2.87 }, { 8323, 327.0658, -46.6964, 5.58 }, { 8324, 325.7667, +72.3203, 5.17 },
+ { 8325, 326.6000, +25.5633, 6.28 }, { 8326, 326.9342, -29.1017, 5.01 }, { 8327, 326.2221, +62.4606, 5.95 }, { 8328, 326.8083,  +2.6861, 5.64 },
+ { 8329, 326.5692, +43.0608, 6.54 }, { 8330, 326.7696, +17.1942, 6.21 }, { 8331, 327.5004, -63.2875, 5.62 }, { 8332, 326.9088,  -4.0828, 6.17 },
+ { 8333, 327.6963, -68.3706, 5.53 }, { 8334, 326.3621, +61.1208, 4.29 }, { 8335, 326.6983, +49.3094, 4.23 }, { 8336, 327.0346, +36.5806, 6.47 },
+ { 8337, 327.4212, -11.2769, 6.31 }, { 8338, 327.1225, +38.6486, 6.12 }, { 8339, 326.8554, +60.6928, 5.52 }, { 8340, 327.5546, -15.1553, 6.38 },
+ { 8341, 327.3621, +20.4625, 6.29 }, { 8342, 326.7542, +70.1508, 6.29 }, { 8343, 327.4613, +30.1742, 5.04 }, { 8344, 327.5363, +17.2856, 5.29 },
+ { 8345, 327.4171, +41.1489, 6.48 }, { 8346, 327.9242, -17.3769, 6.16 }, { 8347, 327.3292, +61.2728, 6.17 }, { 8348, 327.8925, +19.8267, 5.77 },
+ { 8349, 327.7704, +39.5367, 6.17 }, { 8350, 328.0758, +21.2731, 6.89 }, { 8351, 328.3242, -12.4483, 5.08 }, { 8352, 328.7979, -60.1136, 5.90 },
+ { 8353, 328.4821, -36.6350, 3.01 }, { 8354, 328.1246, +28.7933, 5.53 }, { 8355, 328.4000,  -9.6883, 6.59 }, { 8356, 328.2658, +25.9250, 5.08 },
+ { 8357, 328.0042, +55.7969, 5.71 }, { 8358, 328.4058, +19.6683, 5.68 }, { 8359, 328.4908,  +6.8644, 6.15 }, { 8360, 328.5433,  -3.7239, 5.71 },
+ { 8361, 327.9054, +65.7528, 6.37 }, { 8362, 329.0583, -56.1006, 6.19 }, { 8363, 328.6496,  -2.6989, 6.20 }, { 8364, 328.5725, +19.7183, 6.39 },
+ { 8365, 328.9817, -29.3936, 6.41 }, { 8366, 329.0950, -36.7464, 5.46 }, { 8367, 329.2592, -36.2531, 6.18 }, { 8368, 329.4796, -53.0075, 4.40 },
+ { 8369, 329.6254, -58.9878, 6.12 }, { 8370, 330.4671, -76.3375, 6.41 }, { 8371, 328.7217, +56.6114, 5.80 }, { 8372, 329.1000, +21.2397, 6.40 },
+ { 8373, 329.2350, +12.0764, 5.54 }, { 8374, 328.8363, +61.5419, 6.13 }, { 8375, 328.8796, +65.3208, 5.86 }, { 8376, 329.5554,  -4.5753, 6.33 },
+ { 8377, 329.2592, +48.6686, 6.42 }, { 8378, 329.6825, -20.8172, 6.12 }, { 8379, 329.8246, -37.6047, 5.50 }, { 8380, 330.7658, -75.8814, 5.95 },
+ { 8381, 330.1004, -54.1172, 6.01 }, { 8382, 329.7292,  -3.6269, 6.22 }, { 8383, 329.1629, +63.6256, 4.91 }, { 8384, 329.2962, +66.1561, 6.43 },
+ { 8385, 330.0329,  +6.7175, 6.00 }, { 8386, 330.2092, -27.5464, 5.42 }, { 8387, 330.8400, -55.2139, 4.69 }, { 8388, 329.7225, +62.6983, 5.93 },
+ { 8389, 329.8458, +57.6583, 6.59 }, { 8390, 330.2708,  +0.6050, 5.58 }, { 8391, 330.1117, +33.0061, 6.46 }, { 8392, 330.2725, +13.1197, 5.60 },
+ { 8393, 330.2883,  +8.2572, 5.65 }, { 8394, 330.5496, -16.0964, 6.28 }, { 8395, 329.4625, +74.9967, 6.35 }, { 8396, 330.6108, -15.0358, 6.37 },
+ { 8397, 330.5058, +10.9739, 6.37 }, { 8398, 330.8217, -28.0958, 7.10 }, { 8399, 330.1637, +62.4881, 6.66 }, { 8400, 329.8125, +73.1800, 5.03 },
+ { 8401, 330.8183,  -5.4775, 5.54 }, { 8402, 330.8288,  -1.8447, 4.69 }, { 8403, 330.4608, +52.8822, 5.78 }, { 8404, 330.8292, +11.3864, 5.80 },
+ { 8405, 331.0996, -28.0833, 6.47 }, { 8406, 330.5192, +58.0006, 5.56 }, { 8407, 330.7362, +44.6500, 5.60 }, { 8408, 331.1533, -25.1775, 5.96 },
+ { 8409, 331.4621, -58.3639, 5.62 }, { 8410, 331.1975,  +0.9067, 5.30 }, { 8411, 331.5288, -38.4567, 4.46 }, { 8412, 331.1433, +32.9419, 6.38 },
+ { 8413, 331.4200,  +5.0586, 4.84 }, { 8414, 331.4458,  +0.3197, 2.96 }, { 8415, 331.2975, +26.6739, 5.78 }, { 8416, 330.9704, +63.1197, 5.29 },
+ { 8417, 330.9475, +64.6278, 4.29 }, { 8418, 331.6092, -12.1303, 4.27 }, { 8419, 331.3946, +28.9639, 5.70 }, { 8420, 332.6771, -74.1194, 6.55 },
+ { 8421, 331.3183, +46.7447, 6.13 }, { 8422, 331.4608, +45.1122, 6.44 }, { 8423, 329.5529, +82.8697, 6.98 }, { 8424, 331.5083, +45.0144, 5.14 },
+ { 8425, 332.0583, -45.0389, 1.74 }, { 8426, 331.2521, +62.7856, 5.27 }, { 8427, 331.4633, +48.2317, 6.27 }, { 8428, 331.2871, +62.2800, 5.11 },
+ { 8429, 331.5517, +45.2486, 6.19 }, { 8430, 331.7529, +25.3450, 3.76 }, { 8431, 332.0958, -31.0114, 4.50 }, { 8432, 332.9804, -75.8839, 6.15 },
+ { 8433, 332.1083, -33.9561, 4.99 }, { 8434, 331.5562, +56.3431, 6.39 }, { 8435, 331.8692, +19.4756, 5.75 }, { 8436, 331.8750, +18.0006, 6.35 },
+ { 8437, 332.1779, -32.8744, 6.37 }, { 8438, 331.9596, +21.7028, 5.78 }, { 8439, 332.2458, -17.4803, 5.81 }, { 8440, 332.4917, -47.8928, 6.43 },
+ { 8441, 332.0717, +25.5436, 6.11 }, { 8442, 331.7900, +58.8408, 6.32 }, { 8443, 331.8562, +53.3072, 6.14 }, { 8444, 332.4821, -33.9853, 5.37 },
+ { 8445, 332.0688, +49.7964, 6.42 }, { 8446, 332.5004, -27.7075, 6.44 }, { 8447, 332.5367, -31.4517, 4.92 }, { 8448, 332.1708, +45.7419, 6.11 },
+ { 8449, 332.3067, +33.1722, 5.58 }, { 8450, 332.5500,  +6.1978, 3.53 }, { 8451, 332.5879,  -2.1058, 6.27 }, { 8452, 332.6563, -10.4350, 5.46 },
+ { 8453, 332.6408,  -3.7328, 6.01 }, { 8454, 332.4967, +33.1783, 4.29 }, { 8455, 332.5792, +19.6169, 6.18 }, { 8456, 332.5925, +14.6300, 6.33 },
+ { 8457, 332.7600, -20.7675, 6.09 }, { 8458, 332.6558, +11.6244, 5.78 }, { 8459, 332.6258, +20.9781, 6.46 }, { 8460, 332.7150, +30.5531, 6.32 },
+ { 8461, 332.9638, +16.0406, 5.95 }, { 8462, 333.1075, -13.8061, 6.03 }, { 8463, 332.7912, +50.8233, 5.40 }, { 8464, 333.2396, -25.6722, 6.17 },
+ { 8465, 332.7138, +58.2011, 3.35 }, { 8466, 333.0333, +24.9500, 5.92 }, { 8467, 333.1825,  -3.2792, 6.39 }, { 8468, 332.4517, +72.3411, 4.79 },
+ { 8469, 332.8779, +59.4144, 5.04 }, { 8470, 333.4350, -24.8192, 5.58 }, { 8471, 334.4604, -76.4883, 5.51 }, { 8472, 332.9533, +56.8394, 5.24 },
+ { 8473, 332.5638, +72.1111, 6.37 }, { 8474, 332.6621, +70.1328, 5.50 }, { 8475, 333.1992, +34.6047, 5.33 }, { 8476, 332.9871, +59.0847, 6.30 },
+ { 8477, 333.6608, -40.6183, 6.23 }, { 8478, 333.5783, -26.2331, 5.43 }, { 8479, 333.0079, +60.7594, 5.35 }, { 8480, 333.5750, -20.9258, 5.32 },
+ { 8481, 335.0063, -79.5603, 5.10 }, { 8482, 333.4108, +28.6083, 5.89 }, { 8483, 333.0929, +63.2914, 5.79 }, { 8484, 333.8963, -43.5481, 6.10 },
+ { 8485, 333.4696, +39.7150, 4.49 }, { 8486, 333.9038, -40.6533, 4.79 }, { 8487, 333.4554, +45.4408, 5.53 }, { 8488, 334.1108, -40.3725, 5.10 },
+ { 8489, 333.6850, +42.9539, 5.71 }, { 8490, 333.4563, +63.1625, 6.11 }, { 8491, 333.9992,  +8.5494, 6.21 }, { 8492, 334.1558, -24.1017, 6.15 },
+ { 8493, 333.2204, +73.3072, 6.08 }, { 8494, 333.7583, +57.0436, 4.19 }, { 8495, 334.1400,  -0.4036, 6.15 }, { 8496, 334.2004, -11.1686, 5.34 },
+ { 8497, 334.2492, -22.8600, 6.17 }, { 8498, 333.9925, +37.7489, 4.13 }, { 8499, 334.2083,  -6.2167, 4.16 }, { 8500, 334.2192,  -8.9600, 5.79 },
+ { 8501, 334.5650, -52.3722, 5.37 }, { 8502, 334.6254, -59.7403, 2.86 }, { 8503, 334.1237, +27.8042, 6.37 }, { 8504, 334.2771,  -4.6128, 5.75 },
+ { 8505, 337.9058, -84.0328, 5.77 }, { 8506, 334.1104, +57.2203, 5.88 }, { 8507, 334.5179,  +0.2378, 6.39 }, { 8508, 334.7533, -12.6950, 5.95 },
+ { 8509, 335.1508, -56.4900, 6.34 }, { 8510, 334.7342, +37.7694, 6.17 }, { 8511, 334.5529, +62.8044, 5.75 }, { 8512, 335.0496,  -6.1789, 5.37 },
+ { 8513, 335.1150,  +5.7894, 5.37 }, { 8514, 335.2325,  +8.1867, 6.17 }, { 8515, 336.1533, -71.7444, 5.29 }, { 8516, 335.3983, -20.4017, 5.13 },
+ { 8517, 335.2504, +26.9353, 6.47 }, { 8518, 335.4142,  -0.6128, 3.84 }, { 8519, 335.1650, +50.9808, 6.42 }, { 8520, 335.3796, +12.2053, 5.01 },
+ { 8521, 335.6829, -44.0522, 6.62 }, { 8522, 335.3304, +28.3306, 4.81 }, { 8523, 335.2567, +46.5367, 4.57 }, { 8524, 335.7833, -44.0714, 5.62 },
+ { 8525, 334.5850, +76.4881, 6.66 }, { 8526, 336.4625, -74.9844, 6.04 }, { 8527, 336.2937, -69.5683, 5.78 }, { 8528, 335.4621, +42.0783, 6.41 },
+ { 8529, 335.8788, -23.2375, 5.53 }, { 8530, 335.8838,  -6.8056, 5.93 }, { 8531, 336.2350, -56.2028, 5.32 }, { 8532, 335.9150, +20.8483, 6.04 },
+ { 8533, 336.0288,  -3.1631, 5.78 }, { 8534, 336.1129, -12.4706, 5.76 }, { 8535, 335.7508, +57.2844, 6.16 }, { 8536, 335.9758, +38.5736, 6.22 },
+ { 8537, 335.7508, +62.4200, 6.04 }, { 8538, 335.8900, +52.2292, 4.43 }, { 8539, 336.3192,  +1.3775, 4.66 }, { 8540, 336.8333, -63.0336, 4.48 },
+ { 8541, 336.1292, +49.4764, 4.57 }, { 8542, 336.5446, -22.3175, 6.29 }, { 8543, 336.4196, +18.4444, 6.26 }, { 8544, 336.6425, -15.2586, 6.57 },
+ { 8545, 336.6433, -15.2575, 6.35 }, { 8546, 333.2942, +86.1081, 5.27 }, { 8547, 337.1571, -66.5108, 5.55 }, { 8548, 336.6558,  +4.3936, 5.75 },
+ { 8549, 336.6904, +37.4439, 6.46 }, { 8550, 335.9221, +78.2433, 6.76 }, { 8551, 336.9646,  +4.6956, 4.79 }, { 8552, 337.1633, -38.8681, 5.47 },
+ { 8553, 336.8604, +39.8097, 6.14 }, { 8554, 336.7467, +56.4333, 6.57 }, { 8555, 336.9425, +31.8403, 5.98 }, { 8556, 337.3175, -42.5044, 3.97 },
+ { 8557, 336.5033, +70.7708, 5.47 }, { 8558, 337.2071,  +0.0203, 4.59 }, { 8559, 337.2088,  +0.0200, 4.42 }, { 8560, 337.4396, -42.2506, 4.11 },
+ { 8561, 336.7721, +65.1322, 5.46 }, { 8562, 337.2833,  +9.1289, 5.58 }, { 8563, 337.4417, -26.8928, 5.95 }, { 8564, 337.2925, +26.7631, 5.79 },
+ { 8565, 337.5063, -11.0850, 6.40 }, { 8566, 337.4917,  +4.4317, 5.48 }, { 8567, 337.5725, -13.4142, 6.37 }, { 8568, 337.0821, +64.0856, 6.29 },
+ { 8569, 337.4329, +35.7256, 6.56 }, { 8570, 337.7238, -25.9264, 6.43 }, { 8571, 337.2929, +58.4153, 3.75 }, { 8572, 337.3825, +47.7069, 4.36 },
+ { 8573, 337.6617,  -9.3219, 4.82 }, { 8574, 337.5075, +32.5725, 5.65 }, { 8575, 337.5271, +49.3561, 6.40 }, { 8576, 337.8763, -31.6539, 4.29 },
+ { 8577, 338.8600, -77.2283, 6.15 }, { 8578, 336.6771, +78.7858, 5.83 }, { 8579, 337.6221, +43.1233, 4.51 }, { 8580, 337.8267,  -1.0889, 6.16 },
+ { 8581, 337.8267,  -5.4450, 6.14 }, { 8582, 338.2504, -60.0178, 4.81 }, { 8583, 337.9221,  -9.0944, 6.38 }, { 8584, 337.8925, +29.5428, 6.35 },
+ { 8585, 337.8229, +50.2825, 3.77 }, { 8586, 338.1479, +20.2300, 6.42 }, { 8587, 338.1954, +15.8633, 6.32 }, { 8588, 338.1100, +39.7797, 5.88 },
+ { 8589, 338.0783, +54.0375, 6.35 }, { 8590, 338.5121,  -0.4258, 5.89 }, { 8591, 337.4704, +78.8242, 5.50 }, { 8592, 338.6733, -19.2917, 5.20 },
+ { 8593, 338.9704, -56.1164, 6.23 }, { 8594, 338.4192, +56.6250, 5.71 }, { 8595, 338.2621, +69.9136, 6.60 }, { 8596, 338.9021, -22.0089, 5.97 },
+ { 8597, 338.8392,  +0.1175, 4.02 }, { 8598, 338.3208, +70.3739, 6.34 }, { 8599, 338.0675, +76.2264, 5.68 }, { 8600, 339.1221, -39.4172, 6.28 },
+ { 8601, 339.1475, -30.3361, 5.82 }, { 8602, 339.2450, -39.4089, 5.86 }, { 8603, 338.9679, +39.6342, 5.73 }, { 8604, 339.0329, +35.5772, 6.10 },
+ { 8605, 339.1517, +11.6969, 6.40 }, { 8606, 338.9725, +50.0711, 6.29 }, { 8607, 338.9658, +56.0700, 6.38 }, { 8608, 339.2696, +12.5772, 6.30 },
+ { 8609, 339.2029, +35.6525, 6.30 }, { 8610, 339.4392,  -3.7719, 5.03 }, { 8611, 339.7850, -51.3078, 6.65 }, { 8612, 339.5925,  -6.1022, 6.23 },
+ { 8613, 339.3433, +51.5453, 4.63 }, { 8614, 339.6862, -27.2522, 6.47 }, { 8615, 338.9421, +73.6431, 5.08 }, { 8616, 339.7146, -32.9186, 5.66 },
+ { 8617, 339.5729, +45.1831, 6.40 }, { 8618, 339.7192, +19.5222, 5.82 }, { 8619, 339.9333, -27.6747, 6.31 }, { 8620, 340.2038, -56.5778, 5.97 },
+ { 8621, 339.6579, +56.7958, 5.21 }, { 8622, 339.8154, +39.0503, 4.88 }, { 8623, 340.0929, -29.3411, 5.87 }, { 8624, 339.9458, +19.6811, 6.21 },
+ { 8625, 339.3042, +75.3717, 5.79 }, { 8626, 339.8929, +37.5928, 6.03 }, { 8627, 339.6625, +63.5844, 5.19 }, { 8628, 340.1642, -26.9564, 4.17 },
+ { 8629, 340.2000,  -2.4458, 6.31 }, { 8630, 341.5138, -80.6183, 4.15 }, { 8631, 340.2196, +14.5494, 5.71 }, { 8632, 340.1288, +44.2764, 4.46 },
+ { 8633, 340.0767, +53.8461, 5.93 }, { 8634, 340.3654, +10.8314, 3.40 }, { 8635, 340.6538, -46.7894, 5.98 }, { 8636, 340.6671, -45.1153, 2.10 },
+ { 8637, 340.5921, -28.6392, 6.17 }, { 8638, 340.3808, +30.9658, 6.34 }, { 8639, 340.6796, -43.7522, 6.07 }, { 8640, 340.3692, +40.2256, 5.25 },
+ { 8641, 340.4392, +29.3075, 4.79 }, { 8642, 340.4892, +14.5164, 5.90 }, { 8643, 340.4004, +41.5494, 5.94 }, { 8644, 340.8750, -40.5856, 4.85 },
+ { 8645, 340.7646,  -7.6883, 6.45 }, { 8646, 341.0688, -59.5006, 6.30 }, { 8647, 340.8096,  -5.0372, 6.41 }, { 8648, 340.5867, +53.9089, 6.12 },
+ { 8649, 340.8971, -17.1697, 4.69 }, { 8650, 340.7504, +30.2214, 2.94 }, { 8651, 340.7312, +37.8028, 6.43 }, { 8652, 340.7688, +47.1686, 6.39 },
+ { 8653, 340.9279, +10.9392, 6.51 }, { 8654, 341.0217, +39.4656, 5.95 }, { 8655, 341.4079, -52.4997, 4.85 }, { 8656, 341.0229, +41.8192, 5.08 },
+ { 8657, 341.4196, -45.4525, 5.51 }, { 8658, 341.5333, -47.0211, 6.62 }, { 8659, 341.6179, -48.3142, 6.48 }, { 8660, 341.3675, +19.3667, 6.25 },
+ { 8661, 341.2050, +52.5172, 6.55 }, { 8662, 341.6821, -45.0606, 6.56 }, { 8663, 342.5954, -79.8758, 5.35 }, { 8664, 342.4204, -76.9494, 6.73 },
+ { 8665, 341.6733, +12.1728, 4.19 }, { 8666, 341.5425, +44.5461, 5.76 }, { 8667, 341.6329, +23.5656, 3.95 }, { 8668, 341.8296, -33.8389, 6.28 },
+ { 8669, 342.0892, -60.3158, 6.37 }, { 8670, 341.8879, -18.3867, 5.26 }, { 8671, 341.9463, -37.7781, 6.71 }, { 8672, 342.3225, -69.6522, 6.34 },
+ { 8673, 341.9283, -13.9436, 5.66 }, { 8674, 341.9842, -24.0881, 6.30 }, { 8675, 342.1388, -50.6831, 3.49 }, { 8676, 342.1258,  -9.4444, 6.19 },
+ { 8677, 341.8467, +58.4828, 6.36 }, { 8678, 342.0454, +37.4167, 5.90 }, { 8679, 342.3979, -12.4075, 4.01 }, { 8680, 342.4962, -31.1947, 6.33 },
+ { 8681, 342.3846, +10.4789, 6.54 }, { 8682, 342.1992, +54.4150, 6.12 }, { 8683, 342.1842, +62.9383, 6.06 }, { 8684, 342.5008, +24.6017, 3.48 },
+ { 8685, 342.7592, -38.8431, 5.42 }, { 8686, 342.9371, -58.1186, 6.46 }, { 8687, 342.2529, +68.5703, 6.19 }, { 8688, 342.4425, +55.9028, 5.43 },
+ { 8689, 343.0412, -62.8114, 6.12 }, { 8690, 342.5908, +41.9536, 5.92 }, { 8691, 342.6629, +19.1408, 6.40 }, { 8692, 342.5425, +50.6769, 6.21 },
+ { 8693, 342.8371, -28.4639, 5.97 }, { 8694, 342.4200, +66.2006, 3.52 }, { 8695, 343.1317, -31.1244, 4.46 }, { 8696, 342.8450, +61.6969, 5.60 },
+ { 8697, 343.1004,  +9.8356, 5.16 }, { 8698, 343.1538,  -6.4203, 3.74 }, { 8699, 343.0083, +43.3125, 4.94 }, { 8700, 343.4079, -47.4019, 6.04 },
+ { 8701, 343.6642, -69.9264, 6.05 }, { 8702, 341.8708, +83.1539, 4.74 }, { 8703, 343.2596, +16.8411, 5.64 }, { 8704, 343.3696, -10.3833, 5.80 },
+ { 8705, 343.2179, +50.4119, 6.46 }, { 8706, 343.2971, +40.1672, 6.34 }, { 8707, 343.2658, +60.1011, 6.01 }, { 8708, 343.4171, +44.7492, 5.81 },
+ { 8709, 343.6625, -14.1792, 3.27 }, { 8710, 343.6421,  -6.7953, 6.19 }, { 8711, 343.6896, -15.7281, 5.56 }, { 8712, 343.5292, +40.3769, 5.81 },
+ { 8713, 343.8121, -35.6114, 6.40 }, { 8714, 343.6488, +16.9417, 6.12 }, { 8715, 343.7479,  +1.0647, 6.11 }, { 8716, 343.7958,  -3.0122, 5.72 },
+ { 8717, 343.8071,  +8.8158, 4.90 }, { 8718, 343.7608, +37.0769, 5.91 }, { 8719, 343.9642, -30.3669, 6.10 }, { 8720, 343.9871, -31.4603, 4.21 },
+ { 8721, 344.1000, -30.4344, 6.48 }, { 8722, 344.1992, -46.0308, 5.70 }, { 8723, 343.9354, +36.3517, 5.74 }, { 8724, 344.2146, +11.8483, 6.51 },
+ { 8725, 344.0983, +41.6039, 5.59 }, { 8726, 344.1083, +49.7336, 4.95 }, { 8727, 344.3217,  -3.1900, 6.31 }, { 8728, 344.4129, -28.3778, 1.16 },
+ { 8729, 344.3662, +20.7689, 5.49 }, { 8730, 344.3867,  +3.8103, 6.28 }, { 8731, 344.2688, +48.6842, 5.43 }, { 8732, 344.6458, -34.4769, 6.13 },
+ { 8733, 344.4196, +39.3089, 6.18 }, { 8734, 344.5646,  -1.6047, 6.16 }, { 8735, 344.5988,  -0.5897, 6.37 }, { 8736, 342.7592, +85.3736, 5.90 },
+ { 8737, 344.6463,  +9.3569, 6.43 }, { 8738, 344.6775,  +7.3397, 6.33 }, { 8739, 344.7992, +11.7289, 5.75 }, { 8740, 344.8992, -28.5378, 5.51 },
+ { 8741, 344.8988, -12.9292, 6.07 }, { 8742, 344.8642,  +0.9628, 5.43 }, { 8743, 345.0242, -24.8358, 5.65 }, { 8744, 344.7929, +52.6544, 6.29 },
+ { 8745, 344.7875, +59.8147, 6.43 }, { 8746, 345.1025, -24.3733, 6.29 }, { 8747, 345.2200, -51.2458, 4.12 }, { 8748, 343.6033, +84.3461, 4.71 },
+ { 8749, 345.2813, -49.0500, 5.68 }, { 8750, 345.1579,  +0.1858, 6.21 }, { 8751, 345.1787,  +3.0117, 5.83 }, { 8752, 345.0213, +56.9453, 5.00 },
+ { 8753, 345.1771, +31.0831, 6.60 }, { 8754, 345.3308, -27.1464, 5.55 }, { 8755, 345.1433, +45.3750, 6.50 }, { 8756, 345.3458, -21.2092, 6.28 },
+ { 8757, 345.3483,  -6.9389, 6.21 }, { 8758, 345.2279, +38.7081, 6.54 }, { 8759, 345.3821,  -3.2886, 5.94 }, { 8760, 345.6417, -35.5792, 6.47 },
+ { 8761, 345.3779, +57.1056, 6.20 }, { 8762, 345.4804, +42.3261, 3.62 }, { 8763, 345.6358,  -5.4258, 6.15 }, { 8764, 345.6846, -19.1294, 5.97 },
+ { 8765, 345.6379, +31.7806, 6.57 }, { 8766, 345.6513, +42.7578, 5.10 }, { 8767, 345.8742, -33.2506, 5.11 }, { 8768, 345.6883, +44.0589, 6.39 },
+ { 8769, 346.2175, -67.1797, 5.52 }, { 8770, 345.6825, +55.2364, 6.50 }, { 8771, 345.9979, -40.5217, 5.79 }, { 8772, 345.9887,  -3.2047, 6.68 },
+ { 8773, 345.9692,  +3.8200, 4.53 }, { 8774, 346.1650, -52.0350, 5.37 }, { 8775, 345.9438, +28.0828, 2.42 }, { 8776, 346.0042,  +6.6167, 6.41 },
+ { 8777, 345.8488, +60.4453, 6.74 }, { 8778, 345.8400, +58.5647, 6.43 }, { 8779, 345.8871, +67.2092, 5.24 }, { 8780, 346.0458, +50.0522, 4.65 },
+ { 8781, 346.1904, +15.2053, 2.49 }, { 8782, 346.2908,  -6.3064, 5.43 }, { 8783, 346.3033, -16.9208, 6.14 }, { 8784, 346.2763, +16.5631, 6.44 },
+ { 8785, 346.3233,  +1.3069, 6.39 }, { 8786, 347.0988, -78.5192, 6.12 }, { 8787, 346.7200, -42.4794, 4.28 }, { 8788, 346.5758, +18.5175, 6.13 },
+ { 8789, 346.6704, -22.2569, 4.47 }, { 8790, 346.7233, -37.1078, 5.61 }, { 8791, 346.7896, -48.3933, 6.33 }, { 8792, 346.6329, +19.9108, 6.30 },
+ { 8793, 346.8112, -49.3136, 5.83 }, { 8794, 347.1488, -72.4136, 6.15 }, { 8795, 346.7513,  +9.4094, 4.52 }, { 8796, 346.7783, +25.4683, 4.76 },
+ { 8797, 346.6538, +59.4197, 4.85 }, { 8798, 346.8654, +32.8258, 6.02 }, { 8799, 346.8696, +21.1342, 5.99 }, { 8800, 346.8254, +46.0681, 6.66 },
+ { 8801, 346.7921, +52.8164, 6.11 }, { 8802, 347.0875, -27.1767, 5.60 }, { 8803, 346.7933, +59.7275, 6.40 }, { 8804, 346.9137, +46.3872, 5.33 },
+ { 8805, 346.9392, +49.2958, 5.70 }, { 8806, 347.0512, +44.5617, 6.56 }, { 8807, 347.1704,  +2.1278, 5.40 }, { 8808, 346.9488, +63.6333, 6.26 },
+ { 8809, 347.5487, -65.1425, 6.47 }, { 8810, 348.0500, -79.0872, 6.41 }, { 8811, 346.9883, +64.2225, 6.21 }, { 8812, 347.3617, -20.8275, 3.66 },
+ { 8813, 347.4358, -27.9114, 5.87 }, { 8814, 347.4887, -41.1394, 5.81 }, { 8815, 347.3813,  +8.6772, 5.12 }, { 8816, 347.4567, -13.4894, 6.42 },
+ { 8817, 347.4783, -21.5425, 4.69 }, { 8818, 347.5408, -39.4083, 5.83 }, { 8819, 346.9746, +75.3875, 4.41 }, { 8820, 347.5900, -44.7533, 3.90 },
+ { 8821, 347.5063,  +9.8219, 5.39 }, { 8822, 347.4337, +59.3331, 5.70 }, { 8823, 347.6942, -28.4750, 6.51 }, { 8824, 347.6775, +17.5944, 5.71 },
+ { 8825, 347.6133, +43.5442, 5.94 }, { 8826, 347.9342,  +8.7200, 5.16 }, { 8827, 347.9550, +26.8472, 6.17 }, { 8828, 348.3125, -48.3811, 6.80 },
+ { 8829, 348.5275, -61.3000, 6.12 }, { 8830, 348.1375, +49.4064, 4.52 }, { 8831, 348.2667, +29.4417, 6.35 }, { 8832, 348.3208, +57.1683, 5.56 },
+ { 8833, 348.3604, +11.0650, 5.82 }, { 8834, 348.5808,  -5.9511, 4.22 }, { 8835, 348.7442, -40.8944, 5.77 }, { 8836, 348.6675,  -9.3114, 6.12 },
+ { 8837, 348.5596, +50.6178, 6.31 }, { 8838, 348.5904, +29.7717, 6.41 }, { 8839, 348.6521, +24.1031, 6.36 }, { 8840, 348.8929,  -2.5036, 5.55 },
+ { 8841, 348.9729,  -8.9122, 4.21 }, { 8842, 348.9429, +28.2478, 6.49 }, { 8843, 349.2404, -61.9989, 5.66 }, { 8844, 348.6554, +74.2311, 5.84 },
+ { 8845, 348.9912, +24.7711, 6.60 }, { 8846, 349.1654, -43.5108, 5.92 }, { 8847, 349.2075, -40.8056, 6.47 }, { 8848, 349.3575, -57.7642, 3.99 },
+ { 8849, 349.7838, -78.5272, 6.33 }, { 8850, 349.2121,  -6.2733, 5.06 }, { 8851, 348.9075, +70.8881, 5.56 }, { 8852, 349.2912,  +3.2822, 3.69 },
+ { 8853, 349.1762, +53.2136, 5.54 }, { 8854, 349.1117, +61.9631, 6.53 }, { 8855, 349.5833, -66.5289, 6.13 }, { 8856, 349.4167, -10.2869, 6.34 },
+ { 8857, 349.3192, +45.1642, 6.43 }, { 8858, 349.4758,  -8.8175, 4.39 }, { 8859, 349.5412, -39.1756, 5.53 }, { 8860, 349.4362, +49.0153, 4.85 },
+ { 8861, 349.4837, +45.4889, 6.48 }, { 8862, 352.0154, -86.5178, 5.49 }, { 8863, 349.7058, -31.4681, 4.41 }, { 8864, 349.5975, +41.7736, 6.02 },
+ { 8865, 349.7404,  -8.3892, 4.98 }, { 8866, 349.7779, -12.5411, 5.08 }, { 8867, 349.3288, +75.2992, 6.38 }, { 8868, 349.8500,  -4.8756, 5.55 },
+ { 8869, 349.8504, -17.9247, 5.93 }, { 8870, 349.7600, +45.1372, 6.50 }, { 8871, 349.9300, -32.2919, 6.37 }, { 8872, 349.6563, +68.1117, 4.75 },
+ { 8873, 349.8642, +34.7933, 6.32 }, { 8874, 349.8742, +48.6253, 5.44 }, { 8875, 349.9233, +48.3808, 6.32 }, { 8876, 349.9683, +42.0781, 5.79 },
+ { 8877, 350.2083, -49.6933, 6.05 }, { 8878, 350.0858,  +5.3814, 5.05 }, { 8879, 350.1704,  -4.0919, 6.17 }, { 8880, 350.1592, +23.7403, 4.60 },
+ { 8881, 350.0596, +61.9700, 6.45 }, { 8882, 350.2067, +30.4150, 5.59 }, { 8883, 350.3146, -25.0133, 5.64 }, { 8884, 350.1833, +44.1164, 6.13 },
+ { 8885, 350.2221, +38.1822, 5.77 }, { 8886, 350.1442, +62.2131, 6.39 }, { 8887, 350.4787, +31.8125, 5.32 }, { 8888, 350.4925, +26.6089, 6.62 },
+ { 8889, 350.7371, -59.9442, 6.09 }, { 8890, 350.6633, -14.9608, 5.20 }, { 8891, 350.6687, +20.8286, 6.29 }, { 8892, 350.7425, -19.8994, 3.97 },
+ { 8893, 350.7692, +12.3139, 5.08 }, { 8894, 350.6354, +60.1336, 5.56 }, { 8895, 350.9762, -52.1917, 6.15 }, { 8896, 350.9392, -42.8756, 6.10 },
+ { 8897, 350.8829,  +0.2914, 6.31 }, { 8898, 351.0546, -50.1086, 5.75 }, { 8899, 350.9479, +32.5314, 6.69 }, { 8900, 351.0325, -17.3125, 6.19 },
+ { 8901, 351.3308, -55.1508, 5.59 }, { 8902, 351.1458, +41.1128, 6.72 }, { 8903, 351.2117, +32.3850, 5.57 }, { 8904, 351.2096, +62.2828, 4.98 },
+ { 8905, 351.3450, +23.4042, 4.40 }, { 8906, 351.5117, -19.3581, 4.39 }, { 8907, 351.6525, -51.2783, 5.52 }, { 8908, 351.7800, -65.4189, 6.45 },
+ { 8909, 351.8125, -57.5239, 5.63 }, { 8910, 351.7879, -49.8428, 6.20 }, { 8911, 351.7333,  +1.2556, 4.94 }, { 8912, 351.8117,  +1.1225, 6.25 },
+ { 8913, 351.7808, +42.9119, 5.75 }, { 8914, 352.0029, -34.4556, 6.32 }, { 8915, 351.9183, +25.1672, 5.98 }, { 8916, 351.9921,  +6.3789, 4.28 },
+ { 8917, 352.0217, -10.5503, 6.37 }, { 8918, 351.8192, +70.3597, 5.60 }, { 8919, 352.2542, -62.8892, 5.68 }, { 8920, 352.2533, -43.5022, 6.43 },
+ { 8921, 352.2525,  -8.7339, 6.18 }, { 8922, 352.2733, +23.0478, 6.35 }, { 8923, 352.2887, +12.7606, 4.55 }, { 8924, 352.3838,  -3.4672, 6.25 },
+ { 8925, 352.5308, +49.1331, 6.17 }, { 8926, 352.5083, +58.5489, 4.91 }, { 8927, 352.6654, +38.6619, 6.05 }, { 8928, 352.7546,  -5.7117, 6.39 },
+ { 8929, 352.8625, -43.1564, 6.02 }, { 8930, 352.8225, +39.2364, 5.22 }, { 8931, 352.8813,  -3.9128, 6.49 }, { 8932, 352.9254, -20.6306, 6.29 },
+ { 8933, 352.9296, +28.4036, 6.41 }, { 8934, 352.9900,  -0.9142, 6.38 }, { 8935, 353.3313, -76.6147, 5.81 }, { 8936, 353.1025, +34.9525, 6.65 },
+ { 8937, 353.2429, -36.1817, 4.37 }, { 8938, 351.7533, +87.3075, 5.58 }, { 8939, 353.3192, -19.0856, 4.71 }, { 8940, 353.3671, +22.4989, 5.32 },
+ { 8941, 353.4279, +45.0581, 6.24 }, { 8942, 353.4812, +20.8408, 6.06 }, { 8943, 353.4883, +31.3253, 4.98 }, { 8944, 353.5375,  -0.7525, 5.87 },
+ { 8945, 353.8029, -63.3106, 7.40 }, { 8946, 353.7058, -14.7542, 5.96 }, { 8947, 353.6563, +40.2364, 5.59 }, { 8948, 353.6592, +33.4972, 5.63 },
+ { 8949, 353.7692, -41.3850, 4.71 }, { 8950, 353.6946, +38.0239, 6.18 }, { 8951, 353.8838,  -6.5356, 6.39 }, { 8952, 353.7458, +71.6422, 5.84 },
+ { 8953, 353.9829, +24.5611, 6.45 }, { 8954, 354.0971,  +2.1022, 5.68 }, { 8955, 354.1271, +32.9042, 6.35 }, { 8956, 354.2725, -30.1292, 6.52 },
+ { 8957, 354.6004, -75.1300, 6.00 }, { 8958, 354.4150, -12.9397, 5.65 }, { 8959, 354.4625, -44.5075, 4.74 }, { 8960, 354.4158, +16.8256, 6.26 },
+ { 8961, 354.3913, +46.4581, 3.82 }, { 8962, 354.3833, +44.4292, 5.80 }, { 8963, 354.4867, +18.4006, 5.53 }, { 8964, 354.4942, +46.1997, 6.58 },
+ { 8965, 354.5342, +43.2681, 4.29 }, { 8966, 354.8667, -45.3622, 6.09 }, { 8967, 354.7846, +50.4717, 5.30 }, { 8968, 354.9463, -13.7783, 5.00 },
+ { 8969, 354.9875,  +5.6264, 4.13 }, { 8970, 354.9796,  +9.6772, 5.97 }, { 8971, 354.7933, +75.2928, 5.95 }, { 8972, 354.8379, +74.0028, 5.98 },
+ { 8973, 355.0117, +37.6525, 6.53 }, { 8974, 354.8367, +77.6325, 3.21 }, { 8975, 355.1592, -31.9269, 5.31 }, { 8976, 355.1021, +44.3339, 4.14 },
+ { 8977, 355.1692, +36.7208, 6.23 }, { 8978, 355.2792, -23.8397, 6.60 }, { 8979, 355.2871, -10.3194, 5.89 }, { 8980, 355.3938, -17.9728, 5.34 },
+ { 8981, 355.3621, +49.5122, 6.26 }, { 8982, 355.4408, -16.1836, 4.82 }, { 8983, 355.4862,  +7.2506, 5.89 }, { 8984, 355.5117,  +1.7800, 4.50 },
+ { 8985, 355.4771, +57.2600, 6.24 }, { 8986, 355.5617, +44.9919, 6.57 }, { 8987, 355.6162, -14.5522, 5.28 }, { 8988, 355.6804, -13.4550, 4.49 },
+ { 8989, 355.5867, +64.5156, 6.56 }, { 8990, 355.6313, +61.6794, 6.40 }, { 8991, 355.8433, +10.3314, 5.06 }, { 8992, 355.9563, -14.7156, 6.36 },
+ { 8993, 356.0058, -44.9167, 6.09 }, { 8994, 356.1058, -69.5097, 6.07 }, { 8995, 356.1696, -77.2086, 5.75 }, { 8996, 356.0500, -63.5956, 5.72 },
+ { 8997, 355.9979, +29.3617, 4.93 }, { 8998, 356.0504, -17.7231, 5.24 }, { 8999, 356.1204, -25.7536, 6.17 }, { 9000, 356.2013, +55.7997, 6.51 },
+ { 9001, 356.5050, -39.8175, 6.31 }, { 9002, 356.5038, -17.3219, 5.29 }, { 9003, 356.5088, +46.4203, 4.95 }, { 9004, 356.5979,  +3.4867, 5.04 },
+ { 9005, 356.6529, +66.7822, 5.95 }, { 9006, 356.8167, -49.7733, 5.18 }, { 9007, 356.8471, -67.6058, 6.89 }, { 9008, 356.7646, +58.6519, 4.87 },
+ { 9009, 356.8163, -10.0892, 5.73 }, { 9010, 356.7579, +57.4514, 5.51 }, { 9011, 356.8883, +46.8325, 6.07 }, { 9012, 356.9854,  -1.2383, 5.49 },
+ { 9013, 356.9783, +67.8069, 5.04 }, { 9014, 357.1354,  -5.6194, 6.07 }, { 9015, 357.2054,  +2.2142, 6.46 }, { 9016, 357.2317, -27.8697, 4.57 },
+ { 9017, 357.1625, +64.8764, 6.41 }, { 9018, 357.2092, +62.2144, 5.43 }, { 9019, 357.2246, +59.9789, 6.34 }, { 9020, 357.3000, +58.9631, 6.33 },
+ { 9021, 357.3817, -14.1389, 6.24 }, { 9022, 357.3646,  +1.0761, 5.77 }, { 9023, 357.4362, -61.1606, 6.59 }, { 9024, 357.4208, +36.4253, 5.90 },
+ { 9025, 357.4142, +28.8425, 5.97 }, { 9026, 357.4567, -24.6686, 6.42 }, { 9027, 357.5612,  -8.0258, 5.94 }, { 9028, 357.5929, +51.6217, 6.44 },
+ { 9029, 357.6388, -13.5981, 5.72 }, { 9030, 357.8383,  +9.3133, 5.79 }, { 9031, 357.8388, -17.0911, 5.18 }, { 9032, 358.0267, -81.9811, 5.11 },
+ { 9033, 357.9912,  +2.9303, 5.55 }, { 9034, 357.9900, +77.5994, 6.55 }, { 9035, 358.0975, +21.6708, 6.11 }, { 9036, 358.1221, +19.1203, 5.08 },
+ { 9037, 358.1250, -13.7489, 5.87 }, { 9038, 358.1046, +75.5447, 6.39 }, { 9039, 358.1546, +10.9475, 5.30 }, { 9040, 358.2104,  -7.0033, 5.75 },
+ { 9041, 358.2317,  -2.8444, 5.93 }, { 9042, 358.2700,  +2.0906, 6.28 }, { 9043, 358.3367, -23.7708, 6.24 }, { 9044, 358.5892, -26.9578, 6.35 },
+ { 9045, 358.5958, +57.4994, 4.54 }, { 9046, 358.6608, -39.7000, 6.03 }, { 9047, 358.6942,  +0.1092, 5.61 }, { 9048, 358.7825,  +7.0711, 6.21 },
+ { 9049, 358.8192, -30.0783, 6.10 }, { 9050, 358.8192, -30.1158, 6.83 }, { 9051, 358.8458, +25.9550, 6.54 }, { 9052, 358.8904, +57.4122, 6.00 },
+ { 9053, 358.8900, +47.3558, 6.00 }, { 9054, 359.1246, -23.2628, 6.31 }, { 9055, 359.1729, +22.6481, 6.15 }, { 9056, 359.1154, +83.1911, 6.59 },
+ { 9057, 359.2650, +42.6583, 5.97 }, { 9058, 359.2846, -25.3764, 6.26 }, { 9059, 359.2854, +55.7058, 5.55 }, { 9060, 359.3329, -61.0436, 5.97 },
+ { 9061, 359.3863, -81.8300, 5.73 }, { 9062, 359.3967, -63.7017, 5.00 }, { 9063, 359.3896, +60.0236, 6.47 }, { 9064, 359.4396, +25.1414, 4.66 },
+ { 9065, 359.5883, -14.1525, 6.26 }, { 9066, 359.6033, +51.3886, 4.80 }, { 9067, 359.6683,  -2.4439, 4.86 }, { 9068, 359.7050, +32.3817, 6.52 },
+ { 9069, 359.7325, -51.2542, 5.13 }, { 9070, 359.6938, +46.4131, 6.54 }, { 9071, 359.7521, +55.7550, 4.88 }, { 9072, 359.8279,  +6.8633, 4.01 },
+ { 9073, 359.8662, -28.5150, 5.62 }, { 9074, 359.8717, +33.7244, 6.58 }, { 9075, 359.8717, +33.7244, 6.58 }, { 9076, 359.9792, -64.4228, 4.50 },
+ { 9077,   0.0800, -43.7094, 6.29 }, { 9078,   0.0996, +26.9183, 6.46 }, { 9079,   0.1288, +59.5597, 6.19 }, { 9080,   0.1821, +45.2533, 6.38 },
+ { 9081,   0.2687, -47.1900, 5.71 }, { 9082,   0.3333, -49.6628, 5.53 }, { 9083,   0.3304, +49.9817, 6.22 }, { 9084,   0.3987, -76.9342, 4.78 },
+ { 9085,   0.4038, +61.2231, 5.55 }, { 9086,   0.4325, +42.3672, 6.25 }, { 9087,   0.4558,  -2.9725, 5.10 }, { 9088,   0.5425, +27.0819, 5.75 },
+ { 9089,   0.4900,  -5.9858, 4.41 }, { 9090,   0.5304, -13.3239, 7.10 }, { 9091,   0.5829, -28.2797, 5.01 }, { 9092,   0.6008,  +8.9569, 6.32 },
+ { 9093,   0.6238,  +8.4856, 5.63 }, { 9094,   0.6504, +66.0989, 5.86 }, { 9095,   0.7400, -19.9539, 6.25 }, { 9096,   0.7821, -23.8547, 6.44 },
+ { 9097,   0.8571, +63.6419, 6.24 }, { 9098,   0.9350, -16.6639, 4.55 }, { 9099,   0.9662, +66.7122, 6.29 }, { 9100,   1.0567, +62.2878, 5.88 },
+ { 9101,   1.0821, -15.4711, 5.78 }, { 9102,   1.0846, -28.7314, 6.40 }, { 9103,   1.1254,  -9.4906, 4.94 }, { 9104,   1.1750, +67.1667, 5.67 },
+ { 9105,   1.1529, +42.0922, 6.01 }, { 9106,   1.1279, -71.1022, 7.31 }, { 9107,   1.2242, +34.6597, 6.12 }, { 9108,   1.1721, -70.5631, 5.59 },
+ { 9109,   1.2333, +26.6489, 6.25 }, { 9110,   1.2758, +61.3142, 5.80 }, { 9110,   1.2758, +61.3142, 5.80 }, {    0,   0.0,      0.0,    0.0  },
+};
+
+const basicStarData * get_bright_star(int index) {
+    return &brightstars[index];
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/star.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,39 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef STAR_H
+#define STAR_H
+
+#define SEARCH_BOX  3.0
+
+typedef struct _basicStarData {
+    uint16_t  hr;
+    float  ra;
+    float  dec;
+    float  mag;
+} basicStarData;
+
+const basicStarData * get_bright_star(int index);
+basicStarData * star_closest(RaDec *radec, basicStarData *star);
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/stations.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,116 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#include "stations.h"
+
+/** COSPAR observing stations around the World. 
+ */
+const STATION_t stations[] = {
+    
+    { 2010, "MM",   30.3340,     -97.7610,   160.,  "5105 Crestway Dr." },
+    { 2011, "MM",   30.3150,     -97.8661,   300.,  "Bee Caves Rsrch Ctr" },
+    { 2420, "RE",   55.9486,      -3.1386,    40.,  "Russell Eberst" },
+    { 2675, "DB",   52.1358,      -2.3264,    70.,  "David Brierley" },
+    { 2676, "DB",   52.1273,      -2.3365,   107.,  "David Brierley" },
+    { 2018, "PW",   51.0945,      -1.1188,   150.,  "Peter Wakelin" },
+    { 2701, "TM",   43.6876,     -79.3924,   230.,  "Ted Molczan" },
+    { 3022, "JC",   48.7389,       3.4589,    52.,  "Jean-Paul Cornec" },
+    { 5917, "BG",   59.3418,      18.0545,    33.,  "Bjorn Gimle" },
+    { 5918, "BG",   59.2985,      18.1045,    44.,  "Bjorn Gimle" },
+    { 5919, "BG",   59.2615,      18.6206,    33.,  "Bjorn Gimle" },
+    { 9987, "BF",   59.3418,      18.0545,    30.,  "Bjorn Gimle" },
+    {  100, "SG",   59.4628,      17.9137,    30.,  "Sven Grahn" },
+    { 8305, "PG",   26.2431,     -98.2163,    30.,  "Paul Gabriel" },
+    { 2563, "PN",   51.0524,       2.4043,    10.,  "Pierre Nierinck" },
+    { 6226, "SC",   28.4861,     -97.8194,   110.,  "Scott Campbell" },
+    { 8539, "SN",   39.4707,     -79.3388,   839.,  "Steve Newcomb" },
+    { 2751, "BM",   51.3440,      -1.9849,   125.,  "Bruce MacDonald" },
+    { 2756, "AK",   56.0907,      -3.1623,    25.,  "Andy Kirkham" }, /* wow, that's me! Shame I no longer live there. */
+    {  433, "GR",  -33.9406,      18.5129,    10.,  "Greg Roberts" },
+    { 4541, "AR",   41.9639,      12.4531,    80.,  "Alberto Rango" },
+    { 4542, "AR",   41.9683,      12.4545,    80.,  "Alberto Rango" },
+    { 4641, "AR",   41.1060,      16.9010,    70.,  "Alberto Rango" },
+    { 2115, "MW",   51.3286,       0.7950,    75.,  "Mike Waterman" },
+    { 1775, "KF",   44.6062,     -75.6910,   200.,  "Kevin Fettner" },
+    { 1747, "DD",   45.7275,     -72.3526,   191.,  "Daniel Deak" },
+    { 8597, "TB",  -34.9638,     138.6333,   100.,  "Tony Beresford" }, 
+    { 8730, "EC",   30.3086,     -97.7279,   150.,  "Ed Cannon" },
+    { 9730, "MM",   30.3150,     -97.8660,   280.,  "BCRC (0002)" },
+    { 4353, "ML",   52.1541,       4.4908,     0.,  "Marco Langbroek" },
+    { 4354, "ML",   52.1168,       4.5602,    -2.,  "Marco Langbroek" },
+    {  710, "LS",   52.3261,      10.6756,    85.,  "Lutz Schindler" },
+    { 1056, "MK",   57.0122,      23.9833,     4.,  "Martins Keruss" },
+    {  110, "LK",   32.5408,     -96.8906,   200.,  "Lyn Kennedy" },
+    {   11, "VA",   44.7269,      34.0167,   580.,  "Crimea Astrophysical Observ." },
+    {   70, "BC",   53.2233,      -0.6003,    30.,  "Bob Christy" },
+    { 8335, "BY",   35.8311,     -96.1471,   335.,  "Brad Young" },
+    { 8336, "BY",   36.1397,     -95.9838,   205.,  "Brad Young" },
+    { 8337, "BY",   36.9557,     -96.5518,   395.,  "Brad Young" },
+    { 4160, "BD",   51.2793,       5.4768,    35.,  "Bram Dorreman" },
+    { 9011, "RM",   50.9310,       2.4053,    72.,  "Richard Miles" },
+    {   20, "PM",   50.7453,       2.1107,    70.,  "Paul Marsh" },
+    {   40, "IR",   50.7453,       2.1107,    70.,  "Ian Roberts" },
+    {   90, "RF",   50.7453,       2.1107,    70.,  "Richard Flagg" },
+    {    1, "AK",   56.1923,      -3.0340,    53.,  "SOWB Test Station" },       /* Used for testing the SOWB. */
+    {    0, "uk",    0.0000,       0.0000,     0.,  "Unknown station location" } /* Always the last entry. */
+};
+
+/** cospar_station_at
+ *
+ * Given a latitude and longitude is the point within a +/-0.0005 degree
+ * box of a given station? If so, return a handle (array index) for that
+ * station.
+ *
+ * @param double latitude
+ * @param double longitude
+ * @return int index
+ */
+int cospar_station_at(double latitude, double longitude) {
+    int i;
+    double high, low;
+    
+    for (i = 0; stations[i].cospar != 0; i++) {
+        high = stations[i].latitude + 0.0005;
+        low  = stations[i].latitude - 0.0005;
+        if (latitude <= high && latitude >= low) {
+            high = stations[i].longitude + 0.0005;
+            low  = stations[i].longitude - 0.0005;
+            if (longitude <= high && longitude >= low) {
+                return i;
+            }
+        }
+    }
+    
+    return i;
+}
+
+/** station
+ *
+ * Given an array index value, return a pointer to the station information structure.
+ * The proceedure is basically a look-up opertaion.
+ *
+ * @param int index
+ * @return STATION_t *  
+ */
+const STATION_t * cospar_station(int index) {
+    return &stations[index];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/stations.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,39 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+ 
+#ifndef STATION_H
+#define STATION_H
+
+typedef struct _station_t {
+    int     cospar;
+    char    short_name[3];
+    double  latitude;
+    double  longitude;
+    double  hasl;
+    char    long_name[32];
+} STATION_t;
+
+
+int cospar_station_at(double latitude, double longitude);
+const STATION_t * cospar_station(int index);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/utils.c	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,321 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+
+#include "sowb.h"
+#include "ctype.h"
+#include "utils.h"
+#include "gps.h"
+#include "debug.h"
+
+/** ascii2bin
+ *
+ * Converts an ascii char to binary nibble.
+ *
+ * @param char The character to convert [0-9][a-f][A-F]
+ * @return char the bin value or -1 on invalid hex char.
+ */
+char ascii2bin(char c) {
+    if (c >= '0' && c <= '9') return (c - '0') & 0xF;
+    if (c >= 'A' && c <= 'F') return (c - 'A' + 10) & 0xF;
+    if (c >= 'a' && c <= 'f') return (c - 'a' + 10) & 0xF;
+    return (char)0xFF;
+}
+
+/** hex2bin
+ *
+ * Converts a hex ascii string to binary int.
+ *
+ * Note, no error checking, assume string is valid hex chars [0-9][a-f][A-F]
+ *
+ * @param char *s The string to convert.
+ * @param int len The length of the string to convert.
+ * @return uint32_t the converted value.
+ */
+uint32_t hex2bin(char *s, int len) {
+    int i;
+    uint32_t rval;
+    
+    for (rval = 0, i = 0; i < len; i++) rval = rval | (ascii2bin(*(s + i)) << ((len - i - 1) * 4));
+    
+    return rval;
+}
+
+/** bin2ascii
+ *
+ * Convert a nibble to an ASCII character
+ *
+ * @param char c The nibble to convert
+ * @return char The character representation of the nibble.
+ */
+char bin2ascii(char c) {
+    c &= 0xF;
+    if (c < 0xA) return c + '0';
+    return c + 'A' - 10;
+}
+
+/** bin2hex
+ *
+ * Convert a binary to a hex string representation.
+ * The caller should allocate a buffer for *s before
+ * calling this function. The allocation should be
+ * len + 1 in length to hold the string and the 
+ * terminating null character.
+ *
+ * @param uint32_t d The value to convert.
+ * @param int len The string length.
+ * @param char *s Where to put the string.
+ * @return char * Returns *s passed in.
+ */
+ //  238E,238E
+ //  O832,O832
+
+char * bin2hex(uint32_t d, int len, char *s) {
+    char c, i = 0;
+    *(s + len) = '\0';
+    while (len) {
+        c = (d >> (4 * (len - 1))) & 0xF;
+        *(s + i) = bin2ascii(c);
+        len--; i++;        
+    }
+    return s;
+}
+
+/** dec2bin
+ *
+ * Converts a decimal ascii string to binary int.
+ *
+ * Note, no error checking, assume string is valid hex chars [0-9]
+ *
+ * @param char *s The string to convert.
+ * @param int len The length of the string to convert.
+ * @return uint32_t the converted value.
+ */
+uint32_t dec2bin(char *s, int len) {
+    int i, mul;
+    uint32_t rval = 0;
+    
+    for (mul = 1, i = len; i; i--, mul *= 10) rval += (ascii2bin(*(s + i - 1)) * mul);
+    
+    return rval;
+}
+
+/** strcsuml
+ *
+ * Return a two's compliment checksum char for th esupplied string.
+ *
+ * @param char * s The string to sum
+ * @param int len The length of the string.
+ * @return The two's compliment char.
+ */
+char strcsuml(char *s, int len) {
+    char sum = 0;
+    while (len) {
+        sum += *(s +len - 1);
+    }
+    return (~sum) + 1;
+}
+
+/** strcsum
+ *
+ * Return a two's compliment checksum char for the null terminated supplied string.
+ *
+ * @param char * s The string to sum
+ * @return The two's compliment char.
+ */
+char strcsum(char *s) {
+    return strcsuml(s, strlen(s));
+}
+
+/** strsuml
+ *
+ * Return the 8bit sum char for the supplied string.
+ *
+ * @param char * s The string to sum
+ * @param int len The length of the string.
+ * @return The sum
+ */
+char strsuml(char *s, int len) {
+    char sum = 0;
+    while (len) {
+        sum += *(s +len - 1);
+    }
+    return sum;
+}
+
+/** strsum
+ *
+ * Return the 8bit sum of all the characters of the supplied string.
+ *
+ * @param char * s The string to sum
+ * @return The sum
+ */
+char strsum(char *s) {
+    return strsuml(s, strlen(s));
+}
+
+/* Used for the date_AsString function. */
+const char month_abv[][4] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Wtf" };
+
+/** date_AsString
+ *
+ * Used to get the current date and return a formatted string.
+ * Note, the caller must have a 12byte buffer in place, pointed
+ * to by s to accept the string. 
+ *
+ * @param GPS_TIME *t A pointer to the time data struct to "print as"
+ * @param char *s A pointer to a buffer to hold the formatted string.
+ */
+void date_AsString(GPS_TIME *t, char *s) {
+    int month = t->month - 1; if (month > 11 || month < 0) month = 12; /* Ensure in range. */
+    sprintf(s, "%4.4d/%s/%2.2d", t->year, month_abv[month], t->day);
+}
+
+/** time_AsString
+ *
+ * Used to get the current time and return a formatted string.
+ * Note, the caller must have a 12byte buffer in place, pointed
+ * to by s to accept the string. 
+ *
+ * @param GPS_TIME *t A pointer to the time data struct to "print as"
+ * @param char *s A pointer to a buffer to hold the formatted string.
+ */
+void time_AsString(GPS_TIME *t, char *s) {    
+    sprintf(s, "%2.2d:%2.2d:%2.2d.%1.1d%1.1d", t->hour, t->minute, t->second, t->tenth, t->hundreth);
+}
+
+/** double2dms
+ *
+ * Takes double and converts it to a printable display string of
+ * degrees, minutes and seconds. 
+ * The caller is responsible for allocating the buffer *s before
+ * calling this function.
+ *
+ * @param char *s A pointer to the buffer to print to.
+ * @param double d The value to print.
+ */
+void double2dms(char *s, double d) {
+    int degrees, minutes;
+    double seconds, t;
+    
+    degrees = (int)d; t = (d - (double)degrees) * 60.;
+    minutes = (int)t;
+    seconds = (t - (double)minutes) * 60.;
+    
+    sprintf(s, "%03d\xb0%02d\x27%02d\x22", degrees, minutes, (int)seconds);
+}
+
+/** printDouble
+ *
+ * Print a double to a string buffer with correct leading zero(s).
+ * The caller is responsible for allocating the buffer *s before
+ * calling this function.
+ *
+ * @param char *s A pointer to the buffer to print to.
+ * @param double d The value to print.
+ */
+void printDouble(char *s, double d) {
+    if (isnan(d))       sprintf(s, "---.----");
+    else if (d > 100.)  sprintf(s, "%.4f", d);
+    else if (d > 10.)   sprintf(s, "0%.4f", d);
+    else                sprintf(s, "00%.4f", d);
+}
+
+/** printDouble_3_1
+ *
+ * Print a double to a string buffer with correct leading zero(s).
+ * The caller is responsible for allocating the buffer *s before
+ * calling this function.
+ *
+ * @param char *s A pointer to the buffer to print to.
+ * @param double d The value to print.
+ */
+char * printDouble_3_1(char *s, double d) {
+    char temp[16];
+    if (isnan(d))       sprintf(temp, "---.-");
+    else if (d > 100.)  sprintf(temp, "%.6f", d);
+    else if (d > 10.)   sprintf(temp, "0%.6f", d);
+    else                sprintf(temp, "00%.6f", d);
+    memcpy(s, temp, 5);
+    *(s+5) = '\0';
+    return s;
+}
+
+/** printDouble_3_2
+ *
+ * Print a double to a string buffer with correct leading zero(s).
+ * The caller is responsible for allocating the buffer *s before
+ * calling this function.
+ *
+ * @param char *s A pointer to the buffer to print to.
+ * @param double d The value to print.
+ */
+char * printDouble_3_2(char *s, double d) {
+    char temp[16];
+    if (isnan(d))       sprintf(temp, "---.--");
+    else if (d > 100.)  sprintf(temp, "%.6f", d);
+    else if (d > 10.)   sprintf(temp, "0%.6f", d);
+    else                sprintf(temp, "00%.6f", d);
+    memcpy(s, temp, 6);
+    *(s+6) = '\0';
+    return s;
+}
+
+void printBuffer(char *s, int len) {
+    #ifdef DEBUG_ON
+    for (int i = 0; i < len / 0x10; i++) {
+        debug_printf("%02X: ", i);
+        for (int j = 0; j < 0x10; j++) {
+            debug_printf("%02X ", s[(i * 0x10) + j]);
+            if (j == 7) debug_printf(" ");
+        }
+        for (int j = 0; j < 0x10; j++) {
+            if (isprint(s[(i * 0x10) + j])) {
+                debug_printf("%c", s[(i * 0x10) + j]);
+            }
+            else {
+                debug_printf(".");
+            }
+            if (j == 7) debug_printf(" ");
+        }
+        debug_printf("\r\n");
+    }
+    #endif
+}
+
+inline void disable_irqs(void) {
+    NVIC_DisableIRQ(EINT3_IRQn);
+    NVIC_DisableIRQ(RIT_IRQn);
+    NVIC_DisableIRQ(UART0_IRQn);
+    NVIC_DisableIRQ(UART1_IRQn);
+    NVIC_DisableIRQ(UART2_IRQn);
+    NVIC_DisableIRQ(USB_IRQn);
+}
+
+inline void enable_irqs(void) {
+    NVIC_EnableIRQ(USB_IRQn);
+    NVIC_EnableIRQ(EINT3_IRQn);
+    NVIC_EnableIRQ(RIT_IRQn);
+    NVIC_EnableIRQ(UART0_IRQn);
+    NVIC_EnableIRQ(UART1_IRQn);
+    NVIC_EnableIRQ(UART2_IRQn);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/utils.h	Mon Oct 11 10:34:55 2010 +0000
@@ -0,0 +1,52 @@
+/****************************************************************************
+ *    Copyright 2010 Andy Kirkham, Stellar Technologies Ltd
+ *    
+ *    This file is part of the Satellite Observers Workbench (SOWB).
+ *
+ *    SOWB is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    SOWB is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with SOWB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *    $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $
+ *    
+ ***************************************************************************/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "gps.h"
+
+char ascii2bin(char c);
+uint32_t hex2bin(char *s, int len);
+uint32_t dec2bin(char *s, int len);
+
+char bin2ascii(char c);
+char * bin2hex(uint32_t d, int len, char *s);
+
+char strcsum(char *s);
+char strcsuml(char *s, int len);
+
+char strsum(char *s);
+char strsuml(char *s, int len);
+
+void date_AsString(GPS_TIME *t, char *s);
+void time_AsString(GPS_TIME *t, char *s);
+
+void gps_get_coord_AsString(char *s, int type);
+
+void double2dms(char *s, double d);
+void printDouble(char *s, double d);
+char * printDouble_3_1(char *s, double d);
+char * printDouble_3_2(char *s, double d);
+
+void printBuffer(char *s, int len);
+#endif