SSブログ

ColdFire V1 - ラインエディタの入り口 [ColdFire (ColdeFire) V1]このエントリーを含むはてなブックマーク#

一行入力ルーチンを利用して、ラインエディタに拡張しました。 ただし、ユーザ・インターフェース部分だけ。

ソース・コード

/*
 * $Source: /mnt/cvs/rep/CW/CFQE20/Sources/main.c,v $
 * $Id: main.c,v 1.1 2008/01/26 10:49:39 noritan Exp $
 */
#include  /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

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

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

入力された行を解析するために大域変数にラインポインタを導入しました。 解析中のラインバッファの中の文字を指します。

// お便利関数の宣言
int     getc(void);
void    putc(int ch);
void    puts(const char *s);
void    getLine(void);
int     getNumber(void);
void    insertLine(const int nLine, const char *line);
void    removeLine(const int nLine);
char    *findLine(const int nLine);
void    listLines(void);
void    putNumber(const int n);

関数をいくつか追加し、 getLineの定義を見直しました。 詳細は、後ほど。

// メイン関数
void main(void) {
  int       nLine;        // 入力した数値

入力された数値を記憶する局所変数を定義します。

  // 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

  // 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");         // プロンプトを表示する
    getLine();                // 一行受信する
    nLine = getNumber();      // 数値を取り出す
    if (nLine < 0) {          // 数値がない時には
      puts("*ERROR*");        // エラー表示
    } else if (nLine == 0) {  // 数値が0の時には、
      listLines();            // リストを表示する
    } else if (!*linePoint) { // 数値だけの時には、
      removeLine(nLine);      // 削除
    } else {                  // それ以外は、
      insertLine(nLine, linePoint); // 挿入
    } 
  } /* loop forever */
  /* please make sure that you never leave main */
}

メイン関数でエディタの動作を規定しています。

  • 数字で始まらない入力は、エラー表示して無視する。
  • 数値0で始まる入力は、リストを表示する。
  • 数値だけの入力は、該当の行を削除する。
  • 数値に文字列が続く入力は、その行を挿入する。
// 一行受信ルーチン
void 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;         // 文字列末文字を書き込む
        linePoint = lineBuf;  // バッファへのポインタを返す
        return;
      } 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;        // プロンプト出力からやりなおす
        }
      }
    }
  }
}

一行入力ルーチンは、ラインバッファへのポインタを返すかわりに、 大域変数のラインポインタに値を返す方式に変更しました。 もしかしたら、次は元に戻してしまうかも。

// 一文字受信ルーチン
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++);         // 一文字送信する
  }
}

これら三つのルーチンは、これまでと同じです。

// ラインポインタの位置から数値を取り出す
int getNumber(void) {
  int n = 0;                    // 数値
  
  if (!isdigit(*linePoint)) {   // 数字がなければ、 
    return -1;                  // -1 を返す
  }
  while (isdigit(*linePoint)) { // 数値の十進変換
    n = n * 10 + ((*linePoint) - '0');
    linePoint++;
  }
  return n;                     // 数値を返す
}

ラインポインタが指示する位置の文字列から数値を取り出します。 数値が無ければ、-1を返します。

// 数値の表示 - ZERO SUPPRESS は省略。
void putNumber(int n) {
  int m = 1000000;          // 着目する桁
  
  while (m > 0) {           // 一の位まで表示する
    putc((n / m) + '0');    // 着目桁の表示
    n %= m;                 // 残りの桁の部分
    m /= 10;                // 着目桁の移動
  }
}

与えられた数値を十進数で表示します。 あまりにもダサイので、後で何とかしましょう。

// 行挿入
void insertLine(const int nLine, const char *line) {
  // STUB
  puts("INSERT ");
  putNumber(nLine);
  puts(line);
}

// 行削除
void removeLine(const int nLine) {
  // STUB
  puts("REMOVE ");
  putNumber(nLine);
}

// リスト出力
void listLines(void) {
  // STUB
  puts("LIST ");
}

肝心の編集機能部分は、スタブです。 実際には、何もしません。

シミュレータを使ってみよう

CodeWarriorには、シミュレータが付いています。 シミュレータには、端末のシミュレータ"Terminal"も入っているので、 CodeWarriorをインストールするだけで入出力の実験ができます。

"Terminal"シミュレータは、 メニューバーの"Component→Open..."で出てくる "Open Window Component"ダイアログから選択します。

"Terminal"ウィンドウが開いたら、右クリックでプルダウンメニューを出し、 "Configure Connections..."で設定を行います。

右下の"Virtual SCI"にある二つのポートの設定を"Sci0"から"Sci1"に変更して、 "OK"をクリックしたら、準備完了です。 シミュレータ上でプログラムを実行すると、 プロンプトが表示されて、入出力が出来るようになります。


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

nice! 0

コメント 0

コメントを書く

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

トラックバック 0

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

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