SSブログ

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

トラックバックの受付は締め切りました