So-net無料ブログ作成
検索選択

ColdFire V1 - 一行入力ルーチン [ColdFire (ColdeFire) V1]このエントリーを含むはてなブックマーク#

昨日の一文字送受信を拡張して、一行入力ルーチンをプログラムしてみました。

ソース・コード

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

このプログラムでは、一行分の文字列をラインバッファに入れます。 ラインバッファの長さをBUF_LENGTHで宣言します。

// 定数の宣言
#define   BUF_LENGTH  (72)

// 大域変数の宣言
char lineBuf[BUF_LENGTH];   // ラインバッファ

お便利関数に一行入力ルーチンgetLine(void)を加えました。

// お便利関数の宣言
int     getc(void);
void    putc(int ch);
void    puts(const char *s);
char    *getLine(void);

メイン関数で使用する変数は、今回はすべて局所変数にしました。 一行入力ルーチンからのポインタを入れる変数として、 sを用意しました。

// メイン関数
void main(void) {
  char   *s;              // 行へのポインタ

  // SOPT1を設定する
  SOPT1 = 0
    | SOPT1_WAITE_MASK    // Enable WAIT instruction
    | SOPT1_RSTOPE_MASK   // Enable RSTO* port
    | SOPT1_BKGDPE_MASK   // Enable BKGD port
    | SOPT1_RSTPE_MASK ;  // Enable RESET* port

前回は、内部参照クロックを38400Hzに設定して、 ボーレートをちょうどいい値に合わせたのですが、 今回は、デフォルトの31250Hzを使用することにしました。

バス・クロック周波数は、かなり高めの24MHzに設定しています。

  // ICSを設定する
  //   REFCLK = 31,250Hz
  //   DCO    = 48,000,000Hz
  //   BUSCLK = 24,000,000Hz
  ICSTRM          = NVICSTRM;
  ICSSC_FTRIM     = NVFTRIM_FTRIM;
  ICSC2_BDIV      = 0;  // BDIV 1/1
  ICSSC_DRST_DRS  = 2;  // FLL x1536
  
  // SCI1を設定する
  //   BAUD   = 115200
  //   BR     = BUSCLK / BAUD / 16 = 13
  SCI1BD_SBR = 13;      // BUSCLK / BAUD / 16
  SCI1C2_TE  = 1;       // 送信機能を有効にする
  SCI1C2_RE  = 1;       // 受信機能を有効にする

  EnableInterrupts; /* enable interrupts */
  /* include your code here */

メインループは、一行ずつの処理に変更しました。 かなり、簡単になりました。

  for(;;) {
    puts("\n*READY");    // プロンプトを表示する
    s = getLine();       // 一行受信する
    puts(s);             // 受信した文字を送信する
  } /* loop forever */
  /* please make sure that you never leave main */
}

今回、新規に書き起こした一行入力ルーチンです。

// 一行受信ルーチン
char *getLine(void) {
  char  *p;             // バッファポインタ
  char  c;              // 一文字バッファ
  
  for (;;) {
    putc(':');          // プロンプト出力
    p = lineBuf;        // バッファの先頭を指示
    for (;;) {
      c = (char)getc();
      if (c == 8) {
        // Back Spaceの処理
        putc(c);        // カーソルをもどす
        p--;            // 一文字戻す
        // ポインタがバッファの先頭に達したら、
        // プロンプト出力からやりなおす。
        if (p < lineBuf) break;
      } else if (c == '\n') {
        // Enterの処理
        putc(c);        // 改行出力
        *p = 0;         // 文字列末文字を書き込む
        return lineBuf; // バッファへのポインタを返す
      } else if (c < ' ') {
        // その他のコントロール文字
        continue;       // 単に無視する
      } else if (c == 127) {
        // DELETE文字の処理
        putc('\n');     // 改行出力
        break;          // プロンプト出力からやりなおす
      } else {
        // 通常の文字の処理
        putc(c);        // エコーバック
        *p++ = c;       // バッファに書き込む
        // バッファを使い切ったら、
        if (p >= &lineBuf[BUF_LENGTH]) {
          putc('\n');   // 改行出力
          break;        // プロンプト出力からやりなおす
        }
      }
    }
  }
}

一文字戻す"Back space"キーと一行やりなおす"DELETE"キーを 特殊なキーとして、使用しています。 それ以外のコントロール文字は、無視しています。

残りの部分は、前回と同様です。

// 一文字受信ルーチン
int getc(void) {
  int ch;
  
  // 受信バッファがいっぱいになるのを待つ
  while (!SCI1S1_RDRF) {
    // Do nothing
  }
  ch = SCI1D;           // 一文字受け取る
  if (ch == '\r') {     // Enterキーは、
    ch = '\n';          // 行末文字に変換する
  }
  return ch;            // 受け取った文字を返す
}

// 一文字送信ルーチン
void putc(int ch) {
  if (ch == '\n') {     // 行末文字の前にCRを付ける
    // 送信バッファが空くのを待つ
    while (!SCI1S1_TDRE) {
      // Do nothing
    }
    SCI1D = '\r';       // SCIにCR文字を送信する
  }
  // 送信バッファが空くのを待つ
  while (!SCI1S1_TDRE) {
    // Do nothing
  }
  SCI1D = (byte)ch;     // SCIに一文字送信する
}

// 文字列送信ルーチン
void puts(const char *s) {
  while (*s) {          // 文字列末でなければ、
    putc(*s++);         // 一文字送信する
  }
}

使ってみよう

プログラムは、プロンプトを出した後、一行入力して、それを一行出力するだけのものです。

*READY:10 i=1,100
10 i=1,100
*READY:20 @=i+1
20 @=i+1
*READY:30 #=-1
30 #=-1
*READY:

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この記事のトラックバックURL:
※言及リンクのないトラックバックは受信されません。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。