altos: Add test scaffolding for APRS
[fw/altos] / src / drivers / ao_aprs.c
index 79cea49afbaa87028986e39e03a694a69f81964f..df68278c3d71b057af82c2ea7610736f77fadb30 100644 (file)
  *
  */
 
-// Hardware specific configuration.
-#include <18f2525.h>
-#device ADC=10
+#ifndef AO_APRS_TEST
+#include <ao.h>
+#endif
 
-// NOTE: Even though we are using an external clock, we set the HS oscillator mode to
-//       make the PIC 18F252 work with our external clock which is a clipped 1V P-P sine wave.
-#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
+#include <ao_aprs.h>
 
-// C runtime library definitions.
-#include 
-#include 
-
-// These compiler directives set the clock, SPI/I2C ports, and I/O configuration.
-
-// TCXO frequency
-#use delay(clock=19200000)
-
-// Engineering and data extracation port.
-#use rs232(baud=57600, xmit=PIN_B7, rcv=PIN_B6, STREAM=PC_HOST)
-
-// GPS engine 
-#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
-
-#use i2c (master, scl=PIN_C3, sda=PIN_C4)
-
-#use fast_io(A)
-#use fast_io(B)
-#use fast_io(C)
-
-// We define types that are used for all variables.  These are declared
-// because each processor has a different sizes for int and long.
-// The PIC compiler defines int8_t, int16_t, and int32_t.
-
-/// Boolean value { false, true }
-typedef boolean bool_t;
-
-/// Signed 8-bit number in the range -128 through 127.
-typedef signed int8 int8_t;
-
-/// Unsigned 8-bit number in the range 0 through 255.
-typedef unsigned int8 uint8_t;
-
-/// Signed 16-bit number in the range -32768 through 32767.
-typedef signed int16 int16_t;
-
-/// Unsigned 16-bit number in the range 0 through 65535.
-typedef unsigned int16 uint16_t;
-
-/// Signed 32-bit number in the range -2147483648 through 2147483647.
-typedef signed int32 int32_t;
-
-/// Unsigned 32-bit number in the range 0 through 4294967296.
-typedef unsigned int32 uint32_t;
-
-// Function and structure prototypes.  These are declared at the start of
-// the file much like a C++ header file.
-
-// Map I/O pin names to hardware pins.
-
-/// Heartbeat LED - Port A2
-#define IO_LED PIN_A2
-
-/// AD9954 DDS Profile Select 0 - Port A3
-#define IO_PS0 PIN_A3
-
-/// UHF amplifier and PA chain - Port A4
-#define IO_PTT PIN_A4
-
-/// AD9954 DDS Update - Port A5
-#define IO_UPDATE PIN_A5
-
-/// AD9954 CS (Chip Select) - Port B0
-#define IO_CS PIN_B0
-
-/// GPS Engine Power - Port B1
-#define IO_GPS_PWR PIN_B1
-
-/// AD9954 DDS Profile Select 1 - Port C0
-#define IO_PS1 PIN_C0
-
-/// AD9954 DDS OSK (Output Shift Key) - Port C2
-#define IO_OSK PIN_C2
-
-/// GPS engine serial transmit pin - Port C6
-#define IO_GPS_TXD PIN_C6
+typedef int bool_t;
+typedef int32_t int32;
+#define false 0
+#define true 1
 
 // Public methods, constants, and data structures for each class.
 
 /// Operational modes of the AD9954 DDS for the ddsSetMode function.
-enum DDS_MODE
+typedef enum
 {
     /// Device has not been initialized.
     DDS_MODE_NOT_INITIALIZED,
@@ -241,7 +166,7 @@ enum DDS_MODE
 
     /// Generate true FSK tones.
     DDS_MODE_FSK
-};
+}  DDS_MODE;
 
 void ddsInit();
 void ddsSetAmplitude (uint8_t amplitude);
@@ -251,15 +176,8 @@ void ddsSetFreq (uint32_t freq);
 void ddsSetFTW (uint32_t ftw);
 void ddsSetMode (DDS_MODE mode);
 
-void flashErase();
-uint8_t flashGetByte ();
-void flashReadBlock(uint32_t address, uint8_t *block, uint16_t length);
-void flashSendByte(uint8_t value);
-void flashSendAddress(uint32_t address);
-void flashWriteBlock(uint32_t address, uint8_t *block, uint8_t length);
-
 /// Type of GPS fix.
-enum GPS_FIX_TYPE 
+typedef enum
 {
     /// No GPS FIX
     GPS_NO_FIX,
@@ -269,7 +187,7 @@ enum GPS_FIX_TYPE
 
     /// 3D (Latitude/Longitude/Altitude) fix.
     GPS_3D_FIX
-};
+}  GPS_FIX_TYPE;
 
 /// GPS Position information.
 typedef struct 
@@ -329,6 +247,8 @@ typedef struct
     uint8_t visibleSats;
 } GPSPOSITION_STRUCT;
 
+GPSPOSITION_STRUCT gpsPosition;
+
 void gpsInit();
 bool_t gpsIsReady();
 GPS_FIX_TYPE gpsGetFixType();
@@ -337,47 +257,7 @@ void gpsPowerOn();
 bool_t gpsSetup();
 void gpsUpdate();
 
-int16_t lm92GetTemp();
-
-/// Define the log record types.
-enum LOG_TYPE 
-{
-    /// Time stamp the log was started.
-    LOG_BOOTED = 0xb4,
-
-    /// GPS coordinates.
-    LOG_COORD = 0xa5,
-
-    /// Temperature
-    LOG_TEMPERATURE = 0x96,
-
-    /// Bus voltage.
-    LOG_VOLTAGE = 0x87
-};
-
-void logInit();
-uint32_t logGetAddress();
-void logType (LOG_TYPE type);
-void logUint8 (uint8_t value);
-void logInt16 (int16_t value);
-
-bool_t serialHasData();
-void serialInit();
-uint8_t serialRead();
-void serialUpdate();
-
 uint16_t sysCRC16(uint8_t *buffer, uint8_t length, uint16_t crc);
-void sysInit();
-void sysLogVoltage();
-
-/// 0% duty cycle (LED Off) constant for function timeSetDutyCycle
-#define TIME_DUTYCYCLE_0 0
-
-/// 10% duty cycle constant for function timeSetDutyCycle
-#define TIME_DUTYCYCLE_10 1
-
-/// 70% duty cycle constant for function timeSetDutyCycle
-#define TIME_DUTYCYCLE_70 7
 
 uint8_t timeGetTicks();
 void timeInit();
@@ -385,7 +265,7 @@ void timeSetDutyCycle (uint8_t dutyCycle);
 void timeUpdate();
 
 /// Operational modes of the TNC for the tncSetMode function.
-enum TNC_DATA_MODE
+typedef enum
 {
     /// No operation waiting for setup and configuration.
     TNC_MODE_STANDBY, 
@@ -395,7 +275,7 @@ enum TNC_DATA_MODE
 
     /// 9600 bps using true FSK tones.
     TNC_MODE_9600_FSK
-};
+} TNC_DATA_MODE;
 
 void tncInit();
 bool_t tncIsFree();
@@ -406,395 +286,8 @@ void tnc9600TimerTick();
 void tncTxByte (uint8_t value);
 void tncTxPacket(TNC_DATA_MODE dataMode);
 
-/**
- *  @defgroup ADC Analog To Digital Converter
- *
- *  Control and manage the on board PIC A/D converter.
- *
- *  @{
- */
-
-/// Filtered voltages using a single pole, low pass filter.
-uint16_t adcMainBusVolt;
-
-/// PIC ADC Channel number of the reference voltage.
-#define ADC_REF 0
-
-/// PIC ADC Channel number of the main bus voltage.
-#define ADC_MAINBUS 1
-
-/// Input diode drop in units of 0.01 volts.
-#define MAIN_BUS_VOLT_OFFSET 20
-
-/**
- *  Intialize the ADC subsystem.
- */
-void adcInit()
-{
-    // Setup the ADC.
-    setup_adc_ports(AN0_TO_AN1);
-    setup_adc( ADC_CLOCK_DIV_32 );
-
-    // Zero the ADC filters.
-    adcMainBusVolt = 0;
-}
-
-/**
- *   Filtered main bus voltage in 10mV resolution.
- *
- *   @return voltage in 10mV steps
- */
-uint16_t adcGetMainBusVolt()
-{
-    uint32_t volts;
-
-    volts = (uint32_t) (adcMainBusVolt >> 3);
-
-    volts = (volts * 330l) / 1023l;
-
-    return (uint16_t) volts + MAIN_BUS_VOLT_OFFSET;
-}
-
-/** 
- *   Get the current ADC value for the main bus voltage.
- *
- *   @return ADC value in the range 0 to 1023
- */
-uint16_t adcRawBusVolt()
-{
-    set_adc_channel(ADC_MAINBUS);
-    delay_us(50);
-    return read_adc();
-}
-
-/** 
- *   Get the current ADC value for the reference source voltage.
- *
- *   @return ADC value in the range 0 to 1023
- */
-uint16_t adcRawRefVolt()
-{
-    set_adc_channel(ADC_REF);
-    delay_us(50);
-    return read_adc();
-}
-
-/**
- *   Read and filter the ADC channels for bus voltages.
- */
-void adcUpdate(void)
-{
-    // Filter the bus voltage using a single pole low pass filter.
-    set_adc_channel(ADC_MAINBUS);
-    delay_us(50);
-    adcMainBusVolt = read_adc() + adcMainBusVolt - (adcMainBusVolt >> 3);
-}
-
-/** @} */
-
-
-/**
- *  @defgroup diag Diagnostics and Control
- *
- *  Functions for diagnostics and control of the hardware and flight data recorder.
- *
- *  @{
- */
-
-/// Number of bytes per line to display when reading flight data recorder.
-#define DIAG_BYTES_PER_LINE 32
-
-/**
- *   Process the command to erase the data logger flash.
- */
-void diagEraseFlash()
-{
-    // Confirm we want to erase the flash with the key sequence 'yes' .
-    fprintf (PC_HOST, "Are you sure (yes)?  ");
-
-    if (fgetc(PC_HOST) != 'y')
-        return;
-
-    if (fgetc(PC_HOST) != 'e')
-        return;
-
-    if (fgetc(PC_HOST) != 's')
-        return;
-
-    if (fgetc(PC_HOST) != 13)
-        return;
-
-    // User feedback and erase the part.
-    fprintf (PC_HOST, "Erasing flash...");
-
-    flashErase();
-
-    fprintf (PC_HOST, "done.\n\r");
-}
-
-/**
- *   Display the engineering mode menu.
- */
-void diagMenu()
-{
-    // User interface.
-    fprintf (PC_HOST, "Options: (e)rase Flash, (r)ead Flash\n\r");
-    fprintf (PC_HOST, "         Toggle (L)ED\n\r");
-    fprintf (PC_HOST, "         (P)TT - Push To Transmit\n\r");
-    fprintf (PC_HOST, "         (f)requencey down, (F)requency up - 1KHz step\n\r");
-    fprintf (PC_HOST, "         (c)hannel down, (C)hannel up - 25KHz step\n\r");
-    fprintf (PC_HOST, "         (a)mplitude down, (A)mplitude up - 0.5 dB steps\n\r");
-    fprintf (PC_HOST, "         e(x)it engineering mode\n\r");
-}
-
-/**
- *   Process the command to dump the contents of the data logger flash.
- */
-void diagReadFlash()
-{
-    bool_t dataFoundFlag, userStopFlag;
-    uint8_t i, buffer[DIAG_BYTES_PER_LINE];
-    uint32_t address;
-
-    // Set the initial conditions to read the flash.
-    address = 0x0000;
-    userStopFlag = false;
-
-    do 
-    {
-        // Read each block from the flash device.
-        flashReadBlock (address, buffer, DIAG_BYTES_PER_LINE);
-
-        // This flag will get set if any data byte is not equal to 0xff (erase flash state)
-        dataFoundFlag = false;
-
-        // Display the address.
-        fprintf (PC_HOST, "%08lx ", address);
-
-        // Display each byte in the line.
-        for (i = 0; i < DIAG_BYTES_PER_LINE; ++i) 
-        {
-            fprintf (PC_HOST, "%02x", buffer[i]);
-
-            // Set this flag if the cell is not erased.
-            if (buffer[i] != 0xff)
-                dataFoundFlag = true;
-
-            // Any key will abort the transfer.
-            if (kbhit(PC_HOST))
-                userStopFlag = true;
-        } // END for
-
-        //  at the end of each line.
-        fprintf (PC_HOST, "\n\r");
-
-        // Advance to the next block of memory.
-        address += DIAG_BYTES_PER_LINE;
-    } while (dataFoundFlag && !userStopFlag);
-
-    // Feedback to let the user know why the transfer stopped.
-    if (userStopFlag)
-        fprintf (PC_HOST, "User aborted download!\n\r");
-}
-
-void diag1PPS()
-{
-    uint16_t timeStamp, lastTimeStamp;
-
-    lastTimeStamp = 0x0000;
-
-    gpsPowerOn();
-
-    for (;;)
-    {
-        timeStamp = CCP_2;
-
-        if (timeStamp != lastTimeStamp)
-        {
-            delay_ms (10);
-
-            timeStamp = CCP_2;
-
-            fprintf (PC_HOST, "%lu %lu\n\r", timeStamp, (timeStamp - lastTimeStamp));
-
-            lastTimeStamp = timeStamp;
-        }
-    }
-}
-
-/**
- *   Process diagnostic commands through the debug RS-232 port.
- */
-void diagPort()
-{
-    bool_t diagDoneFlag, ledFlag, paFlag, showSettingsFlag;
-    uint8_t command, amplitude;
-    uint32_t freqHz;
-
-    // If the input is low, we aren't connected to the RS-232 device so continue to boot.
-    if (!input(PIN_B6))
-        return;
-
-    fprintf (PC_HOST, "Engineering Mode\n\r");
-    fprintf (PC_HOST, "Application Built %s %s\n\r", __DATE__, __TIME__);
-
-    // Current state of the status LED.
-    ledFlag = false;
-    output_bit (IO_LED, ledFlag);
-
-    // This flag indicates we are ready to leave the diagnostics mode.
-    diagDoneFlag = false;
-
-    // Current state of the PA.
-    paFlag = false;
-
-    // Flag that indicate we should show the current carrier frequency.
-    showSettingsFlag = false;
-
-    // Set the initial carrier frequency and amplitude.
-    freqHz = 445950000;
-    amplitude = 0;
-
-    // Wait for the exit command.
-    while (!diagDoneFlag) 
-    {
-        // Wait for the user command.
-        command = fgetc(PC_HOST);
-
-        // Decode and process the key stroke.
-        switch (command) 
-        {
-            case 'e':
-                diagEraseFlash();
-                logInit();
-                break;
-
-            case 'l':
-            case 'L':
-                ledFlag = (ledFlag ? false : true);
-                output_bit (IO_LED, ledFlag);
-                break;
-
-            case 'h':
-            case 'H':
-            case '?':
-                diagMenu();
-                break;
-
-            case 'r':
-                diagReadFlash();
-                break;
-
-            case 't':
-                tncHighRate (true);
-                fprintf (PC_HOST, "Set high rate TNC.\n\r");    
-                break;
-
-            case 'f':
-                freqHz -= 1000;
-                ddsSetFreq (freqHz);
-
-                // Display the new frequency.
-                showSettingsFlag = true;
-                break;
-
-            case 'F':
-                freqHz += 1000;
-                ddsSetFreq (freqHz);
-
-                // Display the new frequency.
-                showSettingsFlag = true;
-                break;
-
-            case 'c':
-                freqHz -= 25000;
-                ddsSetFreq (freqHz);
-
-                // Display the new frequency.
-                showSettingsFlag = true;
-                break;
-
-            case 'C':
-                freqHz += 25000;
-                ddsSetFreq (freqHz);
-
-                // Display the new frequency.
-                showSettingsFlag = true;
-                break;
-
-            case 'p':
-            case 'P':
-                ddsSetFreq (freqHz);
-
-                paFlag = (paFlag ? false : true);
-                output_bit (IO_PTT, paFlag);
-                output_bit (IO_OSK, paFlag);
-
-                if (paFlag)
-                {
-                    ddsSetMode (DDS_MODE_AFSK);             
-                    ddsSetAmplitude (amplitude);
-                } else
-                    ddsSetMode (DDS_MODE_POWERDOWN);
-
-                break;
-
-            case 'a':
-                if (amplitude != 200)
-                {
-                    amplitude += 5;
-                    ddsSetAmplitude (amplitude);
-
-                    // Display the new amplitude.
-                    showSettingsFlag = true;
-                }
-                break;
-
-            case 'A':
-                if (amplitude != 0)
-                {
-                    amplitude -= 5;
-                    ddsSetAmplitude (amplitude);
-
-                    // Display the new amplitude.
-                    showSettingsFlag = true;
-                }
-                break;
-
-            case 'g':
-                diag1PPS();
-                break;
-
-            case 'x':
-                diagDoneFlag = true;
-                break;
-
-            default:
-                fprintf (PC_HOST, "Invalid command.  (H)elp for menu.\n\r");
-                break;
-        } // END switch
-
-        // Display the results of any user requests or commands.
-        if (showSettingsFlag) 
-        {
-            showSettingsFlag = false;
-
-            fprintf (PC_HOST, "%03ld.%03ld MHz  ", freqHz / 1000000, (freqHz / 1000) % 1000);
-            fprintf (PC_HOST, "%d.%01ddBc\n\r", amplitude / 10, amplitude % 10);
-
-        } // END if
-
-    } // END while
-
-    // Let the user know we are done with this mode.
-    fprintf (PC_HOST, "Exit diagnostic mode.\n\r");
-
-    return;
-}
-
 /** @} */
 
-
 /**
  *  @defgroup DDS AD9954 DDS (Direct Digital Synthesizer)
  *
@@ -894,89 +387,6 @@ const uint32_t freqTable[256] =
     955409113, 955410249, 955411390, 955412535, 955413684, 955414836, 955415989, 955417144
 };
 
-/**
- *   Initialize the DDS regsiters and RAM.
- */
-void ddsInit()
-{
-    // Setup the SPI port for the DDS interface.    
-    setup_spi( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_XMIT_L_TO_H );    
-
-    // Set the initial DDS mode.  The ddsSetMode function uses this value to make the desired DDS selections. 
-    ddsMode = DDS_MODE_NOT_INITIALIZED;
-
-    // Set the DDS operational mode.
-    ddsSetMode (DDS_MODE_POWERDOWN);
-
-    // Set the output to full scale.
-    ddsSetOutputScale (0x3fff);
-
-    // CFR2 (Control Function Register No. 2)
-    output_low (IO_CS);
-    spi_write (DDS_AD9954_CFR2);
-
-    spi_write (0x00);     // Unused register bits
-    spi_write (0x00);
-    spi_write (0x9c);     // 19x reference clock multipler, high VCO range, nominal charge pump current
-    output_high (IO_CS);
-
-    // ARR (Amplitude Ramp Rate) to 15mS for OSK
-    output_low (IO_CS);
-    spi_write (DDS_AD9954_ARR);
-
-    spi_write (83);
-    output_high (IO_CS);
-
-    // Strobe the part so we apply the updates.
-    output_high (IO_UPDATE);
-    output_low (IO_UPDATE);
-}
-
-/**
- *  Set DDS amplitude value in the range 0 to 16383 where 16383 is full scale.  This value is a 
- *  linear multiplier and needs to be scale for RF output power in log scale.
- *
- *  @param scale in the range 0 to 16383
- */
-void ddsSetOutputScale (uint16_t scale)
-{
-    // Set ASF (Amplitude Scale Factor)
-    output_low (IO_CS);
-    spi_write (DDS_AD9954_ASF);
-
-    spi_write ((scale >> 8) & 0xff);
-    spi_write (scale & 0xff);
-
-    output_high (IO_CS);
-    
-    // Strobe the DDS to set the amplitude.
-    output_high (IO_UPDATE);
-    output_low (IO_UPDATE);
-}
-
-/**
- *   Set the DDS amplitude in units of dBc of full scale where 1 is 0.1 dB.  For example, a value of 30 is 3dBc
- *   or a value of 85 is 8.5dBc.
- *
- *   @param amplitude in 0.1 dBc of full scale
- */ 
-void ddsSetAmplitude (uint8_t amplitude)
-{
-    // Range limit based on the lookup table size.
-    if (amplitude > 200)
-        return;
-
-    // Set the linear DDS ASF (Amplitude Scale Factor) based on the dB lookup table.
-    ddsSetOutputScale (DDS_AMP_TO_SCALE[amplitude / 5]);
-
-    // Toggle the DDS output low and then high to force it to ramp to the new output level setting.
-    output_low (IO_OSK);
-    delay_ms(25); 
-
-    output_high (IO_OSK);
-    delay_ms(25); 
-}
-
 /**
  *  Set DDS frequency tuning word.  The output frequency is equal to RefClock * (ftw / 2 ^ 32).
  *
@@ -984,20 +394,8 @@ void ddsSetAmplitude (uint8_t amplitude)
  */
 void ddsSetFTW (uint32_t ftw)
 {
-    // Set FTW0 (Frequency Tuning Word 0)
-    output_low (IO_CS);
-    spi_write (DDS_AD9954_FTW0);
-
-    spi_write ((ftw >> 24) & 0xff);
-    spi_write ((ftw >> 16) & 0xff);
-    spi_write ((ftw >> 8) & 0xff);
-    spi_write (ftw & 0xff);
-
-    output_high (IO_CS);
-    
-    // Strobe the DDS to set the frequency.
-    output_high (IO_UPDATE);
-    output_low (IO_UPDATE);     
+    int        x = ftw - freqTable[0];
+    putchar (x > 0 ? 0xff : 0x0);
 }
 
 /**
@@ -1029,31 +427,7 @@ void ddsSetFreq(uint32_t freq)
  */
 void ddsSetFSKFreq (uint32_t ftw0, uint32_t ftw1)
 {
-    // Set FTW0 (Frequency Tuning Word 0)
-    output_low (IO_CS);
-    spi_write (DDS_AD9954_FTW0);
-
-    spi_write ((ftw0 >> 24) & 0xff);
-    spi_write ((ftw0 >> 16) & 0xff);
-    spi_write ((ftw0 >> 8) & 0xff);
-    spi_write (ftw0 & 0xff);
-
-    output_high (IO_CS);
-    
-    // Set FTW0 (Frequency Tuning Word 1)
-    output_low (IO_CS);
-    spi_write (DDS_AD9954_FTW1);
-
-    spi_write ((ftw1 >> 24) & 0xff);
-    spi_write ((ftw1 >> 16) & 0xff);
-    spi_write ((ftw1 >> 8) & 0xff);
-    spi_write (ftw1 & 0xff);
-
-    output_high (IO_CS);
-    
-    // Strobe the DDS to set the frequency.
-    output_high (IO_UPDATE);
-    output_low (IO_UPDATE);     
+//     printf ("ftw0 %d ftw1 %d\n", ftw0, ftw1);
 }
 
 /** 
@@ -1063,342 +437,33 @@ void ddsSetFSKFreq (uint32_t ftw0, uint32_t ftw1)
  */
 void ddsSetMode (DDS_MODE mode)
 {
-    // Save the current mode.
-    ddsMode = mode;
-
-    switch (mode) 
-    {
-        case DDS_MODE_POWERDOWN:
-            // CFR1 (Control Function Register No. 1)
-            output_low (IO_CS);
-            spi_write (DDS_AD9954_CFR1);
-        
-            spi_write (0x00);
-            spi_write (0x00);
-            spi_write (0x00);
-            spi_write (0xf0);  // Power down all subsystems.
-            output_high (IO_CS);
-            break;
-
-        case DDS_MODE_AFSK:
-            // CFR1 (Control Function Register No. 1)
-            output_low (IO_CS);
-            spi_write (DDS_AD9954_CFR1);
-        
-            spi_write (0x03);  // OSK Enable and Auto OSK keying
-            spi_write (0x00);
-            spi_write (0x00);
-            spi_write (0x40);  // Power down comparator circuit
-            output_high (IO_CS);
-            break;
-
-        case DDS_MODE_FSK:
-            // CFR1 (Control Function Register No. 1)
-            output_low (IO_CS);
-            spi_write (DDS_AD9954_CFR1);
-
-            spi_write (0x03);  // Clear RAM Enable, OSK Enable, Auto OSK keying
-            spi_write (0x00);
-            spi_write (0x00);
-            spi_write (0x40);  // Power down comparator circuit
-            output_high (IO_CS);
-
-            // NOTE: The sweep rate requires 1/4 of a bit time (26uS) to transition.
-            // 6KHz delta = 70641 counts = (6KHz / 364.8MHz) * 2 ^ 32
-            // SYNC_CLK = 91.2MHz  1/91.2MHz * 70641 * 1/29 = 26.7uS
-
-            // NLSCW (Negative Linear Sweep Control Word)
-            output_low (IO_CS);
-            spi_write (DDS_AD9954_NLSCW);
-
-            spi_write (1);     // Falling sweep ramp rate word
-            spi_write (0x00);  // Delta frequency tuning word
-            spi_write (0x00);
-            spi_write (0x00);
-            spi_write (250); 
-            output_high (IO_CS);
-
-            // PLSCW (Positive Linear Sweep Control Word)
-            output_low (IO_CS);
-            spi_write (DDS_AD9954_PLSCW);
-
-            spi_write (1);     // Rising sweep ramp rate word
-            spi_write (0x00);  // Delta frequency tuning word
-            spi_write (0x00);
-            spi_write (0x00);
-            spi_write (250); 
-            output_high (IO_CS);
-            break;
-    } // END switch
-    
-    // Strobe the DDS to change the mode.
-    output_high (IO_UPDATE);
-    output_low (IO_UPDATE);      
+//     printf ("mode %d\n", mode);
 }
 
 /** @} */
 
 /**
- *  @defgroup flash Flash Manager
+ *  @defgroup GPS Motorola M12+ GPS Engine
  *
- *  Functions to control the ST MP25P80 serial flash device.
+ *  Functions to control the Motorola M12+ GPS engine in native binary protocol mode.
  *
  *  @{
  */
 
-/// Flash Chip Select - Port B3
-#define FLASH_CS PIN_B3
-
-/// Flash Clock - Port B5
-#define FLASH_CLK PIN_B5
-
-/// Flash Data Input - Port B4
-#define FLASH_D PIN_B4
-
-/// Flash Data Output - Port B2
-#define FLASH_Q PIN_B2
+/// The maximum length of a binary GPS engine message.
+#define GPS_BUFFER_SIZE 50
 
-/** 
- *   Determine if a flash write or erase operation is currently in progress.
- *
- *   @return true if write/erase in progress
- */
-bool_t flashIsWriteInProgress()
+/// GPS parse engine state machine values.
+typedef enum
 {
-    uint8_t status;
-
-    output_low (FLASH_CS);
+    /// 1st start character '@'
+    GPS_START1,
 
-    // Read Status Register (RDSR) flash command.
-    flashSendByte (0x05);
+    /// 2nd start character '@'
+    GPS_START2,
 
-    status = flashGetByte();
-
-    output_high (FLASH_CS);
-
-    return (((status & 0x01) == 0x01) ? true : false);
-}
-
-/**
- *   Read a block of memory from the flash device.
- *
- *   @param address of desired location in the range 0x00000 to 0xFFFFF (1MB)
- *   @param block pointer to locate of data block
- *   @param length number of bytes to read
- */
-void flashReadBlock(uint32_t address, uint8_t *block, uint16_t length)
-{
-    uint16_t i;
-    
-    output_low (FLASH_CS);
-
-    // Read Data Byte(s) (READ) flash command.
-    flashSendByte (0x03);
-    flashSendAddress (address);
-    
-    for (i = 0; i < length; ++i)
-        *block++ = flashGetByte();
-    
-    output_high (FLASH_CS);
-}
-
-/**
- *   Write a block of memory to the flash device.
- *
- *   @param address of desired location in the range 0x00000 to 0xFFFFF (1MB)
- *   @param block pointer data block to write
- *   @param length number of bytes to write
- */
-void flashWriteBlock(uint32_t address, uint8_t *block, uint8_t length)
-{
-    uint8_t i;
-
-    output_low (FLASH_CS);
-    // Write Enable (WREN) flash command.
-    flashSendByte (0x06);
-    output_high (FLASH_CS);
-    
-    output_low (FLASH_CS);
-    // Page Program (PP) flash command.
-    flashSendByte (0x02);
-    flashSendAddress (address);
-    
-    for (i = 0; i < length; ++i) 
-    {
-        // Send each byte in the data block.
-        flashSendByte (*block++);
-
-        // Track the address in the flash device.
-        ++address;
-
-        // If we cross a page boundary (a page is 256 bytes) we need to stop and send the address again.
-        if ((address & 0xff) == 0x00) 
-        {
-            output_high (FLASH_CS);
-
-            // Write this block of data.
-            while (flashIsWriteInProgress());
-
-            output_low (FLASH_CS);
-            // Write Enable (WREN) flash command.
-            flashSendByte (0x06);
-            output_high (FLASH_CS);
-
-            output_low (FLASH_CS);
-            // Page Program (PP) flash command.
-            flashSendByte (0x02);
-            flashSendAddress (address);
-        } // END if
-    } // END for    
-
-    output_high (FLASH_CS);
-
-    // Wait for the final write operation to complete.
-    while (flashIsWriteInProgress());
-}
-
-/** 
- *   Erase the entire flash device (all locations set to 0xff).
- */
-void flashErase()
-{
-    output_low (FLASH_CS);
-    // Write Enable (WREN) flash command.
-    flashSendByte (0x06);
-    output_high (FLASH_CS);
-    
-    output_low (FLASH_CS);
-    // Bulk Erase (BE) flash command.
-    flashSendByte (0xc7);
-    output_high (FLASH_CS);
-
-    while (flashIsWriteInProgress());
-}
-
-/**
- *   Read a single byte from the flash device through the serial interface.  This function
- *   only controls the clock line.  The chip select must be configured before calling
- *   this function.
- *
- *   @return byte read from device
- */
-uint8_t flashGetByte()
-{
-    uint8_t i, value;
-    
-    value = 0;      
-    
-    // Bit bang the 8-bits.
-    for (i = 0; i < 8; ++i) 
-    {
-        // Data is ready on the rising edge of the clock.
-        output_high (FLASH_CLK);
-
-        // MSB is first, so shift left.
-        value = value << 1;
-    
-        if (input (FLASH_Q))
-            value = value | 0x01;
-    
-        output_low (FLASH_CLK);
-    } // END for
-
-    return value;
-}
-
-/**
- *   Initialize the flash memory subsystem.
- */
-void flashInit()
-{
-    // I/O lines to control flash.
-    output_high (FLASH_CS);
-    output_low (FLASH_CLK);
-    output_low (FLASH_D);
-}
-
-/**
- *   Write a single byte to the flash device through the serial interface.  This function
- *   only controls the clock line.  The chip select must be configured before calling
- *   this function.
- *
- *   @param value byte to write to device
- */
-void flashSendByte(uint8_t value)
-{
-    uint8_t i;
-    
-    // Bit bang the 8-bits.
-    for (i = 0; i < 8; ++i) 
-    {
-        // Drive the data input pin.
-        if ((value & 0x80) == 0x80)
-            output_high (FLASH_D);
-        else
-            output_low (FLASH_D);
-        
-        // MSB is first, so shift leeft.
-        value = value << 1;
-        
-        // Data is accepted on the rising edge of the clock.
-        output_high (FLASH_CLK);
-        output_low (FLASH_CLK);
-    } // END for
-}
-
-/**
- *    Write the 24-bit address to the flash device through the serial interface.  This function
- *   only controls the clock line.  The chip select must be configured before calling
- *   this function.
- *
- *   @param address 24-bit flash device address
- */
-void flashSendAddress(uint32_t address)
-{
-    uint8_t i;
-    
-    // Bit bang the 24-bits.
-    for (i = 0; i < 24; ++i) 
-    {
-        // Drive the data input pin.
-        if ((address & 0x800000) == 0x800000)
-            output_high (FLASH_D);
-        else
-            output_low (FLASH_D);
-        
-        // MSB is first, so shift left.
-        address = address << 1;
-
-        // Data is accepted on the rising edge of the clock.
-        output_high (FLASH_CLK);
-        output_low (FLASH_CLK);
-    } // END for
-}
-
-/** @} */
-
-/**
- *  @defgroup GPS Motorola M12+ GPS Engine
- *
- *  Functions to control the Motorola M12+ GPS engine in native binary protocol mode.
- *
- *  @{
- */
-
-/// The maximum length of a binary GPS engine message.
-#define GPS_BUFFER_SIZE 50
-
-/// GPS parse engine state machine values.
-enum GPS_PARSE_STATE_MACHINE 
-{
-    /// 1st start character '@'
-    GPS_START1,
-
-    /// 2nd start character '@'
-    GPS_START2,
-
-    /// Upper case 'A' - 'Z' message type
-    GPS_COMMAND1,
+    /// Upper case 'A' - 'Z' message type
+    GPS_COMMAND1,
 
     /// Lower case 'a' - 'z' message type
     GPS_COMMAND2,
@@ -1414,7 +479,7 @@ enum GPS_PARSE_STATE_MACHINE
 
     /// End of message - Line Feed
     GPS_EOMLF
-};
+} GPS_PARSE_STATE_MACHINE;
 
 /// Index into gpsBuffer used to store message data.
 uint8_t gpsIndex;
@@ -1426,578 +491,194 @@ GPS_PARSE_STATE_MACHINE gpsParseState;
 uint8_t gpsBuffer[GPS_BUFFER_SIZE]; 
 
 /// Peak altitude detected while GPS is in 3D fix mode.
-int32_t gpsPeakAltitude;
-
-/// Checksum used to verify binary message from GPS engine.
-uint8_t gpsChecksum;
-
-/// Last verified GPS message received.
-GPSPOSITION_STRUCT gpsPosition;
-
-/**
- *   Get the type of fix.
- *
- *   @return gps fix type enumeration
- */
-GPS_FIX_TYPE gpsGetFixType()
-{
-    // The upper 3-bits determine the fix type.
-    switch (gpsPosition.status & 0xe000) 
-    {
-        case 0xe000:
-            return GPS_3D_FIX;
-
-        case 0xc000:
-            return GPS_2D_FIX;
-    
-        default:
-            return GPS_NO_FIX;
-    } // END switch
-}
-
-/**
- *  Peak altitude detected while GPS is in 3D fix mode since the system was booted.
- *
- *  @return altitude in feet
- */
-int32_t gpsGetPeakAltitude()
-{
-    return gpsPeakAltitude;
-}
-
-/** 
- *    Initialize the GPS subsystem.
- */
-void gpsInit()
-{
-    // Initial parse state.
-    gpsParseState = GPS_START1;
-
-    // Assume we start at sea level.
-    gpsPeakAltitude = 0;
-
-    // Clear the structure that stores the position message.
-    memset (&gpsPosition, 0, sizeof(GPSPOSITION_STRUCT));
-
-    // Setup the timers used to measure the 1-PPS time period.
-    setup_timer_3(T3_INTERNAL | T3_DIV_BY_1);
-    setup_ccp2 (CCP_CAPTURE_RE | CCP_USE_TIMER3);
-}
-
-/**
- *   Determine if new GPS message is ready to process.  This function is a one shot and
- *   typically returns true once a second for each GPS position fix.
- *
- *   @return true if new message available; otherwise false
- */
-bool_t gpsIsReady()
-{
-    if (gpsPosition.updateFlag) 
-    {
-        gpsPosition.updateFlag = false;
-        return true;
-    } // END if
-
-    return false;
-}
-
-/**
- *   Calculate NMEA-0183 message checksum of buffer that is length bytes long.
- *
- *   @param buffer pointer to data buffer.
- *   @param length number of bytes in buffer.
- *
- *   @return checksum of buffer
- */
-uint8_t gpsNMEAChecksum (uint8_t *buffer, uint8_t length)
-{
-    uint8_t i, checksum;
-
-    checksum = 0;
-
-    for (i = 0; i < length; ++i)
-        checksum ^= buffer[i];
-
-    return checksum;
-}
-
-/**
- *   Verify the GPS engine is sending the @@Hb position report message.  If not,
- *   configure the GPS engine to send the desired report.
- *
- *   @return true if GPS engine operation; otherwise false
- */
-bool_t gpsSetup()
-{
-    uint8_t startTime, retryCount;
-
-    // We wait 10 seconds for the GPS engine to respond to our message request.
-    startTime = timeGetTicks();
-    retryCount = 0;
-
-    while (++retryCount < 10) 
-    {
-        // Read the serial FIFO and process the GPS messages.
-        gpsUpdate();
-
-        // If a GPS data set is available, then GPS is operational.
-        if (gpsIsReady()) 
-        {
-            timeSetDutyCycle (TIME_DUTYCYCLE_10);
-            return true;
-        }
-
-        if (timeGetTicks() > startTime) 
-        {
-            puts ("@@Hb\001\053\015\012");
-            startTime += 10;
-        } // END if
-            
-    } // END while
-
-    return false;
-}
-
-/**
- *   Parse the Motorola @@Hb (Short position/message) report.
- */
-void gpsParsePositionMessage()
-{
-    // Convert the binary stream into data elements.  We will scale to the desired units
-    // as the values are used.
-    gpsPosition.updateFlag = true;
-
-    gpsPosition.month = gpsBuffer[0];
-    gpsPosition.day = gpsBuffer[1];
-    gpsPosition.year = ((uint16_t) gpsBuffer[2] << 8) | gpsBuffer[3];
-    gpsPosition.hours = gpsBuffer[4];
-    gpsPosition.minutes = gpsBuffer[5];
-    gpsPosition.seconds = gpsBuffer[6];
-    gpsPosition.latitude = ((int32) gpsBuffer[11] << 24) | ((int32) gpsBuffer[12] << 16) | ((int32) gpsBuffer[13] << 8) | (int32) gpsBuffer[14];
-    gpsPosition.longitude = ((int32) gpsBuffer[15] << 24) | ((int32) gpsBuffer[16] << 16) | ((int32) gpsBuffer[17] << 8) | gpsBuffer[18];
-    gpsPosition.altitudeCM = ((int32) gpsBuffer[19] << 24) | ((int32) gpsBuffer[20] << 16) | ((int32) gpsBuffer[21] << 8) | gpsBuffer[22];
-    gpsPosition.altitudeFeet = gpsPosition.altitudeCM * 100l / 3048l;
-    gpsPosition.vSpeed = ((uint16_t) gpsBuffer[27] << 8) | gpsBuffer[28];
-    gpsPosition.hSpeed = ((uint16_t) gpsBuffer[29] << 8) | gpsBuffer[30];
-    gpsPosition.heading = ((uint16_t) gpsBuffer[31] << 8) | gpsBuffer[32];
-    gpsPosition.dop = ((uint16_t) gpsBuffer[33] << 8) | gpsBuffer[34];
-    gpsPosition.visibleSats = gpsBuffer[35];
-    gpsPosition.trackedSats = gpsBuffer[36];
-    gpsPosition.status = ((uint16_t) gpsBuffer[37] << 8) | gpsBuffer[38];
-
-    // Update the peak altitude if we have a valid 3D fix.
-    if (gpsGetFixType() == GPS_3D_FIX)
-        if (gpsPosition.altitudeFeet > gpsPeakAltitude)
-            gpsPeakAltitude = gpsPosition.altitudeFeet;
-}
-
-/**
- *  Turn on the GPS engine power and serial interface.
- */
-void gpsPowerOn()
-{
-    // 3.0 VDC LDO control line.
-    output_high (IO_GPS_PWR);
-
-    // Enable the UART and the transmit line.
-#asm
-    bsf 0xFAB.7
-#endasm
-}
-
-/**
- *   Turn off the GPS engine power and serial interface.
- */
-void gpsPowerOff()
-{
-    // Disable the UART and the transmit line.
-#asm
-    bcf 0xFAB.7
-#endasm
-
-    // 3.0 VDC LDO control line.
-    output_low (IO_GPS_PWR);
-}
-
-/**
- *   Read the serial FIFO and process complete GPS messages.
- */
-void gpsUpdate() 
-{
-    uint8_t value;
-
-    // This state machine handles each characters as it is read from the GPS serial port.
-    // We are looking for the GPS mesage @@Hb ... C
-    while (serialHasData()) 
-    {
-        // Get the character value.
-        value = serialRead();
-
-        // Process based on the state machine.
-        switch (gpsParseState) 
-        {
-            case GPS_START1:
-                if (value == '@')
-                    gpsParseState = GPS_START2;
-                break;
-
-            case GPS_START2:
-                if (value == '@')
-                    gpsParseState = GPS_COMMAND1;
-                else
-                    gpsParseState = GPS_START1;
-                break;
-
-            case GPS_COMMAND1:
-                if (value == 'H')
-                    gpsParseState = GPS_COMMAND2;
-                else
-                    gpsParseState = GPS_START1;
-                break;
-
-            case GPS_COMMAND2:
-                if (value == 'b') 
-                {
-                    gpsParseState = GPS_READMESSAGE;
-                    gpsIndex = 0;
-                    gpsChecksum = 0;
-                    gpsChecksum ^= 'H';
-                    gpsChecksum ^= 'b';
-                } else
-                    gpsParseState = GPS_START1;
-                break;
-
-            case GPS_READMESSAGE:
-                gpsChecksum ^= value;
-                gpsBuffer[gpsIndex++] = value;
-
-                if (gpsIndex == 47)
-                    gpsParseState = GPS_CHECKSUMMESSAGE;
-
-                break;
-
-            case GPS_CHECKSUMMESSAGE:
-                if (gpsChecksum == value)
-                    gpsParseState = GPS_EOMCR;
-                else
-                    gpsParseState = GPS_START1;
-                break;
-
-            case GPS_EOMCR:
-                if (value == 13)
-                    gpsParseState = GPS_EOMLF;
-                else
-                    gpsParseState = GPS_START1;
-                break;
-
-            case GPS_EOMLF:
-                // Once we have the last character, convert the binary message to something usable.
-                if (value == 10)
-                    gpsParsePositionMessage();
-
-                gpsParseState = GPS_START1;
-                break;
-        } // END switch
-    } // END while
-}
-
-/** @} */
-
-
-/**
- *  @defgroup log Flight Data Recorder
- *
- *  Functions to manage and control the flight data recorder
- *
- *  @{
- */
-
-/// Number of bytes to buffer before writing to flash memory.
-#define LOG_WRITE_BUFFER_SIZE 40
-
-/// Last used address in flash memory.
-uint32_t logAddress;
-
-/// Temporary buffer that holds data before it is written to flash device.
-uint8_t logBuffer[LOG_WRITE_BUFFER_SIZE];
-
-/// Current index into log buffer.
-uint8_t logIndex;
-
-/** 
- *    Last used address in flash memory.  This location is where the next log data will
- *    be written.
- *
- *    @return 24-bit flash memory address
- */
-uint32_t logGetAddress()
-{
-    return logAddress;
-}
-
-/**
- *   Write the contents of the temporary log buffer to the flash device.  If the buffer
- *   is empty, nothing is done.
- */
-void logFlush()
-{
-    // We only need to write if there is data.
-    if (logIndex != 0) 
-    {
-        flashWriteBlock (logAddress, logBuffer, logIndex);
-        logAddress += logIndex;
-        logIndex = 0;
-    } // END if
-}
-
-/** 
- *   Prepare the flight data recorder for logging.
- */
-void logInit()
-{
-    uint8_t buffer[8];
-    bool_t endFound;
-
-    fprintf (PC_HOST, "Searching for end of flash log...");
-
-    logAddress = 0x0000;
-    endFound = false;
-
-    // Read each logged data block from flash to determine how long it is.
-    do 
-    {
-        // Read the data log entry type.
-        flashReadBlock (logAddress, buffer, 1);
-
-        // Based on the log entry type, we'll skip over the data contained in the entry.
-        switch (buffer[0]) 
-        {
-            case LOG_BOOTED:
-                logAddress += 7;
-                break;
-
-            case LOG_COORD:
-                logAddress += 26;
-                break;
-
-            case LOG_TEMPERATURE:
-                logAddress += 3;
-                break;
-
-            case LOG_VOLTAGE:
-                logAddress += 5;
-                break;
-
-            case 0xff:
-                endFound = true;
-                break;
-
-            default:
-                ++logAddress;
-        } // END switch
-    } while (logAddress < 0x100000 && !endFound);
+int32_t gpsPeakAltitude;
 
-    fprintf (PC_HOST, "done.  Log contains %ld bytes.\n\r", logAddress);
+/// Checksum used to verify binary message from GPS engine.
+uint8_t gpsChecksum;
 
-    logIndex = 0;
-}
+/// Last verified GPS message received.
+GPSPOSITION_STRUCT gpsPosition;
 
 /**
- *   Start a entry in the data log.
+ *   Get the type of fix.
  *
- *   @param type of log entry, i.e. LOG_BOOTED, LOG_COORD, etc.
+ *   @return gps fix type enumeration
  */
-void logType (LOG_TYPE type)
+GPS_FIX_TYPE gpsGetFixType()
 {
-    // Only add the new entry if there is space.
-    if (logAddress >= 0x100000)
-        return;
-
-    // Write the old entry first.
-    logFlush();
+    // The upper 3-bits determine the fix type.
+    switch (gpsPosition.status & 0xe000) 
+    {
+        case 0xe000:
+            return GPS_3D_FIX;
 
-    // Save the type and set the log buffer pointer.
-    logBuffer[0] = type;
-    logIndex = 1;
+        case 0xc000:
+            return GPS_2D_FIX;
+    
+        default:
+            return GPS_NO_FIX;
+    } // END switch
 }
 
 /**
- *  Save an unsigned, 8-bit value in the log.
+ *  Peak altitude detected while GPS is in 3D fix mode since the system was booted.
  *
- *  @param value unsigned, 8-bit value
+ *  @return altitude in feet
  */
-void logUint8 (uint8_t value)
+int32_t gpsGetPeakAltitude()
 {
-    logBuffer[logIndex++] = value;
+    return gpsPeakAltitude;
 }
 
-/**
- *  Save a signed, 16-bit value in the log.
- *
- *  @param value signed, 16-bit value
+/** 
+ *    Initialize the GPS subsystem.
  */
-void logInt16 (int16_t value)
+void gpsInit()
 {
-    logBuffer[logIndex++] = (value >> 8) & 0xff;
-    logBuffer[logIndex++] = value & 0xff;
-}
+    // Initial parse state.
+    gpsParseState = GPS_START1;
 
-/**
- *  Save an unsigned, 16-bit value in the log.
- *
- *  @param value unsigned, 16-bit value
- */
-void logUint16 (uint16_t value)
-{
-    logBuffer[logIndex++] = (value >> 8) & 0xff;
-    logBuffer[logIndex++] = value & 0xff;
+    // Assume we start at sea level.
+    gpsPeakAltitude = 0;
+
+    // Clear the structure that stores the position message.
+    memset (&gpsPosition, 0, sizeof(GPSPOSITION_STRUCT));
+
+    // Setup the timers used to measure the 1-PPS time period.
+//    setup_timer_3(T3_INTERNAL | T3_DIV_BY_1);
+//    setup_ccp2 (CCP_CAPTURE_RE | CCP_USE_TIMER3);
 }
 
 /**
- *  Save a signed, 32-bit value in the log.
+ *   Determine if new GPS message is ready to process.  This function is a one shot and
+ *   typically returns true once a second for each GPS position fix.
  *
- *  @param value signed, 32-bit value
+ *   @return true if new message available; otherwise false
  */
-void logInt32 (int32_t value)
+bool_t gpsIsReady()
 {
-    logBuffer[logIndex++] = (value >> 24) & 0xff;
-    logBuffer[logIndex++] = (value >> 16) & 0xff;
-    logBuffer[logIndex++] = (value >> 8) & 0xff;
-    logBuffer[logIndex++] = value & 0xff;
-}
+    return true;
+    if (gpsPosition.updateFlag) 
+    {
+        gpsPosition.updateFlag = false;
+        return true;
+    } // END if
 
-/** @} */
+    return false;
+}
 
 /**
- *  @defgroup LM92 LM92 temperature sensor
- *
- *  Read and control the National Semiconductor LM92 I2C temperature sensor
+ *   Calculate NMEA-0183 message checksum of buffer that is length bytes long.
  *
- *  @{
- */
-
-/** 
- *   Read the LM92 temperature value in 0.1 degrees F.
+ *   @param buffer pointer to data buffer.
+ *   @param length number of bytes in buffer.
  *
- *   @return 0.1 degrees F
+ *   @return checksum of buffer
  */
-int16_t lm92GetTemp()
+uint8_t gpsNMEAChecksum (uint8_t *buffer, uint8_t length)
 {
-    int16_t value;
-    int32_t temp;
-
-    // Set the SDA and SCL to input pins to control the LM92.
-    set_tris_c (0x9a);
-
-    // Read the temperature register value.
-    i2c_start();
-    i2c_write(0x97);
-    value = ((int16_t) i2c_read() << 8);
-    value = value | ((int16_t) i2c_read() & 0x00f8);
-    i2c_stop();
+    uint8_t i, checksum;
 
-    // Set the SDA and SCL back to outputs for use with the AD9954 because we share common clock pins.
-    set_tris_c (0x82);
+    checksum = 0;
 
-    //  LM92 register   0.0625degC/bit   9   10     9
-    //  ------------- * -------------- * - * -- =  -- + 320
-    //        8                          5         64
+    for (i = 0; i < length; ++i)
+        checksum ^= buffer[i];
 
-    // Convert to degrees F.
-    temp = (int32_t) value;
-    temp = ((temp * 9l) / 64l) + 320;
-    
-    return (int16_t) temp;
+    return checksum;
 }
 
-/** @} */
-
-
 /**
- *  @defgroup serial Serial Port FIFO
- *
- *  FIFO for the built-in serial port.
+ *   Verify the GPS engine is sending the @@Hb position report message.  If not,
+ *   configure the GPS engine to send the desired report.
  *
- *  @{
+ *   @return true if GPS engine operation; otherwise false
  */
+bool_t gpsSetup()
+{
+    uint8_t startTime, retryCount;
 
-/// Size of serial port FIFO in bytes.  It must be a power of 2, i.e. 2, 4, 8, 16, etc.
-#define SERIAL_BUFFER_SIZE 64
+    // We wait 10 seconds for the GPS engine to respond to our message request.
+    startTime = timeGetTicks();
+    retryCount = 0;
 
-/// Mask to wrap around at end of circular buffer.  (SERIAL_BUFFER_SIZE - 1)
-#define SERIAL_BUFFER_MASK 0x3f
+    while (++retryCount < 10) 
+    {
+        // Read the serial FIFO and process the GPS messages.
+//        gpsUpdate();
 
-/// Index to the next free location in the buffer.
-uint8_t serialHead;
+        // If a GPS data set is available, then GPS is operational.
+        if (gpsIsReady()) 
+        {
+//            timeSetDutyCycle (TIME_DUTYCYCLE_10);
+            return true;
+        }
 
-/// Index to the next oldest data in the buffer.
-uint8_t serialTail;
+        if (timeGetTicks() > startTime) 
+        {
+            puts ("@@Hb\001\053\015\012");
+            startTime += 10;
+        } // END if
+            
+    } // END while
 
-/// Circular buffer (FIFO) to hold serial data.
-uint8_t serialBuffer[SERIAL_BUFFER_SIZE];
+    return false;
+}
 
 /**
- *   Determine if the FIFO contains data.
- *
- *   @return true if data present; otherwise false
+ *   Parse the Motorola @@Hb (Short position/message) report.
  */
-bool_t serialHasData()
+void gpsParsePositionMessage()
 {
-    if (serialHead == serialTail)
-        return false;
+    // Convert the binary stream into data elements.  We will scale to the desired units
+    // as the values are used.
+    gpsPosition.updateFlag = true;
 
-    return true;
-}
+    gpsPosition.month = gpsBuffer[0];
+    gpsPosition.day = gpsBuffer[1];
+    gpsPosition.year = ((uint16_t) gpsBuffer[2] << 8) | gpsBuffer[3];
+    gpsPosition.hours = gpsBuffer[4];
+    gpsPosition.minutes = gpsBuffer[5];
+    gpsPosition.seconds = gpsBuffer[6];
+    gpsPosition.latitude = ((int32) gpsBuffer[11] << 24) | ((int32) gpsBuffer[12] << 16) | ((int32) gpsBuffer[13] << 8) | (int32) gpsBuffer[14];
+    gpsPosition.longitude = ((int32) gpsBuffer[15] << 24) | ((int32) gpsBuffer[16] << 16) | ((int32) gpsBuffer[17] << 8) | gpsBuffer[18];
+    gpsPosition.altitudeCM = ((int32) gpsBuffer[19] << 24) | ((int32) gpsBuffer[20] << 16) | ((int32) gpsBuffer[21] << 8) | gpsBuffer[22];
+    gpsPosition.altitudeFeet = gpsPosition.altitudeCM * 100l / 3048l;
+    gpsPosition.vSpeed = ((uint16_t) gpsBuffer[27] << 8) | gpsBuffer[28];
+    gpsPosition.hSpeed = ((uint16_t) gpsBuffer[29] << 8) | gpsBuffer[30];
+    gpsPosition.heading = ((uint16_t) gpsBuffer[31] << 8) | gpsBuffer[32];
+    gpsPosition.dop = ((uint16_t) gpsBuffer[33] << 8) | gpsBuffer[34];
+    gpsPosition.visibleSats = gpsBuffer[35];
+    gpsPosition.trackedSats = gpsBuffer[36];
+    gpsPosition.status = ((uint16_t) gpsBuffer[37] << 8) | gpsBuffer[38];
 
-/** 
- *   Initialize the serial processor.
- */
-void serialInit()
-{
-    serialHead = 0;
-    serialTail = 0;
+    // Update the peak altitude if we have a valid 3D fix.
+    if (gpsGetFixType() == GPS_3D_FIX)
+        if (gpsPosition.altitudeFeet > gpsPeakAltitude)
+            gpsPeakAltitude = gpsPosition.altitudeFeet;
 }
 
 /**
- *   Get the oldest character from the FIFO.
- *
- *   @return oldest character; 0 if FIFO is empty
+ *  Turn on the GPS engine power and serial interface.
  */
-uint8_t serialRead()
+void gpsPowerOn()
 {
-    uint8_t value;
-
-    // Make sure we have something to return.
-    if (serialHead == serialTail)
-        return 0;
-
-    // Save the value.
-    value = serialBuffer[serialTail];
-
-    // Update the pointer.
-    serialTail = (serialTail + 1) & SERIAL_BUFFER_MASK;
+    // 3.0 VDC LDO control line.
+//    output_high (IO_GPS_PWR);
 
-    return value;
 }
 
 /**
- *   Read and store any characters in the PIC serial port in a FIFO.
+ *   Turn off the GPS engine power and serial interface.
  */
-void serialUpdate()
+void gpsPowerOff()
 {
-    // If there isn't a character in the PIC buffer, just leave.
-    while (kbhit()) 
-    {
-        // Save the value in the FIFO.
-        serialBuffer[serialHead] = getc();
-
-        // Move the pointer to the next open space.
-        serialHead = (serialHead + 1) & SERIAL_BUFFER_MASK;
-    }
+    // 3.0 VDC LDO control line.
+//    output_low (IO_GPS_PWR);
 }
 
 /** @} */
 
+
 /**
  *  @defgroup sys System Library Functions
  *
@@ -2035,65 +716,6 @@ uint16_t sysCRC16(uint8_t *buffer, uint8_t length, uint16_t crc)
     return crc ^ 0xffff;
 }
 
-/**
- *   Initialize the system library and global resources.
- */
-void sysInit()
-{
-    gpsPowerOff ();
-    output_high (IO_LED);
-
-    output_high (IO_CS);
-    output_low (IO_PS1);
-    output_low (IO_PS0);
-    output_low (IO_OSK);
-    output_low (IO_UPDATE);
-    output_low (IO_PTT);
-    output_low (IO_GPS_TXD);
-
-    // Configure the port direction (input/output).
-    set_tris_a (0xc3);
-    set_tris_b (0x44);
-    set_tris_c (0x82);
-
-    // Display a startup message during boot.
-    fprintf (PC_HOST, "System booted.\n\r");
-}
-
-/**
- *   Log the current GPS position.
- */
-void sysLogGPSData()
-{
-    // Log the data.
-    logType (LOG_COORD);
-    logUint8 (gpsPosition.hours);
-    logUint8 (gpsPosition.minutes);
-    logUint8 (gpsPosition.seconds);
-    logInt32 (gpsPosition.latitude);
-    logInt32 (gpsPosition.longitude);
-    logInt32 (gpsPosition.altitudeCM);
-
-    logUint16 (gpsPosition.vSpeed);
-    logUint16 (gpsPosition.hSpeed);
-    logUint16 (gpsPosition.heading);
-
-    logUint16 (gpsPosition.status);
-
-    logUint8 ((uint8_t) (gpsPosition.dop & 0xff));
-    logUint8 ((uint8_t) ((gpsPosition.visibleSats << 4) | gpsPosition.trackedSats));
-}
-
-/**
- *   Log the ADC values of the bus and reference voltage values.
- */
-void sysLogVoltage()
-{
-    logType (LOG_VOLTAGE);
-    logUint16 (adcRawBusVolt());
-    logUint16 (adcRawRefVolt());
-}
-
 /** @} */
 
 /**
@@ -2166,11 +788,10 @@ void timeInit()
 {
     timeTicks = 0;
     timeInterruptCount = 0;
-    time100mS = 0;
+//    time100mS = 0;
     timeSeconds = 0;
     timeMinutes = 0;
     timeHours = 0;
-    timeDutyCycle = TIME_DUTYCYCLE_70;
     timeCompare = TIME_RATE;
     timeUpdateFlag = false;
     timeNCO = 0x00;
@@ -2178,12 +799,6 @@ void timeInit()
     timeNCOFreq = 0x2000;
     tncDataMode = TNC_MODE_STANDBY;  
     timeRunFlag = false;
-    
-    // Configure CCP1 to interrupt at 1mS for PSK31 or 833uS for 1200 baud APRS
-    CCP_1 = TIME_RATE;
-    set_timer1(timeCompare);
-    setup_ccp1( CCP_COMPARE_INT );
-    setup_timer_1( T1_INTERNAL | T1_DIV_BY_4 );
 }
 
 /**
@@ -2202,16 +817,6 @@ bool_t timeIsUpdate()
     return false;
 }
 
-/**
- *   Set the blink duty cycle of the heartbeat LED.  The LED blinks at a 1Hz rate.
- *
- *   @param dutyCycle TIME_DUTYCYCLE_xx constant
- */
-void timeSetDutyCycle (uint8_t dutyCycle)
-{
-    timeDutyCycle = dutyCycle;
-}
-
 /**
  *   Set a flag to indicate the flight time should run.  This flag is typically set when the payload
  *   lifts off.
@@ -2221,7 +826,6 @@ void timeSetRunFlag()
     timeRunFlag = true;
 }
 
-#INT_CCP1
 /**
  *   Timer interrupt handler called every 104uS (9600 times/second).
  */
@@ -2229,7 +833,7 @@ void timeUpdate()
 {
     // Setup the next interrupt for the operational mode.
     timeCompare += TIME_RATE;
-    CCP_1 = timeCompare;
+//    CCP_1 = timeCompare;
 
     switch (tncDataMode) 
     {
@@ -2252,46 +856,6 @@ void timeUpdate()
             tnc9600TimerTick();
             break;
     } // END switch
-
-    // Read the GPS serial port and save any incoming characters.
-    serialUpdate();
-
-    // Count the number of milliseconds required for the tenth second counter.
-    if (++timeInterruptCount == 960) 
-    {
-        timeInterruptCount = 0;
-
-        // This timer just ticks every 100mS and is used for general timing.
-        ++timeTicks;
-
-        // Roll the counter over every second.
-        if (++time100mS == 10) 
-        {
-            time100mS = 0;
-
-            // We set this flag true every second.
-            timeUpdateFlag = true;
-
-            // Maintain a Real Time Clock.
-            if (timeRunFlag)
-                if (++timeSeconds == 60) 
-                {
-                    timeSeconds = 0;
-    
-                    if (++timeMinutes == 60) 
-                    {
-                        timeMinutes = 0;
-                        ++timeHours;
-                    } // END if timeMinutes
-                } // END if timeSeconds
-        } // END if time100mS
-
-        // Flash the status LED at timeDutyCycle % per second.  We use the duty cycle for mode feedback.
-        if (time100mS >= timeDutyCycle)
-            output_low (IO_LED);
-        else
-            output_high (IO_LED);
-    } // END if
 }
 
 /** @} */
@@ -2311,7 +875,7 @@ void timeUpdate()
 #define TNC_BUFFER_SIZE 80
 
 /// States that define the current mode of the 1200 bps (A-FSK) state machine.
-enum TNC_TX_1200BPS_STATE 
+typedef enum
 {
     /// Stand by state ready to accept new message.
     TNC_TX_READY,
@@ -2327,10 +891,10 @@ enum TNC_TX_1200BPS_STATE
 
     /// Transmit the end flag sequence.
     TNC_TX_END
-};
+} TNC_TX_1200BPS_STATE;
 
 /// Enumeration of the messages we can transmit. 
-enum TNC_MESSAGE_TYPE 
+typedef enum
 {
     /// Startup message that contains software version information.
     TNC_BOOT_MESSAGE,
@@ -2343,13 +907,13 @@ enum TNC_MESSAGE_TYPE
 
     /// Message that contains GPS NMEA-0183 $GPRMC message.
     TNC_RMC
-};
+}  TNC_MESSAGE_TYPE;
 
 /// AX.25 compliant packet header that contains destination, station call sign, and path.
 /// 0x76 for SSID-11, 0x78 for SSID-12
 uint8_t TNC_AX25_HEADER[30] = { 
     'A' << 1, 'P' << 1, 'R' << 1, 'S' << 1, ' ' << 1, ' ' << 1, 0x60, \
-    'K' << 1, 'D' << 1, '7' << 1, 'L' << 1, 'M' << 1, 'O' << 1, 0x76, \
+    'K' << 1, 'D' << 1, '7' << 1, 'S' << 1, 'Q' << 1, 'G' << 1, 0x76, \
     'G' << 1, 'A' << 1, 'T' << 1, 'E' << 1, ' ' << 1, ' ' << 1, 0x60, \
     'W' << 1, 'I' << 1, 'D' << 1, 'E' << 1, '3' << 1, ' ' << 1, 0x67, \
     0x03, 0xf0 };
@@ -2436,6 +1000,8 @@ void tncSetMode(TNC_DATA_MODE dataMode)
             // FSK tones at 445.947 and 445.953 MHz
             ddsSetFSKFreq (955382980, 955453621);
             break;
+       case TNC_MODE_STANDBY:
+           break;
     } // END switch
 
     tncDataMode = dataMode; 
@@ -2494,11 +1060,12 @@ void tnc1200TimerTick()
         case TNC_TX_SYNC:
             // The variable tncShift contains the lastest data byte.
             // NRZI enocde the data stream.
-            if ((tncShift & 0x01) == 0x00)
+            if ((tncShift & 0x01) == 0x00) {
                 if (tncTxBit == 0)
                     tncTxBit = 1;
                 else
                     tncTxBit = 0;
+           }
                     
             // When the flag is done, determine if we need to send more or data.
             if (++tncBitCount == 8) 
@@ -2534,11 +1101,12 @@ void tnc1200TimerTick()
 
             // The variable tncShift contains the lastest data byte.
             // NRZI enocde the data stream.
-            if ((tncShift & 0x01) == 0x00)
+            if ((tncShift & 0x01) == 0x00) {
                 if (tncTxBit == 0)
                     tncTxBit = 1;
                 else
                     tncTxBit = 0;
+           }
 
             // Save the data stream so we can determine if bit stuffing is 
             // required on the next bit time.
@@ -2578,11 +1146,12 @@ void tnc1200TimerTick()
 
             // The variable tncShift contains the lastest data byte.
             // NRZI enocde the data stream.
-            if ((tncShift & 0x01) == 0x00)
+            if ((tncShift & 0x01) == 0x00) {
                 if (tncTxBit == 0)
                     tncTxBit = 1;
                 else
                     tncTxBit = 0;
+           }
 
             // Save the data stream so we can determine if bit stuffing is 
             // required on the next bit time.
@@ -2610,11 +1179,12 @@ void tnc1200TimerTick()
         case TNC_TX_END:
             // The variable tncShift contains the lastest data byte.
             // NRZI enocde the data stream. 
-            if ((tncShift & 0x01) == 0x00)
+            if ((tncShift & 0x01) == 0x00) {
                 if (tncTxBit == 0)
                     tncTxBit = 1;
                 else
                     tncTxBit = 0;
+           }
 
             // If all the bits were shifted, get the next one.
             if (++tncBitCount == 8) 
@@ -2631,8 +1201,8 @@ void tnc1200TimerTick()
                     tncDataMode = TNC_MODE_STANDBY;
 
                     // Key off the DDS.
-                    output_low (IO_OSK);
-                    output_low (IO_PTT);
+//                    output_low (IO_OSK);
+//                    output_low (IO_PTT);
                     ddsSetMode (DDS_MODE_POWERDOWN);
 
                     return;
@@ -2665,6 +1235,19 @@ void tncTxByte (uint8_t character)
     ++tncLength;
 }
 
+static void
+tncPrintf(char *fmt, ...)
+{
+    va_list    ap;
+    int                c;
+
+    va_start(ap, fmt);
+    c = vsprintf((char *) tncBufferPnt, fmt, ap);
+    va_end(ap);
+    tncBufferPnt += c;
+    tncLength += c;
+}
+
 /**
  *   Generate the GPS NMEA standard UTC time stamp.  Data is written through the tncTxByte
  *   callback function.
@@ -2672,7 +1255,7 @@ void tncTxByte (uint8_t character)
 void tncNMEATime()
 {
     // UTC of position fix.
-    printf (tncTxByte, "%02d%02d%02d,", gpsPosition.hours, gpsPosition.minutes, gpsPosition.seconds);
+    tncPrintf ("%02d%02d%02d,", gpsPosition.hours, gpsPosition.minutes, gpsPosition.seconds);
 }
 
 /**
@@ -2697,7 +1280,7 @@ void tncNMEAFix()
     }
 
     coordMin = (coord % 3600000) / 6;
-    printf (tncTxByte, "%02ld%02ld.%04ld,%c,", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 10000), (uint32_t) (coordMin % 10000), dirChar);
+    tncPrintf ("%02ld%02ld.%04ld,%c,", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 10000), (uint32_t) (coordMin % 10000), dirChar);
 
 
     // Longitude value.
@@ -2711,8 +1294,8 @@ void tncNMEAFix()
     }
 
     coordMin = (coord % 3600000) / 6;
-    printf (tncTxByte, "%03ld%02ld.%04ld,%c,", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 10000), (uint32_t) (coordMin % 10000), dirChar);
-
+    tncPrintf ("%03ld%02ld.%04ld,%c,", (uint32_t) (coord / 3600000), (uint32_t) (coordMin / 10000), (uint32_t) (coordMin % 10000), dirChar);
+    
 }
 
 /**
@@ -2722,7 +1305,7 @@ void tncNMEAFix()
 void tncGPGGAPacket()
 {
     // Generate the GPGGA message.
-    printf (tncTxByte, "$GPGGA,");
+    tncPrintf ("$GPGGA,");
 
     // Standard NMEA time.
     tncNMEATime();
@@ -2732,21 +1315,21 @@ void tncGPGGAPacket()
 
     // GPS status where 0: not available, 1: available
     if (gpsGetFixType() != GPS_NO_FIX)
-        printf (tncTxByte, "1,");
+        tncPrintf ("1,");
     else
-        printf (tncTxByte, "0,");
+        tncPrintf ("0,");
 
     // Number of visible birds.
-    printf (tncTxByte, "%02d,", gpsPosition.trackedSats);
+    tncPrintf ("%02d,", gpsPosition.trackedSats);
 
     // DOP
-    printf (tncTxByte, "%ld.%01ld,", gpsPosition.dop / 10, gpsPosition.dop % 10);
+    tncPrintf ("%ld.%01ld,", gpsPosition.dop / 10, gpsPosition.dop % 10);
 
     // Altitude in meters.
-    printf (tncTxByte, "%ld.%02ld,M,,M,,", (int32_t) (gpsPosition.altitudeCM / 100l), (int32_t) (gpsPosition.altitudeCM % 100));
+    tncPrintf ("%ld.%02ld,M,,M,,", (int32_t) (gpsPosition.altitudeCM / 100l), (int32_t) (gpsPosition.altitudeCM % 100));
 
     // Checksum, we add 1 to skip over the $ character.
-    printf (tncTxByte, "*%02X", gpsNMEAChecksum(tncBuffer + 1, tncLength - 1));
+    tncPrintf ("*%02X", gpsNMEAChecksum(tncBuffer + 1, tncLength - 1));
 }
 
 /**
@@ -2758,29 +1341,29 @@ void tncGPRMCPacket()
     uint32_t temp;
 
     // Generate the GPRMC message.
-    printf (tncTxByte, "$GPRMC,");
+    tncPrintf ("$GPRMC,");
 
     // Standard NMEA time.
     tncNMEATime();
 
     // GPS status.
     if (gpsGetFixType() != GPS_NO_FIX)
-        printf (tncTxByte, "A,");
+        tncPrintf ("A,");
     else
-        printf (tncTxByte, "V,");
+        tncPrintf ("V,");
 
     // Standard NMEA-0183 latitude/longitude.
     tncNMEAFix();
 
     // Speed knots and heading.
     temp = (int32_t) gpsPosition.hSpeed * 75000 / 385826;
-    printf (tncTxByte, "%ld.%ld,%ld.%ld,", (int16_t) (temp / 10), (int16_t) (temp % 10), gpsPosition.heading / 10, gpsPosition.heading % 10);
+    tncPrintf ("%ld.%ld,%ld.%ld,", (int16_t) (temp / 10), (int16_t) (temp % 10), gpsPosition.heading / 10, gpsPosition.heading % 10);
 
     // Date
-    printf (tncTxByte, "%02d%02d%02ld,,", gpsPosition.day, gpsPosition.month, gpsPosition.year % 100);
+    tncPrintf ("%02d%02d%02ld,,", gpsPosition.day, gpsPosition.month, gpsPosition.year % 100);
 
     // Checksum, skip over the $ character.
-    printf (tncTxByte, "*%02X", gpsNMEAChecksum(tncBuffer + 1, tncLength - 1));
+    tncPrintf ("*%02X", gpsNMEAChecksum(tncBuffer + 1, tncLength - 1));
 }
 
 /**
@@ -2789,52 +1372,52 @@ void tncGPRMCPacket()
  */
 void tncStatusPacket(int16_t temperature)
 {
-    uint16_t voltage;
+//    uint16_t voltage;
 
     // Plain text telemetry.
-    printf (tncTxByte, ">ANSR ");
+    tncPrintf (">ANSR ");
     
     // Display the flight time.
-    printf (tncTxByte, "%02U:%02U:%02U ", timeHours, timeMinutes, timeSeconds);
+    tncPrintf ("%02U:%02U:%02U ", timeHours, timeMinutes, timeSeconds);
     
     // Altitude in feet.
-    printf (tncTxByte, "%ld' ", gpsPosition.altitudeFeet);
+    tncPrintf ("%ld' ", gpsPosition.altitudeFeet);
     
     // Peak altitude in feet.
-    printf (tncTxByte, "%ld'pk ", gpsGetPeakAltitude());
+    tncPrintf ("%ld'pk ", gpsGetPeakAltitude());
     
     // GPS hdop or pdop
-    printf (tncTxByte, "%lu.%lu", gpsPosition.dop / 10, gpsPosition.dop % 10);
+    tncPrintf ("%lu.%lu", gpsPosition.dop / 10, gpsPosition.dop % 10);
 
     // The text 'pdop' for a 3D fix, 'hdop' for a 2D fix, and 'dop' for no fix.
     switch (gpsGetFixType()) 
     {
         case GPS_NO_FIX:
-            printf (tncTxByte, "dop ");
+            tncPrintf ("dop ");
             break;
 
         case GPS_2D_FIX:
-            printf (tncTxByte, "hdop ");
+            tncPrintf ("hdop ");
             break;
 
 
         case GPS_3D_FIX:
-            printf (tncTxByte, "pdop ");
+            tncPrintf ("pdop ");
             break;
     } // END switch
 
     // Number of satellites in the solution.
-    printf (tncTxByte, "%utrk ", gpsPosition.trackedSats);
+    tncPrintf ("%utrk ", gpsPosition.trackedSats);
     
     // Display main bus voltage.
-    voltage = adcGetMainBusVolt();
-    printf (tncTxByte, "%lu.%02luvdc ", voltage / 100, voltage % 100);
+//    voltage = adcGetMainBusVolt();
+//    tncPrintf ("%lu.%02luvdc ", voltage / 100, voltage % 100);
     
     // Display internal temperature.
-    printf (tncTxByte, "%ld.%01ldF ", temperature / 10, abs(temperature % 10));
+//    tncPrintf ("%ld.%01ldF ", temperature / 10, abs(temperature % 10));
     
     // Print web address link.
-    printf (tncTxByte, "www.kd7lmo.net");
+    tncPrintf ("www.altusmetrum.org");
 }  
 
 /** 
@@ -2845,23 +1428,13 @@ void tncStatusPacket(int16_t temperature)
  */
 void tncTxPacket(TNC_DATA_MODE dataMode)
 {
-    int16_t temperature;
+    int16_t temperature = 20;
     uint16_t crc;
 
     // Only transmit if there is not another message in progress.
     if (tncMode != TNC_TX_READY)
         return;
 
-    // Log the battery and reference voltage before we start the RF chain.
-    sysLogVoltage();
-
-    // We need to read the temperature sensor before we setup the DDS since they share a common clock pin.
-    temperature = lm92GetTemp();
-
-    // Log the system temperature every time we transmit a packet.
-    logType (LOG_TEMPERATURE);
-    logInt16 (temperature);
-
     // Configure the DDS for the desired operational.
     tncSetMode (dataMode);
 
@@ -2875,7 +1448,7 @@ void tncTxPacket(TNC_DATA_MODE dataMode)
     switch (tncPacketType) 
     {
         case TNC_BOOT_MESSAGE:
-            printf (tncTxByte, ">ANSR Pico Beacon - V3.05");
+            tncPrintf (">MegaMetrum v1.0 Beacon");
 
             // Select the next packet we will generate.
             tncPacketType = TNC_STATUS;
@@ -2904,7 +1477,7 @@ void tncTxPacket(TNC_DATA_MODE dataMode)
     }
 
     // Add the end of message character.
-    printf (tncTxByte, "\015");
+    tncPrintf ("\015");
 
     // Calculate the CRC for the header and message.
     crc = sysCRC16(TNC_AX25_HEADER, sizeof(TNC_AX25_HEADER), 0xffff);
@@ -2925,178 +1498,18 @@ void tncTxPacket(TNC_DATA_MODE dataMode)
     tncMode = TNC_TX_SYNC;
 
     // Turn on the PA chain.
-    output_high (IO_PTT);
+//    output_high (IO_PTT);
 
     // Wait for the PA chain to power up.
-    delay_ms (10);
+//    delay_ms (10);
 
     // Key the DDS.
-    output_high (IO_OSK);
+//    output_high (IO_OSK);
 
     // Log the battery and reference voltage just after we key the transmitter.
-    sysLogVoltage();
+//    sysLogVoltage();
+    while (tncMode != TNC_TX_READY)
+       timeUpdate();
 }
 
 /** @} */
-
-uint32_t counter;
-
-uint8_t bitIndex;
-uint8_t streamIndex;
-uint8_t value;
-
-uint8_t bitStream[] = { 0x10, 0x20, 0x30 };
-
-void init()
-{
-    counter = 0;
-    bitIndex = 0;
-    streamIndex = 0;
-    value = bitStream[0];
-}
-
-void test()
-{
-    counter += 0x10622d;
-
-    CCP_1 = (uint16_t) ((counter >> 16) & 0xffff);
-
-    if ((value & 0x80) == 0x80)
-        setup_ccp1 (CCP_COMPARE_SET_ON_MATCH);
-    else
-        setup_ccp1 (CCP_COMPARE_CLR_ON_MATCH);
-
-    if (++bitIndex == 8)
-    {
-        bitIndex = 0;
-        
-        if (++streamIndex == sizeof(bitStream))
-        {
-            streamIndex = 0;
-        }
-
-        value = bitStream[streamIndex];
-    } else
-        value = value << 1;
-}
-
-// This is where we go after reset.
-void main()
-{
-    uint8_t i, utcSeconds, lockLostCounter;
-
-test();
-
-    // Configure the basic systems.
-    sysInit();
-
-    // Wait for the power converter chains to stabilize.
-    delay_ms (100);
-
-    // Setup the subsystems.
-    adcInit();
-    flashInit();
-    gpsInit();
-    logInit();
-    timeInit();
-    serialInit();
-    tncInit();
-
-    // Program the DDS.
-    ddsInit();
-
-    // Turn off the LED after everything is configured.
-    output_low (IO_LED);
-
-    // Check for the diagnostics plug, otherwise we'll continue to boot.
-    diagPort();
-
-    // Setup our interrupts.
-    enable_interrupts(GLOBAL);
-    enable_interrupts(INT_CCP1);
-
-    // Turn on the GPS engine.
-    gpsPowerOn();
-
-    // Allow the GPS engine to boot.
-    delay_ms (250);
-
-    // Initialize the GPS engine.
-    while (!gpsSetup());
-
-    // Charge the ADC filters.
-    for (i = 0; i < 32; ++i)
-        adcUpdate();
-
-    // Log startup event.
-    logType (LOG_BOOTED);
-    logUint8 (gpsPosition.month);
-    logUint8 (gpsPosition.day);
-    logUint8 (gpsPosition.year & 0xff);
-
-    logUint8 (gpsPosition.hours);
-    logUint8 (gpsPosition.minutes);
-    logUint8 (gpsPosition.seconds);
-
-    // Transmit software version packet on start up.
-    tncTxPacket(TNC_MODE_1200_AFSK);
-
-    // Counters to send packets if the GPS time stamp is not available.
-    lockLostCounter = 5;
-    utcSeconds = 55;
-  
-    // This is the main loop that process GPS data and waits for the once per second timer tick.
-    for (;;) 
-    {
-        // Read the GPS engine serial port FIFO and process the GPS data.
-        gpsUpdate();
-
-        if (gpsIsReady()) 
-        {
-            // Start the flight timer when we get a valid 3D fix.
-            if (gpsGetFixType() == GPS_3D_FIX)
-                timeSetRunFlag();
-
-            // Generate our packets based on the GPS time.
-            if (tncIsTimeSlot(gpsPosition.seconds))
-                 tncTxPacket(TNC_MODE_1200_AFSK);
-
-            // Sync the internal clock to GPS UTC time.
-            utcSeconds = gpsPosition.seconds;
-
-            // This counter is reset every time we receive the GPS message.
-            lockLostCounter = 0;
-
-            // Log the data to flash.
-            sysLogGPSData();            
-        } // END if gpsIsReady   
-
-        // Processing that occurs once a second.
-        if (timeIsUpdate()) 
-        {
-            // We maintain the UTC time in seconds if we shut off the GPS engine or it fails.
-            if (++utcSeconds == 60)
-                utcSeconds = 0;
-
-            // If we loose information for more than 5 seconds, 
-            // we will determine when to send a packet based on internal time.
-            if (lockLostCounter == 5) 
-            {
-                if (tncIsTimeSlot(utcSeconds))
-                    tncTxPacket(TNC_MODE_1200_AFSK);
-            } else
-                ++lockLostCounter;
-
-            // Update the ADC filters.
-            adcUpdate();
-
-            if (timeHours == 5 && timeMinutes == 0 && timeSeconds == 0)
-                gpsPowerOff();
-
-        } // END if timeIsUpdate
-
-    } // END for
-}
-
-
-