/*
* ESP32 Si5351A 7MHz VFO
* 2020.02.16
* JH7UBC Keiji Hata
*/
//TFT関係の定義 #include #include #define __CS 5 #define __DC 17 #define __RST 16 // SDA(MOSI) 23 // SCK 18 // VCC,LED 3V3
Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);
//I2C #include
//Si5351A関係の定義 #define Si5351A_ADDR 0x60 #define MSNA_ADDR 26 #define MSNB_ADDR 34 #define MS0_ADDR 42 #define MS1_ADDR 50 #define MS2_ADDR 58 #define CLK0_CTRL 16 #define CLK1_CTRL 17 #define CLK2_CTRL 18 #define OUTPUT_CTRL 3 #define XTAL_LOAD_C 183 #define PLL_RESET 177 const uint32_t XtalFreq = 25000000; uint32_t divider; uint32_t PllFreq; uint8_t mult; uint32_t num; uint32_t denom; uint32_t l; float f; uint32_t P1; uint32_t P2; uint32_t P3;
//Rotary endoder関係の定義 #define ENC_A 12 #define ENC_B 13 volatile uint8_t old_value = 0x11; volatile uint8_t value = 0; volatile uint8_t D; volatile int8_t count = 0;
//STEP関係の定義 #define SW_STEP 14 uint16_t STEP = 10000; //STEP 初期値
//VFO関係の定義 const uint32_t LOW_FREQ = 7000000; //下限周波数 const uint32_t HI_FREQ = 7200000; //上限周波数 uint32_t FREQ = 7000000; //VFO周波数初期値 uint32_t FREQ_OLD = FREQ; //周波数の前の値 int16_t df = 130; //周波数補正値(Hz) String freqt = String(FREQ); String fH_old = ""; String fM_old = ""; String fL_old = "";
//ROtary encoder 割込みサービスルーチン void rotary(){ value = (digitalRead(ENC_B)<<1) | digitalRead(ENC_A); if(old_value != value){ D = ((old_value << 1) ^ value) & 3; if(D < 2){ count += 1; }else{ count -= 1; } if(count >= 4){ FREQ += STEP; count = 0; }else if(count <= -4){ FREQ -= STEP; count = 0; } FREQ = constrain(FREQ,LOW_FREQ,HI_FREQ); //VFOの下限と上限を超えないように old_value = value; } }
//レジスタに1バイトデータを書き込む。 void Si5351_write(byte Reg , byte Data){ Wire.beginTransmission(Si5351A_ADDR); Wire.write(Reg); Wire.write(Data); Wire.endTransmission(); }
//Si5351Aの初期化 void Si5351_init(){ Si5351_write(OUTPUT_CTRL,0xFF); //Disable Output Si5351_write(CLK0_CTRL,0x80); //CLOCK0 Power down Si5351_write(CLK1_CTRL,0x80); //CLOCK1 Power down Si5351_write(CLK2_CTRL,0x80); //CLOCK2 Power down Si5351_write(XTAL_LOAD_C,0x92); //Crystal Load Capasitance=8pF Si5351_write(PLL_RESET,0xA0); //Reset PLLA and PLLB Si5351_write(CLK0_CTRL,0x4F); //CLOCK0 Power up Si5351_write(OUTPUT_CTRL,0xFE); //Enable CLOCK0 }
void VFO_Set(uint32_t freqency){ //PLLのセット divider = 900000000 / freqency; if (divider % 2) divider--; PllFreq = divider * freqency; mult = PllFreq / XtalFreq; l = PllFreq % XtalFreq; f = l; f *= 1048575; f /= XtalFreq; num = f; denom = 1048575; 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; Parameter_write(MSNA_ADDR,P1,P2,P3);
//MultiSynth(分周器)のセット P1 = 128 * divider - 512; P2 = 0; P3 = 1; Parameter_write(MS0_ADDR,P1,P2,P3); }
//レジスタにパラメータP1,P2,P3を書き込む。 void Parameter_write(uint8_t REG_ADDR,uint32_t Pa1,uint32_t Pa2,uint32_t Pa3){ Si5351_write(REG_ADDR + 0,(Pa3 & 0x0000FF00) >> 8); Si5351_write(REG_ADDR + 1,(Pa3 & 0x000000FF)); Si5351_write(REG_ADDR + 2,(Pa1 & 0x00030000) >> 16); Si5351_write(REG_ADDR + 3,(Pa1 & 0x0000FF00) >> 8); Si5351_write(REG_ADDR + 4,(Pa1 & 0x000000FF)); Si5351_write(REG_ADDR + 5,((Pa3 & 0x000F0000) >> 12) | ((Pa2 & 0X000F0000) >> 16)); Si5351_write(REG_ADDR + 6,(Pa2 & 0x0000FF00) >> 8); Si5351_write(REG_ADDR + 7,(Pa2 & 0x000000FF)); }
//周波数表示 void Freq_Disp(long frequency){ freqt = String(frequency); String fH = freqt.substring(0,1); String fM = freqt.substring(1,4); String fL = freqt.substring(4,6); ucg.setFont(ucg_font_fur35_tr);//Font設定 //MHzの表示 if (fH != fH_old){ ucg.setColor(0,0,0); ucg.drawBox(60,40,30,40); ucg.setColor(0,255,255); ucg.setPrintPos(60,80); ucg.print(fH); fH_old = fH; }
//KHzの表示 if (fM != fM_old){ ucg.setColor(0,0,0); ucg.drawBox(100,40,80,40); ucg.setColor(0,255,255); ucg.setPrintPos(100,80); ucg.print(fM); fM_old = fM; }
//Hzの表示 if (fL != fL_old){ ucg.setColor(0,0,0); ucg.drawBox(200,40,70,40); ucg.setColor(0,255,255); ucg.setPrintPos(200,80); ucg.print(fL); fL_old = fL; } }
//STEP表示 void Step_Disp(){ ucg.setFont(ucg_font_fur17_tr); ucg.setColor(0,0,0); ucg.drawBox(60,120,70,35); ucg.setColor(255,255,255); ucg.setPrintPos(60,140); if (STEP == 10)ucg.print("10Hz"); if (STEP == 100)ucg.print("100Hz"); if (STEP == 1000)ucg.print("1KHz"); if (STEP == 10000)ucg.print("10KHz"); }
//STEP切り替え void Set_Step(){ if (STEP == 10){ STEP = 10000; }else{ STEP /= 10; } delay(10); Step_Disp(); while(digitalRead(SW_STEP) == LOW){ delay(10); } } void setup(){ //ロータリーエンコーダとSTEP使用ピンの設定とプルアップ pinMode(ENC_A, INPUT_PULLUP); pinMode(ENC_B, INPUT_PULLUP); pinMode(SW_STEP, INPUT_PULLUP); //ロータリーエンコーダ割込み設定 attachInterrupt(ENC_A, rotary, CHANGE); attachInterrupt(ENC_B, rotary, CHANGE);
Wire.begin(); //I2C初期化 Si5351_init(); //Si5351Aの初期化
//TFT初期化 ucg.begin(UCG_FONT_MODE_TRANSPARENT);//透過モード ucg.clearScreen(); //画面クリア ucg.setRotate270(); //画面を270°回転
//Titleの表示 ucg.setFont(ucg_font_ncenB12_tr); ucg.setColor(0,0,255); ucg.setPrintPos(20,20); ucg.print("ESP32 Si5351A 7MHz VFO test");
//周波数初期値表示 Freq_Disp(FREQ); ucg.setPrintPos(85,80); ucg.print("."); ucg.setPrintPos(185,80); ucg.print(".");
//周波数STEPの表示 ucg.setFont(ucg_font_fur17_tr); ucg.setColor(255,255,255); ucg.setPrintPos(60,115); ucg.print("STEP"); Step_Disp(); VFO_Set(FREQ + df); Freq_Disp(FREQ); }
//Main program void loop(){ if(digitalRead(SW_STEP) == LOW)Set_Step(); if(FREQ != FREQ_OLD){ //周波数FREQが変わったら、Si5351Aの周波数を変更 VFO_Set(FREQ + df); Freq_Disp(FREQ); FREQ_OLD = FREQ; //変更された周波数を保存 } delay(10); }
|