目次

ファームウエア検討

 2015年まで、ファームウエアは外国人研修担当時に作成した
 H8/3048用のものを加筆、修正したコードを使っていました。

 マルチプロセッサ構成で、新シャーシを使ったメカには
 相応しくない内容なので、一新します。

 研修担当時に作成したファームウエアでは、密着タイプセンサー
 を使っていました。




 GBC(Game Boy Camera)に合わせた処理に変更し、最上位のデバイスは
 GBCの出力情報を使って移動方法を決定後、DCモータにPWM波形で使う
 DUTY比を出力すると機能限定します。

 入力、出力に必要なビット数を見積もります。

 入力

  GBCを担当するプロセッサはArduino互換で、4ビットで構成した
  情報を利用。

#define ALL_BLACK   0
#define ALL_WHITE   1
#define LEFT_WHITE  2
#define RIGHT_WHITE 3
#define CENTER      4
#define TINY_RIGHT  5
#define RIGHT       6
#define BIG_RIGHT   7
#define TINY_LEFT   8
#define LEFT        9
#define BIG_LEFT    10
#define BOTH_WHITE  11
#define ILLEAGAL    12

  この4ビットの他に、スタートゲートの開閉状態とスタートスイッチ
  の状態を受取る3ビットを用意すれば、入力はおしまい。

  入力は合計7ビットですが、1ビットの予備を考え8ビット。

 出力

  DCモータを動かすために、2ビット必要。

  センサーと内部状態を表示するには、各8ビットあれば充分。

  合算すると、2+8+8=18になります。

  センサーと内部状態を表示する、各8ビットは74HC164のような
  シフトレジスタを間に入れると、転送クロック、データ2ビット
  の合計3ビットで処理可能。

  必要なビット数は、2+3=5になります。

  回路は、次のように単純にできます。



  マイコンからは、3ピンで2ブロックのLEDを制御。

  FPGAでは、内部に専用レジスタがあればよいだけなので
  8ビット出力を2つ用意します。

 ここまでの検討から、Arduino+PICのマルチプロセッサ構成
 基板ではセンサーと内部状態表示をシリアル通信で対応すると
 新しい基板の半田付けは不要と判断。

 Arduinoをピン数の多いSanguinoに交換すれば、他にGameBoyCameraを
 担当するユニットとの接続だけにできます。

 利用メカの特性に最適なファームウエアを用意したいので
 タイヤの回転と線方向の移動距離を求めておきます。

 タイヤ関連諸元からの計算

  DCモータシャフトに取付けたタイヤ直径は、57mm。



  タイヤ円周は、2πr(rは半径)より、57πmm。
  πを3と近似すると、1回転で171mm移動可能に。

  1回転を正の整数で除算すると、次の移動距離に。

  左右のモータの回転数に差がある場合、内周と外周の
  中間にある円弧で、移動する距離を換算してマシンの
  挙動を考えます。




  左右の回転数の差を求め、移動距離の差に換算し
  arc tangentを取れば、回転角度を計算できます。

  瞬時値から、その時点のベクトルを判断できます。




  角度を計算するには、縦、横の値が必要。縦はタイヤの
  回転数の差で求められ、横はモーターのシャフト長で
  固定値になります。

  シャフト長は、固定で154mm。




  左右の回転数の差が0.5であれば、回転角度は45度程度。

  マシンが走行している状態で、45度という回転角度は
  スピンするくらいの大きな力をかけることになります。

  スピンしないでラインを追従するには、回転数の差が
  0.01から0.2程度にするとわかります。
  車速感応制御で、滑らかなに走行させることも考えて
  おかないと。

  回転数の差を求めるには、ロータリーエンコーダを使うことが
  知られていますが、モータに流れる電流値で回転数を算出する
  ことも可能。メカに制約がある場合、電流値による回転数算出
  を利用することに。

 ここまでで大まかな処理を決めたので、APIを利用してトップレベル
 のコードを作成します。

int main(void)
{
  /* initialize */
  init_usr();
  /* detect start gate state */
  sgate = get_start();
  while ( sgate == CLOSED ) {
    /* delay 100ms */
    delay_ms(100);
    /* get start gate state */
    sgate = get_start();
  }
  /* endless loop */
  while ( ON ) {
    /* get sensor state */
    sensor = get_sensor();
    /* judge mode */
    switch ( mode ) {
      case MD_NORMAL : mode = execute_normal(sensor); break ;
      case MD_CRANK  : mode = execute_crank(sensor) ; break ;
      case MD_ROTATE : mode = execute_rotate(sensor); break ;
      case MD_LANE   : mode = execute_lane(sensor);   break ;
      case MD_CHANGE : mode = execute_change(sensor); break ;
      case MD_BLIND  : mode = execute_blind(sensor);  break ;
      default        : break ;
    }
    /* delay 100ms */
    delay_ms(100);
  }
  /* dummy */
  return 0 ;
}

 トップレベルの処理から展開していくと以下。

#include <ADuC7026.h>

#define OFF 0
#define ON  OFF+1

#define NO  0
#define YES NO+1

/* data definitions */
typedef unsigned char  UBYTE ;
typedef   signed char  SBYTE ;
typedef unsigned short UWORD ;
typedef   signed short SWORD ;
typedef unsigned long  ULONG ;
typedef   signed long  SLONG ;

void  IRQ_Handler(void) __irq;
void  init_usr(void);

/*--------------------*/
/* function prototype */
/*--------------------*/
void  delay_100us(UWORD x);
void  delay_ms(UWORD x);

/*---------------*/
/* FPGA handling */
/*---------------*/
UBYTE execute_normal(UBYTE x);
UBYTE execute_crank(UBYTE x);
UBYTE execute_rotate(UBYTE x);
UBYTE execute_lane(UBYTE x);
UBYTE execute_change(UBYTE x);
UBYTE execute_blind(UBYTE x);

UBYTE get_start(void);
UBYTE get_sensor(void);
void  send_duty(UBYTE which,UBYTE x);
void  update_motor(void);

/* global variables */
volatile ULONG timcnt ;

volatile UBYTE lduty ;
volatile UBYTE rduty ;

volatile UBYTE dir[2] ;

#define MD_NONE   0
#define MD_NORMAL MD_NONE+1
#define MD_CRANK  MD_NONE+2
#define MD_ROTATE MD_NONE+3
#define MD_LANE   MD_NONE+4
#define MD_CHANGE MD_NONE+5
#define MD_BLIND  MD_NONE+6

#define ALL_BLACK   0
#define ALL_WHITE   1
#define LEFT_WHITE  2
#define RIGHT_WHITE 3
#define CENTER      4
#define TINY_RIGHT  5
#define RIGHT       6
#define BIG_RIGHT   7
#define TINY_LEFT   8
#define LEFT        9
#define BIG_LEFT    10
#define BOTH_WHITE  11
#define ILLEAGAL    12

#define TRG 18
#define BLD 17
#define ALD 16

#define MASK0F 0x0f

#define DIR_CENTER 0
#define DIR_RIGHT  DIR_CENTER+1
#define DIR_LEFT   DIR_CENTER+2

#define CLOSED 0
#define OPENED CLOSED+1

volatile UBYTE sgate ;
volatile UBYTE sensor ;
volatile UBYTE mode  ;

void main(void)
{
  /* initialize */
  init_usr();
  /* detect start gate state */
  while ( sgate == CLOSED ) {
    /* delay 100ms */
    delay_ms(100);
    /* get start gate state */
    sgate = get_start();
  }
  /* endless loop */
  while ( ON ) {
    /* get sensor state */
    sensor = get_sensor();
    /* judge mode */
    switch ( mode ) {
      case MD_NORMAL : mode = execute_normal(sensor); break ;
      case MD_CRANK  : mode = execute_crank(sensor) ; break ;
      case MD_ROTATE : mode = execute_rotate(sensor); break ;
      case MD_LANE   : mode = execute_lane(sensor);   break ;
      case MD_CHANGE : mode = execute_change(sensor); break ;
      case MD_BLIND  : mode = execute_blind(sensor);  break ;
      default        : break ;
    }
    /* delay 100ms */
    delay_ms(100);
  }
}

void IRQ_Handler(void) __irq
{
  /* judge timer0 interruption (100us) */
  if ( (IRQSTA & RTOS_TIMER_BIT) == RTOS_TIMER_BIT ) {
    /* clear timer0 interrupt flag */
    T0CLRI = 0xff ;
    /* increment */
    timcnt++ ;
    /* judge */
    if ( (timcnt & 0xfff) == 0 ) { GP4DAT ^= (1 << 23); }
  }
}

void init_usr(void)
{
  /* select clock 10.44MHz
     initialized in start up routine
  */
  PLLKEY1 = 0xaa ;
  PLLCON  = 0x01 ;
  PLLKEY2 = 0x55 ;
  /* power control
     initialized in start up routine 
  */
  /* initialize UART */
  {
    /* set baud rate 19200 bps CD = 2 */
    COMCON0 = 0x80 ; /* select COMDIV1 and COMDIV0 */
    COMDIV0 = 0x11 ;
    COMDIV1 = 0x00 ;
    /* set conditions */
    COMCON0 = 0x03 ; /* select COMRX and COMTX , 8bit data , 1 stop bit , no parity */
    /* enable interrupt */
    COMIEN0 = 0x01 ; /* ERBFI */
  }
  /* P0 */
  {
    /* use GPIO */
    GP0CON = 0x00000000 ;
    /* */
    GP0DAT = 0xDF1F0000 ;
  }
  /* P1 */
  {
    /* use UART */
    GP1CON = 0x00000011 ;
    /* */
    GP1DAT = 0xfef00000 ;
  }
  /* P2 */
  {
    /* all bits inputs */
    GP2DAT = 0x00000000 ;
  }
  /* P3 */
  {
    /* all bits outputs */
    GP3DAT = 0xff000000 ;
  }
  /* P4 */
  {
    /* all bits outputs */
    GP4DAT = 0xff030000 ;
  }
  /* initialize timer 0 (10kHz) */
  {
    T0LD  = 1044 ; /* (10.44MHz / 1) / 10kHz */
    T0CON = 0xc0  ; /* enable , cyclic , 1/1  */ 
  }
  timcnt = 0 ;
  lduty  = 0 ;
  rduty  = 0 ;
  update_motor();
  mode = MD_NONE ;
  sgate = CLOSED ;
  /* enable timer 0 interrupt */
  IRQEN = RTOS_TIMER_BIT ;
}

void delay_100us(UWORD x)
{
  ULONG last ;
  /* calculate */
  last = timcnt + x ;
  /* wait */
  while ( timcnt < last ) ;
}

void delay_ms(UWORD x)
{
  ULONG last ;
  /* calculate */
  last = timcnt + 10 * x ;
  /* wait */
  while ( timcnt < last ) ;
}

UBYTE execute_normal(UBYTE x)
{
  UBYTE state ;
  UBYTE dtime ;

  /* default */
  lduty = 30 ;
  rduty = 30 ;
  dtime = 30 ;
  state = MD_NORMAL ;

  if ( x == ALL_BLACK )
  {
    lduty = 10 ; rduty = 10 ; dtime = 10 ;
  }
  if ( x == ALL_WHITE )
  {
    lduty = 30 ; rduty = 30 ; dtime = 30 ;
  }
  if ( x == LEFT_WHITE || x == RIGHT_WHITE || x == CENTER )
  {
    lduty = 50 ; rduty = 50 ; dtime = 30 ;
  }
  if ( x == TINY_RIGHT )
  {
    lduty = 50 ; rduty = 55 ; dtime = 25 ;
  }
  if ( x == RIGHT )
  {
    lduty = 50 ; rduty = 60 ; dtime = 25 ;
  }
  if ( x == BIG_RIGHT )
  {
    lduty = 50 ; rduty = 70 ; dtime = 25 ;
  }
  if ( x == TINY_LEFT )
  {
    lduty = 55 ; rduty = 50 ; dtime = 25 ;
  }
  if ( x == LEFT )
  {
    lduty = 60 ; rduty = 50 ; dtime = 25 ;
  }
  if ( x == BIG_LEFT )
  {
    lduty = 70 ; rduty = 50 ; dtime = 25 ;
  }
  if ( x == BOTH_WHITE )
  {
    lduty = 30 ; rduty = 30 ; dtime = 10 ;
  }
  /* update motor parameters */
  update_motor();
  delay_ms( dtime );

  *(dir+0) = DIR_CENTER;
  if ( x == ALL_WHITE )
  {
    state = MD_CRANK ;
  }
  if ( x == LEFT_WHITE )
  {
    state = MD_LANE ;
    *(dir+0) = DIR_LEFT ;
  }
  if ( x == RIGHT_WHITE )
  {
    state = MD_LANE ;
    *(dir+0) = DIR_RIGHT ;
  }

  return state;
}

UBYTE execute_crank(UBYTE x)
{
  UBYTE state ;
  UBYTE dtime ;

  /* default */
  lduty = 30 ;
  rduty = 30 ;
  dtime = 30 ;

  if ( x == ALL_BLACK )
  {
    lduty = 10 ; rduty = 10 ; dtime = 10 ;
  }
  if ( x == ALL_WHITE )
  {
    lduty = 30 ; rduty = 30 ; dtime = 10 ;
  }
  if ( x == LEFT_WHITE )
  {
    lduty = 30 ; rduty = 30 ; dtime = 20 ;
  }
  if ( x == RIGHT_WHITE )
  {
    lduty = 30 ; rduty = 30 ; dtime = 20 ;
  }
  if ( x == CENTER )
  {
    lduty = 40 ; rduty = 40 ; dtime = 30 ;
  }
  if ( x == TINY_RIGHT )
  {
    lduty = 40 ; rduty = 45 ; dtime = 25 ;
  }
  if ( x == RIGHT ) 
  {
    lduty = 40 ; rduty = 50 ; dtime = 25 ;
  }
  if ( x == BIG_RIGHT )
  {
    lduty = 40 ; rduty = 55 ; dtime = 25 ;
  }
  if ( x == TINY_LEFT )
  {
    lduty = 45 ; rduty = 40 ; dtime = 25 ;
  }
  if ( x == LEFT )
  {
    lduty = 50 ; rduty = 40 ; dtime = 25 ;
  }
  if ( x == BIG_LEFT )
  {
    lduty = 55 ; rduty = 40 ; dtime = 25 ;
  }
  if ( x == BOTH_WHITE )
  {
    lduty = 30 ; rduty = 30 ; dtime = 20 ;
  }

  /* update motor parameters */
  update_motor();
  delay_ms( dtime );

  state = MD_CRANK ;
  *(dir+0) = DIR_CENTER;
  if ( x == ALL_WHITE )
  {
    state = MD_CRANK ;
  }
  if ( x == LEFT_WHITE )
  {
    state = MD_LANE ;
    *(dir+0) = DIR_LEFT ;
  }
  if ( x == RIGHT_WHITE )
  {
    state = MD_LANE ;
    *(dir+0) = DIR_RIGHT ;
  }

  return state;
}

UBYTE execute_rotate(UBYTE x)
{
  UBYTE state ;
  UBYTE dtime ;

  dtime = 30 ;
  state = MD_ROTATE ;
  if ( dir == DIR_LEFT )
  {
    lduty = 30 ; rduty = 50 ;
  }
  if ( dir == DIR_RIGHT )
  {
    lduty = 50 ; rduty = 30 ;
  }
  /* update motor parameters */
  update_motor();
  delay_ms( dtime );

  if ( x == CENTER )
  {
    lduty = 30 ; rduty = 30 ; *(dir+0) = DIR_CENTER ; state = MD_NORMAL ;
  }

  return state;
}

UBYTE execute_lane(UBYTE x)
{
  UBYTE state ;
  UBYTE dtime ;

  /* default */
  lduty = 30 ;
  rduty = 30 ;
  dtime = 30 ;
  state = MD_LANE ;

  if ( x == ALL_BLACK )
  {
    lduty = 10 ; rduty = 10 ; dtime = 10 ;
  }
  if ( x == ALL_WHITE ) 
  {
    lduty = 30 ; rduty = 30 ; dtime = 10 ;
  }
  if ( x == LEFT_WHITE || x == RIGHT_WHITE )
  {
    lduty = 30 ; rduty = 30 ; dtime = 30 ;
  }
  if ( x == CENTER )
  {
    lduty = 40 ; rduty = 40 ; dtime = 30 ;
  }
  if ( x == TINY_RIGHT )
  {
    lduty = 40 ; rduty = 45 ; dtime = 25 ;
  }
  if ( x == RIGHT )
  {
    lduty = 40 ; rduty = 50 ; dtime = 25 ;
  }
  if ( x == BIG_RIGHT )
  {
    lduty = 40 ; rduty = 55 ; dtime = 25 ;
  }
  if ( x == TINY_LEFT )
  {
    lduty = 45 ; rduty = 40 ; dtime = 25 ;
  }
  if ( x == LEFT )
  {
    lduty = 50 ; rduty = 40 ; dtime = 25 ;
  }
  if ( x == BIG_LEFT )
  {
    lduty = 55 ; rduty = 40 ; dtime = 25 ;
  }

  /* update motor parameters */
  update_motor();
  delay_ms( dtime );

  if ( x == ALL_BLACK )
  {
    state = MD_CHANGE ; *(dir+0) = DIR_CENTER ;
  }

  return state ;
}

UBYTE execute_change(UBYTE x)
{
  UBYTE state ;
  UBYTE dtime ;

  /* default */
  dtime = 50 ;
  state = MD_CHANGE ;

  /* turn */
  if ( *(dir+0) == DIR_LEFT )
  {
    lduty = 35 ; rduty = 55 ;
  }
  if ( *(dir+0) == DIR_RIGHT )
  {
    lduty = 55 ; rduty = 35 ;
  }

  /* update motor parameters */
  update_motor();
  delay_ms( dtime );

  /* straight */
  lduty = 30 ;
  rduty = 30 ;

  /* update motor parameters */
  update_motor();
  delay_ms( dtime );

  /* turn */
  if ( x == ALL_BLACK ) {
    if ( *(dir+0) == DIR_LEFT )
    {
	    *(dir+1) = DIR_RIGHT ;
    }
    if ( *(dir+0) == DIR_RIGHT )
    {
      *(dir+1) = DIR_LEFT ;
    }
  }
  return 0;
}

UBYTE execute_blind(UBYTE x)
{
  UBYTE state ;
  UBYTE dtime ;

  /* default */
  dtime = 50 ;
	state = MD_BLIND ;

  /* judge */
  if ( x == CENTER ) {
    if ( *(dir+1) == DIR_LEFT )
    {
      lduty = 25 ; rduty = 35 ;
    }
    if ( *(dir+1) == DIR_RIGHT )
    {
      lduty = 35 ; rduty = 25 ;
    }
    /* update motor parameters */
    update_motor();
    delay_ms( dtime );
    state = MD_NORMAL ;
  } else {
    lduty = 30 ; rduty = 30 ;
    /* update motor parameters */
    update_motor();
    delay_ms( dtime );
  }

  return state ;
}

void send_duty(UBYTE which,UBYTE x)
{
  /* clear */
  GP3DAT = 0xff000000 ;
  /* impress duty */
  GP3DAT |= (x << 16);
  /* send trigger */
  if ( which ) { GP4DAT &= ~(1 << BLD); }
  else         { GP4DAT &= ~(1 << ALD); }
  /* wait */
  delay_100us(1);
  /* send trigger */
  if ( which ) { GP4DAT |= (1 << BLD); }
  else         { GP4DAT |= (1 << ALD); }
}

void update_motor(void)
{
  /* send left duty */
  send_duty(ON, lduty);
  send_duty(OFF,rduty);
  /* send trigger */
  GP4DAT |= (1 << TRG);
  /* wait */
  delay_100us(1);
  /* send trigger */
  GP4DAT &= ~(1 << TRG);
}

UBYTE get_start(void)
{
  return 0;
}

UBYTE get_sensor(void)
{
  UBYTE result ;

  result = GP2DAT & MASK0F ;

  return result ;
}

 RTOSを使う場合、以下とします。

#include "3052.h"

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;
typedef unsigned long  ULONG ;
typedef   signed char  SBYTE ;
typedef   signed short SWORD ;

#define NO  0
#define YES NO+1

typedef struct {
  void  (*tsk)(void);
  UWORD wcount ;
} TCBP ;

#define TSK_ID_MAX 9

#define TSK_ID0 0
#define TSK_ID1 1
#define TSK_ID2 2
#define TSK_ID3 3
#define TSK_ID4 4
#define TSK_ID5 5
#define TSK_ID6 6
#define TSK_ID7 7
#define TSK_ID8 8

#define NORMAL TSK_ID1
#define CRANK  TSK_ID2
#define ROTATE TSK_ID3
#define LANE   TSK_ID4
#define CHANGE TSK_ID5
#define BLIND  TSK_ID6

#define XDEBUG TSK_ID8

#define TTS_SUSPEND 0
#define TTS_WAIT    TTS_SUSPEND+1
#define TTS_READY   TTS_SUSPEND+2

TCBP tcb[TSK_ID_MAX];

/*----------------*/
/* user variables */
/*----------------*/
#define ITU1_AREG 24999

typedef union {
  struct {
    unsigned char B7:1;
    unsigned char B6:1;
    unsigned char B5:1;
    unsigned char B4:1;
    unsigned char B3:1;
    unsigned char B2:1;
    unsigned char B1:1;
    unsigned char B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

FLAGSP xflags ;

ULONG timcnt ;

#define SFLAG xflags.BIT.B0
#define UFLAG xflags.BIT.B1
#define WFLAG xflags.BIT.B2
#define TFLAG xflags.BIT.B3
#define MFLAG xflags.BIT.B4

#define P1DDR P1.DDR
#define P1DR  P1.DR.BYTE
#define P2DDR P2.DDR
#define P2DR  P2.DR.BYTE
#define P3DDR P3.DDR
#define P3DR  P3.DR.BYTE
#define P4DDR P4.DDR
#define P4DR  P4.DR.BYTE
#define P5DDR P5.DDR
#define P5DR  P5.DR.BYTE
#define P6DDR P6.DDR
#define P6DR  P6.DR.BYTE
#define P8DDR P8.DDR
#define P8DR  P8.DR.BYTE
#define P7DR  P7.DR.BYTE
#define P9DDR P9.DDR
#define P9DR  P9.DR.BYTE
#define PADDR PA.DDR
#define PADR  PA.DR.BYTE
#define PBDDR PB.DDR
#define PBDR  PB.DR.BYTE

#define MASKFFFF 0xffff
#define MASKFF   0xff
#define MASKCF   0xcf
#define MASK0F   0x0f
#define MASK80   0x80
#define MASK03   0x03

#define OFF      0
#define ON       OFF+1

#define MASKF0 0xf0

#define CLOSED 0
#define OPENED CLOSED+1

#define DIR_CENTER 0
#define DIR_RIGHT  1
#define DIR_LEFT   2

UBYTE sgate ;
UBYTE timeoutcnt ;

UBYTE dir[2] ;
UBYTE left  ;
UBYTE right ;

UBYTE state  ;
UBYTE mstate ;

UBYTE mode ;

UBYTE sloapf ;
UBYTE sloapr ;
UBYTE sloap  ;
UBYTE sloapt[3] ;

UBYTE xcnt3 ;
UBYTE xcnt5 ;
UBYTE xcnt6 ;

UBYTE normal_l[13] ;
UBYTE normal_r[13] ;

UBYTE crank_l[13] ;
UBYTE crank_r[13] ;

UBYTE lane_l[13] ;
UBYTE lane_r[13] ;

UBYTE run_tsk ;
UWORD ready   ;
UWORD suspend ;
UWORD waitq   ;
UWORD bpat[16] ;

#define ALL_BLACK   0
#define ALL_WHITE   1
#define LEFT_WHITE  2
#define RIGHT_WHITE 3
#define CENTER      4
#define TINY_RIGHT  5
#define RIGHT       6
#define BIG_RIGHT   7
#define TINY_LEFT   8
#define LEFT        9
#define BIG_LEFT    10
#define BOTH_WHITE  11
#define ILLEAGAL    12

#define GEAR0     10
#define GEAR5    150
#define GEAR10   300
#define GEAR15   450
#define GEAR20   600
#define GEAR25   750
#define GEAR30   900
#define GEAR35  1050
#define GEAR40  1200
#define GEAR45  1350
#define GEAR50  1500
#define GEAR55  1650
#define GEAR60  1800
#define GEAR65  1950
#define GEAR70  2100
#define GEAR75  2250
#define GEAR80  2400
#define GEAR85  2550
#define GEAR90  2700
#define GEAR95  2850
#define GEAR100 2999

#define IDLE 0
#define RUN  IDLE+1

#define SGATE_BIT 4
#define EDC_BIT   1

void init_sci_1(TBaudRate x);
void rs1_putchar(UBYTE x);
void rs1_crlf(void);
void rs1_puts(UBYTE *x);
void show_help(void);

UBYTE sindex ;
UBYTE sbuf[16];
UBYTE cmd ;
UBYTE asc_hex[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} ;

/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void  init_usr(void);
void  init_timer1(void);
void  init_table(void);
UBYTE get_hex(UBYTE x);
void  delay_ms(UWORD x);
void  binary_display(UBYTE x);
UWORD conv_value(UBYTE x);
UBYTE get_swx(void);
void  send_motor_power(UBYTE x);

/*-------------*/
/* system call */
/*-------------*/
void  cre_tsk(UBYTE tid,void (*tsk)(void));
void  rsm_tsk(UBYTE tid);
void  sus_tsk(UBYTE tid);
void  slp_tsk(void);
void  wai_tsk(UWORD x);
void  init_os(void);
void  timer_handler(void);
UBYTE is_tsk_ready(UBYTE tid);

/*------*/
/* task */
/*------*/
void  tsk0_proc(void);
void  tsk1_proc(void);
void  tsk2_proc(void);
void  tsk3_proc(void);
void  tsk4_proc(void);
void  tsk5_proc(void);
void  tsk6_proc(void);
void  tsk7_proc(void);
void  tsk8_proc(void);

/*------*/
/* main */
/*------*/
int main(void)
{
  TCBP pcur_tsk ;
  /* disable interrupt */
  DI ;
  /* initialize */
  init_usr();
  /* initialize monitor */
  init_os();
  /* enable interrupt */
  EI ;
  /* opening message */
  rs1_puts("Hello");
  rs1_crlf();
  /* endless loop */
  run_tsk = TSK_ID0 ;
  while ( ON ) {
    /* RTOS */
    pcur_tsk = tcb[run_tsk] ;
    if ( is_tsk_ready( run_tsk ) ) { (*(pcur_tsk.tsk))(); }
    run_tsk++;
    if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; }
    /* 10ms handling */
    if ( WFLAG == ON ) {
      WFLAG = OFF ;
      timer_handler();
    }
  }
  return 0 ;
}

/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void init_usr(void)
{
  /* PORT 4 */
  P4DR  = 0x00 ;
  P4DDR = MASKFF ; /* all outputs */
  /* PORT 6 */
  P6DR  = 0x00 ;
  P6DDR = 0x00 ; /* all inputs */
  /* PORT A */
  PADR  = 0      ;
  PADDR = MASKFF ; /* all outputs */
  /* PORT B */
  PBDR  = 0xc0 ;
  PBDDR = 0xcf ; /* PB5,PB4 are inputs , others are outputs */
  /* initialize */
  init_timer1();
  /* clear flags */
  xflags.DR = 0 ;
  /* initialize PWM */
  {
    ITU.TSTR.BIT.STR3 = (UBYTE)0x00; /* Stop the counter */
    ITU.TOER.BYTE     = (UBYTE)0x00;
    ITU3.TCR.BYTE     = (UBYTE)0xa0;
    ITU3.TCNT         = (UWORD)0x00;
    ITU.TFCR.BYTE     = (UBYTE)0xf6;
    ITU3.GRA          = (UWORD)3000;
    ITU4.GRA          = (UWORD)GEAR0;
    ITU3.GRB          = (UWORD)GEAR0;
  }
  /* start PWM */
  {
    ITU.TOER.BYTE     = (UBYTE)0xff;
    ITU.TSTR.BIT.STR3 = (UBYTE)0x01;
    ITU3.BRB          = (UWORD)GEAR10;
    ITU4.BRA          = (UWORD)GEAR10;
  }
  /* clear SCI buffer */
  *(sbuf+0) = 0 ;
  sindex = 0 ;
  /* initialize */
  timcnt = 0 ;
  xcnt3 = 0 ;
  xcnt5 = 0 ;
  xcnt6 = 0 ;
  /* SCI */
  init_sci_1(br9600);
  /* others */
  init_table();
  left   = 0 ;
  right  = 0 ;
  state = IDLE ;
  mstate = 0 ;
  sloap = 0 ;
  sloapf = 0 ;
  sloapr = 0 ;
  *(sloapt+0) = 100 ;
  *(sloapt+1) = 120 ;
  *(sloapt+2) =  80 ;
}

void init_timer1(void)
{
  /* stop timer */
  ITU.TSTR.BIT.STR1 = OFF ;
  /* TOER : Timer Output Enable Register
        7 **** -> 0
        6 **** -> 0
        5 EXB4 -> 0
        4 EXA4 -> 0
        3 EB3  -> 0
        2 EB4  -> 0
        1 EA4  -> 0
        0 EA3  -> 0
  */
  ITU.TOER.BYTE = 0 ;
  /* TIOR : Timer I/O Control Register
        7 **** -> 0
        6 IOB2 -> 0 GRB is not output compare match register
        5 IOB1 -> 0
        4 IOB0 -> 0
        3 **** -> 0
        2 IOA2 -> 0 GRA is not output compare match register
        1 IOA1 -> 0
        0 IOA0 -> 0
  */
  ITU1.TIOR.BYTE = 0 ;
  /* TCR : Timer Control Register
        7 ****  -> 0
        6 CCLR1 -> 0 clear TCNT if GRA = TCNT
        5 CCLR0 -> 1
        4 CKEG1 -> 0 rising edge
        3 CKEG0 -> 0
        2 TPSC2 -> 0 φ利用
        1 TPSC1 -> 0
        0 TPSC0 -> 0
  */
  ITU1.TCR.BYTE = 0x20 ;
  /* TIER : Timer Interrupt Enable Register
        7 ****  -> 0
        6 ***   -> 0
        5 ***   -> 0
        4 ***   -> 0
        3 ***   -> 0
        2 OVIE  -> 0
        1 IMIEB -> 0
        0 IMIEA -> 1 select compare match interrupt
  */
  ITU1.TIER.BIT.IMIEA = ON ;
  /* reference */
  ITU1.GRA = ITU1_AREG ;
  ITU1.GRB = MASKFFFF ;
  /* counter */
  ITU1.TCNT = 0 ;
  /* start timer */
  ITU.TSTR.BIT.STR1 = ON ;
}

/*+++++++++++++++++++++++++++++++++++++*/
/* ITU1 interrupt with compare match A */
/*                     1ms interval */
/*+++++++++++++++++++++++++++++++++++++*/
void int_imia1(void)
{
  UBYTE dummy ;
  /* clear flag */
  dummy = ITU1.TSR.BIT.IMFA ;
  ITU1.TSR.BIT.IMFA = OFF ;
  /* increment */
  timcnt++ ;
  /* judge 10ms passed */
  if ( timcnt & 10 ) { WFLAG = ON ; }
  /* judge 1000ms passed */
  if ( (timcnt & 1023) == 100 ) {
    timeoutcnt++ ;
  }
}

/*+++++++++++++++++++++++++*/
/* SCI_1 receive interrupt */
/*+++++++++++++++++++++++++*/
void  init_sci_1(TBaudRate x)
{
  volatile UWORD i;
  /* SCR : Serial Control Register
    7 bit TIE  -> 0 Transmit Interrupt Enable(disable)
    6 bit RIE  -> 0 Receive  Interrupt Enable(disable)
    5 bit TE   -> 0 Transmit Enable(disable)
    4 bit RE   -> 0 Receive  Enable(disable)
    3 bit MPIE -> 0 Multi Processor Interrupt Enable(disable)
    2 bit TEIE -> 0 Transmit End Interrupt Enable(disable)
    1 bit CKE1 -> 0 Clock Source (Use Internal Baud Rate Generator)
    0 bit CKE0 -> 0 
  */
  SCI1.SCR.BYTE = 0 ;
  /* SMR : Serial Mode Register
    7 bit C/nA -> 0 Communication Mode(Asynchronous)
    6 bit CHR  -> 0 data Charactor (8 bits)
    5 bit PE   -> 0 Parity Enable(disable)
    4 bit O/nE -> 0 Parity Mode(even)
    3 bit STOP -> 0 Stop Bit(1 bit)
    2 bit MP   -> 0 Multi Processor(disable)
    1 bit CKS1 -> 0 Clock Source ( φ )
    0 bit CKS0 -> 0 
  */
  SCI1.SMR.BYTE = 0 ;
  /* data transfer speed */
  SCI1.BRR = x ;
  /* wait 1 frame */
  for (i = 0; i < 3000 ; i++) ;
  /* enable Transmmit and Receive with interrupt */
  SCI1.SCR.BYTE = 0x70 ;
}

/*+++++++++++++++++++++++++*/
/* SCI_1 receive interrupt */
/*+++++++++++++++++++++++++*/
void int_rxi1(void)
{
  volatile UBYTE ch,dummy ;
  /* clear flag */
  dummy = SCI1.SSR.BYTE ;
  SCI1.SSR.BIT.RDRF = OFF ;
  /* get a character */
  ch = SCI1.RDR ;
  /* store */
  *(sbuf+sindex) = ch ;
  sindex++ ;
  /* check */
  if ( ch == '\r' ) {
    *(sbuf+sindex) = 0 ;
    sindex = 0 ;
    UFLAG  = ON ;
  }
}

/*+++++++++++++++*/
/* SCI_1 putchar */
/*+++++++++++++++*/
void rs1_putchar(UBYTE x)
{
  /* wait data transfer */
  while ( SCI1.SSR.BIT.TDRE == OFF ) ;
  /* put */
  SCI1.TDR = x ;
  SCI1.SSR.BIT.TDRE = OFF ;
}

/*++++++++++++*/
/* SCI_1 puts */
/*++++++++++++*/
void rs1_puts(UBYTE *x)
{
  while ( *x ) {
    /* send 1 charactors */
    rs1_putchar(*x);
    x++ ;
  }
}

/*++++++++++++*/
/* SCI_1 crlf */
/*++++++++++++*/
void rs1_crlf(void)
{
  rs1_putchar('\r');
  rs1_putchar('\n');
}

/*++++++++++++++++++++*/
/* SCI_1 command help */
/*++++++++++++++++++++*/
void show_help(void)
{
  rs1_puts("? help")    ; rs1_crlf();
  rs1_puts("E enable")  ; rs1_crlf();
  rs1_puts("e disable") ; rs1_crlf();
}

void  init_table(void)
{
  /* NORMAL */
  *(normal_l+ALL_BLACK)   = 10 ; *(normal_r+ALL_BLACK)   = 10 ;
  *(normal_l+ALL_WHITE)   = 30 ; *(normal_r+ALL_WHITE)   = 30 ;
  *(normal_l+LEFT_WHITE)  = 30 ; *(normal_r+LEFT_WHITE)  = 30 ;
  *(normal_l+RIGHT_WHITE) = 30 ; *(normal_r+RIGHT_WHITE) = 30 ;
  *(normal_l+CENTER)      = 50 ; *(normal_r+CENTER)      = 50 ;
  *(normal_l+TINY_RIGHT)  = 50 ; *(normal_r+TINY_RIGHT)  = 55 ;
  *(normal_l+RIGHT)       = 50 ; *(normal_r+RIGHT)       = 60 ;
  *(normal_l+BIG_RIGHT)   = 50 ; *(normal_r+BIG_RIGHT)   = 70 ;
  *(normal_l+TINY_LEFT)   = 55 ; *(normal_r+TINY_LEFT)   = 50 ;
  *(normal_l+LEFT)        = 60 ; *(normal_r+LEFT)        = 50 ;
  *(normal_l+BIG_LEFT)    = 70 ; *(normal_r+BIG_LEFT)    = 50 ;
  *(normal_l+BOTH_WHITE)  = 20 ; *(normal_r+BOTH_WHITE)  = 20 ;
  *(normal_l+ILLEAGAL)    = 10 ; *(normal_r+ILLEAGAL)    = 10 ;
  /* CRANK */
  *(crank_l+ALL_BLACK)   = 10 ; *(crank_r+ALL_BLACK)   = 10 ;
  *(crank_l+ALL_WHITE)   = 25 ; *(crank_r+ALL_WHITE)   = 25 ;
  *(crank_l+LEFT_WHITE)  = 25 ; *(crank_r+LEFT_WHITE)  = 25 ;
  *(crank_l+RIGHT_WHITE) = 25 ; *(crank_r+RIGHT_WHITE) = 25 ;
  *(crank_l+CENTER)      = 30 ; *(crank_r+CENTER)      = 30 ;
  *(crank_l+TINY_RIGHT)  = 30 ; *(crank_r+TINY_RIGHT)  = 35 ;
  *(crank_l+RIGHT)       = 30 ; *(crank_r+RIGHT)       = 40 ;
  *(crank_l+BIG_RIGHT)   = 30 ; *(crank_r+BIG_RIGHT)   = 45 ;
  *(crank_l+TINY_LEFT)   = 35 ; *(crank_r+TINY_LEFT)   = 30 ;
  *(crank_l+LEFT)        = 40 ; *(crank_r+LEFT)        = 30 ;
  *(crank_l+BIG_LEFT)    = 45 ; *(crank_r+BIG_LEFT)    = 30 ;
  *(crank_l+BOTH_WHITE)  = 20 ; *(crank_r+BOTH_WHITE)  = 20 ;
  *(crank_l+ILLEAGAL)    = 10 ; *(crank_r+ILLEAGAL)    = 10 ;
  /* LANE */
  *(lane_l+ALL_BLACK)   = 10 ; *(lane_r+ALL_BLACK)   = 10 ;
  *(lane_l+ALL_WHITE)   = 25 ; *(lane_r+ALL_WHITE)   = 25 ;
  *(lane_l+LEFT_WHITE)  = 25 ; *(lane_r+LEFT_WHITE)  = 25 ;
  *(lane_l+RIGHT_WHITE) = 25 ; *(lane_r+RIGHT_WHITE) = 25 ;
  *(lane_l+CENTER)      = 30 ; *(lane_r+CENTER)      = 30 ;
  *(lane_l+TINY_RIGHT)  = 30 ; *(lane_r+TINY_RIGHT)  = 35 ;
  *(lane_l+RIGHT)       = 30 ; *(lane_r+RIGHT)       = 40 ;
  *(lane_l+BIG_RIGHT)   = 30 ; *(lane_r+BIG_RIGHT)   = 45 ;
  *(lane_l+TINY_LEFT)   = 35 ; *(lane_r+TINY_LEFT)   = 30 ;
  *(lane_l+LEFT)        = 40 ; *(lane_r+LEFT)        = 30 ;
  *(lane_l+BIG_LEFT)    = 45 ; *(lane_r+BIG_LEFT)    = 30 ;
  *(lane_l+BOTH_WHITE)  = 20 ; *(lane_r+BOTH_WHITE)  = 20 ;
  *(lane_l+ILLEAGAL)    = 10 ; *(lane_r+ILLEAGAL)    = 10 ;
}

UBYTE get_hex(UBYTE x)
{
  UBYTE result ;
  /* default */
  result = 0 ;
  /* convert */
  if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
  if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
  if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }

  return result ;
}

void delay_ms(UWORD x)
{
  ULONG target ;
  /* calculate last value */
  target = timcnt + x ;
  /* wait */
  while ( timcnt < target ) ;
}

void  binary_display(UBYTE x)
{
  UBYTE loop ;
  UBYTE bdat ;
  /* show */
  for ( loop = 0 ; loop < 8 ; loop++ ) {
    bdat = '0' ;
    if ( x & MASK80 ) { bdat++ ; }
    rs1_putchar( bdat );
    x <<= 1 ;
  }
}

UWORD conv_value(UBYTE x)
{
  UWORD result ;
  /* convert */
  switch ( x ) {
    case   5 : result =   GEAR5 ; break ;
    case  10 : result =  GEAR10 ; break ;
    case  15 : result =  GEAR15 ; break ;
    case  20 : result =  GEAR20 ; break ;
    case  25 : result =  GEAR25 ; break ;
    case  30 : result =  GEAR30 ; break ;
    case  35 : result =  GEAR35 ; break ;
    case  40 : result =  GEAR40 ; break ;
    case  45 : result =  GEAR45 ; break ;
    case  50 : result =  GEAR50 ; break ;
    case  55 : result =  GEAR55 ; break ;
    case  60 : result =  GEAR60 ; break ;
    case  65 : result =  GEAR65 ; break ;
    case  70 : result =  GEAR70 ; break ;
    case  75 : result =  GEAR75 ; break ;
    case  80 : result =  GEAR80 ; break ;
    case  85 : result =  GEAR85 ; break ;
    case  90 : result =  GEAR90 ; break ;
    case  95 : result =  GEAR95 ; break ;
    case 100 : result = GEAR100 ; break ;
    default  : result =   GEAR0 ; break ;
  }

  return result ;
}

void  send_dc(UBYTE lx,UBYTE rx)
{
  UWORD left ;
  UWORD right ;
  /* convert */
  left  = conv_value( lx );
  right = conv_value( rx );
  /* store */
  ITU3.BRB = (UWORD)left;
  ITU4.BRA = (UWORD)right;
}

UBYTE get_sensor(void)
{
  UBYTE result ;
  /* get information from PORT7 lower nibble */
  result = P7DR ;
  /* masking */
  result &= MASK0F ;

  return result ;
}

UBYTE get_start(void)
{
  return sgate;
}

void  show_state(UBYTE x)
{
  UBYTE result;
  /* generate code */
  result = (1 << x);
  /* impress */
  P4DR = result ^ MASKFF ;
}

UBYTE get_swx(void)
{
  UBYTE tmp ;
  /* get switch state */
  tmp = P6DR ^ MASKF0 ;
  /* shift */
  tmp >>= 4 ;

  return tmp ;
}

void  send_motor_power(UBYTE x)
{
  if ( x == ON ) { PBDR |=  (1 << EDC_BIT); }
  else           { PBDR &= ~(1 << EDC_BIT); }
}

/* system call */
void cre_tsk(UBYTE tid,void (*tsk)(void))
{
  tcb[tid].tsk = tsk;
  tcb[tid].wcount = 0;
}

void sta_tsk(UBYTE tid,UBYTE tst)
{
  UWORD xtmp ;
  xtmp = (1 << tid) ;
  if ( tst == TTS_READY   ) { ready   |= xtmp ; }
  if ( tst == TTS_SUSPEND ) { suspend |= xtmp ; }
  if ( tst == TTS_WAIT    ) { waitq   |= xtmp ; }
}

void rsm_tsk(UBYTE tid)
{
  UWORD tmp ;
  UWORD tmpx ;
  /* get bit pattern */
  tmp  = *(bpat+tid);
  tmpx = tmp ^ MASKFFFF ;
  /* bit operation */
  ready   |= tmp;
  suspend &= tmpx;
  waitq   &= tmpx;
}

void sus_tsk(UBYTE tid)
{
  UWORD tmp ;
  UWORD tmpx ;
  /* get bit pattern */
  tmp  = *(bpat+tid);
  tmpx = tmp ^ MASKFFFF ;
  /* bit operation */
  ready   &= tmpx;
  suspend |= tmp ;
  waitq   &= tmpx;
}

void slp_tsk(void)
{
  sus_tsk(run_tsk);
}

void wai_tsk(UWORD x)
{
  UWORD tmp ;
  UWORD tmpx ;
  /* get bit pattern */
  tmp  = *(bpat+run_tsk);
  tmpx = tmp ^ MASKFFFF ;
  /* bit operation */
  ready   &= tmpx;
  suspend &= tmpx;
  waitq   |= tmp ;
  /* update counter */
  tcb[run_tsk].wcount = x ;
}

void init_os(void)
{
  UBYTE i;
  /* initialize queue */
  ready   = 0;
  suspend = 0;
  waitq   = 0;
  /* initalize pattern */
  for ( i = 0 ; i < 16 ; i++ ) { *(bpat+i) = (1 << i) ; }
  /* create task */
  cre_tsk(TSK_ID0,tsk0_proc); cre_tsk(NORMAL ,tsk1_proc);
  cre_tsk(CRANK  ,tsk2_proc); cre_tsk(ROTATE ,tsk3_proc);
  cre_tsk(LANE   ,tsk4_proc); cre_tsk(CHANGE ,tsk5_proc);
  cre_tsk(BLIND  ,tsk6_proc); cre_tsk(TSK_ID7,tsk7_proc);
  cre_tsk(XDEBUG ,tsk8_proc);
  /* start task state */
  sta_tsk(TSK_ID0,TTS_READY)  ; sta_tsk(TSK_ID1,TTS_SUSPEND);
  sta_tsk(TSK_ID2,TTS_SUSPEND); sta_tsk(TSK_ID3,TTS_SUSPEND);
  sta_tsk(TSK_ID4,TTS_SUSPEND); sta_tsk(TSK_ID5,TTS_SUSPEND);
  sta_tsk(TSK_ID6,TTS_SUSPEND); sta_tsk(TSK_ID7,TTS_READY);
  sta_tsk(TSK_ID8,TTS_READY)  ;
}

void  timer_handler(void)
{
  UBYTE i ;

  for ( i = 0 ; i < TSK_ID_MAX ; i++ ) {
    /* judge WAIT state */
    if ( waitq & *(bpat+i) ) {
      tcb[i].wcount-- ;
      if ( tcb[i].wcount == 0 ) { rsm_tsk(i); }
    }
  }
}

UBYTE is_tsk_ready(UBYTE tid)
{
  return( ready & *(bpat+tid) ) ;
}

/* system control */
void tsk0_proc(void)
{
  /* debug run */
  mode = get_swx() ;
  if ( mode & 0x08 ) {
    /* set flag */
    MFLAG = ON ;
    /* get mode */
    mode &= 7 ;
    /* change state */
    state = RUN ;
    /* crank */
    if ( mode == 2 ) { rsm_tsk(CRANK); }
    /* rotate */
    if ( mode == 3 ) { rsm_tsk(ROTATE); }
    /* lane */
    if ( mode == 4 ) { rsm_tsk(LANE); }
    /* change */
    if ( mode == 5 ) { rsm_tsk(CHANGE); }
    /* blind */
    if ( mode == 6 ) {  rsm_tsk(BLIND); }
    /* enable motor power */
    send_motor_power(ON);
    /* timer trigger clear */
    timeoutcnt = 0 ;
    TFLAG = OFF ;
  }
  /* start trigger */
  if ( state == IDLE ) {
    if ( get_start() == OPENED ) {
      state = RUN ;
      rsm_tsk(NORMAL);
      /* enable motor power */
      send_motor_power(ON);
      /* timer trigger clear */
      timeoutcnt = 0 ;
      TFLAG = OFF ;
    }
  }
  /* timeout */
  if ( state == RUN ) {
    if ( TFLAG == ON ) {
      state = IDLE ;
      /* suspend move handling task */
      state = IDLE ;
      sus_tsk(NORMAL);
      sus_tsk(CRANK);
      sus_tsk(ROTATE);
      sus_tsk(LANE);
      sus_tsk(CHANGE);
      sus_tsk(BLIND);
      /* machine state */
      mstate = 0 ;
      /* disable motor power */
      send_motor_power(OFF);
    }
  }
  /* show state */
  show_state( mstate );
}

/* NORMAL */
void tsk1_proc(void)
{
  UBYTE xmul ;
  UBYTE flag ;
  UBYTE xsensor ;
  /* default */
  flag = OFF ;
  /* show state */
  mstate = 1 ;
  show_state( mstate );
  /* get sensor */
  xsensor = get_sensor();
  /* update motor duty ratio */
  left  = *(normal_l+xsensor);
  right = *(normal_r+xsensor);
  /* default */
  *(dir+0) = DIR_CENTER ;
  *(dir+1) = DIR_CENTER ;
  /* get sensor */
  if ( xsensor == CENTER ) {
    /* climb hill or down hill */
    if ( sloap ) {
      xmul = *(sloapt+sloap) ;
      left  = (UBYTE)( xmul * left * 1.0 / 100 );
      right = (UBYTE)( xmul * right * 1.0 / 100 );
    }
  }
  /* update */
  send_dc(left,right);
  /* judge */
  if ( xsensor == ALL_WHITE ) {
    rsm_tsk(CRANK);
    flag = ON ;
  }
  if ( xsensor == LEFT_WHITE ) {
    *(dir+0) = DIR_LEFT ;
    *(dir+1) = DIR_RIGHT ;
    rsm_tsk(LANE);
    flag = ON ;
  }
  if ( xsensor == RIGHT_WHITE ) {
    *(dir+0) = DIR_RIGHT ;
    *(dir+0) = DIR_LEFT ;
    rsm_tsk(LANE);
    flag = ON ;
  }
  /* cyclic */
  if ( flag == ON ) {
    flag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 10 );
  }
}

/* CRANK */
void tsk2_proc(void)
{
  UBYTE flag ;
  UBYTE xsensor ;
  /* default */
  flag = OFF ;
  /* show state */
  mstate = 2 ;
  show_state( mstate );
  /* get sensor */
  xsensor = get_sensor();
  /* update motor duty ratio */
  left  = *(crank_l+xsensor);
  right = *(crank_r+xsensor);
  /* update */
  send_dc(left,right);
  /* judge */
  if ( xsensor == LEFT_WHITE ) {
    *(dir+0) = DIR_LEFT ;
    *(dir+1) = DIR_RIGHT ;
  }
  if ( xsensor == RIGHT_WHITE ) {
    *(dir+0) = DIR_RIGHT ;
    *(dir+1) = DIR_LEFT ;
  }
  if ( xsensor == ALL_BLACK  ) {
    /* initialize sequence counter */
    xcnt3 = 0 ;
    /* update state */
    rsm_tsk(ROTATE);
    flag = ON ;
  }
  /* cyclic */
  if ( flag == ON ) {
    flag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 100 );
  }
}

/* ROTATE */
void tsk3_proc(void)
{
  UBYTE flag ;
  UBYTE xsensor ;
  /* default */
  flag = OFF ;
  /* show state */
  mstate = 3 ;
  show_state( mstate );
  /* get sensor */
  xsensor = get_sensor();
  /* sequence */
  switch ( xcnt3 ) {
    /* rotate */
    case 0 :
      xcnt3 = 1 ;
      left = 50 ; right = 10 ;
      if ( *(dir+0) == DIR_RIGHT ) {
        left = 10 ; right = 50 ;
      }
      break ;
    /* judge */
    case 1 :
      xcnt3 = 1 ;
      if ( xsensor == CENTER ) {
        left = 30 ; right = 30 ;
        xcnt3 = 2 ; 
      }
      break ;
    /* straight and move */
    case 2 :
      xcnt3 = 3 ;
      break ;
    /* exit */
    case 3 :
      rsm_tsk(NORMAL);
      flag = ON ;
      break ;
    /* others */
    default:
      break;
  }
  /* update */
  send_dc(left,right);
  /* cyclic */
  if ( flag == ON ) {
    xcnt3 = 0 ;
    flag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 100 );
  }
}

/* LANE */
void tsk4_proc(void)
{
  UBYTE flag ;
  UBYTE xsensor ;
  /* default */
  flag = OFF ;
  /* show state */
  mstate = 4 ;
  show_state( mstate );
  /* get sensor */
  xsensor = get_sensor();
  /* update motor duty ratio */
  left  = *(lane_l+xsensor) ;
  right = *(lane_r+xsensor) ;
  /* update */
  send_dc(left,right);
  /* judge */
  if ( xsensor == ALL_BLACK ) {
    /* initialize sequence counter */
    xcnt5 = 0 ;
    /* update state */
    rsm_tsk(CHANGE);
    flag = ON ;
  }
  if ( xsensor == LEFT_WHITE ) {
    *(dir+0) = DIR_LEFT  ;
    *(dir+1) = DIR_RIGHT ;
  }
  if ( xsensor == RIGHT_WHITE ) {
    *(dir+0) = DIR_RIGHT ;
    *(dir+1) = DIR_LEFT  ;
  }
  /* cyclic */
  if ( flag == ON ) {
    flag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 10 );
  }
}

/* CHANGE */
void tsk5_proc(void)
{
  UBYTE flag ;
  /* default */
  flag = OFF ;
  /* show state */
  mstate = 5 ;
  show_state( mstate );
  /* sequence */
  switch ( xcnt5 ) {
    /* rotate */
    case 0 :
      xcnt5 = 1 ;
      /* set rotate direction */
      left = 50 ; right = 30 ;
      if ( *(dir+0) == DIR_LEFT ) {
        left = 30 ; right = 50 ;
      }
      break ;
    /* straight */
    case 1 :
      xcnt5 = 2 ;
      left = 30 ; right = 30 ;
      break ;
    /* move */
    case 2 :
      xcnt5 = 3 ;
      break ;
    /* exit */
    case 3 :
      rsm_tsk(BLIND);
      flag = ON ;
      break ;
    /* others */
    default:
      break;
  }
  /* update */
  send_dc(left,right);
  /* cyclic */
  if ( flag == ON ) {
    flag = OFF ;
    xcnt5 = 0 ;
    xcnt6 = 0 ;
    slp_tsk();
  } else {
    wai_tsk( 10 );
  }
}

/* BLIND */
void tsk6_proc(void)
{
  UBYTE flag ;
  UBYTE xsensor ;
  /* default */
  flag = OFF ;
  /* show state */
  mstate = 6 ;
  show_state( mstate );
  /* get sensor */
  xsensor = get_sensor();
  /* sequence */
  switch ( xcnt6 ) {
    /* straight */
    case 0 :
      xcnt6 = 1 ;
      left = 30 ; right = 30 ;
      break ;
    /* judge and move */
    case 1 :
      xcnt6 = 1 ;
      if ( xsensor == CENTER     ) { xcnt6 = 2 ; }
      if ( xsensor == TINY_LEFT  ) { xcnt6 = 2 ; }
      if ( xsensor == TINY_RIGHT ) { xcnt6 = 2 ; }
      break ;
    /* rotate */
    case 2 :
      xcnt6 = 3 ;
      /* set rotate direction */
      left = 50 ; right = 30 ;
      if ( *(dir+1) == DIR_LEFT ) {
        left = 30 ; right = 50 ;
      }
      break ;
    /* move */
    case 3 :
      xcnt6 = 4 ;
      left = 30 ; right = 30 ;
      break ;
    /* exit */
    case 4 :
      rsm_tsk(NORMAL);
      flag = ON ;
      break ;
    /* others */
    default:
      break;
  }
  /* update */
  send_dc(left,right);
  /* cyclic */
  if ( flag == ON ) {
    flag = OFF ;
    xcnt6 = 0 ;
    slp_tsk();
  } else {
    wai_tsk( 10 );
  }
}

/* sensing */
void tsk7_proc(void)
{
  UBYTE stmp ;
  UBYTE xsensor ;
  /* get sensor data */
  xsensor = P7DR ;
  /* start gate */
  sgate = CLOSED ;
  if ( !(xsensor & (1 << SGATE_BIT)) ) { sgate = OPENED ; }
  /* sloap */
  sloapf <<= 1 ; sloapf &= MASK03 ;
  sloapr <<= 1 ; sloapr &= MASK03 ;
  if ( xsensor & 0x40 ) { sloapr |= ON ; }
  if ( xsensor & 0x80 ) { sloapf |= ON ; }
  sloap = 0 ;
  if ( sloapf == 3 ) { sloap |= 1 ; }
  if ( sloapr == 3 ) { sloap |= 2 ; }
  /* time out */
  if ( timeoutcnt > 119 ) { TFLAG = ON ; }
  /* wait 50ms */
  wai_tsk(5);
}

/* execute debug */
void tsk8_proc(void)
{
  if ( UFLAG == ON ) {
    /* clear */
    UFLAG = OFF ;
    /* new line */
    rs1_crlf();
    /* command interpreter */
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help() ; }
    /* enable DCDC conveter */
    if ( cmd == 'E' ) { send_motor_power(ON); }
    /* disable DCDC conveter */
    if ( cmd == 'e' ) { send_motor_power(OFF); }
  }
}


目次

inserted by FC2 system