目次

エレクトリックキーヤー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 ) ;
}


目次

inserted by FC2 system