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
Diff: main.cpp
- 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