/* * Si5351A VFO for 7MHz Tranciever Ver1.31 * 受信用にCLK0,CLK1に90度位相差のあるクロックを発生する。 * CLK2は送信用 * 2018.20.26 バグ修正版 * JH7UBC Keiji Hata */ #include #include #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 #define CLK0_PHOFF 165 #define CLK1_PHOFF 166 const uint32_t XtalFreq = 25000000; const int DF = 110;//Si5351Aの周波数補正値 const int CW_SHIFT = 700;//CWトーン周波数 uint32_t FREQ_RX; //受信用周波数 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; char PLL; uint8_t PLL_ADDR; uint8_t MS_ADDR; //各定数の定義 //Rotary Encoder #define ENC_A 2 //Rotary encoder A #define ENC_B 3 //Rotary encoder B //Switchの定義 #define SW_STEP 4 //STEP Switch #define SW_RIT 5 //RIT Switch #define SW_TX 12 //TX Switch uint32_t FREQ = 7000000 + DF; //VFO周波数初期値 const uint32_t LOW_FREQ = FREQ; //下限周波数 const uint32_t HI_FREQ = FREQ + 200000; //上限周波数 uint32_t FREQ_OLD = FREQ; //周波数の前の値 int STEP = 1000; //STEP 初期値 int RIT_FREQ = 0; //Rit周波数初期値 int RIT_OLD = RIT_FREQ; //フラッグ初期値 uint8_t Flg_Rit = 0; //Ritフラッグ //送信・受信 int val = 1; //SW_TX初期値 int old_val = 1; //SW_TXの前の値 LCD5110 myGLCD(8,9,10,11,12); // SCK,MOSI,DC,RST,CS extern uint8_t SmallFont[]; extern uint8_t MediumNumbers[]; Rotary r = Rotary(ENC_B,ENC_A); //ENC_A=3,ENC_B=2 void setup() { Wire.begin(); //Arduino is Master Si5351_init(); //Si5351Aの初期化 //PLLA,PLLBに初期周波数をセット FREQ_RX = FREQ - CW_SHIFT; PLL_Set('A',FREQ_RX); //PLLAに受信用周波数の初期値をセット MS_Set(0); Si5351_write(CLK0_PHOFF,0); MS_Set(1); Si5351_write(CLK1_PHOFF,divider); //CLK1の位相を90°遅らせる PLL_Set('B',FREQ); //PLLBに送信用周波数の初期値をセット MS_Set(2); Si5351_write(PLL_RESET,0xA0); //Reset PLLA & PLLB myGLCD.InitLCD(); //nokia5110の初期化 //各SWのセットアップ pinMode(SW_STEP,INPUT_PULLUP); //STEP SWを入力に設定しプルアップ pinMode(SW_RIT,INPUT_PULLUP); //RIT SWを入力に設定しプルアップ pinMode(SW_TX,INPUT); //TX SWを入力に設定 //ピン変化割り込みの設定 PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); //割り込み許可 //初期画面表示 myGLCD.setFont(SmallFont); myGLCD.print("STEP",12,32); myGLCD.print(".",12,16); myGLCD.print(".",54,16); myGLCD.print("RIT",60,32); Fnc_Freq_Disp(); //周波数表示 Fnc_Step_Disp(); //STEP表示 Fnc_Rit_Disp(); //RIT表示 } //Main program void loop() { val = digitalRead(SW_TX); if( val != old_val){ //SW_TXの値に変化があったら if( val == LOW){ Fnc_Tx(); }else{ Fnc_Rx(); } } old_val = val; if(digitalRead(SW_STEP) == LOW)Fnc_Stp(); //Check STEP SW if(digitalRead(SW_RIT) == LOW)Fnc_Rit(); //Check RIT SW if(FREQ != FREQ_OLD)Fnc_Pll(); //FREQが変化したらPLLの周波数変更 if(RIT_FREQ != RIT_OLD)Fnc_Pll(); delay(10); } //ロータリーエンコーダ処理(ISR=割り込みサービスルーチン) ISR(PCINT2_vect) { unsigned char result = r.process(); if(result){ if(result == DIR_CW){ if(Flg_Rit == 1){ RIT_FREQ += 10; }else{ FREQ += STEP; } }else{ if(Flg_Rit == 1){ RIT_FREQ -= 10; }else{ FREQ -= STEP; } } } FREQ = constrain(FREQ,LOW_FREQ,HI_FREQ); //VFOの下限と上限を超えないように } //SW_TX=LOWの時の処理 void Fnc_Tx(){ delay(5); Si5351_write(OUTPUT_CTRL,0xF8);//Enable CLK2,Enable CLK1,CLK0 } //SW_TX=HIGHの時の処理 void Fnc_Rx(){ delay(5); Si5351_write(OUTPUT_CTRL,0xFC);//Disable CLK2,Enable CLK1,CLK0 } void Fnc_Pll(){ if(Flg_Rit == 1){ FREQ_RX = FREQ -CW_SHIFT + RIT_FREQ; }else{ FREQ_RX = FREQ - CW_SHIFT; } PLL_Set('A',FREQ_RX);//PLLAセット MS_Set(0);//MS0セット MS_Set(1);//MS1セット Si5351_write(CLK1_PHOFF,divider); PLL_Set('B',FREQ);//PLLBセット MS_Set(2);//MS2セット Si5351_write(PLL_RESET,0xA0);//PLL reset Fnc_Freq_Disp(); //周波数を表示する。 FREQ_OLD = FREQ; //変更された周波数を保存 Fnc_Rit_Disp(); RIT_OLD = RIT_FREQ; } //STEP SWが押された時の処理 void Fnc_Stp() { if(STEP == 10){ STEP = 1000; } else{ STEP /= 10; } delay(10); Fnc_Step_Disp(); while(digitalRead(SW_STEP) == LOW){ delay(10); } } //RIT SWが押された時の処理 void Fnc_Rit(){ if (Flg_Rit == 1){ Flg_Rit = 0; }else{ Flg_Rit = 1; } delay(10); while(digitalRead(SW_RIT) == LOW){ delay(10); } Fnc_Pll(); Fnc_Rit_Disp(); } //周波数表示 void Fnc_Freq_Disp() { myGLCD.setFont(MediumNumbers); uint32_t FREQ_Disp = FREQ - DF; uint8_t freqH = FREQ_Disp / 1000000; myGLCD.printNumI(freqH,0,8); uint32_t freqL = FREQ_Disp % 1000000; int fM = freqL /1000; int fL = (freqL % 1000) / 10; myGLCD.printNumI(fM,18,8,3,'0'); myGLCD.printNumI(fL,60,8,2,'0'); } //STEP表示 void Fnc_Step_Disp() { myGLCD.setFont(SmallFont); myGLCD.printNumI(STEP,12,40,4,' '); } //RIT表示 void Fnc_Rit_Disp(){ myGLCD.setFont(SmallFont); if (Flg_Rit == 1){ myGLCD.printNumI(RIT_FREQ,54,40,4); }else{ myGLCD.print(" OFF",54,40); } } //レジスタに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,0x80); //Crystal Load Capasitance=8pF Si5351_write(PLL_RESET,0xA0); //Reset PLLA and PLLB Si5351_write(CLK0_CTRL,0x4F); //CLOCK0 Sorce PLLA Power up 8mA Si5351_write(CLK1_CTRL,0x4F); //CLOCK1 Sorce PLLA Power up 8mA Si5351_write(CLK2_CTRL,0x6E); //CLOCK2 Sorce PLLB Power up 6mA Si5351_write(OUTPUT_CTRL,0xFC); //Enable CLOCK0,CLK1,Disable CLK2 } //PLLの設定 void PLL_Set(char Pll,uint32_t Frequency) { divider = 700000000 / Frequency; if (divider % 2) divider--; PllFreq = divider * Frequency; 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; if (Pll == 'A') { PLL_ADDR = MSNA_ADDR; }else { PLL_ADDR = MSNB_ADDR; } Parameter_write(PLL_ADDR,P1,P2,P3); } //MultiSynth(分周器)のセット void MS_Set(uint8_t MS_No){ P1 = 128 * divider - 512; P2 = 0; P3 = 1; switch(MS_No){ case 0: MS_ADDR = MS0_ADDR; break; case 1: MS_ADDR = MS1_ADDR; break; case 2: MS_ADDR = MS2_ADDR; break; default: MS_ADDR = MS0_ADDR; } Parameter_write(MS_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)); }