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

Revision:
0:1ed24aaf786d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Apr 04 18:14:54 2012 +0000
@@ -0,0 +1,1199 @@
+/*
+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;
+        }
+
+    }
+}
\ No newline at end of file