目次

LPC1114Arduino化

 mugen2015までは、MCR_VCマシンを動かすため、一部にArduinoを
 利用していました。



 ATmega168、ATmega328を¥200、¥250で秋月電子から入手可能で
 北海道職業能力開発大校の非常勤講師をしていた頃に、学生実習の
 サポートで使ったので、様々なアプリケーションを作成しました。

 秋月電子の通販サイトで、IchigoJamが紹介されていました。
 このIchigoJamで使われているマイコンは、32ビットでは定番
 のARMでした。型番はLPC1114。

 IchigoJamに興味をもち、自作の互換基板を半田付けして
 使ってみました。



 128kバイトのEEPROMを載せると、Basicプログラムを100程度入れる
 ことができます。Basicでは動作が遅いのと、I/Oポート数が少ない
 と不満を持っていました。

 LPC1114を、Arduinoと同じように使えるという情報を
 掴んだので、どんなものかと調べてみました。

 「LPCXpresso IDE」を利用して、C/C++でファームウエアを開発する
 ところまではやっていました。さらに、IchigoJamのファームウエア
 をダウンロードするために、FlashMagicも使えます。
 これらに、eXodusinoを加えればよいとか。

 回路図を作成し、基板の半田付けをしました。
 回路図は、以下。



 作成した基板です。



 上の基板で、MCR_VCマシンの動作をエミュレートするため
 雛形になるスケッチをATmega168で作成。内容は、以下。

#include <MsTimer2.h>
#define OFF 0
#define ON  OFF+1

#define MD_IDLE 0
#define MD_RUN  MD_IDLE+1

#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 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 XNORMAL 1
#define XCRANK  2
#define XROTATE 3
#define XLANE   4
#define XCHANGE 5
#define XBLIND  6

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

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

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

TCBP tcbx[TSK_ID_MAX] ;
TCBP pcur_tsk ;

long timcnt ;

char sbuf[8] ;
char sindex ;
byte UFLAG ;
char cmd ;
byte EFLAG ;

word xready ;
word xsuspend ;
word xwaitq ;
byte run_tsk ;
byte WFLAG ;
byte dcnt ;

byte state ;
byte xdir[2] ;
byte xcnt1 ;
byte xcnt2 ;
byte xcnt3 ;
byte xcnt4 ;
byte xcnt5 ;
byte xcnt6 ;

byte road[96];

void serialEvent();

void rs_putchar(char x)
{
  Serial.write(x);
}

void rs_puts(char *x)
{
  while ( *x != '\0' ) {
    rs_putchar( *x ) ;
    x++ ;
  }
}

void crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void show_help()
{
  rs_puts("? help");    crlf();
  rs_puts("E enable");  crlf();
  rs_puts("e disable"); crlf();
}

void show_info(byte x)
{
  switch ( x ) {
    case ALL_BLACK   : rs_puts("ALL_BLACK")  ; break ;
    case ALL_WHITE   : rs_puts("ALL_WHITE")  ; break ;
    case LEFT_WHITE  : rs_puts("LEFT_WHITE") ; break ;
    case RIGHT_WHITE : rs_puts("RIGHT_WHITE"); break ;
    case CENTER      : rs_puts("CENTER")     ; break ;
    case TINY_RIGHT  : rs_puts("TINY_RIGHT") ; break ;
    case RIGHT       : rs_puts("RIGHT")      ; break ;
    case BIG_RIGHT   : rs_puts("BIG_RIGHT")  ; break ;
    case TINY_LEFT   : rs_puts("TINY_LEFT")  ; break ;
    case LEFT        : rs_puts("LEFT")       ; break ;
    case BIG_LEFT    : rs_puts("BIG_LEFT")   ; break ;
    case BOTH_WHITE  : rs_puts("BOTH_WHITE") ; break ;
    default          : rs_puts("ILLEAGAL")   ; break ;
  }
}

void  init_road()
{
  byte i ;
  /* clear */
  for ( i = 0 ; i < 96 ; i++ ) {
    *(road+i) = CENTER ;
  }
  /* NORMAL */
  *(road+ 0) = CENTER      ; *(road+ 1) = TINY_RIGHT ;
  *(road+ 2) = CENTER      ; *(road+ 3) = TINY_LEFT  ;
  *(road+ 4) = ALL_WHITE   ; *(road+ 5) = CENTER     ;
  *(road+ 6) = CENTER      ; *(road+ 7) = LEFT_WHITE ;
  *(road+ 8) = CENTER      ; *(road+ 9) = CENTER     ;
  *(road+10) = RIGHT_WHITE ; *(road+11) = CENTER     ;
  *(road+12) = TINY_LEFT   ; *(road+13) = CENTER     ;
  *(road+14) = TINY_RIGHT  ; *(road+15) = CENTER     ;
  /* CRANK */
  *(road+ 0+16) = CENTER    ; *(road+ 1+16) = LEFT_WHITE  ;
  *(road+ 2+16) = TINY_LEFT ; *(road+ 3+16) = TINY_RIGHT  ;
  *(road+ 4+16) = CENTER    ; *(road+ 5+16) = ALL_BLACK   ;
  *(road+ 6+16) = CENTER    ; *(road+ 7+16) = ILLEAGAL    ;
  *(road+ 8+16) = CENTER    ; *(road+ 9+16) = RIGHT_WHITE ;
  *(road+10+16) = TINY_LEFT ; *(road+11+16) = TINY_RIGHT  ;
  *(road+12+16) = CENTER    ; *(road+13+16) = ALL_BLACK   ;
  *(road+14+16) = CENTER    ; *(road+15+16) = ILLEAGAL    ;
  /* ROTATE */
  *(road+ 0+32) = ALL_BLACK ; *(road+ 1+32) = ALL_BLACK ;
  *(road+ 2+32) = BIG_LEFT  ; *(road+ 3+32) = BIG_LEFT  ;
  *(road+ 4+32) = LEFT      ; *(road+ 5+32) = TINY_LEFT ;
  *(road+ 6+32) = CENTER    ; *(road+ 7+32) = TINY_RIGHT;
  *(road+ 8+32) = ILLEAGAL  ; *(road+ 9+32) = ILLEAGAL  ;
  *(road+10+32) = ILLEAGAL  ; *(road+11+32) = ILLEAGAL  ;
  *(road+12+32) = ILLEAGAL  ; *(road+13+32) = ILLEAGAL  ;
  *(road+14+32) = ILLEAGAL  ; *(road+15+32) = ILLEAGAL  ;
  /* LANE */
  *(road+ 0+48) = CENTER   ; *(road+ 1+48) = TINY_LEFT  ;
  *(road+ 2+48) = CENTER   ; *(road+ 3+48) = TINY_RIGHT ;
  *(road+ 4+48) = CENTER   ; *(road+ 5+48) = ALL_BLACK  ;
  *(road+ 6+48) = ILLEAGAL ; *(road+ 7+48) = ILLEAGAL   ;
  *(road+ 8+48) = ILLEAGAL ; *(road+ 9+48) = ILLEAGAL   ;
  *(road+10+48) = ILLEAGAL ; *(road+11+48) = ILLEAGAL   ;
  *(road+12+48) = ILLEAGAL ; *(road+13+48) = ILLEAGAL   ;
  *(road+14+48) = ILLEAGAL ; *(road+15+48) = ILLEAGAL   ;
  /* CHANGE */
  *(road+ 0+64) = ALL_BLACK ; *(road+ 1+64) = ALL_BLACK ;
  *(road+ 2+64) = ALL_BLACK ; *(road+ 3+64) = ALL_BLACK ;
  *(road+ 4+64) = BIG_LEFT  ; *(road+ 5+64) = LEFT      ;
  *(road+ 6+64) = TINY_LEFT ; *(road+ 7+64) = CENTER    ;
  /* BLIND */
  *(road+ 0+80) = ALL_BLACK ; *(road+ 1+80) = ALL_BLACK ;
  *(road+ 2+80) = ALL_BLACK ; *(road+ 3+80) = ALL_BLACK ;
  *(road+ 4+80) = BIG_LEFT  ; *(road+ 5+80) = LEFT      ;
  *(road+ 6+80) = TINY_LEFT ; *(road+ 7+80) = CENTER    ;
}

void  cre_tsk(byte tid,void (*tsk)(void))
{
  tcbx[tid].tsk    = tsk;
  tcbx[tid].wcount = 0;
}

void sta_tsk(byte tid,byte sta)
{
  word tmp ;
  tmp = (1 << tid);
  if ( sta == TTS_READY   ) { xready   |= tmp; }
  if ( sta == TTS_SUSPEND ) { xsuspend |= tmp; }
  if ( sta == TTS_WAIT    ) { xwaitq   |= tmp; }
}

void rsm_tsk(byte tid)
{
  word tmp ;
  tmp = (1 << tid);
  xready   |=  tmp;
  xsuspend &= ~tmp;
  xwaitq   &= ~tmp;
}

void sus_tsk(byte tid)
{
  word tmp ;
  tmp = (1 << tid);
  xready   &= ~tmp;
  xsuspend |=  tmp;
  xwaitq   &= ~tmp;
}

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

void wai_tsk(word x)
{
  word tmp ;
  tmp = (1 << run_tsk);
  xready   &= ~tmp;
  xsuspend &= ~tmp;
  xwaitq   |=  tmp;
  tcbx[run_tsk].wcount = x ;
}

byte is_tsk_ready(byte tid)
{
  return( (xready >> tid) & ON ) ;
}

void init_os()
{
  /* clear flag */
  WFLAG = OFF ; 
  /* create */
  cre_tsk(TSK_ID0,tsk0_proc);
  cre_tsk(TSK_ID1,tsk1_proc);
  cre_tsk(TSK_ID2,tsk2_proc);
  cre_tsk(TSK_ID3,tsk3_proc);
  cre_tsk(TSK_ID4,tsk4_proc);
  cre_tsk(TSK_ID5,tsk5_proc);
  cre_tsk(TSK_ID6,tsk6_proc);
  cre_tsk(TSK_ID7,tsk7_proc);
  cre_tsk(TSK_ID8,tsk8_proc);
  /* initialize 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);
  /* clear counter */
  xcnt1 = 0 ;
}

void timer_handler()
{
  byte i ;
  word xtmp ;
  for ( i = 0 ; i < TSK_ID_MAX ; i++ ) {
    /* judge */
    if ( xwaitq & (1 << i) ) {
      xtmp = tcbx[i].wcount ;
      xtmp-- ;
      tcbx[i].wcount = xtmp ;
      if ( xtmp == 0 ) { rsm_tsk(i); }
    }
  }
}

byte get_sensor(byte xid,byte xc)
{
  byte result ;
  byte xptr ;
  /* default */
  result = 0 ;
  /* check ID */
  if ( xid > TSK_ID6 ) { result = 0 ; }
  else {
    /* calculate address */
    xptr = ((xid-1) << 4) | xc ;
    /* get data */
    result = *(road+xptr);
  }  

  return result ;
}

void tsk0_proc()
{
  /* judge */
  if ( EFLAG == ON ) {
    /* IDLE -> RUN */
    if ( state == MD_IDLE ) {
      xcnt1 = 0 ;
      state = MD_RUN ;
      rsm_tsk( XNORMAL ) ;
      rs_puts("-> NORMAL");
      crlf();
    }
  }
  if ( EFLAG == OFF ) {
    /* RUN -> IDLE */
    if ( state == MD_RUN ) {
      state = MD_IDLE ;
      rs_puts(" suspend all task");
      crlf(); 
      sus_tsk( TSK_ID1 ) ;
      sus_tsk( TSK_ID2 ) ;
      sus_tsk( TSK_ID3 ) ;
      sus_tsk( TSK_ID4 ) ;
      sus_tsk( TSK_ID5 ) ;
      sus_tsk( TSK_ID6 ) ;
    }
  }
}

void tsk1_proc()
{
  byte xx ;
  byte eflag ;
  /* */
  eflag = OFF ;
  show_hex( xcnt1 );
  /* get code */
  xx = get_sensor(XNORMAL,xcnt1);
  rs_putchar('\t');
  show_info( xx );
  rs_putchar('\t');
  /* judge */
  if ( xx == ALL_WHITE ) {
    xcnt2 = 0 ;
    /* TSK_ID2(CRANK) */
    rsm_tsk( XCRANK ) ;
    eflag = ON ;
  }
  if ( xx == LEFT_WHITE || xx == RIGHT_WHITE ) {
    /* set directions */
    if ( xx == LEFT_WHITE ) {
      *(xdir+0) = DIR_LEFT ;
      *(xdir+1) = DIR_RIGHT ;
    }
    if ( xx == RIGHT_WHITE ) {
      *(xdir+0) = DIR_RIGHT ;
      *(xdir+1) = DIR_LEFT ;
    }    
    /* TSK_ID4(LANE) */
    xcnt4 = 0 ;
    rsm_tsk( XLANE ) ;
    eflag = ON ;
  }
  /* DEBUG */
  crlf();
  xcnt1++;
  if ( xcnt1 == 16 ) { xcnt1 = 0 ; } 
  /* delay 100ms */
  if ( eflag == ON ) {
    eflag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 15 );
  }
}

void tsk2_proc()
{
  byte xx ;
  byte eflag ;
  /* */
  eflag = OFF ;
  rs_putchar('\t'); 
  show_hex( xcnt2 );
  /* get code */
  xx = get_sensor(XCRANK,xcnt2);
  rs_putchar('\t'); 
  show_info( xx );
  rs_putchar('\t');
  /* DEBUG */
  if ( xcnt2 == 0 ) {
    crlf(); 
    rs_puts("+ CRANK +");
    crlf();
  }
  /* judge */
  if ( xx == ALL_BLACK ) {
    xcnt3 = 0 ;
    /* */
    rs_puts("DIR:");
    if ( *(xdir+0) == DIR_LEFT  ) { rs_putchar('L'); }
    if ( *(xdir+0) == DIR_RIGHT ) { rs_putchar('R'); }
    rs_puts("\t>>ROTATE");
    crlf();
    /* TSK_ID3(ROTATE) */
    rsm_tsk( XROTATE ) ;
    eflag = ON ;
  }
  if ( xx == LEFT_WHITE || xx == RIGHT_WHITE ) {
    /* set directions */
    if ( xx == LEFT_WHITE ) {
      *(xdir+0) = DIR_LEFT ;
      *(xdir+1) = DIR_RIGHT ;
    }
    if ( xx == RIGHT_WHITE ) {
      *(xdir+0) = DIR_RIGHT ;
      *(xdir+1) = DIR_LEFT ;
    }    
  }
  /* DEBUG */
  crlf();
  xcnt2++;
  if ( xcnt2 == 16 ) { xcnt2 = 0 ; }
  /* delay 100ms */
  if ( eflag == ON ) {
    eflag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 100 );
  }
}

void tsk3_proc()
{
  byte xx ;
  byte eflag ;
  /* */
  eflag = OFF ;
  rs_puts("\t\t");
  show_hex( xcnt3 );
  /* get code */
  xx = get_sensor(XROTATE,xcnt3);
  rs_putchar('\t');
  show_info( xx );
  rs_putchar('\t');
  /* DEBUG */
  if ( xcnt3 == 0 ) {
    crlf();
    rs_puts("+ ROTATE + ");
    crlf();
  }
  /* judge */
  if ( xx == CENTER ) {
    *(xdir+0) = DIR_CENTER ;
    *(xdir+1) = DIR_CENTER ;
    rs_puts("\t>>NORMAL");
    crlf();
    /* TSK_ID1(NORMAL) */
    rsm_tsk( XNORMAL ) ;
    eflag = ON ;
  }
  /* DEBUG */
  crlf();
  xcnt3++;
  if ( xcnt3 == 16 ) { xcnt3 = 0 ; }
  /* delay 1000ms */
  if ( eflag == ON ) {
    eflag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 100 );
  }
}

void tsk4_proc()
{
  byte xx ;
  byte eflag ;
  /* */
  eflag = OFF ;
  rs_putchar('\t');
  show_hex( xcnt4 );
  /* get code */
  xx = get_sensor(XLANE,xcnt4);
  rs_putchar('\t'); 
  show_info( xx );
  rs_putchar('\t');
  /* DEBUG */
  if ( xcnt4 == 0 ) {
    crlf(); 
    rs_puts("+ LANE +");
    crlf();
  }
  /* judge */
  if ( xx == ALL_BLACK ) {
    xcnt5 = 0 ;
    /* message */
    rs_puts("\t>>CHANGE");
    crlf();
    /* TSK_ID5(CHANGE) */
    rsm_tsk( XCHANGE ) ;
    eflag = ON ;
  }
  /* DEBUG */
  crlf();
  xcnt4++;
  if ( xcnt4 == 16 ) { xcnt4 = 0 ; }
  /* delay 1000ms */
  if ( eflag == ON ) {
    eflag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 100 );
  }
}

void tsk5_proc()
{
  byte xx ;
  byte eflag ;
  /* */
  eflag = OFF ;
  rs_puts("\t\t");
  show_hex( xcnt5 );
  /* get code */
  xx = get_sensor(XCHANGE,xcnt5);
  rs_putchar('\t'); 
  show_info( xx );
  rs_putchar('\t');
  /* DEBUG */
  if ( xcnt5 == 0 ) {
    crlf(); 
    rs_puts("+ CHANGE +");
    rs_puts("\tDir:");
    if ( *(xdir+0) == DIR_LEFT  ) { rs_putchar('L'); }
    if ( *(xdir+0) == DIR_RIGHT ) { rs_putchar('R'); }
    crlf();
  }  
  /* judge */
  if ( xcnt5 == 8 ) {
    xcnt6 = 0 ;
    /* message */
    rs_puts("\t>>BLIND");
    crlf();
    /* TSK_ID5(BLIND) */
    rsm_tsk( XBLIND ) ;
    eflag = ON ;
  }
  /* DEBUG */
  crlf();
  xcnt5++;
  if ( xcnt5 == 16 ) { xcnt5 = 0 ; }
  /* delay 1000ms */
  if ( eflag == ON ) {
    eflag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 100 );
  }
}

void tsk6_proc()
{
  byte xx ;
  byte eflag ;
  /* */
  eflag = OFF ;
  rs_puts("\t\t\t");
  show_hex( xcnt6 );
  /* get code */
  xx = get_sensor(XBLIND,xcnt6);
  rs_putchar('\t'); 
  show_info( xx );
  rs_putchar('\t');
  /* DEBUG */
  if ( xcnt6 == 0 ) {
    crlf(); 
    rs_puts("+ BLIND +");
    rs_puts("\tDir:");
    if ( *(xdir+1) == DIR_LEFT  ) { rs_putchar('L'); }
    if ( *(xdir+1) == DIR_RIGHT ) { rs_putchar('R'); }
    crlf();
  }
  /* judge */
  if ( xx == CENTER ) {
    /* message */
    rs_puts("\t>>NORMAL");
    crlf();
    /* TSK_ID1(NORMAL) */
    rsm_tsk( XNORMAL ) ;
    eflag = ON ;
  }
  /* DEBUG */
  crlf();
  xcnt6++;
  if ( xcnt6 == 16 ) { xcnt6 = 0 ; }
  /* delay 1000ms */
  if ( eflag == ON ) {
    eflag = OFF ;
    slp_tsk();
  } else {
    wai_tsk( 100 );
  }
}

void tsk7_proc(void)
{
  /* command intepreter */
  if ( UFLAG == ON ) {
    /* clear flag */
    UFLAG = OFF ;
    /* new line */
    crlf() ;
    /* get command */
    cmd = sbuf[0] ;
    /* help */
    if ( cmd == '?' ) { show_help() ; }
    /* enable */
    if ( cmd == 'E' ) { EFLAG = ON ; }
    /* disable */
    if ( cmd == 'e' ) { EFLAG = OFF; }
  }
}

void tsk8_proc(void)
{
  /* impress */
  if ( dcnt & ON ) { PORTB |=  (1 << 5); }
  else             { PORTB &= ~(1 << 5); }
  /* increment */
  dcnt++ ;
  /* delay 500ms */
  wai_tsk( 50 );
}

void update_trigger()
{
  WFLAG = ON ;
}

char get_hex(byte x)
{
  char result ;
  /* default */
  result = '0' ;
  /* convert */
  if ( x < 10 ) { result = x + '0' ; }
  if ( x > 9 ) { result = x - 10 + 'A' ; }

  return result ;
}

void  show_hex(byte x)
{
  byte dh ;
  byte dl ;
  /* separate */
  dh = (x >> 4) & 15 ;
  dl = x & 15 ;
  /* */
  rs_putchar( get_hex( dh ) ) ;
  rs_putchar( get_hex( dl ) ) ;
}

void  binary_display(byte x)
{
  int i ;
  for ( i = 7 ; i > -1 ; i-- ) {
    rs_putchar('0'+((x >> i) & ON));
  }
}

/* initialize */
void setup()
{
  /* initialize serial port */
  Serial.begin(9600);
  sindex = 0 ;
  /* */
  PORTB = 0xff ;
  PORTC = 0xff ;
  /* data direction */
  DDRB = 0xff ;
  DDRC = 0x00 ;
  /* initialize variables */
  sindex = 0 ;
  UFLAG = OFF ;
  dcnt = 0 ;
  xcnt1 = 0 ;
  timcnt = 0 ;
  /* initialize USO */
  init_os();
  run_tsk = TSK_ID0 ;
  state = MD_IDLE ;
  /* initialize table */
  init_road();
  /* trigger period */
  MsTimer2::set(10,update_trigger);
  /* enable */ 
  MsTimer2::start();
  /* direction */
  *(xdir+0) = DIR_CENTER ;
  *(xdir+1) = DIR_CENTER ;
  /* */
  crlf();
  show_help();
}

/* main */
void loop()
{
  /* RTOS handling */
  {
    /* 10ms has passed */
    if ( WFLAG == ON ) {
      /* clear flag */
      WFLAG = OFF ;
      /* call */
      timer_handler();
    }
    /* round robbin */
    pcur_tsk = tcbx[run_tsk] ;
    if ( is_tsk_ready( run_tsk ) != OFF ) { (*(pcur_tsk.tsk))(); }
    run_tsk++;
    if ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; }
  }
}

/* receive interrupt */
void serialEvent()
{
  char ch;

  if ( Serial.available() > 0 ) {
    /* get 1 character */
    ch = Serial.read();
    /* store */
    *(sbuf+sindex) = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      UFLAG = ON ;
    }
  }
}

 LPC1114のハードウエアに合わせる前に、メモリ上にセンサー
 情報を定義し、それを参照してタスクを動かします。

 マシンを制御するタスクが、センサー情報により切り替わり
 必要な処理を実行しているのかを調べることに特化してます。

 端末接続すると、以下のコマンドが使えると表示。



 コマンド'E'で、センサー情報を取得して、タスクを切り替える
 ことをエミュレートしていき、コマンド'e'で終了。



 センサー情報は、タスクのIDとカウンタ値から計算できるように
 専用関数を定義。

byte get_sensor(byte xid,byte xc)
{
  byte result ;
  byte xptr ;
  /* default */
  result = 0 ;
  /* check ID */
  if ( xid > TSK_ID6 ) { result = 0 ; }
  else {
    /* calculate address */
    xptr = ((xid-1) << 4) | xc ;
    /* get data */
    result = *(road+xptr);
  }  

  return result ;
}

 タスクのIDは4ビットで表現できるので、タスクが専用で使える
 カウンタを用意し、そのカウンタの値を配列の添字に利用。

 カウンタは4ビットとしていますが、利用できるメモリ容量が
 増えれば8ビットにして、より実際のコースに近い情報を定義
 できます。

 センサー情報を格納した配列の定義は、ひとつの関数で処理。
 添字とセンサー情報値を対応表を作成できます。

void  init_road()
{
  byte i ;
  /* clear */
  for ( i = 0 ; i < 96 ; i++ ) {
    *(road+i) = CENTER ;
  }
  /* NORMAL */
  *(road+ 0) = CENTER      ; *(road+ 1) = TINY_RIGHT ;
  *(road+ 2) = CENTER      ; *(road+ 3) = TINY_LEFT  ;
  *(road+ 4) = ALL_WHITE   ; *(road+ 5) = CENTER     ;
  *(road+ 6) = CENTER      ; *(road+ 7) = LEFT_WHITE ;
  *(road+ 8) = CENTER      ; *(road+ 9) = CENTER     ;
  *(road+10) = RIGHT_WHITE ; *(road+11) = CENTER     ;
  *(road+12) = TINY_LEFT   ; *(road+13) = CENTER     ;
  *(road+14) = TINY_RIGHT  ; *(road+15) = CENTER     ;
  /* CRANK */
  *(road+ 0+16) = CENTER    ; *(road+ 1+16) = LEFT_WHITE  ;
  *(road+ 2+16) = TINY_LEFT ; *(road+ 3+16) = TINY_RIGHT  ;
  *(road+ 4+16) = CENTER    ; *(road+ 5+16) = ALL_BLACK   ;
  *(road+ 6+16) = CENTER    ; *(road+ 7+16) = ILLEAGAL    ;
  *(road+ 8+16) = CENTER    ; *(road+ 9+16) = RIGHT_WHITE ;
  *(road+10+16) = TINY_LEFT ; *(road+11+16) = TINY_RIGHT  ;
  *(road+12+16) = CENTER    ; *(road+13+16) = ALL_BLACK   ;
  *(road+14+16) = CENTER    ; *(road+15+16) = ILLEAGAL    ;
  /* ROTATE */
  *(road+ 0+32) = ALL_BLACK ; *(road+ 1+32) = ALL_BLACK ;
  *(road+ 2+32) = BIG_LEFT  ; *(road+ 3+32) = BIG_LEFT  ;
  *(road+ 4+32) = LEFT      ; *(road+ 5+32) = TINY_LEFT ;
  *(road+ 6+32) = CENTER    ; *(road+ 7+32) = TINY_RIGHT;
  *(road+ 8+32) = ILLEAGAL  ; *(road+ 9+32) = ILLEAGAL  ;
  *(road+10+32) = ILLEAGAL  ; *(road+11+32) = ILLEAGAL  ;
  *(road+12+32) = ILLEAGAL  ; *(road+13+32) = ILLEAGAL  ;
  *(road+14+32) = ILLEAGAL  ; *(road+15+32) = ILLEAGAL  ;
  /* LANE */
  *(road+ 0+48) = CENTER   ; *(road+ 1+48) = TINY_LEFT  ;
  *(road+ 2+48) = CENTER   ; *(road+ 3+48) = TINY_RIGHT ;
  *(road+ 4+48) = CENTER   ; *(road+ 5+48) = ALL_BLACK  ;
  *(road+ 6+48) = ILLEAGAL ; *(road+ 7+48) = ILLEAGAL   ;
  *(road+ 8+48) = ILLEAGAL ; *(road+ 9+48) = ILLEAGAL   ;
  *(road+10+48) = ILLEAGAL ; *(road+11+48) = ILLEAGAL   ;
  *(road+12+48) = ILLEAGAL ; *(road+13+48) = ILLEAGAL   ;
  *(road+14+48) = ILLEAGAL ; *(road+15+48) = ILLEAGAL   ;
  /* CHANGE */
  *(road+ 0+64) = ALL_BLACK ; *(road+ 1+64) = ALL_BLACK ;
  *(road+ 2+64) = ALL_BLACK ; *(road+ 3+64) = ALL_BLACK ;
  *(road+ 4+64) = BIG_LEFT  ; *(road+ 5+64) = LEFT      ;
  *(road+ 6+64) = TINY_LEFT ; *(road+ 7+64) = CENTER    ;
  /* BLIND */
  *(road+ 0+80) = ALL_BLACK ; *(road+ 1+80) = ALL_BLACK ;
  *(road+ 2+80) = ALL_BLACK ; *(road+ 3+80) = ALL_BLACK ;
  *(road+ 4+80) = BIG_LEFT  ; *(road+ 5+80) = LEFT      ;
  *(road+ 6+80) = TINY_LEFT ; *(road+ 7+80) = CENTER    ;
}

 ATmega168を利用したArduinoでは、SRAMが2kバイトなので
 センサー情報定義に96バイトを使うと、容量を圧迫しますが
 LPC1114では、SRAMが4kバイトあるので、気にすることなく
 センサー情報定義の容量を増やせます。

 センサー情報を、スケッチ作成時のたびに格納するのは
 面倒なので、EEPROMに入れておき、パワーオンで入力と
 しておきます。

 利用したEEPROMは、IICバス対応のもの。



 ArduinoでSDカード中のテキストファイルからEEPROMに転送します。



 手持ちのSDカードシールドは、Arduino対応なので
 直接接続できるのかも知れませんが、時間を有効
 に使うために、専用治具としておきます。



 実機でセンサーであるGame Boy Cameraユニットに接続する
 ピンは、以下。

 モータ制御は、ArduinoにPWM波形生成ピンがあるので
 writeAnalog関数を使います。

 ATmega168を利用した純正のArduinoで動作確認後
 LPC1114利用のArduino互換器にスケッチを転送し
 動作確認できました。

 writeAnalogのパラメータで、ピン番号が異なるだけ
 なので、マクロを定義して対応します。

/* ATmega168 */
#define LEFT_PWM_PIN  10
#define WRITE_PWM_PIN  9

/* LPC1114 */
#define LEFT_PWM_PIN  6
#define WRITE_PWM_PIN 3

 下位で利用できる関数ができたので、DCモータに与える
 DUTY比の計算ルーチンを挟んでから、writeAnalog関数
 でPWM波形を出力します。


目次

inserted by FC2 system