LPC810M021FN8 (15) -- ディジタル SCR (3)

8 ビット AVR 用のディジタル SCR プログラムでは、動作を変えるためにはプログラム自体を変更しなければならなかったので、動作モードを表すシンボルを定義して使っていました。
LPC810 のプログラムではハード的に実現しているので、動作の変更は、単に内蔵モジュールへ設定するパラメタの変更ですみ、プログラム自体を大きく変える必要はありません。
そこで、アナログ・コンパレータ、SCT (State Configurable Timer)、スイッチ・マトリクスのそれぞれの初期設定のための関数

  LPC8xx_acmp_setup();
  LPC8xx_sct_scr_setup();
  LPC8xx_pin_setup();

を用意し、動作モードのバリエーションは、主に各関数へ渡すパラメタの変更で行うようにしました。 (ピン割り当ての変更は LPC8xx_pin_setup() 関数の中身をいじる必要がある)
今回は SCT 設定のための LPC8xx_sct_scr_setup() 関数のソース・リストを掲載します。

void LPC8xx_sct_scr_setup(LPC_SCT_T *pSCT, int32_t SCR_PW)
{
  int ev_n, out_m;
  
// set counter High for "digital SCR"
// halt SCT timer_H to modify params
  pSCT->CTRL_H |=  SCT_CTRL_HALT_L; // halt counter
// set SCT config
  pSCT->CONFIG |= (1UL << 18);   // use AUTOLIMIT_H
// LIMIT_H event 
  ev_n = 0;  
  out_m = ((0 <= SCR_PW) ? SCR_PW : -SCR_PW); // abs(SCR_PW)
  pSCT->MATCH[ev_n].H    = out_m;
  pSCT->MATCHREL[ev_n].H = out_m;
// STOP_H event  
  ev_n  = 3; 
  out_m = ev_n;  
  pSCT->OUTPUTDIRCTRL    &= ~(0x3 << (2*ev_n)); // normal operation
  pSCT->MATCH[ev_n].H     = 0;
  pSCT->MATCHREL[ev_n].H  = 0;
  pSCT->EVENT[ev_n].CTRL  = (  ev_n       // MATCHSEL = n
                            | (1UL << 12) // COMBMODE = MATCH only
                            | (1UL << 4)  // HEVENT
                            );
  pSCT->EVENT[ev_n].STATE = 1;        // enable EVENT_n at STATE=0
  if (0 <= SCR_PW) {
    pSCT->OUT[out_m].SET  = (1 << ev_n); // set   CT_OUT_m at EVENT_n
  } else {
    pSCT->OUT[out_m].CLR  = (1 << ev_n); // clear CT_OUT_m at EVENT_n
  } // if (0 <= SCR_PW) { ...
  pSCT->STOP_H            = (1 << ev_n); // EVENT_n for STOP_H
// START_H event
  ev_n  = 5;
  out_m = 3;
  pSCT->EVENT[ev_n].CTRL  = ( (3UL << 6)  // IOSEL = 3
                            | (3UL << 10) // IOCOND = H level
                            | (2UL << 12) // COMBMODE = IO only
                            | (1UL << 4)  // HEVENT
                            );
  pSCT->EVENT[ev_n].STATE  = 1;        // enable EVENT_n at STATE=0
  if (0 <= SCR_PW) {
    pSCT->OUT[out_m].CLR   = (1 << ev_n); // clear CT_OUT_m at EVENT_n
  } else {
    pSCT->OUT[out_m].SET   = (1 << ev_n); // set   CT_OUT_m at EVENT_n
  } // if (0 <= SCR_PW) { ...
  pSCT->START_H           = (1 << ev_n); // EVENT_n for START_H
// set SCT control and start timer_H (HALT=0, STOP=0)
  pSCT->CTRL_H = (                 
                   SCT_CTRL_CLRCTR_L          // clear counter_H
                 | SCT_CTRL_PRE_L(1 - 1)      // prescaler_H = 1/1
                 );
} // void LPC8xx_sct_scr_setup()

LPCOpen V2.01 のインクルード・ファイル "chip.h" を利用しています。
LPC8xx_sct_scr_setup() 関数は、PWM セットアップのための LPC8xx_pwm_setup() 関数の直後に呼び出されるものとして、バスクロックのイネーブルなどは省略してあります。
PWM セットアップで設定された SCT 出力 CTOUT_3、イベント 3 を「奪って」ワンショット動作のために設定し直しています。
まず、念のため、CTRL_H レジスタの HALT ビットを立ててカウンタを停止させておきます。
そして、CONFIG レジスタの AUTOLIMIT_H ビットを立ててオートリミット・モードを有効にします。
パルス幅は SCR_PW パラメタで渡しますが、値が正の場合はリセット/リワインド・パルスは負極性、値が負の場合は正極性のパルスとなるように設定しています。
イベント 3 をワンショットの停止イベントとして使っています。
カウンタ・マッチのみによるイベントですが、H 側カウンタを使うので、HEVENT ビットを立てて H 側であることを指定する必要があります。

  ev_n  = 3; 
  ...
  pSCT->EVENT[ev_n].CTRL  = (  ev_n       // MATCHSEL = n
                            | (1UL << 12) // COMBMODE = MATCH only
                            | (1UL << 4)  // HEVENT
                            );

イベント 5 を外部入力 CTIN_3 によるワンショット起動のトリガに使います。

// START_H event
  ev_n  = 5;
  pSCT->EVENT[ev_n].CTRL  = ( (3UL << 6)  // IOSEL = 3
                            | (3UL << 10) // IOCOND = H level
                            | (2UL << 12) // COMBMODE = IO only
                            | (1UL << 4)  // HEVENT
                            );

アナログ・コンパレータの反転入力、非反転入力との対応が分かりやすいように、「H」レベルをトリガ有効とします。
最後に L 側カウンタの動作には影響を与えず、H 側カウンタだけをスタートさせます。

// set SCT control and start timer_H (HALT=0, STOP=0)
  pSCT->CTRL_H = (                 
                   SCT_CTRL_CLRCTR_L          // clear counter_H
                 | SCT_CTRL_PRE_L(1 - 1)      // prescaler_H = 1/1
                 );

H 側カウンタのスタートなのに、設定しているのは L 側に対する定数となっていますが、これは、32 ビット幅の CTRL レジスタを 16 ビット幅ずつ CTRL_H と CTRL_L としてアクセスした場合に、CTRL_H レジスタでの有効ビット位置は CTRL_L レジスタに対するものと一致するためです。