2016年8月1日月曜日

AD9850 TFT DDS VFO

特徴は、TFT画面を使い、Ucglibライブラリを使った事による繊細表示である。オリジナルJA2NKD/1スケッチをUNO対応版に変更し、メモリ機能を追加した。機能追加は、スイッチの増設する事なく行ったので、改造前/改造後の変化を感じないであろう。メモリ機能は、ModeまたはRIT操作で、周波数とSTEPをEEPROMに保存。自動メモリ保存してない。 

AD9850を実装した基板。 

部品を実装した基板。0Ω(2本)は、ジャンパー線。

TFT接続用コネクタは、ピンヘッダにソケットをハンダ付けし、TFT取付高さを調整した。


回路図 


基板サイズ 70 × 55  














Program

/////////////////////////////////////////////////////////////////////////////
//     DDS VFO Ver2.03        
//                         JA2NKD 2016.07.19    
//     Aruduino IDE 1.6.5
//     Arduino nano only
//    
//   <Rotary.h>    https://github.com/brianlow/Rotary
//   <EF_AD9850.h> http://forum.arduino.cc/index.php?topic=77483.0
//   "Ucglib.h"    https://github.com/olikraus/ucglib
//
//----------------------------------------------------------------------------
//   Added      EEPROM function             2016/7/31 JA2GQP
//
///////////////////////////////////////////////////////////////////////////////

// Library include
#include <SPI.h>
#include <Rotary.h>
#include <EEPROM.h>
//#include <EF_AD9850.h>                      // <JA2GQP>
#include "Ucglib.h"


//----------   I/O setting  ---------------

/////////////////////
//  Hardware SPI Pins:
//  Arduino nano sclk=13, data=11
/////////////////////

const byte   __CS = 10;
const byte   __DC = 9;
const byte   __RST = 8;

const byte  W_CLK = A0;                     // DIO7(nano) <JA2GQP>
const byte  FQ_UD = A1;                     // DIO6(nano) <JA2GQP>
const byte  DATA = A2;                      // DIO5(nano) <JA2GQP>

const byte modeout1=7;                      // A0(nano)   <JA2GQP>
const byte modeout2=12;                     // A1(nano)   <JA2GQP>

const byte modesw=6;                        // A2(nano)   <JA2GQP>
const byte stepsw=4;                        // A3(nano)   <JA2GQP>
const byte ritsw=5;                         // A4(nano)   <JA2GQP>
const byte txsw=A3;                         // A5(nano)   <JA2GQP>
const byte s_meter=A5;                      // A6(nano)   <JA2GQP>
const byte t_meter=A4;                      // A7(nano)   <JA2GQP>

/////////////////////                       <JA2GQP>
// DDS parameter
/////////////////////

const unsigned long  DDS_CLK = 125000000L; // AD9850 Clock
const unsigned long  TWO_E32 = 4294967295L;// 2^32
const byte  DDS_CMD = B00000000;           // AD9850 Command

//----------  EEPROM Memory Address   ---------- <JA2GQP>

const byte  Frq_Eep = 0x00;                // Frequency(4byte*4)
const byte  Stp_Eep = 0x10;                // STEP(4byte*4)
const byte  Chn_Eep = 0x20;                // Channel(1byte*1)
const byte  Mode_Eep = 0x22;               // Mode(1byte*1)
const byte  Eep_Int = 0x2e;                // Eep Init(1byte*1)

const byte  Max_Chn = 4;                   // Max Channel(4ch)
const byte  Int_End = 73;                  // Initial end code

//----------- Default Value -------------------- <JA2GQP>

const long  DEF_FRQ = 7100000L;            // Init Frequency
const long  DEF_STP = 100L;                // Init STEP
const byte  DEF_Mode = 0;                  // 0=LSB 1=USB 2=CW 3=AM

//----------  Encorder Pin Assign(INT)  --------

  Rotary r=Rotary(2,3);

//----------  TFT Ucglib Assign --------

Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);
 
//----------  Memory Assign  --------------------------------

long int freq =DEF_FRQ;                    // <JA2GQP>
long int freqmax=7200000;
long int freqmin=7000000;
long int freqold=0;
long int freqrit=0;
String freqt=String(freq);
long int ifshift = 0;
long int ifshiftLSB =10698500;
long int ifshiftUSB =10701500;
long int ifshiftCW =10699200;
long int ifshiftAM=10700000;
long int txshiftLSB=10698500;
long int txshiftUSB=10701500;
long int txshiftCW=10700000;
long int txshiftAM=10700000;
long int ddsfreq = 0;
char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1;
int ddsstep=2;
int rit=0;
int fstep=DEF_STP;                          // <JA2GQP>
int fmode;
int fmodeold=1;
int flagrit=0;
int fritold=0;
int flagmode=0;
int smeterval1=0;
int tmeterval=0;
byte Byt_Chn;                             // Channel SW <JA2GQP>
byte Byt_Chnb;                            // Channel SW Old <JA2GQP>
 
//----------  Initialization  Program  ----------------------

void setup() {
  delay(100);
  ucg.begin(UCG_FONT_MODE_TRANSPARENT);
 //ucg.begin(UCG_FONT_MODE_SOLID);
  ucg.clearScreen();
  ucg.setRotate90();

  pinMode (stepsw,INPUT_PULLUP);
  pinMode (ritsw,INPUT_PULLUP);
  pinMode(txsw,INPUT_PULLUP);
  pinMode(modesw,INPUT_PULLUP);
  pinMode(modeout1,OUTPUT);
  pinMode(modeout2,OUTPUT);

  PCICR |=(1<<PCIE2);
  PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
  sei();

  pinMode(FQ_UD,OUTPUT);                    
  pinMode(W_CLK,OUTPUT);
  pinMode(DATA,OUTPUT);

  screen01();
 
  if(EEPROM.read(Eep_Int) != Int_End){        // Eep initialaz <JA2GQP>
    delay(10);
    Fnc_Eep_Int();
  }

  Byt_Chn = EEPROM.read(Chn_Eep);            // Channel     <JA2GQP>
  Byt_Chnb = Byt_Chn;                         //             <JA2GQP>
  Fnc_Eep_Rd();                               // EEPROM Read <JA2GQP>
  modeset();                                  // modeset * 4 <JA2GQP>
  modeset();
  modeset();
  modeset();
 
  steplcd();
  freqt=String(freq);
  freqlcd();
 }

//----------  Main program  ---------------------------------

void loop() {
  if (digitalRead(stepsw)==LOW){setstep();}
  if (digitalRead(modesw)==LOW){modeset();}
  if (digitalRead(ritsw)==LOW){setrit();Fnc_Eep_Wt(Byt_Chn);}  // <JA2GQP>
  if (digitalRead(txsw)==LOW){txset();}

    if(Byt_Chnb != Byt_Chn){                 // CH SW OLD != NEW? <JA2GQP>
      Fnc_Eep_Wt(Byt_Chnb);
      Byt_Chnb = Byt_Chn;
      Fnc_Eep_Rd();
      steplcd();
    }
       
  if (flagrit==1){
    if (freqrit == fritold){
      smeter();
    }  

    if (freqrit!=fritold){
      ddswrite();
      ritlcd();
      fritold=freqrit;
    }
  }
  else{
    if (freq == freqold){
        smeter();
    }
//  ddsfreq=freq+ifshift;
    ddswrite();
    freqt=String(freq);
    freqlcd();
    freqold=freq;
  }
}

//---------- Function Eeprom Initialization ------------  <JA2GQP>

void Fnc_Eep_Int(){
  int i;

  for (i=0;i<48;i++)                               // 0 clear(48byte)
    EEPROM.write(i, 0);

  for(i=0;i<Max_Chn;i++){
    Fnc_Eep_Sav4(DEF_FRQ,Frq_Eep+i*4);            // Frequency(7.10MHz)
    Fnc_Eep_Sav4(DEF_STP,Stp_Eep+i*4);            // Step(100Hz)
  }

  EEPROM.write(Chn_Eep,0);
  EEPROM.write(Mode_Eep,DEF_Mode);
  EEPROM.write(Eep_Int,Int_End);                 // Init end set(73)
}

//----------  Function EEPROM Read  ---------             <JA2GQP>

void Fnc_Eep_Rd(){
  if((0 <= Byt_Chn) && (Byt_Chn < Max_Chn))
    freq = Fnc_Eep_Lod4(Frq_Eep+Byt_Chn*4);
  else{
    freq = Fnc_Eep_Lod4(Frq_Eep+0);
    Byt_Chn = 0;
  }

  if((0 <= Byt_Chn) && (Byt_Chn < Max_Chn))
    fstep = Fnc_Eep_Lod4(Stp_Eep+Byt_Chn*4);
  else
    fstep = Fnc_Eep_Lod4(Stp_Eep+0);
   
  fmode = EEPROM.read(Mode_Eep);
}

//----------  Function EEPROM Write  ------------------- <JA2GQP>

void Fnc_Eep_Wt(byte chn){
  if((0 <= chn) && (chn < Max_Chn)){
    Fnc_Eep_Sav4(freq,Frq_Eep+chn*4);
    Fnc_Eep_Sav4(fstep,Stp_Eep+chn*4);
  }
 
  EEPROM.write(Chn_Eep,Byt_Chn);
  EEPROM.write(Mode_Eep,fmode);
}

//----------  Function Save EEPROM 4byte  --------       <JA2GQP>

void Fnc_Eep_Sav4(long value,int address){
  address += 3;
  for(int i = 0;i < 4;i++){
    byte toSave = value & 0xFF;
    if(EEPROM.read(address) != toSave){
      EEPROM.write(address,toSave);
      }
    value = value >> 8;
    address--;
  }
}

//----------  Function Load EEPROM 4byte  ---------       <JA2GQP>

long Fnc_Eep_Lod4(int address){
  long value = 0;
  for(int i = 0;i < 4;i++){
    value = value | EEPROM.read(address);
    if( i < 3){
      value = value << 8;
      address++;
      }
  }
  return value;
}

//----------  Function DDS set  ---------------           <JA2GQP>

void Fnc_Dds(double frquency){
  unsigned long wrk = frquency * TWO_E32 / DDS_CLK;
 
  digitalWrite(FQ_UD,LOW);

  shiftOut(DATA,W_CLK,LSBFIRST,wrk);
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 8));
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 16));
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 24));
  shiftOut(DATA,W_CLK,LSBFIRST,DDS_CMD);   // AD9850 command

  digitalWrite(FQ_UD,HIGH);
}

//---------- S-meter --------------------------

void smeter(){
 smeterval1=analogRead(s_meter);
 smeterval1=smeterval1/50;
 if (smeterval1>15){smeterval1=15;}
  int sx1=sx1+(smeterval1*17);
  sx1=sx1+41;
  int sx2=0;
  sx2=sx2+(40+((15-smeterval1)*17));
  ucg.setFont(ucg_font_fub35_tr);
  ucg.setColor(0,0,0);
  ucg.drawBox(sx1,180,sx2,16);
  ucg.setPrintPos(40,200);
  for(int i=1;i<=smeterval1;i++){
    if (i<=9){
      ucg.setColor(0,255,255);
      ucg.print("-");
    }
    else{
      ucg.setColor(255,0,0);
      ucg.print("-");
    }
  }
}

//---------- Transmission Power meter ------------------

void tmeter(){
  ucg.setColor(0,0,0);
 ucg.drawBox(41,180,270,16);
 tmeterval=analogRead(t_meter);
 tmeterval=tmeterval/50;
 if (tmeterval>15){tmeterval=15;}
  int sx1=sx1+(tmeterval*17);
  sx1=sx1+41;
  int sx2=0;
  sx2=sx2+(40+((15-tmeterval)*17));
  ucg.setFont(ucg_font_fub35_tr);
  ucg.setColor(0,0,0);
  ucg.drawBox(sx1,145,sx2,16);
  ucg.setPrintPos(40,165);
  for(int i=1;i<=tmeterval;i++){
    if (i<=9){
      ucg.setColor(250,80,0);
      ucg.print("-");
    }
    else{
      ucg.setColor(250,0,0);
      ucg.print("-");
    }
  }
}

//---------- Encoder Interrupt -----------------------

ISR(PCINT2_vect) {
  if (flagrit==1){
  unsigned char result = r.process();
    if(result) {
      if(result == DIR_CW){
        freqrit=freqrit+fstep;
        if (freqrit>=10000){
          freqrit=10000;
        }
     }
    else{
        freqrit=freqrit-fstep;
        if (freqrit<=-10000){
          freqrit=-10000;
        }
    }
 //   ddswrite();
    }
  }
 
  else{
    unsigned char result = r.process();
      if(result) {
        if(result == DIR_CW){
          freq=freq+fstep;
          if (freq>=freqmax){freq=freqmax;}
        }
        else{
          freq=freq-fstep;
          if (freq<=freqmin){freq=freqmin;}
        }
     }
  }
 
}

//------------ On Air -----------------------------

void txset(){
  noInterrupts();
    if (flagmode==0){ddsfreq=freq+txshiftLSB;}
    if (flagmode==1){ddsfreq=freq+txshiftUSB;}
    if (flagmode==2){ddsfreq=freq+txshiftCW;}
    if (flagmode==3){ddsfreq=freq+txshiftAM;}
//    AD9850.wr_serial(0x00,ddsfreq);
   
    ucg.setPrintPos(140,140);
    ucg.setFont(ucg_font_fub17_tr);
    ucg.setColor(255,0,0);
    ucg.print("ON AIR");
    while(digitalRead(txsw) == LOW){
      tmeter();
    }
    ucg.setColor(0,0,0);
    ucg.drawBox(30,120,250,30);
    ddswrite();
    ucg.drawBox(41,145,270,16);
    interrupts();
  }

//------------- Mode change(LSB-USB-CW-AM) ------------

void modeset(){
  ucg.setFont(ucg_font_fub17_tr);
//  if (fmode==0){                            // <JA2GQP>
  if (fmode==1){                              // <JA2GQP>
    ifshift=ifshiftUSB;
    ucg.setColor(255,255,0);
    ucg.setPrintPos(82,82);
    ucg.print("USB");
    ucg.setPrintPos(12,82);
    ucg.setColor(0,0,0);
    ucg.print("LSB");  
    digitalWrite(modeout1,HIGH);
    digitalWrite(modeout2,LOW);
  }

//  if(fmode==1){                            // <JA2GQP>
  if(fmode==2){                              // <JA2GQP>
    ifshift=ifshiftCW;
    ucg.setPrintPos(12,112);
    ucg.setColor(255,255,0);
    ucg.print("C W");
    ucg.setPrintPos(82,82);
    ucg.setColor(0,0,0);
    ucg.print("USB");
    digitalWrite(modeout1,LOW);
    digitalWrite(modeout2,HIGH);
  }

//  if (fmode==2){                            // <JA2GQP>
  if (fmode==3){                              // <JA2GQP>
    ifshift=ifshiftAM;
    ucg.setPrintPos(82,112);
    ucg.setColor(255,255,0);
    ucg.print("A M");
    ucg.setColor(0,0,0);      
    ucg.setPrintPos(12,112);
    ucg.print("C W");
    digitalWrite(modeout1,HIGH);
    digitalWrite(modeout2,HIGH);
    }

//  if (fmode==3){                            // <JA2GQP>
  if (fmode==0){                              // <JA2GQP>
    ifshift=ifshiftLSB;
    ucg.setPrintPos(12,82);
    ucg.setColor(255,255,0);
    ucg.print("LSB");
    ucg.setPrintPos(82,112);
    ucg.setColor(0,0,0);
    ucg.print("A M");
    digitalWrite(modeout1,LOW);
    digitalWrite(modeout2,LOW);
  }

  fmode=fmode+1;

  Byt_Chn++;                                // <JA2GQP>
  if(Byt_Chn > 3)              
    Byt_Chn = 0;

  if (fmode==4){fmode=0;}
  ddswrite();
  while(digitalRead(modesw) == LOW);
}

//------------ Rit SET ------------------------------

void setrit(){
  if(flagrit==0){
    flagrit=1;
    ucg.setFont(ucg_font_fub11_tr);
    ucg.setPrintPos(190,110);
    ucg.setColor(255,0,0);
    ucg.print("RIT");
//    freqrit=0;
    ritlcd();
  }
  else {
    flagrit=0;
    ddsfreq=freq+ifshift;
//    AD9850.wr_serial(0x00,ddsfreq);       // <JA2GQP>
    Fnc_Dds(ddsfreq);                       // DDS Out <JA2GQP>
    freqt=String(freq);
    ucg.setFont(ucg_font_fub11_tr);
    ucg.setPrintPos(190,110);
    ucg.setColor(255,255,255);
    ucg.print("RIT");
    ucg.setColor(0,0,0);
    ucg.drawRBox(222,92,91,21,3);
    freqrit=0;
  }
  while(digitalRead(ritsw) == LOW);
}

//----------- Rit screen ----------------------

void ritlcd(){
  noInterrupts();
  ucg.setColor(0,0,0);
  ucg.drawBox(222,92,91,21);
  ucg.setFont(ucg_font_fub17_tr);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(230,110);
  ucg.print(freqrit);
  interrupts();
}

//-------------- encorder frequency step set -----------

void setstep(){
  noInterrupts();
  if (fstep==10000){
    fstep=10;
  }
  else{
    fstep=fstep * 10;
  }

 steplcd();
 while(digitalRead(stepsw) == LOW);
 interrupts();
}

//------------- Step Screen ---------------------------

void steplcd(){
  ucg.setColor(0,0,0);
  ucg.drawRBox(221,61,93,23,3);
  ucg.setFont(ucg_font_fub17_tr);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(220,80);
  if (fstep==10){ucg.print("    10Hz");}
  if (fstep==100){ucg.print("   100Hz");}
  if (fstep==1000){ucg.print("    1KHz");}
  if (fstep==10000){ucg.print("  10KHz");}
}

//----------- Main frequency screen -------------------

void freqlcd(){
  ucg.setFont(ucg_font_fub35_tn);
  int mojisuu=(freqt.length());
/*
  ucg.setPrintPos(19,45);
  if(freq>=100000000){
    if(f100m !=(freqt.charAt(0))){
      ucg.setColor(0,0,0);
      ucg.drawBox(19,9,28,36);
      ucg .setPrintPos(19,45);
      ucg.setColor(0,255,0);
      ucg.print(freqt.charAt(0));
      f100m = (freqt.charAt(0));
    }
  }

   if(freq<100000000){
    ucg.setColor(0,0,0);
    ucg.drawBox(19,9,28,36);
       }
   if (f10m !=(freqt.charAt(mojisuu-8))){
    ucg.setColor(0,0,0);
    ucg.drawBox(47,9,28,36);
    ucg .setPrintPos(47,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-8));
    f10m = (freqt.charAt(mojisuu-8));
   }

   if(freq<10000000){
     ucg.setColor(0,0,0);
    ucg.drawBox(47,9,28,36);
     }
   if(fmega !=(freqt.charAt(mojisuu-7))){
    ucg.setColor(0,0,0);
    ucg.drawBox(75,9,28,36);
    ucg .setPrintPos(75,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-7));  
    fmega  = (freqt.charAt(mojisuu-7));
   }

  if(freq>=1000000){
    ucg.setPrintPos(103,45);
    ucg.setColor(0,255,0);
    ucg.print(".");
  }
*/
  if(freq<1000000){
    ucg.setColor(0,0,0);
    ucg.drawBox(103,9,15,36);
    }
  if(f100k !=(freqt.charAt(mojisuu-6))){
    ucg.setColor(0,0,0);
    ucg.drawBox(118,9,28,36);
    ucg.setPrintPos(118,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-6));  
    f100k = (freqt.charAt(mojisuu-6));
  }
 
  if(freq<100000){
    ucg.setColor(0,0,0);
    ucg.drawBox(118,9,28,36);
  }
  if(f10k !=(freqt.charAt(mojisuu-5))){
    ucg.setColor(0,0,0);
    ucg.drawBox(146,9,28,36);
    ucg.setPrintPos(146,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-5));  
    f10k = (freqt.charAt(mojisuu-5));
  }
 
  if(freq<10000){
    ucg.setColor(0,0,0);
    ucg.drawBox(146,9,28,36);    
    }
  if(f1k !=(freqt.charAt(mojisuu-4))){
    ucg.setColor(0,0,0);
    ucg.drawBox(174,9,28,36);
    ucg.setPrintPos(174,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-4));      
    f1k  = (freqt.charAt(mojisuu-4));
  }
 
  if(freq>=1000){
    ucg.setPrintPos(202,45);
    ucg.setColor(0,255,0);
    ucg.print(".");
  }

  if(freq<1000){
    ucg.setColor(0,0,0);
    ucg.drawBox(202,9,15,36);      
    }
  if(f100 !=(freqt.charAt(mojisuu-3))){
    ucg.setColor(0,0,0);
    ucg.drawBox(217,9,28,36);
    ucg.setPrintPos(217,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-3));
    f100 = (freqt.charAt(mojisuu-3));
  }

  if(freq<100){
    ucg.setColor(0,0,0);
    ucg.drawBox(217,9,28,36);    
  }
  if(f10 !=(freqt.charAt(mojisuu-2))){
    ucg.setColor(0,0,0);
    ucg.drawBox(245,9,28,36);
    ucg.setPrintPos(245,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-2));
    f10 = (freqt.charAt(mojisuu-2));
  }
/*
  if(freq<10){
    ucg.setColor(0,0,0);
    ucg.drawBox(245,9,28,36);  
     }
  if(f1 !=(freqt.charAt(mojisuu-1))){
    ucg.setColor(0,0,0);
    ucg.drawBox(273,9,28,36);
    ucg.setPrintPos(273,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-1));    
    f1  = (freqt.charAt(mojisuu-1));  
  }
*/
}

//----------- Basic Screen -------------------------

void screen01(){
  ucg.setColor(255,255,255);
  ucg.drawRFrame(0,0,320,55,5);
  ucg.drawRFrame(1,1,318,53,5);
  ucg.setColor(50,50,50);
  ucg.drawRBox(5,60,60,25,3);
  ucg.drawRBox(75,60,60,25,3);
  ucg.drawRBox(5,90,60,25,3);
  ucg.drawRBox(75,90,60,25,3);
  ucg.setFont(ucg_font_fub17_tr);
  ucg.setPrintPos(12,82);
  ucg.setColor(0,0,0);
  ucg.print("LSB");
  ucg.setPrintPos(82,82);
  ucg.print("USB");
  ucg.setPrintPos(12,112);
  ucg.print("C W");
  ucg.setPrintPos(82,112);
  ucg.print("A M");
  ucg.setColor(255,255,255);
  ucg.drawRFrame(220,60,95,25,3);
  ucg.drawRFrame(220,90,95,25,3);
  ucg.setColor(100,100,100);
  ucg.setPrintPos(15,200);
  ucg.print("S:");
  ucg.setPrintPos(15,165);
  ucg.print("P:");
  ucg.setFont(ucg_font_fub11_tr);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(175,80);
  ucg.print("STEP");
  ucg.setPrintPos(190,110);
  ucg.setColor(255,255,255);
  ucg.print("RIT");
  ucg.setColor(100,100,100);
  ucg.setPrintPos(40,210);
  ucg.print("1-----3-------6-------9---Over--------");
  ucg.setPrintPos(40,175);
  ucg.print("1-----3----5------------10--------------");
  ucg.setPrintPos(10,230);
  ucg.setColor(235,0,200);
//  ucg.print(" Home Blew DDS-VFO Ver2.0 JA2NKD");    // <JA2GQP>
  ucg.print  ("Sketch of JA2NKD.JA2GQP added.");      // <JA2GQP>
  ucg.setFont(ucg_font_fub35_tr);
    ucg .setPrintPos(75,45);
    ucg.setColor(0,255,0);
    ucg.print("7");  
    ucg.setPrintPos(103,45);
    ucg.print(".");
    ucg.setPrintPos(273,45);
    ucg.print("0");  
}

//--------------- DDS Write -------------------------------

void ddswrite(){
//  if (flagmode==0){(ifshift=ifshiftLSB);}
//  if (flagmode==1){(ifshift=ifshiftCW);}

  if (flagrit==0){
    ddsfreq=freq+ifshift;
//    AD9850.wr_serial(0x00,ddsfreq);               // <JA2GQP>
    Fnc_Dds(ddsfreq);                               // DDS out <JA2GQP>
  }

  if(flagrit==1){
    ddsfreq=freq+ifshift+freqrit;
//    AD9850.wr_serial(0x00,ddsfreq);              // <JA2GQP>
    Fnc_Dds(ddsfreq);                              // DDS out <JA2GQP>
  }
 
}








    

2016年7月16日土曜日

Arduino AD9850 DDS VFO Ver.1.2

 Arduino AD9850 DDS VFOを作ってから約2年経過する。現在も、多くの方からアクセスがあるが、機能追加する事にした。初版(2014/2/28)のPCBをそのまま流用し、H/Wはスイッチ周りの変更のみに留めた。固有要素であるIF周波数、Offset周波数、VFOモードは、EEPに保存し、読込/書込み出来る様にした。RIT/SPLIT動作も見直しを行った。
また、自動Mode(LSB,USB,CW) 切替方式を採用。操作説明を含む関連資料は、JA2GQP's Download site
Arduino AD9850 DDSフォルダにアップロードしてある。

 

回路図である。 チャンネル切替をロータリSWからプッシュSWに変更し、ENT SWを追加。

Program

スケッチは、Arduino IDE1.6.9で開発したが、1.0.6で動作する事を確認している。

//////////////////////////////////////////////////////////////////////
//  AD9850 DDS VFO Premixed type program ver.1.2
//
//    Copyright(C)2014-2016.JA2GQP.All rights reserved.
//
//                                                  2016/7/16
//                                                  JA2GQP
//--------------------------------------------------------------------
//  Function
//    1.RIT Operation(-50kHZ to 50kHZ)
//    2.STEP(1M,100k,10k,1k,100,10)
//    3.Memory Operation is Push ENT
//      (Frequency and Step)
//    4.Protection Operation At The Time Of Transmission
//    5.Channel Memory(0-9ch)
//    6.Split Operation
//--------------------------------------------------------------------
//  Library
//  http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
//
//////////////////////////////////////////////////////////////////////

#include <LiquidCrystal.h>
#include <rotary.h>
#include <EEPROM.h>

//----------  LCD Pin Assign  ------------------

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);   // RS,R/W,DB4,DB5,DB6,DB7

//----------  Define Constant Value   ----------

////////////////////////////////
// I/O assign
////////////////////////////////
const byte  ENC_A = 2;                     // Encorder A
const byte  ENC_B = 3;                     // Encoeder B
const byte  SW_STEP = 4;                 // STEP Sw
const byte  SW_RIT = 5;                    // RIT Sw
const byte  SW_SPLIT = 6;                // SPLIT Sw
const byte  SW_TX = 7;                     // TX Sw
const byte  W_CLK = 14;                   // DIO14(A0)
const byte  FQ_UD = 15;                   // DIO15(A1)
const byte  DATA = 16;                    // DIO16(A2)
const byte  SW_CH = 17;                   // DIO17(A3)
const byte  SW_ENT = 18;                  // ENT SW

////////////////////////////////
// default value
////////////////////////////////
const long DEF_LSB = -1500L;           // LSB Offset(IF-1500Hz)
const long DEF_USB = 1500L;            // USB Offset(IF+1500Hz)
const long DEF_CW  = -600L;             // CW Offset(IF-600Hz)
const long DEF_IF  = 10700000L;         // 10.7000MHz

const long  DEF_VFO  = 3;                 // Vfo Mode(TR+IF)
const long  DEF_FRQ = 7050000L;      // Init Frequency
const long  DEF_STP = 1000L;            // Init STEP

////////////////////////////////
// Limited range
////////////////////////////////
const long  LW_FRQ = 0L;                   // Frequency Lower Limit
const long  HI_FRQ = 30000000L;         //           Upper Limit

const long  LW_VFO80 = 3500000L;      // 3.5MHz Lower
const long  MI_VFO80 = 3535000L;      //        Middle
const long  HI_VFO80 = 3575000L;       //        Upper
const long  LW_VFO40 = 7000000L;      // 7MHz   Lower
const long  MI_VFO40 = 7045000L;       //        Middle
const long  HI_VFO40 = 7200000L;       //        Upper
const long  LW_VFO20 = 14000000L;    // 14MHz  Lower
const long  MI_VFO20 = 14100000L;     //        Middle
const long  HI_VFO20 = 14350000L;     //        Upper
const long  LW_VFO15 = 21000000L;     // 21MHz  Lower
const long  MI_VFO15 = 21150000L;      //        Middle
const long  HI_VFO15 = 21450000L;      //        Upper
const long  LW_VFO10 = 28000000L;     // 28MHz  Lower
const long  MI_VFO10 = 28200000L;      //        Middle
const long  HI_VFO10 = 29000000L;       //        Upper

const long  LW_OFT = -10000L;            // Offset Lower Limit
const long  HI_OFT = 10000L;               //        Upper Limit

const long  LW_RIT = -50000L;             // RIT Lower Limit
const long  HI_RIT = 50000L;                // RIT Upper Limit

////////////////////////////////
// DDS parameter
////////////////////////////////
const unsigned long  DDS_CLK = 125000000L; // AD9850 Clock
const unsigned long  TWO_E32 = 4294967295L;// 2^32
const byte  DDS_CMD = B00000000;           // AD9850 Command

////////////////////////////////
// etc
////////////////////////////////
const byte  Max_Chn = 10;                       // Max Channel(10ch)
const byte  Int_End = 73;                          // Initial end code
const char *CALL = "JA2GQP  ";             // Display Call sign


//----------  EEPROM Memory Address   ----------

const byte  Frq_Eep = 0x00;                 // Frequency(4byte*10)
const byte  Stp_Eep = 0x30;                 // STEP(4byte*10)
const byte  Mode_Eep = 0x60;               // Mode(1byte*10)
const byte  Care_Eep = 0x70;               // Career point(4byte* 4)
const byte  If_Eep = 0x80;                    // IF(4byte*1)
const byte  Chn_Eep = 0x90;                // Channel(1byte*1)
const byte  Vfo_Eep = 0x92;                 // Vfo mode(1byte*1)
const byte  Sav_Eep = 0x94;                // Vfo Frequency save(4byte*1)
const byte  Eep_Int = 0x9e;                  // Eep Init(1byte*1)

//----------  Encorder Pin Assign(INT)  --------

Rotary r = Rotary(ENC_A,ENC_B);            // 2 = ENC_A,3 = ENC_B

//----------  Memory Assign  -------------------

long Vfo_Dat;                             // Vfo Frequency
long Vfo_Datb;                            // Vfo data(old)
long RX_Dat;                              // RX DDS Out Data
long TX_Dat;                              // TX DDS Out Data
long Rit_Dat;                             // RIT Data
long Rit_Datb;                            // RIT Data Old
long Enc_Stp;                             // STEP
long Lng_Wk1;                             // Long Work1
long Lng_Wk2;                             // Long Work2
long If_Dat;                              // IF Frequency
char *Lcd_Dat = "           ";            // Lcd Display Buffer

byte Byt_Chn;                             // Channel SW
byte Byt_Chnb;                            // Channel SW Old
byte Flg_Rit;                             // RIT Flag
byte Flg_Ritb;                            // RIT Flag Old
byte Flg_Tx;                              // TX Flag
byte Flg_Spl;                             // SPLIT Flag
byte Flg_Mode;                            // Mode Flag
byte Byt_Mode;                            // Mode
byte Flg_LSB;                             // LSB Flag
byte Flg_USB;                             // USB Flag
byte Flg_CW;                              // CW Flag
byte Flg_SUB;                             // SUB Flag
byte Flg_Over;                            // Over Flag
byte Flg_Ent;                             // ENT Flag
byte Byt_Ent;                             // ENT Mode
byte Flg_If;                              // IF Flag
byte Flg_Vfo;                             // DDS Flag
byte Byt_Vfo;                             // VFO Mode

//----------  Initialization  Program  ---------------

void setup(){
  lcd.begin(16, 2);                       // LCD 16*2

  pinMode(SW_STEP,INPUT_PULLUP);
  pinMode(SW_RIT,INPUT_PULLUP);
  pinMode(SW_SPLIT,INPUT_PULLUP);
  pinMode(SW_TX,INPUT_PULLUP);
  pinMode(SW_CH,INPUT_PULLUP);
  pinMode(SW_ENT,INPUT_PULLUP);

  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();                                    // INT Enable

  pinMode(FQ_UD,OUTPUT);
  pinMode(W_CLK,OUTPUT);
  pinMode(DATA,OUTPUT);

  Flg_Tx = 0;
  Flg_Rit = 0;
  Flg_Spl = 0;
  lcd.clear();

  if(EEPROM.read(Eep_Int) != Int_End){        // Eep initialaz
    delay(10);
    Fnc_Eep_Int();
  }
  Byt_Chn = EEPROM.read(Chn_Eep);             // Channel
  Byt_Chnb = Byt_Chn;
  Fnc_Eep_Rd();                              // EEPROM Read
}

//----------  Main program  ---------------

void loop() {
  if(Flg_Tx == 0){                            // Tx off?
    if(digitalRead(SW_STEP) == LOW)           // STEP Sw On?
      Fnc_Stp();                          

    if(digitalRead(SW_ENT) == LOW)            // ENT SW On?
      Fnc_Ent();                          

    if((Flg_Mode == 0) && (Flg_Spl != 2)){
      if(digitalRead(SW_RIT) == LOW)          // RIT Sw On?
        Fnc_Rit();
    }                          

    if((Flg_Ent == 0) && (Flg_Rit != 2)){
      if(digitalRead(SW_SPLIT) == LOW)      // SPLIT Sw On?
        Fnc_Spl();                        
      if((digitalRead(SW_CH) == LOW))       // CH SW On?
        Fnc_Chsw();                          
    }

    if(Byt_Chnb != Byt_Chn){                 // CH SW OLD != NEW?
      Fnc_Eep_Wt(Byt_Chnb);
      Byt_Chnb = Byt_Chn;
      Fnc_Eep_Rd();
    }

    if(Flg_Ent == 1)                         // ENT proc.?
      Fnc_Prm();
  }

  if(digitalRead(SW_TX) == LOW)              // Tx On?
    Flg_Tx = 1;                          
  else                                
    Flg_Tx = 0;                                        

  Fnc_Band(Vfo_Dat+Rit_Dat);              // Range check
  Fnc_If(Byt_Vfo);

  if(Flg_Tx == 0)
    Fnc_Dds(RX_Dat);                      // AD9850 DDS RX set
  else{
    if(Flg_Over == 0)                     // Frequency not range over?
      Fnc_Dds(TX_Dat);                    // AD9850 DDS TX set
    else                    
      Fnc_Dds(0L);                        // DDS 0Hz
  }

  Fnc_Lcd();                               // LCD Display
}

//----------  Encorder procedure(INT)  ---------------

ISR(PCINT2_vect) {
  unsigned char result = r.process();

  if(Flg_Tx == 0){
    if(result) {
      if(result == DIR_CW){
        Lng_Wk1 = Vfo_Dat + Enc_Stp;
        Lng_Wk2 = Rit_Dat + Enc_Stp;
      }
      else{
          Lng_Wk1 = Vfo_Dat - Enc_Stp;
          Lng_Wk2 = Rit_Dat - Enc_Stp;
      }  

      if((Flg_Rit == 1) || (Flg_Spl == 1))
        Rit_Dat = Lng_Wk2;
      else{
        if((Flg_Rit == 2) || (Flg_Spl == 2) || (Flg_Rit == 0) || (Flg_Spl == 0))
          Vfo_Dat = Lng_Wk1;
        else
          Rit_Dat = 0;
      }

      if(Flg_Mode == 0)
        Vfo_Dat = constrain(Vfo_Dat,LW_FRQ,HI_FRQ);// VFO range check
      else
        Vfo_Dat = constrain(Vfo_Dat,LW_OFT,HI_OFT);// Offset range check
       
      Rit_Dat = constrain(Rit_Dat,LW_RIT,HI_RIT);  // RIT range check
    }
  }
}

//----------  Function DDS set  ---------------

void Fnc_Dds(double frquency){
  unsigned long wrk = frquency * TWO_E32 / DDS_CLK;

  digitalWrite(FQ_UD,LOW);

  shiftOut(DATA,W_CLK,LSBFIRST,wrk);
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 8));
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 16));
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 24));
  shiftOut(DATA,W_CLK,LSBFIRST,DDS_CMD);   // AD9850 command

  digitalWrite(FQ_UD,HIGH);
}

//----------  Function Encorder STEP  ---------

void Fnc_Stp(){
  if(Enc_Stp == 10)                       // Step = 10Hz ?
    Enc_Stp = 1000000;                    //   Yes,1MHz set
  else
    Enc_Stp = Enc_Stp / 10;               // Step down 1 digit

  Fnc_Step_Disp();
  while(digitalRead(SW_STEP) == LOW)
    ;
}

//----------  Function STEP Display  ----------

void Fnc_Step_Disp(){
  lcd.setCursor(0,1);
  switch(Enc_Stp){
    case 10:
      lcd.print("10  ");
      break;
    case 100:
      lcd.print("100 ");
      break;
    case 1000:
      lcd.print("1k  ");
      break;
    case 10000:
      lcd.print("10k ");
      break;
    case 100000:
      lcd.print("100k");
      break;
    case 1000000:
      lcd.print("1M  ");
      break;
    default:
      lcd.print("1k  ");
      Enc_Stp = 1000;
      break;
  }
}

//----------  Function String Dot Edit  --------
 
char *Fnc_Dot_Edit(char *str,long n){
  int  i = 0;                           // Write the number
  char *p = str;
  unsigned long  u = abs(n);

  do{
    *p++ = "0123456789"[u % 10];
    u = u / 10;
    i++;
    if((0 != u) && (0 == (i % 3)))
      *p++ = '.';
    }
  while( 0 != u );

  if ( n < 0 )
     *p++ = '-';
   *p = '\0';
   Fnc_Revr( str );
   return str;
}

//----------  Function String Reverse  ---------

void Fnc_Revr(char *str){
  int i,n;
  char c;

  n=strlen(str);
  for(i = 0;i < n / 2;i++){
    c=str[i];
    str[i]=str[n - i - 1];
    str[n - i - 1]=c;
  }
}

//----------  Function Save EEPROM 4byte  ---------

void Fnc_Eep_Sav4(long value,int address){
  address += 3;
  for(int i = 0;i < 4;i++){
    byte toSave = value & 0xFF;
    if(EEPROM.read(address) != toSave){
      EEPROM.write(address,toSave);
      }
    value = value >> 8;
    address--;
  }
}

//----------  Function Load EEPROM 4byte  ---------

long Fnc_Eep_Lod4(int address){
  long value = 0;
  for(int i = 0;i < 4;i++){
    value = value | EEPROM.read(address);
    if( i < 3){
      value = value << 8;
      address++;
      }
  }
  return value;
}

//----------  Function LCD Display  ---------

void Fnc_Lcd(){
  lcd.setCursor(0,0);
  if(Flg_Tx == 1)
    lcd.write('T');
  else if(Flg_Ent == 1)
    lcd.write('P');
  else
    lcd.print(Byt_Chn);

  Fnc_Step_Disp();

  if(Flg_Rit == 1){                              // Rit display
    lcd.setCursor(5,1);
    if(Rit_Dat != Rit_Datb){
      lcd.print("R          ");
      Rit_Datb = Rit_Dat;
    }
    lcd.setCursor(6,1);
    if(Rit_Dat >=0)
      lcd.write('+');
    Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
    lcd.print(Lcd_Dat);
  }

  if(Flg_Spl == 1){                              // Split display
    lcd.setCursor(5,1);
    if(Rit_Dat != Rit_Datb){
      lcd.print("T          ");
      Rit_Datb = Rit_Dat;
    }
    lcd.setCursor(6,1);
    if(Rit_Dat >=0)
      lcd.write('+');
    Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
    lcd.print(Lcd_Dat);
  }

    if((Flg_Over == 1) && (Flg_Ent == 0)){
      Fnc_Fdsp(Vfo_Dat);
      lcd.setCursor(14,1);
      lcd.print("ov");
    }
    else
      Fnc_Fdsp(Vfo_Dat);

    if((Flg_Over == 0) && (Flg_Ent == 0)){
      lcd.setCursor(14,1);
      lcd.write(' ');
      lcd.write(' ');
    }

  if((Flg_Vfo == 0) && (Flg_If == 0) && (Flg_Rit == 0) && (Flg_Spl == 0) && (Flg_Mode == 0)){
    lcd.setCursor(5,1);
    lcd.print(CALL);
  }
}

//----------  Function Frequency Display  -------------------

void Fnc_Fdsp(long f_disp){
  Fnc_Dot_Edit(Lcd_Dat,f_disp);
  lcd.setCursor(1,0);
  if(f_disp != Vfo_Datb){
    lcd.write(':');
    for(int i=0;i<10;i++)
      lcd.write(' ');
    Vfo_Datb = f_disp;
  }

  lcd.setCursor(2,0);
  lcd.print(Lcd_Dat);
  if(Flg_Mode == 0)
    Fnc_Mdisp();
  if((Flg_If == 1) || (Flg_Vfo == 1)){
    lcd.setCursor(13,0);
    for(int i=0;i<3;i++)
      lcd.write(' ');
  }
}

//----------  Function Mode Display  -----------------------

void Fnc_Mdisp(){
  lcd.setCursor(13,0);
  switch(Byt_Mode){
    case 0:                              // LSB
      lcd.print("LSB");
      break;
    case 1:                              // USB
      lcd.print("USB");                
      break;
    case 2:                              // CW
      lcd.print("CW ");                
      break;
  }
}

//----------  Function Rit  ---------

void Fnc_Rit(){
  if(Flg_Vfo == 0){
    if(Flg_Rit == 0){
      if(Flg_Spl == 1)
        Flg_Spl = 0;
      Flg_Rit = 1;
      lcd.setCursor(5,1);
      lcd.print("R          ");
      if(Rit_Dat >=0){
        lcd.setCursor(6,1);
        lcd.write('+');
        Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
        lcd.print(Lcd_Dat);
      }
    }
    else{
      lcd.setCursor(5,1);
      lcd.print(CALL);
      Flg_Rit = 0;
      Rit_Dat = 0;
    }
  }
  else
    Byt_Vfo++;

  while(digitalRead(SW_RIT) == LOW)
    ;
}

//----------  Function Channel SW Check  ---------

void Fnc_Chsw(){
  byte cnt = 0;

  Byt_Chn++;
  while(digitalRead(SW_CH) == LOW){
    delay(500);
    cnt++;
    if(6 <= cnt){                            // Eep Initial start(3sec)?
      Fnc_Eep_Int();
      Byt_Chn = EEPROM.read(Chn_Eep);         // Channel
      Byt_Chnb = Byt_Chn;
      Fnc_Eep_Rd();                           // EEPROM Read
      lcd.setCursor(0,0);                     // LCD display
      lcd.print(Byt_Chn);
      Fnc_Fdsp(Vfo_Dat);
      lcd.setCursor(5,1);
      lcd.print("Init End   ");
    }
  }
}

//---------- Function Eeprom Initialization -----------------

void Fnc_Eep_Int(){
  int i;

  for (i=0;i<160;i++)                            // 0 clear(160byte)
    EEPROM.write(i, 0);

  for(i=0;i<Max_Chn;i++){
    Fnc_Eep_Sav4(DEF_FRQ,Frq_Eep+i*4);            // Frequency(7.05MHz)
    Fnc_Eep_Sav4(DEF_STP,Stp_Eep+i*4);            // Step(1kHz)
  }

  Fnc_Eep_Sav4(DEF_IF,If_Eep);                         // IF(10.7MHz)
  Fnc_Eep_Sav4(DEF_LSB,Care_Eep+0);              // LSB Offset(-1500Hz)
  Fnc_Eep_Sav4(DEF_USB,Care_Eep+4);              // USB Offset(1500Hz)
  Fnc_Eep_Sav4(DEF_CW,Care_Eep+8);                // CW Offset(-600Hz)
  EEPROM.write(Vfo_Eep,DEF_VFO);                 // Vfo Mode
  EEPROM.write(Eep_Int,Int_End);                      // Init end set(73)
}

//----------  Function EEPROM Read  ---------

void Fnc_Eep_Rd(){
  if((0 <= Byt_Chn) && (Byt_Chn < Max_Chn))
    Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep+Byt_Chn*4);
  else{
    Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep+0*4);
    Byt_Chn = 0;
  }

   if((0 <= Byt_Chn) && (Byt_Chn < Max_Chn))
    Enc_Stp = Fnc_Eep_Lod4(Stp_Eep+Byt_Chn*4);
  else
    Enc_Stp = Fnc_Eep_Lod4(Stp_Eep+0*4);

  If_Dat = Fnc_Eep_Lod4(If_Eep);
  Byt_Vfo = EEPROM.read(Vfo_Eep);
}

//----------  Function EEPROM Write  -----------------------

void Fnc_Eep_Wt(byte chn){
  if((0 <= chn) && (chn < Max_Chn)){
    Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep+chn*4);
    Fnc_Eep_Sav4(Enc_Stp,Stp_Eep+chn*4);
  }
  EEPROM.write(Chn_Eep,Byt_Chn);
}

//----------  Function Split  ---------

void Fnc_Spl(){
  if(Flg_Spl == 0){
    if(Flg_Rit == 1)
      Flg_Rit = 0;
    Flg_Spl = 1;
    lcd.setCursor(5,1);
    lcd.print("T          ");
    if(Rit_Dat >=0){
      lcd.setCursor(6,1);
      lcd.write('+');
      Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
      lcd.print(Lcd_Dat);
    }
  }
  else{
    lcd.setCursor(5,1);
    lcd.print(CALL);
    Flg_Spl = 0;
    Rit_Dat = 0;
  }

  while(digitalRead(SW_SPLIT) == LOW)
    ;
}

//----------  Function ENT  --------------------------------

void Fnc_Ent(){
  byte cnt = 0;

  if(Flg_Ent == 0){
    if(Flg_Rit == 1){
      Flg_Rit = 2;
      lcd.setCursor(5,1);
      lcd.write('r');
    }
     else
      if(Flg_Rit == 2){
        Flg_Rit = 1;
        lcd.setCursor(5,1);
        lcd.write('R');
      }

    if(Flg_Spl == 1){
      Flg_Spl = 2;
      lcd.setCursor(5,1);
      lcd.write('t');
    }
    else
      if(Flg_Spl == 2){
        lcd.setCursor(5,1);
        lcd.write('T');
        Flg_Spl = 1;
      }

    Fnc_Eep_Wt(Byt_Chn);

    while(digitalRead(SW_ENT) == LOW){
      delay(500);
      cnt++;
      if(6 <= cnt){                              // Parameter change mode(3sec)
        lcd.setCursor(0,0);
        lcd.print("P");
        Flg_Ent = 1;
        Flg_Rit = 0;
        Flg_Spl = 0;
        Byt_Ent = 0;
        if(Flg_If == 0){
          Fnc_Eep_Sav4(Vfo_Dat,Sav_Eep);
          Vfo_Dat = Fnc_Eep_Lod4(If_Eep);
          Flg_If = 1;
        }
        Fnc_Fdsp(Vfo_Dat);
        lcd.setCursor(5,1);
        lcd.print("IF    ");
      }
    }
  }

  else{
    while(digitalRead(SW_ENT) == LOW){
      delay(500);
      cnt++;
      if(6 <= cnt){                              // Return Parameter cahne mode(3sec)
        lcd.setCursor(0,0);
        lcd.print(Byt_Chn);
        Flg_Ent = 0;
        Flg_Vfo = 0;
        Flg_If = 0;
        Vfo_Dat = Fnc_Eep_Lod4(Sav_Eep);
        Fnc_Fdsp(Vfo_Dat);
        lcd.setCursor(5,1);
        lcd.print(CALL);
        EEPROM.write(Vfo_Eep,Byt_Vfo);
      }
      else
        Byt_Ent++;
    }
  }

}

//----------  Function Prameter PROC  ----------------------

void Fnc_Prm(){
  lcd.setCursor(5,1);
  switch(Byt_Ent){
    case 0:                                         // IF Frequency load
      if(Flg_If == 0){
        Vfo_Dat = Fnc_Eep_Lod4(If_Eep);
        Flg_If = 1;
      }
      lcd.setCursor(5,1);
      lcd.print("IF         ");
      break;
    case 1:                                         // IF Frequency proc.
      if(Flg_If == 1){
        Fnc_Eep_Sav4(Vfo_Dat,If_Eep);
        If_Dat = Vfo_Dat;
        Flg_If = 0;
      }
      lcd.setCursor(5,1);
      lcd.print("Offset");
      if(Flg_LSB == 0){                             // LSB Offset data load
        Vfo_Dat = Fnc_Eep_Lod4(Care_Eep+0);
        Flg_LSB = 1;
        Flg_Mode = 1;
      }
      lcd.setCursor(13,1);
      lcd.print("LSB");
      break;
    case 2:                                         // LSB Offset proc.
      if(Flg_LSB == 1){
        Fnc_Eep_Sav4(Vfo_Dat,Care_Eep+0);
        Flg_LSB = 0;
      }
      if(Flg_USB == 0){                             // USB Offset data load                      
        Vfo_Dat = Fnc_Eep_Lod4(Care_Eep+4);
        Flg_USB = 1;
      }
      lcd.setCursor(13,1);
      lcd.print("USB");
      break;
    case 3:                                         // USB Offset proc.
      if(Flg_USB == 1){
        Fnc_Eep_Sav4(Vfo_Dat,Care_Eep+4);
        Flg_USB = 0;
      }
      if(Flg_CW == 0){                            // CW Offset
        Vfo_Dat = Fnc_Eep_Lod4(Care_Eep+8);
        Flg_CW = 1;
      }
      lcd.setCursor(13,1);
      lcd.print("CW ");
      break;
    case 4:                                       // VFO Mode Set
      if(Flg_CW == 1){
        Fnc_Eep_Sav4(Vfo_Dat,Care_Eep+8);
        Flg_CW = 0;
        Flg_Mode = 0;
      }
      if(Flg_Vfo == 0){
        Byt_Vfo = EEPROM.read(Vfo_Eep);          // Vfo Mode data
        if(Byt_Vfo < 0)
          Byt_Vfo = 0;
        Flg_Vfo = 1;
      }
      Vfo_Dat = Fnc_Eep_Lod4(Sav_Eep);
      lcd.setCursor(5,1);
      lcd.print("VFO  ");
      lcd.setCursor(10,1);
      switch(Byt_Vfo){
        case 0:
          lcd.print("Roff  ");                  // TX=VFO RX=0
          break;
        case 1:
          lcd.print("TR    ");                  // TX=VFO RX=VFO
          break;
        case 2:
          lcd.print("R+IF  ");                  // TX=VFO RX=VFO+IF
          break;
        case 3:
          lcd.print("TR+IF ");                  // TX=VFO+IF RX=VFO+IF
          break;
        default:
          Byt_Vfo = 0;
          lcd.print("Roff  ");
          break;
      }
      break;
    default:
      if(Flg_Vfo == 1){
        EEPROM.write(Vfo_Eep,Byt_Vfo);
        Flg_Vfo = 0;
      }
      lcd.setCursor(5,1);
      lcd.print("IF    ");
      Byt_Ent = 0;
      break;
  }
}

//----------  Function Band  -------------------------------

void Fnc_Band(long vfo){
  if((vfo >= LW_VFO80) && (vfo < MI_VFO80)){          // 3.5MHz
    Flg_Over = 0;
    Byt_Mode = 2;                                     // CW
  }
  else if((vfo >= MI_VFO80) && (vfo <= HI_VFO80)){
    Flg_Over = 0;
    Byt_Mode = 0;                                     // LSB
  }

  else if((vfo >= LW_VFO40) && (vfo < MI_VFO40)){     // 7MHz
    Flg_Over = 0;
    Byt_Mode = 2;                                     // CW
  }
  else if((vfo >= MI_VFO40) && (vfo <= HI_VFO40)){
    Flg_Over = 0;
    Byt_Mode = 0;                                     // LSB
  }

  else if((vfo >= LW_VFO20) && (vfo < MI_VFO20)){     // 14MHz
    Flg_Over = 0;
    Byt_Mode = 2;                                     // CW
  }
  else if((vfo >= MI_VFO20) && (vfo <= HI_VFO20)){
    Flg_Over = 0;
    Byt_Mode = 1;                                     // USB
  }

  else if((vfo >= LW_VFO15) && (vfo < MI_VFO15)){     // 21MHz
    Flg_Over = 0;
    Byt_Mode = 2;                                     // CW
  }
  else if((vfo >= MI_VFO15) && (vfo <= HI_VFO15)){
    Flg_Over = 0;
    Byt_Mode = 1;                                     // USB
  }

  else if((vfo >= LW_VFO10) && (vfo < MI_VFO10)){     // 28MHz
    Flg_Over = 0;
    Byt_Mode = 2;                                     // CW
  }
  else if((vfo >= MI_VFO10) && (vfo <= HI_VFO10)){
    Flg_Over = 0;
    Byt_Mode = 1;                                      // USB
  }

  else if (Vfo_Dat < 10000000L){
    Byt_Mode = 0;                                      // LSB
    Flg_Over = 1;                                
  }
  else{
    Byt_Mode = 1;                                      // USB
    Flg_Over = 1;
  }
}

//----------  Function IF Proc.  ---------------------------

void Fnc_If(byte if_mode){
  long bfo = Fnc_Eep_Lod4(Care_Eep+Byt_Mode*4);

  switch(if_mode){
    case 0:                                      // Roff
      RX_Dat = 0L;                            // RX = off
      TX_Dat = Vfo_Dat;                     // TX = VFO
      break;
    case 1:                                      // TR
      RX_Dat = Vfo_Dat;                     // RX = VFO
      TX_Dat = Vfo_Dat;                     // TX = VFO
      break;
    case 2:                                      // R+IF
      RX_Dat = Vfo_Dat + If_Dat + bfo;  // RX = VFO + IF + bfo
      TX_Dat = Vfo_Dat;                     // TX = VFO
      break;
    case 3:                                      // TR+IF
      RX_Dat = Vfo_Dat + If_Dat + bfo;  // RX = VFO + IF + bfo
      if(Byt_Mode == 2)                      // CW Mode?
        TX_Dat = Vfo_Dat + If_Dat;        // TX = VFO + IF
      else
        TX_Dat = Vfo_Dat + If_Dat + bfo;// TX = VFO + IF + bfo
      break;
    default:
      RX_Dat = 0L;                            // RX = off
      TX_Dat = Vfo_Dat;                     // TX = VFO
      break;
    }
  if((RX_Dat != 0) && ((Flg_Rit == 1) || (Flg_Rit == 2)))
    RX_Dat = RX_Dat + Rit_Dat;
  if((Flg_Spl == 1) || (Flg_Spl == 2))
    TX_Dat = TX_Dat + Rit_Dat;
}


2016年7月3日日曜日

PICerFT

AVRとPIC両用のprogrammer PICerFTを作った。これは、秋月電子のFT232RLモジュールを使い、 外部電源不要、ライタファームウェア不要のprogrammerである。
詳しくは、こちら
秋月電子のFT232RLで作る前に、中華のFT232RLでトライしたが、チップのEEPROMが変更出来なかった為、失敗した。
基板は、秋月電子 透明ケース(117-TSS)に収納した。

回路図である。   
リンク先の回路図は、判りづらい為、書き換えた。

基板サイズ 47 x 65
  

PIC書込みの様子
 

AVR書込みの様子 

2016年6月1日水曜日

si5351 VFO

Adafruit si5351モジュールを使ったVFOで、LCDにnokia5110 を組合わせた。DUAL VFO方式を採用し、BFOを自動選択方式にしてスイッチを減らした。チャンネルは、0-9(max10ch)でバンドに割り付ける事も可能だが、同一周波数帯としても使える。RITは、±10kHZ。Sメータ機能付き。周波数帯域外は、over表示して送信不可。また、送信時はスイッチ操作が出来ない様、誤操作保護を行っている。SPLIT機能は、メモリ不足の為、優先順位から除外した。   
 

部品実装基板である。0Ωは、ジャンパーとして使用している。部品の大半がジャンパーなので、PCBとして出来が悪いかも知れない。 



回路図である。nokia5110のバックライトは、現時点で電源印可の違いで、2種ある事が判っているいる。
タイプ1 BL端子 VCC接続
タイプ2 BL端子 GND接続
バックライトのタイプの違いに対応する為、ジャンパチップで設定する事にした。

基板寸法 93 x 47










Program

使っているライブラリは、ソースに書いて有るので参照願いたい。
BANDプランでモード変更(CW、LSB、USB)を行っているので、必要に応じ修正しなければならない。
//////////////////////////////////////////////////////////////////////
//  si5351 VFO program ver.1.0
//    Copyright(C)2016.JA2GQP.All rights reserved.
//
//                                Arduino IDE 1.6.9 Compiled                                  
//
//                                                2016/5/30
//                                                  JA2GQP
//--------------------------------------------------------------------
//  Function
//    1.STEP(1M,100k,10k,1k,100,10)
//    2.Memory Channel ch0 - ch9(10ch)
//    3.Protection Operation At The Time Of Transmission
//--------------------------------------------------------------------
// Library
//  Rotary encoeder  http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
//  si5351Arduino    https://github.com/etherkit/Si5351Arduino
//  LCD5110_Basic    http://www.rinkydinkelectronics.com/library.php?id=44
//////////////////////////////////////////////////////////////////////

#include <rotary.h>
#include <si5351.h>
#include <Wire.h>
#include <LCD5110_Basic.h>
#include <EEPROM.h>

//----------  Define Constant Value   -----------------------

////////////////////////////////
// I/O assign
////////////////////////////////

const byte  ENC_A = 2;                     // Encorder A
const byte  ENC_B = 3;                     // Encoeder B
const byte  SW_STEP = 4;                   // STEP SW
const byte  SW_RIT = 5;                    // RIT SW
const byte  SW_CH = 6;                     // CH SW
const byte  SW_TX = 15;                    // TX SW

const byte  AD_IN = A0;                    // analog input for left channel

////////////////////////////////
// default value
////////////////////////////////

const long  DEF_FRQ = 7050000L;            // Default Vfo(7.05MHz)
const long  DEF_STP = 1000L;               // Init STEP(1kHz)

////////////////////////////////
// Limited range
////////////////////////////////

const long  LW_FRQ = 0L;                   // Frequency Lower Limit
const long  HI_FRQ = 60000000L;            //           Upper Limit

const long  LW_RIT = -10000L;              // RIT Lower Limit
const long  HI_RIT = 10000L;               // RIT Upper Limit

const long  LW_VFO80 = 3500000L;           // 3.5MHz Lower
const long  MI_VFO80 = 3535000L;           //        Middle
const long  HI_VFO80 = 3575000L;           //        Upper
const long  LW_VFO40 = 7000000L;           // 7MHz   Lower
const long  MI_VFO40 = 7045000L;           //        Middle
const long  HI_VFO40 = 7200000L;           //        Upper
const long  LW_VFO20 = 14000000L;          // 14MHz  Lower
const long  MI_VFO20 = 14100000L;          //        Middle
const long  HI_VFO20 = 14350000L;          //        Upper
const long  LW_VFO15 = 21000000L;          // 21MHz  Lower
const long  MI_VFO15 = 21150000L;          //        Middle
const long  HI_VFO15 = 21450000L;          //        Upper
const long  LW_VFO10 = 28000000L;          // 28MHz  Lower
const long  MI_VFO10 = 28200000L;          //        Middle
const long  HI_VFO10 = 29000000L;          //        Upper

////////////////////////////////
// etc
////////////////////////////////

const byte  Max_Chn = 10;                  // Max Channel(1-10ch)
const byte  Int_End = 73;                  // Initial end code

//----------  EEPROM Memory Address   -----------------------

const byte  Frq_Eep = 0x00;                // Frequency(4byte*10)
const byte  Stp_Eep = 0x30;                // STEP(4byte*10)
const byte  Chn_Eep = 0x60;                // Channel(1byte*1)
const byte  Eep_Int = 0x6e;                // Eep Init(1byte*1)

//----------  LCD NOKIA 5110 definition --------------------

LCD5110 myGLCD(8,9,10,11,12);             // SCK,MOSI,DC,RST,CS
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];

//----------  si5351 definition -----------------------------

Si5351 si5351;

//----------  Encorder Pin definition  ----------------------

Rotary r = Rotary(ENC_A, ENC_B);

//----------  Memory Assign  --------------------------------

volatile long LSB = 10701500L;              // 10.7015MHz
volatile long USB = 10698500L;              // 10.6985MHz
volatile long CW  = 10700600L;              // 10.7006MHz
volatile long bfo = 10701500L;              // start in LSB
volatile long IF  = 10700000L;              // 10.7000MHz

volatile long Vfo_Dat = DEF_FRQ;            // Default Frequency
volatile long Vfo_Datb;                     // Vfo data(old)
volatile long Lng_Wk1;                      // Long Work1
volatile long Lng_Wk2;                      // Long Work2
volatile long Dds_Dat;
String tbfo = "";

volatile long Rit_Dat = 0;                 // RIT Data
volatile long Rit_Datb = 0;
volatile long Enc_Stp = 1000;              // STEP

byte Flg_Tx = 0;                          // TX Flag
byte Flg_Rit = 0;                         // RIT Flag
byte Flg_Spl;                             // SPLIT Flag
byte Flg_Over;                            // Over Flag
byte Byt_Chn = 0;                         // Channel SW
byte Byt_Chnb = 0;                        // Channel SW Old

//----------  Initialization  Program  ----------------------

void setup(){
  myGLCD.InitLCD();                              // nokia5110 Init  
  Wire.begin();

  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);       //initialize the Si5351
  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA); // Set PLL
                                                 // Set CLK0 Frequency(VFO)
  pinMode(SW_STEP,INPUT_PULLUP);
  pinMode(SW_RIT,INPUT_PULLUP);
  pinMode(SW_CH,INPUT_PULLUP);
  pinMode(SW_TX,INPUT_PULLUP);
 
  PCICR |= (1 << PCIE2);                        // Enable pin change interrupt for the encoder
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();                                        // INT Enable
  Rit_Dat = 0;
  Flg_Rit = 0;
 
  if(EEPROM.read(Eep_Int) != Int_End){         // Eep initialaz
    delay(10);
    Fnc_Eep_Int();
  }

  Byt_Chn = EEPROM.read(Chn_Eep);              // Eep Channel Read
  Byt_Chnb = Byt_Chn;
  Fnc_Eep_Rd();
  Fnc_Lcd();                                   // Display LCD
  Fnc_Step_Disp();
}

//----------  Main program  ---------------------------------

void loop(){
  if(Flg_Tx == 0){
    Fnc_Smeter();
   
    if(digitalRead(SW_STEP) == LOW)               // STEP Sw On?
      Fnc_Stp();                          
    if((digitalRead(SW_RIT) == LOW))              // RIT SW On?
      Fnc_Rit();
    if((digitalRead(SW_CH) == LOW))               // CH SW On?
      Fnc_Chsw();

    if(Byt_Chnb != Byt_Chn){                      // CH SW OLD != NEW?
      Fnc_Eep_Wt(Byt_Chnb);
      Byt_Chnb = Byt_Chn;
      Fnc_Eep_Rd();
    }
  }

  if(digitalRead(SW_TX) == LOW)                  // Tx On?
    Flg_Tx = 1;
  else
    Flg_Tx = 0;

  Fnc_Step_Disp();
  Fnc_Lcd();

  if((Flg_Tx == 0) && (Flg_Rit == 1))
      si5351.set_freq(((Vfo_Dat+IF+Rit_Dat) * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK0);
  if((Flg_Tx == 1) || (Flg_Rit == 0))
     si5351.set_freq(((Vfo_Dat+IF) * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK0);

  Fnc_Band(Vfo_Dat);
   
  if(Flg_Over == 1)                             // Over?
    myGLCD.print("over",CENTER,16);             // Display(over)
  else  
    myGLCD.clrRow(2);                           // Clear(over)

  if((Flg_Over == 1) && (Flg_Tx == 1))
    si5351.output_enable(SI5351_CLK0, 0);       // VFO disable
  else
     si5351.output_enable(SI5351_CLK0, 1);      // VFO enable

  si5351.set_freq(( bfo* SI5351_FREQ_MULT), 0, SI5351_CLK2);
}

//----------  Function S-Meter Display  -----------------------

void Fnc_Smeter(){
  int ad1 = 0;
  int ad2 = 0;
 
  for(int i=0;i<6;i++){
    ad1 = map(sqrt( analogRead( AD_IN  )*20 ),0,143,0,140);
    ad2 = ad1 + ad2;
  }
  ad2 = ad2 / 5;
  int s_dat = map(ad2,0,140,0,14);

  for (int i=0; i<s_dat; i++)        
    myGLCD.print("\\",(i*6), 40);
  myGLCD.clrRow(5,(s_dat*6));

  if(s_dat < 1)
    myGLCD.print("S0   ",RIGHT,32);
  else if((s_dat <=1) &&(s_dat < 2))
    myGLCD.print("S1   ",RIGHT,32);
  else if((s_dat <= 2) && (s_dat < 4))
    myGLCD.print("S3   ",RIGHT,32);
  else if((s_dat <= 4) && (s_dat < 5))
    myGLCD.print("S5   ",RIGHT,32);            
  else if((s_dat <= 5) && (s_dat < 7))
    myGLCD.print("S7   ",RIGHT,32);
  else if((s_dat <= 7) && (s_dat < 9))
    myGLCD.print("S9   ",RIGHT,32);
  else if((s_dat <= 9) && (s_dat < 12))
    myGLCD.print("S9+10",RIGHT,32);
  else if((s_dat <= 12) && (s_dat < 13))
    myGLCD.print("S9+20",RIGHT,32);
  else if(s_dat >= 13)
    myGLCD.print("S9+40",RIGHT,32);
}

//----------  Encorder procedure(INT)  ---------------

ISR(PCINT2_vect) {
  unsigned char result = r.process();

  if(Flg_Tx == 0){
    if(result) {  
      if(result == DIR_CW){
        Lng_Wk1 = Vfo_Dat + Enc_Stp;
        Lng_Wk2 = Rit_Dat + Enc_Stp;
      }
      else{
          Lng_Wk1 = Vfo_Dat - Enc_Stp;
          Lng_Wk2 = Rit_Dat - Enc_Stp;
      }    

      if(Flg_Rit == 1)
        Rit_Dat = Lng_Wk2;
      else{
        Vfo_Dat = Lng_Wk1;
        Rit_Dat = 0;
      }

      Vfo_Dat = constrain(Vfo_Dat,LW_FRQ,HI_FRQ);  // VFO range check
      Rit_Dat = constrain(Rit_Dat,LW_RIT,HI_RIT);  // RIT range check
    }
  }
}

//----------  Function Encorder STEP  -----------------------

void Fnc_Stp(){
  if(Enc_Stp == 10)                       // Step = 10Hz ?
    Enc_Stp = 1000000;                    //   Yes,1Mhz set
    else
      Enc_Stp = Enc_Stp / 10;             // Step down 1 digit

  Fnc_Step_Disp();
  while(digitalRead(SW_STEP) == LOW)
    ;
}

//----------  Function STEP Display  ------------------------

void Fnc_Step_Disp(){
  switch(Enc_Stp){
    case 10:
      myGLCD.print("  10", RIGHT,24);
      break;
    case 100:
      myGLCD.print(" 100", RIGHT,24);
      break;
    case 1000:
      myGLCD.print("  1k", RIGHT,24);
      break;
    case 10000:
      myGLCD.print(" 10k", RIGHT,24);
      break;
    case 100000:
      myGLCD.print("100k", RIGHT,24);
      break;
    case 1000000:
      myGLCD.print("  1M", RIGHT,24);
      break;
    default:
      myGLCD.print("  1k", RIGHT,24);
      Enc_Stp = 1000;
      break;
  }
}

//----------  Function Save EEPROM 4byte  ---------

void Fnc_Eep_Sav4(long value,int address){
  address += 3;
  for(int i = 0;i < 4;i++){
    byte toSave = value & 0xFF;
    if(EEPROM.read(address) != toSave){
      EEPROM.write(address,toSave);
      }
    value = value >> 8;
    address--;
  }
}

//----------  Function Load EEPROM 4byte  ---------

long Fnc_Eep_Lod4(int address){
  long value = 0;

  for(int i = 0;i < 4;i++){
    value = value | EEPROM.read(address);
    if( i < 3){
      value = value << 8;
      address++;
    }
  }
  return value;
}


//---------- LCD Display --------------------------

void Fnc_Lcd(){
  char s[6] ={'\0'};
 
  Fnc_Fdsp(Vfo_Dat);
  myGLCD.setFont(SmallFont);
  if(Flg_Tx == 0)
    myGLCD.printNumI(Byt_Chn,RIGHT, 0);
  else
    myGLCD.print("T",RIGHT,0);
  myGLCD.print(tbfo,LEFT,24);           // Mode
  if(Flg_Rit == 1){
    myGLCD.print("R",0,32);
    if(Rit_Dat != Rit_Datb){
      myGLCD.print("      ",6, 32);
      Rit_Datb = Rit_Dat;
    }
    sprintf(s,"%+d",Rit_Dat);
    myGLCD.print(s,6, 32);
  }
}

//----------  Function Frequency Display  ---------

void Fnc_Fdsp(long f_disp){
  long f1 = f_disp / 1000L;
  long f2 = f_disp % 1000L;
  char s1[6] ={'\0'};
  char s2[4] ={'\0'};

  if(f_disp != Vfo_Datb){
    myGLCD.clrRow(0);
    myGLCD.clrRow(1);
    Vfo_Datb = Vfo_Dat;
  }
  myGLCD.setFont(MediumNumbers);
  myGLCD.printNumI(f1,LEFT, 0);
  myGLCD.setFont(SmallFont);
  sprintf(s2,"%03d",f2);
  myGLCD.print(s2,RIGHT,8);
}

//----------  Function Rit  ---------

void Fnc_Rit(){
  char s[6] ={'\0'};
 
  if(Flg_Rit == 0){
    Rit_Dat = 0;
    Fnc_Eep_Wt(Byt_Chn);
    myGLCD.print("R",0,32);
    sprintf(s,"%+d",Rit_Dat);
    myGLCD.print(s,6, 32);
    Flg_Rit = 1;
  }
  else{
    Flg_Rit = 0;
    myGLCD.print("        ",0, 32);
  }

  while(digitalRead(SW_RIT) == LOW)
    ;
}

//----------  Function CH SW Check  ---------

void Fnc_Chsw(){
  byte cnt = 0;
 
  Byt_Chn++;
 
  while(digitalRead(SW_CH) == LOW){
    delay(500);
    cnt++;
    if(6 <= cnt){                               // Eep Initial start(3sec)?
      Fnc_Eep_Int();                            // Initialization
      Byt_Chn = EEPROM.read(Chn_Eep);           // Channel Read
      Byt_Chnb = Byt_Chn;
      Fnc_Eep_Rd();                             // EEPROM Read
      Fnc_Fdsp(Vfo_Dat);
      myGLCD.print("default",CENTER,16);
    }
  }
}

//----------  Function Band  -------------------------------

void Fnc_Band(long vfo){
  if((vfo >= LW_VFO80) && (vfo < MI_VFO80)){          // 3.5MHz
    Flg_Over = 0;
    tbfo = "CW ";
    bfo = CW;
  }
  else if((vfo >= MI_VFO80) && (vfo <= HI_VFO80)){
    Flg_Over = 0;
    tbfo = "LSB";
    bfo = LSB;
  }

  else if((vfo >= LW_VFO40) && (vfo < MI_VFO40)){     // 7MHz
    Flg_Over = 0;
    tbfo = "CW ";
    bfo = CW;
  }
  else if((vfo >= MI_VFO40) && (vfo <= HI_VFO40)){
    Flg_Over = 0;
    tbfo = "LSB";
    bfo = LSB;
  }

  else if((vfo >= LW_VFO20) && (vfo < MI_VFO20)){     // 14MHz
    Flg_Over = 0;
    tbfo = "CW ";
    bfo = CW;
  }
  else if((vfo >= MI_VFO20) && (vfo <= HI_VFO20)){
    Flg_Over = 0;
    tbfo = "USB";
    bfo = USB;
  }

  else if((vfo >= LW_VFO15) && (vfo < MI_VFO15)){     // 21MHz
    Flg_Over = 0;
    tbfo = "CW ";
    bfo = CW;
  }
  else if((vfo >= MI_VFO15) && (vfo <= HI_VFO15)){
    Flg_Over = 0;
    tbfo = "USB";
    bfo = USB;
  }

  else if((vfo >= LW_VFO10) && (vfo < MI_VFO10)){     // 28MHz
    Flg_Over = 0;
    tbfo = "CW ";
    bfo = CW;
  }
  else if((vfo >= MI_VFO10) && (vfo <= HI_VFO10)){
    Flg_Over = 0;
    tbfo = "USB";
    bfo = USB;
  }

  else if (Vfo_Dat < 10000000L){
    bfo = LSB;
    tbfo = "LSB";
    Flg_Over = 1;
  }
  else{
    bfo = USB;
    tbfo = "USB";
    Flg_Over = 1;
  }
}

//---------- Function Eeprom Initialization -----------------

void Fnc_Eep_Int(){
  int i;

  for (i=0;i<112;i++)                            // 0 clear(112byte)
    EEPROM.write(i, 0);

  for(i=0;i<Max_Chn;i++){
    Fnc_Eep_Sav4(DEF_FRQ,Frq_Eep+i*4);            // Frequency(7.05MHz)
    Fnc_Eep_Sav4(DEF_STP,Stp_Eep+i*4);            // Step(1kHz)
  }

  EEPROM.write(Eep_Int,Int_End);                  // Init end set(73)
}

//----------  Function EEPROM Read  ---------

void Fnc_Eep_Rd(){
  if((0 <= Byt_Chn) && (Byt_Chn < Max_Chn))
    Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep+Byt_Chn*4);
  else{
    Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep+0*4);
    Byt_Chn = 0;
  }

  if((0 <= Byt_Chn) && (Byt_Chn < Max_Chn))
    Enc_Stp = Fnc_Eep_Lod4(Stp_Eep+Byt_Chn*4);
  else
    Enc_Stp = Fnc_Eep_Lod4(Stp_Eep+0*4);
}

//----------  Function EEPROM Write  ---------

void Fnc_Eep_Wt(byte chn){
  if((0 <= chn) && (chn < Max_Chn)){
    Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep+chn*4);
    Fnc_Eep_Sav4(Enc_Stp,Stp_Eep+chn*4);
  }

  EEPROM.write(Chn_Eep,chn);
}