esmKeyer629:PIC12F629-I/Pを用いたベーシックエレキー

Initial release: 18 June, 2024
Revised: 29 June, 2024
Note: 本機は計画とブレッドボードテストのみで実機化はしていません.実機化はesmKeyer222(計画編実機製作編)で実施しました.

今さらという感もしないわけではないですが...

手元にあったPIC12F629-I/Pで基本的なエレキーを作ってみました.スクイーズ操作ではなく,EK-103/Zのような短点優先タイプです.(短点)メモリーはありません.現状はフォトカプラを除いた回路でのブレッドボードテストの段階で,送信機に接続したテストはまだ行っていません.

基本回路図です:

U1がPIC12F629-I/Pです.GP5(Pin2),GP4(Pin3)及びGP2(Pin5)はプログラムで内部プルアップを設定しています.内部プルアップが信頼できないという方は10kΩ〜47kΩくらいで外部プルアップして下さい.クロックは内蔵4MHzオシレータをキャリブレートせずに使っています.

キーイングはフォトカプラU3で絶縁したPNPトランジスタQ1で行うこととし,エレキーの回路を送信機から絶縁します(昔,トランジスタだけでキーイングした時に酷い目にあったことがあります:苦笑).

モードスイッチはOFF(内部プルアップでH)が通常のキーイング動作です.キーヤ内蔵サイドトーンはスイッチでON/OFFできます.

モードスイッチON(L)で速度設定モードになり,このときは連動スイッチで内蔵サイドトーンも動作させます.ただし,送信キーライン(フォトカプラに接続されるライン:GP0)は動作させません.短点一つを入力する毎に1wpm増加,長点一つを入力する毎に1wpm減少するようにしています.速度範囲は欧文暗語で5wpm〜20wpm(25cpm〜100cpm)の16段階です.

内蔵サイドトーンはLMC555CN(U2)による50%デューティ発振回路です.この回路定数(130kΩ,6.8nF)で約800Hzを発振します.4番ピン〜GNDにつながっている10kΩは,サイドトーンスイッチがどちらもオフの場合に発振を停止させるためのプルダウン抵抗です.

欧文暗語の送信速度に応じた短点時間の計算結果をこちら(Googleスプレッドシート)に示します.プログラムはこれをベースに,短点は1ms,長点は3msの時間待ちを送信速度に応じた回数(G列の値)繰返すことにより発生させています.本当ならば,for文で費やす時間を考慮する必要がありますが,ここでは無視しています.

xc8用のソースコードは以下のとおりです(ダウンロードする場合はこちら).割込も使わず,安直に書いています.(同じようなコードはきっとどこかにあると思いますが,0から書き起こしたので)ライセンスはCC BY-NC-SA 4.0 Internationalとします:

/*
 * File:   esmKeyer629.c
 * Author: Cosy MUTO, JH5ESM
 *
 * Version 1.0, 18 June, 2024
 * CC BY-NC-SA 4.0 International
 *     https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en
 */

// PIC12F629 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ 4000000

#define basetimedot   1
#define basetimedash  3

// 16 code speed steps from 5wpm to 20wpm, default 9 (14wpm, 72ms/dot)
int klist[] = {204, 170, 145, 127, 112, 101, 92, 84, 77, 72, 67, 63, 59, 56, 53, 50};

void main(void) {
    // Pin assignment for the keyer
    // 1 VDD -> VDD
    // 2 GP5 -> Dot,   active Low
    // 3 GP4 -> Dash,  active Low
    // 4 GP3 -> MCLR,  active Low
    // 5 GP2 -> Speed, active Low
    // 6 GP1 -> Keyer sidetone, active High
    // 7 GP0 -> Keyout, active High
    // 8 VSS -> VDD
    
    OPTION_REG = 0b00000000; // GPIO pull-up enabled
    TRISIO = 0b00111100;
    GPIO   = 0b00111100;
    WPU    = 0b00110100; // Weak Pull-up enabled on GP5, GP4 & GP2

    int i;
    int j = 9; // default speed: 70cpm/14wpm, 72ms/dot
    int k = klist[j];

    while(1){
        while(GP2){ // normal operation
            if(!GP5){ // dot
                GP0 = 1;
                GP1 = 1;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedot);
// wait 1ms for designated times
                }
                GP0 = 0;
                GP1 = 0;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedot);
// wait 1ms for designated times
                }
            }
            if(GP5 && !GP4){ // dash
                GP0 = 1;
                GP1 = 1;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedash);
// wait 3ms for designated times
                }
                GP0 = 0;
                GP1 = 0;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedot);
// wait 1ms for designated times
                }
            }
        }
        while(!GP2){ // set speed
            if(!GP5){ // QRQ
                GP1 = 1;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedot);
// wait 1ms for designated times
                }
                GP1 = 0;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedot);
// wait 1ms for designated times
                }
                j += 1;
                if(j > 15){
                    j = 15;
                }
                k = klist[j];
            }
            if(GP5 && !GP4){ // QRS
                GP1 = 1;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedash);
// wait 3ms for designated times
                }
                GP1 = 0;
                for(i=0;i < k;i++){
                    __delay_ms(basetimedot);
// wait 1ms for designated times
                }
                j -= 1;
                if(j < 0){
                    j = 0;
                }
                k = klist[j];
            }
        }
    }
}

HEXファイルはこちら

メモリ使用状況は,データが42バイト,プログラムが454ワードでした.これなら,サイドトーンのラインをキーイングラインと共用(あるいはサイドトーンなし)してリセットもGPIOとして使えば,ベースラインの10F322でも作れそうです.