目次

ROMデコーダ代行

 センサーの情報から、動作モードを変更するROM
 デコーダを設計、開発していました。



 ROMに入れるHEXファイルの内容は、以下。

:1000000000000000000000000000000000000000F0
:1000100000000000000000000000000000000000E0
:1000200000010001000300020001000100010001C5
:1000300000010001000100010001000100010001B8
:100040000002000200020002000F00020002000293
:100050000002000200020002000200020002000290
:100060000003000300030003000F0003000300036C
:100070000003000300030003000300030003000368
:1001000000090008000800080008000800080008AE
:10011000000800080008000800080008000800089F
:100120000009000900090009000A00090009000986
:100130000009000900090009000900090009000977
:10014000000A000A000A000A000F000A000A000A5A
:10015000000A000A000A000A000A000A000A000A4F
:10018000000D000C000C000C000C000C000C000C0E
:10019000000C000C000C000C000C000C000C000CFF
:1001A000000D000D000D000D000E000D000D000DE6
:1001B000000D000D000D000D000D000D000D000DD7
:1001C000000E000E000E000E000F000E000E000EBE
:1001D000000E000E000E000E000E000E000E000EAF
:1001E000000F000F0008000C000F000F000F000FA1
:1001F000000F000F000F000F000F000F000F000F87
:00000001FF

 ROMデコーダは、次のステートを実現するために用意。



 ステートの遷移は、要約してみました。

 内部にステートを用意し、トリガーでNONEからNORMALに
 変化させ、NORMALからはセンサー値での変化をさせる。

 これらをPICのプログラムコードにすると、以下。

/* redefine data type */
typedef unsigned char UBYTE ;

#define OFF 0
#define ON  OFF+1

#define NONE             0
#define CRANK            1
#define RIGHT_ROTATE     2
#define LEFT_ROTATE      3
#define LANE_LEFT        8
#define LANE_LEFT_BLIND  9
#define LANE_LEFTX       10
#define LANE_RIGHT       12
#define LANE_RIGHT_BLIND 13
#define LANE_RIGHTX      14
#define NORMAL           15

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

#define QH   PORTB.F7
#define SCLK PORTB.F6
#define LOAD PORTB.F5
#define TRG  PORTB.F4

#define ITMR   6

volatile UBYTE uflag ;
volatile UBYTE tflag ;
volatile UBYTE sprev ;
volatile UBYTE scur ;
volatile UBYTE cmd ;
volatile UBYTE sbuf[8];
volatile UBYTE sindex ;
volatile UBYTE mode ;
volatile UBYTE tmp ;
volatile UBYTE trg_sft ;
volatile char msg[2] ;

/* function prototype */
void  init_usr(void);
void  rs_putchar(UBYTE x);
void  rs_puts(UBYTE *ptr);
void  crlf(void);
UBYTE get_hex(UBYTE x);
void  show_help(void);
char  get_asc(UBYTE x);
UBYTE get_sensor(void);
UBYTE get_mode(UBYTE x,UBYTE y);

/* interrupt handler */
void interrupt(void)
{
  char chx ;
  /* generate 1ms */
  if ( INTCON.TMR0IF == ON ) {
    /* clear flag */
    INTCON.TMR0IF = OFF ;
    /* 256 - 250 = 6 */
    TMR0 = ITMR ;
    /* set flag */
    tflag = ON ;
  }
  /* receive interrupt */
  if ( PIR1.RCIF == ON ) {
    /* clear flag */
    PIR1.RCIF = OFF ;
    /* get 1 charactor */
    chx = RCREG ;
    /* store */
    *(sbuf+sindex) = chx ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( chx == '\r' ) {
      sindex = 0 ;
      uflag  = ON ;
    }
  }
}

void main(void)
{
  /* initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* timer handler */
    if ( tflag == ON ) {
      /* clear flag */
      tflag = OFF ;
      /* trigger handling */
      trg_sft <<= 1 ;
      trg_sft &= 3 ;
      if ( TRG == ON ) { trg_sft |= ON ; }
      if ( trg_sft == ON && mode == NONE ) {
        mode = NORMAL ;
      }
      /* get sensor data */
      scur = get_sensor();
      /* judge */
      if ( sprev ^ scur ) {
        /* update */
        sprev = scur ;
        /* update mode */
        mode = get_mode(mode,sprev);
        /* impress */
        PORTA = mode ;
      }
    }
    /* receive handler */
    if ( uflag == ON ) {
      /* clear flag */
      uflag = OFF ;
      /* command interpreter */
      cmd = *(sbuf+0) ;
      /* help */
      if ( cmd == '?' ) { show_help(); }
      /* show mode */
      if ( cmd == 'E' ) {
        msg[0] = get_hex( sbuf[1] ) ;
        msg[1] = get_hex( sbuf[2] ) ;
        tmp = get_mode( msg[0] , msg[1] );
        rs_putchar( get_asc( tmp ) );
        crlf() ;
      }
    }
  }
}

/* define function body */
void init_usr(void)
{
  /* disable CCP */
  CCP1CON = 0x00 ;
  /* I/O state */
  PORTA = 0x00 ;
  PORTB = 0x20 ;
  /* I/O directions */
  TRISA = 0x38 ;
  TRISB = 0x6A ;
  /* initialize timer 0 */
  {
    /*
       5MHz (Fosc)
       Fosc/4 = 1.25MHz
       1.25MHz/2 = 625kHz prescaler = 1:2
    */
    OPTION_REG = 0x00 ;
    /* 256 - 250 = 6 */
    TMR0 = ITMR ;
    /* enable timer0 overflow interrupt */
    INTCON.TMR0IE = ON ;
  }
  /* initialize serial port */
  {
    TXSTA = (1 << BRGH) | (1 << TXEN) ;
    RCSTA = (1 << SPEN) | (1 << CREN) ;
    SPBRG = 7 ;
    PIE1.RCIE = ON ;
    sindex = 0 ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
  /* clear flags */
  tflag = OFF ;
  uflag = OFF ;
  /* initialize variables */
  sprev = 0 ;
  scur = sprev ;
  trg_sft = 0 ;
  mode = NONE ;
  /* opening message */
  rs_putchar('H');
  rs_putchar('i');
  rs_putchar('!');
  crlf();
}

void rs_putchar(UBYTE x)
{
  /* judge empty */
  while ( TXSTA.TRMT == OFF ) ;
  /* transmit */
  TXREG = x ;
}

void  rs_puts(UBYTE *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++ ;
  }
}

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

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  show_help(void)
{
  rs_puts("? help") ; crlf();
  rs_puts("E check"); crlf();
}

char  get_asc(UBYTE x)
{
  char result ;
  /* default */
  result = x + '0' ;
  /* judge */
  if ( x > 9 ) { result += 17 ; }

  return result  ;
}

UBYTE get_sensor(void)
{
  UBYTE result ;
  UBYTE i ;
  /* LOAD */
  LOAD = OFF ;
  LOAD = ON ;
  /* clear */
  result = 0 ;
  /* get data */
  for ( i = 0 ; i < 8 ; i++ ) {
    /* shift */
    result <<= 1 ;
    /* get 1 bit */
    if ( QH == ON ) { result |= ON ; }
    /* SCLK : H  */
    SCLK = ON ;
    /* SCLK : L  */
    SCLK = OFF ;
  }

  return result ;
}

UBYTE get_mode(UBYTE x,UBYTE y)
{
  UBYTE result ;
  /* default */
  result = x ;
  /* judge */
  if ( x == CRANK ) {
    if ( y == LEFT_WHITE ) { result = LEFT_ROTATE ; }
    if ( y == RIGHT_WHITE ) { result = RIGHT_ROTATE ; }
  }
  if ( x == RIGHT_ROTATE || x == LEFT_ROTATE ) {
    if ( y == CENTER ) { result = NORMAL ; }
  }
  if ( x == LANE_LEFT ) {
    if ( y == ALL_BLACK ) { result = LANE_LEFT_BLIND ; }
  }
  if ( x == LANE_LEFT_BLIND ) {
    if ( y == CENTER ) { result = LANE_LEFTX ; }
  }
  if ( x == LANE_LEFTX || x == LANE_RIGHTX ) {
    if ( y == CENTER ) { result = NORMAL ; }
  }
  if ( x == LANE_RIGHT ) {
    if ( y == ALL_BLACK ) { result = LANE_RIGHT_BLIND ; }
  }
  if ( x == LANE_RIGHT_BLIND ) {
    if ( y == CENTER ) { result = LANE_RIGHTX ; }
  }
  if ( x == NORMAL ) {
    if ( y == ALL_WHITE ) { result = CRANK ; }
    if ( y == LEFT_WHITE ) { result = LANE_LEFT ; }
    if ( y == RIGHT_WHITE ) { result = LANE_RIGHT ; }
  }

  return result ;
}

 タイマー割込みで、トリガーの変化を取得しています。
 また、シリアルインタフェースを使い、状態遷移をして
 いるのかをテストできるように、してあります。

 8ビットデータは、74HC165を利用して取得。
 これは、ピン数が少ないPICでも使えるように
 するため。

 PICは、PIC16F628Aを使います。
 ピンアサインは、次のように決めました。

RA5 <output> --
RA4 <output> --
RA3 <output>ROM_data3
RA2 <output>ROM_data2
RA1 <output>ROM_data1
RA0 <output>ROM_data0

RB7 <input> QH
RB6 <output>SCLK
RB5 <output>LOAD
RB4 <input> TRG
RB3 --
RB2 <output>TxD
RB1 <input> RxD
RB0 --


目次

inserted by FC2 system