2017年12月5日火曜日

Knobless Wonder

Knobless Wonderは、VK3YEが開発 した単一周波数のSSBトランシーバである。このトランシーバは、ツマミが無く極めてシンプルな構造をしている。今回、7.15909MHzの水晶発振子を使い、7.160MHz版を作った。出力2W程のQRPであるが、数局とQSOした。電波品位に関しマイナス評価は、今の所ない。
ファイルは、Download siteのKnobless Wonderフォルダからダウンロード可能。






Knobless Wonderで最も重要となるのは、クリスタルフィルタである。水晶発振子は、中華の49US(小型の背が低いタイプ)を入手し、FRMSで特性を測った。最適値では無いが、LSBでのキャリアポイントは、7.1607MHzである。日本国内の7MHz帯運用状況から、1kHZステップでの運用が暗黙の了解なので、1kHZに丸める事が望ましい。従って、このフィルタは使えない。(キャリアポイント有りき、フィルタ帯域である。)



キャリアポイントを7.160MHz±100Hzを目標値とした時、市販部品で作れるフィルタである。一般的に、この様なSSBには不向きと思われる狭帯域となる定数は選ばないであろう。だが求めている物は、HiFi音質でなく、通信に必要な実用レベルの音質なので、これで良い。







オリジナルを改造した回路図である。オリジナル回路のコレクタ抵抗は、ゲインが不足することから、インダクタに交換。更に、低周波出力はスピーカーマイクを使う為にゲインを向上させた。






基板サイズ 73 × 95
pcbeでパターン設計し、中華にPCBを注文した。中華に発注したPCBで組立たが、終段で異常発振した。パターン引き回し上の単純なミスであった。左は、修正済みのパターン。 






2017年11月27日月曜日

stm32版si5351a VFO周波数校正

9月にsi5351a VFOに周波数校正機能を追加したが、機能をTwitterで紹介した程度であったので、機能説明をする。周波数校正機能の起動は、RITスイッチを約1秒長押する。周波数カウンタをCLK0周波数が10MHzとなる様、エンコーダで調整する。(LCDは、基準水晶発振子の周波数表示。)調整後、再びRITスイッチを約1秒長押しすると疑似EEPROMに書き込まれる。



周波数カウンタでCLK0出力周波数を表示している様子。













スケッチ

機能が含まれたスケッチは、JA2GQP's Download siteのstm32フォルダにあるstm32_si5351a.zipファイル。si5351a2.hは、水晶発振子の基本周波数を変数 xtalFreq が定義されているので、zipファイルに含まれたファイルを使う。
      

2017年11月2日木曜日

7.2MHz Knobless Wonder Filter

自作仲間JA2NKD 、JH8SST/7、Kさん でKnobless Wonderを試験している。ここで問題になっているのは、水晶発振子である。価格が安く、多く流通している物が使えれば好ましい。Knobless Wonderサイト、Knobless Wonderサイトに7.2MHz水晶発振子の紹介がある。そこで、日本国内で7.2MHz水晶発振子を使う場合、オフバンドが危惧されるので、バンド内に収まる様なフィルタを試験した。


試験した回路図である。7.2MHz以下に収める必要があるので、多少余裕を見てこの定数とした。試験回路をユニバーサル基板で作った。







FRMSで抵抗マッチング(680Ω)により測定した。一般的に-3dBにおける帯域幅をフィルタ帯域と言っているが、4ポールのシャープファクタの低いフィルタの為、-20dB(一般的なキャリアポイントの位置)でフィルタ定数を決めた。
cf(中心周波数) 7.1979MHz
cp(LSBキャリアポイント)7.1990MHz
試作した結果から、7.2MHzの水晶発振子をフィルタとして使える。ただし、最終的な回路を組み立て、実機検証する必要がある。






参考データ 

コンデンサを47pとした場合のデータである。
















今後の課題 

ユニバーサル基板で試作した為、リード線の浮遊容量が大きい。この回路方式の場合、浮遊インダクタンスの影響を大きく受けるので、最終的な姿で回路定数を決め検証する。




  

2017年9月16日土曜日

stm32 si5351a VFO(With BFO)

 このVFOは、JA2NKD OMのマルチバンドVFO にBFOを付加した物で、stm32F103c8t6+si5351aで構成している。特徴は、BFOが簡単に変更出来る様にした事と、光学エンコーダの採用でアナログ感覚のVFO操作である。BFO変更は、Modeスイッチを長押し(約1秒間スイッチを押す)エンコーダで周波数を調整後、再び、Modeスイッチを長押し(約1秒間)で書換を行う。
光学エンコーダは、中華製400P/R($10位)を使ったため、エンコーダのコントロールSTEPは、1Hz、10Hz、100Hzにした。






回路図である。光学エンコーダの電源は省略してある。stm32への書込みは、シリアルとした。理由は、省メモリとシリアルモニタが使える環境にした。開発環境にST-LINK V2を使った場合、I/O割付に制限がある様なので変更(9/17)した。









スケッチ

JA2NKD OMのオリジナルVFOは、max 8 Bandであるが6 Bandに変更している。VFO周波数は、周波数変化が2秒以上なければ、疑似EEPROMに保存する機能を追加した。si5351a2.hは、オリジナルの物を使っている。ただ、Ucglib.hは私のPC環境で複数のライブラリが参照されるため、参照場所の明確化をした。スケッチと関係ファイルは、download siteのstm32フォルダからダウンロード可能。

///////////////////////////////////////////////////////////////////////////////////
//    stm32 + si5351a VFO(With BFO) Ver1.01
//          (Based on 'JAN2KD 2016.10.19 Multi Band DDS VFO Ver3.1')  
//
//                                                        2017/9/16
//                                                        JA2GQP    
///////////////////////////////////////////////////////////////////////////////////

//---------- Library include ----------

#include "si5351a2.h"                  
#include <SPI.h>
#include <EEPROM.h>
#include <Rotary.h>
#include "src/Ucglib.h"

//----------   Encorder setting  ---------------

#define ENC_A     PB12                    // Rotary encoder A
#define ENC_B     PB13                    // Rotary encoder B

Rotary r=Rotary(ENC_A,ENC_B);

//----------   TFT setting  -------------------

#define   __CS    PB10                    // CS  
#define   __DC    PB0                     // D/C
#define   __RST   PB1                     // RESET

Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);

//----------   CW Tone  -------------------

#define   CW_TONE     700                // 700Hz

//----------   I/O Assign  -------------------

#define   MODE_OUT1    PB15             // 2017/9/17                 
#define   MODE_OUT2    PA8              // 2017/9/17               
#define   BAND_OUT1    PB3
#define   BAND_OUT2    PB4
#define   BAND_OUT3    PB5

#define   SW_BAND      PA0              
#define   SW_MODE      PC14              
#define   SW_STEP      PB14              
#define   SW_RIT       PC15                
#define   SW_TX        PC13              
#define   METER        PA1                

#define   EEP_BAND     0x00               // EEPROM BAND Adress
#define   EEP_INIT     0x0e               //        INIT end Adress

//---------- Variable setting ----------

long      romf[4];                        // EEPROM freq copy buffer
long      freq    = 7100000;
long      freqmax = 7200000;
long      freqmin = 7000000;
long      freqold = 0;
long      freqrit = 0;

String    freqt=String(freq);             // Frequency text

long      ifshift = 0;
long      ifshiftb;
long      romb[5];                        // EEPROM bfo copy buffer
long      vfofreq = 0;
long      vfofreqb;              

char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1;

int       rit        = 0;
int       fstep      = 100;
uint16    steprom    = 1;
uint16    fmode      = 3;
uint16    fmodeb     = 3;
int       fmodeold   = 1;
int       flagrit    = 0;
int       fritold    = 0;
int       flagmode   = 0;
int       meterval1  = 0;
int       tmeterval  = 0;
int       romadd     = 0;
int       rombadd    = 0;
int       analogdata = 0;
uint16    band       = 0;                   // 3.5MHz
int       bandmax    = 6;                   // 6band

uint16    Status;
uint16    Data;          

unsigned long eep_freq[4];
int       eep_romadd;
int       eep_fstep;
int       eep_fmode;
unsigned long eep_bfo[6];
int       eep_rombadd;

int_fast32_t timepassed;                    // int to hold the arduino miilis since startup
int       flg_frqwt = 0;                                // Frequency data Wite Flag(EEPROM)
int       flg_bfowt = 0;                                // BFO Wite Flag(EEPROM)
int       flg_bfochg = 0;                               // BFO Wite Flag(EEPROM)


//----------  Initialization  Program  ----------------------

void setup() {
  timepassed = millis();

  afio_cfg_debug_ports(AFIO_DEBUG_NONE);    // ST-LINK(PB3,PB4,PA15,PA12,PA11) Can be used
  Wire.begin();                

  pinMode( ENC_A,INPUT_PULLUP);                   // PC13 pull up
  pinMode( ENC_B,INPUT_PULLUP);                   // PC14

  attachInterrupt( ENC_A, Rotaly_enc, CHANGE);    // Encorder A
  attachInterrupt( ENC_B, Rotaly_enc, CHANGE);    //          B

  delay(100);
  ucg.begin(UCG_FONT_MODE_TRANSPARENT);
  ucg.clearScreen();
  ucg.setRotate270();

  pinMode(SW_BAND,INPUT_PULLUP);
  pinMode(SW_MODE,INPUT_PULLUP);
  pinMode(SW_STEP,INPUT_PULLUP);
  pinMode(SW_RIT,INPUT_PULLUP);
  pinMode(SW_TX,INPUT_PULLUP);
  pinMode(ENC_A,INPUT_PULLUP);                   // pull up encorede A
  pinMode(ENC_B,INPUT_PULLUP);                   //         encorder B

  pinMode (BAND_OUT1,OUTPUT);
  pinMode (BAND_OUT2,OUTPUT);
  pinMode (BAND_OUT3,OUTPUT);
  pinMode(SW_TX,INPUT_PULLUP);
  pinMode(MODE_OUT1,OUTPUT);
  pinMode(MODE_OUT2,OUTPUT);

  Fnc_eepINIT();
  delay(100);
  band2eep();
  delay(100);

  Status = EEPROM.read(EEP_BAND,&band);         // EEPROM read(frequency)
  romadd=0x010+(band*0x10);
  for (int i=0; i<3;i++){
   romf[i]=Fnc_eepRD((romadd+4*i));
  }
  freq = romf[0];
  freqmin = romf[1];
  freqmax = romf[2];
  Status = EEPROM.read(romadd+12,&fmode);
  Status = EEPROM.read(romadd+14,&steprom);

  eep_rombadd=0x090;                             // EEPROM read(BFO)
  for (int i=0; i<4;i++){
    romb[i]=Fnc_eepRD((eep_rombadd+(4*i)));
    eep_bfo[i] = romb[i];  
  }

  if (steprom==1){fstep=1;}                      // STEP set
  if (steprom==2){fstep=10;}
  if (steprom==3){fstep=100;}
  banddataout();
  screen01();
  chlcd();

  modeset();
  steplcd();
  freqt=String(freq);
  freqlcd();
}

//----------  Main program  ---------------------------------

void loop() {
  if(digitalRead(SW_STEP) == LOW)               // STEP sw check
    setstep();
  else if(digitalRead(SW_MODE) == LOW)          // MODE sw check
    modesw();
  else if(digitalRead(SW_RIT) == LOW)           // RIT sw check
    setrit();
  else if(digitalRead(SW_BAND) == LOW)          // BAND sw check
    bandcall();

  if (digitalRead(SW_TX)==LOW)                  // TX sw check
    txset();

  if (flagrit==1){
    if (freqrit == fritold){
      meter();
    }  
    if (freqrit!=fritold){
      PLL_write();
      ritlcd();
      fritold=freqrit;
    }
  }
  else{
    if (freq == freqold){
      meter();
    }
    PLL_write();
    freqt=String(freq);
    freqlcd();
    freqold=freq;
  }

  if((flg_frqwt == 1) && (flg_bfochg == 0)){                  // EEPROM auto save 2sec
    if(timepassed+1000 < millis()){
      bandwrite();
      flg_frqwt = 0;
    }
  }
}

//----------  EEPROM Data initialization  ---------------      

void band2eep(){
  Status = EEPROM.read(EEP_INIT,&Data);
  if(Data != 73){                       // Iinitialization check
    Status = EEPROM.write(EEP_BAND,1);
 
    eep_romadd=0x010;                   // BAND:0 ROMadd:0x010
    eep_freq[0]=3500000;
    eep_freq[1]=3500000;
    eep_freq[2]=3800000;
    eep_fmode=0;
    eep_fstep=2;
    band2write();

    eep_romadd=0x020;                   // BAND:1 ROMadd:0x020
    eep_freq[0]=7000000;
    eep_freq[1]=7000000;
    eep_freq[2]=7200000;
    eep_fmode=0;
    eep_fstep=2;
    band2write();

    eep_romadd=0x030;                   // BAND:2 ROMadd:0x030
    eep_freq[0]=10100000;
    eep_freq[1]=10100000;
    eep_freq[2]=10150000;
    eep_fmode=2;
    eep_fstep=1;
    band2write();

    eep_romadd=0x040;                   // BAND:3 ROMadd:0x040
    eep_freq[0]=14000000;
    eep_freq[1]=14000000;
    eep_freq[2]=14350000;
    eep_fmode=1;
    eep_fstep=2;
    band2write();

    eep_romadd=0x050;                   // BAND:4 ROMadd:0x050
    eep_freq[0]=21000000;
    eep_freq[1]=21000000;
    eep_freq[2]=21450000;
    eep_fmode=1;
    eep_fstep=2;
    band2write();

    eep_romadd=0x060;                   // BAND:5 ROMadd:0x060
    eep_freq[0]=28000000;
    eep_freq[1]=28000000;
    eep_freq[2]=29700000;
    eep_fmode=1;
    eep_fstep=2;
    band2write();

    eep_rombadd=0x090;                  // BFO ROMadd:0x090
    eep_bfo[0]=7999600;                 //     LSB
    eep_bfo[1]=8002600;                 //     USB
    eep_bfo[2]=8000400;                 //     CW
    eep_bfo[3]=8001100;                 //     AM

    for (int i=0;i<4;i++){
      Fnc_eepWT(eep_bfo[i],(eep_rombadd+4*i));
    }

    Status = EEPROM.write(EEP_INIT,73); // Initialyzed End code
  }
}

//----------  Function Band Write to EEPROM  ---------------      

void band2write(){
  for (int i=0;i<3;i++){
    Fnc_eepWT(eep_freq[i],(eep_romadd+4*i));
  }
  Status = EEPROM.write(eep_romadd+12,eep_fmode);
  Status = EEPROM.write(eep_romadd+14,eep_fstep);
}

//---------- PLL write ---------------------------

void PLL_write(){
  if(flg_bfochg == 0){
    if (flagrit==0)
      vfofreq=freq+ifshift;
    else
      vfofreq=freq+ifshift+freqrit;

    Vfo_out(vfofreq);                         // DDS out  2016/10/24 JA2GQP
    Bfo_out(ifshift);                         // BFO
  }
  else{
    ifshift = freq;
    Bfo_out(ifshift);                         // BFO
    freq = ifshift;
  }
}

//----------  VFO out  ---------------

void Vfo_out(long frequency){
  if(vfofreq != vfofreqb){
    si5351aSetFrequency(frequency);
    flg_frqwt = 1;                                // EEP Wite Flag
    timepassed = millis();
    vfofreqb = vfofreq;
  }
}

//----------  BFO out  ---------------      

void Bfo_out(long frequency){
  if(ifshift != ifshiftb){
    si5351aSetFrequency2(frequency);
    flg_bfowt = 1;                                // EEP Wite Flag
    ifshiftb = ifshift;
  }
}

//---------- meter --------------------------

void meter(){
 meterval1=analogRead(METER);
// meterval1=meterval1/50;                   // old
 meterval1=meterval1/200;                
 if (meterval1>15){meterval1=15;}
  int sx1=sx1+(meterval1*17);
  sx1=sx1+41;
  int sx2=0;
  sx2=sx2+(40+((15-meterval1)*17));
  ucg.setFont(ucg_font_fub35_tr);
  ucg.setColor(0,0,0);
  ucg.drawBox(sx1,180,sx2,16);
  ucg.setPrintPos(40,200);
  for(int i=1;i<=meterval1;i++){
    if (i<=9){
      ucg.setColor(0,255,255);
      ucg.print("-");
    }
    else{
      ucg.setColor(255,0,0);
      ucg.print("-");
    }
  }
}

//---------- Encoder Interrupt -----------------------

void Rotaly_enc(){
  if (flagrit==1){
    unsigned char result = r.process();
    if(result) {
      if(result == DIR_CW){
        freqrit=freqrit+fstep;
        if (freqrit>=10000){
          freqrit=10000;
        }
     }
     else{
      freqrit=freqrit-fstep;
      if (freqrit<=-10000){
        freqrit=-10000;
      }
    }
   }
  }

  else{
    unsigned char result = r.process();
    if(result) {
      if(result == DIR_CW){
        freq=freq+fstep;
        if((flg_bfochg == 0) && (freq>=freqmax)){freq=freqmax;}
      }
      else{
        freq=freq-fstep;
        if((flg_bfochg == 0) && (freq<=freqmin)){freq=freqmin;}
      }
    }
  }
}

//------------ On Air -----------------------------

void txset(){
  if(fmode == 2)                              // CW?
    Vfo_out(vfofreq + CW_TONE);               // Vfofreq+700Hz
  else
    Vfo_out(vfofreq);                         // vfo out
 

  ucg.setPrintPos(110,140);
  ucg.setFont(ucg_font_fub17_tr);
  ucg.setColor(255,0,0);
  ucg.print("ON AIR");
  while(digitalRead(SW_TX) == LOW){
    meter();
  }

  ucg.setFont(ucg_font_fub17_tr);
  ucg.setColor(0,0,0);
  ucg.drawBox(100,120,250,30);  //45
}

//------------- Mode set(LSB-USB-CW-AM) ------------

void modeset(){
    ucg.setFont(ucg_font_fub17_tr);
    ucg.setPrintPos(82,82);
    ucg.setColor(0,0,0);
    ucg.print("USB");
    ucg.setPrintPos(12,82);
    ucg.print("LSB");
    ucg.setPrintPos(82,112);
    ucg.print("A M");
    ucg.setPrintPos(12,112);
    ucg.print("C W");  

  switch(fmode){
    case 0:                                       // LSB
      ifshift = eep_bfo[0];
      ucg.setPrintPos(12,82);
      ucg.setColor(255,255,0);
      ucg.print("LSB");
      digitalWrite(MODE_OUT1,LOW);
      digitalWrite(MODE_OUT2,LOW);
      break;
    case 1:                                       // USB                                    
      ifshift = eep_bfo[1];
      ucg.setColor(255,255,0);
      ucg.setPrintPos(82,82);
      ucg.print("USB");
      digitalWrite(MODE_OUT1,HIGH);
      digitalWrite(MODE_OUT2,LOW);  
      break;
    case 2:                                       // CW
      ifshift = eep_bfo[2];
      ucg.setPrintPos(12,112);
      ucg.setColor(255,255,0);
      ucg.print("C W");
      digitalWrite(MODE_OUT1,LOW);
      digitalWrite(MODE_OUT2,HIGH);
      break;
    case 3:                                       // AM
      ifshift = eep_bfo[3];
      ucg.setPrintPos(82,112);
      ucg.setColor(255,255,0);
      ucg.print("A M");
      digitalWrite(MODE_OUT1,HIGH);
      digitalWrite(MODE_OUT2,HIGH);
      break;
    default:
      ifshift = eep_bfo[0];
      ucg.setPrintPos(12,82);
      ucg.setColor(255,255,0);
      ucg.print("LSB");
      digitalWrite(MODE_OUT1,LOW);
      digitalWrite(MODE_OUT2,LOW);
      fmode = 0;
      break;
    }
}

//------------- Mode set SW ------------

void modesw(){
int cnt = 0;

  if(flg_bfochg == 0){
    while(digitalRead(SW_MODE) == LOW){
      delay(100);
      cnt++;
      if(10 <= cnt){                              // BFO data change mode(1sec)
        romadd=0x010+(band*0x10);
        romf[0]=Fnc_eepRD(romadd);
        freq = Fnc_eepRD(0x090+(fmode * 4));
        freqt=String(freq);
        freqlcd();
        ucg.setPrintPos(110,140);
        ucg.setFont(ucg_font_fub17_tr);
        ucg.setColor(255,255,0);
        ucg.print("BFO ADJ");
        fmodeb = fmode;
        flg_bfochg = 1;
        break;
      }
    }
  }
  else{
    while(digitalRead(SW_MODE) == LOW){
      delay(100);
      cnt++;
      if(10 <= cnt){                              // BFO data update(1sec)
        ifshift = freq;
        Fnc_eepWT(ifshift,0x090+(fmode * 4));     // data write
        eep_bfo[fmode] = ifshift;
        freq = romf[0];
        freqt=String(freq);
        freqlcd();
        ucg.setFont(ucg_font_fub17_tr);
        ucg.setColor(0,0,0);
        ucg.drawBox(100,120,250,30);  //45
        flg_bfochg = 0;
        fmode--;
        break;
        }
      }
    }
  if(flg_bfochg == 0)
    fmode++;
  modeset();
  PLL_write();
  while(digitalRead(SW_MODE) == LOW);
}

//------------ Rit SET ------------------------------

void setrit(){
  if(flagrit==0){
    flagrit=1;
    ucg.setFont(ucg_font_fub11_tr);
    ucg.setPrintPos(190,110);
    ucg.setColor(255,0,0);
    ucg.print("RIT");
    ritlcd();
  }
  else {
    flagrit=0;
    vfofreq=freq+ifshift;

    Vfo_out(vfofreq);                       // DDS Out  2016/10/23 JA2GQP

    freqt=String(freq);
    ucg.setFont(ucg_font_fub11_tr);
    ucg.setPrintPos(190,110);
    ucg.setColor(255,255,255);
    ucg.print("RIT");
    ucg.setColor(0,0,0);
    ucg.drawRBox(222,92,91,21,3);
    freqrit=0;
  }
  while(digitalRead(SW_RIT) == LOW);
}

//----------- Rit screen ----------------------

void ritlcd(){
  ucg.setColor(0,0,0);
  ucg.drawBox(222,92,91,21);
  ucg.setFont(ucg_font_fub17_tr);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(230,110);
  ucg.print(freqrit);
}

//-------------- encorder frequency step set -----------

void setstep(){
  if (fstep==100){
    fstep=1;
  }
  else{
    fstep=fstep * 10;
  }
 steplcd();
 while(digitalRead(SW_STEP) == LOW);
}

//------------- Step Screen ---------------------------

void steplcd(){
  ucg.setColor(0,0,0);
  ucg.drawRBox(221,61,93,23,3);
  ucg.setFont(ucg_font_fub17_tr);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(220,80);
  if (fstep==1){ucg.print("     1Hz");}
  if (fstep==10){ucg.print("    10Hz");}
  if (fstep==100){ucg.print("   100Hz");}
}

//----------- Main frequency screen -------------------

void freqlcd(){
  ucg.setFont(ucg_font_fub35_tn);
  int mojisuu=(freqt.length());
  if(freq<100){
    ucg.setColor(0,0,0);
    ucg.drawBox(217,9,28,36);  
  }
  if(f10 !=(freqt.charAt(mojisuu-2))){
    ucg.setColor(0,0,0);
    ucg.drawBox(245,9,28,36);
    ucg.setPrintPos(245,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-2));
    f10 = (freqt.charAt(mojisuu-2));
  }
  if(freq<10){
    ucg.setColor(0,0,0);
    ucg.drawBox(245,9,28,36);  
     }
  if(f1 !=(freqt.charAt(mojisuu-1))){
    ucg.setColor(0,0,0);
    ucg.drawBox(273,9,28,36);
    ucg.setPrintPos(273,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-1));  
    f1  = (freqt.charAt(mojisuu-1));
  }
  if(freq<1000){
    ucg.setColor(0,0,0);
    ucg.drawBox(202,9,15,36);      
    }
  if(f100 !=(freqt.charAt(mojisuu-3))){
    ucg.setColor(0,0,0);
    ucg.drawBox(217,9,28,36);
    ucg.setPrintPos(217,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-3));
    f100 = (freqt.charAt(mojisuu-3));
  }
  if(freq>=1000){
    ucg.setPrintPos(202,45);
    ucg.setColor(0,255,0);
    ucg.print(".");
  }
  if(freq<10000){
    ucg.setColor(0,0,0);
    ucg.drawBox(146,9,28,36);  
    }
  if(f1k !=(freqt.charAt(mojisuu-4))){
    ucg.setColor(0,0,0);
    ucg.drawBox(174,9,28,36);
    ucg.setPrintPos(174,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-4));    
    f1k  = (freqt.charAt(mojisuu-4));
  }
  if(freq<100000){
    ucg.setColor(0,0,0);
    ucg.drawBox(118,9,28,36);
  }
  if(f10k !=(freqt.charAt(mojisuu-5))){
    ucg.setColor(0,0,0);
    ucg.drawBox(146,9,28,36);
    ucg.setPrintPos(146,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-5));
    f10k = (freqt.charAt(mojisuu-5));
  }
   if(freq<1000000){
    ucg.setColor(0,0,0);
    ucg.drawBox(103,9,15,36);
    }
  if(f100k !=(freqt.charAt(mojisuu-6))){
    ucg.setColor(0,0,0);
    ucg.drawBox(118,9,28,36);
    ucg.setPrintPos(118,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-6));
    f100k = (freqt.charAt(mojisuu-6));
  }
     
   if(freq>=1000000){
    ucg.setPrintPos(103,45);
    ucg.setColor(0,255,0);
    ucg.print(".");
  }
   if(freq<10000000){
     ucg.setColor(0,0,0);
    ucg.drawBox(47,9,28,36);
     }
   if(fmega !=(freqt.charAt(mojisuu-7))){
    ucg.setColor(0,0,0);
    ucg.drawBox(75,9,28,36);
    ucg .setPrintPos(75,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-7));
    fmega  = (freqt.charAt(mojisuu-7));
   }
   if(freq<100000000){
    ucg.setColor(0,0,0);
    ucg.drawBox(19,9,28,36);
       }
   if (f10m !=(freqt.charAt(mojisuu-8))){
    ucg.setColor(0,0,0);
    ucg.drawBox(47,9,28,36);
    ucg .setPrintPos(47,45);
    ucg.setColor(0,255,0);
    ucg.print(freqt.charAt(mojisuu-8));
    f10m = (freqt.charAt(mojisuu-8));
   }
}
//----------- Basic Screen -------------------------

void screen01(){
  ucg.setColor(255,255,255);
  ucg.drawRFrame(1,1,314,55,5);
  ucg.drawRFrame(2,2,312,53,5);
  ucg.setColor(50,50,50);
  ucg.drawRBox(5,60,60,25,3);
  ucg.drawRBox(75,60,60,25,3);
  ucg.drawRBox(5,90,60,25,3);
  ucg.drawRBox(75,90,60,25,3);
  ucg.setFont(ucg_font_fub17_tr);
  ucg.setPrintPos(12,82);
  ucg.setColor(0,0,0);
  ucg.print("LSB");
  ucg.setPrintPos(82,82);
  ucg.print("USB");
  ucg.setPrintPos(12,112);
  ucg.print("C W");
  ucg.setPrintPos(82,112);
  ucg.print("A M");
  ucg.setColor(255,255,255);
  ucg.drawRFrame(220,60,95,25,3);
  ucg.drawRFrame(220,90,95,25,3);
  ucg.setFont(ucg_font_fub11_tr);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(175,80);
  ucg.print("STEP");
  ucg.setPrintPos(190,110);
  ucg.setColor(255,255,255);
  ucg.print("RIT");
  ucg.setColor(100,100,100);
  ucg.setPrintPos(10,210);
  ucg.print(" S:  1-----3-------6-------9---Over--------");
  ucg.setPrintPos(10,177);
  ucg.print(" P:  1-----3-----5-----------10--------------");
  ucg.setPrintPos(10,230);
  ucg.setColor(235,0,200);
  ucg.print( "stm32 VFO(with BFO) Ver1.0 JA2GQP");
  ucg.setFont(ucg_font_fub35_tr);
    ucg.setColor(0,255,0);
    ucg.setPrintPos(273,45);
    ucg.print("0");  
}

//---------- Band data call from eeprom ----------

void bandcall(){
  band=band+1;
  if (band>(bandmax-1)){band=0;}
  romadd=0x010+(band*0x010);
 for (int i=0; i<3;i++){
   romf[i]=Fnc_eepRD((romadd+4*i));
  }
  freq = romf[0];
  freqmin = romf[1];
  freqmax = romf[2];
  Status = EEPROM.read(romadd+12,&fmode);
  Status = EEPROM.read(romadd+14,&steprom);

  if (steprom==1){fstep=1;}
  if (steprom==2){fstep=10;}
  if (steprom==3){fstep=100;}

  modeset();
  steplcd();
  freqt=String(freq);
  freqlcd();
  banddataout();
  chlcd();
 while(digitalRead(SW_BAND) == LOW);
}

//---------- Band data write to eeprom ----------

void bandwrite(){
  romadd=0x010+(band*0x010);
    Fnc_eepWT(freq,romadd);
  Status = EEPROM.write(EEP_BAND,band);
  Status = EEPROM.write(romadd+12,fmode);
  if (fstep==1){steprom=1;}
  if (fstep==10){steprom=2;}
  if (fstep==100){steprom=3;}
  Status = EEPROM.write(romadd+14,steprom);
}

//----------  Function EEPROM Initialize  ---------

void Fnc_eepINIT(){
  uint16 dummy;

  EEPROM.PageBase0 = 0x801F000;
  EEPROM.PageBase1 = 0x801F800;
  EEPROM.PageSize  = 0x400;             // 2kB
  dummy = EEPROM.init();
}

//----------  Function EEPROM Read(4byte)  ---------

long Fnc_eepRD(uint16 adr){
  long val = 0;
  uint16 dat,dummy;

  dummy = EEPROM.read(adr,&dat);
  val = dat << 16;
  dummy = EEPROM.read(adr+1,&dat);
  return val | dat;
}

//----------  Function EEPROM Write(4byte)  ---------

void Fnc_eepWT(long dat,uint16 adr){
  uint16 dummy,val;

  val = dat & 0xffff;
  dummy = EEPROM.write(adr+1,val);
  val = dat >> 16;
  val = val & 0xffff;
  dummy = EEPROM.write(adr,val);
}

//---------- Band data output I/O ----------

void banddataout(){
  digitalWrite(BAND_OUT1,LOW);
  digitalWrite(BAND_OUT2,LOW);
  digitalWrite(BAND_OUT3,LOW);
  if (band==0){}
  if (band==1){
   digitalWrite( BAND_OUT1,HIGH);
  }
   if (band==2){
   digitalWrite(BAND_OUT2,HIGH);
  }
  if (band==3){
   digitalWrite(BAND_OUT1,HIGH);
   digitalWrite(BAND_OUT2,HIGH);
  }
  if (band==4){
   digitalWrite(BAND_OUT3,HIGH);
  }
  if (band==5){
   digitalWrite(BAND_OUT1,HIGH);
   digitalWrite(BAND_OUT3,HIGH);
  }
  if (band==6){
   digitalWrite(BAND_OUT2,HIGH);
   digitalWrite(BAND_OUT3,HIGH);
  }
  if (band==7){
   digitalWrite(BAND_OUT1,HIGH);
   digitalWrite(BAND_OUT2,HIGH);
   digitalWrite(BAND_OUT3,HIGH);  
  }
}

//----------  Band No.(Chanel No.) write to LCD ----------

void chlcd(){
  ucg.setColor(0,0,0);
  ucg.drawBox(5,120,80,20);
  ucg.setFont(ucg_font_fub11_tr);
  ucg.setPrintPos(12,137);
  ucg.setColor(255,255,255);
  ucg.print("CH: ");
  ucg.print(band+1);
}


     

2017年7月31日月曜日

K4GC VFO

何時もお世話になっているKさんから、K4GC VFOスケッチについて相談を受けた。エンコーダ操作で周波数調整が困難との事であった。スケッチを見ると割込み処理を行わずに、エンコーダ読取りが行われており、取りこぼしが原因と思われる。今回問題が有ったエンコーダ処理とLCD表示を変更した。

回路図である。
ダイレクトコンバージョン受信機と組合わせた40m CW QRP機で、フルブレイクイン動作する。オリジナルからkey paddleとエンコーダのIO割付のみ変更。









スケッチ

基本的な処理は、オリジナルを継承している。RIT処理がアナログ処理で行われており、参考になる所もある。スケッチは、ダウンロードサイトのsi5351aフォルダ。

/**************************************************************************
   DIRECT CONVERSION CW TRANSCEIVER CONTROLLER WITH IAMBIC KEYER FOR ARDUINO
   Uses SI5351 clock generator shild from Adafruit for VFO
   Uses NT7S SI5351 library for Arduino on github:
   https://github.com/etherkit/Si5351Arduino
   2 x 16 LCD display for frequency, offset, and tuning rate
   Has an iambic keyer with dot/dash memories
   Arduino Pro Mini pin assignments:
   2) Encoder A input
   3) Encoder B input
   4) STEP SW
   5) Iambic paddle DSH input
   6) Iambic paddle DIT input
   7)
   8) Transmit/mute output
   9) Sidetone output
   10) LCD RS output
   11) LCD E output
   12) LCD D4 output
   13) LCD D5 output
   A0) LCD D6 output
   A1) LCD D7 output
   A2)
   A3)
   A4) si5351 SDA
   A5) si5351 SCL
   A6) Offset voltage input
   A7) Keyer speed voltage input
 ***************************************************************************/

#include <si5351.h>
#include "Wire.h"
#include <Rotary.h>
#include "src/LiquidCrystal.h"                // use Arduino LCD library.


//----------   PLL setting  --------------------

Si5351 si5351;

//----------   LCD setting  --------------------

LiquidCrystal lcd(10, 11, 12, 13, A0, A1);  // RS,E,D4,D5,D6,D7

//----------   Encorder setting  ---------------

#define   ENC_A       2                       // Encorder A
#define   ENC_B       3                       // Encoeder B

Rotary r=Rotary(ENC_A,ENC_B);


////////////////////////ENCODER SETUP///////////////////////////////////////
#define SW_STEP       4
#define Pad_Dah       5
#define Pad_Dit       6  
#define XMIT          8
#define TONE          9

#define LW_FRQ        7000000L
#define HI_FRQ        7200000L

long Vfo_Dat = 7030000L;                      //Start up frequency <<<2017/6/27>>>
long Vfo_Datb = 0;                            //                   <<<2017/6/27>>>
int Enc_Stp = 10;                             // STEP=10Hz
int rateindicator = 5;
char Lcd_data[17] = "                ";
int Flg_Set0 = 1;
/////////////////////////////////////////////////////////////////////////////

//////////////////////////////RIT SETUP//////////////////////////////////////
int rit = A6;
int ritvoltage = 0;
int oldritvoltage = 0;
int modulo = 0;
int ritcenter = 512;
int rittune = 0;
int rittuneb = rittune;
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////IAMBIC KEYER////////////////////////////////////
int count = 0;
int dit = 1;
int dah = 1;
int sidetone = 700;
int ditmem = 0;
int dahmem = 0;
int sspeed = 50;
int speedinput = A7;
/////////////////////////////////////////////////////////////////////////////

//----------  Setup  ---------------

void setup(){
  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);
  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
  lcd.begin(16, 2);

  pinMode(Pad_Dah, INPUT_PULLUP);                  // Dah
  pinMode(Pad_Dit, INPUT_PULLUP);                  // Dit

  pinMode(SW_STEP, INPUT_PULLUP);                  // STEP

  pinMode(TONE, OUTPUT);
  pinMode(XMIT, OUTPUT);
  digitalWrite(XMIT, HIGH);

  PCICR |=(1<<PCIE2);
  PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
  sei();

  Fnc_Step_Disp();
}

//----------  Main loop  --------

void loop() {
  if(digitalRead(SW_STEP) == LOW)                   // STEP SW On?
    Fnc_Stp();                          

  setclock0();
 
  ritvoltage = analogRead(A6);
  rittune = ritvoltage - ritcenter;
  rittune = rittune * 5;
  if (ritvoltage != oldritvoltage){
    ritune();
  }

  if (ditmem == 1) makedit();
  if (dahmem == 1) makedah();
  sspeed = analogRead(speedinput);
  sspeed = sspeed / 6.5;
  if (sspeed < 24) sspeed = 24;
  count = 0;
  checkpaddle();
}

//----------  Encorder procedure(INT)  ---------------

ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if(result) {  
    if(result == DIR_CW)
      Vfo_Dat = Vfo_Dat + Enc_Stp;
    else
      Vfo_Dat = Vfo_Dat - Enc_Stp;
    Vfo_Dat = constrain(Vfo_Dat,LW_FRQ,HI_FRQ);
  }
  Flg_Set0 = 1;
}

//----------  Set Clock0  ---------------

void setclock0() {                            //function to set the SI5351 clock frequency
  if(Flg_Set0 == 1){
    lcd.setCursor(2, 0);
    Fnc_Dot_Edit(Lcd_data,Vfo_Dat);
    lcd.print(Lcd_data);
    lcd.print(" MHz");
    si5351.set_freq((Vfo_Dat + rittune) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
  }
  Flg_Set0 = 0;
}

//----------  RIT proc  ---------------

void ritune() {                             //function to determine RIT offset frequency
  modulo = 0;
  oldritvoltage = ritvoltage;
  rittune = ritvoltage - ritcenter;
  rittune = rittune * 5;                    //RIT steps in 5 Hz increments
  if (rittune > 30) {                       //Keep a dead zone near 0 offset
    rittune = rittune;
  }
  else if (rittune < -30)  {
    rittune = rittune;                      //Keep a dead zone near 0 offset
  }
  else {
    rittune = 0;
  }
  lcd.setCursor(8, 1);
  lcd.print("        ");
  lcd.setCursor(8, 1);
  lcd.print("Rit");
  if (rittune > 0) {
    lcd.print("+");
  }
  lcd.print(rittune);
  Flg_Set0 = 1;
  setclock0();
}

//----------  Check Paddle  ---------------

void checkpaddle() {                            //function for checking iambic paddle status
  dit = digitalRead(Pad_Dit);
  dah = digitalRead(Pad_Dah);
  if (!dit) makedit();
  if (!dah) makedah();
}

//----------  Dit make proc  ---------------

void makedit() {                                //function to make dits
  count = 0;
  ditmem = 0;
  si5351.set_freq(Vfo_Dat * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
  digitalWrite(XMIT, 0);
  tone(TONE, sidetone);
  while (count < sspeed) {
    dah = digitalRead(Pad_Dah);
    if (!dah) dahmem = 1;
    delay(1);
    ++count;
  }
  count = 0;
  noTone(TONE);
  digitalWrite(XMIT, 1);
  si5351.set_freq((Vfo_Dat + rittune) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
    while (count < sspeed) {
    dah = digitalRead(Pad_Dah);
    delay(1);
    ++count;
  }
}

//----------  Dah make proc  ---------------

void makedah(){                                 //function to make dahs
  count = 0;
  dahmem = 0;
  si5351.set_freq(Vfo_Dat * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
  digitalWrite(XMIT, 0);
  tone(TONE, sidetone);

  while (count < (sspeed * 3)){
    dit = digitalRead(Pad_Dit);
    if (!dit) ditmem = 1;
    delay(1);
    ++count;
  }

  count = 0;
  noTone(TONE);
  digitalWrite(XMIT, 1);
  si5351.set_freq((Vfo_Dat + rittune) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);

  while (count < sspeed) {
    dit = digitalRead(Pad_Dit);
    if (!dit) ditmem = 1;
    delay(1);
    ++count;
  }
}

//----------  Function String Dot Edit  --------
 
char *Fnc_Dot_Edit(char *str,long n){
  int  i = 0;                           // Write the number
  char *p = str;
  unsigned long  u = abs(n);

  do{
    *p++ = "0123456789"[u % 10];
    u = u / 10;
    i++;
    if((0 != u) && (0 == (i % 3)))
      *p++ = '.';
    }
  while( 0 != u );

  if ( n < 0 )
     *p++ = '-';
   *p = '\0';
   Fnc_Revr( str );
   return str;
}

//----------  Function String Reverse  ---------

void Fnc_Revr(char *str){
  int i,n;
  char c;

  n=strlen(str);
  for(i = 0;i < n / 2;i++){
    c=str[i];
    str[i]=str[n - i - 1];
    str[n - i - 1]=c;
  }
}

//----------  Function Encorder STEP  ---------

void Fnc_Stp(){
  if(Enc_Stp == 10000)                   // Step = 10kHz ?
    Enc_Stp = 10;                        //   Yes,100khz set
  else
    Enc_Stp = Enc_Stp * 10;              // Step up 1 digit

  Fnc_Step_Disp();
  while(digitalRead(SW_STEP) == LOW)
    ;
  delay(50);
}

//----------  Function STEP Display  ----------

void Fnc_Step_Disp(){
  lcd.setCursor(0,1);
  switch(Enc_Stp){
    case 10:
      lcd.print("Step10 ");
      break;
    case 100:
      lcd.print("Step100");
      break;
    case 1000:
      lcd.print("Step1k ");
      break;
    case 10000:
      lcd.print("Step10k");
      break;
    default:
      lcd.print("Step10 ");
      Enc_Stp = 10;
      break;
  }
}


     

2017年6月17日土曜日

stm32VFO 6mAM

stm32f103c8t6とsi5351aを使って、50MHzAM用VFOを作った。周波数は50MHzから51MHzまでとし、STEPは1Khz、10kHzとした。電源off時の周波数とSTEPを電源on時に復帰させるメモリ機能を付加したVFOである。資料は、Download siteのstm32フォルダに保存してある。






stm32BaseBordから不要な部分を除いた、回路図である。












スケッチ

si5351a2.hは、本来、スケッチと同じフォルダに入れるが、srcフルダに入れ階層的にした。PLL発振出力は clk0 1chのみである。デフォルト周波数は、50.6MHzとし、STEPは10kHz刻みにした。受信機はダブルスーパ(IF=10.7MHz)を想定したので、条件が異なれば修正が必要。メモリー保存は、AD7C方式を採用した。また、周波数補正は、si5351a2.hの41行目XTAL_FREQ 25000000を実周波数(カウンターなどで測定した値)に書換えれば良い。

///////////////////////////////////////////////////////////////////
//    si5351a Simple 50MHz AM VFO(Memory Version) Ver1.01
//                                        2017/6/17
//                                        JA2GQP
//-----------------------------------------------------------------
//  Bug fixes
//    Encoder processing problem.   Ve.1.01 2017/8/17
///////////////////////////////////////////////////////////////////

#include <LCD5110_Basic.h>
#include <Rotary.h>
#include <EEPROM.h>
#include "src/si5351a2.h"

#define ENC_A     PC13                            // Rotary encoder A
#define ENC_B     PC14                            // Rotary encoder B
#define SW_STEP   PC15                            // Frequency Change Step
#define SW_TX     PB12                            // TX switch

#define LOW_FREQ  50000000                        // Lowwer Frequency (50MHz)
#define HI_FREQ   51000000                        // Upper Frequency  (51MHz)
#define IF_FREQ   10700000                        // IF Frequency

#define EEP_FREQ  0x00                            // EEPROM Frequency Adress
#define EEP_STEP  0x04                            //        STEP
#define EEP_INIT  0x20                            // Initialyze check Adress
#define EEP_END   0x73                            // Initialyze check data

//------ Register define ------

long Vfo_freq =  50600000;                        // Default Frequency(50.6MHz )
long Vfo_freqb = Vfo_freq;                        // Frequency Old
long Enc_step = 10000;                            // Default STEP
byte Flg_Tx;                                      // TX Flag

uint16 Status;
uint16 Data;

int_fast32_t timepassed;                          // int to hold the arduino miilis since startup

int Flg_eepWT = 0;                                // EEP Wite Flag

char Lcd_data[10];

//------  nokia5110 ------

LCD5110 myGLCD(PB3,PB5,PA15,PA12,PA11);        // SCK,MOSI,DC,RST,CS
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];

//------  Rotaly Encorder ------

Rotary r = Rotary(ENC_A,ENC_B);               // ENC_A=2,ENC_B=3

//---------- Setup -----------------------------------------------------------------

void setup(){
  timepassed = millis();
  Wire.begin();                  

  attachInterrupt(PC13, Rotaly_enc, CHANGE);    // Encorder A
  attachInterrupt(PC14, Rotaly_enc, CHANGE);    //          B

  pinMode(PC13,INPUT_PULLUP);                   // PC13 pull up
  pinMode(PC14,INPUT_PULLUP);                   // PC14
  pinMode(SW_STEP,INPUT_PULLUP);
  pinMode(SW_TX,INPUT_PULLUP);


  Fnc_eepINIT();
 
  Status = EEPROM.read(EEP_INIT, &Data);
  if(Data != EEP_END){
    Status = EEPROM.write(EEP_INIT, EEP_END);
    Vfo_freq = 50600000;
    Fnc_eepWT(Vfo_freq,EEP_FREQ);
    Fnc_eepWT(Enc_step,EEP_STEP);
  }
  else{
    Vfo_freq = Fnc_eepRD(EEP_FREQ);
    Enc_step = Fnc_eepRD(EEP_STEP);
  }


  Si5351_write(XTAL_LOAD_C,0x80);               // Crystal Load Capasitance=8pF
  si5351aSetFrequency(Vfo_freq);                // CLK0

  myGLCD.InitLCD();                             // nokia5110 Initialyze
  Feq_disp(Vfo_freq);
  Stp_disp();
  myGLCD.setFont(SmallFont);
  myGLCD.print("JA2GQP",CENTER,32);
}

//---------- Main Loop --------------------------------------------------------

void loop(){
  if(Flg_Tx == 0){
    if(digitalRead(SW_STEP) == LOW)             // STEP sw check
      Fnc_Stp();
  }                      

  if(digitalRead(SW_TX) == LOW)                 // Tx On?
    Flg_Tx = 1;                            
  else                                  
    Flg_Tx = 0;                                          

  if(Vfo_freq != Vfo_freqb){                    // Frequency update?
    Vfo_freqb = Vfo_freq;
    Flg_eepWT = 1;
    myGLCD.clrRow(0);
    myGLCD.clrRow(1);
    Feq_disp(Vfo_freq);                         // Frequency display
  }

    if(Flg_Tx  == 0){
      si5351aSetFrequency(Vfo_freq+IF_FREQ);    // CLK0 = RX frequency
      myGLCD.setFont(SmallFont);  
      myGLCD.print("     ", CENTER,16);
    }    
    else{
      si5351aSetFrequency(Vfo_freq);            // CLK0 = TX frequency
      myGLCD.setFont(SmallFont);  
      myGLCD.print("OnAir", CENTER,16);
    }

  if(Flg_eepWT == 1){  
    if(timepassed+2000 < millis()){
      Fnc_eepWT(Vfo_freq,EEP_FREQ);
      Flg_eepWT = 0;
    }
  }  
 
}

//---------- Rotary Encorder Interrupt handling ------------------------------

void Rotaly_enc(){
  noInterrupts();
  unsigned char result = r.process();
  if(Flg_Tx == 0){
    if(result) {  
      if(result == DIR_CW)
        Vfo_freq = Vfo_freq + Enc_step;
      if(result == DIR_CCW)
        Vfo_freq = Vfo_freq - Enc_step;
      Vfo_freq = constrain(Vfo_freq,LOW_FREQ,HI_FREQ);    // Frequency range check
    }
  }
  interrupts();
}

//---------- Step -------------------------------------------------------------

void Fnc_Stp(){
  if(Enc_step == 10000)                           // Step = 10kHz ?
//    Enc_step = 10;                                // 10Hz set
     Enc_step = 1000;                             // 1kHz set
  else
    Enc_step= Enc_step * 10;
  Stp_disp();
  while(digitalRead(SW_STEP) == LOW)
    ;
  delay(20);
}


//---------- Frequency Display ------------------------------------------------

void Feq_disp(long f_disp){
  char s[4] ={'\0'};

  Fnc_Dot_Edit(Lcd_data,f_disp/1000L);
  myGLCD.setFont(MediumNumbers);
  myGLCD.print(Lcd_data,RIGHT, 0);

//  myGLCD.printNumI(f_disp/1000L,RIGHT, 0);
//  myGLCD.setFont(SmallFont);
//  sprintf(s,"%03d",f_disp%1000L);
//  myGLCD.print(s,RIGHT,16);

}

//---------- Step Display ------------------------------------------------------

void Stp_disp(){
  myGLCD.setFont(SmallFont);
  switch(Enc_step){
//    case 10:
//      myGLCD.print("10  ", LEFT,16);
//      break;
//    case 100:
//      myGLCD.print("100 ", LEFT,16);
//      break;
    case 1000:
      myGLCD.print("1k  ", LEFT,16);
      break;
    case 10000:
      myGLCD.print("10k ", LEFT,16);
      break;
    default:
      myGLCD.print("10k ", LEFT,16);
      Enc_step = 10000;
      break;
  }
  Fnc_eepWT(Enc_step,EEP_STEP);
}

//----------  Function String Dot Edit  --------
   
char *Fnc_Dot_Edit(char *str,long n){
  int  i = 0;                           // Write the number
  char *p = str;
  unsigned long  u = abs(n);

  do{
    *p++ = "0123456789"[u % 10];
    u = u / 10;
    i++;
    if((0 != u) && (0 == (i % 3)))
      *p++ = '.';
    }
  while( 0 != u );

  if ( n < 0 )
     *p++ = '-';
   *p = '\0';
   Fnc_Revr( str );
   return str;
}

//----------  Function String Reverse  ---------

void Fnc_Revr(char *str){
  int i,n;
  char c;

  n=strlen(str);
  for(i = 0;i < n / 2;i++){
    c=str[i];
    str[i]=str[n - i - 1];
    str[n - i - 1]=c;
  }
}

//----------  Function EEPROM Initialize  ---------

void Fnc_eepINIT(){
  uint16 dummy;
 
  EEPROM.PageBase0 = 0x801F000;
  EEPROM.PageBase1 = 0x801F800;
  EEPROM.PageSize  = 0x400;             // 2kB
  dummy = EEPROM.init();
}

//----------  Function EEPROM Read(4byte)  ---------

long Fnc_eepRD(uint16 adr){
  long val = 0;
  uint16 dat,dummy;

  dummy = EEPROM.read(adr,&dat);
  val = dat << 16;
  dummy = EEPROM.read(adr+1,&dat);
  return val | dat;
}

//----------  Function EEPROM Write(4byte)  ---------

void Fnc_eepWT(long dat,uint16 adr){
  uint16 dummy,val;

  val = dat & 0xffff;
  dummy = EEPROM.write(adr+1,val);
  val = dat >> 16;
  val = val & 0xffff;
  dummy = EEPROM.write(adr,val);
}


2017年6月12日月曜日

stm32f103c8t6 Base Bord

stm32f103c8t6のスケッチを開発するにあたり、プロトタイプのベースボードを作った。同時に、このボードのI/O割付に修正したスケッチサンプルを作った。このサンプルを使えば、VFOを簡単に作る事が出来るであろう。





ベースボードの回路図である。スケッチ書込みポートは、シリアルのコネクタを設けてあり、USBアダプタ(CH340G)を直接繋ぐ事ができる。表示器は、0.96"OLED、1.8"TFT、nokia5110を繋ぐ事ができる。si5351a取付コネクタを設けてあるので、このままVFO開発が可能。






サンプルスケッチ

全てのサンプルは、先に紹介した回路図に対応する様、I/O割付を変更済である。回路図通り接続し、即、スケッチが実行可能。このサンプルスケッチは、JA2GQP's Download siteのstm32フォルダ。

・Blink

LEDのブリンク。

・encorder

stm32f103c8t6の割込み処理は自由度がある。どのポートに割付しても、割込み処理で動作させる事ができる。

・si5351a

PLL出力(clk0、clk2)の出力サンプル。

・noki5110

nokia5110液晶文字表示サンプル。

・oled(ssd1306)

oledグラフィック表示サンプル。

・メモリ記憶

エンコーダと組合わせた、メモリ記憶のサンプル。

・Ucglib(ili9341、st7735)

TFT液晶の表示サンプル。

VFO製作例


              
サンプルスケッチを基にして作ったVFO。