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

Your IP is 44.213.60.33
ec2-44-213-60-33.compute-1.a
Info
Valid HTML 4.01 Transitional Creative Commons Lizenzvertrag
rss
เราจะทำแบบวิศวกรผู้ยิ่งใหญ่
We love the King
23. July 2024
Your valuable opinion :
4.5 stars

Avg. 4.50 from 14 votes.



Amy Winehouse, 14.09.1983 - 23.07.2011
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    06-07-2024 22:08:01


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.


Your Browser says that you allow tracking. Mayst we suggest that you check that DNT thing ?

 
t1 = 6585 d

t2 = 219 ms

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

Impressum