目次
前
次
エレクトリックキーヤー2
アマチュア無線のリグに、モールス信号を生成するため
エレクトリックキーヤー(電鍵)を作成しました。
電鍵は、長点、短点に相当する論理レベルの'H'を
2つのボタンで生成します。
ボタンを非接触とし、リードスイッチで電鍵を実現。
2個のリードスイッチから入力とサイドトーン用
スピーカ接続とリグへの出力ができるように基板
を作成しました。
左側に、DOT、DASHを与えるリードスイッチを接続。
右側に、リグ、スピーカを接続。
リードスイッチの状態は、シフトレジスタで入力し
L→Hに変化したときに、スイッチが押されたと判断
するカラクリを用意。
リードスイッチは2個あるので、シフトレジスタは
2個用意し、タイマー割込みで定期的に状態をLSB
に入れています。
2個のシフトレジスタの値を利用し、サイドトーンを
出力するシーケンサを起動。シーケンサは、規定時間
だけサイドトーンを出力したなら、自動停止する様に
プログラム。
2機能をステートメントで定義したなら、タイマー割込み
からイベント通知フラグで、時間経過のトリガーを貰って
対応した処理を実行。
ファームウエアの内容は、以下。
/* redefine data type */
typedef unsigned char UBYTE ;
typedef unsigned int UWORD ;
#define OFF 0
#define ON OFF+1
#define CNTBEGIN 131
#define XCNTMAX 65398
#define YCNTMAX 65466
volatile UWORD systim ;
volatile UBYTE tflag ;
volatile UBYTE lcnt ;
volatile UBYTE sflag ;
volatile UBYTE eflag ;
volatile UBYTE sfts ;
volatile UBYTE sftl ;
volatile UBYTE scnt ;
volatile UBYTE xport ;
volatile UWORD xf ;
volatile UBYTE aport ;
volatile UBYTE aportx ;
volatile UBYTE tmp ;
/* function prototype */
void init_usr(void);
void plc(UBYTE x);
void send_h(UBYTE x);
void delay_cnt(UWORD x);
/* interrupt handler */
void interrupt(void)
{
/* timer 0 generate 1kHz */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* update system timer */
systim = systim + 1 ;
/* set flag */
tflag = ON ;
}
/* timer 1 overflow */
if ( PIR1.TMR1IF == ON ) {
/* clear flag */
PIR1.TMR1IF = OFF ;
/* initialize */
TMR1L = xf & 0xff ;
TMR1H = xf / 256 ;
/* increment */
scnt = scnt + 1 ;
/* get PORTA state */
aport = PORTA ;
/* default */
aport &= ~0x04 ;
/* sound out */
tmp = eflag & scnt.F0 ;
if ( tmp ) { aport |= 0x04 ; }
/* impress */
PORTA = aport ;
}
}
void main(void)
{
/* user initialize */
init_usr();
/* endless loop */
while ( ON ) {
/* shift register */
if ( tflag == ON ) {
/* clear flag */
tflag = OFF ;
/* get switch 2 bits */
xport = PORTA ;
xport = swap(xport);
/* inverse */
xport = xport ^ 0x03 ;
xport = xport & 0x03 ;
/* shift */
sfts <<= 1 ;
sftl <<= 1 ;
/* mask */
sfts = sfts & 3;
sftl = sftl & 3;
/* set */
if ( xport == 1 ) { sfts = sfts + 1 ; }
if ( xport == 2 ) { sftl = sftl + 1 ; }
/* default */
sflag = OFF ;
lcnt = 0 ;
/* judge */
if ( sfts == 1 ) {
sflag = ON ;
lcnt = 3 ;
}
if ( sftl == 1 ) {
sflag = ON ;
lcnt = 9 ;
}
if ( sflag == ON ) {
/* clear flag */
sflag = OFF ;
/* impress : H */
send_h(ON);
/* run */
plc( lcnt );
/* impress : L */
send_h(OFF);
}
}
}
}
/* define function body */
void init_usr(void)
{
/* 4MHz */
OSCCON = (0x0d << 3) | 0x03 ;
/* disable A/D converter */
ADCON0.ADON = OFF ;
ADCON2 = 0 ;
/* disable D/A converter */
DACCON0.DACEN = OFF ;
/* disable compare module */
CM1CON0.C1ON = OFF ;
CM1CON0.C1OE = OFF ;
/* I/O state */
PORTA = 0x00 ;
/* I/O directions */
TRISA = 0xf8 ; /* bit0,1,2 as output , others as input */
/* pull-up */
WPUA = 0x30 ;
/* initialize Timer 0 */
{
/*
4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
125kHz/250 = 500Hz
*/
OPTION_REG = 0x02 ;
/* 256 - 131 = 125 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* initialize Timer 1 */
{
/*
4MHz/4 = 1MHz -> 1MHz/8 = 125kHz
125kHz / 880 or 440
*/
T1CON = 0x30 ;
/* enable timer1 overflow interrupt */
PIE1.TMR1IE = ON ;
INTCON.PEIE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
tflag = OFF ;
sflag = OFF ;
eflag = OFF ;
/* others */
lcnt = 0 ;
systim = 0 ;
scnt = 0 ;
sfts = 0 ;
sftl = 0 ;
}
void plc(UBYTE x)
{
UBYTE i ;
/* default */
xf = XCNTMAX ;
/* calculate */
TMR1L = xf & 0xff ;
TMR1H = xf / 256 ;
/* enable */
T1CON.TMR1ON = ON ;
/* delay */
for ( i = 0 ; i < x ; i++ ) { delay_cnt(10); }
/* disable */
T1CON.TMR1ON = OFF ;
}
void send_h(UBYTE x)
{
/* get state */
aportx = PORTA ;
/* update flag */
eflag = x ;
/* judge */
if ( x ) { aportx = aportx | 0x01 ; }
else { aportx = aportx & 0xfe ; }
/* update */
PORTA = aportx ;
}
void delay_cnt(UWORD x)
{
UWORD last ;
/* calculate */
last = systim + x ;
/* wait */
while ( systim < last ) ;
}
目次
前
次