This program supports the Image processing micon car production kit (M-S348).

Dependencies:   GR-PEACH_video mbed

main.cpp

Committer:
TetsuyaKonno
Date:
2018-10-30
Revision:
0:00b6f7454ada

File content as of revision 0:00b6f7454ada:

//------------------------------------------------------------------//
//Supported MCU:   RZ/A1H
//File Contents:   kit18 GR-peach ( Trace program )
//Version number:  Ver.1.00
//Date:            2018.10.30
//Copyright:       Renesas Electronics Corporation
//                 Hitachi Document Solutions Co., Ltd.
//------------------------------------------------------------------//

//This program supports the following kit:
//* M-S348 Image processing micon car production kit

//------------------------------------------------------------------//
//Include
//------------------------------------------------------------------//
#include "mbed.h"
#include "iodefine.h"
#include "DisplayBace.h"
#include "image_process.h"

//------------------------------------------------------------------//
//Define
//------------------------------------------------------------------//
//Motor PWM cycle
#define     MOTOR_PWM_CYCLE     33332   /* Motor PWM period         */
                                        /* 1ms    P0φ/1  = 0.03us   */
//Servo PWM cycle
#define     SERVO_PWM_CYCLE     33332   /* SERVO PWM period         */
                                        /* 16ms   P0φ/16 = 0.48us   */
#define     SERVO_CENTER        3124    /* 1.5ms / 0.48us - 1 = 3124*/
#define     HANDLE_STEP         18      /* 1 degree value           */

#define     THRESHOLD           128     /* Binarization function only */

//LED Color on GR-PEACH
#define     LED_OFF             0x00
#define     LED_RED             0x01
#define     LED_GREEN           0x02
#define     LED_YELLOW          0x03
#define     LED_BLUE            0x04
#define     LED_PURPLE          0x05
#define     LED_SKYBLUE         0x06
#define     LED_WHITE           0x07

//led_m_set function only
#define     RUN                 0x00
#define     STOP                0x01
#define     ERROR               0x02
#define     DEBUG               0x03
#define     CRANK               0x04
#define     LCHANGE             0x05

//ImageData_Serial_out3 function only
#define     COLOR               0x01
#define     GREY_SCALE          0x02
#define     BINARY              0x03

//------------------------------------------------------------------//
//Define(NTSC-Video)
//------------------------------------------------------------------//
#define VIDEO_INPUT_CH         (DisplayBase::VIDEO_INPUT_CHANNEL_0)
#define VIDEO_INT_TYPE         (DisplayBase::INT_TYPE_S0_VFIELD)
#define DATA_SIZE_PER_PIC      (2u)

/*! Frame buffer stride: Frame buffer stride should be set to a multiple of 32 or 128
    in accordance with the frame buffer burst transfer mode. */
#define PIXEL_HW               (160u)  /* QVGA */
#define PIXEL_VW               (120u)  /* QVGA */
#define VIDEO_BUFFER_STRIDE    (((PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u)
#define VIDEO_BUFFER_HEIGHT    (PIXEL_VW)

//------------------------------------------------------------------//
//Constructor
//------------------------------------------------------------------//
/* Create DisplayBase object */
DisplayBase Display;

Ticker      interrput;
Serial      pc(USBTX, USBRX);

DigitalOut  LED_R(P6_13);               /* LED1 on the GR-PEACH board */
DigitalOut  LED_G(P6_14);               /* LED2 on the GR-PEACH board */
DigitalOut  LED_B(P6_15);               /* LED3 on the GR-PEACH board */
DigitalOut  USER_LED(P6_12);            /* USER_LED on the GR-PEACH board */
DigitalIn   user_botton(P6_0);          /* SW1 on the GR-PEACH board */

BusIn       dipsw( P7_15, P8_1, P2_9, P2_10 ); /* SW1 on Shield board */

DigitalOut  Left_motor_signal(P4_6);    /* Used by motor function   */
DigitalOut  Right_motor_signal(P4_7);   /* Used by motor function   */
DigitalIn   push_sw(P2_13);             /* SW1 on the Motor Drive board */
DigitalOut  LED_3(P2_14);               /* LED3 on the Motor Drive board */
DigitalOut  LED_2(P2_15);               /* LED2 on the Motor Drive board */

//------------------------------------------------------------------//
//Prototype(NTSC-video)
//------------------------------------------------------------------//
void init_Camera( void );
void ChangeFrameBuffer( void );
static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type);
static void WaitVfield(const int32_t wait_count);
static void IntCallbackFunc_Vsync(DisplayBase::int_type_t int_type);
static void WaitVsync(const int32_t wait_count);

//------------------------------------------------------------------//
//Prototype
//------------------------------------------------------------------//
//Peripheral functions
void init_MTU2_PWM_Motor( void );       /* Initialize PWM functions */
void init_MTU2_PWM_Servo( void );       /* Initialize PWM functions */

//Interrupt function
void intTimer( void );                  /* 1ms period               */

//GR-peach board
void led_rgb(int led);
void led_m_user( int led );
unsigned char user_button_get( void );
void led_m_set( int set );
void led_m_process( void );             /* Only function for interrupt */

//Motor drive board
void led_out(int led);
unsigned char pushsw_get( void );
void motor( int accele_l, int accele_r );
void motor2( int accele_l, int accele_r );
void handle( int angle );
int diff( int pwm );

//Shield board
unsigned char dipsw_get( void );

//------------------------------------------------------------------//
//Prototype( Digital sensor process )
//------------------------------------------------------------------//
int init_sensor( unsigned char *BuffAddrIn, int HW, int VW, int Cx, int *SENPx, int Y );
unsigned char sensor_process( unsigned char *BuffAddrIn, int HW, int VW, int *SENPx, int Y ); /* Only function for interrupt */
unsigned char sensor_inp( void );
unsigned char center_inp( void );

//------------------------------------------------------------------//
//Prototype( Mark detect functions )
//------------------------------------------------------------------//
int RightCrankCheck( int percentage );
int RightLaneChangeCheck( int percentage );

//------------------------------------------------------------------//
//Prototype( Debug functions )
//------------------------------------------------------------------//
void ImageData_Serial_Out1( unsigned char *ImageData, int HW, int VW );
void ImageData_Serial_Out2( unsigned char *ImageData, int HW, int VW );
void ImageData_Serial_Out3( unsigned char *ImageData, int HW, int VW, int color_pattern );

//------------------------------------------------------------------//
//Global variable (NTSC-video)
//------------------------------------------------------------------//
static uint8_t FrameBuffer_Video_A[VIDEO_BUFFER_STRIDE * VIDEO_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(16)));  //16 bytes aligned!;
static uint8_t FrameBuffer_Video_B[VIDEO_BUFFER_STRIDE * VIDEO_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(16)));  //16 bytes aligned!;
uint8_t * write_buff_addr = FrameBuffer_Video_A;
uint8_t * save_buff_addr  = FrameBuffer_Video_B;
static volatile int32_t vsync_count;
static volatile int32_t vfield_count;
static volatile int32_t vfield_count2 = 1;
static volatile int32_t vfield_count2_buff;

//------------------------------------------------------------------//
//Global variable for Image process
//------------------------------------------------------------------//
unsigned char   ImageData_A[ ( ( PIXEL_HW * 2) * PIXEL_VW ) ];
unsigned char   ImageData_B[ ( PIXEL_HW * PIXEL_VW ) ];
unsigned char   ImageComp_B[ ( PIXEL_HW * PIXEL_VW ) ];
unsigned char   ImageBinary[ ( PIXEL_HW * PIXEL_VW ) ];

double          Rate = 0.125;       /* Reduction ratio              */

//------------------------------------------------------------------//
//Global variable for Digital sensor function
//------------------------------------------------------------------//
int             SenError;
int             Sen1Px[5];
unsigned char   SenVal1;

//------------------------------------------------------------------//
//Global variable for Mark detection function
//------------------------------------------------------------------//
ImagePartPattern RightCrank = {0,0,0,0,{0},   //percent, Point X, Point Y, Standard_Deviation, Deviation
                              {0,0,0,0,0,0,0, //Binary image
                               0,0,1,1,1,1,1, //Binary image
                               0,0,1,1,1,0,0, //Binary image
                               0,0,1,1,1,0,0},//Binary image
                               7, 4};         //Binary Width pixel, Binary Height pixel

ImagePartPattern RightLaneChange = {0,0,0,0,{0},//percent, Point X, Point Y, Standard_Deviation, Deviation
                                   {0,0,0,1,1,0,0,0,0,0,0,0,0,0, //Binary image
                                    0,0,0,1,1,0,0,0,0,0,0,0,0,0, //Binary image
                                    0,0,0,1,1,0,0,0,0,0,0,0,0,0},//Binary image
                                    14, 3};   //Binary Width pixel, Binary Height pixel

//------------------------------------------------------------------//
//Global variable for Trace program
//------------------------------------------------------------------//
volatile unsigned long  cnt0;           /* Used by timer function   */
volatile unsigned long  cnt1;           /* Used within main         */
volatile int            pattern;        /* Pattern numbers          */

volatile int            led_pattern;    /* led_m_process function only */
volatile int            initFlag;       /* Initialize flag          */
volatile int            threshold_buff; /* Binarization function only */
volatile int            handle_buff;    /* diff function only       */

const int revolution_difference[] = {   /* diff function only       */
    100, 98, 97, 95, 93,
    92, 90, 88, 87, 85,
    84, 82, 81, 79, 78,
    76, 75, 73, 72, 71,
    69, 68, 66, 65, 64,
    62, 61, 59, 58, 57,
    55, 54, 52, 51, 50,
    48, 47, 45, 44, 42,
    41, 39, 38, 36, 35,
    33 };

//******************************************************************//
// Main function
//*******************************************************************/
int main( void )
{
    volatile int    Number;             /* Serial Debug Mode only   */

    initFlag = 1;                       /* Initialization start     */

    /* Camera start */
    init_Camera();
    /* wait to stabilize NTSC signal (about 170ms) */
    wait(0.2);

    /* Initialize MCU functions */
    init_MTU2_PWM_Motor();
    init_MTU2_PWM_Servo();
    interrput.attach(&intTimer, 0.001);
    pc.baud(230400);

    /* Initialize Micon Car state */
    handle( 0 );
    motor( 0, 0 );
    led_out( 0x0 );
    led_m_set( STOP );

    threshold_buff = THRESHOLD;

    wait(0.5);

    /* Initialize Digital sensor */
    SenError = init_sensor( ImageBinary, (PIXEL_HW * Rate), (PIXEL_VW * Rate), (PIXEL_HW * Rate) / 2, Sen1Px, 12 );
    if( SenError !=0 ) {
        led_m_set( ERROR );
        cnt1 = 0;
        while( cnt1 < 3000 ){
            if( cnt1 % 200 < 100 ) {
                led_out( 0x3 );
            } else {
                led_out( 0x0 );
            }
        }
    }

    /* Initialize Pattern Matching */
    RightCrank.sdevi = Standard_Deviation( RightCrank.binary, RightCrank.devi, RightCrank.w, RightCrank.h );
    RightLaneChange.sdevi = Standard_Deviation( RightLaneChange.binary, RightLaneChange.devi, RightLaneChange.w, RightLaneChange.h );

    initFlag = 0;                       /* Initialization end       */

    /* Debug Program */
    if( user_button_get() ) {
        led_m_set( DEBUG );
        wait(0.1);//ON Time
        while( user_button_get() );
        wait(0.5);//OFF Time
        while( 1 ){
            pc.printf( "Serial Debug Mode Ver1.0 (2018.10.30)\n\r" );
            pc.printf( "\n\r" );
            pc.printf( "0:TeraTram Real-time display 20* 15pixel (Binary)\n\r" );
            pc.printf( "1:Excel(csv) 160*120pixel\n\r" );
            pc.printf( "2:Excel(csv)  20* 15pixel\n\r" );
            pc.printf( "3:Excel(csv) 160*120pixel -> csv_jpg_convert.bat (color)\n\r" );
            pc.printf( "4:Excel(csv) 160*120pixel -> csv_jpg_convert.bat (grey scale)\n\r" );
            pc.printf( "5:Excel(csv)  20* 15pixel -> csv_jpg_convert.bat (binary)\n\r" );
            pc.printf( "\n\r" );
            pc.printf( "Please Number\n\r" );
            pc.printf( "No = " );
            pc.scanf( "%d", &Number );
            pc.printf( "\n\r" );
            pc.printf( "Please push the SW ( on the Motor drive board )\n\r" );
            pc.printf( "\n\r" );
            while( !pushsw_get() );

            switch( Number ) {
            case 0:
                /* for TeraTerm(Real-time display) */
                while( 1 ) {
                    ImageData_Serial_Out2( ImageBinary, (PIXEL_HW * Rate), (PIXEL_VW * Rate) );
                }
                break;
            case 1:
                /* for the Excel(csv) 160*120pixel */
                ImageData_Serial_Out1( ImageData_B, PIXEL_HW, PIXEL_VW );
                break;
            case 2:
                /* for the Excel(csv)  20* 15pixel */
                ImageData_Serial_Out1( ImageComp_B, (PIXEL_HW * Rate), (PIXEL_VW * Rate) );
                break;
            case 3:
                /* for the Excel(csv) -> csv_jpg_convert.bat */
                ChangeFrameBuffer();
                ImageData_Serial_Out3( save_buff_addr, PIXEL_HW, PIXEL_VW, COLOR );
                break;
            case 4:
                /* for the Excel(csv) -> csv_jpg_convert.bat */
                ImageData_Serial_Out3( ImageData_B, PIXEL_HW, PIXEL_VW, GREY_SCALE );
                break;
            case 5:
                /* for the Excel(csv) -> csv_jpg_convert.bat */
                ImageData_Serial_Out3( ImageBinary, (PIXEL_HW * Rate), (PIXEL_VW * Rate), BINARY );
                break;
            default:
                break;
            }
            led_m_set( STOP );
            while(1);
        }
    }

    /* Trace program */
    led_m_set( RUN );

    while( 1 ) {

    switch( pattern ) {
    /*****************************************************************
    About patern
     0:wait for switch input
     1:check if start bar is open
    11:normal trace
    12:Left side
    13:right side
    *****************************************************************/
    case 0:
        /* wait for switch input */
        if( pushsw_get() ) {
            led_out( 0x0 );
            led_m_set( RUN );
            pattern = 11;
            cnt1 = 0;
            break;
        }
        if( cnt1 < 100 ) {
            led_out( 0x1 );
        } else if( cnt1 < 200 ) {
            led_out( 0x2 );
        } else {
            cnt1 = 0;
        }
        break;

    case 11:
        /* normal trace */
        if( RightCrankCheck( 85 ) ) {    /* Right Crank Check */
            pattern = 31;
            break;
        }
        if( RightLaneChangeCheck( 85 ) ) {    /* Right Lane Change Check */
            pattern = 51;
            break;
        }
        switch( (sensor_inp()&0x0f) ) {
            case 0x00:
                handle( 0 );
                motor( 100, 100 );
                break;
            case 0x02:
                handle( 3 );
                motor( 100, diff(100) );
                break;
            case 0x03:
                handle( 12 );
                motor( 100, diff(100) );
                break;
            case 0x01:
                handle( 20 );
                motor( 100, diff(100) );
                pattern = 12;
                break;
            case 0x04:
                handle( -3 );
                motor( diff(100), 100 );
                break;
            case 0x0c:
                handle( -12 );
                motor( diff(100), 100 );
                break;
            case 0x08:
                handle( -20 );
                motor( diff(100), 100 );
                pattern = 13;
                break;
            default:
                break;
        }
        break;

    case 12:
        /* Left side */
        if( (sensor_inp()&0x02) == 0x02 ) {
            pattern = 11;
            break;
        }
        switch( (sensor_inp()&0x0f) ) {
            case 0x01:
                handle( 20 );
                motor( 100, diff(100) );
                break;
            case 0x00:
            case 0x08:
            case 0x0c:
                handle( 22 );
                motor( 100, diff(100) );
                break;
            default:
                break;
        }
        break;

    case 13:
        /* right side */
        if( (sensor_inp()&0x04) == 0x04 ) {
            pattern = 11;
        }
        switch( (sensor_inp()&0x0f) ) {
            case 0x08:
                handle( -20 );
                motor( diff(100), 100 );
                break;
            case 0x00:
            case 0x01:
            case 0x03:
                handle( -22 );
                motor( diff(100), 100 );
                break;
            default:
                break;
        }
        break;

    case 31:
        /* Right crank processing at 1st process */
        led_m_set( CRANK );
        led_out( 0x1 );
        handle( 0 );
        motor2( 0 ,0 );
        pattern = 32;
        cnt1 = 0;
        break;

    case 32:
        /* Right crank processing at 2nd process */
        if( cnt1 > 300 ) {
            pattern = 33;
            cnt1 = 0;
        }
        break;

    case 33:
        /* Right crank processing at 3rd process */
        if( ( center_inp() == 0 ) && ( (sensor_inp()&0x0f) == 0x00 ) ) {
            handle( 41 );
            motor2( 50 ,10 );
            pattern = 34;
            cnt1 = 0;
            break;
        }
        switch( (sensor_inp()&0x0f) ) {
            case 0x00:
                /* Center -> straight */
                handle( 0 );
                motor2( 30 ,30 );
                break;
            case 0x02:
                /* Left of center -> turn to right */
                handle( 5 );
                motor2( 30 ,diff(30) );
                break;
            case 0x04:
                /* Right of center -> turn to left */
                handle( -5 );
                motor2( diff(30) ,30 );
                break;
            default:
                break;
        }
        break;

    case 34:
        /* Right crank clearing processing - wait until stable */
        if( cnt1 > 800 ) {
            pattern = 35;
            cnt1 = 0;
        }
        break;

    case 35:
        /* Right crank clearing processing - check end of turn */
        if( (sensor_inp()&0x02) == 0x02 ) {
            led_out( 0x0 );
            led_m_set( RUN );
            pattern = 11;
            cnt1 = 0;
        }
        break;

    case 51:
        /* Right lane change processing at 1st process */
        led_m_set( LCHANGE );
        led_out( 0x01 );
        handle( 0 );
        motor2( 0 ,0 );
        pattern = 52;
        cnt1 = 0;
        break;

    case 52:
        /* Right lane change processing at 2nd process */
        if( cnt1 > 300 ) {
            pattern = 53;
            cnt1 = 0;
            break;
        }
        break;

    case 53:
        /* Right lane change processing at 3rd process */
        if( ( center_inp() == 0 ) && ( (sensor_inp()&0x0f) == 0x00 ) ) {
            handle( 20 );
            motor2( 30 ,diff(30) );
            pattern = 54;
            cnt1 = 0;
            break;
        }
        switch( (sensor_inp()&0x0f) ) {
            case 0x00:
                /* Center -> straight */
                handle( 0 );
                motor2( 30 ,30 );
                break;
            case 0x02:
                /* Left of center -> turn to right */
                handle( 5 );
                motor2( 30 ,diff(30) );
                break;
            case 0x04:
                /* Right of center -> turn to left */
                handle( -5 );
                motor2( diff(30) ,30 );
                break;
            default:
                break;
        }
        break;

    case 54:
        /* Right lane change clearing processing - wait until stable */
        if( cnt1 > 800 ){
            pattern = 55;
            cnt1 = 0;
        }
        break;

    case 55:
        /* Right lane change end check */
        if( (sensor_inp()&0x04) == 0x04 ) {
            led_m_set( RUN );
            led_out( 0x0 );
            pattern = 11;
            cnt1 = 0;
        }
        break;

    default:
        break;
    }
    }
}

//******************************************************************//
// Initialize functions
//*******************************************************************/
//------------------------------------------------------------------//
//Initialize MTU2 PWM functions
//------------------------------------------------------------------//
//MTU2_3, MTU2_4
//Reset-Synchronized PWM mode
//TIOC4A(P4_4) :Left-motor
//TIOC4B(P4_5) :Right-motor
//------------------------------------------------------------------//
void init_MTU2_PWM_Motor( void )
{
    /* Port setting for S/W I/O Control */
    /* alternative mode     */

    /* MTU2_4 (P4_4)(P4_5)  */
    GPIOPBDC4   = 0x0000;               /* Bidirection mode disabled*/
    GPIOPFCAE4 &= 0xffcf;               /* The alternative function of a pin */
    GPIOPFCE4  |= 0x0030;               /* The alternative function of a pin */
    GPIOPFC4   &= 0xffcf;               /* The alternative function of a pin */
                                        /* 2nd altemative function/output    */
    GPIOP4     &= 0xffcf;               /*                          */
    GPIOPM4    &= 0xffcf;               /* p4_4,P4_5:output         */
    GPIOPMC4   |= 0x0030;               /* P4_4,P4_5:double         */

    /* Module stop 33(MTU2) canceling */
    CPGSTBCR3  &= 0xf7;

    /* MTU2_3 and MTU2_4 (Motor PWM) */
    MTU2TCR_3   = 0x20;                 /* TCNT Clear(TGRA), P0φ/1  */
    MTU2TOCR1   = 0x04;                 /*                          */
    MTU2TOCR2   = 0x40;                 /* N L>H  P H>L             */
    MTU2TMDR_3  = 0x38;                 /* Buff:ON Reset-Synchronized PWM mode */
    MTU2TMDR_4  = 0x30;                 /* Buff:ON                  */
    MTU2TOER    = 0xc6;                 /* TIOC3B,4A,4B enabled output */
    MTU2TCNT_3  = MTU2TCNT_4 = 0;       /* TCNT3,TCNT4 Set 0        */
    MTU2TGRA_3  = MTU2TGRC_3 = MOTOR_PWM_CYCLE;
                                        /* PWM-Cycle(1ms)           */
    MTU2TGRA_4  = MTU2TGRC_4 = 0;       /* Left-motor(P4_4)         */
    MTU2TGRB_4  = MTU2TGRD_4 = 0;       /* Right-motor(P4_5)        */
    MTU2TSTR   |= 0x40;                 /* TCNT_4 Start             */
}

//------------------------------------------------------------------//
//Initialize MTU2 PWM functions
//------------------------------------------------------------------//
//MTU2_0
//PWM mode 1
//TIOC0A(P4_0) :Servo-motor
//------------------------------------------------------------------//
void init_MTU2_PWM_Servo( void )
{
    /* Port setting for S/W I/O Control */
    /* alternative mode     */

    /* MTU2_0 (P4_0)        */
    GPIOPBDC4   = 0x0000;               /* Bidirection mode disabled*/
    GPIOPFCAE4 &= 0xfffe;               /* The alternative function of a pin */
    GPIOPFCE4  &= 0xfffe;               /* The alternative function of a pin */
    GPIOPFC4   |= 0x0001;               /* The alternative function of a pin */
                                        /* 2nd alternative function/output   */
    GPIOP4     &= 0xfffe;               /*                          */
    GPIOPM4    &= 0xfffe;               /* p4_0:output              */
    GPIOPMC4   |= 0x0001;               /* P4_0:double              */

    /* Module stop 33(MTU2) canceling */
    CPGSTBCR3  &= 0xf7;

    /* MTU2_0 (Motor PWM) */
    MTU2TCR_0   = 0x22;                 /* TCNT Clear(TGRA), P0φ/16 */
    MTU2TIORH_0 = 0x52;                 /* TGRA L>H, TGRB H>L       */
    MTU2TMDR_0  = 0x32;                 /* TGRC and TGRD = Buff-mode*/
                                        /* PWM-mode1                */
    MTU2TCNT_0  = 0;                    /* TCNT0 Set 0              */
    MTU2TGRA_0  = MTU2TGRC_0 = SERVO_PWM_CYCLE;
                                        /* PWM-Cycle(16ms)          */
    MTU2TGRB_0  = MTU2TGRD_0 = 0;       /* Servo-motor(P4_0)        */
    MTU2TSTR   |= 0x01;                 /* TCNT_0 Start             */
}

//------------------------------------------------------------------//
//Initialize Camera function
//------------------------------------------------------------------//
void init_Camera( void )
{
    /* NTSC-Video */
    DisplayBase::graphics_error_t error;

    /* Graphics initialization process */
    error = Display.Graphics_init(NULL);
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }

    error = Display.Graphics_Video_init( DisplayBase::INPUT_SEL_VDEC, NULL);
    if( error != DisplayBase::GRAPHICS_OK ) {
        while(1);
    }

    /* Interrupt callback function setting (Vsync signal input to scaler 0) */
    error = Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_VI_VSYNC, 0, IntCallbackFunc_Vsync);
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }

    /* Video capture setting (progressive form fixed) */
    error = Display.Video_Write_Setting(
                VIDEO_INPUT_CH,
                DisplayBase::COL_SYS_NTSC_358,
                write_buff_addr,
                VIDEO_BUFFER_STRIDE,
                DisplayBase::VIDEO_FORMAT_YCBCR422,
                DisplayBase::WR_RD_WRSWA_32_16BIT,
                PIXEL_VW,
                PIXEL_HW
            );
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }

    /* Interrupt callback function setting (Field end signal for recording function in scaler 0) */
    error = Display.Graphics_Irq_Handler_Set(VIDEO_INT_TYPE, 0, IntCallbackFunc_Vfield);
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }

    /* Video write process start */
    error = Display.Video_Start (VIDEO_INPUT_CH);
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }

    /* Video write process stop */
    error = Display.Video_Stop (VIDEO_INPUT_CH);
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }

    /* Video write process start */
    error = Display.Video_Start (VIDEO_INPUT_CH);
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }

    /* Wait vsync to update resister */
    WaitVsync(1);

    /* Wait 2 Vfield(Top or bottom field) */
    WaitVfield(2);
}

//------------------------------------------------------------------//
//ChangeFrameBuffer function
//------------------------------------------------------------------//
void ChangeFrameBuffer( void )
{
    /* NTSC-Video */
    DisplayBase::graphics_error_t error;

    /* Change write buffer */
    if (write_buff_addr == FrameBuffer_Video_A) {
        write_buff_addr = FrameBuffer_Video_B;
        save_buff_addr  = FrameBuffer_Video_A;
    } else {
        write_buff_addr = FrameBuffer_Video_A;
        save_buff_addr  = FrameBuffer_Video_B;
    }
    error = Display.Video_Write_Change(
                VIDEO_INPUT_CH,
                write_buff_addr,
                VIDEO_BUFFER_STRIDE);
    if (error != DisplayBase::GRAPHICS_OK) {
        pc.printf("Line %d, error %d\n", __LINE__, error);
        while (1);
    }
}

//------------------------------------------------------------------//
// @brief       Interrupt callback function
// @param[in]   int_type    : VDC5 interrupt type
// @retval      None
//------------------------------------------------------------------//
static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type)
{
    if (vfield_count > 0) {
        vfield_count--;
    }
    /* top or bottom (Change) */
    if( vfield_count2 == 0 )  vfield_count2 = 1;
    else                      vfield_count2 = 0;
    led_m_user( vfield_count2 );
}

//------------------------------------------------------------------//
// @brief       Wait for the specified number of times Vsync occurs
// @param[in]   wait_count          : Wait count
// @retval      None
//------------------------------------------------------------------//
static void WaitVfield(const int32_t wait_count)
{
    vfield_count = wait_count;
    while (vfield_count > 0) {
        /* Do nothing */
    }
}

//------------------------------------------------------------------//
// @brief       Interrupt callback function for Vsync interruption
// @param[in]   int_type    : VDC5 interrupt type
// @retval      None
//------------------------------------------------------------------//
static void IntCallbackFunc_Vsync(DisplayBase::int_type_t int_type)
{
    if (vsync_count > 0) {
        vsync_count--;
    }
}

//------------------------------------------------------------------//
// @brief       Wait for the specified number of times Vsync occurs
// @param[in]   wait_count          : Wait count
// @retval      None
//------------------------------------------------------------------//
static void WaitVsync(const int32_t wait_count)
{
    vsync_count = wait_count;
    while (vsync_count > 0) {
        /* Do nothing */
    }
}

//------------------------------------------------------------------//
// Interrupt function( intTimer )
//------------------------------------------------------------------//
void intTimer( void )
{
    static int      counter = 0;    /* Only variable for image process */

    cnt0++;
    cnt1++;

    /* field check */
    if( vfield_count2 != vfield_count2_buff ) {
        vfield_count2_buff = vfield_count2;
        counter = 0;
    }

    /* Top field / bottom field */
    switch( counter++ ) {
    case 0:
        ImageCopy( write_buff_addr, PIXEL_HW, PIXEL_VW, ImageData_A, vfield_count2 );
        break;
    case 1:
        ImageCopy( write_buff_addr, PIXEL_HW, PIXEL_VW, ImageData_A, vfield_count2 );
        break;
    case 2:
        Extraction_Brightness( ImageData_A, PIXEL_HW, PIXEL_VW, ImageData_B, vfield_count2 );
        break;
    case 3:
        Extraction_Brightness( ImageData_A, PIXEL_HW, PIXEL_VW, ImageData_B, vfield_count2 );
        break;
    case 4:
        ImageReduction( ImageData_B, PIXEL_HW, PIXEL_VW, ImageComp_B, Rate );
        break;
    case 5:
        ImageReduction( ImageData_B, PIXEL_HW, PIXEL_VW, ImageComp_B, Rate );
        break;
    case 6:
        Binarization( ImageComp_B, (PIXEL_HW * Rate), (PIXEL_VW * Rate), ImageBinary, threshold_buff );
        if( !initFlag ) SenVal1 = sensor_process( ImageBinary, (PIXEL_HW * Rate), (PIXEL_VW * Rate), Sen1Px, 12 );
        break;
    case 7:
        if( !initFlag ) PatternMatching_process( ImageBinary, (PIXEL_HW * Rate), (PIXEL_VW * Rate), &RightCrank, 2, 10, 2, 8 );
        break;
    case 8:
        if( !initFlag ) PatternMatching_process( ImageBinary, (PIXEL_HW * Rate), (PIXEL_VW * Rate), &RightLaneChange, 4, 6, 1, 3 );
        break;
    default:
        break;
    }

    /* LED(rgb) on the GR-peach board */
    led_m_process();
}

//******************************************************************//
// functions ( on GR-PEACH board )
//*******************************************************************/
//------------------------------------------------------------------//
//led_rgb Function
//------------------------------------------------------------------//
void led_rgb(int led)
{
    LED_R = led & 0x1;
    LED_G = (led >> 1 ) & 0x1;
    LED_B = (led >> 2 ) & 0x1;
}

//------------------------------------------------------------------//
//user_button_get Function
//------------------------------------------------------------------//
unsigned char user_button_get( void )
{
    return (~user_botton) & 0x1;        /* Read ports with switches */
}

//------------------------------------------------------------------//
//led_m_user Function
//------------------------------------------------------------------//
void led_m_user( int led )
{
    USER_LED = led & 0x01;
}

//------------------------------------------------------------------//
//led_m_set Function
//------------------------------------------------------------------//
void led_m_set( int set )
{
    led_pattern = set;
}

//------------------------------------------------------------------//
//led_m_process Function for only interrupt
//------------------------------------------------------------------//
void led_m_process( void )
{
    int                     led_color;
    int                     onTime;
    int                     offTime;
    static unsigned long    cnt_led_m;

    switch( led_pattern ) {
    case RUN:
        led_color = LED_GREEN;
        onTime    = 500;
        offTime   = 500;
        break;
    case STOP:
        led_color = LED_RED;
        onTime    = 500;
        offTime   = 0;
        break;
    case ERROR:
        led_color = LED_RED;
        onTime    = 100;
        offTime   = 100;
        break;
    case DEBUG:
        led_color = LED_BLUE;
        onTime    = 50;
        offTime   = 50;
        break;
    case CRANK:
        led_color = LED_YELLOW;
        onTime    = 500;
        offTime   = 500;
        break;
    case LCHANGE:
        led_color = LED_BLUE;
        onTime    = 500;
        offTime   = 500;
        break;
    default:
        led_color = LED_OFF;
        onTime    = 500;
        offTime   = 500;
        break;
    }

    cnt_led_m++;

    /* Display */
    if( cnt_led_m < onTime ) led_rgb( led_color );
    else if( cnt_led_m < ( onTime + offTime ) ) led_rgb( LED_OFF );
    else cnt_led_m = 0;
}

//******************************************************************//
// functions ( on Motor drive board )
//*******************************************************************/
//------------------------------------------------------------------//
//led_out Function
//------------------------------------------------------------------//
void led_out(int led)
{
    led = ~led;
    LED_3 = led & 0x1;
    LED_2 = ( led >> 1 ) & 0x1;
}

//------------------------------------------------------------------//
//pushsw_get Function
//------------------------------------------------------------------//
unsigned char pushsw_get( void )
{
    return (~push_sw) & 0x1;            /* Read ports with switches */
}

//------------------------------------------------------------------//
//motor speed control(PWM)
//Arguments: motor:-100 to 100
//Here, 0 is stop, 100 is forward, -100 is reverse
//------------------------------------------------------------------//
void motor( int accele_l, int accele_r )
{
    int    sw_data;

    sw_data = dipsw_get() + 5;
    accele_l = ( accele_l * sw_data ) / 20;
    accele_r = ( accele_r * sw_data ) / 20;

    /* Left Motor Control */
    if( accele_l >= 0 ) {
        /* forward */
        Left_motor_signal = 0;
        MTU2TGRC_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * accele_l / 100;
    } else {
        /* reverse */
        Left_motor_signal = 1;
        MTU2TGRC_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * ( -accele_l ) / 100;
    }

    /* Right Motor Control */
    if( accele_r >= 0 ) {
        /* forward */
        Right_motor_signal = 0;
        MTU2TGRD_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * accele_r / 100;
    } else {
        /* reverse */
        Right_motor_signal = 1;
        MTU2TGRD_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * ( -accele_r ) / 100;
    }
}

//------------------------------------------------------------------//
//motor speed control(PWM)
//Arguments: motor:-100 to 100
//Here, 0 is stop, 100 is forward, -100 is reverse
//------------------------------------------------------------------//
void motor2( int accele_l, int accele_r )
{
    /* Left Motor Control */
    if( accele_l >= 0 ) {
        /* forward */
        Left_motor_signal = 0;
        MTU2TGRC_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * accele_l / 100;
    } else {
        /* reverse */
        Left_motor_signal = 1;
        MTU2TGRC_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * ( -accele_l ) / 100;
    }

    /* Right Motor Control */
    if( accele_r >= 0 ) {
        /* forward */
        Right_motor_signal = 0;
        MTU2TGRD_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * accele_r / 100;
    } else {
        /* reverse */
        Right_motor_signal = 1;
        MTU2TGRD_4 = (long)( MOTOR_PWM_CYCLE - 1 ) * ( -accele_r ) / 100;
    }
}

//------------------------------------------------------------------//
//handle Function
//------------------------------------------------------------------//
void handle( int angle )
{
    handle_buff = angle;
    /* When the servo move from left to right in reverse, replace "-" with "+" */
    MTU2TGRD_0 = SERVO_CENTER - angle * HANDLE_STEP;
}

//------------------------------------------------------------------//
//diff Function
//------------------------------------------------------------------//
int diff( int pwm )
{
    int i, ret;

    i  = handle_buff;
    if( i <  0 ) i = -i;
    if( i > 45 ) i = 45;
    ret = revolution_difference[i] * pwm / 100;

    return ret;
}

//******************************************************************//
// functions ( on Shield board )
//*******************************************************************/
//------------------------------------------------------------------//
//Dipsw get Function
//------------------------------------------------------------------//
unsigned char dipsw_get( void )
{
    return( dipsw.read() & 0x0f );
}

//******************************************************************//
// digital sensor functions
//*******************************************************************/
//------------------------------------------------------------------//
// init sensor Function
//------------------------------------------------------------------//
int init_sensor( unsigned char *BuffAddrIn, int HW, int VW, int Cx, int *SENPx, int Y )
{
    int X;
    int L1x, R1x;
    int i, error_cnt;

    //Left side
    for( X = Cx; X > 1; X-- ){
        if( BuffAddrIn[ ( Y * HW ) + ( X - 0 ) ] == 0 && BuffAddrIn[ ( Y * HW ) + ( X - 1 ) ] == 0 ) {
            L1x = X;
            break;
        }
    }
    //Right side
    for( X = Cx; X < ( HW - 1 ); X++ ){
        if( BuffAddrIn[ ( Y * HW ) + ( X + 0 ) ] == 0 && BuffAddrIn[ ( Y * HW ) + ( X + 1 ) ] == 0 ) {
            R1x = X;
            break;
        }
    }

    SENPx[ 4 ] = L1x + ( ( R1x - L1x ) / 2 );    // Center
    SENPx[ 2 ] = L1x;   // L1
    SENPx[ 1 ] = R1x;   // R1
    SENPx[ 3 ] = SENPx[ 2 ] - ( SENPx[ 4 ] - SENPx[ 2 ] );  //L2
    SENPx[ 0 ] = SENPx[ 1 ] + ( SENPx[ 1 ] - SENPx[ 4 ] );  //R2

    /* error check */
    error_cnt = 0;
    for( i = 0; i < 4; i++ ){
        if( SENPx[4] == SENPx[i] ) error_cnt += 1;
    }

//#define DEBUG_MODE
#ifdef DEBUG_MODE
    pc.printf( "L2=%2d, L1=%2d, Cx=%2d, R1=%2d, R2=%2d\n\r", SENPx[ 3 ], SENPx[ 2 ], SENPx[ 4 ], SENPx[ 1 ], SENPx[ 0 ] );
    if( error_cnt != 0 ) pc.printf( "init_sensor function Error %1d\n\r", error_cnt );
    else                 pc.printf( "init_sensor function complete\n\r" );
    pc.printf( "\n\r" );
#endif

    return error_cnt;
}

//------------------------------------------------------------------//
//sensor_process Function(Interrupt function)
//------------------------------------------------------------------//
unsigned char sensor_process( unsigned char *BuffAddrIn, int HW, int VW, int *SENPx, int Y )
{
    int sensor;
    int data;

    sensor  = 0x00;
    if( VW < Y ) {
        pc.printf( "sensor process function error\n\r" );
        return sensor;
    }

    data    = BuffAddrIn[ ( Y * HW ) + SENPx[ 4 ] ] & 0x01;
    sensor |= ( data << 4 ) & 0x10;
    data    = BuffAddrIn[ ( Y * HW ) + SENPx[ 3 ] ] & 0x01;
    sensor |= ( data << 3 ) & 0x08;
    data    = BuffAddrIn[ ( Y * HW ) + SENPx[ 2 ] ] & 0x01;
    sensor |= ( data << 2 ) & 0x04;
    data    = BuffAddrIn[ ( Y * HW ) + SENPx[ 1 ] ] & 0x01;
    sensor |= ( data << 1 ) & 0x02;
    sensor |= BuffAddrIn[ ( Y * HW ) + SENPx[ 0 ] ] & 0x01;

    sensor &= 0x1f;

    return sensor;
}

//------------------------------------------------------------------//
//sensor Function
//------------------------------------------------------------------//
unsigned char sensor_inp( void )
{
    return SenVal1 & 0x0f;
}

//------------------------------------------------------------------//
//sensor Function
//------------------------------------------------------------------//
unsigned char center_inp( void )
{
    return ( SenVal1 >> 4 ) & 0x01;
}

//------------------------------------------------------------------//
// RightCrank Check
// Return values: 0: no triangle mark, 1: Triangle mark
//------------------------------------------------------------------//
int RightCrankCheck( int percentage )
{
    int ret;

    ret = 0;
    if( RightCrank.p >= percentage ) {
        ret = 1;
    }

    return ret;
}

//------------------------------------------------------------------//
// RightLaneChange Check
// Return values: 0: no triangle mark, 1: Triangle mark
//------------------------------------------------------------------//
int RightLaneChangeCheck( int percentage )
{
    int ret;

    ret = 0;
    if( RightLaneChange.p >= percentage ) {
        ret = 1;
    }

    return ret;
}

//******************************************************************//
// Debug functions
//*******************************************************************/
//------------------------------------------------------------------//
//Image Data Output( for the Excel )
//------------------------------------------------------------------//
void ImageData_Serial_Out1( unsigned char *ImageData, int HW, int VW )
{
    int     Xp, Yp, inc;

    for( Yp = 0, inc = 0; Yp < VW; Yp++ ) {
        for( Xp = 0; Xp < HW; Xp++, inc++ ) {
            pc.printf( "%d,", ImageData[ inc ] );
        }
        pc.printf("\n\r");
    }
}

//------------------------------------------------------------------//
//Image Data Output2( for TeraTerm )
//------------------------------------------------------------------//
void ImageData_Serial_Out2( unsigned char *ImageData, int HW, int VW )
{
    int     Xp, Yp;
    int     i;

    for( Yp = 0; Yp < VW; Yp++ ) {
        for( Xp = 0; Xp < HW; Xp++ ) {
            pc.printf( "%d ", ImageData[Xp + (Yp * HW)] );
        }
        pc.printf( "\n\r" );
    }

    //Add display
    pc.printf( "\n\r" );
    pc.printf( "sensor_inp = 0x%02x\n\r", sensor_inp() );
    pc.printf( "center_inp = 0x%02x\n\r", center_inp() );
    pc.printf( "RightCrank      = %01d, = %3d%%, X = %2d, Y = %2d\n\r", RightCrankCheck(80), RightCrank.p, RightCrank.x, RightCrank.y );
    pc.printf( "RightLaneChange = %01d, = %3d%%, X = %2d, Y = %2d\n\r", RightLaneChangeCheck(80), RightLaneChange.p, RightLaneChange.x, RightLaneChange.y );
    pc.printf( "\n\r" );
    VW += 6;

    pc.printf( "Threshold Check ( please user button on GR-peach board )\n\r" );
    pc.printf( "\n\r" );
    VW += 2;

    if( user_button_get() ){
        pc.printf( "Please Threshold\n\r" );
        pc.printf( " = " );
        pc.scanf( "%d", &i );
        pc.printf( "\n\r" );
        threshold_buff = i;
        VW += 2;
    }

    pc.printf( "\033[%dA" , VW );
}

//------------------------------------------------------------------//
//Image Data Output3( for TeraTerm )
//------------------------------------------------------------------//
void ImageData_Serial_Out3( unsigned char *ImageData, int HW, int VW, int color_pattern )
{
    int X, Y;
    int Px, Py;
    int HW_T;//HW Twice
    int value;

    HW_T = HW + HW;

    /* Camera module test process 2 */
    pc.printf( "//,X-Size,Y-Size" );
    pc.printf( "\n\r" );
    pc.printf( "#SIZE,%3d,%3d", HW, VW );
    pc.printf( "\n\r" );
    pc.printf( "//,X-Point,Y-Point" );
    pc.printf( "\n\r" );

    switch( color_pattern ) {
    case COLOR:
        //YCBCR_422 Color
        for( Py = 0, Y = 0; Py < VW; Py+=1, Y++ ){
            for( Px = 0, X = 0; Px < HW_T; Px+=4, X+=2 ){
                pc.printf( "#YCbCr," );
          /*Xp*/pc.printf( "%d,", X);
          /*Yp*/pc.printf( "%d,", Y);
          /*Y0*/pc.printf( "%d,", ImageData[ ( Px + 0 ) + ( HW_T * Py ) ] );//6
          /*Cb*/pc.printf( "%d,", ImageData[ ( Px + 1 ) + ( HW_T * Py ) ] );//5
          /*Cr*/pc.printf( "%d,", ImageData[ ( Px + 3 ) + ( HW_T * Py ) ] );//7
                pc.printf( "\n\r" );

                pc.printf( "#YCbCr," );
          /*Xp*/pc.printf( "%d,", X+1);
          /*Yp*/pc.printf( "%d,", Y);
          /*Y1*/pc.printf( "%d,", ImageData[ ( Px + 2 ) + ( HW_T * Py ) ] );//4
          /*Cb*/pc.printf( "%d,", ImageData[ ( Px + 1 ) + ( HW_T * Py ) ] );//5
          /*Cr*/pc.printf( "%d,", ImageData[ ( Px + 3 ) + ( HW_T * Py ) ] );//7
                pc.printf( "\n\r" );
            }
        }
        break;
    case GREY_SCALE:
        //YCBCR_422 GreyScale
        for( Y = 0; Y < VW; Y++ ){
            for( X = 0; X < HW; X+=2 ){
                pc.printf( "#YCbCr," );
          /*Xp*/pc.printf( "%d,", X);
          /*Yp*/pc.printf( "%d,", Y);
          /*Y0*/pc.printf( "%d,", ImageData[ ( Y * HW ) + ( X + 0 ) ] );//6
          /*Cb*/pc.printf( "%d,", 128);//5
          /*Cr*/pc.printf( "%d,", 128);//7
                pc.printf( "\n\r" );

                pc.printf( "#YCbCr," );
          /*Xp*/pc.printf( "%d,", X+1);
          /*Yp*/pc.printf( "%d,", Y);
          /*Y1*/pc.printf( "%d,", ImageData[ ( Y * HW ) + ( X + 1 ) ] );//4
          /*Cb*/pc.printf( "%d,", 128);//5
          /*Cr*/pc.printf( "%d,", 128);//7
                pc.printf( "\n\r" );
            }
        }
        break;
    case BINARY:
        //YCBCR_422 Binary
        for( Y = 0; Y < VW; Y++ ){
            for( X = 0; X < HW; X+=2 ){
                pc.printf( "#YCbCr," );
          /*Xp*/pc.printf( "%d,", X);
          /*Yp*/pc.printf( "%d,", Y);
                value = ImageData[ ( Y * HW ) + ( X + 0 ) ];
                if( value ) value = 255;
                else        value = 0;
          /*Y0*/pc.printf( "%d,", value );//6
          /*Cb*/pc.printf( "%d,", 128);//5
          /*Cr*/pc.printf( "%d,", 128);//7
                pc.printf( "\n\r" );

                pc.printf( "#YCbCr," );
          /*Xp*/pc.printf( "%d,", X+1);
          /*Yp*/pc.printf( "%d,", Y);
                value = ImageData[ ( Y * HW ) + ( X + 1 ) ];
                if( value ) value = 255;
                else        value = 0;
          /*Y1*/pc.printf( "%d,", value );//4
          /*Cb*/pc.printf( "%d,", 128);//5
          /*Cr*/pc.printf( "%d,", 128);//7
                pc.printf( "\n\r" );
            }
        }
        break;
    default:
        break;
    }
    pc.printf( "End\n\r" );
}

//------------------------------------------------------------------//
// End of file
//------------------------------------------------------------------//