PCBの様子
左側がADF4351をプラグイン仕様に改造し、メインボードに実装している。マイコンはPro mini 3.3V。oledの上側に有るのがレベル変換ボード。回路図
スケッチ
//////////////////////////////////////////////////////////////////////////////
// Copyright©2018.JA2GQP.All rights reserved.
// ADF4351 Pll Local oscillator
// 2026/2/4
// JA2GQP
//
//----------------------------------------------------------------------------
// The original is here.
// https://github.com/Giorgiofox/ADF4351-Arduino-LCDSHIELD
//
//////////////////////////////////////////////////////////////////////////////
#include "src/Rotary.h" // http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
#include <SPI.h>
#include <Tiny4kOLED.h>
#include "font/Tlcdnums14x24.h"
#include "font/Tfont5x7.h"
#include <EEPROM.h>
//------------------------ Define value ---------------------------------------
#define ENC_A 2 // encorder A
#define ENC_B 3 // B
#define LE 5 // LE
#define SW_STEP 6 // STEP SW
#define SW_REPT 7 // REPT SW
#define SW_TX 8 // TX SW
#define Xtal_Freq 12.8 // ADF4351 clock 12.8MHz
#define Scal_10kHz 0.01 // STEP 10kHz
#define DEF_Freq 115000 // default frequency 1150.00MHz
#define DEF_Step 100 // step 1MHz
#define DEF_Rsft -2000 // repeater shift -20.00MHz
///---------- Set Device -----------------------------
Rotary r = Rotary(ENC_A, ENC_B);
//---------- EEPROM Memory Address ------------------
#define Eep_Init 0x00 // Eep Init(1byte)
#define Eep_Resw 0x02 // REPT sw(1byte)
#define Eep_Step 0x04 // STEP(4byte)
#define Eep_Rsft 0x08 // REPT shift(4byte)
#define Eep_Freq 0x0c // Frequency(4byte)
//---- frequency limit offset
#define LOW_REPT -9000
#define HI_REPT 9000
//------------------------ Register definition --------------------------------
/////////////////////////////////////////
// ADF4351 Register initialize value
/////////////////////////////////////////
unsigned long registers[6] = { // 437.00MHz @12.8MHz
0x888008, // Register 0( 0x4580A8 @25MHz)
0x8008041, // 1(0x80080C9 )
0x4E42, // 2( 0x4E42 )
0x4B3, // 3( 0x4B3 )
0xB6703C, // 4( 0xBC803C )
0x580005} ; // 5( 0x580005 )
/////////////////////////////////////////
// Register declaration
/////////////////////////////////////////
double RFout,
REFin,
PFDRFout = Xtal_Freq, // X'tal frequency set
OutputChannelSpacing = Scal_10kHz, // Scaling(10kHz)
FRACF;
long RFint,
RFintold = 0,
INTA,
MOD,
FRAC;
byte OutputDivider;
/////////////////////////////////////////
// etc
/////////////////////////////////////////
const byte Int_End = 73; // Initial end code
byte Flg_eepWT = 0; // EEP Write Flag
byte Flg_Tx = 0;
byte Flg_Resw;
byte Flg_Re=0;
int Rsft = DEF_Rsft;
unsigned long Time_Passd; // int to hold the arduino miilis since startup
long Time_Mode; // Mode change Time
int32_t Enc_Step; // STEP
int8_t Enc_Dir = 0;
//------------------------ Setup ----------------------------------------------
void setup(){
pinMode(SW_STEP, INPUT_PULLUP);
pinMode(SW_REPT, INPUT_PULLUP);
pinMode(SW_TX, INPUT_PULLUP);
pinMode(LE, OUTPUT); // Setup pins
attachInterrupt(0, rotary_encoder, CHANGE);
attachInterrupt(1, rotary_encoder, CHANGE);
oled.begin();
oled.clear();
oled.on();
if(EEPROM.read(Eep_Init) != Int_End){ // Eep initialaz
delay(10);
eep_init();
}
else{
if(digitalRead(SW_STEP) == LOW){
delay(10);
eep_init();
fover_disp();
while (digitalRead(SW_STEP) == LOW);
}
}
digitalWrite(LE, HIGH);
SPI.begin(); // Init SPI bus
SPI.setDataMode(SPI_MODE0); // CPHA = 0 et Clock positive
SPI.setBitOrder(MSBFIRST); // highs in the lead
eep_rdata();
freq_disp(RFint); // frequency display
step_disp();
}
//------------------------ Main -----------------------------------------------
void loop(){
/////////////////////////////////////////
// TX SW check
/////////////////////////////////////////
if(digitalRead(SW_TX) == LOW)
Flg_Tx = 1; // <<< Tx >>>
else
Flg_Tx = 0; // <<< Rx >>>
/////////////////////////////////////////
// Repeater PROC
/////////////////////////////////////////
if(Flg_Resw == 0){ // repeater off?
freq_disp(RFint);
rpt_disp(Rsft);
Pll_ADF4351(RFint);
}
if(Flg_Resw == 1){ // repeater on?
freq_disp(RFint);
rpt_disp(Rsft);
if(Flg_Tx == 1) // <<< Tx >>>
Pll_ADF4351(RFint + Rsft); // frequency shift
else // <<< Rx >>>
Pll_ADF4351(RFint); // normal frequency
}
else if(Flg_Resw == 2){
shift_disp(Rsft);
rpt_disp(Rsft);
}
/////////////////////////////////////////
// Step PROC
/////////////////////////////////////////
if (digitalRead(SW_STEP) == LOW) { // increment events
enc_step();
step_disp();
delay(300);
while (digitalRead(SW_STEP) == LOW);
}
/////////////////////////////////////////
// Repeater SW check
/////////////////////////////////////////
if(digitalRead(SW_REPT) == LOW){
Time_Mode = millis();
while (digitalRead(SW_REPT) == LOW){
while (digitalRead(SW_REPT) == LOW);
if(Time_Mode+1000 < millis()){
Flg_Resw = 2;
break;
}
if(Flg_Resw == 0){
Flg_Resw = 1;
EEPROM.write(Eep_Resw,Flg_Resw);
break;
}
else {
Flg_Resw = 0;
EEPROM.write(Eep_Resw,Flg_Resw);
break;
}
}
}
/////////////////////////////////////////
// freqency EEP auto write
/////////////////////////////////////////
if(Flg_eepWT == 1){ // EEPROM auto Write
if(Time_Passd+2000 < millis()){
eep_wdata();
Flg_eepWT = 0;
}
}
}
//---------- Write EEPROM 4byte --------------------------------------
void eep_write4(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--;
}
}
//---------- Read EEPROM 4byte ---------------------------------------
long eep_read4(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;
}
//---------- EEPROM Dat Read -----------------------------------------
void eep_rdata(){
RFint = eep_read4(Eep_Freq);
Enc_Step = eep_read4(Eep_Step);
Rsft = eep_read4(Eep_Rsft);
Flg_Resw = EEPROM.read(Eep_Resw);
}
//---------- EEPROM Dat Write ----------------------------------------
void eep_wdata(){
eep_write4(RFint,Eep_Freq);
eep_write4(Enc_Step,Eep_Step);
eep_write4(Rsft,Eep_Rsft);
}
//---------- EEPROM Initialization ------------------------------------
void eep_init(){
int i;
for (i=0;i<128;i++) // 0 clear(128byte)
EEPROM.write(i, 0);
EEPROM.write(Eep_Resw,Flg_Resw); // Repeater off
eep_write4(DEF_Freq,Eep_Freq); // Frequency 1150MHz
eep_write4(DEF_Step,Eep_Step); // Step 1MHz
eep_write4(DEF_Rsft,Eep_Rsft); // Repeater shift -20MHz
EEPROM.write(Eep_Init,Int_End); // Init end set(73)
}
//---------- Rotaly Encorder -----------------------------------------
void rotary_encoder() { // rotary encoder events
long wk4;
int wk2;
uint8_t result = r.process();
if(Flg_Tx == 0){
if (result) {
if (result == DIR_CW){
wk2 = Rsft + Enc_Step;
wk4 = RFint + Enc_Step;
}
else{
wk2 = Rsft - Enc_Step;
wk4 = RFint - Enc_Step;
}
wk2 = constrain(wk2,LOW_REPT,HI_REPT);
if(Flg_Resw == 2)
Rsft = wk2;
else
RFint = wk4;
Flg_eepWT = 1;
Time_Passd = millis();
}
}
}
//---------- Encorede STEP -------------------------------------------
void enc_step() {
if(Enc_Step == 1)
Enc_Step = 10;
else if(Enc_Step == 10)
Enc_Step = 100;
else if(Enc_Step == 100)
Enc_Step = 1000;
else if(Enc_Step == 1000)
Enc_Step = 1;
else
Enc_Step = 100;
}
//---------- STEP Display --------------------------------------------
void step_disp() {
oled.setCursor(64, 3);
oled.print(" ");
oled.setCursor(64, 3);
oled.setFont(&Tfont5x7);
if (Enc_Step == 1)
oled.print(" 10k"); // 10k
else if(Enc_Step == 10)
oled.print("100k"); // 100k
else if(Enc_Step == 100)
oled.print(" 1M"); // 1M
else
oled.print(" 10M"); // 10M
}
//---------- Frequency renge over --------------------------------------
void fover_disp() {
oled.setFont(&Tlcdnums14x24);
oled.setCursor(1, 0);
oled.print("--.---.--");
}
//---------- Frequency renge over --------------------------------------
void rpt_disp(int32_t rep_shift) {
oled.setFont(FONT8X16);
if(Flg_Resw == 1){
oled.setFont(FONT8X16);
oled.setCursor(102, 0);
oled.print("REP");
oled.setCursor(102, 2);
if(rep_shift >= 0)
oled.print('+');
oled.print(rep_shift / 100);
oled.print(' ');
}
else {
oled.setCursor(102, 0);
oled.print(" ");
oled.setCursor(102, 2);
oled.print(" ");
}
}
//---------- Shift Display ---------------------------------------
void shift_disp(int32_t sf_rx) {
int32_t fr;
oled.setFont(&Tlcdnums14x24);
oled.setCursor(0, 0);
fr = sf_rx / 100;
oled.print(':'); // ':' is changed to ' ' in lcdnums14x24.h
if(fr >= 0)
oled.print('+');
oled.print(fr);
oled.print('.');
fr = (sf_rx % 100);
if (fr < 10)
oled.print('0');
oled.print(fr);
oled.print(':'); // ':' is changed to ' ' in lcdnums14x24.h
}
//---------- Frequency Display ---------------------------------------
void freq_disp(int32_t sf_rx) {
int32_t fr;
oled.setFont(&Tlcdnums14x24);
oled.setCursor(0, 0);
fr = sf_rx / 100;
if (fr < 1000)
oled.print(':'); // ':' is changed to ' ' in lcdnums14x24.h
if (fr < 100)
oled.print(':'); // ':' is changed to ' ' in lcdnums14x24.h
oled.print(fr);
oled.print('.');
fr = (sf_rx % 100);
if (fr < 10)
oled.print('0');
oled.print(fr);
}
//------------------------ SPI 32BIT Register Write proc. ---------------------
void WriteRegister32(const uint32_t value){
digitalWrite(LE, LOW);
for (int i = 3; i >= 0; i-- )
SPI.transfer((value >> 8 * i) & 0xFF);
digitalWrite(LE, HIGH);
digitalWrite(LE, LOW);
}
//------------------------ ADF4351 Register set -------------------------------
void Set_Reg()
{
for (int i = 5; i >= 0; i-- ) // Reg5 --> Reg0 Write
WriteRegister32(registers[i]);
}
//------------------------ Pll ADF4351 proc. ----------------------------------
void Pll_ADF4351(int32_t frq){
RFout=frq;
RFout=RFout/100;
if (frq != RFintold){
if (RFout >= 2200){
OutputDivider = 1;
bitWrite (registers[4], 22, 0);
bitWrite (registers[4], 21, 0);
bitWrite (registers[4], 20, 0);
}
if (RFout < 2200){
OutputDivider = 2;
bitWrite (registers[4], 22, 0);
bitWrite (registers[4], 21, 0);
bitWrite (registers[4], 20, 1);
}
if (RFout < 1100){
OutputDivider = 4;
bitWrite (registers[4], 22, 0);
bitWrite (registers[4], 21, 1);
bitWrite (registers[4], 20, 0);
}
if (RFout < 550){
OutputDivider = 8;
bitWrite (registers[4], 22, 0);
bitWrite (registers[4], 21, 1);
bitWrite (registers[4], 20, 1);
}
if (RFout < 275){
OutputDivider = 16;
bitWrite (registers[4], 22, 1);
bitWrite (registers[4], 21, 0);
bitWrite (registers[4], 20, 0);
}
if (RFout < 137.5){
OutputDivider = 32;
bitWrite (registers[4], 22, 1);
bitWrite (registers[4], 21, 0);
bitWrite (registers[4], 20, 1);
}
if (RFout < 68.75){
OutputDivider = 64;
bitWrite (registers[4], 22, 1);
bitWrite (registers[4], 21, 1);
bitWrite (registers[4], 20, 0);
}
INTA = (RFout * OutputDivider) / PFDRFout;
MOD = (PFDRFout / OutputChannelSpacing);
FRACF = (((RFout * OutputDivider) / PFDRFout) - INTA) * MOD;
FRAC =round(FRACF); // On arrondit le résultat
registers[0] = 0; // Register 0
registers[0] = INTA << 15;// OK
FRAC = FRAC << 3;
registers[0] = registers[0] + FRAC;
registers[1] = 0; // Register 1
registers[1] = MOD << 3;
registers[1] = registers[1] + 1 ; // adding the address "001"
bitSet (registers[1], 27); // Prescaler on 8/9
bitSet (registers[2], 28); // Register 2(Pll lock setup)
bitSet (registers[2], 27);
bitClear (registers[2], 26);
Set_Reg(); // ADF4351 Register write
RFintold = frq;
}
}
ダウンロード
回路図、スケッチなどJA2GQP's Download siteのadf4351フォルダからダウンロード出来る。



0 件のコメント:
コメントを投稿