Specification | Condition | MAX2870 | MAX2871 |
Reference Input Frequency (MHz) | Max. | 200 | 210 |
Maximum PFD Frequency (MHz) | INT mode FRAC mode |
105 50 |
140 125 |
3.0 GHZ VCO Open Loop Phase Noise (dBc/Hz) | 10MHz offs. | -155.0 | -158.0 |
4.5 GHz VCO Open Loop Phase Noise (dBc/Hz) | 10MHz offs. | -151.0 | -153.0 |
6.0 GHz VCO Open Loop Phase Noise (dBc/Hz) | 10 MHz offs. | -150.0 | -151.0 |
Integrated RMS Jitter (ps) | 0.250 | 0.200 | |
Normalized In-Band Noise Floor (dBc/Hz) | -266 int | -230 int | |
1/f Noise (dBc/Hz) | -95.0 | -122.0 | |
2nd Harmonics (VCO/2) dBc | -20 | -25 | |
Temperature Sensor & ADC | |||
Temp. Compensation from -40C to +85C | |||
Phase Synchronization | |||
Cycle-Slip Reduction and Fast Lock | |||
Mute Until Lock | |||
Muted Output Power | -31.0 | -40.0 | |
Total Supply Current at 6 GHz (mA) | 162 | 182 | |
Price / 2500 in CHF (digi-key, 5/2019) | 6.912 | 6.912 |
/* ///////////////////////////////////////////////////////////////////// ARDUINO/Genuino (DUE) Sketch for Shield "SUPERMOD" https://www.changpuak.ch/electronics/Arduino-Shield-SUPERMOD.php Software Version 1.0, 21.05.2019 by Christoph Gisler (IPA) using routines by Joël Steinemann (IPA) and Alexander Sse Frank (Fachvorgesetzter) using libraries from Adafruit Final Version as of 13.06.2019 //////////////////////////////////////////////////////////////////////*/ #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SH1106.h> // PINS MAX2871 #define CLOCKPIN A0 #define DATAPIN A1 #define LE A2 #define CE A3 //composition of MAX2871 Registers //Register 0 unsigned long INT = 0x0; //Enables fractional-N mode unsigned long NDIV; // Integer part from N-Divider unsigned long FRAC; unsigned long ADDR0 = 0x0; //Register 1 unsigned long CPL = 0x3; //Charge pump liniarity 30% unsigned long CPT = 0x00; //Charge pump test mode = normal mode unsigned long PHASE = 0x1; //Phase Value (recomened) unsigned long MODULUS = 0xFA0; //4000 for max resolution unsigned long ADDR1 = 0x1; //Register 2 unsigned long LDS = 0x1; // 1 if fPFD > 32 MHz unsigned long SDN = 0x0; //noise mode = Low-noise mode unsigned long MUX = 0x6; //MUX pin configuration = Digital lock detect unsigned long DBR = 0x0; //reference doubler is disabled unsigned long RDIV2 = 0x0; //reference divide-by-2 is disabled unsigned long RCNT = 0x0; // reference divide Value is unused unsigned long REG4DB = 0x0; //double buffer mode disabled unsigned long CP = 0x00; //charge pump current = 0.32 mA (1.36/RSET * (1 + CP[3:0]) RSET = 5k1) unsigned long LDF = 0x0; // lock dtect function = Frac-N lock detect unsigned long LDP = 0x0; // lock detect precision = 10ns unsigned long PDP = 0x1; //phase detector polarity set poitive unsigned long SHDN = 0x0; //power down mode = normal mode unsigned long TRI = 0x0; //charge pump output high-impedance mode disabled unsigned long RST = 0x0; // counter reset mode = normal operation unsigned long ADDR2 = 0x2; //Register 3 unsigned long VCO_MS = 0x0; // VCO maual selction: unused unsigned long VAS_SHDN = 0x0; //VAS enabled unsigned long VAS_TEMP = 0x1; //VAS temperature compensation enabled unsigned long CSM = 0x0; //Cycle slip mode disabled unsigned long MUTEDEL = 0x0; //mute delay mode disabled unsigned long CDM = 0x1; // Fast-lock mode enabled unsigned long CDIV = 0x0; // clock divider value unused unsigned long ADDR3 = 0x3; //Register 4 unsigned long RES = 0x3; //Reserved unsigned long SDLDO = 0x0; //LDO endabled unsigned long SDDIV = 0x0; //VCO Divider enabled unsigned long SDREF = 0x0; //Reference input enabled unsigned long FB = 0x1; //VCO to N counter mode is NOT divided unsigned long DIVA; unsigned long BS = 0x30FF; //shoud be choosen so that fPFD/BS = 50kH or less unsigned long SDVCO = 0x0; //VCO enabled unsigned long MTLD = 0x0; //RFOUT Mute until Lock detet mode disabled unsigned long BDIV = 0x0; //RFOUTB is divided (so it's the same as RFOUTA) unsigned long RFB_EN = 0x1; //RFOUTB enabled unsigned long BPWR = 0x3; //RFOUTB = 5 dBm unsigned long RFA_EN = 0x1; //RFOUTA enabled unsigned long APWR = 0x3; //RFOUTA = 5dBm unsigned long ADDR4 = 0x4; //Register 5 unsigned long VAS_DLY = 0x3; //0x0 if VAS_TEMP = 0, 0x3 if VAS_TEMP = 1 unsigned long SDPLL = 0x0; // PLL enabled unsigned long F01 = 0x1; // if F = 0 then int unsigned long LD = 0x3; //Lock-Detect pin function = HIGH unsigned long MUX_MSB = 0x0; //MSB of MUX unsigned long ADCS = 0x0; //ADC normal operation (ADC isn't used) unsigned long ADCM = 0x0; //ADC disabled unsigned long ADDR5 = 0x5; float AC[56]; unsigned long long FreqOUT = 0; unsigned long long FreqOUTold = 0; unsigned long long FMIN = 23499999; unsigned long long FMAX = 6000000001; unsigned long composedRegisterValue; float EEPROM_float; float LMAX = 12; float LMIN = LMAX - 31.5; float LACT = 12.0; float ATT = 0.0; float CAL = 0.0; // OLED 128x64 with SH1106 Controller // E.G. DM-OLED13-625 #define OLED_MOSI 29 #define OLED_CLK 27 #define OLED_DC 35 #define OLED_CS 37 #define OLED_RESET 31 Adafruit_SH1106 display(OLED_MOSI,OLED_CLK,OLED_DC,OLED_RESET,OLED_CS); #if (SH1106_LCDHEIGHT != 64) #error("Height incorrect, please fix Adafruit_SH1106.h!"); #endif unsigned int ActiveDisplay = 1 ; // AMPLITUDE boolean ShowCursor = true ; unsigned int CursorPosition = 2 ; // Menue Intem to be displayed unsigned int MenueItem = 0 ; // STATE OF THE ROTARY ENCODER const int RE2 = 49 ; // PRESSED const int RE1 = 47 ; const int RE0 = 45 ; unsigned long StartMilli ; unsigned long DurationMilli ; boolean PressedLong = false ; // "INTERRUPT" VARIABLES unsigned int RE_now = 0; unsigned int RE_old = 0; unsigned int RE_xor = 0 ; unsigned int RE_one = 0 ; unsigned int RE_two = 0 ; unsigned int RE_eval = 0x0 ; // 0 = LEFT(-), 1=RIGHT(+), 2=PRESSED unsigned long RE_time0 = 0 ; unsigned long RE_time1 = 0 ; unsigned long RE_time2 = 0 ; const int MCPADR = 0x27; const int ATTREGADR = 0x12; // ATTENUATOR, MCP REG A const int CALREGADR = 0x13; // CALIBRATION, MCP REG B unsigned int CALBYTE; unsigned int ATTBYTE; const int EEPROM_ADR = 0x50; void setup() { delay(5000); Serial.begin(9600); Wire.begin(); pinMode(CLOCKPIN, OUTPUT); pinMode(DATAPIN, OUTPUT); pinMode(LE, OUTPUT); pinMode(CE, OUTPUT); digitalWrite(CLOCKPIN, LOW); digitalWrite(DATAPIN, LOW); digitalWrite(LE, HIGH); digitalWrite(CE, HIGH); // INIT OLED display.begin(SH1106_SWITCHCAPVCC); // SHOW STARTUP SCREEN display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0,0); display.println("Supermod"); display.setTextSize(1); display.setCursor(0,21); display.println("AN UHF SYNTHESISER"); display.setCursor(0,33); display.println("BASED ON THE MAX 2871"); display.setCursor(0,45); display.println("(C) ETH QUANTUMOPTICS"); display.setCursor(0,57); display.println("BUILT 29.04.2019"); display.display(); delay(2000); display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0,0); display.println("Supermod"); display.setTextSize(1); display.setCursor(0,21); display.println("FIRMWARE WRITTEN BY"); display.setCursor(0,33); display.println("MR. JOEL STEINEMANN"); display.setCursor(0,45); display.println("MR. CHRISTOPH GISLER"); display.setCursor(0,57); display.println("MR. ALEXANDER FRANK"); display.display(); delay(2000); display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0,0); display.println("Supermod"); display.setTextSize(1); display.setCursor(0,21); display.println("HARDWARE DESIGNED BY"); display.setCursor(0,33); display.println("MR. CHRISTOPH GISLER"); display.setCursor(0,45); display.println("MR. ALEXANDER FRANK"); display.setCursor(0,57); display.println("MR. TILMAN ESSLINGER"); display.display(); delay(2000); // KNOB - ROTARY ENCODER pinMode(RE2, INPUT_PULLUP); pinMode(RE1, INPUT_PULLUP); pinMode(RE0, INPUT_PULLUP); RE_now = (digitalRead(RE2)<<2)|(digitalRead(RE1)<<1)|digitalRead(RE0); RE_old = RE_now ; //request 8 Bytes from EEPROM Wire.beginTransmission(EEPROM_ADR); Wire.write(0x0); //Addres of EEPROM where first byte of FreqOUT is saved delay(10); Wire.endTransmission(); Wire.requestFrom(EEPROM_ADR,8); FreqOUT = 0; //combines FreqOUT value from the 8 bytes for(int i = 7; i >= 0; i--) { FreqOUT |= ((unsigned long long)Wire.read() << (i * 8)); delay(10); } //request 2 bytes from Eprom Wire.beginTransmission(EEPROM_ADR); Wire.write(0x8); delay(10); Wire.endTransmission(); Wire.requestFrom(EEPROM_ADR,2); //combines LACT valie from the 2 bytes LACT = Wire.read(); delay(10); LACT += Wire.read()/2.; delay(10); if (FreqOUT == -1) { FreqOUT = 4000000000; LACT = 12; } //LACT = 12; //FreqOUT = 4000000000; //Wire.endTransmission(); delay(2000); CalculateRegisterValues(); //init MAX2871 2* (see datasheet) for(int i = 0; i < 2; i++) { composedRegisterValue = VAS_DLY << 29|SDPLL << 25 |F01 << 24| LD <<22 |MUX << 18|ADCS << 6 |ADCM << 3|ADDR5; WriteMAX2871(composedRegisterValue); delay(20); //Serial.println(composedRegisterValue, BIN); composedRegisterValue = RES << 29|SDLDO << 28 |SDDIV << 27| SDREF << 26|FB << 23 |DIVA << 20|BS << 12|SDVCO << 11|MTLD << 10 |BDIV << 9| RFB_EN << 8|BPWR << 6|RFA_EN << 5 |APWR << 3|ADDR4; WriteMAX2871(composedRegisterValue); //Serial.println(composedRegisterValue, BIN); composedRegisterValue = VCO_MS << 26|VAS_SHDN << 25 |VAS_TEMP << 24|CSM << 18 |MUTEDEL << 17|CDM << 15|CDIV << 3|ADDR3; WriteMAX2871(composedRegisterValue); //Serial.println(composedRegisterValue, BIN); composedRegisterValue = LDS << 31|SDN << 29|MUX << 26 |DBR <<25|RDIV2 <<24|RCNT <<14 |REG4DB <<13|CP << 9|LDF << 8|LDP << 7 |PDP << 6|SHDN << 5|TRI << 4|RST <<3|ADDR2; WriteMAX2871(composedRegisterValue); //Serial.println(composedRegisterValue, BIN); composedRegisterValue = CPL << 29|CPT << 27 |PHASE <<15|MODULUS << 3|ADDR1; WriteMAX2871(composedRegisterValue); //Serial.println(composedRegisterValue, BIN); composedRegisterValue = INT << 31|NDIV << 15 |FRAC << 3|ADDR0; WriteMAX2871(composedRegisterValue); //Serial.println(composedRegisterValue, BIN); } // ATTENUATION NEEDED FOR LMAX OUTPUT - CHECK THAT AC[0] = 19 ; // 100 MHz AC[1] = 19 ; // 300 MHz AC[2] = 20 ; // 500 MHz AC[3] = 18.5 ; // 700 MHz AC[4] = 18.5 ; // 900 MHz AC[5] = 18.5 ; // 1100 MHz AC[6] = 18.5 ; // 1300 MHz AC[7] = 17 ; // 1500 MHz AC[8] = 17 ; // 1700 MHz AC[9] = 16.5 ; // 1900 MHz AC[10] = 16 ; // 2100 MHz AC[11] = 15 ; // 2300 MHz AC[12] = 13 ; // 2500 MHz AC[13] = 13 ; // 2700 MHz AC[14] = 11 ; // 2900 MHz AC[15] = 9.5 ; // 3100 MHz AC[16] = 10 ; // 3300 MHz AC[17] = 9 ; // 3500 MHz AC[18] = 8.5 ; // 3700 MHz AC[19] = 7 ; // 3900 MHz AC[20] = 6 ; // 4100 MHz AC[21] = 4 ; //4300 MHz AC[22] = 5.5 ; //4500 MHz AC[23] = 5 ; //4700 MHz AC[24] = 2 ; //4900 MHz AC[25] = 0 ; //5100 MHz AC[26] = 0 ; //5300 MHz AC[27] = 0 ; //5500 MHz AC[28] = 0 ; //5700 MHz AC[29] = 0 ; //5900 MHz AC[30] = 0 ; //6100 MHz // INIT MCP23017, ALL OUTPUT, A0,A1,A2 = HIGH Wire.beginTransmission(MCPADR); Wire.write(0x00); // IODIRA register Wire.write(0x00); // set all of port A to outputs Wire.endTransmission(); Wire.beginTransmission(MCPADR); Wire.write(0x01); // IODIRB register Wire.write(0x00); // set all of port B to outputs Wire.endTransmission(); } void loop() { switch (MenueItem) { case 0: ShowFrequencyMenue() ; ActiveDisplay = 0 ; MenueItem = 2 ; ProgramMAX2871(); SetRFLevel(); break; case 1: ShowAmplitudeMenue() ; ActiveDisplay = 1 ; MenueItem = 2 ; SetRFLevel(); break; case 2: // ////////////////////////////////////////////////////////////// // READ THE ROTARY ENCODER EVERY 1 ms // Timer Interrupt does not work here // ////////////////////////////////////////////////////////////// RE_xor = 0x00 ; while (RE_xor == 0x00) { CheckRE() ; delay(1) ; // saves LACT and FreqOUT to EEPROM if FreqOUT changed and the // incrementer is not moved for 5 sechonds if((FreqOUTold != FreqOUT) && ((millis() - RE_time1) > 5000)) { //save FreqOut to EEPROM Wire.beginTransmission(EEPROM_ADR); Wire.write(0x00); delay(10); for(int i = 7; i >= 0; i--) { Wire.write((int)(FreqOUT >> ((i * 8) & 0xFF))); delay(10); } Wire.endTransmission(); //svaes LACT to EEPROM Wire.beginTransmission(EEPROM_ADR); Wire.write(0x08); delay(10); EEPROM_float = (int)LACT; Wire.write((int)LACT); delay(10); EEPROM_float =(LACT-EEPROM_float)*2.; Wire.write((int)EEPROM_float); delay(10); Wire.endTransmission(); FreqOUTold = FreqOUT; } } RE_time0 = millis(); RE_one = RE_xor ; delay(1); // NOW WAIT FOR THE SECOND TRANSITION ... RE_xor = 0x00 ; while (RE_xor == 0x00) { CheckRE() ; delay(1) ; } RE_time1 = millis(); RE_two = RE_xor ; // TIME DURATION RE_time2 = RE_time1 - RE_time0 ; PressedLong = false ; if (RE_time2 > 999 ) PressedLong = true ; // NOW EVALUATE //Serial.print("RE_old: "); Serial.println(RE_old,BIN); //Serial.print("RE_now: "); Serial.println(RE_now,BIN); //Serial.print("RE_xor: "); Serial.println(RE_xor,BIN); //Serial.print("RE_one : ");Serial.println(RE_one,BIN); //Serial.print("RE_two : ");Serial.println(RE_two,BIN); //Serial.print("RE_time2 : ");Serial.println(RE_time2); //Serial.println(" "); RE_eval = 0xFF ; if ((RE_one == 0x1) & (RE_two == 0x2)) RE_eval = 0x0; // LEFT if ((RE_one == 0x2) & (RE_two == 0x1)) RE_eval = 0x1; // RIGHT if ((RE_one == 0x4) & (RE_two == 0x4)) RE_eval = 0x2; // PRESSED // ////////////////////////////////////////////////////////////// // ROTATION = LEFT = - // ////////////////////////////////////////////////////////////// if ((RE_eval == 0x0) && (ActiveDisplay == 0)) { switch (CursorPosition) { case 0: // -1 GHZ if (FreqOUT > (FMIN + 1E9)) FreqOUT -= 1E9 ; break; case 1: // -100 MHz if (FreqOUT > (FMIN + 1E8)) FreqOUT -= 1E8 ; break; case 2: // -10 MHz if (FreqOUT > (FMIN + 1E7)) FreqOUT -= 1E7 ; break; case 3: // -1 MHz if (FreqOUT > (FMIN + 1E6)) FreqOUT -= 1E6 ; break; case 4: // -100 kHz if (FreqOUT > (FMIN + 1E5)) FreqOUT -= 1E5 ; break; case 5: // -12.5 kHz if (FreqOUT > (FMIN + 12500)) FreqOUT -= 12500 ; break; } MenueItem = ActiveDisplay ; } // ////////////////////////////////////////////////////////////// // ROTATION = LEFT = - // ////////////////////////////////////////////////////////////// if ((RE_eval == 0x0) && (ActiveDisplay == 1)) { // DECREASE LEVEL LACT -= 0.5 ; if (LACT < LMIN) LACT = LMIN ; MenueItem = ActiveDisplay ; } // ////////////////////////////////////////////////////////////// // ROTATION = RIGHT = + // ////////////////////////////////////////////////////////////// if ((RE_eval == 0x1) && (ActiveDisplay == 0)) { switch (CursorPosition) { case 0: // +1 GHZ if (FreqOUT < (FMAX - 1E9)) FreqOUT += 1E9 ; break; case 1: // +100 MHz if (FreqOUT < (FMAX - 1E8)) FreqOUT += 1E8 ; break; case 2: // +10 MHz if (FreqOUT < (FMAX - 1E7)) FreqOUT += 1E7 ; break; case 3: // +1 MHz if (FreqOUT < (FMAX - 1E6)) FreqOUT += 1E6 ; break; case 4: // +100 kHz if (FreqOUT < (FMAX - 1E5)) FreqOUT += 1E5 ; break; case 5: // +12.5 kHz if (FreqOUT < (FMAX - 12500)) FreqOUT += 12500 ; break; } MenueItem = ActiveDisplay ; } // ////////////////////////////////////////////////////////////// // ROTATION = RIGHT = + // ////////////////////////////////////////////////////////////// if ((RE_eval == 0x1) && (ActiveDisplay == 1)) { // INCREASE LEVEL LACT += 0.5 ; if (LACT > LMAX) LACT = LMAX ; MenueItem = ActiveDisplay ; } // ////////////////////////////////////////////////////////////// // ROTARY ENCODER WAS PRESSED // ////////////////////////////////////////////////////////////// if (RE_eval == 0x2) { // CASE 1 : FREQUENCY MODE AND SHORT PRESS if ((ActiveDisplay == 0) && !PressedLong) { // MOVE CURSOR ONE POSITION RIGHT CursorPosition += 1; if (CursorPosition > 5) CursorPosition = 0 ; MenueItem = ActiveDisplay ; } // CASE 2 : FREQUENCY MODE AND LONG PRESS else if ((ActiveDisplay == 0) && PressedLong) { // SWITCH TO AMPLITUDE MODE ActiveDisplay = 1 ; MenueItem = ActiveDisplay ; } // CASE 3 : AMPLITUDE MODE AND SHORT PRESS else if ((ActiveDisplay == 1) && !PressedLong) { // NOTHING TO DO HERE delay(1); } // CASE 4 : AMPLITUDE MODE AND LONG PRESS else if ((ActiveDisplay == 1) && PressedLong) { // SWITCH TO FREQUENCY MODE ActiveDisplay = 0 ; MenueItem = ActiveDisplay ; } } break; default: ShowErrorMenue() ; MenueItem = 2 ; delay(999); ActiveDisplay = 0 ; MenueItem = ActiveDisplay ; break; } } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES FOR THE MAX2871. // ///////////////////////////////////////////////////////////////////// void WriteMAX2871( unsigned long data ) //Writes 32 Bit value to register of MAX2871 { digitalWrite(LE, LOW); shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, ((data & 0xFF000000) >> 24)); shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, ((data & 0x00FF0000) >> 16)); shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, ((data & 0x0000FF00) >> 8)); shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, (data & 0x000000FF)); digitalWrite(LE, HIGH); //delay(50); } void ProgramMAX2871() // compose register value of register 0 and 4 { CalculateRegisterValues(); composedRegisterValue = INT << 31|NDIV << 15|FRAC << 3|ADDR0; WriteMAX2871(composedRegisterValue); //Serial.println(composedRegisterValue, BIN); composedRegisterValue = RES << 29|SDLDO << 28|SDDIV << 27 | SDREF << 26|FB << 23|DIVA << 20|BS << 12 |SDVCO << 11|MTLD << 10|BDIV << 9|RFB_EN << 8 |BPWR << 6|RFA_EN << 5|APWR << 3|ADDR4; WriteMAX2871(composedRegisterValue); //Serial.println(composedRegisterValue, BIN); } void CalculateRegisterValues() //calculates values of NDIV, FRAC & DIVA { double rest; if(FreqOUT >= 3000000000) { DIVA = 0; NDIV = FreqOUT / 50000000; rest = FreqOUT % 50000000; FRAC = rest / 50000000.0 * 4000.0; } else if((FreqOUT < 3000000000) && (FreqOUT >= 1500000000)) { DIVA = 1; NDIV = FreqOUT * 2 / 50000000; rest = FreqOUT * 2 % 50000000; FRAC = rest / 50000000.0 * 4000.0; } else if((FreqOUT < 1500000000) && (FreqOUT >= 750000000)) { DIVA = 2; NDIV = FreqOUT * 4 / 50000000; rest = FreqOUT * 4 % 50000000; FRAC = rest / 50000000.0 * 4000.0; } else if((FreqOUT < 750000000) && (FreqOUT >= 375000000)) { DIVA = 3; NDIV = FreqOUT * 8 / 50000000; rest = FreqOUT * 8 % 50000000; FRAC = rest / 50000000.0 * 4000.0; } else if((FreqOUT < 375000000) && (FreqOUT >= 187500000)) { DIVA = 4; NDIV = FreqOUT * 16 / 50000000; rest = FreqOUT * 16 % 50000000; FRAC = rest / 50000000.0 * 4000.0; } else if((FreqOUT < 187500000) && (FreqOUT >= 93750000)) { DIVA = 5; NDIV = FreqOUT * 32 / 50000000; rest = FreqOUT * 32 % 50000000; FRAC = rest / 50000000.0 * 4000.0; } else if((FreqOUT < 93750000) && (FreqOUT >= 46875000)) { DIVA = 6; NDIV = FreqOUT * 64 / 50000000; rest = FreqOUT * 64 % 50000000; FRAC = rest / 50000000.0 * 4000.0; } else { DIVA = 7; NDIV = FreqOUT * 128 / 50000000; rest = FreqOUT * 128 % 50000000; FRAC = rest / 50000000.0 * 4000.0; } //Serial.println(NDIV); //Serial.println(FRAC); } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES DISPLAY. // ///////////////////////////////////////////////////////////////////// void ShowFrequencyMenue () { char str[20]; sprintf(str, "%10lld", FreqOUT); int len=strlen(str); int offset = 0; display.clearDisplay(); display.setTextColor(WHITE); display.setTextSize(2); display.setCursor(0,0); display.println("FREQUENCY"); for (int i=0; i<10; i++) { if (i>=0) offset = 0; if (i>=1) offset = 5; if (i>=4) offset = 10; if (i>=7) offset = 15; display.setTextColor(WHITE); display.setCursor(i*11+offset,20); if (i<10-len) display.print(" "); else display.print(str[i]); if ((ShowCursor) && (CursorPosition == i)) { display.setCursor(i*11+offset,26); display.print("_"); } } ShowInfo(); display.display(); } void ShowAmplitudeMenue () { display.clearDisplay(); display.setTextColor(WHITE); display.setTextSize(2); display.setCursor(0,0); display.println("AMPLITUDE"); display.setCursor(0,20); if (LACT > 0.0) display.print("+"); if (LACT == 0.0) display.print(" "); display.print(LACT,1); display.print(" dBm "); ShowInfo(); display.display(); } void ShowErrorMenue () { display.clearDisplay(); display.setTextColor(WHITE); display.setTextSize(2); display.setCursor(0,0); display.println("ERROR 0x89"); display.setCursor(0,20); //display.print("UNLOCKED"); ShowInfo(); display.display(); } void ShowInfo() { display.drawLine(0, 40, 128, 40, WHITE); display.setTextSize(1); display.setCursor(0,46); display.println("PRESS -> ROTATE +/-"); display.setCursor(0,57); display.print("INTERN REFERENCE "); //if (digitalRead(Locked)) display.print("LOCKED "); //else display.print("UNLOCKED "); } // CHECK ROTARY ENCODER void CheckRE() { RE_old = RE_now ; RE_now = (digitalRead(RE2)<<2)|(digitalRead(RE1)<<1)|digitalRead(RE0); RE_xor = RE_now ^ RE_old ; } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES ATTENUATOR. // ///////////////////////////////////////////////////////////////////// // SET RF LEVEL / BOTH ATTENUATORS void SetRFLevel() { ATT = LMAX - LACT ; unsigned int IndexCalValue = (int)(FreqOUT / 200000000); // FLOOR CAL = AC[IndexCalValue] ; //MCP23017 SWITCH // ///////////////////////////////////// // REVERSE THE ORDER TO MATCH MCP23017 LAYOUT // CALBYTE: CALBYTE = 0xFF; if ( CAL >= 16 ) { CALBYTE -= 0x01; CAL -= 16; } if ( CAL >= 8 ) { CALBYTE -= 0x02; CAL -= 8; } if ( CAL >= 4 ) { CALBYTE -= 0x04; CAL -= 4; } if ( CAL >= 2 ) { CALBYTE -= 0x08; CAL -= 2; } if ( CAL >= 1 ) { CALBYTE -= 0x10; CAL -= 1; } if ( CAL >= 0.5 ) { CALBYTE -= 0x20; CAL -= 0.5; } // ATTBYTE: ATTBYTE = 0xFF; if ( ATT >= 16 ) { ATTBYTE -= 0x01; ATT -= 16; } if ( ATT >= 8 ) { ATTBYTE -= 0x02; ATT -= 8; } if ( ATT >= 4 ) { ATTBYTE -= 0x04; ATT -= 4; } if ( ATT >= 2 ) { ATTBYTE -= 0x08; ATT -= 2; } if ( ATT >= 1 ) { ATTBYTE -= 0x10; ATT -= 1; } if ( ATT >= 0.5 ) { ATTBYTE -= 0x20; ATT -= 0.5; } //Serial.print("ATT: "); Serial.println(ATT, BIN); //Serial.print("CALBYTE: "); Serial.println(CALBYTE,BIN); //Serial.print("ATTBYTE: "); Serial.println(ATTBYTE,BIN); // WRITE NEW REGISTERS Wire.beginTransmission(MCPADR); Wire.write(ATTREGADR); // address port A Wire.write(ATTBYTE); // value to send Wire.endTransmission(); Wire.beginTransmission(MCPADR); Wire.write(CALREGADR); // address port B Wire.write(CALBYTE); // value to send Wire.endTransmission(); } // ///////////////////////////////////////////////////////////////////// // END OF FILE. // /////////////////////////////////////////////////////////////////////