Vocês, que curte e gosta dos projetos do blog, por gentileza olhem às propagandas e click para maiores detalhes no que interessar, desta forma vocês estarão ajudando o blog. Muito obrigado por acessar e ajudar o blog, conto com vocês muito agradecido.
Olá pessoal, postei aqui em Fevereiro, que comecei a fazer minhas experiências com Arduíno DDS VFO, sempre no interesse de incentivar a todos os iniciantes que querem montar um VFO digital em suas montagens ou seus transceptores AM, FM, SSB, mesmo o Cobra 148 GTL. Já fiz várias experiências modificações em sketchs e algumas deram certo. Quero deixar claro que não sou programador, não sei nada, estou aprendendo, por favor, quero aprender com todos vocês. O primeiro sketch modificado a ser postado aqui no blog e em vídeo, oled_cb_vfo4 do Sr. Akio Mizuno JA2GQP, meus agradecimentos. Download Google Driver de vários DDS VFO's e projetos como oled CB VFO em seu blog, Eu fiz algumas modificações no sketch do oled_cb_vfo4, que servirão para nossos projetos de transceptores SSB, super-heteródinos, dupla conversão, até mesmo servirá para o nosso Cobra 148 GTL. Apesar de não ter o deslocamento das bandas de SSB em relação ao AM, por exemplo: Canal 1 AM = 34.765 Mhz, LSB = 34.763,5 Mhz, USB = 34.766,5 Mhz. Estas são frequências originais na saída VCO em TP1 no esquema do Cobra 148 GTL, que para ficar correto na faixa de LSB, USB terá de ter estes deslocamentos no VFO, além da frequência ser feita por cima e a FI subtraindo.
Modificações: Modifiquei a FI como já descrita, entre os 34Mhz. Retirei a proteção de TX no VFO. Coloquei o STEP para 1M, 10k, 1k, 100Hz, 10Hz, ideal para SSB, aumentei os canais para mais de 190, á serem gravados do VFO frequências, ao ser pressionado a chave RIT por alguns segundos. Pressionando a tecla STEP por alguns segundos você entra ou sai do modo canal.
Quando não tem nenhum canal gravado na memória a frequência em RX, TX em CLK0 é de 7.800 Mhz frequências de FI.
Gravando os canais na memória. Primeiro você terá de selecionar o dígito do canal Ex: canal 1 0.000 agora aperte a tecla STEP por alguns segundos, entre no modo VFO e selecione a frequência 26.965.00 que é a frequência do canal 1 PX CB, ou a que se deseja gravar no canal 1. Aperte a tecla RIT por alguns segundos, pronto já está gravado a frequência no canal 1. Faça o mesmo procedimento para quantos canais gravar na memória, os gravados depois do dígito canal 10, sumirá o último dígito da frequência, Ex: no canal 1 gravado 26.965, se for gravado no canal 10 só aparecerá 26.96 o dígito 5 não aparecerá em RX, só em TX aparece toda frequência em modo VFO. Eu tentei fazer uma modificação que explico mais abaixo. Os gravados após dígito canal 10 eles permanecerão na memória, mesmo que resetado mas poderão ser regravados novamente. Grave os canais dígito 1 frequência de 26.965,00 Mhz até dígito 80 frequência de 27.855,00 Mhz.
Alterei a biblioteca do oled 128x64, mas os caracteres ficaram muito pequenos, então retornei e deixei original como o autor programou. O oled 128x32 achei que tem mais nitidez do que o 128x64.
Atenção: Alterei o modo canal que começa do número 0 zero até 99, o inconveniente é que do canal 0 a 9 o display mostra em RX 6 dígitos escondendo o penúltimo. Depois do canal 10 até 99 em RX o display só mostra 5 dígitos da frequência, porem em TX tem a frequência total, já comentado acima.
Tecla STEP - A cada toque rápido muda de 10Hz, 100Hz, 1khz, 10khz, 1Mhz, toque seguro por alguns segundos entrar modo canal e VFO. Lembrando qua a faixa de PX (CB) tem seus canais separados em 10 Khz, exceto nos 5 canais de telecomandos que ficam entre os canais 3 e 4 = 1T freq. 26.995,00 Mhz, entre os canais 7 e 8 = 2T freq. 27.045,00 Mhz, entre os canais 11 e 12 = 3T freq. 27.095,00 Mhz, entre os canais 15 e 16 = 4T freq. 27.145,00 Mhz, entre os canais 19 e 20 = 5T freq. 27.195,00 Mhz. Obs. o canal 23 é freq. 27.255,00 Mhz, é como se ele estivesse entre os canais 25 e 26. Sejam atento ao gravar os canais no seu projeto.
Tecla RIT - Toque rápido entra modo RIT, o RIT também poderá ser selecionado em 10Hz, 1k, 10k, nesta última só subirá 5Khz ou descerá 5Khz, só muda os sinais - e + continua dígito 5. O modo RIT só funciona em RX, em TX a frequência permanecerá a mesma. Ex: CLK0 tem 34.765,00 Mhz canal 1 em RX no modo RIT com +5.00 ficará em RX 34.770,00 Mhz, com -5.00 ficará 34.760,00 Mhz. Em TX a frequência permanecerá 34.765,00 Mhz. Ou seja você transmite em uma frequência e recebe em outra. Eu já havia modificado o STEP para 10Hz, 1Khz, 10Khz, mas pesquisando encontrei o comentário lá no blog Sr. Akio JA2GQP, que o PU2XLB Sr. Wagner havia solicitado uma modificação no STEP, eu baixei o sketch e coloquei o exemplo neste, o que funcionou perfeitamente como eu queria.
O sketch que o PU2XLB Sr. Wagner solicitou em comentário em 5 Fevereiro 2025, com modificação no STEP estava na página de download como si5351_oled_BFO_pu2xlb.zip do Sr. Akio JA2GQP, onde não mas achei, mas eu adicionei aqui neste sketch.
No arquivo em ZIP WinRAR vocês encontrarão na pasta "src" todas ou algumas bibliotecas que precisam para adicionar neste sketch, algumas bibliotecas poderá dá erro na compilação do sketch, leiam alguns comentários na página do autor. instale ás bibliotecas em arquivos ZIP. Na parte de cima do programa Arduíno, vá em sketch - incluir biblioteca - Adicionar biblioteca .ZIP, selecione a pasta do arquivo e instale novamente e leia os comentários lá na página blog do autor.
Esta é Protoboard laboratório VFO com componentes de testes.
Contem um Arduino Nano ATmega 328P de 2018, SI5351, Oled 0.96 128x64, chaves, Encoder.
Um regulador 7805 capacitores filtro, uma fonte de 7.5 volts por 500mA para alimentar o Arduíno e todo circuito.
Assistam ao vídeo e olhem ás fotos aqui no blog.
Estas são mini chaves táctil Push Button 6x6x4,5mm, retiradas de sucatas de TV.
Vejam mais uma chave liga desliga, e Encoder.
Vejam que o sketch permite os dois oleds, 128x32, 128x64. Este melhor visível.
Vejam que CLK0 no Frequencímetro está em 34.776,85 Khz, FI 7.800 Khz para Cobra 148 GTL.
Nítido, melhor que o Oled 128x64, mas fica com letras e S/meter bem próximo aos números da frequência. Ainda está com plástico no visor. Está selecionado 100 Hz.
Este 128x64, eu achei melhor, pois os caracteres números são maiores, este é menos claro, menos nitidez, e o AM em RX e S/meter ficam bem posicionado, está com 10Hz. 
Vejam que em TX permanece a frequência, retirei a proteção de TX.
Este meu velho Frequencímetro está variando Hz com a temperatura, já foi muito bom na época.
Para correção calibração do SI5351 eu modifiquei a linha 132 no circulo vermelho:
si5351.init(SI5351_CRYSTAL_LOAD_8PF,0,0); // crystal 25.000 MHz, correction 0
para:
si5351.init( SI5351_CRYSTAL_LOAD_8PF, 0, 12500); // 62100 is the specific calibration factor for this Si5351 board.
Ficou mais próximo a frequência final Hz.
Na linha 133 em circulo vermelho, vocês poderão aumentar ou diminuir o consumo SI5351 em 2, 4, 8 mA com isso ajusta potencia RF. Mas cuidado, Melhor montar um Buffer na saída de CLK0.
Sugestão do Buffer para SI5351, se for usar FM tem que ter o diodo Varicap para entrada de modulação ajustável e dosar a modulação para o varicap. Em AM, SSB, não coloque o varicap, use este ou outros circuitos como amplificador de RF para SI5351.
Vejam abaixo no quadrado vermelho ás funções que modifiquei.
Veja mas abaixo quadrado vermelho a biblioteca para o Oled 128x32 original.
Melhor adicionar ás duas bibliotecas.
Vejam no circulo vermelho, FI offset, estes valores são para FI do Cobra 148 GTL.
Vocês devem mudar se quiser outras FI em CLK0 e CLK1.
Em RX a soma das duas frequências resulta em 7.800 Mhz.
Vejam no circulo vermelho é para acrescentar mais um dígito no modo canal, deixe só dois pontos no meio, talvez apareça um número 5 no final do display onde não há gravação de canal.
Eu deixei original pois queria mais um dígito depois do canal 10, mas é fácil de resolver, basta apertar o TX PTT que mostra a frequência total em modo VFO. Quem fizer outra modificação e queira comentar agradeço.
Abaixo sketch modificado por mim, para FI de 7.800 Khz Cobra 148 GTL, servirá para transceptores em 80, 40, 20, 15, 11, 10, 6 e 2 metros. É só modificar a frequência de inicio do VFO, ás frequências da FI se quiser usar CLK0, CLK1, e montar um transceptor dupla conversão, heteródino. Selecione todo sketch, copie e cole no programa Arduino IDE, adicione todas ás bibliotecas "src" contida na pasta compactada do sketch do autor.
//////////////////////////////////////////////////////////////////////
// si5351a oled(128x32) VFO program ver.2.0
// Copyright(C)2019.JA2GQP.All rights reserved.
// 2023/11/10 JA2GQP
// Modified sketch FI 34Mhz Cobra 148 GTL or for superheterodyne
// double conversion transceivers. by Waldir Cardoso
// Blog: https://projetosetransceptores.blogspot.com/ 2025/05/20.
//--------------------------------------------------------------------
// Function
// 1.VFO/200 Channel mode
// 2.STEP(1M,10k,1k,100,10)
// 3.Automatic memory VFO
// 4.S-Meter
//////////////////////////////////////////////////////////////////////
#include "src/Rotary.h" // http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
#include "src/si5351.h" // https://github.com/etherkit/Si5351Arduino, v2.1.0
#include "src/SSD1306Ascii.h"
#include "src/SSD1306AsciiAvrI2c.h" // https://github.com/greiman/SSD1306Ascii
#include <EEPROM.h> // IDE Standard
////////////////////////////////
// Set Device
////////////////////////////////
Rotary r = Rotary(2, 3);
Si5351 si5351(0x60); // Si5351 I2C address
SSD1306AsciiAvrI2c oled;
////////////////////////////////
// I/O Port
////////////////////////////////
const byte SW_RIT = A0; // RIT SW
const byte SW_STEP = A1; // STEP SW
const byte SW_TX = A2; // TX/RX
//const byte SW_TX = 4; // TX/RX
const byte AD_SM = A7; // S-meter AD
////////////////////////////////
// EEPROM Memory Address
////////////////////////////////
const byte Eep_Init = 0x00; // Eep Init(1byte*1)
const byte Eep_Band = 0x01; // RIT(1byte*1)
const byte Eep_Ch = 0x02; // Channel(1byte*1)
const byte Eep_Chan = 0x03; // VFO-Channel Mode(1byte*1)
const byte Eep_Freq = 0x10; // Frequency(4byte*5)
const byte Eep_Step = 0x30; // STEP(4byte*5)
const long Eep_Chfreq = 0x50; // Channel(4byte*5)
////////////////////////////////
// frquency data
////////////////////////////////
const unsigned long FRQ_TBL[5] = {
// DEF_F CW_F SSB_F AM_F HI_F
26965000 ,26515000 ,26515000 ,26515000 ,28855000
};
//const unsigned long CH_TBL[] = { // Initial frequency value
//26005000 ,26968000 ,26976000 ,27040000 ,27080000 ,
//27088000 ,27112000 ,27120000 ,28144000
//};
//const byte Max_Chan = sizeof(CH_TBL) / sizeof(CH_TBL[0]); // Max Channel
//---- IF offset data -------
const long RX_FIL = 7345000;
const long RX_LO = 455000;
const long TX_LO = 7800000;
const unsigned long RX_IF = RX_FIL + RX_LO; // RX_IF offset
const unsigned long TX_IF = TX_LO; // TX_IF offset
//---- data offset -----
const byte DEF_F = 0;
const byte CW_F = 1;
const byte SSB_F = 2;
const byte AM_F = 3;
const byte HI_F = 4;
////////////////////////////////
// Encorder STEP
////////////////////////////////
const long STEP_10 = 10; // STEP 10Hz
const long STEP_100 = 100; // 100Hz
const long STEP_1k = 1000; // 1k
const long STEP_10k = 10000; // 10k
const long STEP_100k = 100000; // 100k
const long STEP_1M = 1000000; // 1M
//const int STEP_10 = 10; // STEP 10Hz
//const int STEP_1k = 1000; // 1k
//const int STEP_10k = 10000; // 10k
////////////////////////////////
// etc
////////////////////////////////
const byte Int_End = 88; // Initial end code
const char Call[9] = "JA2GQP"; // Display Call sign
////////////////////////////////
// Memory Assign
////////////////////////////////
unsigned long Vfo_Dat; // VFO Data
unsigned long Ch_Dat; // Channel Data
int Rit_Dat; // RIT Data
unsigned long Enc_Step; // STEP
char Enc_Dir = 0; // -1 DIR_CCW, 0 DIR_NONE, 1 DIR_CCW
byte Ch_Index = 0; // Channel TBL index
unsigned int Val_Smeter = 0;
unsigned int Val_Smeterb = 1;
long Time_Passd; // int to hold the arduino miilis since startup
long Time_Mode; // Mode change Time
long Time_smeter; // smeter scan Time
byte Flg_eepWT = 0; // EEP Write Flag
byte Flg_Mode = 3;
byte Flg_Over = 0;
byte Flg_Vfo = 0;
byte Flg_Tx = 0;
byte Flg_Chan = 1; // Channel Flag 0:VFO, 1:Cannel
byte Disp_Over = 1;
byte Disp_Freq = 1;
byte Disp_Tx = 0;
byte Disp_Rit = 0;
byte Flg_Rit = 0; // RIT Flag
//---------- setup ----------------------------------------------------
void setup() {
pinMode(SW_STEP, INPUT_PULLUP);
pinMode(SW_TX, INPUT_PULLUP);
pinMode(SW_RIT, INPUT_PULLUP);
pinMode(12, OUTPUT); // pin12,pin13
pinMode(13, OUTPUT); // 0,0=CW 1,0=LSB 0,1=USB 1,1=AM
attachInterrupt(0, rotary_encoder, CHANGE);
attachInterrupt(1, rotary_encoder, CHANGE);
si5351.init( SI5351_CRYSTAL_LOAD_8PF, 0, 12500); // 62100 is the specific calibration factor for this Si5351 board
si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_4MA);//Drive lebel 4mA set
oled.begin(&Adafruit128x32, 0x3C);
if(EEPROM.read(Eep_Init) != Int_End){ // Eep initialaz
delay(10);
eep_init();
}
else{
if(digitalRead(SW_STEP) == LOW){
delay(10);
mode_disp();
eep_init();
fover_disp();
while (digitalRead(SW_STEP) == LOW);
}
}
eep_rdata();
mode_disp();
step_disp();
Time_smeter = millis();
}
//---------- main ----------------------------------------------------
void loop() {
if(Flg_Chan == 0){
vfo_mode();
}
if(Flg_Chan == 1){
ch_mode();
}
}
//---------- Channel mode ------------------------------------------------
void ch_mode(){
////////////////////////
// receive
////////////////////////
if(digitalRead(SW_TX) == HIGH){
Flg_Tx = 0;
si5351.output_enable(SI5351_CLK0, 1); // VFO enable
si5351.output_enable(SI5351_CLK1, 1); // LO enable
mode_disp();
if (Flg_Rit == 0){
if(Disp_Freq == 1){
if((Ch_Index == 0) && (Enc_Dir == -1))
//Ch_Index = Max_Chan-1;
//else if((Ch_Index == Max_Chan-1) && (Enc_Dir == 1))
Ch_Index = 0;
else
Ch_Index += Enc_Dir;
Enc_Dir = 0;
Ch_Dat = eep_read4(Eep_Chfreq+Ch_Index*4); // Channel data read
band_check(Ch_Dat); // range check
si5351_set_freq(Ch_Dat + RX_IF); // frequency out
ch_disp(Ch_Dat); // Channel display
Disp_Freq = 0;
Flg_Vfo = 1;
Rit_Dat = 0;
Time_Passd = millis();
Flg_eepWT = 1;
}
}
else{
if (Disp_Rit == 1){
Rit_Dat += Enc_Dir * Enc_Step;
Enc_Dir = 0;
Rit_Dat = constrain(Rit_Dat, -5000, 5000);
si5351_set_freq(Ch_Dat + RX_IF + Rit_Dat);
rit_disp(Rit_Dat);
Disp_Rit = 0;
Flg_Vfo = 1;
}
}
////////////////////////
// STEP
////////////////////////
if (digitalRead(SW_STEP) == LOW) { // increment events
Time_Mode = millis();
while (digitalRead(SW_STEP) == LOW){
if(Time_Mode+1000 < millis()){
if(Flg_Chan == 0){ // VFO mode?
Flg_Chan = 1; // yes,Channel mode set
break;
}
else{ // no,VFO mode
Flg_Chan = 0;
freq_disp(Vfo_Dat); // frequency display
si5351_set_freq(Vfo_Dat + RX_IF); // fequency data output
Flg_Rit = 0; // RIT reset
Disp_Freq = 0;
break;
}
}
}
while (digitalRead(SW_STEP) == LOW);
if(Flg_Chan == 1){
enc_step();
step_disp();
}
}
////////////////////////
// RIT
////////////////////////
if (digitalRead(SW_RIT) == LOW) {
Time_Mode = millis();
while (digitalRead(SW_RIT) == LOW){
if((Ch_Index == 0) || (Ch_Index == 9)){
if(Time_Mode+1000 < millis()){
if(Flg_Chan == 1){
Flg_Chan = 0;
Vfo_Dat = Ch_Dat;
freq_disp(Vfo_Dat);
si5351_set_freq(Vfo_Dat + RX_IF);
Flg_Rit = 0;
break;
}
}
}
}
while (digitalRead(SW_RIT) == LOW);
if(Flg_Chan == 1){
rit_disp(Rit_Dat);
Fnc_Rit();
}
}
Disp_Tx = 1;
si5351.set_freq(RX_LO * SI5351_FREQ_MULT, SI5351_CLK1);
}
////////////////////////
// send
////////////////////////
else{
Flg_Tx = 1;
Disp_Over = 1;
if(Flg_Over == 0){ // Within transmittable range?
freq_disp(Ch_Dat); // frequency display
si5351.output_enable(SI5351_CLK0, 1); // VFO enable
si5351.output_enable(SI5351_CLK1, 1); // LO enable
if(Flg_Vfo == 1){
si5351_set_freq(Ch_Dat + TX_IF);
Flg_Vfo = 0;
}
Disp_Freq = 1;
Disp_Rit = 1;
}
else{ // Out of range
si5351.output_enable(SI5351_CLK0, 1); // VFO enable
si5351.output_enable(SI5351_CLK1, 1); // LO enable
if((Flg_Rit == 0) && (Disp_Over == 1)){
fover_disp(); // Display of over range
Disp_Over = 0;
}
}
if(Disp_Tx == 1){
tx_disp();
Disp_Tx = 0;
}
Disp_Freq = 1;
si5351.set_freq(TX_LO * SI5351_FREQ_MULT, SI5351_CLK1);
}
////////////////////////
// common
////////////////////////
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();
}
}
if(Flg_eepWT == 1){ // EEPROM auto Write
if(Time_Passd+2000 < millis()){
eep_wdata();
Flg_eepWT = 0;
}
}
}
//---------- VFO mode ------------------------------------------------
void vfo_mode(){
////////////////////////
// receive
////////////////////////
if(digitalRead(SW_TX) == HIGH){
Flg_Tx = 0;
si5351.output_enable(SI5351_CLK0, 1); // VFO enable
si5351.output_enable(SI5351_CLK1, 1); // LO enable
mode_disp();
if (Flg_Rit == 0){
if(Disp_Freq == 1){
Vfo_Dat += Enc_Dir * Enc_Step;
Enc_Dir = 0;
si5351_set_freq(Vfo_Dat + RX_IF);
freq_disp(Vfo_Dat); // frequency display
Disp_Freq = 0;
Flg_Vfo = 1;
Rit_Dat = 0;
Time_Passd = millis();
Flg_eepWT = 1;
}
}
else{
if (Disp_Rit == 1){
Rit_Dat += Enc_Dir * Enc_Step;
Enc_Dir = 0;
Rit_Dat = constrain(Rit_Dat, -5000, 5000);
si5351_set_freq(Vfo_Dat + RX_IF + Rit_Dat);
rit_disp(Rit_Dat);
Disp_Rit = 0;
Flg_Vfo = 1;
}
}
////////////////////////
// STEP
////////////////////////
if (digitalRead(SW_STEP) == LOW) { // increment events
Time_Mode = millis();
while (digitalRead(SW_STEP) == LOW){
if(Time_Mode+1000 < millis()){
if(Flg_Chan == 0){
Flg_Chan = 1;
ch_disp(Ch_Dat);
si5351_set_freq(Ch_Dat + RX_IF);
eep_wdata();
Flg_Rit = 0;
break;
}
else{
Flg_Chan = 0;
break;
}
}
}
while (digitalRead(SW_STEP) == LOW);
if(Flg_Chan == 0){
enc_step();
step_disp();
}
}
////////////////////////
// RIT
////////////////////////
if (digitalRead(SW_RIT) == LOW) {
Time_Mode = millis();
while (digitalRead(SW_RIT) == LOW){
if(Time_Mode+1000 < millis()){
if(Flg_Chan == 0){
eep_write4(Vfo_Dat,Eep_Freq);
Ch_Dat = Vfo_Dat;
ch_disp(Ch_Dat);
eep_write4(Ch_Dat,Eep_Chfreq+Ch_Index*4);
si5351_set_freq(Ch_Dat + RX_IF);
Flg_Rit = 0;
Flg_Chan = 1;
break;
}
}
}
while (digitalRead(SW_RIT) == LOW);
if(Flg_Chan == 0){
rit_disp(Rit_Dat);
Fnc_Rit();
}
}
Disp_Tx = 1;
si5351.set_freq(RX_LO * SI5351_FREQ_MULT, SI5351_CLK1);
}
////////////////////////
// send
////////////////////////
else{
Flg_Tx = 1;
Disp_Over = 1;
band_check(Vfo_Dat); // range check
if(Flg_Over == 0){ // Within transmittable range?
freq_disp(Vfo_Dat); // frequency display
si5351.output_enable(SI5351_CLK0, 1); // VFO enable
si5351.output_enable(SI5351_CLK1, 1); // VFO enable
if(Flg_Vfo == 1){
si5351_set_freq(Vfo_Dat + TX_IF);
Flg_Vfo = 0;
}
Disp_Freq = 1;
Disp_Rit = 1;
}
else{ // Out of range
si5351.output_enable(SI5351_CLK0, 1); // VFO enable
si5351.output_enable(SI5351_CLK1, 1); // LO enable
if((Flg_Rit == 0) && (Disp_Over == 1)){
fover_disp(); // Display of over range
Disp_Over = 0;
}
}
if(Disp_Tx == 1){
tx_disp();
Disp_Tx = 0;
}
Disp_Freq = 1;
si5351.set_freq(TX_LO * SI5351_FREQ_MULT, SI5351_CLK1);
}
////////////////////////
// common
////////////////////////
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();
}
}
if(Flg_eepWT == 1){ // EEPROM auto Write
if(Time_Passd+2000 < millis()){
eep_wdata();
Flg_eepWT = 0;
}
}
}
//---------- Function Rit --------------------------------------------
void Fnc_Rit(){
if(Flg_Rit == 0){
Rit_Dat = 0;
Flg_Rit = 1;
}
else{
Flg_Rit = 0;
Disp_Freq = 1;
}
}
//---------- RIT Display ---------------------------------------------
void rit_disp(int rit_data) {
unsigned int ri,rit;
oled.setFont(lcdnums14x24);
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);
Ch_Index = EEPROM.read(Eep_Ch);
Flg_Chan = EEPROM.read(Eep_Chan);
Ch_Dat = eep_read4(Eep_Chfreq+Ch_Index*4);
}
//---------- EEPROM Dat Write ----------------------------------------
void eep_wdata(){
eep_write4(Vfo_Dat,Eep_Freq);
eep_write4(Enc_Step,Eep_Step);
EEPROM.write(Eep_Ch,Ch_Index); // Ch_Index set
EEPROM.write(Eep_Chan,Flg_Chan); // VFO-Channel 0:VFO 1:Channel
eep_write4(Ch_Dat,Eep_Chfreq+Ch_Index*4);
}
//---------- EEPROM Initialization ------------------------------------
void eep_init(){
int i;
for (i=0;i<128;i++) // 0 clear(128byte)
EEPROM.write(i, 0);
eep_write4(FRQ_TBL[DEF_F],Eep_Freq);
eep_write4(STEP_1k,Eep_Step); // Step(1kHz)
EEPROM.write(Eep_Ch,Ch_Index); // Ch_Index set
EEPROM.write(Eep_Chan,Flg_Chan); // Ch_Index set
//for(i=0;i<Max_Chan;i++)
// eep_write4(CH_TBL[i],Eep_Chfreq+i*4);
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) {
Disp_Freq = 1;
Disp_Rit = 1;
if (result == DIR_CW)
Enc_Dir = 1;
else
Enc_Dir = -1;
}
}
}
//---------- si5351 PLL Output ---------------------------------------
void si5351_set_freq(uint32_t frequency) {
si5351.set_freq(frequency * SI5351_FREQ_MULT, SI5351_CLK0);
}
//---------- Encorede STEP -------------------------------------------
void enc_step() {
if(Enc_Step == STEP_1M){ // 1M?
Enc_Step = STEP_10; // yes,10Hz set
// Disp_freq = 1;
}
else
Enc_Step = Enc_Step * 10;
}
//void enc_step() {
//if (Enc_Step == STEP_10) {
//Enc_Step = STEP_1k; // 1000 Hz, round to XX.XXX.000
//float tmp = round (Vfo_Dat / (STEP_1k * 1.000));
//Vfo_Dat = (uint32_t)(tmp * STEP_1k);
//Disp_freq = 1;
//}
//else if(Enc_Step == STEP_1k)
// Enc_Step = STEP_10k; // 10k
//else
//Enc_Step = STEP_10; // 10 Hz
//}
//---------- STEP Display --------------------------------------------
void step_disp() {
oled.setCursor(105, 4);
oled.setFont(GQPfont5x7);
switch(Enc_Step){
case STEP_10:
oled.print("10 ");
break;
case STEP_100:
oled.print("100 ");
break;
case STEP_1k:
oled.print("1k ");
break;
case STEP_10k:
oled.print("10k ");
break;
case STEP_100k:
oled.print("100k");
break;
case STEP_1M:
oled.print("1M ");
break;
}
//void step_disp() {
//oled.setCursor(109, 4);
//oled.setFont(GQPfont5x7);
//if (Enc_Step == STEP_10)
//oled.print("10 "); // 10Hz
//else if(Enc_Step == STEP_1k)
//oled.print("1k "); // 1k
//else
//oled.print("10k"); // 10k
}
//---------- Frequency renge over --------------------------------------
void fover_disp() {
oled.setFont(lcdnums14x24);
oled.setCursor(1, 0);
oled.print("--.---.--");
}
//---------- callsign display ------------------------------------------
void call_disp() {
oled.setFont(Arial_bold_14);
oled.setCursor(56, 6);
oled.print(Call);
}
//---------- Frequency Display ---------------------------------------
void freq_disp(uint32_t sf_rx) {
uint16_t fr;
oled.setFont(lcdnums14x24);
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);
}
//---------- Channel Display -----------------------------------------
void ch_disp(uint32_t sf_rx) {
uint16_t fr;
oled.setFont(lcdnums14x24);
oled.setCursor(1, 0);
oled.print(Ch_Index);
oled.print("::"); // ':' is changed to ' ' in lcdnums14x24.h
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);
}
//---------- TX display ------------------------------------------------
void tx_disp() {
oled.setCursor(2, 3);
oled.setFont(GQPfont5x7);
oled.print("TX "); // TX
}
//---------- Mode display ----------------------------------------------
void mode_disp() {
oled.setCursor(2, 3);
oled.setFont(GQPfont5x7);
if (Flg_Mode == 0){
oled.print("CW "); // CW
digitalWrite(12,LOW);
digitalWrite(13,LOW);
}
else if(Flg_Mode == 1){
oled.print("LSB"); // LSB
digitalWrite(12,HIGH);
digitalWrite(13,LOW);
}
else if(Flg_Mode == 2){
oled.print("USB"); // USB
digitalWrite(12,LOW);
digitalWrite(13,HIGH);
}
else if(Flg_Mode == 3){
oled.print("AM "); // AM
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);
}
}
//---------- S-Meter Display -----------------------------------------
void sm_disp() {
uint8_t a = 0;
uint8_t m = 0;
a = (Val_Smeter + 3) / 113; // 1024 / 9 characters for S = 1,3,5,7,8,9,+10,+20,+30
oled.setFont(pixels);
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){
Flg_Over = 1;
for(int i=1;i<9;i++){
//if(freq == CH_TBL[i]){
Flg_Over = 0;
break;
}
}
// Flg_Mode = 3;
//}
Nenhum comentário:
Postar um comentário
Façam seus comentários com experiências no projeto. Ou de sua opinião.