2016年8月18日木曜日

si5351a TFT VFO

Arduino UNO/nanoとUglibを組合わせ、TFT表示をさせる場合、メモリ不足でコンパイル出来ない。そこで、多くのメモリ消費させるsi5351ライブラリを使わず、コンパクトなヘッダーファイルを使う事で、メモリ消費を抑えた。si5351aコントロールに必要な部分は、インクルードファイルの形で定義。但し、si5351aコントロール機能は少なく、clok0の1チャンネルのみ。必要なファイルは、si5351a TFTフォルダからダウンロード出来る。Arduino IDE 1.6.9及び、1.6.10で動作確認しました。

Arduno UNO/nano共通の回路図。














Headder File

スケッチと同じディレクトリに、下記内容のファイル”si5351a.h”を保存する。


////////////////////////////////////////////////////////////////////////
// Author: Hans Summers, 2015
// Website: http://www.hanssummers.com
//
// A very very simple Si5351a demonstration
// using the Si5351a module kit http://www.hanssummers.com/synth
// Please also refer to SiLabs AN619 which describes all the registers to use
//----------------------------------------------------------------------
// Addered: JA2GQP,2016/8/18
////////////////////////////////////////////////////////////////////////

#define I2C_START       0x08
#define I2C_START_RPT   0x10
#define I2C_SLA_W_ACK   0x18
#define I2C_SLA_R_ACK   0x40
#define I2C_DATA_ACK    0x28
#define I2C_WRITE       0b11000000
#define I2C_READ        0b11000001

#define SI_CLK0_CONTROL 16            // Register definitions
#define SI_CLK1_CONTROL 17
#define SI_CLK2_CONTROL 18
#define SI_SYNTH_PLL_A  26
#define SI_SYNTH_PLL_B  34
#define SI_SYNTH_MS_0   42
#define SI_SYNTH_MS_1   50
#define SI_SYNTH_MS_2   58
#define SI_PLL_RESET    177

#define SI_R_DIV_1      0b00000000  // R-division ratio definitions
#define SI_R_DIV_2      0b00010000
#define SI_R_DIV_4      0b00100000
#define SI_R_DIV_8      0b00110000
#define SI_R_DIV_16     0b01000000
#define SI_R_DIV_32     0b01010000
#define SI_R_DIV_64     0b01100000
#define SI_R_DIV_128    0b01110000

#define SI_CLK_SRC_PLL_A 0b00000000
#define SI_CLK_SRC_PLL_B 0b00100000

#define XTAL_FREQ       25000000    // Crystal frequency for Hans' board

uint8_t i2cStart(){
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

  while (!(TWCR & (1<<TWINT))) ;

  return (TWSR & 0xF8);
}

void i2cStop(){
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

  while ((TWCR & (1<<TWSTO))) ;
}

uint8_t i2cByteSend(uint8_t data){
  TWDR = data;

  TWCR = (1<<TWINT) | (1<<TWEN);

  while (!(TWCR & (1<<TWINT))) ;

  return (TWSR & 0xF8);
}

uint8_t i2cByteRead(){
  TWCR = (1<<TWINT) | (1<<TWEN);

  while (!(TWCR & (1<<TWINT))) ;

  return (TWDR);
}

uint8_t i2cSendRegister(uint8_t reg, uint8_t data){
  uint8_t stts;

  stts = i2cStart();
  if (stts != I2C_START)
    return 1;

  stts = i2cByteSend(I2C_WRITE);
  if (stts != I2C_SLA_W_ACK)
    return 2;

  stts = i2cByteSend(reg);
  if (stts != I2C_DATA_ACK)
    return 3;

  stts = i2cByteSend(data);
  if (stts != I2C_DATA_ACK)
    return 4;

  i2cStop();

  return 0;
}

uint8_t i2cReadRegister(uint8_t reg, uint8_t *data){
  uint8_t stts;

  stts = i2cStart();
  if (stts != I2C_START)
    return 1;

  stts = i2cByteSend(I2C_WRITE);
  if (stts != I2C_SLA_W_ACK)
    return 2;

  stts = i2cByteSend(reg);
  if (stts != I2C_DATA_ACK)
    return 3;

  stts = i2cStart();
  if (stts != I2C_START_RPT)
    return 4;

  stts = i2cByteSend(I2C_READ);
  if (stts != I2C_SLA_R_ACK)
    return 5;

  *data = i2cByteRead();

  i2cStop();

  return 0;
}

// Init TWI (I2C)
//
void i2cInit(){
  TWBR = 92;
  TWSR = 0;
  TWDR = 0xFF;
  PRR = 0;
}

////////////////////////////////////////////////////////////////////////
// Set up specified PLL with mult, num and denom
// mult is 15..90
// num is 0..1,048,575 (0xFFFFF)
// denom is 0..1,048,575 (0xFFFFF)
///////////////////////////////////////////////////////////////////////

void setupPLL(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom){
  uint32_t P1;                            // PLL config register P1
  uint32_t P2;                            // PLL config register P2
  uint32_t P3;                            // PLL config register P3

  P1 = (uint32_t)(128 * ((float)num / (float)denom));
  P1 = (uint32_t)(128 * (uint32_t)(mult) + P1 - 512);
  P2 = (uint32_t)(128 * ((float)num / (float)denom));
  P2 = (uint32_t)(128 * num - denom * P2);
  P3 = denom;

  i2cSendRegister(pll + 0, (P3 & 0x0000FF00) >> 8);
  i2cSendRegister(pll + 1, (P3 & 0x000000FF));
  i2cSendRegister(pll + 2, (P1 & 0x00030000) >> 16);
  i2cSendRegister(pll + 3, (P1 & 0x0000FF00) >> 8);
  i2cSendRegister(pll + 4, (P1 & 0x000000FF));
  i2cSendRegister(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
  i2cSendRegister(pll + 6, (P2 & 0x0000FF00) >> 8);
  i2cSendRegister(pll + 7, (P2 & 0x000000FF));
}

////////////////////////////////////////////////////////////////////////
// Set up MultiSynth with integer divider and R divider
// R divider is the bit value which is OR'ed onto the appropriate
// register, it is a #define in si5351a.h
////////////////////////////////////////////////////////////////////////

void setupMultisynth(uint8_t synth, uint32_t divider, uint8_t rDiv){
  uint32_t P1;                          // Synth config register P1
  uint32_t P2;                          // Synth config register P2
  uint32_t P3;                          // Synth config register P3

  P1 = 128 * divider - 512;
  P2 = 0;                               // P2 = 0, P3 = 1 forces an integer value for the divider
  P3 = 1;

  i2cSendRegister(synth + 0, (P3 & 0x0000FF00) >> 8);
  i2cSendRegister(synth + 1, (P3 & 0x000000FF));
  i2cSendRegister(synth + 2, ((P1 & 0x00030000) >> 16) | rDiv);
  i2cSendRegister(synth + 3, (P1 & 0x0000FF00) >> 8);
  i2cSendRegister(synth + 4, (P1 & 0x000000FF));
  i2cSendRegister(synth + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
  i2cSendRegister(synth + 6, (P2 & 0x0000FF00) >> 8);
  i2cSendRegister(synth + 7, (P2 & 0x000000FF));
}

////////////////////////////////////////////////////////////////////////
// Switches off Si5351a output
// Example: si5351aOutputOff(SI_CLK0_CONTROL);
// will switch off output CLK0
////////////////////////////////////////////////////////////////////////

void si5351aOutputOff(uint8_t clk){
  i2cSendRegister(clk, 0x80);           // Refer to SiLabs AN619 to see
                                        //bit values - 0x80 turns off the output stage
}

////////////////////////////////////////////////////////////////////////
// Set CLK0 output ON and to the specified frequency
// Frequency is in the range 1MHz to 150MHz
// Example: si5351aSetFrequency(10000000);
// will set output CLK0 to 10MHz
//
// This example sets up PLL A
// and MultiSynth 0
// and produces the output on CLK0
////////////////////////////////////////////////////////////////////////

void si5351aSetFrequency(uint32_t frequency){
  uint32_t pllFreq;
  uint32_t xtalFreq = XTAL_FREQ;
  uint32_t l;
  float f;
  uint8_t mult;
  uint32_t num;
  uint32_t denom;
  uint32_t divider;

  divider = 900000000 / frequency;  // Calculate the division ratio. 900,000,000 is the maximum                        // internal
                                                 // PLL frequency: 900MHz
  if (divider % 2) divider--;             // Ensure an even integer
                                                //division ratio

  pllFreq = divider * frequency;      // Calculate the pllFrequency:
                                                //the divider * desired output frequency

  mult = pllFreq / xtalFreq;            // Determine the multiplier to
                                                //get to the required pllFrequency
  l = pllFreq % xtalFreq;                 // It has three parts:
  f = l;                                        // mult is an integer that must be in the range 15..90
  f *= 1048575;                           // num and denom are the fractional parts, the numerator and denominator
  f /= xtalFreq;                           // each is 20 bits (range 0..1048575)
  num = f;                                  // the actual multiplier is mult + num / denom
  denom = 1048575;                    // For simplicity we set the denominator to the maximum 1048575

                                          // Set up PLL A with the calculated  multiplication ratio
  setupPLL(SI_SYNTH_PLL_A, mult, num, denom);
                                          // Set up MultiSynth divider 0, with the calculated divider.
                                          // The final R division stage can divide by a power of two, from                                               // 1..128.
                                          // reprented by constants SI_R_DIV1 to SI_R_DIV128 (see                                                       // si5351a.h header file)
                                          // If you want to output frequencies below 1MHz, you have to use                                           // the
                                          // final R division stage
  setupMultisynth(SI_SYNTH_MS_0, divider, SI_R_DIV_1);
                                          // Reset the PLL. This causes a glitch in the output. For small                                                 // changes to
                                          // the parameters, you don't need to reset the PLL, and there is                                             // no glitch
  i2cSendRegister(SI_PLL_RESET, 0xA0);
                                          // Finally switch on the CLK0 output (0x4F)
                                          // and set the MultiSynth0 input to be PLL A
  i2cSendRegister(SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);
}

/////////////////////////////////////////////////////////// <<JA2GQP >>
// Power strength
// Example: SetPower(1);
// The setting range is from 1 to 4
////////////////////////////////////////////////////////////////////////

void SetPower(byte power){
  switch(power){
    case 1:
      i2cSendRegister(SI_CLK0_CONTROL,76);  // CLK0 strength = 2mA; power level ~ -10dB
      break;
    case 2:
      i2cSendRegister(SI_CLK0_CONTROL,77);  // CLK0 strength = 4mA; power level ~ -6dB
      break;
    case 3:
      i2cSendRegister(SI_CLK0_CONTROL,78);  // CLK0 strength = 6mA; power level ~ -3dB
      break;
    case 4:
      i2cSendRegister(SI_CLK0_CONTROL,79);  // CLK0 strength = 8mA; power level := 0dB
      break;
    default:
      i2cSendRegister(SI_CLK0_CONTROL,76);  // CLK0 strength = 2mA; power level ~ -10dB
      break;
  }
}

Sketch

ベースとなるスケッチは、JA2NKD松浦OMの2.2"TFT版AD9850 DDS VFOで、si5351a PLLに移植。オリジナルと異なる点は、Arduino UNO/nano対応とメモリ機能。


//////////////////////////////////////////////////////////////////////////////
//       Copyright©2016.JA2GQP.All rights reserved.
//            si5351a PLL VFO Ver1.0      << JA2NKD sketch is based >>      
//                                                    2016/8/18
//                                                    JA2GQP  
//                      << Aruduino IDE 1.6.X >>
//
//----------------------------------------------------------------------------  
//  Function
//    1.RIT Operation(-10kHZ to 10kHZ)
//    2.STEP(10,100,1k,10k,100k)
//    3.Memory Operation is Push RIT
//    4.Protection Operation At The Time Of Transmission
//    5.Memory 4ch(LSB,USB.CW,AM)
//    6.IF shift
//----------------------------------------------------------------------------  
//  Library
//          <Rotary.h>    https://github.com/brianlow/Rotary
//          "Ucglib.h"    https://github.com/olikraus/ucglib
//
//////////////////////////////////////////////////////////////////////////////

//---------- include Files ---------------

#include "si5351a.h"
#include <SPI.h>
#include <Rotary.h>
#include <EEPROM.h>
#include "Ucglib.h"

//----------   TFT setting  ---------------

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

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

/////////////////////
// Ucglib Assign
/////////////////////

  Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);

//----------   Encorder setting  ---------------

const byte  ENC_A = 2;                     // Encorder A
const byte  ENC_B = 3;                     // Encoeder B

  Rotary r=Rotary(ENC_A,ENC_B);

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

const byte modeout1 = 7;                  // DIO7
const byte modeout2 = 12;                // DIO12
const byte modesw = 6;                    // DIO6
const byte stepsw = 4;                     // DIO4
const byte ritsw = 5;                       // DIO5
const byte txsw = A3;                      // A3
const byte s_meter = A0;                  // A0
const byte t_meter = A1;                  // A1

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

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 --------------------

const long  DEF_FRQ  =  7050000L;         // Init Frequency
const long  DEF_FMAX =  7200000L;         // Frequency Max
const long  DEF_FMIN =  7000000L;         //           Min
const long  DEF_RLSB = 10698500L;         // RX IF Shift LSB
const long  DEF_RUSB = 10701500L;         //             USB
const long  DEF_RCW  = 10699200L;         //             CW
const long  DEF_RAM  = 10700000L;         //             AM
const long  DEF_TLSB = 10698500L;         // TX IF Shift LSB
const long  DEF_TUSB = 10701500L;         //             USB
const long  DEF_TCW  = 10700000L;         //             CW
const long  DEF_TAM  = 10700000L;         //             AM

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

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

long freq    = DEF_FRQ;                   // Frequency data
long freqb;                                     //           old data
long freqmax = DEF_FMAX;              // VFO Upper Limit
long freqmin = DEF_FMIN;                //     Lower Limit
long freqold = 0;
long freqrit = 0;
String freqt=String(freq);
long ifshift = 0;
long ifshiftLSB = DEF_RLSB;               // RX IF Shift LSB
long ifshiftUSB = DEF_RUSB;              //             USB
long ifshiftCW = DEF_RCW;                 //             CW
long ifshiftAM = DEF_RAM;                 //             AM
long txshiftLSB = DEF_TLSB;              // TX IF Shift LSB
long txshiftUSB = DEF_TUSB;             //             USB
long txshiftCW = DEF_TCW;                //             CW
long txshiftAM = DEF_TAM;                //             AM
long ddsfreq = 0;                         // VFO data
long ddsfreqb;                            //     old
char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1;
int ddsstep=2;
int rit=0;
int fstep = DEF_STP;                      // Default Step
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
byte Byt_Chnb;                            //            Old

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

void setup() {
  i2cInit();                             // I2c initialaz

  delay(100);
  ucg.begin(UCG_FONT_MODE_TRANSPARENT);
  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();

  screen01();

  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

  modeset();                             // modeset * 4 times
  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);}
  if (digitalRead(txsw)==LOW){txset();}

    if(Byt_Chnb != Byt_Chn){             // CH SW OLD != NEW?
      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 ------------

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  ---------          

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  -------------------

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  --------  

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 DDS set  ---------------      

void Fnc_Dds(long frequency){
  if(ddsfreq != ddsfreqb){
    si5351aSetFrequency(frequency);
    SetPower(1);
    ddsfreqb = ddsfreq;
  }
}

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

    Fnc_Dds(ddsfreq);                            // DDS out
 
    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){                          
  if (fmode==1){                              // 2016/8/3
    ifshift=ifshiftUSB;
    flagmode = 1;                             // 2016/8/3
    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){                          
  if(fmode==2){                              // 2016/8/3
    ifshift=ifshiftCW;
    flagmode = 2;                            // 2016/8/3
    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){                          
  if (fmode==3){                              // 2016/8/3
    ifshift=ifshiftAM;
    flagmode = 3;                             // 2016/8/3
    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){                          
  if (fmode==0){                              // 2016/8/3
    ifshift=ifshiftLSB;
    flagmode = 0;                             // 2016/8/3
    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++;                              
  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;
    Fnc_Dds(ddsfreq);                       // DDS Out
    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  ("si5351a PLL VFO Ver.1.0 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 (flagrit==0){
    ddsfreq=freq+ifshift;
    Fnc_Dds(ddsfreq);                               // DDS out
  }

  if(flagrit==1){
    ddsfreq=freq+ifshift+freqrit;
    Fnc_Dds(ddsfreq);                              // DDS out
  }

}





 

21 件のコメント:

Alex, US5EVD さんのコメント...

Beautiful synth. Beautiful display. But we need a second output
Si5351. But the memory of a little....

JA2GQP さんのコメント...

It will be realized by mega2560.
However, it is difficult by the UNO and the nano.

Alex, US5EVD さんのコメント...

YES, in the NANO difficult. Can try to cut font library, leave some big numbers (35 font size).

Alex, US5EVD さんのコメント...

I wanted to try, but could not figure out how the font is designed for this display. For monochrome display I was able to reduce library.

JA2GQP さんのコメント...

Please publish If you can Ucglib to the Compact.

Alex, US5EVD さんのコメント...

Please e- maile, i send file
us5evd()ukr.net

Alex, US5EVD さんのコメント...

replace UCG_FONT_SECTION ( "ucg_font_fub35_tr") in the file


/*
replace UCG_FONT_SECTION ( "ucg_font_fub35_tr") in the file "ucg font vector data"

use chars code only 32,45-57

*/

const ucg_fntpgm_uint8_t ucg_font_fub35_tr[733] UCG_FONT_SECTION("ucg_font_fub35_tr") = {
95,0,5,5,6,6,5,6,7,50,52,255,243,35,247,36,
250,6,111,13,86,

32,6,0,0,193,39, //spase





45,9,141,
33,211,40,248,1,8,

46,9,135,81,193,39,248,192,2,

47,
42,209,41,187,42,43,24,193,74,140,96,101,171,96,37,70,
176,18,35,88,217,42,88,137,17,172,196,8,86,182,10,86,
90,5,43,49,130,149,173,130,1,

48,73,217,40,67,238,81,
154,163,32,36,157,169,28,230,40,6,58,198,145,140,97,40,
99,24,203,16,198,50,194,177,140,112,44,35,28,203,8,199,
114,191,101,132,99,25,225,88,134,48,150,33,140,101,8,67,
29,226,72,6,49,208,65,14,115,152,201,72,8,82,78,83,
16,0,

49,24,207,88,65,46,58,14,82,20,178,136,15,76,
161,17,11,73,204,129,206,255,255,31,

50,47,217,40,67,46,
90,216,147,162,51,149,106,32,6,25,71,58,132,161,142,112,
168,67,158,197,67,30,17,129,40,152,188,116,46,121,169,135,
188,228,33,16,137,31,248,3,26,

51,61,216,40,67,174,89,
214,131,34,51,145,106,28,6,17,7,58,196,145,12,113,164,
35,158,224,17,15,151,44,134,41,46,121,75,107,34,34,143,
120,72,67,30,209,81,174,116,4,4,29,226,56,199,168,200,
100,34,244,172,229,0,

52,61,218,24,65,110,75,160,242,86,
142,213,26,102,132,131,25,225,88,134,56,150,33,14,101,140,
35,29,227,72,6,57,144,81,14,100,148,227,24,230,204,24,
231,40,6,58,200,129,14,98,164,131,124,224,31,8,222,49,
207,71,0,

53,52,216,40,65,110,168,70,125,227,136,231,27,
199,57,194,82,40,82,141,106,36,5,17,7,58,196,145,142,
96,168,35,158,139,142,114,210,17,142,116,4,228,28,163,26,
84,145,144,179,152,3,0,

54,75,217,40,67,46,82,154,163,
32,36,25,170,32,229,32,200,57,198,129,14,113,200,147,52,
228,65,142,115,136,165,28,161,33,71,112,198,37,22,130,8,
197,32,33,65,71,64,148,17,16,245,166,142,112,40,67,28,
202,16,8,58,4,130,142,129,152,163,76,102,58,81,114,154,
130,0,

55,47,216,40,65,46,248,7,168,120,130,71,60,32,
2,15,136,192,3,34,240,128,168,135,64,228,33,16,129,7,
68,224,1,81,15,129,200,67,32,242,16,136,188,228,33,12,
0,

56,76,217,40,67,174,97,22,132,166,82,145,106,36,37,
17,200,65,196,145,14,113,164,67,28,233,16,71,58,196,145,
142,113,156,131,32,229,56,81,114,218,178,32,36,25,164,32,
3,57,199,56,210,17,142,101,132,99,25,225,88,174,245,36,
40,29,2,57,136,184,70,69,168,19,169,198,0,

57,71,217,
40,67,238,89,152,163,162,51,21,138,32,6,25,7,58,134,
145,144,112,168,35,28,234,8,135,122,151,146,112,160,36,32,
101,17,151,120,194,49,156,112,16,70,28,199,40,135,52,228,
153,56,208,49,14,116,140,227,32,228,40,136,153,140,132,32,
229,52,5,1,


};

Alex, US5EVD さんのコメント...

If the crop is similar to the rest of the fonts, it will add about 3kb. Total will 7K. It may be enough?

Unknown さんのコメント...

how to eliminate the loud clicks when frequency hopping?

JA2GQP さんのコメント...

This problem is difficult in PLL.

Unknown さんのコメント...

Hello
When I use tft 1.44inch I have 27% free space, is any chance to run clk2 for bfo

JA2GQP さんのコメント...

When running in a bfo, please tell me.

ub7kpv さんのコメント...

Hi
Good project! It inspired me to make my own, take a look https://www.youtube.com/watch?v=76_tweVlOxc

JA2GQP さんのコメント...

Hi.
I saw. It is a good easy to use VFO.

Robert KH2BR さんのコメント...

HI Akio,
I have a new BITX 40.
The I.F. is 12mhz
I need 5MHZ L.O. = 7.0 Mhz 4.7MHZ =7.3 Mhz
Display should be 7.0 Mhz (L.O.) 5 MHZ 7.3 MHZ (L.O.) 4.7 Mhz
How do I change display frequency? I have L.O. set ok.
DEF_RCW = -2300000L; // CW.
Can you help ? Robert KH2BR rholsti@icloud.com

Unknown さんのコメント...

Hi,Akio
Add sketch under 1.8 inch screen st775 please, synthesizer on si5351.

Unknown さんのコメント...

Hi Akio San,
Have you designed a pcb for this?

JA2GQP さんのコメント...

Sorry no PCB.

JA2GQP さんのコメント...

コメント有難うございます。
AD9850でVFOを作るとの事、了解です。頑張って作ってください。

EP3AS さんのコメント...

Hello Mr. ja2gqp
I had a request from you
Please send me the hex DDS si5351 file
We haven't been able to fix it for a long time and now we need the hex file
Our LCD type is TFT ILI 9341
Its size is 8 * 2 inches
Please email the hex file to me
This is my email address:
ep3as.83@gmail.com
Thanks a lot
73

JA2GQP さんのコメント...

Hi EP3AS.
I'm sorry. I don't have my development environment anymore, so I can't handle it.