This program was added the mark detection program on the trace program.
Dependencies: GR-PEACH_video mbed
main.cpp
- Committer:
- ssuzukito
- Date:
- 2016-03-02
- Revision:
- 1:551e0f0cd55d
- Parent:
- 0:5db2664ff378
File content as of revision 1:551e0f0cd55d:
//------------------------------------------------------------------//
//Supported MCU: RZ/A1H
//File Contents: Trace program 2 (Mark detection) by image processing
// (GR-PEACH version on the Micon Car)
//Version number: Ver.1.01
//Date: 2016.02.23
//Copyright: Renesas Electronics Corporation
//------------------------------------------------------------------//
//This program supports the following boards:
//* GR-PEACH(E version)
//* Motor drive board Ver.5
//* Camera module (SC-310)
//Include
//------------------------------------------------------------------//
#include "mbed.h"
#include "math.h"
#include "iodefine.h"
#include "DisplayBace.h"
//Define
//------------------------------------------------------------------//
//Motor PWM cycle
#define MOTOR_PWM_CYCLE 33332 /* Motor PWM period */
/* 1ms P0φ/1 = 0.03us */
//Motor speed
#define MAX_SPEED 30 /* motor() set: 0 to 100 */
//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 */
//Image sensor
#define IMAGE_LINE 160 /* Y Line No */
#define IM_GAP_SET 48 /* 160pix - 112pix = 48 */
//Handle
#define ANLOG_STEP 60 /* */
//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
//Status
#define RUN 0x00
#define SENSOR 0x01
#define MARK 0x02
#define STOP 0x03
#define ERROR 0xff
//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 (320u) /* QVGA */
#define PIXEL_VW (240u) /* QVGA */
#define VIDEO_BUFFER_STRIDE (((PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u)
#define VIDEO_BUFFER_HEIGHT (PIXEL_VW)
//Constructor
//------------------------------------------------------------------//
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 */
DigitalIn user_botton(P6_0); /* SW1 on the GR-PEACH board */
DigitalOut Left_motor_signal(P4_6); /* Used by motor fanction */
DigitalOut Right_motor_signal(P4_7); /* Used by motor fanction */
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
//------------------------------------------------------------------//
void init_MTU2_PWM_Motor( void ); /* Initialize PWM functions */
void init_MTU2_PWM_Servo( void ); /* Initialize PWM functions */
void intTimer( void ); /* Interrupt fanction */
void led_rgb(int led);
unsigned int user_button_get( void );
void led_status_process( void ); /* Function for only interrupt */
void led_status_set( int set );
void led_out(int led);
unsigned int pushsw_get( void );
void motor( int accele_l, int accele_r );
void handle( int angle );
int diff( int pwm );
void ServoControl_process( void );
//Prototype(NTSC-video)
//------------------------------------------------------------------//
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(Display Debug)
//------------------------------------------------------------------//
void ImageData_Serial_Out( unsigned char *Data_Y, int Width );
void ImageData_Serial_Out2( unsigned char *Data_Y, int Width );
void ImageData_Serial_Out3( void );
//Prototype(Trace by Image Processing)
//------------------------------------------------------------------//
void change_framebuffer_process( void );
int center_line_corrective( void );
void digital_sensor_corrective( void );
void image_SensorAnalog_process( int timer33 );
int image_sensorAnalog_get( void );
unsigned char image_digital_sensor( void );
//Prototype(Mark detection)
//------------------------------------------------------------------//
void Image_Extraction( unsigned char *Data_Y );
void Image_part_Extraction( unsigned char *Binary, int Width, int Xpix, int Ypix, unsigned char *Data_B, int x_size, int y_size );
void Image_Compression( unsigned char *Data_Y, int Data_W , unsigned char *Comp_Y, int Comp_W );
void Image_Compression2( unsigned char *Data_Y, int Data_W , unsigned char *Comp_Y, int Comp_M );
void Binarization_process( unsigned char *Comp_Y, unsigned char *Binary, long items );
double Standard_Deviation( unsigned char *data, double *Devi, int items );
double Covariance( double *Devi_A, double *Devi_B, int items );
int Judgement_ImageMatching( double covari, double SDevi_A, double SDevi_B );
//Globle
//------------------------------------------------------------------//
volatile unsigned long cnt0; /* Used by timer function */
volatile unsigned long cnt1; /* Used within main */
volatile int pattern; /* Pattern numbers */
volatile int status_set; /* Status */
volatile int handle_buff;
volatile int iServo;
const int revolution_difference[] = {
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 };
/* Trace by image processing */
volatile int im_offset_x;
volatile int digital_sensor_threshold;
volatile int sensor_x[5];
volatile int sensor_mode;
volatile int Left_sensor;
volatile int Right_sensor;
volatile int white;
volatile int black;
/* Mark detection */
unsigned char ImageData[320*240];
unsigned char ImageComp[160*120];
unsigned char ImageBinary[160*120];
double TempDevi_A[15];
unsigned char TempBinary_A[15] = {0,1,1,1,0,
0,0,1,0,0,
0,0,0,0,0};
double NowDevi[15];
unsigned char NowImageBinary[15];
volatile double retDevi_A;
volatile double retDevi_B;
volatile double retCovari;
volatile int retJudgeIM;
volatile int retJudgeIM_Max;
int X_buff, Y_buff;
//Globle(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!;
static volatile int32_t vsync_count;
static volatile int32_t vfield_count;
uint8_t * write_buff_addr = FrameBuffer_Video_A;
uint8_t * save_buff_addr = FrameBuffer_Video_B;
//Main
//------------------------------------------------------------------//
int main( void )
{
int i;
/* NTSC-Video */
DisplayBase::graphics_error_t error;
/* Create DisplayBase object */
DisplayBase Display;
/* Graphics initialization process */
error = Display.Graphics_init(NULL);
if (error != DisplayBase::GRAPHICS_OK) {
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) {
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) {
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) {
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) {
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) {
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) {
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);
/* Initialize MCU functions */
init_MTU2_PWM_Motor();
init_MTU2_PWM_Servo();
interrput.attach(&intTimer, 0.001);
pc.baud(230400);
/* Initialize Micon Car state */
led_out( 0x0 );
handle( 0 );
motor( 0, 0 );
/* wait to stabilize NTSC signal (about 170ms) */
wait(0.2);
led_status_set( SENSOR );
while(1) {
sensor_mode = 1;
i = center_line_corrective();
pc.printf( "x = %04d, cnt1 = %03d iret = %01d \r", im_offset_x, cnt1, i );
if( i == -1 ) {
/* End process */
pattern = 99;
break;
} else if ( i == 1 ) {
sensor_mode = 0;
pattern = 0;
led_status_set( RUN );
break;
}
}
pc.printf( "\n\r" );
digital_sensor_corrective();
pc.printf( "B = %04d, W = %04d \n\r", black, white );
pc.printf( "\n\r" );
pc.printf( "threshold = %03d \n\r", digital_sensor_threshold );
pc.printf( "\n\r" );
pc.printf( "\n\r" );
pc.printf( "image_sensor_value\n\r" );
while(1) {
i = image_digital_sensor();
pc.printf( "= %05d, = 0x%02x, = %03d J= %3d%% X=%2d Y=%2d DIGI=%x\r",
image_sensorAnalog_get(), i, handle_buff, retJudgeIM_Max, X_buff, Y_buff, image_digital_sensor() );
switch( pattern ) {
/*****************************************************************
About patern
0:wait for switch input
1:check if start bar is open
11:normal trace
*****************************************************************/
case 0:
/* wait for switch input */
handle( iServo );
if( pushsw_get() ) {
led_out( 0x0 );
led_status_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 */
handle( iServo );
if( retJudgeIM_Max >= 85 ) {
pattern = 90;
break;
}
if( handle_buff > 5 ) {
motor( 100, diff(100) );
} else if( handle_buff < -5 ) {
motor( diff(100), 100 );
} else {
motor( 100, 100 );
}
break;
case 90:
led_status_set( MARK );
motor( 0, 0 );
break;
case 99:
led_status_set( ERROR );
motor( 0, 0 );
break;
default:
break;
}
}
}
//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 Contorol */
/* 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 */
/* Mosule 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 Contorol */
/* 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 */
/* Mosule 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 */
}
//Interrupt Timer
//------------------------------------------------------------------//
void intTimer( void )
{
int x, y;
static int counter = 0;
cnt0++;
cnt1++;
/* Trace by image processing */
image_SensorAnalog_process( counter );
ServoControl_process();
switch( counter++ ) {
case 0:
change_framebuffer_process();
break;
case 1:
Image_Extraction( ImageData );
break;
case 2:
Image_Extraction( ImageData );
break;
case 3:
Image_Extraction( ImageData );
break;
case 4:
Image_Extraction( ImageData );
break;
case 5:
Image_Extraction( ImageData );
break;
case 6:
Image_Extraction( ImageData );
break;
case 7:
Image_Extraction( ImageData );
break;
case 8:
Image_Extraction( ImageData );
break;
case 9:
Image_Compression2( ImageData, 320, ImageComp, 16 );
break;
case 10:
Image_Compression2( ImageData, 320, ImageComp, 16 );
break;
case 11:
Binarization_process( ImageComp, ImageBinary, 20*15 );
break;
case 12:
retDevi_A = Standard_Deviation( TempBinary_A, TempDevi_A, 15 );
break;
case 13:
retJudgeIM_Max = 0;
for( y = 0; y <= 12; y++ ) {
for( x = 0; x <= 15; x++ ) {
Image_part_Extraction( ImageBinary, 20, x, y, NowImageBinary, 5, 3 );
retDevi_B = Standard_Deviation( NowImageBinary, NowDevi, 15 );
retCovari = Covariance( TempDevi_A, NowDevi, 15 );
retJudgeIM = 0;
retJudgeIM = Judgement_ImageMatching( retCovari, retDevi_A, retDevi_B );
if( 100 >= retJudgeIM && retJudgeIM > retJudgeIM_Max ) {
X_buff = x;
Y_buff = y;
retJudgeIM_Max = retJudgeIM;
}
}
}
break;
case 33:
counter = 0;
break;
default:
break;
}
led_status_process();
}
//LED_RGB(on GR-PEACH board)
//------------------------------------------------------------------//
void led_rgb(int led)
{
LED_R = led & 0x1;
LED_G = (led >> 1 ) & 0x1;
LED_B = (led >> 2 ) & 0x1;
}
//user_button_get(on GR-PEACH board)
//------------------------------------------------------------------//
unsigned int user_button_get( void )
{
return (~user_botton) & 0x1; /* Read ports with switches */
}
//LED_Status(on GR-PEACH board) Function for only interrupt
//------------------------------------------------------------------//
void led_status_process( void )
{
static unsigned long led_timer;
int led_set;
int on_time;
int off_time;
/* setting */
switch( status_set ){
case RUN:
led_set = LED_GREEN;
on_time = 500;
off_time = 500;
break;
case SENSOR:
led_set = LED_BLUE;
on_time = 50;
off_time = 50;
break;
case MARK:
led_set = LED_RED;
on_time = 250;
off_time = 250;
break;
case STOP:
led_set = LED_RED;
on_time = 1;
off_time = 0;
break;
case ERROR:
led_set = LED_RED;
on_time = 50;
off_time = 50;
break;
default:
led_set = LED_OFF;
on_time = 0;
off_time = 1;
break;
}
/* Display */
led_timer++;
if( led_timer < on_time ) led_rgb( led_set );
else if( led_timer < ( on_time + off_time ) ) led_rgb( LED_OFF );
else led_timer = 0;
}
//LED_Status(on GR-PEACH board) Function for only interrupt
//------------------------------------------------------------------//
void led_status_set( int set )
{
status_set = set;
}
//led_out(on Motor drive board)
//------------------------------------------------------------------//
void led_out(int led)
{
led = ~led;
LED_3 = led & 0x1;
LED_2 = ( led >> 1 ) & 0x1;
}
//pushsw_get(on Motor drive board)
//------------------------------------------------------------------//
unsigned int 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 )
{
accele_l = ( accele_l * MAX_SPEED ) / 100;
accele_r = ( accele_r * MAX_SPEED ) / 100;
/* 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 fanction
//------------------------------------------------------------------//
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;
}
//Deff fanction
//------------------------------------------------------------------//
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;
}
//ServoControl_process
//------------------------------------------------------------------//
void ServoControl_process( void )
{
static int iSensorPattern = 0;
/* -3° ~ +3° */
iServo = image_sensorAnalog_get() / ANLOG_STEP;
if( !sensor_mode ) {
switch( iSensorPattern ) {
case 0:
switch( image_digital_sensor()&0x0f ) {
case 0x03:
iServo = 14;
break;
case 0x01:
iServo = 20;
iSensorPattern = 11;
break;
case 0x0c:
iServo = -14;
break;
case 0x08:
iServo = -20;
iSensorPattern = 12;
break;
default:
break;
}
break;
case 11:
/* Left side */
iServo = 23;
if( (image_digital_sensor()&0x0f) == 0x03 ) {
iSensorPattern = 0;
}
break;
case 12:
/* right side */
iServo = -23;
if( (image_digital_sensor()&0x0f) == 0x0c ) {
iSensorPattern = 0;
}
break;
}
}
}
//Image Data Output( for the Excel )
//------------------------------------------------------------------//
void ImageData_Serial_Out( unsigned char *Data_Y, int Width )
{
int Xp, Yp, inc, Height;
Height = (Width / (double)4) * 3;
for( Yp = 0, inc = 0; Yp < Height; Yp++ ) {
for( Xp = 0; Xp < Width; Xp++, inc++ ) {
pc.printf( "%d,", Data_Y[ inc ] );
}
pc.printf("\n\r");
}
}
//Image Data Output2( for TeraTerm )
//------------------------------------------------------------------//
void ImageData_Serial_Out2( unsigned char *Data_Y, int Width )
{
int Xp, Yp, Height;
Height = (Width / (double)4) * 3;
for( Yp = 0; Yp < Height; Yp++ ) {
for( Xp = 0; Xp < Width; Xp++ ) {
pc.printf( "%d ", Data_Y[Xp + (Yp * Width)] );
}
pc.printf( "\n\r" );
}
pc.printf( "\033[%dA" , Height );
}
//Image Data Output3( for the converter ( csv --> jpg ) )
//------------------------------------------------------------------//
void ImageData_Serial_Out3( void )
{
int Xp, Yp, x, y;
/* Camera module test process */
pc.printf( "//,X-Size,Y-Size" );
pc.printf( "\n\r" );
pc.printf( "#SIZE,320,240" );
pc.printf( "\n\r" );
pc.printf( "//,X-Point,Y-Point" );
pc.printf( "\n\r" );
for( Yp = 0, y = 0; Yp < 240; Yp+=1, y++ ){
for( Xp = 0, x = 0; Xp < 640; Xp+=4, x+=2 ){
pc.printf( "#YCbCr," );
/*Xp*/pc.printf( "%d,", x);
/*Yp*/pc.printf( "%d,", y);
/*Y0*/pc.printf( "%d,", save_buff_addr[(Xp+0)+(640*Yp)]);//6
/*Cb*/pc.printf( "%d,", save_buff_addr[(Xp+1)+(640*Yp)]);//5
/*Cr*/pc.printf( "%d,", save_buff_addr[(Xp+3)+(640*Yp)]);//7
pc.printf( "\n\r" );
pc.printf( "#YCbCr," );
/*Xp*/pc.printf( "%d,", x+1);
/*Yp*/pc.printf( "%d,", y);
/*Y1*/pc.printf( "%d,", save_buff_addr[(Xp+2)+(640*Yp)]);//4
/*Cb*/pc.printf( "%d,", save_buff_addr[(Xp+1)+(640*Yp)]);//5
/*Cr*/pc.printf( "%d,", save_buff_addr[(Xp+3)+(640*Yp)]);//7
pc.printf( "\n\r" );
}
}
}
//Change FrameBuffer Process
//------------------------------------------------------------------//
void change_framebuffer_process( void )
{
DisplayBase::graphics_error_t error;
DisplayBase Display;
/* Change address 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;
}
/* Change write buffer */
error = Display.Video_Write_Change(
VIDEO_INPUT_CH,
write_buff_addr,
VIDEO_BUFFER_STRIDE);
if (error != DisplayBase::GRAPHICS_OK) {
printf("Line %d, error %d\n", __LINE__, error);
while (1);
}
}
//center_line_corrective_process
//------------------------------------------------------------------//
int center_line_corrective( void )
{
static int process_No = 0;
static int im_cnt = 0;
static int value = 0;
int iRet = 0;
int image_sensor_value;
image_sensor_value = image_sensorAnalog_get();
switch( process_No ) {
case 0:
/* center_line_corrective */
if( (value > image_sensor_value) && (image_sensor_value > -value) ) {
cnt1 = 0;
process_No = 1;
}
if( cnt1 >= 34 ) process_No = 3;
break;
case 1:
/* Retrial after 100ms */
if( cnt1 >= 68 ) {
if( (value > image_sensor_value) && (image_sensor_value > -value) ) {
cnt1 = 0;
process_No = 2;
} else {
process_No = 3;
}
}
break;
case 2:
iRet = 1;
break;
case 3:
im_offset_x += 2;
if( im_offset_x > ( ((160 - IM_GAP_SET) + (IM_GAP_SET * 2)) * 2 ) ) {
im_offset_x = 160 - IM_GAP_SET;
im_cnt++;
}
if( im_cnt >= 1 ) {
im_cnt = 0;
value += 2;
if( value >= 6 ) {
value = 6;
iRet = -1;
}
}
cnt1 = 0;
process_No = 0;
break;
default:
break;
}
return iRet;
}
//digital_sensor_corrective
//------------------------------------------------------------------//
void digital_sensor_corrective( void )
{
int Ypix;
int Xpix;
int pix_value;
black = 127;
white = 127;
/* Maximum value of the black and white */
Ypix = IMAGE_LINE;
for( Xpix = (im_offset_x - 192); Xpix < (im_offset_x + 192); Xpix+=4 ) {
pix_value = save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
if( black >= pix_value ) black = pix_value;
if( white <= pix_value ) white = pix_value;
pix_value = save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
if( black >= pix_value ) black = pix_value;
if( white <= pix_value ) white = pix_value;
}
/* threshold value */
digital_sensor_threshold = ( white - black ) / 2;
/* X3 */
Ypix = IMAGE_LINE;
for( Xpix = (im_offset_x - 192); Xpix < im_offset_x; Xpix+=4 ) {
pix_value = save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
pix_value += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
pix_value /= 2;
if( pix_value > digital_sensor_threshold ) {
sensor_x[3] = Xpix;
break;
}
}
/* X2 */
sensor_x[2] = im_offset_x;
/* X1 */
Ypix = IMAGE_LINE;
for( Xpix = im_offset_x; Xpix < (im_offset_x + 192); Xpix+=4 ) {
pix_value = save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
pix_value += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
pix_value /= 2;
if( pix_value < digital_sensor_threshold ) {
sensor_x[1] = Xpix;
break;
}
}
/* X4 */
sensor_x[4] = sensor_x[3] - (sensor_x[2] - sensor_x[3]);
/* X0 */
sensor_x[0] = (sensor_x[1] - sensor_x[2]) + sensor_x[1];
pc.printf( "x4 = %03d, x3 = %03d, x2 = %03d, x1 = %03d, x0 = %03d \n\n\r", sensor_x[4], sensor_x[3], sensor_x[2], sensor_x[1], sensor_x[0] );
}
//image_SensorAnalog_process
//------------------------------------------------------------------//
void image_SensorAnalog_process( int timer33 )
{
int Ypix;
int Xpix;
int left_value;
int right_value;
/* Initialization */
left_value = 0;
right_value = 0;
/* left image value ( 64pix to 160pix ) */
Ypix = IMAGE_LINE - (timer33);//109 to 75 line
for( Xpix = (im_offset_x - 192); Xpix < im_offset_x; Xpix+=4 ) {
left_value += save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
left_value += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
}
/* right image value ( 161pix to 256pix ) */
Ypix = IMAGE_LINE - (timer33);//109 to 75 line
for( Xpix = im_offset_x; Xpix < ( im_offset_x + 192 ); Xpix+=4 ) {
right_value += save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
right_value += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
}
Left_sensor = left_value / 10;
Right_sensor = right_value / 10;
}
//image_sensorAnalog_get
//------------------------------------------------------------------//
int image_sensorAnalog_get( void )
{
int iRet;
iRet = Left_sensor - Right_sensor;
/* Reverse of the positive and negative. */
iRet *= -1;
if( iRet <= -900 ) iRet = -900;//Left side
if( iRet >= 900 ) iRet = 900;//right side
return iRet;
}
//image_digital_sensor
//------------------------------------------------------------------//
unsigned char image_digital_sensor( void )
{
int Ypix;
int Xpix;
int data;
unsigned char sensor;
sensor = 0;
/* sensor 2 (center) */
data = 0;
Ypix = IMAGE_LINE;
for( Xpix = (sensor_x[2] - 8); Xpix < (sensor_x[2] + 8); Xpix+=4 ) {
data += save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
data += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
}
data /= 8;
if( data <= digital_sensor_threshold ) data = 0;
else data = 1;
sensor |= (data << 4) & 0x10;
/* sensor 4 (left side) */
data = 0;
Ypix = IMAGE_LINE;
for( Xpix = (sensor_x[4] - 16); Xpix < sensor_x[4]; Xpix+=4 ) {
data += save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
data += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
}
data /= 8;
if( data <= digital_sensor_threshold ) data = 0;
else data = 1;
sensor |= (data << 3) & 0x08;
/* sensor 3 (left side) */
data = 0;
Ypix = IMAGE_LINE;
for( Xpix = (sensor_x[3] - 16); Xpix < sensor_x[3]; Xpix+=4 ) {
data += save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
data += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
}
data /= 8;
if( data <= digital_sensor_threshold ) data = 0;
else data = 1;
sensor |= (data << 2) & 0x04;
/* sensor 1 (right side) */
data = 0;
Ypix = IMAGE_LINE;
for( Xpix = sensor_x[1]; Xpix < (sensor_x[1] + 16); Xpix+=4 ) {
data += save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
data += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
}
data /= 8;
if( data <= digital_sensor_threshold ) data = 0;
else data = 1;
sensor |= (data << 1) & 0x02;
/* sensor 0 (right side) */
data = 0;
Ypix = IMAGE_LINE;
for( Xpix = sensor_x[0]; Xpix < (sensor_x[0] + 16); Xpix+=4 ) {
data += save_buff_addr[(Ypix * 640) + (Xpix + 0)];/* Y1 */
data += save_buff_addr[(Ypix * 640) + (Xpix + 2)];/* Y2 */
}
data /= 8;
if( data <= digital_sensor_threshold ) data = 0;
else data = 1;
sensor |= (data) & 0x01;
sensor &= 0x1f;
return sensor;
}
//Image Data YCbCr -> Y(320*240pix)
//------------------------------------------------------------------//
void Image_Extraction( unsigned char *Data_Y )
{
static int Xp, Yp, inc;
static int counter = 0;
#if 0
// Function
for( Yp = 0, inc = 0; Yp < 240; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
#else
// Distributed processing
switch( counter++ ) {
case 0:
for( Yp = 0, inc = 0; Yp < 30; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
break;
case 1:
for( ; Yp < 60; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
break;
case 2:
for( ; Yp < 90; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
break;
case 3:
for( ; Yp < 120; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
break;
case 4:
for( ; Yp < 150; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
break;
case 5:
for( ; Yp < 180; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
break;
case 6:
for( ; Yp < 210; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
break;
case 7:
for( ; Yp < 240; Yp++ ){
for( Xp = 0; Xp < 640; Xp+=2, inc++ ){
Data_Y[ inc ] = save_buff_addr[(Xp)+(640*Yp)];
}
}
counter = 0;
break;
default:
break;
}
#endif
}
//Image_Compression Y ( Thinning processing )
//------------------------------------------------------------------//
void Image_Compression( unsigned char *Data_Y, int Data_W , unsigned char *Comp_Y, int Comp_W )
{
int Data_H, Comp_H, Step_W, Step_H;
int Xp, Yp, inc;
Data_H = (Data_W / (double)4) * 3;
Comp_H = (Comp_W / (double)4) * 3;
Step_W = Data_W / Comp_W;
Step_H = Data_H / Comp_H;
for( Yp = 0, inc = 0; Yp < Comp_H; Yp++ ) {
for( Xp = 0; Xp < Comp_W; Xp++, inc++ ) {
Comp_Y[inc] = Data_Y[(Yp * (Data_W * Step_H)) + (Xp * Step_W)];
}
}
}
//Image_Compression2 Y ( Averaging processing )
//------------------------------------------------------------------//
void Image_Compression2( unsigned char *Data_Y, int Data_W , unsigned char *Comp_Y, int Comp_M )
{
int Data_H, Pixel_T, Pixel_D;
int x, y;
static int Xp, Yp, inc;
static int counter = 0;
Data_H = (Data_W / (double)4) * 3;
Pixel_D = Comp_M * Comp_M;
#if 0
// Function
for( Yp = 0, inc = 0; Yp < Data_H; Yp+=Comp_M ){
for( Xp = 0; Xp < Data_W; Xp+=Comp_M, inc++ ){
Pixel_T = 0;
for( y = 0; y < Comp_M; y++ ){
for( x = 0; x < Comp_M; x++ ){
Pixel_T += Data_Y[( Xp + x ) + (( Yp + y ) * Data_W )];
}
}
Comp_Y[inc] = Pixel_T / Pixel_D;
}
}
#else
// Distributed processing
switch( counter++ ) {
case 0:
for( Yp = 0, inc = 0; Yp < (Data_H / 2); Yp+=Comp_M ){
for( Xp = 0; Xp < Data_W; Xp+=Comp_M, inc++ ){
Pixel_T = 0;
for( y = 0; y < Comp_M; y++ ){
for( x = 0; x < Comp_M; x++ ){
Pixel_T += Data_Y[( Xp + x ) + (( Yp + y ) * Data_W )];
}
}
Comp_Y[inc] = Pixel_T / Pixel_D;
}
}
break;
case 1:
for( ; Yp < Data_H; Yp+=Comp_M ){
for( Xp = 0; Xp < Data_W; Xp+=Comp_M, inc++ ){
Pixel_T = 0;
for( y = 0; y < Comp_M; y++ ){
for( x = 0; x < Comp_M; x++ ){
Pixel_T += Data_Y[( Xp + x ) + (( Yp + y ) * Data_W )];
}
}
Comp_Y[inc] = Pixel_T / Pixel_D;
}
}
counter = 0;
break;
default:
break;
}
#endif
}
// Binarization_process
//------------------------------------------------------------------//
void Binarization_process( unsigned char *Comp_Y, unsigned char *Binary, long items )
{
int i, threshold;
threshold = 150;
for( i = 0; i < items; i++ ) {
if( Comp_Y[i] >= threshold ) Binary[i] = 1;
else Binary[i] = 0;
}
}
// Extract_Image
//------------------------------------------------------------------//
void Image_part_Extraction( unsigned char *Binary, int Width, int Xpix, int Ypix, unsigned char *Data_B, int x_size, int y_size )
{
int x, y;
for( y = 0; y < y_size; y++ ) {
for( x = 0; x < x_size; x++ ) {
Data_B[ x + ( y * x_size ) ] = Binary[ (Xpix + x) + ( (Ypix + y) * Width ) ];
}
}
}
// Standard deviation
//------------------------------------------------------------------//
double Standard_Deviation( unsigned char *data, double *Devi, int items )
{
int i;
double iRet_A, iRet_C, iRet_D;
/* A 合計値 平均化 */
iRet_A = 0;
for( i = 0; i < items; i++ ) {
iRet_A += data[i];
}
iRet_A /= items;
/* B 偏差値 */
for( i = 0; i < items; i++ ) {
Devi[i] = data[i] - iRet_A;
}
/* C 分散 */
iRet_C = 0;
for( i = 0; i < items; i++ ) {
iRet_C += ( Devi[i] * Devi[i] );
}
iRet_C /= items;
/* D 標準偏差 */
iRet_D = sqrt( iRet_C );
return iRet_D;
}
// Covariance
//------------------------------------------------------------------//
double Covariance( double *Devi_A, double *Devi_B, int items )
{
int i;
double iRet, iRet_buff;
iRet = 0;
for( i = 0; i < items; i++ ) {
iRet_buff = Devi_A[i] * Devi_B[i];
iRet += iRet_buff;
}
iRet /= items;
return iRet;
}
// Judgement_ImageMatching
//------------------------------------------------------------------//
int Judgement_ImageMatching( double covari, double SDevi_A, double SDevi_B )
{
int iRet;
iRet = ( covari * 100 ) / ( SDevi_A * SDevi_B );
return iRet;
}
//******************************************************************//
// @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--;
}
}
//******************************************************************//
// @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 */
}
}
//------------------------------------------------------------------//
// End of file
//------------------------------------------------------------------//