回路図
スケッチ
//////////////////////////////////////////////////////////////////////
// si5351a oled(128x32) VFO program ver.1.0
// Copyright(C)2019.JA2GQP.All rights reserved.
//
// 2024/12/11
// JA2GQP
//--------------------------------------------------------------------
// Function
// 1.STEP(10k,1k,100)
// 2.Ofset(0,-1500,+1500)
// 3.Automatic memory
// 44.Protection Operation At The Time Of Transmission
// 5.S-Meter
//////////////////////////////////////////////////////////////////////
#include "src/Rotary.h" // http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
#include "src/si5351a.h" // https://github.com/etherkit/Si5351Arduino, v2.1.0
#include <Tiny4kOLED.h>
#include "font/Tlcdnums14x24.h"
#include "font/Tlabels.h"
#include "font/Tpixels.h"
#include <EEPROM.h>
//---------- I/O Port -------------------------------
#define SW_STEP 0 // STEP SW
#define SW_TX 1 // TX/RX
#define ENC_A 2 // encorder A
#define ENC_B 3 // B
#define SW_RIT 4 // RIT SW
#define SW_OFT 5 // OFFSET SW
#define AD_SM 10 // S-meter AD
//---------- Set Device -----------------------------
Rotary r = Rotary(ENC_B, ENC_A);
//---------- EEPROM Memory Address ------------------
#define Eep_Init 0x00 // Eep Init(1byte)
#define Eep_Oflg 0x02 // Offset flag(1byte)
#define Eep_Odat 0x04 // Offset data(4byte)
#define Eep_Freq 0x10 // Frequency(4byte)
#define Eep_Step 0x30 // STEP(4byte)
//---------- frquency data --------------------------
//---- frequency limit offset
#define DEF_F 50600000 // default frequency
#define LOW_F 50000000
#define HI_F 51000000
//---- receiver IF offset
#define IF_FREQ 10700000
#define RX_FIL 455000
const unsigned long RX_LO = IF_FREQ - RX_FIL;
//---- encorder STEP
#define STEP_100 100 // STEP 100Hz
#define STEP_1k 1000 // 1k
#define STEP_10k 10000 // 10k
//---- RIT limit
#define LW_RIT -5000 // RIT low -5k
#define HI_RIT 5000 // RIT high 5k
//---- OFFSET limit
#define LW_OFT -1500 // OFFSET low -1500
#define HI_OFT 1500 // OFFSET high 1500
//---------- etc ------------------------------------
const byte Int_End = 73; // Initial end code
//---------- Memory Assign --------------------------
unsigned long Vfo_Dat; // VFO Data
int Rit_Dat = 0; // RIT Data
int Oft_Dat = 0; // OFFSET Data
unsigned long Enc_Step; // STEP
unsigned int Val_Smeter = 0;
unsigned int Val_Smeterb = 1;
unsigned long Time_Passd; // int to hold the arduino miilis since startup
unsigned long Time_smeter; // smeter scan Time
byte Flg_eepWT = 0; // EEP Write Flag
byte Flg_Over = 0;
byte Flg_Tx = 0;
byte Flg_Rit = 0; // RIT Flag
byte Flg_Oflg = 0; // OFFSET Flag
long Lng_Wk; // Long Work
int Int_Wk; // Int Work
//---------- setup ----------------------------------------------------
void setup() {
pinMode(SW_STEP, INPUT_PULLUP);
pinMode(SW_TX, INPUT_PULLUP);
pinMode(SW_RIT, INPUT_PULLUP);
pinMode(SW_OFT, INPUT_PULLUP);
attachInterrupt(ENC_A, rotary_encoder, CHANGE);
attachInterrupt(ENC_B, 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);
}
}
eep_rdata();
freq_disp(Vfo_Dat + Oft_Dat); // frequency display
oft_disp(Flg_Oflg);
step_disp();
}
//---------- main ----------------------------------------------------
void loop() {
//---------- receive ----------------------
if(digitalRead(SW_TX) == HIGH){
Flg_Tx = 0;
si5351a_enable(0x02); // clk0,clk2=enable clk1=disable
si5351aSetFrequency2(RX_LO); // RX LO set
//---------- RIT proc
if (Flg_Rit == 0){
si5351aSetFrequency0(Vfo_Dat - IF_FREQ + Oft_Dat);
freq_disp(Vfo_Dat + Oft_Dat); // frequency display
// oft_disp(Flg_Oflg);
}
else{
si5351aSetFrequency0(Vfo_Dat - IF_FREQ + Rit_Dat + Oft_Dat);
rit_disp(Rit_Dat);
}
//---------- STEP SW check
if (digitalRead(SW_STEP) == LOW) {
enc_step();
step_disp();
while (digitalRead(SW_STEP) == LOW);
}
//---------- RIT SW check
if (digitalRead(SW_RIT) == LOW) {
if(Flg_Rit == 0)
Flg_Rit = 1;
else{
Flg_Rit = 0;
Rit_Dat = 0;
}
while (digitalRead(SW_RIT) == LOW);
}
//---------- OFFSET SW check
if (digitalRead(SW_OFT) == LOW) {
switch(Flg_Oflg){
case 0:
Oft_Dat = 0;
freq_disp(Vfo_Dat + Oft_Dat); // frequency display
oft_disp(Flg_Oflg);
EEPROM.write(Eep_Oflg,Flg_Oflg); // offset flg EEPROM save
Flg_Oflg++;
eep_write4(Oft_Dat,Eep_Odat);
break;
case 1:
Oft_Dat = LW_OFT;
freq_disp(Vfo_Dat + Oft_Dat); // frequency display
oft_disp(Flg_Oflg);
EEPROM.write(Eep_Oflg,Flg_Oflg); // offset flg EEPROM save
Flg_Oflg++;
eep_write4(Oft_Dat,Eep_Odat);
break;
case 2:
Oft_Dat = HI_OFT;
freq_disp(Vfo_Dat + Oft_Dat); // frequency display
oft_disp(Flg_Oflg);
EEPROM.write(Eep_Oflg,Flg_Oflg); // offset flg EEPROM save
Flg_Oflg = 0;
eep_write4(Oft_Dat,Eep_Odat);
break;
}
while (digitalRead(SW_OFT) == LOW);
}
}
//---------- send -------------------------
else{
Flg_Tx = 1;
band_check(Vfo_Dat); // range check
if(Flg_Over == 0){ // Within transmittable range?
freq_disp(Vfo_Dat); // frequency display
si5351a_enable(0x05); // si5351 output enable
si5351aSetFrequency1(Vfo_Dat);
}
else{ // Out of range
si5351a_enable(0x02); // si5351 output enable
fover_disp(); // Display of over range
}
}
//---------- common ------------------------
//---------- s meter
if(Time_smeter+100 < millis()){
Val_Smeter = analogRead(AD_SM);
if ((abs(Val_Smeter - Val_Smeterb)) > 3){ // if needed draw S-meter
sm_disp();
Val_Smeterb = Val_Smeter;
Time_smeter = millis();
}
}
//---------- freqency EEP auto write
if(Flg_eepWT == 1){ // EEPROM auto Write
if(Time_Passd+2000 < millis()){
eep_wdata();
Flg_eepWT = 0;
}
}
}
//---------- RIT Display ---------------------------------------------
void rit_disp(int rit_data) {
unsigned int ri,rit;
oled.setFont(&Tlcdnums14x24);
oled.setCursor(1, 0);
oled.print("::::");
if (rit_data < 0)
oled.print('-');
else
oled.print('+');
rit = abs(rit_data);
ri = rit / 1000;
oled.print(ri);
oled.print('.');
ri = (rit % 1000) / 10;
if (ri < 10)
oled.print('0');
oled.print(ri);
}
//---------- 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(){
Vfo_Dat = eep_read4(Eep_Freq);
Enc_Step = eep_read4(Eep_Step);
Flg_Oflg = EEPROM.read(Eep_Oflg);
Oft_Dat = eep_read4(Eep_Odat);
}
//---------- EEPROM Dat Write ----------------------------------------
void eep_wdata(){
eep_write4(Vfo_Dat,Eep_Freq);
eep_write4(Enc_Step,Eep_Step);
}
//---------- EEPROM Initialization ------------------------------------
void eep_init(){
int i;
for (i=0;i<128;i++) // 0 clear(128byte)
EEPROM.write(i, 0);
eep_write4(DEF_F,Eep_Freq);
eep_write4(STEP_1k,Eep_Step); // Step(1kHz)
EEPROM.write(Eep_Oflg,Flg_Oflg); // Offset flag(0)
eep_write4(Oft_Dat,Eep_Odat);
EEPROM.write(Eep_Init,Int_End); // Init end set(73)
}
//---------- Rotaly Encorder -----------------------------------------
void rotary_encoder() { // rotary encoder events
uint8_t result = r.process();
if(Flg_Tx == 0){
if (result) {
if (result == DIR_CW){
Lng_Wk = Vfo_Dat + Enc_Step;
Int_Wk = Rit_Dat + Enc_Step;
}
else{
Lng_Wk = Vfo_Dat - Enc_Step;
Int_Wk = Rit_Dat - Enc_Step;
}
if(Flg_Rit == 1)
Rit_Dat = Int_Wk;
else{
Vfo_Dat = Lng_Wk;
Rit_Dat = 0;
}
Rit_Dat = constrain(Rit_Dat,LW_RIT,HI_RIT); // RIT range check
Flg_eepWT = 1;
Time_Passd = millis();
}
}
}
//---------- Encorede STEP -------------------------------------------
void enc_step() {
if(Enc_Step == STEP_10k) // 10k?
Enc_Step = STEP_100; // yes,100Hz set
else
Enc_Step = Enc_Step * 10;
}
//---------- STEP Display --------------------------------------------
void step_disp() {
oled.setCursor(109, 3);
oled.setFont(&Tlabels);
if (Enc_Step == STEP_100)
oled.print("7"); // 100
else if(Enc_Step == STEP_1k){
oled.print("8"); // 1k
}
else{
oled.print("9"); // 10k
}
}
//---------- Frequency renge over --------------------------------------
void fover_disp() {
oled.setFont(&Tlcdnums14x24);
oled.setCursor(1, 0);
oled.print("--.---.--");
}
//---------- Frequency Display ---------------------------------------
void freq_disp(uint32_t sf_rx) {
uint16_t fr;
oled.setFont(&Tlcdnums14x24);
oled.setCursor(1, 0);
fr = sf_rx / 1000000;
if (fr < 10)
oled.print(':'); // ':' is changed to ' ' in lcdnums14x24.h
oled.print(fr);
oled.print('.');
fr = (sf_rx % 1000000) / 1000;
if (fr < 100)
oled.print('0');
if (fr < 10)
oled.print('0');
oled.print(fr);
oled.print('.');
fr = (sf_rx % 1000) / 10;
if (fr < 10)
oled.print('0');
oled.print(fr);
}
//---------- TX display ------------------------------------------------
void tx_disp() {
oled.setCursor(2, 3);
oled.setFont(&Tlabels);
oled.print("1"); // TX
}
//---------- Mode display ----------------------------------------------
void oft_disp(byte mod) {
oled.setCursor(2, 3);
oled.setFont(&Tlabels);
if(mod == 0)
oled.print("."); // "." is " " in Tlabels.h
else if(mod == 1)
oled.print("3"); // "3" is "LSB"
else if(mod == 2)
oled.print("4"); // "4" is "USB"
}
//---------- S-Meter Display -----------------------------------------
void sm_disp() {
uint8_t a = 0;
uint8_t m = 0;
Val_Smeter = map(Val_Smeter,0,225,0,1023);
a = Val_Smeter / 113; // 1023 / 9 characters for S = 1,3,5,7,8,9,+10,+20,+30
oled.setFont(&Tpixels);
oled.setCursor(25, 3);
for (m = 0; m < a; m++)
if (m < 6)
oled.print('7'); // '5' - hollow rectangle, 6px
else
oled.print('8'); // '6' - filled rectangle, 6px
for (m = a; m < 9; m++)
oled.print('.'); // '.' 1px
}
//---------- band chek -----------------------------------------------
void band_check(unsigned long freq){
if((freq < LOW_F) || (freq > HI_F))
Flg_Over = 1;
else
Flg_Over = 0;
}
ダウンロード
回路図、スケッチなどは、JA2GQP’sDownload siteの6m AM TRXフォルダーからダウンロード可能。