/* ////////////////////////////////////////////////////////////////// ARDUINO/Genuino (UNO) Si570 Evaluation Board - "Micromod Synthesizer" https://www.changpuak.ch/electronics/Si570.php Software Version 2.0, USES TIMER INTERRUPT 29.09.2016 by JOËL STEINEMANN AND ALEXANDER FRANK HELPFUL WEBSITES/LINKS: http://playground.arduino.cc/Main/PinChangeInterrupt http://gammon.com.au/interrupts https://www.youtube.com/watch?v=cwsCxUhHbQM http://hastebin.com/cufoxazoxo.coffee Si570 PROGRAMMING HELP: http://cbjohn.com/aa0zz/PPLL/Article.pdf DATA SHEETS: https://www.silabs.com/Support%20Documents/TechnicalDocs/si570.pdf https://cdn.macom.com/datasheets/MAAD-007086.pdf ////////////////////////////////////////////////////////////////// */ // LCD PINS (NOKIA5110) #define RST 13 #define CE 12 #define DC 9 #define DIN 11 #define CLK 10 char string[8]; #include #include #include #include "font.h"; #include "TimerOne.h" // ///////////////////////////////////////////////////////////// // CONSTANTS FOR THE Si570 const int Si570ADDRESS = 0x55 ; const float MaxFreq = 199.999 ; const float MinFreq = 19.999 ; const float Crystal = 114.285046732392 ; const float MaxVCO = 5670.0 ; const float MinVCO = 4850.0 ; float Frequency = 100.000 ; // ARRAYS FOR THE LOOKUP TABLE float VCO_Freq[7] = {125,140,155,170,202,236}; unsigned int HSDIV[7] = {11,5,9,4,7,4}; unsigned int HS[13] = {0,0,0,0,0,1,0,3,0,5,0,7}; unsigned int N1[7] = {4,8,4,8,4,6}; unsigned int Block ; // VARIABLES FOR PROGRAMMING THE Si570 float RFREQ; unsigned int RF_DIVIDER_INTEGER ; long RF_DIVIDER_FRACTIONAL ; unsigned int HS_DIVIDER; unsigned int N_DIVIDER; float FR; // Si570 REGISTER VARIABLES byte SiR7,SiR8,SiR9,SiR10,SiR11,SiR12; byte R7,R8,R9,R10,R11,R12; // ///////////////////////////////////////////////////////////// //VARIABLES AND PIN DEFINITION FOR THE ATTENUATOR const float LevelMin = -35 ; const float LevelMax = 15 ; int Level = 15 ; const int ATT32 = 2; const int ATT16 = 3; const int ATT08 = 4; const int ATT04 = 5; const int ATT02 = 6; const int ATT01 = 7; // ///////////////////////////////////////////////////////////// unsigned int CursorPosition = 2; unsigned int CursorOFFtime = 0; unsigned int AuxKnobEval = 0x00; float EncoderValue; boolean EncoderState; unsigned long currentmillis; unsigned long LcdMillis; unsigned long lastchange; boolean laststate = true; boolean LcdState = true; int x=12,y=2; boolean Frequency_Level = true; float Max, Min, Addition = 1,maxNr,minNr; // ///////////////////////////////////////////////////////////// // INTERRUPT VARIABLES volatile unsigned int RotaryEncoderStatus = 0; volatile unsigned int RotaryEncoderStatusOld = 0; volatile unsigned int RotaryEncoderActivity = 1 ; // ///////////////////////////////////////////////////////////// // serial data input char inputcmd[100]; int cmdindex=0; // ///////////////////////////////////////////////////////////// void LcdWriteString(char *characters) { while(*characters) LcdWriteCharacter(*characters++); } void LcdWriteData(byte data) { digitalWrite(DC, HIGH); digitalWrite(CE, LOW); shiftOut(DIN, CLK, MSBFIRST, data); digitalWrite(CE, HIGH); } void LcdWriteCmd(byte cmd) { digitalWrite(DC, LOW); digitalWrite(CE, LOW); shiftOut(DIN, CLK, MSBFIRST, cmd); digitalWrite(CE, HIGH); } void LcdWriteCharacter(byte character) { for(int i=0; i<5; i++) LcdWriteData(ASCII[character - 0x20][i]); LcdWriteData(0x00); // 1 pixel distance } void LcdWriteBigCharacter(byte character) { // HEIGHT AND WIDTH IS DOUBLED, 1 pix >> 4 pix for(int i=0; i<5; i++) LcdWriteData(ASCII[character - 0x20][i]); LcdWriteData(0x00); // 1 pixel distance } void LcdDisplay(byte data) { byte UpperNibble = (data & 0xF0) >> 4 ; byte LowerNibble = data & 0x0F ; if (UpperNibble < 0x0A) LcdWriteCharacter(UpperNibble + 0x30); if (UpperNibble >= 0x0A) LcdWriteCharacter(UpperNibble + 0x41 - 0x0A); if (LowerNibble < 0x0A) LcdWriteCharacter(LowerNibble + 0x30); if (LowerNibble >= 0x0A) LcdWriteCharacter(LowerNibble + 0x41 - 0x0A); } void LcdClearScreen() { for (int i=0; i<504; i++) LcdWriteData(0x00) ; } void LcdGoToXY(int x, int y) { LcdWriteCmd(0x80 | x); // COL LcdWriteCmd(0x40 | y); // ROW } void LcdBlink(int x, int y) { if(RotaryEncoderActivity == 0x00) // Encoder pressed or rotated { if(millis() - LcdMillis >= 1000) { LcdMillis = millis(); if(LcdState) { LcdState = !LcdState; LcdGoToXY(x,y); LcdWriteString(" "); } else { if(Frequency_Level) UpDateFreqLCD(); else UpDateLevelLCD(); LcdState = !LcdState; } } } } void UpDateFreqLCD() { LcdGoToXY(0,0); LcdWriteString("FREQUENCY"); LcdGoToXY(0,2); // 3 integers + 1 decimal point + 3 fractionals = 7 characters LcdWriteString(dtostrf(Frequency,7,3,string)); LcdWriteString(" MHz "); } void UpDateLevelLCD() { LcdGoToXY(0,4); LcdWriteString("LEVEL "); if (Level > 0) LcdWriteString("+"); if ((Level <= 0)&& (Level > -10)) LcdWriteString(" "); // 1 sign + 2 integers + 0 decimal point + 0 fractionals = 1+2 characters LcdWriteString(dtostrf(Level,2,0,string)); LcdWriteString(" dBm "); } void UpDateCursorPosition() { // CHANGE THE CURSORPOSITION if (Frequency_Level)// CHECK WHERE IT STANDS NOW(FREQUENCY OR LEVEL) { CursorPosition = CursorPosition + 1; // INCREAS CURSORPOSITION if ( CursorPosition > 5 ) CursorPosition = 0 ; } else CursorPosition = 2; switch(CursorPosition) { case 0: Addition = 100.0; // SET TENS OF MAGNITUDE(10^2) x = 0; y = 2; // COORDINATES FOR THE BLINKING FUNCTION break; case 1: Addition = 10.0; x = 6; y = 2; // break; case 2: Addition = 1; if(Frequency_Level){x = 12; y = 2;} else{x = 47; y = 4;} break; case 3: Addition = 0.1; x = 24; y = 2; break; case 4: Addition = 0.01; x = 30; y = 2; break; case 5: Addition = 0.001; x = 36; y = 2; break; } } void UpdateEncoder() { /* ¦ A ¦ B ¦ ----------------- ¦ 0 ¦ 0 ¦ ----------------- ¦¦ ¦ 0 ¦ 1 ¦ -1 ¦¦ ----------------- /\ \/ ¦ 1 ¦ 1 ¦ ¦¦ +1 ----------------- ¦¦ ¦ 1 ¦ 0 ¦ ----------------- ¦ 0 ¦ 0 ¦ ----------------- WHEN AB IS HIGH AND BY THE NEXT ROTATION B GOES HIGH, THEN THE ENCODER TURNED LEFT. IF B GOES LOW, THEN IT TURNED RIGTH. EXACTLY THE OPPOSITE IS TRUE, WHEN AB IS LOW. */ //DETECT THE ROTATION OF THE ENCODER AND SET SOME CONSTANTS switch(RotaryEncoderStatusOld) { // AB WERE LOW case 4: if ((RotaryEncoderStatus & B0000010) == 0x00) EncoderValue = EncoderValue + Addition; else EncoderValue = EncoderValue - Addition; // STOPS COUNTING IF THE VALUE IS BIGGER THEN MAX OR LOWER THAN MIN if (EncoderValue > Max) EncoderValue = maxNr; if (EncoderValue < Min) EncoderValue = minNr; break; // AB WERE HIGH case 14: if ((RotaryEncoderStatus & B0000010) == 0x00) EncoderValue = EncoderValue - Addition; else EncoderValue = EncoderValue + Addition; // STOPS COUNTING IF THE VALUE IS BIGGER THEN MAX OR LOWER THAN MIN if (EncoderValue > Max) EncoderValue = maxNr; if (EncoderValue < Min) EncoderValue = minNr; break; } if (Frequency_Level){Frequency = EncoderValue; maxNr = Frequency; minNr = Frequency;} else {Level = EncoderValue; maxNr = Level; minNr = Level; } } //SWITCH BETWEEN FREQUENCY AND LEVEL VALUE void SwitchFreqLevel() { // CHECK WHERE IT STANDS NOW Frequency_Level = !Frequency_Level; if (Frequency_Level) { //SET THE CONSTANTS FOR THE FREQUENCY EncoderValue = Frequency; Max = MaxFreq; Min = MinFreq; Addition = 1.0; CursorPosition = 1; UpDateCursorPosition(); UpDateLevelLCD(); } else { //SET THE CONSTANTS FOR THE ATTENTUATOR LEVEL EncoderValue = Level; Max = LevelMax; Min = LevelMin; Addition = 1.0; UpDateCursorPosition(); UpDateFreqLCD(); } } // CHECK ROTARY ENCODER (A1...A3) void CheckRotaryEncoder() { RotaryEncoderStatusOld = RotaryEncoderStatus ; RotaryEncoderStatus = PINC & B00001110 ; // PORT MANIPULATION FOR FAST READ RotaryEncoderActivity = RotaryEncoderActivity | (RotaryEncoderStatus ^ RotaryEncoderStatusOld) ; } void Si570SetFrequency(float Freq) { /* HSDIV ¦ N1 ¦ DIVIDER ¦ VCO_MIN ¦ VCO_MAX ¦ // VCO_MIN = 4850 MHz, VCO_MAX = 5670 MHz ------------------------------------------------------ 4 ¦ 6 ¦ 24 ¦ 202.08 ¦ 236.25 ¦ ------------------------------------------------------ 7 ¦ 4 ¦ 28 ¦ 173.21 ¦ 202.50 ¦ ------------------------------------------------------ 4 ¦ 8 ¦ 32 ¦ 151.56 ¦ 172.18 ¦ ------------------------------------------------------ 9 ¦ 4 ¦ 36 ¦ 134.72 ¦ 157.50 ¦ ------------------------------------------------------ 5 ¦ 8 ¦ 40 ¦ 121.25 ¦ 141.75 ¦ ------------------------------------------------------ 11 ¦ 4 ¦ 44 ¦ 110.23 ¦ 128.87 ¦ ------------------------------------------------------ // :1 4 ¦ 12 ¦ 48 ¦ 101.04 ¦ 118.12 ¦ ------------------------------------------------------ 7 ¦ 8 ¦ 56 ¦ 86.61 ¦ 101.25 ¦ ------------------------------------------------------ 4 ¦ 16 ¦ 64 ¦ 75.78 ¦ 88.59 ¦ ------------------------------------------------------ 9 ¦ 8 ¦ 72 ¦ 67.36 ¦ 78.75 ¦ ------------------------------------------------------ 5 ¦ 16 ¦ 80 ¦ 60.63 ¦ 70.875 ¦ ------------------------------------------------------ 11 ¦ 8 ¦ 88 ¦ 55.11 ¦ 64.43 ¦ ------------------------------------------------------ // :2 4 ¦ 24 ¦ 96 ¦ 50.52 ¦ 59.06 ¦ ------------------------------------------------------ 7 ¦ 16 ¦ 112 ¦ 43.30 ¦ 50.625 ¦ ------------------------------------------------------ 4 ¦ 32 ¦ 128 ¦ 37.89 ¦ 44.29 ¦ ------------------------------------------------------ 9 ¦ 16 ¦ 144 ¦ 33.68 ¦ 39.375 ¦ ------------------------------------------------------ 5 ¦ 32 ¦ 160 ¦ 30.31 ¦ 35.43 ¦ ------------------------------------------------------ 11 ¦ 16 ¦ 176 ¦ 27.56 ¦ 32.21 ¦ ------------------------------------------------------ // :4 4 ¦ 48 ¦ 192 ¦ 25.26 ¦ 29.53 ¦ ------------------------------------------------------ 7 ¦ 32 ¦ 224 ¦ 21.65 ¦ 25.31 ¦ ------------------------------------------------------ 4 ¦ 64 ¦ 256 ¦ 18.95 ¦ 22.14 ¦ ------------------------------------------------------ 9 ¦ 32 ¦ 288 ¦ 16.84 ¦ 19.68 ¦ ------------------------------------------------------ 5 ¦ 64 ¦ 320 ¦ 15.16 ¦ 17.71 ¦ ------------------------------------------------------ 11 ¦ 32 ¦ 352 ¦ 13.78 ¦ 16.10 ¦ ------------------------------------------------------ // :8 4 ¦ 96 ¦ 384 ¦ 12.63 ¦ 14.76 ¦ ------------------------------------------------------ 7 ¦ 64 ¦ 448 ¦ 10.83 ¦ 12.65 ¦ ------------------------------------------------------ 4 ¦ 128 ¦ 512 ¦ 9.47 ¦ 11.07 ¦ ------------------------------------------------------ 9 ¦ 64 ¦ 576 ¦ 8.42 ¦ 9.84 ¦ ------------------------------------------------------ 5 ¦ 128 ¦ 640 ¦ 7.58 ¦ 8.85 ¦ ------------------------------------------------------ 11 ¦ 64 ¦ 704 ¦ 6.89 ¦ 8.05 ¦ ------------------------------------------------------ // :16 THE VALUES IN THE TABLE ABOVE REPEAT ITSELF(236.25/2=118.12, 236.25/4=59.06 AND SO ON). THEREFOR WE JUST SAVED THE FIRST SIX HSDIV, N1 AND VCO_MAX VALUES IN AN ARRAY. FIRST, SET THE BLOCK(DIVIDER) AND THEN WE CAN CALCULATE HS_DIV AND N1 BY DIVIDING THE SAVED VALUES IN THE ARRAY BY THE BLOCK. */ int i=-1; Block = 1; if(Freq <= 115.0)Block = 2; if(Freq <= 58.0)Block = 4; if(Freq <= 28.0)Block = 8; if(Freq <= 14.0)Block = 16; do { i++; HS_DIVIDER = HSDIV[i]; N_DIVIDER = ((N1[i]*Block)); }while((VCO_Freq[i]/Block/Freq) <= 1.0); // BASIC FORMULA: Fout = (Fxtal * RFREQ) / (HS_DIV * N1), WHERE (Fxtal * RFREQ) MUST BE BETWEEN 4.85 AND 5.67 GHz RFREQ = Freq* HS_DIVIDER * N_DIVIDER / Crystal; // SPLIT RFREQ IN INTEGER(10BIT) AND FRACTIONAL(28BIT) PART RF_DIVIDER_INTEGER = int(RFREQ); RF_DIVIDER_FRACTIONAL = long(pow(2,28)*(RFREQ-RF_DIVIDER_INTEGER)); // CALCULATE N1, DATA SHEET : // The value for the N1 register can be calculated by taking the divider ratio minus one. // For example, to divide by 10,write 0001001 (9 decimal) to the N1 registers. N_DIVIDER = N_DIVIDER-1; Si570CommandToByte(); Si570sendData(); } void Si570CommandToByte() { /* ¦ 7 ¦ 6 ¦ 5 ¦ 4 ¦ 3 ¦ 2 ¦ 1 ¦ 0 ¦ ----------------------------------------------------------------------- SiR7 ¦ HS_DIV_INDEX[2:0] ¦ (N1-1)[6:2] ----------------------------------------------------------------------- SiR8 ¦ (N1-1)[1:0] ¦ RFREQ(INTEGER)[37:32] ----------------------------------------------------------------------- SiR9 ¦ RFREQ(INTEGER)[31:28] ¦ RFREQ(FRACTIONAL)[27:24] ----------------------------------------------------------------------- SiR10 ¦ RFREQ(FRACTIONAL)[23:16] ----------------------------------------------------------------------- SiR11 ¦ RFREQ(FRACTIONAL)[15:8] ----------------------------------------------------------------------- SiR12 ¦ RFREQ(FRACTIONAL)[7:0] ----------------------------------------------------------------------- SiReg ¦RST_REG¦ NEW ¦ FREEZ ¦ ¦ ¦ ¦ ¦RECALL ¦ 137 ¦ ¦ Freq ¦ M ¦ ¦ ¦ ¦ ¦ ¦ ----------------------------------------------------------------------- SiReg ¦ ¦ ¦ ¦ FREEZ ¦ ¦ ¦ ¦ ¦ 137 ¦ ¦ ¦ ¦ DCO ¦ ¦ ¦ ¦ ¦ ----------------------------------------------------------------------- */ // SET BYTES AS SEEN ABOVE SiR7 = (HS[HS_DIVIDER]<<5) + (N_DIVIDER>>2); SiR8 = (N_DIVIDER<<6) + (RF_DIVIDER_INTEGER>>4); SiR9 = (RF_DIVIDER_INTEGER<<4) + (RF_DIVIDER_FRACTIONAL>>24); SiR10 = (RF_DIVIDER_FRACTIONAL>>16); SiR11 = (RF_DIVIDER_FRACTIONAL>>8); SiR12 = (RF_DIVIDER_FRACTIONAL); } void Si570sendData() { Wire.beginTransmission(Si570ADDRESS); Wire.write(137); // WRITE THE BYTE ADRESS (REGISTER 137) Wire.write(0x10); // 0x10, FREEZ DCO Wire.endTransmission(); Wire.beginTransmission(Si570ADDRESS); Wire.write(7); // WRITE THE BYTE ADRESS (REGISTER 7) Wire.write(SiR7); // WRITE THE REGISTER 7-12 Wire.write(SiR8); Wire.write(SiR9); Wire.write(SiR10); Wire.write(SiR11); Wire.write(SiR12); Wire.endTransmission(); Wire.beginTransmission(Si570ADDRESS); Wire.write(137); // WRITE THE BYTE ADRESS (REGISTER 137) Wire.write(0x00); // 0x00, UNFREEZ DCO Wire.endTransmission(); Wire.beginTransmission(Si570ADDRESS); Wire.write(135); // WRITE THE BYTE ADRESS (REGISTER 135) Wire.write(0x40); //0x40, INFORM THE Si570 THAT THERE IS A NEW FREQUENCY Wire.endTransmission(); } void Si570readData() { Wire.beginTransmission(Si570ADDRESS); Wire.write(0x07); // WRITE THE BYTE ADRESS (REGISTER 7) Wire.endTransmission(); Wire.requestFrom(Si570ADDRESS,6); R7 = Wire.read(); // 0x07 R8 = Wire.read(); // 0x08 R9 = Wire.read(); // 0x09 R10 = Wire.read(); // 0x0A R11 = Wire.read(); // 0x0B R12 = Wire.read(); // 0x0C } void SetAttentuator(byte b) { /* ATTENTUATION ¦ C32 ¦ C16 ¦ C8 ¦ C4 ¦ C2 ¦ C1 ¦ --------------------------------------------------------------- LOSS,REFERENCE¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ --------------------------------------------------------------- 1 dB ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ --------------------------------------------------------------- 2 dB ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ --------------------------------------------------------------- 4 dB ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ 0 ¦ --------------------------------------------------------------- 8 dB ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ 0 ¦ 0 ¦ --------------------------------------------------------------- 16 dB ¦ 0 ¦ 1 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ --------------------------------------------------------------- 32 dB ¦ 1 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ --------------------------------------------------------------- 50 dB ¦ 1 ¦ 1 ¦ 0 ¦ 0 ¦ 1 ¦ 0 ¦ --------------------------------------------------------------- */ // CHECK IF WE ARE IN THE LEVEL MENU if(!Frequency_Level) { // CHANGE ATTENTUATER LEVEL FROM (-35 -> +15) TO (0 -> +50) b = ((-b)+15); // REVERS THE BYTE AND SET ATTENTUATOR(PORT MANIPULATION) PORTD = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; // Do not change pin 0 and 1(TX,RX) } } void SaveValues() { // CHECK FOR CHANGE OF ROTARY ENCODER if ( RotaryEncoderActivity > 0x00 ) { lastchange = millis(); laststate = true; } // CHECK IF LAST CHANGE OF ROTARY ENCODER > 20 SECONDS if(((millis()-lastchange)>20000)&& laststate) { // SAVE THE VALUES IN THE EEPROM if( EEPROM.get(0,FR) != Frequency )EEPROM.put(0,Frequency); if( EEPROM.get(10,FR) != Level )EEPROM.put(10,Level); laststate = false; } } /* void SerialProgramming() { char ch; long int temp; while (Serial.available()) { ch=(char)Serial.read(); if (((ch >= '0') && (ch <= '9')) || ((ch >= 'A') && (ch <= 'Z'))) inputcmd[cmdindex++]=ch; if (ch == '\n') { // parse command if its a newline inputcmd[cmdindex]=0; // terminate the string if ((temp=atol(inputcmd)) > 0) { if ((tempMinFreq)) Si570SetFrequency(temp); } cmdindex=0; // reset command line } } } */ void setup() { // LCD NOKIA 5110 pinMode(RST, OUTPUT); pinMode(CE, OUTPUT); pinMode(DC, OUTPUT); pinMode(DIN, OUTPUT); pinMode(CLK, OUTPUT); digitalWrite(RST, LOW); digitalWrite(RST, HIGH); LcdWriteCmd(0x21); // LCD extended commands LcdWriteCmd(0xB8); // set LCD Vop (contrast) LcdWriteCmd(0x04); // set temp coefficent LcdWriteCmd(0x14); // LCD bias mode 1:40 LcdWriteCmd(0x20); // LCD basic commands LcdWriteCmd(0x0C); // LCD normal video LcdClearScreen(); // Startup display LcdGoToXY(0,0); LcdWriteString("MICROMOD UNO"); LcdGoToXY(0,2); LcdWriteString("SOFTWARE V1.1"); LcdGoToXY(0,3); LcdWriteString("HARDWARE V1.0"); LcdGoToXY(0,4); LcdWriteString("29.09.2016"); delay(5000); // CHIP USED : SiLabs 570 CAC000121G // C: 3.3V CMOS // A: 50ppm TempStability // C: 10-160 MHz // We need to refer to register 07 - 12 Wire.begin(); // join i2c bus (address optional for master) Si570readData(); // Read the Register LcdClearScreen(); LcdGoToXY(0,0); LcdWriteString("REG. 07 : 0x"); LcdDisplay(R7); LcdGoToXY(0,1); LcdWriteString("REG. 08 : 0x"); LcdDisplay(R8); LcdGoToXY(0,2); LcdWriteString("REG. 09 : 0x"); LcdDisplay(R9); LcdGoToXY(0,3); LcdWriteString("REG. 10 : 0x"); LcdDisplay(R10); LcdGoToXY(0,4); LcdWriteString("REG. 11 : 0x"); LcdDisplay(R11); LcdGoToXY(0,5); LcdWriteString("REG. 12 : 0x"); LcdDisplay(R12); delay(10000); LcdClearScreen(); // ATENUATOR, SET ATTENUATOR TO MAX pinMode(ATT32, OUTPUT); digitalWrite(ATT32, LOW); pinMode(ATT16, OUTPUT); digitalWrite(ATT16, LOW); pinMode(ATT08, OUTPUT); digitalWrite(ATT08, LOW); pinMode(ATT04, OUTPUT); digitalWrite(ATT04, LOW); pinMode(ATT02, OUTPUT); digitalWrite(ATT02, LOW); pinMode(ATT01, OUTPUT); digitalWrite(ATT01, LOW); // THE ROTARY ENCODER: A1, A2, A3 pinMode(A1, INPUT); digitalWrite(A1,HIGH); // PULLUP pinMode(A2, INPUT); digitalWrite(A2,HIGH); pinMode(A3, INPUT); digitalWrite(A3,HIGH); // ENABLE INTERRUPT FOR PIN ... Timer1.initialize(1000); // EVERY 1 ms Timer1.attachInterrupt(CheckRotaryEncoder); RotaryEncoderStatus = PINC ; RotaryEncoderStatusOld = RotaryEncoderStatus ; RotaryEncoderActivity = 0x00; // Read EEPROM if(EEPROM.read(15) != 0) // Clear all by the first upload { for (int i = 0 ; i < EEPROM.length() ; i++) { EEPROM.write(i, 0); } EEPROM.put(0,Frequency); EEPROM.put(10,Level); } else { EEPROM.get(0,Frequency); EEPROM.get(10,Level); } Max = MaxFreq; Min = MinFreq; EncoderValue = Frequency; Addition = 0; // Set to saved values Si570SetFrequency(Frequency); SetAttentuator(Level); UpDateFreqLCD(); UpDateLevelLCD(); Serial.begin(9600); } void loop() { // EVALUATE KNOB PRESSED, BIT 3, TOGGLE if (RotaryEncoderActivity == 0x04) { // FALLING EDGE ONLY if (( RotaryEncoderStatus & B00000100 ) == 0x00) { currentmillis = millis(); EncoderState = true; } } // CHECK IF THE KNOB WAS PRESSED AND HOLDED FOR LONGER THAN 1.5 SECONDS.(PRESS AND HOLD) if ((( RotaryEncoderStatus & B00000100 ) == 0x00)&&(millis() - currentmillis >= 1500)&&EncoderState)// FALLING EDGE ONLY { // CHANGE BETWEEN FREQUENCY AND ATTENTUATOR LEVEL SwitchFreqLevel(); EncoderState = false; } //CHECK IF THE KNOB WAS PRESSED LONGER THAN 0.1 SECONDS.(SINGLE PRESS) if ((( RotaryEncoderStatus & B00000100 ) != 0x00)&&(millis() - currentmillis >= 0.1)&&EncoderState)// RISING EDGE ONLY { UpDateCursorPosition(); EncoderState = false; } // CHECK FOR CHANGE OF ROTARY ENCODER if ( RotaryEncoderActivity > 0x00 ) { // EVALUATE KNOB NOT PRESSED if (( RotaryEncoderStatus & B00000100 ) != 0x00) { UpdateEncoder(); UpDateFreqLCD(); UpDateLevelLCD(); Si570SetFrequency(Frequency); SetAttentuator(Level); } } SaveValues(); LcdBlink(x,y); RotaryEncoderActivity = 0 ; if(Addition == 0)Addition = 1; //SerialProgramming(); delay(1); } // ///////////////////////////////////////////////////////////// // END OF FILE. // /////////////////////////////////////////////////////////////