2025年3月28日金曜日

CW ABC

CWから遠ざかっているので、忘れた感覚を取り戻す為にCW練習機を作った。練習モードは、ABC連続、ABC数字連続、ABC数字ランダムおよびカナ連続、カナランダムから選択できる。LCD0802を使って、5文字表示と打鍵速度表示を行った。マイコンはATiny1614を使って、BCDスイッチ(モード切り替えSW)とRepeat SWは割込み処理にした。









回路図












スケッチ

fabcとfkanaは、ANKコード表による。但しコード表にない文字 ヰは#と表示、ヱはェ
(小さいエ)と表示することにした。ANKコードは下表。
























モード設定はBCD SW行い、速度はボリュームで設定する。
連続モード(sequenceモード)時は、REP_SW操作でリピート開始/リピート中止ができる。

////////////////////////////////////////////////  
//  CW Trainer Ver.1.0
//                                2025/3/31
//                                JA2GQP
////////////////////////////////////////////////

#include <LiquidCrystal.h>

/////////////////////////////
//  Micro define
/////////////////////////////  
#define SP_DO   4                   // SP
#define SPEED   8                   // SPEED
#define freq    700                 // tone freq(Hz)
#define msw_1   7                   // mode SW BIT0  
#define msw_2   6                   //            1
#define msw_4   5                   //            2
#define REP_SW  11

const int rs = 10 , en = 9, d4 = 3, d5 = 2, d6 = 1, d7 = 0;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

/////////////////////////////
//  Morse Code & font table
/////////////////////////////
byte acode[36] =
{0x06,0x11,0x15,0x09,0x02,0x14,0x0b,0x10,0x04,0x1e,  // A B C D E F G H I J
  0x0d,0x12,0x07,0x05,0x0f,0x16,0x1b,0x0a,0x08,0x03,  // K L M N O P Q R S T
  0x0c,0x18,0x0e,0x19,0x1d,0x13,0x3f,0x3e,0x3c,0x38,  // U V W X Y Z 0 1 2 3
  0x30,0x20,0x21,0x23,0x27,0x2f};                     // 4 5 6 7 8 9

byte fabc[36]  =
{0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,  // A B C D E F G H I J
  0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,  // K L M N O P Q R S T
  0x55,0x56,0x57,0x58,0x59,0x5a,0x30,0x31,0x32,0x33,  // U V W X Y Z 0 1 2 3
  0x34,0x35,0x36,0x37,0x38,0x39};                     // 4 5 6 7 8 9

byte kcode[50] =
{0x3b,0x06,0x0c,0x3d,0x22,0x12,0x25,0x18,0x1d,0x1f,  // ア イ ウ エ オ カ キ ク ケ コ  
  0x35,0x2b,0x37,0x2e,0x17,0x05,0x14,0x16,0x3a,0x24,  // サ シ ス セ ソ タ チ ツ テ ト
  0x0a,0x15,0x10,0x1b,0x1c,0x11,0x33,0x13,0x02,0x09,  // ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ
  0x19,0x34,0x03,0x31,0x29,0x0e,0x39,0x07,0x08,0x0b,  // マ ミ ム メ モ ヤ ユ ヨ ラ リ
  0x2d,0x0f,0x1a,0x0d,0x2a,0x04,0x2c,0x29,0x26,0x1e}; // ル レ ロ ワ ン " ゜㋼ エ ヲ

byte fkana[50] =
{0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,  // ア イ ウ エ オ カ キ ク ケ コ
  0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,  // サ シ ス セ ソ タ チ ツ テ ト
  0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,  // ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ
  0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,  // マ ミ ム メ モ ヤ ユ ヨ ラ リ
  0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,0x23,0xaa,0xa6}; // ル レ ロ ワ ン " ゜㋼ エ ヲ

/////////////////////////////
// memory define
/////////////////////////////
int dottime;
int dashtime;
int interval1;
int interval2;
byte mode_val = 0;
byte mode_i = 0;                    // mode IRQ flag
byte rep_i = 0;                     // repeat IRQ flag

//-------- set up --------------------------------------------------//

void setup(){
  pinMode(msw_1, INPUT_PULLUP);
  pinMode(msw_2, INPUT_PULLUP);
  pinMode(msw_4, INPUT_PULLUP);
  pinMode(REP_SW, INPUT_PULLUP);

  attachInterrupt(msw_1,mode_irq,CHANGE);
  attachInterrupt(REP_SW,rep_irq,FALLING);

  randomSeed(100);
  lcd.begin(8, 2);
  lcd.print("CW ABC");
  lcd.setCursor(0, 1);
  lcd.print("ver1.0");
  delay (1000);
  lcd.clear();
  mode_SW();
};

//-------- main ----------------------------------------------------//

void loop(){
  mode_SW();
  lcd.clear();
  lcd.setCursor(0 ,0);

  switch(mode_val){
    case 0:                           // ABC to number sequence
      lcd.print("Seq A09");
      delay(1000);
      HR_BT();
      WPM();
      lcd.setCursor(0, 1);
      seqChar(36);
      break;

    case 1:                           // random ABC
      lcd.print("Ran ABC");
      delay(1000);
      HR_BT();
      WPM();
      lcd.setCursor(0, 1);
      rndChar(26);
      break;

    case 2:                           // ABC to number ramdom
      lcd.print("Ran A09");
      delay(1000);
      HR_BT();
      WPM();
      lcd.setCursor(0, 1);
      rndChar(36);
      break;

    case 3:                           // kana sequence
      lcd.print("Seq kana");
      delay(1000);
      HR_HORE();
      WPM();
      lcd.setCursor(0, 1);
      seqChark(50);
      break;

    case 4:                           // kana ramdom
      lcd.print("Ran kana");
      delay(1000);
      HR_HORE();
      WPM();
      lcd.setCursor(0, 1);
      rndChark(50);
      break;

    case 5:
    case 6:
    case 7:
      break;
    default:
      break;
  }
}

//--------  ABC 0-9 sequence output --------------------------------//

void seqChar(int n){
int cnt=0;                            // counter clear

  while (cnt <n){
    morseTone(acode[cnt]);            // morsecode out
    delay(interval1);                 // wait
    lcd.write(fabc[cnt]);             // A to Z LCD out

    if (( (cnt+1) % 5) ==0){          // 5 dijit check
      delay(300);
      lcd.clear();
      WPM();
      lcd.setCursor(0, 1);

      if(rep_i == 1)
        cnt = cnt - 5;
    }

    cnt++;
    if(mode_i == 1)                   // IRQ check
      break;                          // exit loop
  }
  AR();
  lcd.clear();
}

//-------- random ABC output ---------------------------------------//

void rndChar(int n){
int cnt=0;                              // counter clear

int x;
  while (cnt <80){
    x = random(n);                      // randum code
    morseTone(acode[x]);                // morsecode out
    delay(interval1);                   // wait
    lcd.write(fabc[x]);                 // A to Z LCD out

    if (( (cnt+1) % 5) ==0){            // 5 dijit check
      delay(500);
      lcd.clear() ;
      WPM();
      lcd.setCursor(0, 1);
    }
    cnt++;
    if(mode_i == 1)                     // IRQ check
      break;                            // exit loop
  }
  AR();
  lcd.clear();
}

//--------  kana sequence output -----------------------------------//

void seqChark(int n){
int cnt=0;                              // counter clear

  while (cnt <n){
    morseTone(kcode[cnt]);              // morsecode out
    delay(interval1);                   // wait
    lcd.write(fkana[cnt]);              // kana LCD out

    if (( (cnt+1) % 5) ==0){            // 5 dijit check
      delay(300);
      lcd.clear() ;
      WPM();
      lcd.setCursor(0, 1);

      if(rep_i == 1)
        cnt = cnt - 5;
    }
    cnt++;
    if(mode_i == 1)                     // IRQ check
      break;                            // exit loop
  }
  SN();
  lcd.clear();
}

//-------- kana random output --------//

void rndChark(int n){
int cnt=0;                              // counter clear
int x;
  while (cnt <80){
    x = random(n);                      // randum code
    morseTone(kcode[x]);                // morsecode out
    delay(interval1);                   // wait
    lcd.write(fkana[x]);                // kana LCD out

    if (( (cnt+1) % 5) ==0){            // 5 dijit check
      delay(500);
      lcd.clear() ;
      WPM();
      lcd.setCursor(0, 1);
    }
    cnt++;
    if(mode_i == 1)                     // IRQ check
      break;                            // exit loop
  }
  SN();
  lcd.clear();
}

//-------- mode SW -------------------------------------------------//

void mode_SW(){
  mode_val = 0;
  if(digitalRead(msw_1) == LOW)
    mode_val = mode_val + 1;
  if(digitalRead(msw_2) == LOW)
    mode_val = mode_val + 2;
  if(digitalRead(msw_4) == LOW)
    mode_val = mode_val + 4;
  mode_i = 0;
}

//-------- mode IRQ ------------------------------------------------//

void mode_irq(){
  mode_i = 1;
}

//-------- ESC IRQ ------------------------------------------------//

void rep_irq(){
  delay(50);
  rep_i = rep_i ^ 1;
}

//-------- HR HR BT code output ------------------------------------//

void HR_BT(){
  lcd.clear();
  WPM();
  lcd.setCursor(0 ,1);

  HR();
  HR();
  lcd.print("BT");
  morseTone(0x11);                    // B code output
  morseTone(0x03);                    // T code output
  delay(interval2 *2);
  lcd.clear();
}

//-------- HR code output ------------------------------------------//

void HR(){
  lcd.print("HR ");
  morseTone(0x10);                    // H code output
  delay(interval1);
  morseTone(0x0a);                    // R code output
  delay(interval1);
}

//-------- AR code output ------------------------------------------//

void AR(){
  morseTone(0x2a);
  delay(interval1);
}

//-------- ラタ code output ------------------------------------------//

void SN(){
  morseTone(0x28);
  delay(interval1);
}

//-------- code speed ----------------------------------------------//

void code_speed(){
  dottime = analogRead(SPEED) / 5;
  dashtime = dottime * 3;
  interval1 = dottime * 2;
  interval2 = dottime * 4;
}

//-------- code tone output ----------------------------------------//

void morseTone(int m){
  while (m != 1){
    if ((m & 1) == 0){
      tone(SP_DO,freq,dottime);         // dot
      delay(interval1);
    }
    else{
      tone(SP_DO,freq,dashtime);        // dash
      delay(interval2);
    }
    m = m >> 1;                         // 1bit shift right
  }
}

//-------- WPM -----------------------------------------------------//

void WPM(){
  code_speed();
  lcd.setCursor(0, 0);
  lcd.print("WPM");
  lcd.print(2400 / interval1);
  lcd.setCursor(7, 0);
  lcd.print(mode_val);
}

//-------- HR HR ホレ code output ------------------------------------//

void HR_HORE(){
  lcd.clear();
  WPM();
  lcd.setCursor(0 ,1);

  HR();
  HR();
  morseTone(0x09);                      // ホ code output
  morseTone(0x0f);                      // レ code output
  lcd.write(0xce);
  lcd.write(0xda);
  delay(interval2 *2);
  lcd.clear();
}

ダウンロード
スケッチ、回路図はJA2GQP's Download siteCWフォルダーからダウンロードできる。






2024年12月12日木曜日

6m AM VFO

6m AM TRX専用のVFOを作った。ATmega1614、si5351とoled表示器を使ったVFO。6m AM TRXはダブルス―パー方式を採用したので、si5351の全てのチャンネルを使うことにした。また、新しい機能として受信SHIFTを追加した。SHIFT機能は、受信周波数を-1.5k(LSB)、+1.5k(USB)、SHIFTゼロ(ブランク)をSHIFT SWで切り替えて行う仕様である。







回路図

















 

スケッチ

//////////////////////////////////////////////////////////////////////
//  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フォルダーからダウンロード可能。