Programming of the DDS-60 (AD9851) frequency synthesizer from AmQRP http://midnightdesignsolutions.com/dds60/index.html I had to use long, floating math in order to get accurate frequency output.

Dependencies:   TextLCD mbed ChaNFS

main.cpp

Committer:
loopsva
Date:
2012-04-04
Revision:
0:1ed24aaf786d

File content as of revision 0:1ed24aaf786d:

/*
Rev Date        Changes:
------------------------------------------------------------------------------------------------------------------------------------------
100 5/06/11     - putting things together, first cut
101 5/10/11     - removed G command from menu
                - added AD9851 on/off to summary
102 5/11/11     - added file dds60.ini, initializes file if missing 
                - reads dds60.ini at boot up to get frequency values
                - added ability to store current values in dds60.ini into local memory using new W command
103 5/12/11     - tried a new fix for signal quality problem. wouldn't start above 30MHz, went back to 102 version
                - most commands now use a single keystroke vs waiting for a CR
104 5/17/11     - removed i/o delays in ad9851.cpp. results in a 40 bit download to ad9851 in 10.4uS - was 1.24mS
105 6/08/11     - added "listdir" function

------------------------------------------------------------------------------------------------------------------------------------------
Known issues:
                - Signal quality is bad between 200KHz and 30MHz
102               Patch fix in AD9851.cpp, routine void AD9851::FirstAccess()
105             - "listdir" function works, but "listdirSD" function doesn't

------------------------------------------------------------------------------------------------------------------------------------------
*/

int revision = 105;                     // revision of this code
#include "mbed.h"
#include "SDHCFileSystem.h"
#include "adc.h"
#include "FATFileSystem.h"
//#include "MSCFileSystem.h"
#include "TextLCD.h" 
#include "AD9851.h"
//#include "MODSERIAL.h"
//#define TX_PIN p13 //p9 p13 or p28
//#define RX_PIN p14 //p10 p14 or p27
#define SAMPLE_RATE    150000       //for A:D converter

#define CLS "\033[2J"
extern "C" void mbed_reset();
extern "C" void mbed_mac_address(char *);
#define DEFAULTHOSTNAME "mbed-c3p1"
char *hostname = DEFAULTHOSTNAME;

LocalFileSystem local("local");

PwmOut led1(LED1, "led1");
DigitalOut led2(LED2, "led2");
DigitalOut led3(LED3, "led3");
DigitalOut led4(LED4, "led4");
I2C i2c(p9, p10);                       // sda, scl
TextLCD lcdt(p24, /*p25, */p26, p27, p28, p29, p30, TextLCD::LCD16x2); // rs, rw, e, d0, d1, d2, d3
DigitalOut LCDrw(p25, "LCDrw");         // new LCD code no longer requries R/W pin - tie low (J5 on Orange Board"
Serial/*MODSERIAL*/  pc(USBTX, USBRX);                // Serial USB communications over mbed USB port
//MODSERIAL uart(TX_PIN, RX_PIN);
SDFileSystem sd(p5, p6, p7, p8, "sd");  // mosi, miso, sclk, cs
AD9851 dds60(p16, p17, p15);          //clk, sdo, len



// Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1
int gDebug = 1;                         // display debog level (0 - 3)
int OldgDebug = gDebug;                 // copy of gDebug for updating kb-mbed.ini
int DST = 0;                            // Daylight Saving Time (or as defined in kb-mbed.ini)
int OldDST = DST;                       // Copy of DST for updating kb-mbed.ini
int TZone = -8;                         // Time Zone from UTC (or as defined in kb-mbed.ini)
int OldTZone = TZone;                   // copy for updating kb-mbed.ini
int NTPUpdateValue = 86400;             // update RTC every 24 hours (or as defined in kb-mbed.ini)
int bootDHCP = 1;                       // boot DHCP(1) of fixed IP(0) (or as defined in kb-mbed.ini)
float Press0Ft = 102.4;                 // altimeter - assumed pressure at sea level
float Saved0Ft = Press0Ft;              // saved for later comparison if changed by HTTP
float OldPress0Ft = Press0Ft;           // another copy for updating kb-mbed.ini
char mac[6];                            // mbed MAC address

float Led1Pwm = 0.01;                   // LED1 brightness
bool Led1Up = true;                     // LED1 auto up-down

ADC adc(SAMPLE_RATE, 1);
bool use_sd = false;                    // flag for using SDHC file system
bool ZeroMinFlag = false;               // alignment to 00:00:00 flag
float gWait = 0.005;                    // Main loop wait timeout
float const DISP_SLOW(2.0);             // Long wait for LCD display
float const DISP_FAST(0.5);             // Faster wait for LCD
int i2cQty = 16;                        // number of bytes to get
char i2cData[130];                      // i2c read buffer data

double LclBaseFreq = 1000000.0;         // base frequency - if frequency
double LclIfFreq = 262000.0;            // IF frequency
double StepFreq = 1000.0;               // increment/decrement step frequency
double OldStepFreq = StepFreq;          // old copy of increment/decrement step frequency

int pcRxQty = 0;                        // MODSER RX data counter/pointer
char pcRxData[20];                      // MODSER RX data buffer
char inchar = 0;                        // RX input character
const char BS = 0x08;                   // ascii backspace
const char CR = 0x0d;                   // ascii CR
const char LF = 0x0a;                   // ascii LF
const char SP = 0x20;                   // ascii space
const char ESC = 0x1b;                  // ascii escape
const char DP = 0x2e;                   // ascii decimal point / period
const char ticC = 0x0c;                 // ascii control C
bool pcRxLine = false;                  // CR or LF detected in RX buffer
bool pcRxEOB = false;                   // RX buffer EOB (full)
bool pcRxIsNumb = false;                // whether or not string is a valid number (including dp)
bool ErFlag = false;                    // error flag
bool FirstAccess = false;               // very first DDS60 access
double pcRxNumb = 0.0;                  // RX buffer comversion
char Fcmd = 0;                          // post RX processing command decoder
unsigned int SerialNum[5] = {58,0,0,0,0}; // mbed serial number data

int Tic = 0;                            // Tic counter to update LCD sequence
int Sequence = 0;                       // LCD step through sequence counter



/*----------*/
void disp_i2c() {
    lcdt.cls();
    lcdt.locate(0,0);         //column(0-15), row(0-1)
    lcdt.printf("I2CU! Searching\n");
    lcdt.locate(0,1);         //column(0-15), row(0-1)
    lcdt.printf("for I2C devices");
//    pc.printf("\n\n");
    pc.printf("I2CU! Searching for I2C devices...\n");
    wait(DISP_FAST);

    int count = 0;
    for (int address=2; address<256; address+=2) {
        if (!i2c.write(address, NULL, 0)) { // 0 returned is ok
/* A one time write to all detected EEPROM chips for later identification */
/*            i2cData[0] = 0;         // pointer register (hi)
            i2cData[1] = 0;         // pointer register (lo)
            i2cData[2] = count+1;   // detected i2c device (in sequence 1-128)
            i2cData[3] = address;   // device's i2c address
            i2cData[4] = count;     // device number (0-3)
            int i = 5;
            for (i=5; i<(5+5*8); i+=5) {
                i2cData[i] = 0;         // next available write address (highest Hamming nibble) init to 0x0080
                i2cData[i+1] = 0;       // next available write address, Hamming nibble 2 of 4
                i2cData[i+2] = 0x8b;    // next available write address, Hamming nibble 3 of 4
                i2cData[i+3] = 0;       // next available write address, Hamming nibble 4 of 4
                i2cData[i+4] = 0;       // clear out address pointer flags byte (0x07 = 1 or more of the 4 bytes above is wore out)
            }
            for (i=i+5; i<130; i+=1) {  //clear out remainder of buffer area
                i2cData[i] = 255;
            }
*/
            
/****** The following line inititalizes the EEPROMs to the structure above ******/
//            (!i2c.write(address, i2cData, 132));  // store device address at location 0
            
            wait(0.005);
            pc.printf("-I2C device found at address 0x%02X\n", address);
            for (int clrb=0; clrb<i2cQty; clrb+=1) {  //clear out i2c buffer before reading in data
                i2cData[clrb] = 0;
            }
            // If device is a 24fc1025, then set the pointer register
            if (address>0x9F && address<0xB0) {     // do only if accessing EEPROM
                i2cData[0] = 0;                     // point to location 0 in EEPROM
                i2cData[1] = 0;
                (!i2c.write(address, i2cData, 2));  // set location 0 in EEPROM
            }
            // If device is a temperature sensor (adt7410, then reset device and set 16 bit mode
/*            if (address>0x8F && address<0x91) {     // do only if accessing Temp sensor
                pc.printf("-Initializing ADT7410...\n");
                ADT7410Up = true;                   // set "installed" flag
//                i2cData[0] = 0x2f;                  // point to location 0x2f (reset reg) in Temp
//                (!i2c.write(address, i2cData, 1));  // reset temperature device

                fever.reset();
                wait_ms(1);
//                fever.setConfig(char 0x82);
//                i2cData[0] = 0x03;                  // point to location 0x03 (config reg) in Temp
//                i2cData[1] = 0x82;                  // 16 bit mode, 3 faults
//                (!i2c.write(address, i2cData, 2));  // set config register
//                wait_ms(1);
                i2cData[0] = 0x0b;                  // point to location 0x0b (id register)
                (!i2c.write(address, i2cData, 1));  // set pointer for before read
                i2cData[0] = 0x00;                  // point to location 0
//                (!i2c.write(address, i2cData, 1));  // set pointer for before read
                (!i2c.read(address, i2cData, 1));   // get ID
                TempId = i2cData[0];                // save ID
                pc.printf(" id: %02x\n", TempId);

            }
            // If device is a MPL115A2, then set the pointer register
            if (address>0xBF && address<0xC2) {     // do only if accessing MPL115
                MPL115aUp = true;                   // set "installed" flag
                i2cData[0] = 0x12;                  // start a temp / baro conversion
                i2cData[1] = 0x01;
                (!i2c.write(address, i2cData, 2));  // set location 0x12 in MPL115
                pc.printf("-Initializing MPL115A2...\n");
                wait_ms(6);                         // need 6mS for conversions
                i2cData[0] = 0;                     // point to location 0 in MPL115
                i2cData[1] = 0;
                (!i2c.write(address, i2cData, 1));  // set location 0 in MPL115
            }
            // Read and display first 16 bytes of 'found' device
            (!i2c.read(address, i2cData, i2cQty));  // get first few bytes from device
            if (address>0xBF && address<0xC2) {     // do only if accessing MPL115
                baro.initBaroCoef();    //initializes coeficents - only do once after reset
                baro.getBaroKPa();     //first real pressure access
//                baro.getBaroRegs();     //displays all coef registers
//                baro.getBaroCoef();     //displays all of the coeficent values
            }
            */
            pc.printf(" ");
            for (int ptr=0; ptr<i2cQty/2; ptr+=1) {  // print them out
                pc.printf("%02x ",i2cData[ptr]);
            }
            pc.printf("  ");
            for (int ptr=i2cQty/2; ptr<i2cQty; ptr+=1) {  // print them out
                pc.printf("%02x ",i2cData[ptr]);
            }
            pc.printf("   ");
            for (int ptr=0; ptr<i2cQty; ptr+=1) {  // print them out
                if (i2cData[ptr]>32 && i2cData[ptr]<127) {   // do ascii if legal character
                    pc.printf("%c",i2cData[ptr]);
                }
                else {
                    pc.printf(".");
                }
            }
            pc.printf("\n");
            count++;
/*            if (address>0x8F && address<0x91) {     // do only if accessing Temp sensor
                printf("ADT7410 config: 0x%x\n", fever.getConfig());
//                TempC = fever.getTemp();
//                TempF = TempC * 9.0 / 5.0 + 32.0;
//                printf("Temperature %.3fC   %.3fF\n", TempC, TempF);
            }
            */
        }
    }
    if (count == 0) pc.printf("    ");
    pc.printf("I2CU! %d devices found\n", count);
    lcdt.cls();
    lcdt.locate(0,0);         //column(0-15), row(0-1)
    lcdt.printf("I2CU! found...\n");
    lcdt.locate(0,1);         //column(0-15), row(0-1)
    lcdt.printf("%d devices\n", count);
} 

/* save values in file sensors.csv for later retreval */
/*
void storeValues() {
    time_t cstTime;                                             //need our own time stamp
    cstTime = time(NULL);                                       //get time stamp
    cstTime = cstTime + ((TZone + DST) * 3600);                 //set to local date
    strftime(timebuf_d, 32, "%m/%d/%y,", localtime(&cstTime));  //format date
    strftime(timebuf, 32, "%H:%M:%S,", localtime(&cstTime));    //format time
            
    if(use_sd == false) {                                       //use local or sd file system?
        if(ZeroMinFlag == true) {                               //only do once an hour if local 
            if (gDebug > 1) pc.printf("   Looking for /local/sensors.csv\n");
            FILE *fp = fopen("/local/sensors.csv", "r");
            if (fp == NULL) {
                pc.printf("\n***Creating /local/sensors.csv\n");
                FILE *fp = fopen("/local/sensors.csv", "w");
                if (fp == NULL) {
                    pc.printf("***cannot create /local/sensors.csv !!!\n");
                    return;                                         //exit with create error
                } else {
                    fprintf(fp, "date,time,inHg,kPa,deg F,deg C, alt F,kPa @ 0\n");
                    fclose(fp);
                }
            } else {
                fclose(fp);                                         //close as a read or create file
                if (gDebug > 1) pc.printf("Saving data in /local/sensors.csv ...");
                FILE *fp = fopen("/local/sensors.csv", "a");        //re-open as an append file
                fputs(timebuf_d, fp);                               //save date
                fputs(timebuf, fp);                                 //dave time
                fprintf(fp, "%2.2f,%3.1f,%3.2f,%2.2f,%5.0f,%3.1f\n", 
                    RollAvgPress * kPa_inHg, 
                    RollAvgPress, 
                    RollAvgTemp * 9.0 / 5.0 + 32.0, 
                    RollAvgTemp, 
                    RollAltitude / 0.3048, 
                    Press0Ft); 
                fclose(fp);
                if (gDebug > 1) pc.printf(" done\n");
            }
        }
    } else {                                                    // SDHC available to use
        if (gDebug > 1) pc.printf("   Looking for /sd/sensors.csv\n");
        FILE *fp = fopen("/sd/sensors.csv", "r");
        if (fp == NULL) {
            pc.printf("\n***Creating /sd/sensors.csv\n");
            FILE *fp = fopen("/sd/sensors.csv", "w");
            if (fp == NULL) {
                pc.printf("***cannot create /sd/sensors.csv !!!\n");
                return;                                         //exit with create error
            } else {
                fprintf(fp, "date,time,inHg,kPa,deg F,deg C, alt F,kPa @ 0, Zero Hr\n");
                fclose(fp);
            }
        } else {
            fclose(fp);                                         //close as a read or create file
            if (gDebug > 1) pc.printf("Saving data in /sd/sensors.csv ...");
            FILE *fp = fopen("/sd/sensors.csv", "a");           //re-open as an append file
            fputs(timebuf_d, fp);                               //save date only
            fputs(timebuf, fp);                                 //save time only
            fprintf(fp, "%2.2f,%3.1f,%3.2f,%2.2f,%5.0f,%3.1f", 
                RollAvgPress * kPa_inHg, 
                RollAvgPress, 
                RollAvgTemp * 9.0 / 5.0 + 32.0, 
                RollAvgTemp, 
                RollAltitude / 0.3048, 
                Press0Ft); 
                if(ZeroMinFlag == true) {
                    fprintf(fp, ",****\n");
                } else { 
                    fprintf(fp, "\n"); 
                }
            fclose(fp);
            if (gDebug > 1) pc.printf(" done\n");
        }
    }
}
*/
/*----------*/
// print "local" directory
void listdir(void) {
    pc.printf("/local directory:\n");
    DIR *d;
    struct dirent *p;

    d = opendir("/local");
    if (d != NULL) {
        while ((p = readdir(d)) != NULL) {
            printf(" - %s\n", p->d_name);
        }
    } else {
        pc.printf("Could not open -local- directory!\n");
    }
    closedir(d);
}
/*----------*/
// print "sd" directory ***broken!!
/*
void listdirSD(void) {
    pc.printf("/sd directory:\n");
    DIR *d;
    struct dirent *p;

    d = opendir("/sd");
    if (d != NULL) {
        while ((p = readdir(d)) != NULL) {
            printf(" - %s\n", p->d_name);
        }
    } else {
        printf("Could not open -sd- directory!\n");
    }
    closedir(d);
}
*/
/*----------*/
void getMbedSN() {
    unsigned int SerialNum[5] = {58,0,0,0,0};
    typedef void (*CallMe)(unsigned int[],unsigned int[]);
    CallMe CallMe_entry=(CallMe)0x1FFF1FF1;
    CallMe_entry(SerialNum, SerialNum);
    if (!SerialNum[0])
        pc.printf("mbed serial number is: %0.8x %0.8x %0.8x %0.8x\n", 
            SerialNum[1], SerialNum[2], SerialNum[3], SerialNum[4]);
    else
        pc.printf("***Unable to retrieve Serial Number from LPC Flash\n");
}

/* display MAC address */
void getMbedMAC() {
//    uint64_t uid = 0;
////    char mac[6];
    mbed_mac_address(mac);
//    uid = mac[0] << 40 | mac[1] << 32 |
//          mac[2] << 24 | mac[3] << 16 |
//          mac[4] << 8  | mac[5] << 0;   
    pc.printf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);      
}

/* initialize dds60 configuration file if it doesn't already exist */
void InitIniFile() {
    FILE *fp = fopen("/local/dds60.ini", "w");
    if (fp == NULL) {
        pc.printf("***Cannot create dds60.ini file!!!\n");
    } else {
        if(gDebug) pc.printf("***Updating/Creating dds60.ini file...   \n");
        fprintf(fp, "# DDS-60 configuration file\r\n");
        fprintf(fp, "\r\n[Freqs]\r\n");
        fprintf(fp, "BaseFrequency=%f\r\n",LclBaseFreq);
        fprintf(fp, "IFFrequency=%f\r\n", LclIfFreq);
        fprintf(fp, "StepFrequency=%f\r\n", StepFreq);

        fprintf(fp, "\r\n[Global]\r\n");
        fprintf(fp, "Timezone(hrs)=%d\r\n", TZone);
        fprintf(fp, "DstZone(hrs)=%d\r\n", DST);
        fprintf(fp, "NTPRefresh(sec)=%d\r\n", NTPUpdateValue);
        fprintf(fp, "gDebugLevel=%d\r\n", gDebug);
        fprintf(fp, "\r\n##END\r\n");
        fclose(fp);
        if(gDebug) pc.printf("   done\n");
    }
    OldgDebug = gDebug;
    OldDST = DST;
    OldTZone = TZone;
    OldPress0Ft = Press0Ft;
}

// Trim whitespace/CRLFs from both ends of a given string
// for use with routine below
char * str_cleanup(char *in) {
    char * out = in;
    // Trim leading spaces and CR/LF
    while (*out == ' ' || *out == '\t' || *out == '\r' || *out == '\n')
        out ++;
    // Trim trailing spaces and CR/LF
    int len = strlen(out)-1;
    while (out[len] == ' ' || out[len] == '\t' || out[len] == '\r' || out[len] == '\n') {
        out[len] = '\0';
        len--;
    }
    return out;
}

// Simple ini file parser for SNTP configuration (Case-sensitive!)
// This function is intended to be called only before SNTPClientInit().
// Returns: 0 if OK, errno otherwise
enum {
  SECT_NONE,
  SECT_FREQS,
  SECT_GLOBAL,
};

//int _SNTPClrAddresses();

int SNTPReadIniFile(const char* filename) {
    if (gDebug > 1) pc.printf("Before: tz:%d  dst:%d ntpupd:%d baroZ:%.1f name:%s\n", TZone, DST, NTPUpdateValue, Press0Ft, hostname);
    FILE *f;
    char buf[512];
//    bool addresses_cleared = false;
    bool hname = false;
    f = fopen(filename, "r");
    if (!f)
        return -1;    // errno not used?
    char *buf1, *buf2;
    int section=SECT_NONE;
    int line = 0;
    while (fgets(buf, sizeof(buf)/sizeof(buf[0]), f)) {
        line++;
        buf1 = str_cleanup(buf);
        if (*buf1 == '#' || *buf1 == '\0')
            continue;    // Comment line or empty line - skip
        if (*buf1 == '[') {
            // New section
            if (0 == strncmp(buf1,"[Freqs]", sizeof("[Freqs]")-1)) {
                section=SECT_FREQS;
/*                if (!addresses_cleared) {
                    // Clear addresses only once.
                    _SNTPClrAddresses();
                    addresses_cleared = true;
                }
*/            } else if (0 == strncmp(buf1,"[Global]", sizeof("[Global]")-1)) {
                section=SECT_GLOBAL;
            } else {
                section=SECT_NONE;
                fprintf(stderr, "***File \"%s\", line %d - section \"%s\" is not understood.\r\n", filename, line, buf1);
            }
        } else {
            // Section values
            switch (section) {
            case SECT_FREQS:
                buf2 = strchr(buf1, '=');
                if (buf2) {
                    *buf2++ = '\0';     // Now buf1 has variable name, buf2 has value
                    buf2 = str_cleanup(buf2);
                    if (0 == strncmp(buf1, "BaseFrequency", sizeof("BaseFrequency")-1)) {
                        LclBaseFreq = strtof(buf2, &buf2);
                    } else if (0 == strncmp(buf1, "IFFrequency", sizeof("IFFrequency")-1)) {
                        LclIfFreq = strtof(buf2, &buf2);
                    } else if (0 == strncmp(buf1, "StepFreq", sizeof("StepFreq")-1)) {
                        StepFreq = strtod(buf2, &buf2);
                    } else {
                        pc.printf("***File \"%s\", line %d - unrecognized variable \"%s\" in section [Freqs]\r\n", filename, line, buf1);
                    }
                } else {
                    pc.printf("***File \"%s\", line %d - unrecognized statement in section [Freqs]: %s\r\n", filename, line, buf1);
                }
                break;
            case SECT_GLOBAL:
                buf2 = strchr(buf1, '=');
                if (buf2) {
                    *buf2++ = '\0';     // Now buf1 has variable name, buf2 has value
                    buf2 = str_cleanup(buf2);
                    if (0 == strncmp(buf1, "Timezone(hrs)", sizeof("Timezone(hrs)")-1)) {
                        TZone = strtod(buf2, &buf2);
                    } else if (0 == strncmp(buf1, "NTPRefresh(sec)", sizeof("NTPRefresh(sec)")-1)) {
                        NTPUpdateValue = strtod(buf2, &buf2);
                    } else if (0 == strncmp(buf1, "gDebugLevel", sizeof("gDebugLevel")-1)) {
                        gDebug = strtod(buf2, &buf2);
                    } else if (0 == strncmp(buf1, "bootDHCP", sizeof("bootDHCP")-1)) {
                        bootDHCP = strtod(buf2, &buf2);
                    } else if (0 == strncmp(buf1, "MyName", sizeof("MyName")-1)) {
                        if (hname == false) {
                            hname = true;
                            hostname = buf2;
                            if (gDebug > 1) pc.printf("buf2:%s hn:%s\n", buf2, hostname);
                        }
                    } else if (0 == strncmp(buf1, "PressureSeaLevel", sizeof("PressureSeaLevel")-1)) {
                        Press0Ft = strtof(buf2, &buf2);
                    //} else if (0 == strncmp(buf1, "RtcUtc", sizeof("RtcUtc")-1)) {
                     //   gSntpRtcUtc = (bool)strtol(buf2, &buf2, 10);
                    } else if (0 == strncmp(buf1, "DstZone(hrs)", sizeof("DstZone(hrs)")-1)) {
                        DST = strtod(buf2, &buf2);
                    } else {
                        pc.printf("***File \"%s\", line %d - unrecognized variable \"%s\" in section [Global]\r\n", filename, line, buf1);
                    }
                } else {
                    pc.printf("***File \"%s\", line %d - unrecognized statement in section [Global]: %s\r\n", filename, line, buf1);
                }
                break;
            default:
                pc.printf("***File \"%s\", line %d - unrecognized statement / no section: %s\r\n", filename, line, buf1);
            }
        }
    }
    fclose(f);
    pc.printf("DDS60 configuration read from \"%s\", %d lines.\r\n", filename, line);
    pc.printf("- gDebug display level: %d\n", gDebug);
    pc.printf("- Time Zone: %d hours\n", TZone);
    //pc.printf("- Daylight Saving Time - ");
    if (DST == 0) {
        pc.printf("- Standard Time\n");
    } else {
        pc.printf("- Daylight Saving Time\n");
    }
    pc.printf("- NTC update: %d seconds\n", NTPUpdateValue);
    if (bootDHCP == 1) {
        pc.printf("- booting HTTP, host name: %s\n", hostname);
    } else {
        pc.printf("- booting static IP\n");
    }
    
    pc.printf("- Base Frequency: %.3f kPa\n", LclBaseFreq);
    pc.printf("- IF Frequency:   %.3f kPa\n", LclIfFreq);
    pc.printf("- Step Frequency: %.3f kPa\n", StepFreq);
    
//    if (gDebug > 1) pc.printf("After: tz:%d  dst:%d ntpupd:%d baroZ:%.1f name:%s\n", TZone, DST, NTPUpdateValue, Press0Ft, hostname);

    OldgDebug = gDebug;
    OldDST = DST;
    OldTZone = TZone;
    OldPress0Ft = Press0Ft;
    dds60.SetBaseValue(LclBaseFreq);
    dds60.SetIfValue(LclIfFreq);
    dds60.CalcNewValue();
    OldStepFreq = StepFreq;
    return 0;
}

//update LCD based on Sequence count
void UpdLCD() {
    double Fdata = 0.0;
    int UIdata = 0;
    char Cdata = 0;
    if(Sequence == 0) {
        lcdt.cls();
        lcdt.locate(0,0);                       //column(0-15), row(0-1)
        lcdt.printf("DDS-60 %d", revision);
        lcdt.locate(0,1);                       //column(0-15), row(0-1)
        lcdt.printf("K Braun");
    }
    if(Sequence == 1) {
        lcdt.cls();
        lcdt.locate(0,0);                       //column(0-15), row(0-1)
        lcdt.printf("(%d) Base Freq:", Sequence);
        lcdt.locate(0,1);                       //column(0-15), row(0-1)
        Fdata = dds60.GetBaseValue();
        lcdt.printf("   %.3f", Fdata);
    }
    if(Sequence == 2) {
        lcdt.cls();
        lcdt.locate(0,0);                       //column(0-15), row(0-1)
        lcdt.printf("(%d) IF Freq:", Sequence);
        lcdt.locate(0,1);                       //column(0-15), row(0-1)
        Fdata = dds60.GetIfValue();
        lcdt.printf("   %.3f", Fdata);
    }
    if(Sequence == 3) {
        lcdt.cls();
        lcdt.locate(0,0);                       //column(0-15), row(0-1)
        lcdt.printf("(%d) Step Freq:", Sequence);
        lcdt.locate(0,1);                       //column(0-15), row(0-1)
        lcdt.printf("   %.3f", StepFreq);
    }
    if(Sequence == 4) {
        lcdt.cls();
        lcdt.locate(0,0);                       //column(0-15), row(0-1)
        lcdt.printf("(%d) AD9851 data:", Sequence);
        lcdt.locate(0,1);                       //column(0-15), row(0-1)
        UIdata = dds60.GetFD32Value();    
        Cdata = dds60.GetFortyValue();    
        lcdt.printf("   0x%02x%08x\n", Cdata, UIdata);
    }
    if(Sequence == 5) {
        lcdt.cls();
        lcdt.locate(0,0);                       //column(0-15), row(0-1)
        if(ErFlag == false) {
            lcdt.printf("DDS-60 %d", revision);
            lcdt.locate(0,1);                       //column(0-15), row(0-1)
            lcdt.printf("K Braun");
        } else {
            lcdt.printf("(%d) Entry Error", Sequence);
            lcdt.locate(0,1);                       //column(0-15), row(0-1)
            lcdt.printf("   !!!!!!!!");
        }
    }
    if(Sequence > 5) {
        lcdt.cls();
        lcdt.locate(0,0);                       //column(0-15), row(0-1)
        lcdt.printf("(%d) huh??", Sequence);
    }
}

// manu selection menu
void mainMenu() {
    pc.printf("\n**************************************************************************\n");
    pc.printf("                              MAIN MENU\n");
    double Fdata;
    Fdata = dds60.GetBaseValue();    
    pc.printf("AD9851 Summary:\nBase Freq: %.3f\n", Fdata);
    Fdata = dds60.GetIfValue();    
    pc.printf("IF Freq:   %.3f\n", Fdata);
    pc.printf("Step Freq: %.3f\n", StepFreq);
    unsigned int UIdata;
    UIdata = dds60.GetFD32Value();    
    char Cdata;
    Cdata = dds60.GetFortyValue();    
    pc.printf("40 bit wd: 0x%02x%08x\n", Cdata, UIdata);
    char onoff = Cdata & 0x04;
    if(onoff == 0) {
        pc.printf("AD9851 is: -ON-\n\n");
    } else {
        pc.printf("AD9851 is: -OFF-\n\n");
    }
//    pc.printf("----------\n");
    pc.printf(" B - Base Frequency       Y - IF Frequency         S - Step Frequency\n");
    pc.printf(" E - Enable DDS-60        X - Disable DDS-60\n");
    pc.printf(" U - Update DDS-60        W - Write to Flash\n");
    pc.printf(" I - Inc Step Frequency   D - Dec Step Frequency\n");
    pc.printf(" R - Reboot!!!\n\n");
//    pc.printf("\n");
    pc.printf("**************************************************************************\n");
    pc.printf("Selection: ");
}

// This function is called when a character goes from the TX buffer
// to the Uart THR FIFO register.
//void txCallback(MODSERIAL_IRQ_INFO *q) {
//    led2 = !led2;
//}

// This function is called when TX buffer goes empty
//void txEmpty(MODSERIAL_IRQ_INFO *q) {
//    led2 = 0;
//    pc.puts(" testing done...\n");
//    lcdt.locate(0,1);                    //column(0-15), row(0-1)
//    lcdt.printf("              ");       //print -me- on LCD
//    lcdt.locate(0,1);                    //column(0-15), row(0-1)
//    lcdt.printf("done");                //print -me- on LCD
//}

// This function is called when a character goes into the RX buffer.
//void rxCallback(MODSERIAL_IRQ_INFO *q) {
//    led3 = !led3;
//    pc.putc(uart.getc());
//}

// This function is called when a character goes into the RX buffer.
void Rx_interrupt() {
//void rxCallbackpc(MODSERIAL_IRQ_INFO *q) {
    inchar = pc.getc();
//    led4 = !led4;
    if(inchar == BS) { 
        if(!pcRxQty == 0) {
            pcRxData[pcRxQty] = 0;
            pcRxQty = pcRxQty -1;
        }
    }
    else if(inchar == CR) { 
        pcRxLine = true;
    }
    else if(inchar == LF) {
        pcRxLine = true;
    } else {
        if(pcRxQty < sizeof(pcRxData)) {
            pcRxData[pcRxQty] = inchar;
            pcRxQty = pcRxQty++; 
//            pc.putc(inchar);
        } else {
//            pc.printf ("pcRxData is full!!\n");
            pcRxEOB = true;
        }
    }
}

//clear RxData buffer with all 00's
void pcClrLineBuf() {
    pcRxQty = 0;                            // MODSER RX data counter/pointer
    for(int i = 0; i < (sizeof(pcRxData) + 1); i++) {// clear out rx buffer
        pcRxData[i] = 0;
        pcRxLine = false;
        pcRxEOB = false;
        pcRxIsNumb = false;
    }
}
// assemble a test line.  if it is a number, turn it into a double


int loop = 0;        
void higherDecode() {
    double Fdata = 0.0;
//    unsigned int UIdata;
//    char Cdata;
    if(pcRxLine == true) {                                      //data in rx buffer?
        loop = loop++;
        if(gDebug) pc.printf("loop: %d\n", loop);
        if(pcRxQty == 1) {                                      //single alpha char?
            if((pcRxData[0] == 'b') || (pcRxData[0] == 'B')) {             //enter Base frequency
                Fdata = dds60.GetBaseValue();
                pc.printf("\nBASE Frequency: %.3f  New: ", Fdata);
                Fcmd = pcRxData[0] | 0x20;
//                pcClrLineBuf();
            } 
            else if((pcRxData[0] == 'y') || (pcRxData[0] == 'y')) {        //enter IF frequency
                Fdata = dds60.GetIfValue();
                pc.printf("\nIF Frequency: %.3f  New: ", Fdata);
                Fcmd = pcRxData[0] | 0x20;
            }
            else if((pcRxData[0] == 's') || (pcRxData[0] == 'S')) {        //enter step frequency value
                pc.printf("\nStep Frequency: %.3f  New: ", StepFreq);
                Fcmd = pcRxData[0] | 0x20;
            }
            else if((pcRxData[0] == 'r') || (pcRxData[0] == 'R')) {        //enable DDS-60
                pc.printf("\nREBOOTING...\n");
                wait(0.1);
                mbed_reset();
                mainMenu();
            }
            else if(pcRxIsNumb == false) {
                pc.printf("2-huh???\n");
                pcClrLineBuf();
                mainMenu();
            }
        }
    }
    if((pcRxIsNumb == true) && (Fcmd == 'b')) {
//        pc.printf("here-b ?\n");
        dds60.SetBaseValue(pcRxNumb);
//        pcClrLineBuf();
        Fcmd = 0;
        mainMenu();
    }
    else if((pcRxIsNumb == true) && (Fcmd == 'y')) {
//        pc.printf("here-y ?\n");
        dds60.SetIfValue(pcRxNumb);
        pcRxIsNumb = false;
        Fcmd = 0;
        mainMenu();
    }
    else if((pcRxIsNumb == true) && (Fcmd == 's')) {
//        if(gDebug > 1) pc.printf("1-sF: %.3f\n", StepFreq);
        StepFreq = pcRxNumb;
        if(StepFreq >= 0.0) {
//            if(gDebug > 1) pc.printf("2-sF: %.3f\n", StepFreq);
            pcRxIsNumb = false;
        } else {
            StepFreq = OldStepFreq;
            pc.printf("Step neg number!!!\n");
        }
        Fcmd = 0;
        mainMenu();
    }
    else if((pcRxIsNumb == true) && (!((Fcmd == 'b') || (Fcmd == 'y') || (Fcmd == 's')))) {
        Fcmd = 0;
        pcClrLineBuf();
        mainMenu();
    }
    pcClrLineBuf();
}


void pcRx() {
    double Fdata = 0.0;
    if((pcRxData[0] == ESC) || (pcRxData[0] == ticC)) {            //kill? go back to main menu
        wait_us(100);
        pc.printf("\nblam!!!\n");
        pcClrLineBuf();
        pcRxLine = false;
        pcRxEOB = false;
        mainMenu();
    }
    else if((pcRxData[0] == 'e') || (pcRxData[0] == 'E')) {        //enable DDS-60
        pc.printf("\nEnabling AD9851...\n");
        dds60.AD9851Enable();
        pcClrLineBuf();
        pcRxLine = false;
        pcRxEOB = false;
        mainMenu();
    }
    else if((pcRxData[0] == 'x') || (pcRxData[0] == 'X')) {        //disable DDS-60
        pc.printf("\nDisable AD9851...\n");
        dds60.AD9851Disable();
        pcClrLineBuf();
        pcRxLine = false;
        pcRxEOB = false;
        mainMenu();
    }
    else if((pcRxData[0] == 'w') || (pcRxData[0] == 'W')) {        //save values
        pc.printf("\nWriting current values to Flash...\n");
        LclBaseFreq = dds60.GetBaseValue();
        LclIfFreq = dds60.GetIfValue();
        InitIniFile();
        pcClrLineBuf();
        pcRxLine = false;
        pcRxEOB = false;
        mainMenu();
    }
    else if((pcRxData[0] == 'u') || (pcRxData[0] == 'U')) {        //update DDS-60
        ErFlag = dds60.CalcNewValue();
        if(ErFlag == true) {
            pc.printf("\nfrequency overflow error(1)!!\n");
        } else {
            pc.printf("\nUpdating AD9851...\n");
            LclBaseFreq = dds60.GetBaseValue();
            LclIfFreq = dds60.GetIfValue();
        }
        pcClrLineBuf();
        pcRxLine = false;
        pcRxEOB = false;
        mainMenu();
    }
    else if((pcRxData[0] == 'i') || (pcRxData[0] == 'I')) {        //increment DDS-60 frequency by step value
        Fdata = dds60.GetBaseValue();
        Fdata = Fdata + StepFreq;
        dds60.SetBaseValue(Fdata);
        ErFlag = dds60.CalcNewValue();
        if(ErFlag == true) {
            pc.printf("\nfrequency overflow error(2)!!\n");
        } else {
            pc.printf("\nStepping up freq...\n");
            LclBaseFreq = dds60.GetBaseValue();
            LclIfFreq = dds60.GetIfValue();
        }
        pcClrLineBuf();
        pcRxLine = false;
        pcRxEOB = false;
        mainMenu();
    }
    else if((pcRxData[0] == 'd') || (pcRxData[0] == 'D')) {        //decrement DDS-60 frequency by step value
        Fdata = dds60.GetBaseValue();
        Fdata = Fdata - StepFreq;
        dds60.SetBaseValue(Fdata);
        ErFlag = dds60.CalcNewValue();
        if(ErFlag == true) {
            pc.printf("\nfrequency overflow error(3)!!\n");
        } else {
            pc.printf("\nStepping down freq...\n");
            LclBaseFreq = dds60.GetBaseValue();
            LclIfFreq = dds60.GetIfValue();
        }
        pcClrLineBuf();
        pcRxLine = false;
        pcRxEOB = false;
        mainMenu();
    }
    else if(pcRxLine == true) {
//        pcRxLine = false;
//        pc.printf("  -CR/LF- det  count:%d  size:%d\n", pcRxQty, sizeof(pcRxData));
        if(pcRxQty == 0) {
            wait_us(100);
            pc.printf("empty...\n");
            pcClrLineBuf();
            mainMenu();
        } else {
            bool OneDot = false;
            pcRxIsNumb = true;
            for(int x = 0; x < pcRxQty; x++) {
                char p = pcRxData[x];
                if(pcRxIsNumb == true) {
                    if(!((p == DP) || ((p >= '0') && (p <= '9')) || (pcRxData[0] == '-'))) {    //-not- 0-9 or DP ?
                        pcRxIsNumb = false;
                    }
                    if((p == DP) && (pcRxQty == 1)) {                   //DP w/o numbers ?
                        pcRxIsNumb = false;
                    }
                }
                if((p == DP) && (OneDot == true) && (pcRxQty > 1)) {    //more than one DP?
                    pcRxIsNumb = false;
                }
                if(p == DP) {                                           //one or more DP?
                    OneDot = true;
                }
//                pc.printf("%c",p);
            }
        }
        if(pcRxIsNumb == true) {
            pcRxNumb = atof(pcRxData);
//            pc.printf("valid number: %f\n", pcRxNumb);
//            pcClrLineBuf();
        }
        higherDecode();
        pcClrLineBuf();
//        pc.printf("\n");
    }
    else if(pcRxEOB == true) {
        pcRxEOB = false;
        pc.printf("RxBuff max'd out!!\n");
    }
    else if(inchar == SP) {
//        pc.printf("  -SP- det\n");
        inchar = 0;
    }
}

/*********************************************************************************************/
int main() {
    pc.baud(921600);                        //set up USB serial speed
    i2c.frequency(400000);                  //set up i2c speed
   
    pcRxQty = 0;                            // MODSER RX data counter/pointer
    pcClrLineBuf();                         // initialize pcRxData
    
    lcdt.cls();                             //init the LCD
    lcdt.locate(0,0);                       //column(0-15), row(0-1)
    lcdt.printf("DDS-60 %d", revision);     //print revision on LCD
    lcdt.locate(0,1);                       //column(0-15), row(0-1)
    lcdt.printf("K Braun");                 //print -me- on LCD
    
    pc.printf("\n\n");
    pc.printf("-------------------------------------------------------------------\n");
    pc.printf("DDS-60 Control Routines %d  K Braun\n", revision);
    getMbedSN();                        //display mbed's serial number
    getMbedMAC();                       //display mbed's MAC address
    wait(DISP_SLOW);
    dds60.SetM6Value('A');

    // Check if we can use modify the http name of the mbed
    FILE *fp = fopen("/local/whoami.ini", "r");
//    char *hostname = DEFAULTHOSTNAME;
    if (fp == NULL) {
        pc.printf("    No /local/whoami.ini file, defaulting to:  %s\n",hostname);
    } else {
        char localbuf[64];
        hostname = fgets(localbuf, sizeof(localbuf)-1, fp);
        pc.printf("Found /local/whoami.ini file. my name is:  %s\n",hostname);
        fclose(fp);
    }
    
    FILE *fpi = fopen("/local/dds60.ini", "r");
    if (fpi == NULL) {
        InitIniFile();
        pc.printf("***rebooting after file creation....");
        wait(2.0);
        mbed_reset();
    } else {
        pc.printf("Found /local/dds60.ini file...\n");
        fclose(fpi);
        SNTPReadIniFile("/local/dds60.ini");
    }
    if (gDebug) listdir();              //get local file listing
// broken!!!    if (gDebug) listdirSD();            //get sd file listing
//
//NOTE:  mbed hangs if no SD card installed - need to fix!!!!!!
//    
    lcdt.cls();                          //init the LCD
    lcdt.locate(0,0);                    //column(0-15), row(0-1)
    lcdt.printf("SD Card Missing!");     //---in case SD drive hangs forever---
        
/*See if INDEX.HTM can be created on SD micro drive */
    if (gDebug > 3) {
//        char *WriteTest = "This is a Test!!!";
        fp = fopen("/sd/INDEX.HTM", "w+");
        if (fp == NULL) {
            pc.printf("***Cannot create INDEX.HTM file\n");
        } else {
//            char localbuf[32];
//            localbuf = WriteTest;
            fprintf(fp, "This is a Test!!!\n");
            pc.printf("Creating /sd/INDEX.HTM file\n");
            fclose(fp);
        }
    }
        
    fp = fopen("/sd/index.htm", "r");
    if (fp == NULL) {
        use_sd = false;
        if (gDebug) pc.printf("***No INDEX.HTM file - using LocalFilesystem for WebServer.\r\n");
    } else {
        use_sd = true;
        fclose(fp);
        if (gDebug) pc.printf("Found SD card with INDEX.HTM file - using SD for WebServer.\r\n");
    }
  
    if ((use_sd == true) && (gDebug > 3)) pc.printf(" ");  // to get rid of use_sd "never used" warning
  
    disp_i2c();                         //display all devies on I2C bus
    pc.printf("gDebug level: %d\n", gDebug);
    wait(DISP_SLOW);

/*       
///////////////////////////////////////////////////////////////////////////////
// testing ad9851 routines
    lcdt.cls();                             //init the LCD
    lcdt.locate(0,0);                       //column(0-15), row(0-1)
    lcdt.printf("Testing");                 //print Testing on LCD
    lcdt.locate(0,1);                       //column(0-15), row(0-1)
    lcdt.printf("AD9851...");               //print item on LCD
    wait(DISP_SLOW);
    double Fdata;
    Fdata = dds60.GetBaseValue();    
    pc.printf("----------\nTesting AD9851 routines\nBase Freq: %.3f\n", Fdata);
    Fdata = dds60.GetIfValue();    
    pc.printf("IF Freq:   %.3f\n", Fdata);
    unsigned int UIdata;
    UIdata = dds60.GetFD32Value();    
    pc.printf("32 SDO:    0x%08x\n", UIdata);
    char Cdata;
    Cdata = dds60.GetFortyValue();    
    pc.printf("5th byte:  0x%02x\n", Cdata);
    pc.printf("40 bit wd: 0x%02x%08x\n", Cdata, UIdata);
    dds60.AD9851Enable();
    Cdata = dds60.GetFortyValue();    
    pc.printf("5th byte:  0x%02x\n", Cdata);
    dds60.AD9851Disable();
    Cdata = dds60.GetFortyValue();    
    pc.printf("5th byte:  0x%02x\n", Cdata);
    dds60.CalcNewValue();
    UIdata = dds60.GetFD32Value();    
    Cdata = dds60.GetFortyValue();    
    pc.printf("40 bit wd: 0x%02x%08x\n", Cdata, UIdata);
    pc.printf("----------\n");
    dds60.AD9851Enable();
    bool ErFlag;
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  1 error!!\n");
    dds60.SetBaseValue(7320000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  2 error!!\n");
    dds60.SetIfValue(1620000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  3 error!!\n");
    dds60.SetM6Value('0');
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  4 error!!\n");
    dds60.SetBaseValue(30320000.0);
    ErFlag = dds60.CalcNewValue();
    if(ErFlag == true) pc.printf("  5a error!!\n");
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  5 error!!\n");
    
    dds60.SetM6Value('1');
    ErFlag = dds60.CalcNewValue();
    if(ErFlag == true) pc.printf("  6a error!!\n");
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  6 error!!\n");
    dds60.SetBaseValue(30320000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  7 error!!\n");
    
    dds60.SetM6Value('A');
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  8 error!!\n");
    dds60.SetBaseValue(30320000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf("  9 error!!\n");
    
    dds60.SetBaseValue(180000000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf(" 10 error!!\n");
    
    dds60.SetBaseValue(27000000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf(" 11 error!!\n");
    
    dds60.SetBaseValue(127000000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf(" 12 error!!\n");
    
    dds60.SetBaseValue(10000000.0);
    dds60.SetIfValue(0.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf(" 13 error!!\n");
    
    dds60.SetBaseValue(123456.789);
    dds60.SetIfValue(0.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf(" 14 error!!\n");
    
    dds60.SetBaseValue(29545000.0);
    dds60.SetIfValue(455000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf(" 15 error!!\n");
    
    dds60.SetBaseValue(29544999.999);
    dds60.SetIfValue(455000.0);
    dds60.CalcNewValue();
    ErFlag = dds60.GetErrFlagValue();
    if(ErFlag == true) pc.printf(" 16 error!!\n");
    
    pc.printf("----------\n");
*/    
///////////////////////////////////////////////////////////////////////////////    
//    pc.printf("----------\nTesting MOSERIAL routines\n");
//    int c = 'A';
//    lcdt.cls();                             //init the LCD
//    lcdt.locate(0,0);                       //column(0-15), row(0-1)
//    lcdt.printf("Testing");                 //print Testing on LCD
//    lcdt.locate(0,1);                       //column(0-15), row(0-1)
//    lcdt.printf("MODSERIAL...");            //print item on LCD
    
    // Ensure the baud rate for the PC "USB" serial is much
    // higher than "uart" baud rate below.
//    pc.baud(PC_BAUD);
    
    // Use a deliberatly slow baud to fill up the TX buffer
//    uart.baud(1200);
    
//    uart.attach(&txCallback, MODSERIAL::TxIrq);
//    uart.attach(&rxCallback, MODSERIAL::RxIrq);
//    uart.attach(&txEmpty,    MODSERIAL::TxEmpty);
    
//    pc.attach(&rxCallbackpc, MODSERIAL::RxIrq);
    pc.attach(&Rx_interrupt, Serial::RxIrq);

    
//    led1 = 1; // Show start of sending with LED1.
    
//    for (int loop = 0; loop < 512; loop++) {
//        uart.printf("%c", c);        
//        c++;
//        if (c > 'Z') c = 'A';
//    }
    
    
    // End program. Flash LED4. Notice how LED 2 and 3 continue
    // to flash for a short period while the interrupt system 
    // continues to send the characters left in the TX buffer.
    
    ErFlag = dds60.CalcNewValue();          //init DDS-60

    lcdt.cls();                             //init the LCD
    lcdt.locate(0,0);                       //column(0-15), row(0-1)
    lcdt.printf("DDS-60 %d", revision);     //print revision on LCD
        
    pcClrLineBuf();
    mainMenu();
//    int loop = 0;
    Fcmd = 0;
    Sequence = 0;
    Tic = 0;
    while (true) {
        wait(0.05);
        if(Led1Up == true) {
            Led1Pwm = Led1Pwm + 0.005;
            led1 = Led1Pwm;
            if(Led1Pwm >= 0.20) {
                Led1Up = false;
            }
        } else {
            Led1Pwm = Led1Pwm - 0.005;
            led1 = Led1Pwm;
            if(Led1Pwm <= 0.01) {
                Led1Up = true;
            }
        }
//        led1 = !led1;

        pcRx();
        
        Tic = Tic++;
        if(Tic >= 40) {
            Tic = 0;
            UpdLCD();           //update LCD Values
            Sequence = Sequence++;
            if(Sequence >= 6) Sequence = 0;
        }

    }
}