Categories
Statistics
Flag Counter
Since 08.08.2014
Counts only, if "DNT = disabled".

216.73.217.140
216.73.217.140
Info
Valid HTML 4.01 Transitional Creative Commons Lizenzvertrag
rss
เราจะทำแบบวิศวกรผู้ยิ่งใหญ่
We love the King
16. August 2026
YOUR OPINION     •••
average: 0.001,   n: 0

Rating




When using this form, your ip is stored in order to avoid multiple voting on the same website. That's it.
August 2026 เรา ❤ แม่
LIMITATIONS
Due to our Software License we must not allow to use the Target 3001 File for commercial use !

Favourites  Target 3001 Website
LMK61E2.php    29225 Bytes    04-03-2025 19:13:16


The LMK61E2 (TI) • Macromod VHF Synthesizer


A 10 ... 850 MHz (LVPECL) I2C programmeable Synthesizer



The LMK61E2 has almost the same pinout and form-factor as the widespread Si-570. But there is only one output divider and it looks, that this 10 ms freezing thing was also considered unnecessary. Let's have a closer look at that thing ...


LMK61E2 Demo Board

The LMK61E2 on the Shield using the LVPECL outputs ...





✈ Motivation and Circuit Description




This shield was designed to be able to compare it to the Si-570 (SiLabs) • Micromod RF Synthesizer Shield and to finally have a nice Synthesiser. We therefore put the same attenuator and lowpass on the shield. The external amplifier of the Si-570 was even integrated. As the LMK61E2 is very power-hungry, a step down converter reduces the dissipated heat.

As the Arduino/Genuino UNO is a 5 Volt system, we used two BSS183 to shift the levels of the SCL and SDA lines. An Si7661 generates -5V from the +5V to supply the attenuator, a MAAD-007086 which was chosen for its diy friendly form-factor. Last but not least is a GVA-81+ from Mini Circuits. It has a gain of 10 dB and delivers approx. 8 dBm at the upper end (850 MHz).




✈ What's inside the LMK61E2 ?




The "Ultra-Low Noise" is achieved with mainly two tricks. First the use of a low noise vco and second, the use of frequency dividers. As the minimum value is 5, this will lower the phase noise by at least 20 * log10 (5) = 14 dB. This is in the hp8640 class - just 60 dB cheaper.

LMK61E2-What's inside ?

Building blocks of the LMK61E2. Drawing courtesy of Texas Instruments.







✈ Performance




The device has been programmed to 100.000 MHz, + 7dBm in order to compare it to the Si570. Both measurements look identical !


Si570 spectrum
Si570
LMK61E2 spectrum
LMK61E2


Obviously we need some more sophisticated measurement gear ... like the E5052 :-)


Si570 Phase Noise
Si570
LMK61E2 Phase Noise
LMK61E2


Now the difference becomes obvious. Maybe SiLabs should not have left this capacitor away ???




✈ Arduino Sketch - The Code



Double click on code to select ...


/* ////////////////////////////////////////////////////////////////// 

ARDUINO/Genuino (UNO) LMK61E2 Evaluation Board - Macromod Synthesizer
https://www.changpuak.ch/electronics/LMK61E2.php
Software Version 2.0, USES TIMER INTERRUPT
24.01.2018 by ALEXANDER SSE FRANK
SOME ROUTINES ARE FROM JOËL STEINEMANN

////////////////////////////////////////////////////////////////// */

// LCD PINS (NOKIA5110)
#define RST 13
#define CE  12
#define DC  9
#define DIN  11
#define CLK  10
char string[8];

#include <EEPROM.h>
#include <Wire.h>
#include <stdlib.h>
#include "font.h";
#include "TimerOne.h"


// ///////////////////////////////////////////////////////////// 

// CONSTANTS FOR THE LMK61E2
const int LMK61E2ADR = 0x59 ;
const float MaxFreq = 890.0 ;
const float MinFreq = 10.0 ;
float Frequency = 100.000 ;
const float REF = 100.00000 ; // Doubler Enabled :-)
byte Reg[73] ;

// ///////////////////////////////////////////////////////////// 

//VARIABLES AND PIN DEFINITION FOR THE ATTENUATOR
const float LevelMin = -35 ;
const float LevelMax = 15 ;
int Level = 15 ;
const int ATT32 = 7;
const int ATT16 = 6;
const int ATT08 = 5;
const int ATT04 = 4;
const int ATT02 = 3;
const int ATT01 = 2;
// ///////////////////////////////////////////////////////////// 

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;

float FR;
// ///////////////////////////////////////////////////////////// 

// 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) ;
}  

/*
• FVCO = FREF x D x [(INT + NUM/DEN)] where
• FVCO: PLL/VCO Frequency (4.6 GHz to 5.6 GHz)
• FREF: 50 MHz reference input
• D: PLL input frequency doubler, 1=Disabled, 2=Enabled
• DIVIDER = INT + NUM/DEN
• INT: PLL feedback divider integer value (12 bits, 1 to 4095)
• NUM: PLL feedback divider fractional numerator value, 
• DEN: PLL feedback divider fractional denominator value
• freq = FVCO / OUTDIV
*/
void SetFrequency(float freq)
{
  unsigned int OUTDIV = (int)(5600 / freq ) ; // floor :-)
  float FVCO = freq * OUTDIV ;
  float DIVIDER = FVCO / REF ;
  unsigned int INT = (int)DIVIDER ;
  float REST = DIVIDER - INT ;
  unsigned int NUM = (int)(REST * 10000);
  unsigned int DEN = 10000 ;
    // The 9-bit Output Divider
  Reg[0x16] = (OUTDIV & 0x100) >> 8 ;
  Reg[0x17] = (OUTDIV & 0x0FF) ;
  // The 12-bit N integer divider value for PLL 
  Reg[0x19] = (INT & 0x0F00) >> 8 ;
  Reg[0x1A] = (INT & 0x00FF) ;
  // The 22-bit Fractional Divider Numerator
  Reg[0x1B] = (NUM & 0x03F0000) >> 16 ;
  Reg[0x1C] = (NUM & 0x000FF00) >> 8 ;
  Reg[0x1D] = (NUM & 0x0000FF) ;
  // The 22-bit Fractional Divider Denominator
  if (NUM == 0x00) 
  { 
    DEN = 0x01 ; 
    Reg[0x1E] = 0x00 ;
    Reg[0x1F] = 0x00 ;
    Reg[0x20] = 0x01 ;
  } 
  else 
  {
    Reg[0x1E] = (DEN & 0x03F0000) >> 16 ;
    Reg[0x1F] = (DEN & 0x000FF00) >> 8 ;
    Reg[0x20] = (DEN & 0x0000FF) ;
  }

  Wire.beginTransmission(LMK61E2ADR);
  Wire.write(0x10);
  Wire.write(Reg[0x10]);
  Wire.write(Reg[0x11]);
  Wire.endTransmission();
  Wire.beginTransmission(LMK61E2ADR);
  Wire.write(0x15);
  Wire.write(Reg[0x15]);
  Wire.write(Reg[0x16]);
  Wire.write(Reg[0x17]);
  Wire.write(Reg[0x18]);
  Wire.write(Reg[0x19]);
  Wire.endTransmission();
  Wire.beginTransmission(LMK61E2ADR);
  Wire.write(0x1A);
  Wire.write(Reg[0x1A]);
  Wire.write(Reg[0x1B]);
  Wire.write(Reg[0x1C]);
  Wire.write(Reg[0x1D]);
  Wire.write(Reg[0x1E]);
  Wire.write(Reg[0x1F]);
  Wire.endTransmission();
  Wire.beginTransmission(LMK61E2ADR);
  Wire.write(0x20);
  Wire.write(Reg[0x20]);
  Wire.write(Reg[0x21]);
  Wire.write(Reg[0x22]);
  Wire.write(Reg[0x23]);
  Wire.write(Reg[0x24]);
  Wire.write(Reg[0x25]);
  Wire.write(Reg[0x26]);
  Wire.write(Reg[0x27]);
  Wire.endTransmission();
  Wire.beginTransmission(LMK61E2ADR);
  Wire.write(0x48);
  Wire.write(Reg[0x48]);
  Wire.endTransmission();
}

void SerialHexOutput(byte value) 
{
   Serial.print("0x");
   if (value < 0x10) Serial.print("0");
   Serial.println(value,HEX);
}

void IDN() 
{
  Wire.beginTransmission(LMK61E2ADR);
  Wire.write(0x00);              
  Wire.endTransmission();  
  Wire.requestFrom(LMK61E2ADR,6);
  Reg[0] = Wire.read();       
  Reg[1] = Wire.read();       
  Reg[2] = Wire.read();      
  Reg[3] = Wire.read();      
  Reg[8] = Wire.read();         
  Reg[9] = Wire.read();            
  Serial.write("VNDRID R0: "); SerialHexOutput(Reg[0]);
  Serial.write("VNDRID R1: "); SerialHexOutput(Reg[1]);
  Serial.write("PRODID R2: "); SerialHexOutput(Reg[2]);
  Serial.write("REVID  R3: "); SerialHexOutput(Reg[3]);
  Serial.write("I2CADR R8: "); SerialHexOutput(Reg[8]);
  Serial.write("EEREV  R9: "); SerialHexOutput(Reg[9]);
}



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);
    if (b & 32) digitalWrite(ATT32, HIGH); else digitalWrite(ATT32, LOW);
    if (b & 16) digitalWrite(ATT16, HIGH); else digitalWrite(ATT16, LOW);
    if (b & 8)  digitalWrite(ATT08, HIGH); else digitalWrite(ATT08, LOW);
    if (b & 4)  digitalWrite(ATT04, HIGH); else digitalWrite(ATT04, LOW);
    if (b & 2)  digitalWrite(ATT02, HIGH); else digitalWrite(ATT02, LOW);
    if (b & 1)  digitalWrite(ATT01, HIGH); else digitalWrite(ATT01, LOW);
  }
}

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 ((temp<MaxFreq)&&(temp>MinFreq))
         SetFrequency(temp);
       }
      cmdindex=0; // reset command line      
    }
  }
}
*/

void setup() {
  
  Serial.begin(9600);
  Wire.begin();
  
  // 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("MACROMOD UNO");
  LcdGoToXY(0,2); LcdWriteString("SOFTWARE V1.1"); 
  LcdGoToXY(0,3); LcdWriteString("HARDWARE V2.0"); 
  LcdGoToXY(0,4); LcdWriteString("24.01.2018"); 
  delay(5000);
  
  LcdClearScreen();

  // INIT LMK61E2
  // REGISTERS LMK61E2 FOR 200 MHz
  Reg[0x10] = 0x00 ;  // XO_CAPCTRL_BY1
  Reg[0x11] = 0x80 ;  // XO_CAPCTRL_BY0
  // NO HAVE
  Reg[0x15] = 0x01 ;  // DIFFCTL
  Reg[0x16] = 0x00 ;  // OUTDIV_BY1
  Reg[0x17] = 0x17 ;  // OUTDIV_BY0
  // NO HAVE
  Reg[0x19] = 0x00 ;  // PLL_NDIV_BY1
  Reg[0x1A] = 0x2E ;  // PLL_NDIV_BY0
  Reg[0x1B] = 0x00 ;  // PLL_FRACNUM_BY2
  Reg[0x1C] = 0x00 ;  // PLL_FRACNUM_BY1
  Reg[0x1D] = 0x00 ;  // PLL_FRACNUM_BY0
  Reg[0x1E] = 0x00 ;  // PLL_FRACDEN_BY2
  Reg[0x1F] = 0x00 ;  // PLL_FRACDEN_BY1
  Reg[0x20] = 0x01 ;  // PLL_FRACDEN_BY0
  Reg[0x21] = 0x0F ;  // PLL_MASHCTRL
  Reg[0x22] = 0x28 ;  // PLL_CTRL0
  Reg[0x23] = 0x03 ;  // PLL_CTRL1
  Reg[0x24] = 0x04 ;  // PLL_LF_R2
  Reg[0x25] = 0x00 ;  // PLL_LF_C1
  Reg[0x26] = 0x00 ;  // PLL_LF_R3
  Reg[0x27] = 0x00 ;  // PLL_LF_C3
  // NO HAVE
  Reg[0x2A] = 0x00 ;  // PLL_CALCTRL
  // NO HAVE
  Reg[0x2F] = 0x00 ;  // NVMSRC
  Reg[0x30] = 0x00 ;  // NVMCNT
  Reg[0x31] = 0x10 ;  // NVMCTL
  Reg[0x32] = 0x00 ;  // NVMLCRC
  Reg[0x33] = 0x00 ;  // MEMADR
  Reg[0x34] = 0x00 ;  // NVMDAT
  Reg[0x35] = 0x00 ;  // RAMDAT
  // NO HAVE
  Reg[0x38] = 0x00 ;  // NVMUNLK
  // NO HAVE
  Reg[0x42] = 0x00 ;  // INT_LIVE 
  // NO HAVE
  Reg[0x48] = 0x02 ;  // SWRST
  

  
  // 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
  SetFrequency(Frequency);
  SetAttentuator(Level);
  UpDateFreqLCD();
  UpDateLevelLCD();

}
 
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();     
      SetFrequency(Frequency); 
      SetAttentuator(Level);
    }
  }
  
  SaveValues();
  LcdBlink(x,y);
  RotaryEncoderActivity = 0 ;
  if(Addition == 0)Addition = 1;
  //SerialProgramming();
  delay(1);
        
}
// ///////////////////////////////////////////////////////////// 
// END OF FILE.
// ///////////////////////////////////////////////////////////// 





✈ Downloads







LMK61E2 Demo Board

Thank you for scrolling down :-)
And yes, 107.6 MHz is the frequency of RADIO BASILISK





✈ Share your thoughts



The webmaster does not read these comments regularely. Urgent questions should be send via email. Ads or links to completely uncorrelated things will be removed.




 
t1 = 7339 d

t2 = 279 ms

★ ★ ★  Copyright © 2006 - 2026 by changpuak.ch  ★ ★ ★

Impressum