目次

ファームウエアソースコード

 ATmega644Pを利用した場合のプログラムは、以下です。

 通信速度は、57600bpsでカメラとデバッグ用PCに接続します。

 割込みは、以下の種類を利用しています。

 ポートの各ビット割当ては、次のようにしています。

 Port B SPIインタフェースと外部割込み

 Port C PWM波形出力

 Port D USART通信


#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#define FOSC   16000000
#define BAUD   57600
#define MYUBRR (FOSC/16/BAUD)-1

#define OFF 0
#define ON  OFF+1

#define BUFSIZE 8

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

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

volatile FLAGSP x_flags ;

#define SFLAG x_flags.BIT.B0
#define BFLAG x_flags.BIT.B1
#define CFLAG x_flags.BIT.B2
#define ZFLAG x_flags.BIT.B3
#define GFLAG x_flags.BIT.B4
#define LFLAG x_flags.BIT.B5
#define DFLAG x_flags.BIT.B7

volatile FLAGSP y_flags ;

#define UFLAG y_flags.BIT.B0
#define XFLAG y_flags.BIT.B1

volatile FLAGSP s_flags ;

#define SBUSY       s_flags.BIT.B0
#define SESTABLISH  s_flags.BIT.B1
#define SINITIALIZE s_flags.BIT.B2
#define STHRESOLD   s_flags.BIT.B3
#define SZFLAG      s_flags.BIT.B4
#define SCRANK      s_flags.BIT.B5
#define SLANERIGHT  s_flags.BIT.B6
#define SLANELEFT   s_flags.BIT.B7

#define RING_BSIZE 512

typedef struct {
  UBYTE data[RING_BSIZE];
  UWORD capacity;
  UWORD rdp;
  UWORD wrp;
} RINGP ;

volatile RINGP rings;

volatile UBYTE sbuf[BUFSIZE] ; 
volatile UBYTE sindex;

#define DAT_MAX  480
#define LINE_MAX 60

volatile UBYTE dummy[12];
volatile UBYTE gdat[DAT_MAX] ;
volatile UBYTE sdat[LINE_MAX] ;

volatile UBYTE gindex ;

volatile UBYTE threshold ;

volatile ULONG tickcount ;

#define NO  0
#define YES NO+1

#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0

volatile UBYTE cport ;
volatile UBYTE pcnt ;
volatile UBYTE lcnt ;
volatile UBYTE duty[4];
volatile UBYTE dutyx[4];

const prog_char asc_code[] PROGMEM = "0123456789ABCDEF" ;

const prog_char msg_h[] PROGMEM = "?:help" ;
const prog_char msg_c[] PROGMEM = "C:establish" ;
const prog_char msg_i[] PROGMEM = "I:initialize" ;
const prog_char msg_g[] PROGMEM = "G:get image" ;
const prog_char msg_a[] PROGMEM = "A:sensor data" ;
const prog_char msg_s[] PROGMEM = "S:status" ;

volatile UBYTE mode ;

volatile UWORD dtim ;
volatile UBYTE state ;
volatile UBYTE dc_left ;
volatile UBYTE dc_right ;
volatile UBYTE do_left ;
volatile UBYTE do_right ;
volatile UBYTE lane_direction ;

#define RMOTOR 0
#define LMOTOR 1
#define SERVO  2
#define LED    3

#define PMAX 200

#define SERVO_MID 15
#define LED_MAX   180

#define IDLE 0
#define RUN  IDLE+1

#define ALL_BLACK    0
#define ALL_WHITE    1
#define LEFT_WHITE   2
#define RIGHT_WHITE  3
#define CENTER       4
#define LITTLE_LEFT  5
#define LEFT         6
#define BIG_LEFT     7
#define LITTLE_RIGHT 8
#define RIGHT        9
#define BIG_RIGHT    10
#define CRANK_RIGHT  11
#define CRANK_LEFT   12

#define LANE_RIGHT 0
#define LANE_LEFT  1

/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void  user_initialize(void);
void  rs_putchar(UBYTE x);
void  rs_put_txd1(UBYTE x);
void  rs_puts_txd1(UBYTE *x);
void  rs_crlf(void);
void  usart_interpret(void);
UBYTE establish_c328(void);
void  send_c328(UBYTE x,UWORD p0,UWORD p1);
void  send_sync(void);
void  send_ack(UBYTE x);
void  send_init(void);
void  send_snapshot(void);
void  send_get_img(void);
void  delay_ms(UWORD x);
void  put_ring(UBYTE x);
UBYTE get_ring(void);
UWORD get_ring_cap(void);
void  init_ring(void);
UBYTE init_c328(void);
UBYTE get_c328(void);
UBYTE generate_threshold(void);
UBYTE is_middle(UWORD x);
UBYTE is_edge(UWORD x);
UBYTE get_sensor(void);
void  update_motor(UBYTE ld,UBYTE rd);
void  rotate(SBYTE x);

/*------*/
/* main */
/*------*/
int main(void)
{
  UBYTE sensor_data ;
  SBYTE angle0 ;
  SBYTE angle1 ;
  /* disable interrupt */
  cli();
  /* initialize port and variables */
  user_initialize();
  /* enable interrupt */
  sei();
  /* establish communication bitween c328 and mega328 */
  SESTABLISH = establish_c328() ;
  /* initialzie c328 (dummy shot) */
  SINITIALIZE = init_c328() ;
  /* generate threshold (dummy shot) */
  STHRESOLD = generate_threshold() ;
  /* initialzie c328 */
  SINITIALIZE = init_c328() ;
  /* generate threshold */  
  STHRESOLD = generate_threshold() ;
  /* */
  BFLAG = get_c328();
  /* endless loop */
  while ( ON ) {
    /* INT2 */
    if ( SFLAG == ON ) {
      SFLAG = OFF ;
      /* change mode */
      if ( mode == IDLE ) { mode = RUN ; }
      else                { mode = IDLE ; }
    }
    /* monitor */
    if ( LFLAG == ON ) {
      LFLAG = OFF ;
      /* update counter */
      lcnt++ ;
      PORTD &= ~(1 << 7) ;
      if ( lcnt & 1 ) { PORTD |= (1 << 7) ; }
    }
    /* command interpreter */
    if ( UFLAG == ON ) {
      UFLAG = OFF ;
      /* USART communication process */
      usart_interpret();
    }
    /* ? IDLE or RUN */
    if ( mode == IDLE ) {
      update_motor(0,0);
      XFLAG = OFF ;
    } else {
      dtim = 1000 ;
      /* initial moving */
      if ( XFLAG == OFF ) {
        dc_left = 50 ;
        dc_left = 50 ;
        update_motor(dc_left,dc_left);
        delay_ms(3000);
        XFLAG = ON ;
      }
      /* get sensor data */
      sensor_data = get_sensor();
      /* state machine */
      switch ( state ) {
        case 0 : /* judge */
          state = 0 ;
          if ( sensor_data == ALL_WHITE    ) { state = 100 ; }
          if ( sensor_data == LEFT_WHITE   ) { state = 200 ; }
          if ( sensor_data == RIGHT_WHITE  ) { state = 200 ; }
          if ( sensor_data == CENTER       ) { state =  10 ; }
          if ( sensor_data == LITTLE_LEFT  ) { state =  20 ; }
          if ( sensor_data == LEFT         ) { state =  30 ; }
          if ( sensor_data == BIG_LEFT     ) { state =  40 ; }
          if ( sensor_data == LITTLE_RIGHT ) { state =  50 ; }
          if ( sensor_data == RIGHT        ) { state =  60 ; }
          if ( sensor_data == BIG_RIGHT    ) { state =  70 ; }
          break ;
        /* CENTER */
        case 10 :
          state = 80 ;
          do_left  = dc_left  ;
          do_right = dc_right ;
          dc_left  <<= 3 ; dc_left  /= 10 ;
          dc_right <<= 3 ; dc_right /= 10 ;
          update_motor(dc_left,dc_left);
          break ;
       /* LITTLE_LEFT (move center) */
       case 20 :
          state = 80 ;
          do_left  = dc_left  ;
          do_right = dc_right ;
          dc_left  *= 95 ; dc_left /= 100 ;
          update_motor(dc_left,dc_left);
          break ;
        /* LEFT (move center) */
        case 30 : 
          state = 80 ;
          do_left  = dc_left  ;
          do_right = dc_right ;
          do_right *= 9 ; do_right /= 10 ;
          update_motor(dc_left,dc_left);
          break ;
        /* BIG_LEFT (move center) */
        case 40 :
          state = 80 ;
          do_left  = dc_left  ;
          do_right = dc_right ;
          do_right <<= 3 ; do_right /= 10 ;
          update_motor(dc_left,dc_left);
          break ;
        /* LITTLE_RIGHT (move center) */
        case 50 :
          state = 80 ;
          do_left  = dc_left  ;
          do_right = dc_right ;
          dc_left *= 95 ; dc_left /= 100 ;
          update_motor(dc_left,dc_left);
          break ;
        /* RIGHT (move center) */
        case 60 :
          state = 80 ;
          do_left  = dc_left  ;
          do_right = dc_right ;
          dc_left *= 9 ; dc_left /= 10 ;
          update_motor(dc_left,dc_left);
          break ;
        /* BIG_RIGHT (move center) */
        case 70 :
          state = 80 ;
          do_left  = dc_left  ;
          do_right = dc_right ;
          do_left <<= 3 ; do_left /= 10 ;
          update_motor(dc_left,dc_left);
          break ;
        /* delay */
        case 80 :
          state = 90 ;
          delay_ms( dtim ) ;
          break ;
        /* return */
        case 90 :
          state = 0 ;
          dc_left  = do_left  ;
          dc_right = do_right ;
          break ;
        /* CRANK */
        case 100 : /* slow move */
          state = 100 ;
          update_motor(20,20);
          delay_ms(1000);
          if ( sensor_data == CRANK_RIGHT ) {
            state  = 110 ;
            angle0 = -60 ;
            angle1 =  -5 ;
          }
          if ( sensor_data == CRANK_LEFT  ) {
            state  = 110 ;
            angle0 =  60 ;
            angle1 =   5 ;
          }
          break ;
        case 110 : /* rotate right */
          state = 120 ;
          rotate(angle0);
          delay_ms(3000);
          break ;
        case 120 : /* rotate right (bit by bit) */
          state = 120 ;
          if ( sensor_data == CENTER ) { state = 130 ; }
          else { rotate(angle1) ; delay_ms(100); }
          break ;
        case 130 : /* slow move */
          state = 140 ;
          update_motor(20,20);
          delay_ms(1000);
          break ;
        case 150 : /* return */
          state = 0 ;
          break ;
        /* LANE */
        case 200 : /* slow move */
          state = 200 ;
          update_motor(20,20);
          delay_ms(1000);
          if ( sensor_data == ALL_BLACK ) {
            state  = 210 ; 
            angle0 = -30 ;
            angle1 =  30 ;
            if ( lane_direction == LANE_LEFT ) {
              angle0 *= -1 ;
              angle1 *= -1 ;
            }
          }
          break ;
        case 210 : /* rotate */
          state = 220 ;
          rotate(angle0);
          delay_ms(1000);
          break ;
        case 220 : /* move */
          state = 220 ;
          if ( sensor_data == CENTER ) { state = 230 ; }
          else {
            update_motor(20,20);
            delay_ms(1000);
          }
          break ;
        case 230 : /* roate (reverse) */
          state = 240 ;
          rotate(angle1);
		  delay_ms(1000);
          break ;
        case 240 : /* slow move */
          state = 250 ;
          update_motor(20,20);
          delay_ms(1000);
          break ;
        case 250 : /* return */
          state = 0 ;
          break ;
      }
      /* establish communication bitween c328 and mega328 */
      SESTABLISH = establish_c328() ;
      /* initialzie c328 (dummy shot) */
      SINITIALIZE = init_c328() ;
      /* prepare next state processing */
      BFLAG = get_c328();
    }
  }
  /* dummy */
  return 0 ;
}

#/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void user_initialize(void)
{
  UWORD tmp ;
  /* PORT A */
  PORTA = 0b00000000 ; /* 00000000 */
  DDRA  = 0b11111111 ; /* oooooooo */
  /* PORT B */
  PORTB = 0b00010100 ; /* 00000000 */
  DDRB  = 0b10111011 ; /* oioooioo */
  /* PORT C */
  PORTC = 0b00000000 ; /* 00000000 */
  DDRC  = 0b00111111 ; /* iioooooo */
  /* PORT D */
  PORTD = 0b00000000 ; /* 00000000 */
  DDRD  = 0b11111010 ; /* oooooioi */
  /* */
  x_flags.DR = 0 ;
  y_flags.DR = 0 ;
  s_flags.DR = 0 ;
  sindex = 0 ;
  gindex = 0 ;
  tickcount = 0 ;
  mode = IDLE ;
  /* initialize timer0 */
  {
    /* clear counter */
    TCNT0 = 0 ;
    /* set compare value */
    OCR0A = 199 ;
    OCR0B = 250 ;
    /* inhibit compare match output , select CTC mode */
    TCCR0A = (1 << WGM01) ;
    /* prescaler /8 => 2MHz */
    TCCR0B = (1 << CS01) ;
    /* enable compare match */
    TIMSK0 = (1 << OCIE0A) ;
  }
  /* initialzie duty ratio */
  pcnt = 0 ;
  lcnt = 0 ;
  /* initialize duty */
  *(duty+RMOTOR) = 0 ;	
  *(duty+LMOTOR) = 0 ;	
  *(duty+SERVO)  = SERVO_MID ;	
  *(duty+LED)    = LED_MAX;  
  /* initialize duty (interrupt) */
  *(dutyx+RMOTOR) = 0 ;	
  *(dutyx+LMOTOR) = 0 ;	
  *(dutyx+SERVO)  = SERVO_MID ;	
  *(dutyx+LED)    = LED_MAX;
  /* initialize timer1 */
  {
    /* clear counter */
    TCNT1 = 0 ;
    /* set compare value */
    OCR1A = 1999 ;
    OCR1B = 3200 ;
    /* prescaler /8 => 2MHz */
    TCCR1B = (1 << WGM12) | (1 << CS11) ;
    /* enable compare match */
    TIMSK1 = (1 << OCIE1A) ;
  }
  /* clear index */
  sindex = 0 ;
  /* clear buffer */
  *(sbuf+0) = 0 ;
  /* initialize SCI0 */
  {
    /* set Baud Rate Registers */
    tmp = MYUBRR ;
    UBRR0H = (UBYTE)((tmp >> 8) & MASKFF) ;
    UBRR0L = (UBYTE)(tmp & MASKFF) ;	
    /* Enable receive interrupt , receive module and transmit module */
    UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0) ;
    /* 8 bits , 1 stop bit , no parity */
    UCSR0C = (3 << UCSZ00);
  }
  /* */
  init_ring();
  /* initialize SCI1 */
  {
    /* set Baud Rate Registers */
    tmp = MYUBRR ;
    UBRR1H = (UBYTE)((tmp >> 8) & MASKFF) ;
    UBRR1L = (UBYTE)(tmp & MASKFF) ;	
    /* Enable receive interrupt , receive module and transmit module */
    UCSR1B = (1 << RXCIE1) | (1 << RXEN1) | (1 << TXEN1) ;
    /* 8 bits , 1 stop bit , no parity */
    UCSR1C = (3 << UCSZ10);
  }
}

/* UART receive interrupt */
ISR(USART0_RX_vect)
{
  volatile UBYTE ch ;
  if ( !(UCSR0B & (1 << FE0)) ) {
    /* get 1 charactoer */
    ch = UDR0 ;
    /* store */
    put_ring( ch );
  }
}

/* UART receive interrupt */
ISR(USART1_RX_vect)
{
  volatile UBYTE ch ;
  if ( !(UCSR1B & (1 << FE1)) ) {
    /* get 1 charactoer */
    ch = UDR1 ;
    /* store */
    *(sbuf+sindex) = ch ;
    /* update */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ;
      UFLAG = ON ;
    }
  }
}

void  rs_putchar(UBYTE x)
{
  while ( !(UCSR0A & (1 << UDRE0)) ) {}
  UDR0 = x ;
}

void  rs_put_txd1(UBYTE x)
{
  while ( !(UCSR1A & (1 << UDRE1)) ) {}
  UDR1 = x ;
}

void  rs_puts_txd1(UBYTE *x)
{
  while ( *x != '\0' ){
    rs_put_txd1(*x) ;
    x++ ;
  }
  rs_crlf();
}

void  rs_crlf(void)
{
  rs_put_txd1('\r') ;
  rs_put_txd1('\n') ;
}

/* timer0 comare match interrupt */
ISR(TIMER0_COMPA_vect)
{
  /* initialize */
  cport = 0 ;
  /* judge */
  if ( pcnt <= *(dutyx+RMOTOR) ) { cport |= 1 ; }
  if ( pcnt <= *(dutyx+LMOTOR) ) { cport |= 2 ; }
  if ( pcnt <= *(dutyx+SERVO)  ) { cport |= 4 ; }
  if ( pcnt <= *(dutyx+LED)    ) { cport |= 8 ; }
  /* set */
  PORTC = cport ;
  /* increment */
  pcnt++ ;
  if ( pcnt == PMAX ) {
    pcnt = 0 ;
    /* update */
    *(dutyx+RMOTOR) = *(duty+RMOTOR) ;
    *(dutyx+LMOTOR) = *(duty+LMOTOR) ;
    *(dutyx+SERVO)  = *(duty+SERVO)  ;
    *(dutyx+LED)    = *(duty+LED)    ;
    /* monitor */
    LFLAG = ON ;
  }
}

/* INT2 interrupt */
ISR(INT2_vect)
{
  SFLAG = ON ;
}

#define SEL_BIT 5
#define LT_BIT  4
#define FLG_BIT 3

#define KEEP_INDEX 30

#define MASK0F 0x0f 

/* USART interpreter */
void  usart_interpret(void)
{
  UBYTE cmd ;
  UBYTE i ;
  UBYTE tmp ;
  char  msg[20];
  /* get command */
  cmd = *(sbuf+0) ;
  /* help */
  if ( cmd == '?' ) {
    strcpy_P(msg,msg_h); rs_puts_txd1((UBYTE *)msg) ;
    strcpy_P(msg,msg_c); rs_puts_txd1((UBYTE *)msg) ;
    strcpy_P(msg,msg_i); rs_puts_txd1((UBYTE *)msg) ;
    strcpy_P(msg,msg_g); rs_puts_txd1((UBYTE *)msg) ;
    strcpy_P(msg,msg_a); rs_puts_txd1((UBYTE *)msg) ;
    strcpy_P(msg,msg_s); rs_puts_txd1((UBYTE *)msg) ;
  }
  /* establish communication */
  if ( cmd == 'C' ) { establish_c328(); }
  /* initialize c328 */
  if ( cmd == 'I' ) { init_c328(); }
  /* get image from c328 and convert data to sensor data */
  if ( cmd == 'G' ) { get_c328(); }
  /* show sensor data */
  if ( cmd == 'A' ) {
    for ( i = 0 ; i < 60 ; i++ ) {
      /* get code */
      tmp = *(sdat+i) ;
      /* separate */
      rs_put_txd1( pgm_read_byte(&asc_code[((tmp >> 4) & MASK0F)]) );
      rs_put_txd1( pgm_read_byte(&asc_code[(tmp & MASK0F)]) );
      rs_crlf();
    }
  }
  /* show status */
  if ( cmd == 'S' ) {
    if ( SBUSY )      { rs_puts_txd1((UBYTE *)"BUSY"); }
    if ( SESTABLISH ) { rs_puts_txd1((UBYTE *)"connected"); }
    else              { rs_puts_txd1((UBYTE *)"disconnected"); }
    rs_puts_txd1((UBYTE *)"threshold ");
    if ( STHRESOLD )   { rs_puts_txd1((UBYTE *)" exists"); }
    else               { rs_puts_txd1((UBYTE *)" not existed"); }
    if ( SCRANK )      { rs_puts_txd1((UBYTE *)"crank mode"); }
    if ( SLANERIGHT )  { rs_puts_txd1((UBYTE *)"right lane"); }	
    if ( SLANELEFT  )  { rs_puts_txd1((UBYTE *)"left lane"); }
  }
}

UBYTE establish_c328(void)
{
  UWORD i ;
  UWORD length ;
  UBYTE result ;
  UBYTE gflag  ;
  UBYTE yflag0 ;
  UBYTE yflag1 ;
  /* default */
  gflag = OFF ;
  yflag0 = OFF ;
  yflag1 = OFF ;
  if ( DFLAG ) { rs_puts_txd1((UBYTE *)" _SYNC") ; }
  /* flush */
  length = get_ring_cap() ;
  if ( length ) {
    for ( i = 0 ; i < length ; i++ ) { result = get_ring() ; }
  }
  /* looping */
  for ( i = 0 ; i < 60 ; i++ ) {
    /* send SYNC command */
    send_sync();
    /* wait */
    delay_ms( 10 ) ;
    /* judge */
    if ( get_ring_cap() < 12 ) continue ;
    /* get data from buffer */
    length = get_ring_cap() ;
    for ( i = 0 ; i < length ; i++ ) {
      if ( i > 11 ) { result = get_ring() ; }
      else          { *(dummy+i) = get_ring() ; }
    }
    /* */
    gflag = ON ;
    if ( gflag ) break ;
  }
  /* judge */
  if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x0D ) { yflag0 = ON ; }
  if ( *(dummy+7) == 0x0D && *(dummy+8) == 0x00 ) { yflag1 = ON ; }
  /* send ACK */
  result = gflag & yflag0 & yflag1 ;
  if ( result ) {
    send_ack( 0x0D ) ;
    if ( DFLAG )  { rs_puts_txd1((UBYTE *)" _established") ; }
    if ( yflag0 ) { rs_puts_txd1((UBYTE *)" _ACK OK! ")  ;   }
    if ( yflag1 ) { rs_puts_txd1((UBYTE *)" _SYNC send ") ;  }
  }

  return result ;  
}

void  send_c328(UBYTE x,UWORD p0,UWORD p1)
{
  rs_putchar( 0xAA );
  rs_putchar( x    );
  rs_putchar( (UBYTE)((p0 >> 8) & MASKFF) );
  rs_putchar( (UBYTE)(p0 & MASKFF) );
  rs_putchar( (UBYTE)((p1 >> 8) & MASKFF) );
  rs_putchar( (UBYTE)(p1 & MASKFF) );
}

void  send_sync(void)
{
  send_c328(0x0D,0x0000,0x0000);
}

void  send_ack(UBYTE x)
{
  send_c328(0x0D,(x << 8) | 0x00,0x0000);
}

/* Timer1 interrupt */
ISR(TIMER1_COMPA_vect)
{
  /* increment */
  tickcount++ ;
}

void delay_ms(UWORD x)
{
  ULONG target ;
  /* set target */
  target = tickcount + (ULONG)x ;
  /* wait */
  while( target > tickcount ) ;
}

void  put_ring(UBYTE x)
{
  UWORD ptmp ;
  /* store data */
  rings.data[rings.wrp] = x ;
  /* pointer increment */
  ptmp = rings.wrp  ;
  ptmp++ ;
  if ( ptmp == RING_BSIZE ) { rings.wrp = 0 ; }
  /* capacity increment */
  ptmp = rings.capacity ;
  ptmp++ ;
  rings.capacity = ptmp ;
}

UBYTE get_ring(void)
{
  UWORD ptmp ;
  UBYTE result ;
  /* default */
  result = 0 ;
  /* judge */
  ptmp = rings.rdp ;
  if ( rings.capacity == 0 ) { return result ; }
  /* read data */
  result = rings.data[ptmp] ;
  /* pointer increment */
  ptmp++ ;
  if ( ptmp == RING_BSIZE ) { rings.rdp = 0 ; }
  /* capacity decrement */
  ptmp = rings.capacity ;
  if ( ptmp > 0 ) { rings.capacity = ptmp - 1 ; }
  
  return result ;
}

UWORD get_ring_cap(void)
{
  return rings.capacity ;
}

void  init_ring(void)
{
  /* clear capacity */
  rings.capacity = 0 ;
  /* initialize read pointer */
  rings.rdp = 0 ;
  /* initialize write pointer */
  rings.wrp = 0 ;
}

UBYTE init_c328(void)
{
  UWORD i ;
  UWORD length ;
  UBYTE yflag0 ;
  UBYTE yflag1 ;
  /* set BUSY */
  BFLAG = ON ;
  /* default */
  yflag0 = OFF ;
  /* send SYNC command */
  send_init();
  /* wait response */
  delay_ms(20) ;
  /* get data from buffer */
  length = get_ring_cap() ;
  for ( i = 0 ; i < 6 ; i++ ) { *(dummy+i) = get_ring() ; }
  if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x01 ) { yflag0 = ON ; }
  /* send snap shot */
  send_snapshot();
  /* wait response */
  delay_ms(20) ;
  /* get data from buffer */
  length = get_ring_cap() ;
  for ( i = 6 ; i < 12 ; i++ ) { *(dummy+i) = get_ring() ; }
  if ( *(dummy+7) == 0x0E && *(dummy+8) == 0x05 ) { yflag1 = ON ; }
  /* reset BUSY */
  BFLAG = OFF ;

  return yflag1 & yflag0 ;
}

void  send_init(void)
{
  send_c328(0x01,0x0003,0x0100);
}

void  send_snapshot(void)
{
  send_c328( 0x05 , 0x0100 , 0x0000 );
}

void  send_get_img(void)
{
  send_c328(0x04,0x0100,0x0000);
}

UBYTE get_c328(void)
{
  UWORD i ;
  UWORD j ;
  ULONG length ;
  UBYTE k ;
  UBYTE resx ;
  UBYTE result ;
  UBYTE yflag0 ;
  UBYTE yflag1 ;
  /* set BUSY */
  BFLAG = ON ;
  /* set status */
  SBUSY = ON ;
  /* sweap */
  length = get_ring_cap();
  if ( length ) {
    for ( i = 0 ; i < (UWORD)length ; i++ ) { result = get_ring() ;}
  }
  /* send get picture command */
  send_get_img();
  /* wait */
  while ( ON ) {
    result = get_ring_cap() ;
    if ( result >= 12 ) break ;
    delay_ms(1);
  }
  /* copy */
  for ( i = 0 ; i < 12 ; i++ ) { *(dummy+i) = get_ring() ; }
  /* judge */
  yflag0 = OFF ;
  yflag1 = OFF ;
  if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x04 ) { yflag0 = ON ; }
  if ( *(dummy+7) == 0x0A && *(dummy+8) == 0x01 ) { yflag1 = ON ; }
  /* calculate size */
  length  = *(dummy+11) ; length <<= 8 ;
  length += *(dummy+10) ; length <<= 8 ;
  length += *(dummy+9 ) ;
  if ( length > 32767 ) {
    /* flush */
    length = get_ring_cap(); 
    for ( i = 0 ; i < length ; i++ ) { result = get_ring(); }
    return OFF ;
  }
  /* get image data */
  k = 0 ;
  resx = 0 ;
  for ( i = 0 ; i < (UWORD)length ; i++ ) {
    /* wait receive graphic data */
    while ( get_ring_cap() <= 0 ) ;
    /* get 1 pixel */
    result = get_ring();
    /* judge */
    if ( result > threshold ) { resx++ ; }
    /* block summuation */
    j = i % 10 ;
    if ( j == 9 ) {
      /* store summuation */
      *(gdat+k) = resx ;
      /* clear block summuation */
      resx = 0 ;
      /* pointer increment */
      k++ ;
    }
  }
  /* send ACK */
  send_ack( 0x0A );
  /* generate sensor data */
  SCRANK = OFF ;
  SLANERIGHT = OFF ;
  SLANELEFT  = OFF ;
  for ( i = 0 ; i < LINE_MAX ; i++ ) {
    /* index */
    j = (i << 3) ;
    /* summuation */
    resx = 0 ;
    resx += *(gdat+j+0) ;
    resx += *(gdat+j+1) ;
    resx += *(gdat+j+2) ;
    resx += *(gdat+j+3) ;
    resx += *(gdat+j+4) ;
    resx += *(gdat+j+5) ;
    resx += *(gdat+j+6) ;
    resx += *(gdat+j+7) ;
    /* average */
    resx >>= 3 ;
    /* convert */
    result = 0 ;
    if ( *(gdat+j+0) > result ) { result |= 0x80 ; }
    if ( *(gdat+j+1) > result ) { result |= 0x40 ; }
    if ( *(gdat+j+2) > result ) { result |= 0x20 ; }
    if ( *(gdat+j+3) > result ) { result |= 0x10 ; }
    if ( *(gdat+j+4) > result ) { result |= 0x08 ; }
    if ( *(gdat+j+5) > result ) { result |= 0x04 ; }
    if ( *(gdat+j+6) > result ) { result |= 0x02 ; }
    if ( *(gdat+j+7) > result ) { result |= 0x01 ; }
    /* reverse store */
    *(sdat+59-i) = result ;
    /* judge CRANK */
    if ( result == 0xff ) { SCRANK = ON ; }
    if ( result == 0xf0 || result == 0xf8 ) { SLANELEFT  = ON ; }
    if ( result == 0x0f || result == 0x1f ) { SLANERIGHT = ON ; }
  }
  /* */
  BFLAG = OFF ;
  /* reset status */
  SBUSY = OFF ;
  
  return ON ;
}

UBYTE generate_threshold(void)
{
  UWORD i ;
  ULONG length ;
  UBYTE resx ;
  UBYTE resy ;
  UBYTE result ;
  UBYTE yflag0 ;
  UBYTE yflag1 ;
  /* set BUSY */
  BFLAG = ON ;
  /* set status */
  SBUSY = ON ;
  /* sweap */
  length = get_ring_cap();
  if ( length ) {
    for ( i = 0 ; i < (UWORD)length ; i++ ) { result = get_ring() ;}
  }
  /* send get picture command */
  send_get_img();
  /* wait */
  while ( ON ) {
    result = get_ring_cap() ;
    if ( result >= 12 ) break ;
    delay_ms(1);
  }
  /* copy */
  for ( i = 0 ; i < 12 ; i++ ) { *(dummy+i) = get_ring() ; }
  /* judge */
  yflag0 = OFF ;
  yflag1 = OFF ;
  if ( *(dummy+1) == 0x0E && *(dummy+2) == 0x04 ) { yflag0 = ON ; }
  if ( *(dummy+7) == 0x0A && *(dummy+8) == 0x01 ) { yflag1 = ON ; }
  /* calculate size */
  length  = *(dummy+11) ; length <<= 8 ;
  length += *(dummy+10) ; length <<= 8 ;
  length += *(dummy+9 ) ;
  if ( length > 32767 ) {
    /* flush */
    length = get_ring_cap(); 
    for ( i = 0 ; i < length ; i++ ) { result = get_ring(); }
    return OFF ;
  }
  /* get image data */
  resx = 0 ;
  resy = 0 ;
  for ( i = 0 ; i < (UWORD)length ; i++ ) {
    /* wait receive graphic data */
    while ( get_ring_cap() <= 0 ) ;
    /* get 1 pixel */
    result = get_ring();
    /* judge */
    if ( is_middle(i) ) { resx += result ; }
    if ( is_edge(i)   ) { resy += result ; }
    /* calculate threshold and store it */
    if ( i == 4799 ) {
      resx >>= 3 ;
      resy >>= 3 ;
      threshold = ((resx+resy) >> 1) ;
    }
  }
  /* send ACK */
  send_ack( 0x0A );
  /* */
  BFLAG = OFF ;
  /* reset status */
  SBUSY = OFF ;
  
  return ON ;
}

UBYTE is_middle(UWORD x)
{
  UBYTE result ;
  result = OFF ;
  if ( x == 1159 ) { result = ON ; }
  if ( x == 1160 ) { result = ON ; }
  if ( x == 2359 ) { result = ON ; }
  if ( x == 2360 ) { result = ON ; }
  if ( x == 3559 ) { result = ON ; }
  if ( x == 3540 ) { result = ON ; }
  if ( x == 4759 ) { result = ON ; }
  if ( x == 4760 ) { result = ON ; }
  return result ;
}

UBYTE is_edge(UWORD x)
{
  UBYTE result ;
  result = OFF ;
  if ( x == 1120 ) { result = ON ; }
  if ( x == 1179 ) { result = ON ; }
  if ( x == 2320 ) { result = ON ; }
  if ( x == 2399 ) { result = ON ; }
  if ( x == 3520 ) { result = ON ; }
  if ( x == 3599 ) { result = ON ; }
  if ( x == 4720 ) { result = ON ; }
  if ( x == 4799 ) { result = ON ; }
  return result ;
}

UBYTE get_sensor(void)
{
  return *(sdat+29) ;
}

void  update_motor(UBYTE ld,UBYTE rd)
{
  *(duty+LMOTOR) = (ld << 1);
  *(duty+RMOTOR) = (rd << 1);
}

void  rotate(SBYTE x)
{
  UBYTE dx_left  ;
  UBYTE dx_right ;
  UBYTE tmp ;
  /* default */
  dx_left  = 10 ;
  dx_right = 10 ;
  if ( x < 0 ) {
    tmp = x *(-1);
    if ( tmp == 5  ) { dx_right = dx_left+5  ; }
    if ( tmp == 30 ) { dx_right = dx_left+15 ; }
    if ( tmp == 60 ) { dx_right = dx_left+30 ; }
  } else {
    tmp = x ;
    if ( tmp == 5  ) { dx_left = dx_right+5  ; }
    if ( tmp == 30 ) { dx_left = dx_right+15 ; }
    if ( tmp == 60 ) { dx_left = dx_right+30 ; }
  }
  /* update */
  update_motor(dx_left,dx_right);
}


目次

inserted by FC2 system