近頃バリキャップの入手が難しくなってきている。そこで、バリキャップの代替をする為に、測定治具を作った。LC meterにアダプタを付加する方式で、既存のLC meterの改造を行わない事にした。ツマミが付いた部分が、バリキャップ測定治具である。
測定治具は、アダプタ方式にしたので、取付/取外しが容易な構造にした。
回路図
バリキャップ代替
手持品の代替として使えそうな物の、特性を測った。
無線機の製作記録の全てを公開してます。 https://sites.google.com/view/ja2gqpから必要なファイルをダウンロードできます。 このBlogは、詳細な説明は一切行っておらず、ある程度のスキルが要求されます。 質問に応じますが、カスタマイズは対応しません。尚、コメントは誰でも出来る様に変更しました。
2016年12月9日金曜日
2016年11月17日木曜日
Nextion TFT
Nextion 3.2"TFTを入手した。 このLCDは、インテリジェントTFTで、制御機器(PC,マイコンなど)からのシリアル通信で画面コントロールが出来る。最もシンプルの構成は、Nextionのみで動作する。マイコンなどによる画面制御では、メモリ、表示速度など神経を使わなければ出来ないアプリケーションも多々ある。表示部を分散した事で、より自由度の高いプログラムングが出来るであろう。今回、スイッチ画像を作り、タッチパネル操作でLED点灯/消灯る事が出来た。
開発は、 Nextion Editor とNextionに書き込む為の、USBアダプタ又は、マイクロSDカードが必要。SDカードは必須でなく、USBアダプタでもNextionに書込み出来る。SDカードを使う方が、書込み時間が少なく、お薦めである。
Nextion資料は、ライブラリ 、命令セット。また購入先は、こちら またはAliexpress、e-Bayなど。
NextionとUNOを使ったLチカ。画面をタッチすると、UNOのDIO(13)に接続のLEDが点灯/消灯する。
int charflag=0;
void setup() {
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop() {
if (Serial.available()>1)
{
if (charflag)
{
char2=Serial.read();
if (char2==0) digitalWrite(13,HIGH);
else if (char2==0x01) digitalWrite(13,LOW);
charflag=0;
}
else
{
char1=Serial.read();
if(char1==0x65) charflag=1;
}
}
}
NextionのHMIファイル、ArduinoスケッチなどダウンロードサイトのNextionフォルダからDownload可能。
開発は、 Nextion Editor とNextionに書き込む為の、USBアダプタ又は、マイクロSDカードが必要。SDカードは必須でなく、USBアダプタでもNextionに書込み出来る。SDカードを使う方が、書込み時間が少なく、お薦めである。
Nextion資料は、ライブラリ 、命令セット。また購入先は、こちら またはAliexpress、e-Bayなど。
NextionとUNOを使ったLチカ。画面をタッチすると、UNOのDIO(13)に接続のLEDが点灯/消灯する。
スケッチ
int char1,char2;int charflag=0;
void setup() {
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop() {
if (Serial.available()>1)
{
if (charflag)
{
char2=Serial.read();
if (char2==0) digitalWrite(13,HIGH);
else if (char2==0x01) digitalWrite(13,LOW);
charflag=0;
}
else
{
char1=Serial.read();
if(char1==0x65) charflag=1;
}
}
}
NextionのHMIファイル、ArduinoスケッチなどダウンロードサイトのNextionフォルダからDownload可能。
2016年10月27日木曜日
si5351a_TFT_Ver3.1 VFO
JA2NKD松浦OM開発のAD9850_TFT_Ver3.1(Multi-Band対応)をsi5351aに移植した。今回、機能追加は行わなかったので、チップが異なる以外、全く同じである。このVFOは、EEPROM初期値設定を別スケッチで書込みを行っている。同OMのBlogを読んで、設定されたい。EEPROM初期値設定スケッチがバージョンアップされて齟齬が危惧される為、Download siteにvfo_v3_eepスケッチのコピーを保存した。 IDEは、1.6.12(最新版)を使った。
Arduino nano/UNO対応の回路図である。スイッチ入力がアナログポートを使ったレベルによる入力判定を行っている。
////////////////////////////////////////////////////////////////////////
// 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;
//#ifdef ARDUINO_AVR_MEGA2560
// PRR0 = 0;
//#else
PRR = 0;
//#endif
}
////////////////////////////////////////////////////////////////////////
// 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); // 2016/10/23 JA2GQP
// 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 drive strength = 2mA; power level ~ -10dB
break;
case 2:
i2cSendRegister(SI_CLK0_CONTROL,77); // CLK0 drive strength = 4mA; power level ~ -6dB
break;
case 3:
i2cSendRegister(SI_CLK0_CONTROL,78); // CLK0 drive strength = 6mA; power level ~ -3dB
break;
case 4:
i2cSendRegister(SI_CLK0_CONTROL,79); // CLK0 drive strength = 8mA; power level := 0dB
break;
default:
i2cSendRegister(SI_CLK0_CONTROL,76); // CLK0 drive strength = 2mA; power level ~ -10dB
break;
}
}
// Multi Band DDS VFO Ver3.1
// JA2NKD 2016.10.19
// Aruduino IDE 1.6.12
// Arduino nano/UNO
//
// <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
// "si5351a.h" https://sites.google.com/site/ja2gqp/
//---------------------------------------------------------------------------------
// si5351a transplant 2016/10/23 JA2GQP
// (si5351a.h is original hedder file.)
//---------------------------------------------------------------------------------
//---------- Library include ----------
#include "si5351a.h" // 2016/10/23 JA2GQP
#include <SPI.h>
#include <EEPROM.h>
#include <Rotary.h>
//#include <EF_AD9850.h> // 2016/10/23 JA2GQP
#include "Ucglib.h"
/*
* Hardware SPI Pins:
* Arduino nano sclk=13, data=11
*/
// I/O setting
const byte __CS=10;
const byte __DC=9;
const byte __RST=8;
const byte modeout1=7; // 2016/10/24 JA2GQP
const byte modeout2=12; //
const byte bandout1=4; //
const byte bandout2=5; //
const byte bandout3=6; //
const byte txsw=A3; //
const byte meterin=A0; //
const byte analogsw=A1; //
// EF_AD9850 AD9850(ddsclock,ddsfqup,ddsreset,ddsdata); // 2016/10/23 JA2GQP
Rotary r=Rotary(2,3);
Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);
//---------- Variable setting ----------
long romf[4];
long freq =7100000;
long freqmax=7200000;
long freqmin=7000000;
long freqold=0;
long freqrit=0;
String freqt=String(freq);
long ifshift = 0;
long ifshiftLSB =8998500; // VFO>frequency USB/LSB is turn over
long ifshiftUSB =9001500;
long ifshiftCW =8999200;
long ifshiftAM =9000000;
long txshiftLSB =8998500;
long txshiftUSB =9001500;
long txshiftCW =9000000;
long txshiftAM =9000000;
long ddsfreq = 0;
long ddsfreqb; // 2016/10/23 JA2GQP
char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1;
int ddsstep=2;
int rit=0;
int fstep=100;
int steprom=1;
int fmode=3;
int fmodeold=1;
int flagrit=0;
int fritold=0;
int flagmode=0;
int meterval1=0;
int tmeterval=0;
int romadd=0;
int analogdata=0;
int band=0;
int bandmax=8;
//---------- Initialization Program ----------------------
void setup() {
i2cInit(); // I2c initialaz 2016/10/23 JA2GQP
delay(100);
ucg.begin(UCG_FONT_MODE_TRANSPARENT);
//ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
ucg.setRotate270();
pinMode (bandout1,OUTPUT);
pinMode (bandout2,OUTPUT);
pinMode (bandout3,OUTPUT);
pinMode(txsw,INPUT_PULLUP);
pinMode(modeout1,OUTPUT);
pinMode(modeout2,OUTPUT);
PCICR |=(1<<PCIE2);
PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
sei();
// AD9850.init(); // 2016/10/23 JA2GQP
// AD9850.reset(); // 2016/10/23 JA2GQP
band=EEPROM.read(0x01);
romadd=0x010+(band*0x10);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
banddataout();
screen01();
chlcd();
if (fmode==0){fmode=3;}
else{fmode=fmode-1;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
}
//---------- Main program ---------------------------------
void loop() {
analogdata=analogRead(analogsw);
// ucg.setPrintPos(12,157);
// ucg.setColor(255,255,255);
// ucg.print(analogdata);
if (analogdata<50){
setstep();
} else if (analogdata<300){
modeset();
} else if (analogdata<600){
setrit();
}else if (analogdata<750){
bandcall();
}else if (analogdata<980){
bandwrite();
}
if (digitalRead(txsw)==LOW){txset();}
if (flagrit==1){
if (freqrit == fritold){
meter();
}
if (freqrit!=fritold){
ddswrite();
ritlcd();
fritold=freqrit;
}
}
else{
if (freq == freqold){
meter();
}
ddswrite();
freqt=String(freq);
freqlcd();
freqold=freq;
}
}
//---------- Function DDS set --------------- 2016/10/23 JA2GQP
void Fnc_Dds(long frequency){
if(ddsfreq != ddsfreqb){
si5351aSetFrequency(frequency);
SetPower(1);
ddsfreqb = ddsfreq;
}
}
//---------- meter --------------------------
void meter(){
meterval1=analogRead(meterin);
meterval1=meterval1/50;
if (meterval1>15){meterval1=15;}
int sx1=sx1+(meterval1*17);
sx1=sx1+41;
int sx2=0;
sx2=sx2+(40+((15-meterval1)*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<=meterval1;i++){
if (i<=9){
ucg.setColor(0,255,255);
ucg.print("-");
}
else{
ucg.setColor(255,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;
}
}
}
}
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 (fmode==0){ddsfreq=freq+txshiftLSB;}
if (fmode==1){ddsfreq=freq+txshiftUSB;}
if (fmode==2){ddsfreq=freq+txshiftCW;}
if (fmode==3){ddsfreq=freq+txshiftAM;}
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("ON AIR");
while(digitalRead(txsw) == LOW){
meter();
}
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30); //45
ddswrite();
interrupts();
}
//------------- Mode change(LSB-USB-CW-AM) ------------
void modeset(){
ucg.setFont(ucg_font_fub17_tr);
ucg.setPrintPos(82,82);
ucg.setColor(0,0,0);
ucg.print("USB");
ucg.setPrintPos(12,82);
ucg.print("LSB");
ucg.setPrintPos(82,112);
ucg.print("A M");
ucg.setPrintPos(12,112);
ucg.print("C W");
if (fmode==0){
ifshift=ifshiftUSB;
ucg.setColor(255,255,0);
ucg.setPrintPos(82,82);
ucg.print("USB");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,LOW);
}
if(fmode==1){
ifshift=ifshiftCW;
ucg.setPrintPos(12,112);
ucg.setColor(255,255,0);
ucg.print("C W");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,HIGH);
}
if (fmode==2){
ifshift=ifshiftAM;
ucg.setPrintPos(82,112);
ucg.setColor(255,255,0);
ucg.print("A M");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,HIGH);
}
if (fmode==3){
ifshift=ifshiftLSB;
ucg.setPrintPos(12,82);
ucg.setColor(255,255,0);
ucg.print("LSB");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,LOW);
}
fmode=fmode+1;
if (fmode==4){fmode=0;}
ddswrite();
while(analogRead(analogsw) <1000);
}
//------------ 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");
ritlcd();
}
else {
flagrit=0;
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS Out 2016/10/23 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(analogRead(analogsw) <1000);
}
//----------- 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(analogRead(analogsw) < 1000);
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());
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));
}
*/
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>=1000){
ucg.setPrintPos(202,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
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<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<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>=1000000){
ucg.setPrintPos(103,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
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<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));
}
/*
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));
}
}
*/
}
//----------- Basic Screen -------------------------
void screen01(){
ucg.setColor(255,255,255);
ucg.drawRFrame(1,1,314,55,5);
ucg.drawRFrame(2,2,312,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.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(10,210);
ucg.print(" S: 1-----3-------6-------9---Over--------");
ucg.setPrintPos(10,177);
ucg.print(" P: 1-----3-----5-----------10--------------");
ucg.setPrintPos(10,230);
ucg.setColor(235,0,200);
ucg.print(" Home Blew DDS-VFO Ver3.1 JA2NKD");
ucg.setFont(ucg_font_fub35_tr);
ucg.setColor(0,255,0);
// ucg.setPrintPos(19,45);
// ucg.print("4");
// ucg.setPrintPos(47,45);
// ucg.print("3");
// ucg.setPrintPos(75,45);
// ucg.print("7");
// ucg.setPrintPos(103,45);
// ucg.print(".");
ucg.setPrintPos(273,45);
ucg.print("0");
}
//---------- DDS Frequency write -----------
void ddswrite(){
if (flagrit==0){
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
if(flagrit==1){
ddsfreq=freq+ifshift+freqrit;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
}
//---------- Band data call from eeprom ----------
void bandcall(){
band=band+1;
if (band>(bandmax-1)){band=0;}
romadd=0x010+(band*0x010);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (fmode >=1 ){
fmode=fmode-1;
}else if (fmode==0){
fmode=3;
}
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
banddataout();
chlcd();
}
//---------- Band data write to eeprom ----------
void bandwrite(){
romadd=0x010+(band*0x010);
// for (int i=0;i<3;i++){
eepwrite(freq,romadd);
// }
EEPROM.write(0x001,band);
EEPROM.write(romadd+12,fmode);
if (fstep==10){steprom=1;}
if (fstep==100){steprom=2;}
if (fstep==1000){steprom=3;}
if (fstep==10000){steprom=4;}
EEPROM.write(romadd+13,steprom);
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("Complete!!");
delay (500);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30);
//ucg.drawBox(41,145,270,16);
}
//---------- EEPROM Write(4byte) subroutine ----------
void eepwrite(unsigned long f0,int epadd){
for (int i=0; i<=3;i++){
EEPROM.write(epadd+i,f0%256);
f0=f0/256;
}
}
//---------- EEPROM Read(4byte) subroutin ----------
unsigned long eepread(int epadd){
unsigned long f0=0;
for (int i=3; i >=0 ;i--){
f0=f0*256+EEPROM.read(epadd+i);
}
return f0;
}
//---------- Band data output I/O ----------
void banddataout(){
digitalWrite(bandout1,LOW);
digitalWrite(bandout2,LOW);
digitalWrite(bandout3,LOW);
if (band==0){}
if (band==1){
digitalWrite( bandout1,HIGH);
}
if (band==2){
digitalWrite(bandout2,HIGH);
}
if (band==3){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
}
if (band==4){
digitalWrite(bandout3,HIGH);
}
if (band==5){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==6){
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==7){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
}
//---------- Band No.(Chanel No.) write to LCD ----------
void chlcd(){
ucg.setColor(0,0,0);
ucg.drawBox(5,120,80,20);
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(12,137);
ucg.setColor(255,255,255);
ucg.print("CH: ");
ucg.print(band+1);
}
Arduino nano/UNO対応の回路図である。スイッチ入力がアナログポートを使ったレベルによる入力判定を行っている。
ヘッダーファイル
si5351a.hは、スケッチと同じフォルダーに入れる事。Download siteにヘッダーファイル、スケッチ、vfo_v3_eepを保存した。////////////////////////////////////////////////////////////////////////
// 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;
//#ifdef ARDUINO_AVR_MEGA2560
// PRR0 = 0;
//#else
PRR = 0;
//#endif
}
////////////////////////////////////////////////////////////////////////
// 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); // 2016/10/23 JA2GQP
// 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 drive strength = 2mA; power level ~ -10dB
break;
case 2:
i2cSendRegister(SI_CLK0_CONTROL,77); // CLK0 drive strength = 4mA; power level ~ -6dB
break;
case 3:
i2cSendRegister(SI_CLK0_CONTROL,78); // CLK0 drive strength = 6mA; power level ~ -3dB
break;
case 4:
i2cSendRegister(SI_CLK0_CONTROL,79); // CLK0 drive strength = 8mA; power level := 0dB
break;
default:
i2cSendRegister(SI_CLK0_CONTROL,76); // CLK0 drive strength = 2mA; power level ~ -10dB
break;
}
}
スケッチ
//----------------------------------------------------------------------------------// Multi Band DDS VFO Ver3.1
// JA2NKD 2016.10.19
// Aruduino IDE 1.6.12
// Arduino nano/UNO
//
// <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
// "si5351a.h" https://sites.google.com/site/ja2gqp/
//---------------------------------------------------------------------------------
// si5351a transplant 2016/10/23 JA2GQP
// (si5351a.h is original hedder file.)
//---------------------------------------------------------------------------------
//---------- Library include ----------
#include "si5351a.h" // 2016/10/23 JA2GQP
#include <SPI.h>
#include <EEPROM.h>
#include <Rotary.h>
//#include <EF_AD9850.h> // 2016/10/23 JA2GQP
#include "Ucglib.h"
/*
* Hardware SPI Pins:
* Arduino nano sclk=13, data=11
*/
// I/O setting
const byte __CS=10;
const byte __DC=9;
const byte __RST=8;
const byte modeout1=7; // 2016/10/24 JA2GQP
const byte modeout2=12; //
const byte bandout1=4; //
const byte bandout2=5; //
const byte bandout3=6; //
const byte txsw=A3; //
const byte meterin=A0; //
const byte analogsw=A1; //
// EF_AD9850 AD9850(ddsclock,ddsfqup,ddsreset,ddsdata); // 2016/10/23 JA2GQP
Rotary r=Rotary(2,3);
Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);
//---------- Variable setting ----------
long romf[4];
long freq =7100000;
long freqmax=7200000;
long freqmin=7000000;
long freqold=0;
long freqrit=0;
String freqt=String(freq);
long ifshift = 0;
long ifshiftLSB =8998500; // VFO>frequency USB/LSB is turn over
long ifshiftUSB =9001500;
long ifshiftCW =8999200;
long ifshiftAM =9000000;
long txshiftLSB =8998500;
long txshiftUSB =9001500;
long txshiftCW =9000000;
long txshiftAM =9000000;
long ddsfreq = 0;
long ddsfreqb; // 2016/10/23 JA2GQP
char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1;
int ddsstep=2;
int rit=0;
int fstep=100;
int steprom=1;
int fmode=3;
int fmodeold=1;
int flagrit=0;
int fritold=0;
int flagmode=0;
int meterval1=0;
int tmeterval=0;
int romadd=0;
int analogdata=0;
int band=0;
int bandmax=8;
//---------- Initialization Program ----------------------
void setup() {
i2cInit(); // I2c initialaz 2016/10/23 JA2GQP
delay(100);
ucg.begin(UCG_FONT_MODE_TRANSPARENT);
//ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
ucg.setRotate270();
pinMode (bandout1,OUTPUT);
pinMode (bandout2,OUTPUT);
pinMode (bandout3,OUTPUT);
pinMode(txsw,INPUT_PULLUP);
pinMode(modeout1,OUTPUT);
pinMode(modeout2,OUTPUT);
PCICR |=(1<<PCIE2);
PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
sei();
// AD9850.init(); // 2016/10/23 JA2GQP
// AD9850.reset(); // 2016/10/23 JA2GQP
band=EEPROM.read(0x01);
romadd=0x010+(band*0x10);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
banddataout();
screen01();
chlcd();
if (fmode==0){fmode=3;}
else{fmode=fmode-1;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
}
//---------- Main program ---------------------------------
void loop() {
analogdata=analogRead(analogsw);
// ucg.setPrintPos(12,157);
// ucg.setColor(255,255,255);
// ucg.print(analogdata);
if (analogdata<50){
setstep();
} else if (analogdata<300){
modeset();
} else if (analogdata<600){
setrit();
}else if (analogdata<750){
bandcall();
}else if (analogdata<980){
bandwrite();
}
if (digitalRead(txsw)==LOW){txset();}
if (flagrit==1){
if (freqrit == fritold){
meter();
}
if (freqrit!=fritold){
ddswrite();
ritlcd();
fritold=freqrit;
}
}
else{
if (freq == freqold){
meter();
}
ddswrite();
freqt=String(freq);
freqlcd();
freqold=freq;
}
}
//---------- Function DDS set --------------- 2016/10/23 JA2GQP
void Fnc_Dds(long frequency){
if(ddsfreq != ddsfreqb){
si5351aSetFrequency(frequency);
SetPower(1);
ddsfreqb = ddsfreq;
}
}
//---------- meter --------------------------
void meter(){
meterval1=analogRead(meterin);
meterval1=meterval1/50;
if (meterval1>15){meterval1=15;}
int sx1=sx1+(meterval1*17);
sx1=sx1+41;
int sx2=0;
sx2=sx2+(40+((15-meterval1)*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<=meterval1;i++){
if (i<=9){
ucg.setColor(0,255,255);
ucg.print("-");
}
else{
ucg.setColor(255,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;
}
}
}
}
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 (fmode==0){ddsfreq=freq+txshiftLSB;}
if (fmode==1){ddsfreq=freq+txshiftUSB;}
if (fmode==2){ddsfreq=freq+txshiftCW;}
if (fmode==3){ddsfreq=freq+txshiftAM;}
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("ON AIR");
while(digitalRead(txsw) == LOW){
meter();
}
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30); //45
ddswrite();
interrupts();
}
//------------- Mode change(LSB-USB-CW-AM) ------------
void modeset(){
ucg.setFont(ucg_font_fub17_tr);
ucg.setPrintPos(82,82);
ucg.setColor(0,0,0);
ucg.print("USB");
ucg.setPrintPos(12,82);
ucg.print("LSB");
ucg.setPrintPos(82,112);
ucg.print("A M");
ucg.setPrintPos(12,112);
ucg.print("C W");
if (fmode==0){
ifshift=ifshiftUSB;
ucg.setColor(255,255,0);
ucg.setPrintPos(82,82);
ucg.print("USB");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,LOW);
}
if(fmode==1){
ifshift=ifshiftCW;
ucg.setPrintPos(12,112);
ucg.setColor(255,255,0);
ucg.print("C W");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,HIGH);
}
if (fmode==2){
ifshift=ifshiftAM;
ucg.setPrintPos(82,112);
ucg.setColor(255,255,0);
ucg.print("A M");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,HIGH);
}
if (fmode==3){
ifshift=ifshiftLSB;
ucg.setPrintPos(12,82);
ucg.setColor(255,255,0);
ucg.print("LSB");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,LOW);
}
fmode=fmode+1;
if (fmode==4){fmode=0;}
ddswrite();
while(analogRead(analogsw) <1000);
}
//------------ 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");
ritlcd();
}
else {
flagrit=0;
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS Out 2016/10/23 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(analogRead(analogsw) <1000);
}
//----------- 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(analogRead(analogsw) < 1000);
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());
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));
}
*/
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>=1000){
ucg.setPrintPos(202,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
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<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<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>=1000000){
ucg.setPrintPos(103,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
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<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));
}
/*
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));
}
}
*/
}
//----------- Basic Screen -------------------------
void screen01(){
ucg.setColor(255,255,255);
ucg.drawRFrame(1,1,314,55,5);
ucg.drawRFrame(2,2,312,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.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(10,210);
ucg.print(" S: 1-----3-------6-------9---Over--------");
ucg.setPrintPos(10,177);
ucg.print(" P: 1-----3-----5-----------10--------------");
ucg.setPrintPos(10,230);
ucg.setColor(235,0,200);
ucg.print(" Home Blew DDS-VFO Ver3.1 JA2NKD");
ucg.setFont(ucg_font_fub35_tr);
ucg.setColor(0,255,0);
// ucg.setPrintPos(19,45);
// ucg.print("4");
// ucg.setPrintPos(47,45);
// ucg.print("3");
// ucg.setPrintPos(75,45);
// ucg.print("7");
// ucg.setPrintPos(103,45);
// ucg.print(".");
ucg.setPrintPos(273,45);
ucg.print("0");
}
//---------- DDS Frequency write -----------
void ddswrite(){
if (flagrit==0){
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
if(flagrit==1){
ddsfreq=freq+ifshift+freqrit;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
}
//---------- Band data call from eeprom ----------
void bandcall(){
band=band+1;
if (band>(bandmax-1)){band=0;}
romadd=0x010+(band*0x010);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (fmode >=1 ){
fmode=fmode-1;
}else if (fmode==0){
fmode=3;
}
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
banddataout();
chlcd();
}
//---------- Band data write to eeprom ----------
void bandwrite(){
romadd=0x010+(band*0x010);
// for (int i=0;i<3;i++){
eepwrite(freq,romadd);
// }
EEPROM.write(0x001,band);
EEPROM.write(romadd+12,fmode);
if (fstep==10){steprom=1;}
if (fstep==100){steprom=2;}
if (fstep==1000){steprom=3;}
if (fstep==10000){steprom=4;}
EEPROM.write(romadd+13,steprom);
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("Complete!!");
delay (500);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30);
//ucg.drawBox(41,145,270,16);
}
//---------- EEPROM Write(4byte) subroutine ----------
void eepwrite(unsigned long f0,int epadd){
for (int i=0; i<=3;i++){
EEPROM.write(epadd+i,f0%256);
f0=f0/256;
}
}
//---------- EEPROM Read(4byte) subroutin ----------
unsigned long eepread(int epadd){
unsigned long f0=0;
for (int i=3; i >=0 ;i--){
f0=f0*256+EEPROM.read(epadd+i);
}
return f0;
}
//---------- Band data output I/O ----------
void banddataout(){
digitalWrite(bandout1,LOW);
digitalWrite(bandout2,LOW);
digitalWrite(bandout3,LOW);
if (band==0){}
if (band==1){
digitalWrite( bandout1,HIGH);
}
if (band==2){
digitalWrite(bandout2,HIGH);
}
if (band==3){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
}
if (band==4){
digitalWrite(bandout3,HIGH);
}
if (band==5){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==6){
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==7){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
}
//---------- Band No.(Chanel No.) write to LCD ----------
void chlcd(){
ucg.setColor(0,0,0);
ucg.drawBox(5,120,80,20);
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(12,137);
ucg.setColor(255,255,255);
ucg.print("CH: ");
ucg.print(band+1);
}
2016年9月18日日曜日
6 pole Crystal filter
今まで、G3UUR回路で水晶発振子分類のみ行っていたが、パラメータを求めるプログラムを探した所、フィルタのシュミレーションまで出来るDishal203が見つかった。G3UUR methodによる水晶発振子パラメータをDishal203を使って求め、6poleクリスタルフィルタを作った。水晶の選別とDishal203へのパラメータを正しく入力すれば、無調整で計算値に近似した特性が得られる事が判った。
switch ON(F1)、switch off(F2)を以降の説明で表す事とする。 この回路で注意すべき点は、33pFを使うが実装前にコンデンサ容量を実測(小数点第一位までの読み取り精度が必要)の事。製作したチェッカーは、実測値35.2pFであった。(470pFは、測定の必要なし)コンデンサの測定は、単体で行う事。Webの記事で基板などに実装時の容量と記した記事も見受けられるが、実装時の容量をCswとして入力すると、帯域巾が目標値より狭くなる傾向がある。
G3UUR methodによる水晶発振子チェッカー製作例。電源電圧9V(006P)で使っている。
水晶発振子チェッカーに周波数カウンタ(最少分解能1Hz程度)を繋ぎ、switch F1側(ON)とswitch F2側(off)の周波数を1Hz単位まで読み取る。更に、水晶発振子の容量を0.1pF単位まで読み取る。水晶発振子の選別は、F1周波数を許容差30Hz以内(目標帯域巾の1/100位)、1グループに纏める。許容差100Hzで選別などの記事もあるが、無調整では上手く出来ないであろう。また、許容差100Hzを超えるものは、選外とした方が良い。
Csw値(33pF単体で測定した値)、水晶発振子の静電容量(0.1pF単位まで必要)、F1(SW CLOSE)周波数、F2(SW OPEN)周波数を入力し、Calculateを選び演算する。(470pFは、そのまま入力する)この演算は、6個の水晶発振子全て行い、Lm(mH),Cm(fF),fs(kHz)を記録する。更に、6個のCp(pF),Lm(mH),Cm(fF),fs(kHz)平均値を求め、記録する。
Lm(mH),fs(kHz),Cp(pF)の各々の平均値を入力する。帯域巾B3db(kHz) 2.7、PB ripple(0..3db) 0.1,# of xtals(2..14) 6を各々入力する。各々の値を入力後、Calculateを選び演算する。また、フィルタ特性の数値データは、show Tableを選べば表示出来る。
FRMSによる実測スペクトル。計算したフィルタの入出力インピーダンスは、512.2Ωであった。FRMSの入出力インピーダンスが50Ωの為、2kΩのVR(約462Ω)をFRMS入出力に繋ぎ、抵抗マッチングさせた。抵抗による疑似マッチングにより、約10dBの損失がある。
フィルタ回路図。値は全て計算値。コンデンサは、実測し、合成容量で最大誤差0.3pF以内で実装。
基板サイズ 48 x 27
switch ON(F1)、switch off(F2)を以降の説明で表す事とする。 この回路で注意すべき点は、33pFを使うが実装前にコンデンサ容量を実測(小数点第一位までの読み取り精度が必要)の事。製作したチェッカーは、実測値35.2pFであった。(470pFは、測定の必要なし)コンデンサの測定は、単体で行う事。Webの記事で基板などに実装時の容量と記した記事も見受けられるが、実装時の容量をCswとして入力すると、帯域巾が目標値より狭くなる傾向がある。
G3UUR methodによる水晶発振子チェッカー製作例。電源電圧9V(006P)で使っている。
水晶発振子チェッカーに周波数カウンタ(最少分解能1Hz程度)を繋ぎ、switch F1側(ON)とswitch F2側(off)の周波数を1Hz単位まで読み取る。更に、水晶発振子の容量を0.1pF単位まで読み取る。水晶発振子の選別は、F1周波数を許容差30Hz以内(目標帯域巾の1/100位)、1グループに纏める。許容差100Hzで選別などの記事もあるが、無調整では上手く出来ないであろう。また、許容差100Hzを超えるものは、選外とした方が良い。
Csw値(33pF単体で測定した値)、水晶発振子の静電容量(0.1pF単位まで必要)、F1(SW CLOSE)周波数、F2(SW OPEN)周波数を入力し、Calculateを選び演算する。(470pFは、そのまま入力する)この演算は、6個の水晶発振子全て行い、Lm(mH),Cm(fF),fs(kHz)を記録する。更に、6個のCp(pF),Lm(mH),Cm(fF),fs(kHz)平均値を求め、記録する。
Lm(mH),fs(kHz),Cp(pF)の各々の平均値を入力する。帯域巾B3db(kHz) 2.7、PB ripple(0..3db) 0.1,# of xtals(2..14) 6を各々入力する。各々の値を入力後、Calculateを選び演算する。また、フィルタ特性の数値データは、show Tableを選べば表示出来る。
FRMSによる実測スペクトル。計算したフィルタの入出力インピーダンスは、512.2Ωであった。FRMSの入出力インピーダンスが50Ωの為、2kΩのVR(約462Ω)をFRMS入出力に繋ぎ、抵抗マッチングさせた。抵抗による疑似マッチングにより、約10dBの損失がある。
フィルタ回路図。値は全て計算値。コンデンサは、実測し、合成容量で最大誤差0.3pF以内で実装。
基板サイズ 48 x 27
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共通の回路図。
////////////////////////////////////////////////////////////////////////
// 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;
}
}
//////////////////////////////////////////////////////////////////////////////
// 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
}
}
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
}
}
登録:
投稿 (Atom)