Send the data of GR-PEACH_HVC-P2_sample to the cloud.

Dependencies:   AsciiFont GR-PEACH_video GraphicsFramework LCD_shield_config R_BSP USBHost_custom easy-connect-gr-peach

Fork of mbed-os-example-client by mbed-os-examples

Note at the time of sample import

Please not check the "Update all libraries to the latest version" at the time of import.

Warning!

When exporting and using it, increase the following stack size.

mbed-os/features/FEATURE_LWIP/lwip-interface/lwipopts.h

#define TCPIP_THREAD_STACKSIZE      1024
->
#define TCPIP_THREAD_STACKSIZE      2048

Overview

This is a sample to send the analysis result of GR-PEACH_HVC-P2_sample to the cloud using mbed-client. Please refer to following for operation of HVC-P2.

Import programGR-PEACH_HVC-P2_sample

Sample to operate omron HVC-P2 on GR-PEACH.


Required hardware

Application setup

Client credentials

To register the application to mbed Device Connector, you need to create and set the client side certificate.

  1. Go to https://connector.mbed.com/ and log in with your mbed account
  2. On mbed Device Connector, go to https://connector.mbed.com/#credentials and click the Get my device security credentials button to get new credentials for your device.
  3. Replace the contents in security.h of this example with content copied above.

Ethernet settings

This sample uses Ethernet as the default connection type. To change the connection type, set WIFI_BP3595 in mbed_app.json:

mbed_app.json

"network-interface":{
    "help": "Options are ETHERNET, WIFI_ESP8266, WIFI_BP3595",
    "value": "ETHERNET"
},


To specify MAC address, add fllowing function to main.cpp. (When using Wifi, setting of MAC address is not necessary.)

Specify MAC address

// set mac address
void mbed_mac_address(char *mac) {
    mac[0] = 0x00;
    mac[1] = 0x02;
    mac[2] = 0xF7;
    mac[3] = 0xF0;
    mac[4] = 0x00;
    mac[5] = 0x00;
}


Wifi settings

This example can use BP3595 Wifi Interface for managing the wireless connectivity. To run this example using Wifi, you need:

  1. A BP3595 Wifi module ( https://developer.mbed.org/components/BP3595-for-GR-PEACH/ )
  2. Mount BP3595 onto GR-PEACH
  3. Close GR-PEACH's JP21 (https://developer.mbed.org/teams/Renesas/wiki/Jumper-settings-of-GR-PEACH)
  4. In the mbed_app.json file, change

mbed_app.json

"network-interface":{
    "help": "Options are ETHERNET, WIFI_ESP8266, WIFI_BP3595",
    "value": "WIFI_BP3595"
},


Provide your Wifi SSID and password here and leave \" in the beginning and end of your SSID and password as shown in the example below:

mbed_app.json

"wifi-ssid": {
    "help": "WiFi SSID",
    "value": "\"SSID\""
},
"wifi-password": {
    "help": "WIFI Password",
    "value": "\"Password\""
}


Specify the security type for connection to be used. When the security type is WPA2, you need to specify NSAPI_SECURITY_WAP as follows:

mbed_app.json

"wifi-security":{
    "help": "Options are NSAPI_SECURITY_WEP, NSAPI_SECURITY_WPA, NSAPI_SECURITY_WPA2, NSAPI_SECURITY_WPA_WPA2",
    "value": "NSAPI_SECURITY_WEP"
},

By default, NSAPI_SECURITY_WPA_WPA2 is specified here.

Application resources

This example exposes four resources listed below:

  1. 3202/0/5700. Recognition result from HVC-P2 (GET).
  2. 3201/0/5850. Blink function, blinks LED when executed (POST).
  3. 3201/0/5853. Blink pattern, used by the blink function to determine how to blink. In the format of 1000:500:1000:500:1000:500 (PUT).
  4. 3201/0/5855. Blink color, used by the blink function. Any of red, green, blue, cyan, yellow and magenta is acceptable (PUT).

For more info on how to get notifications when resource 1 changes, or how to use resource 2, 3 and 4, please look at

Import programGR-PEACH_mbed-connector-ZXingSample-node

Node.js based Web Application for mbed Device Connector specific to GR-PEACH_mbed-os-client-ZXingSample

# This is a Web Application for GR-PEACH_mbed-os-client-ZXingSample, but it can also be used for this sample.

touch_proc/touch_proc.cpp

Committer:
dkato
Date:
2017-03-14
Revision:
73:fbc0212c2eaf

File content as of revision 73:fbc0212c2eaf:

#include "mbed.h"
#include "DisplayBace.h"
#include "rtos.h"
#include "LCD_shield_config_4_3inch.h"
#include "RGA.h"
#include "BinaryImage_RZ_A1H.h"
#include "recognition_proc.h"

/*! 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. */
/* TOUCH BUFFER Parameter GRAPHICS_LAYER_2 */
#define TOUCH_BUFFER_BYTE_PER_PIXEL     (4u)
#define TOUCH_BUFFER_STRIDE             (((LCD_PIXEL_WIDTH * TOUCH_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u)

/* Disp mode */
#define DISP_MODE_NORMAL                (0)
#define DISP_MODE_SETTING_1             (1)
#define DISP_MODE_SETTING_2             (2)
#define DISP_MODE_SETTING_3             (3)

/* Setting range  */
#define THRESHOLD_MIN                   (1)
#define THRESHOLD_MAX                   (1000)
#define SIZE_RANGE_MIN                  (20)
#define SIZE_RANGE_MAX                  (1000)
#define POSE_MIN                        (0)
#define POSE_MAX                        (2)
#define ANGLE_MIN                       (0)
#define ANGLE_MAX                       (1)

/* slide bar */
#define POS_SLIDE_BAR_X                 (185)
#define SLIDE_BAR_LENGTH                (200)
#define POS_PROGRESS_0_X                (POS_SLIDE_BAR_X + 15)

/* func_code */
#define TOUCH_KEY_CLOSE                 (1)
#define TOUCH_KEY_SETTING_1             (2)
#define TOUCH_KEY_SETTING_2             (3)
#define TOUCH_KEY_SETTING_3             (4)
#define TOUCH_KEY_REGISTRATION          (5)
#define TOUCH_KEY_THRESHOLD_BODY        (6)
#define TOUCH_KEY_THRESHOLD_FACE        (7)
#define TOUCH_KEY_THRESHOLD_RECO        (8)
#define TOUCH_KEY_RANGE_BODY_MIN        (9)
#define TOUCH_KEY_RANGE_BODY_MAX        (10)
#define TOUCH_KEY_RANGE_FACE_MIN        (11)
#define TOUCH_KEY_RANGE_FACE_MAX        (12)
#define TOUCH_KEY_FACE_POSE             (13)
#define TOUCH_KEY_FACE_ANGLE            (14)
#define TOUCH_KEY_BODY_DETECTION        (15)
#define TOUCH_KEY_FACE_DETECTION        (16)
#define TOUCH_KEY_AGE_ESTIMATION        (17)
#define TOUCH_KEY_GENDER_ESTIMATION     (18)
#define TOUCH_KEY_EXPRESSION_ESTIMATION (19)
#define TOUCH_KEY_SETTING_LAST          (20)
#define TOUCH_KEY_RESET_SETTING         (21)

typedef struct {
    uint32_t pic_pos_x;             /* X position of the key picture. */
    uint32_t pic_pos_y;             /* Y position of the key picture. */
    uint32_t pic_width;             /* Width of the key picture. */
    uint32_t pic_height;            /* Height of the key picture. */
    uint32_t func_code;             /* func code of the key picture. */
} key_pic_info_t;

static const key_pic_info_t touch_key_tbl_normal[] = {
    /*                X      Y    Width  Height   Func code                      */
    {                330,    10,   140,    36,    TOUCH_KEY_BODY_DETECTION        },
    {                330,    56,   140,    36,    TOUCH_KEY_FACE_DETECTION        },
    {                330,   102,   140,    36,    TOUCH_KEY_AGE_ESTIMATION        },
    {                330,   148,   140,    36,    TOUCH_KEY_GENDER_ESTIMATION     },
    {                330,   194,   140,    36,    TOUCH_KEY_EXPRESSION_ESTIMATION },
    {                448,   240,    32,    32,    TOUCH_KEY_SETTING_LAST          },
    {                  0,     0,   320,   240,    TOUCH_KEY_REGISTRATION          },
    {                  0,     0,     0,     0,    0                               } /* table end */
};

static const key_pic_info_t touch_key_tbl_setting_1[] = {
    /*                X      Y    Width  Height   Func code                      */
    {                127,   220,    80,    34,    TOUCH_KEY_RESET_SETTING         },
    {                273,   220,    80,    34,    TOUCH_KEY_CLOSE                 },
    {                 21,    20,   146,    34,    TOUCH_KEY_SETTING_1             },
    {                167,    20,   146,    34,    TOUCH_KEY_SETTING_2             },
    {                313,    20,   146,    34,    TOUCH_KEY_SETTING_3             },
    { POS_SLIDE_BAR_X-20,  80-8,   281,    30,    TOUCH_KEY_THRESHOLD_BODY        },
    { POS_SLIDE_BAR_X-20, 120-8,   281,    30,    TOUCH_KEY_THRESHOLD_FACE        },
    { POS_SLIDE_BAR_X-20, 160-8,   281,    30,    TOUCH_KEY_THRESHOLD_RECO        },
    {                  0,     0,     0,     0,    0                               } /* table end */
};

static const key_pic_info_t touch_key_tbl_setting_2[] = {
    /*                X      Y    Width  Height   Func code                      */
    {                127,   220,    80,    34,    TOUCH_KEY_RESET_SETTING         },
    {                273,   220,    80,    34,    TOUCH_KEY_CLOSE                 },
    {                 21,    20,   146,    34,    TOUCH_KEY_SETTING_1             },
    {                167,    20,   146,    34,    TOUCH_KEY_SETTING_2             },
    {                313,    20,   146,    34,    TOUCH_KEY_SETTING_3             },
    { POS_SLIDE_BAR_X-20,  80-8,   281,    30,    TOUCH_KEY_RANGE_BODY_MIN        },
    { POS_SLIDE_BAR_X-20, 110-8,   281,    30,    TOUCH_KEY_RANGE_BODY_MAX        },
    { POS_SLIDE_BAR_X-20, 150-8,   281,    30,    TOUCH_KEY_RANGE_FACE_MIN        },
    { POS_SLIDE_BAR_X-20, 180-8,   281,    30,    TOUCH_KEY_RANGE_FACE_MAX        },
    {                  0,     0,     0,     0,    0                               } /* table end */
};

static const key_pic_info_t touch_key_tbl_setting_3[] = {
    /*                X      Y    Width  Height   Func code                      */
    {                127,   220,    80,    34,    TOUCH_KEY_RESET_SETTING         },
    {                273,   220,    80,    34,    TOUCH_KEY_CLOSE                 },
    {                 21,    20,   146,    34,    TOUCH_KEY_SETTING_1             },
    {                167,    20,   146,    34,    TOUCH_KEY_SETTING_2             },
    {                313,    20,   146,    34,    TOUCH_KEY_SETTING_3             },
    { POS_SLIDE_BAR_X-20,  80-8,   281,    30,    TOUCH_KEY_FACE_POSE             },
    { POS_SLIDE_BAR_X-20, 120-8,   281,    30,    TOUCH_KEY_FACE_ANGLE            },
    {                  0,     0,     0,     0,    0                               } /* table end */
};

static const key_pic_info_t * p_touch_key_tbl[] = {
    touch_key_tbl_normal,           /* DISP_MODE_NORMAL    */
    touch_key_tbl_setting_1,        /* DISP_MODE_SETTING_1 */
    touch_key_tbl_setting_2,        /* DISP_MODE_SETTING_2 */
    touch_key_tbl_setting_3,        /* DISP_MODE_SETTING_3 */
    NULL
};

static TouckKey_LCD_shield touch(P4_0, P2_13, I2C_SDA, I2C_SCL);
static Semaphore   sem_touch_int(0);

#if defined(__ICCARM__)
/* 32 bytes aligned */
#pragma data_alignment=32
static uint8_t user_frame_buffer_touch0[TOUCH_BUFFER_STRIDE * LCD_PIXEL_HEIGHT];
#pragma data_alignment=32
static uint8_t user_frame_buffer_touch1[TOUCH_BUFFER_STRIDE * LCD_PIXEL_HEIGHT];
#else
/* 32 bytes aligned */
static uint8_t user_frame_buffer_touch0[TOUCH_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32)));
static uint8_t user_frame_buffer_touch1[TOUCH_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32)));
#endif

static volatile int32_t vsync_count = 0;
static recognition_setting_t * p_setting;
static int disp_mode;

/****** Touch panel ******/
static uint32_t Scan_Key(const key_pic_info_t * key_tbl, const uint32_t pos_x, const uint32_t pos_y) {
    uint32_t ret = 0;

    while (ret == 0) {
        if (key_tbl->func_code == 0) {
            break;
        }
        /* Check the range of the X position */
        if ((pos_x >= key_tbl->pic_pos_x) && (pos_x <= (key_tbl->pic_pos_x + key_tbl->pic_width))) {
            /* Check the range of the Y position */
            if ((pos_y >= key_tbl->pic_pos_y) && (pos_y <= (key_tbl->pic_pos_y + key_tbl->pic_height))) {
                /* Decide the func code. */
                ret = key_tbl->func_code;
            }
        }
        key_tbl++;
    }

    return ret;
}

static void draw_button(Canvas2D_ContextClass * p_canvas2d) {
    const graphics_image_t* p_wk;

    /* Draw background */
    p_canvas2d->drawImage(background, 320, 0);

    /* Draw "HUMAN BODY" button */
    if ((p_setting->execFlag & HVC_ACTIV_BODY_DETECTION) == 0) {
        p_wk = button_off;
    } else {
        p_wk = button_on;
    }
    p_canvas2d->drawImage(p_wk, 330, 10);
    p_canvas2d->drawImage(str_human_body, 330 + 19, 10 + 11);

    /* Draw "FACE" or "RECOGNITION" button */
    if ((p_setting->execFlag & HVC_ACTIV_FACE_RECOGNITION) == 0) {
        if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
            p_wk = button_off;
        } else {
            p_wk = button_on;
        }
        p_canvas2d->drawImage(p_wk, 330, 56);
        p_canvas2d->drawImage(str_face, 330 + 51, 56 + 11);
    } else {
        p_canvas2d->drawImage(button_on2, 330, 56);
        p_canvas2d->drawImage(str_recognition, 330 + 19, 56 + 11);
    }

    /* Draw "AGE" button */
    if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
        p_wk = button_inv;
    } else if ((p_setting->execFlag & HVC_ACTIV_AGE_ESTIMATION) == 0) {
        p_wk = button_off;
    } else {
        p_wk = button_on;
    }
    p_canvas2d->drawImage(p_wk, 330, 102);
    p_canvas2d->drawImage(str_age, 330 + 54, 102 + 11);

    /* Draw "GENDER" button */
    if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
        p_wk = button_inv;
    } else if ((p_setting->execFlag & HVC_ACTIV_GENDER_ESTIMATION) == 0) {
        p_wk = button_off;
    } else {
        p_wk = button_on;
    }
    p_canvas2d->drawImage(p_wk, 330, 148);
    p_canvas2d->drawImage(str_gender, 330 + 39, 148 + 11);

    /* Draw "EXPRESSION" button */
    if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
        p_wk = button_inv;
    } else if ((p_setting->execFlag & HVC_ACTIV_EXPRESSION_ESTIMATION) == 0) {
        p_wk = button_off;
    } else {
        p_wk = button_on;
    }
    p_canvas2d->drawImage(p_wk, 330, 194);
    p_canvas2d->drawImage(str_expression, 330 + 23, 194 + 11);

    /* Draw setting icon */
    p_canvas2d->drawImage(icon_setting, LCD_PIXEL_WIDTH - 32, LCD_PIXEL_HEIGHT - 32);
}

static void draw_number(Canvas2D_ContextClass * p_canvas2d, int x, int y, int number) {
    int wk_num;
    bool disp_flg = false;
    const graphics_image_t * p_num_tbl[] = {
        char_0, char_1, char_2, char_3, char_4, char_5, char_6, char_7, char_8, char_9
    };

    wk_num = (number / 1000) % 10;
    if ((wk_num != 0) || (disp_flg != false)) {
        p_canvas2d->drawImage(p_num_tbl[wk_num], x + 9 * 0, y);
        R_OSPL_CLEAR_ERROR();
        disp_flg = true;
    }
    wk_num = (number / 100) % 10;
    if ((wk_num != 0) || (disp_flg != false)) {
        p_canvas2d->drawImage(p_num_tbl[wk_num], x + 9 * 1, y);
        R_OSPL_CLEAR_ERROR();
        disp_flg = true;
    }
    wk_num = (number / 10) % 10;
    if ((wk_num != 0) || (disp_flg != false)) {
        p_canvas2d->drawImage(p_num_tbl[wk_num], x + 9 * 2, y);
        R_OSPL_CLEAR_ERROR();
    }
    wk_num = number % 10;
    p_canvas2d->drawImage(p_num_tbl[wk_num], x + 9 * 3, y);
    R_OSPL_CLEAR_ERROR();
}

static void draw_slide_bar(Canvas2D_ContextClass * p_canvas2d, int y, INT32 data, int min, int max) {
    p_canvas2d->globalAlpha = 0.7f;
    p_canvas2d->fillStyle = "#D9C3E6";
    p_canvas2d->fillRect(POS_PROGRESS_0_X, y + 6, SLIDE_BAR_LENGTH + 10, 2);
    p_canvas2d->globalAlpha = 1.0f;
    p_canvas2d->drawImage(char_left, POS_SLIDE_BAR_X, y);
    p_canvas2d->drawImage(char_rigth, POS_PROGRESS_0_X + SLIDE_BAR_LENGTH + 10 + 1, y);
    p_canvas2d->fillStyle = "#5B9BD5";
    p_canvas2d->fillRect(POS_PROGRESS_0_X + (int)(SLIDE_BAR_LENGTH * ((float)(data - min) / (max - min))), y, 10, 14);
}

static void draw_setting_menu(Canvas2D_ContextClass * p_canvas2d) {
    if (disp_mode == DISP_MODE_NORMAL) {
        return;
    }

    p_canvas2d->globalAlpha = 0.95f;
    p_canvas2d->drawImage(background_setting, 0, 0);

    /* Tab */
    if (disp_mode == DISP_MODE_SETTING_1) {
        p_canvas2d->globalAlpha = 0.9f;
        p_canvas2d->fillStyle = "#5B9BD5";
        p_canvas2d->fillRect(21, 20, 146, 34);
        p_canvas2d->globalAlpha = 1.0f;
    } else {
        p_canvas2d->globalAlpha = 0.3f;
    }
    p_canvas2d->drawImage(str_threshold_value, 23, 30);

    if (disp_mode == DISP_MODE_SETTING_2) {
        p_canvas2d->globalAlpha = 0.9f;
        p_canvas2d->fillStyle = "#5B9BD5";
        p_canvas2d->fillRect(167, 20, 146, 34);
        p_canvas2d->globalAlpha = 1.0f;
    } else {
        p_canvas2d->globalAlpha = 0.3f;
    }
    p_canvas2d->drawImage(str_detection_size, 181, 30);

    if (disp_mode == DISP_MODE_SETTING_3) {
        p_canvas2d->globalAlpha = 0.9f;
        p_canvas2d->fillStyle = "#5B9BD5";
        p_canvas2d->fillRect(313, 20, 146, 34);
        p_canvas2d->globalAlpha = 1.0f;
    } else {
        p_canvas2d->globalAlpha = 0.3f;
    }
    p_canvas2d->drawImage(str_face, 342, 30);
    p_canvas2d->drawImage(str_angle, 383, 30);

    /* Setting */
    p_canvas2d->globalAlpha = 1.0f;
    if (disp_mode == DISP_MODE_SETTING_1) {
        p_canvas2d->drawImage(str_human_body, 30, 80);
        p_canvas2d->drawImage(str_face, 30, 120);
        p_canvas2d->drawImage(str_recognition, 30, 160);

        draw_slide_bar(p_canvas2d,  80, p_setting->threshold.bdThreshold, THRESHOLD_MIN, THRESHOLD_MAX);
        draw_slide_bar(p_canvas2d, 120, p_setting->threshold.dtThreshold, THRESHOLD_MIN, THRESHOLD_MAX);
        draw_slide_bar(p_canvas2d, 160, p_setting->threshold.rsThreshold, THRESHOLD_MIN, THRESHOLD_MAX);

        draw_number(p_canvas2d, 430,  80, p_setting->threshold.bdThreshold);
        draw_number(p_canvas2d, 430, 120, p_setting->threshold.dtThreshold);
        draw_number(p_canvas2d, 430, 160, p_setting->threshold.rsThreshold);
    } else if (disp_mode == DISP_MODE_SETTING_2) {
        p_canvas2d->drawImage(str_human_body, 30, 80);
        p_canvas2d->drawImage(str_min, 140, 80);
        p_canvas2d->drawImage(str_max, 140, 110);
        p_canvas2d->drawImage(str_face, 30, 150);
        p_canvas2d->drawImage(str_min, 140, 150);
        p_canvas2d->drawImage(str_max, 140, 180);

        draw_slide_bar(p_canvas2d,  80, p_setting->sizeRange.bdMinSize, SIZE_RANGE_MIN, SIZE_RANGE_MAX);
        draw_slide_bar(p_canvas2d, 110, p_setting->sizeRange.bdMaxSize, SIZE_RANGE_MIN, SIZE_RANGE_MAX);
        draw_slide_bar(p_canvas2d, 150, p_setting->sizeRange.dtMinSize, SIZE_RANGE_MIN, SIZE_RANGE_MAX);
        draw_slide_bar(p_canvas2d, 180, p_setting->sizeRange.dtMaxSize, SIZE_RANGE_MIN, SIZE_RANGE_MAX);

        draw_number(p_canvas2d, 430,  80, p_setting->sizeRange.bdMinSize);
        draw_number(p_canvas2d, 430, 110, p_setting->sizeRange.bdMaxSize);
        draw_number(p_canvas2d, 430, 150, p_setting->sizeRange.dtMinSize);
        draw_number(p_canvas2d, 430, 180, p_setting->sizeRange.dtMaxSize);
    } else {
        int wk_data;

        p_canvas2d->drawImage(str_yaw, 30, 80);
        p_canvas2d->drawImage(str_angle, 30 + 41, 80);
        p_canvas2d->drawImage(str_roll, 30, 120);
        p_canvas2d->drawImage(str_angle, 30 + 42, 120);

        if (p_setting->pose == 0) {
            wk_data = 30;
        } else if (p_setting->pose == 1) {
            wk_data = 60;
        } else {
            wk_data = 90;
        }
        draw_slide_bar(p_canvas2d,  80, p_setting->pose, POSE_MIN , POSE_MAX);
        p_canvas2d->drawImage(char_plus_minus, 426, 80);
        draw_number(p_canvas2d, 420,  80, wk_data); /* 30 60 90 */
        p_canvas2d->drawImage(char_angle, 457, 80);

        if (p_setting->angle == 0) {
            wk_data = 15;
        } else {
            wk_data = 45;
        }
        draw_slide_bar(p_canvas2d, 120, p_setting->angle, ANGLE_MIN, ANGLE_MAX);
        p_canvas2d->drawImage(char_plus_minus, 426, 120);
        draw_number(p_canvas2d, 420, 120, wk_data); /* 15 45 */
        p_canvas2d->drawImage(char_angle, 457, 120);
    }
    p_canvas2d->drawImage(str_reset, 144, 230);
    p_canvas2d->drawImage(str_close, 290, 230);
}

static void draw_touch_layer(DisplayBase * p_display, frame_buffer_t * frmbuf_info, Canvas2D_ContextClass * p_canvas2d) {
    while (vsync_count > 0) {
        Thread::wait(1);
    }

    /* Swap the frame buffer */
    if (frmbuf_info->draw_buffer_index == 1) {
        frmbuf_info->draw_buffer_index = 0;
    } else {
        frmbuf_info->draw_buffer_index = 1;
    }

    /* Clear */
    p_canvas2d->clearRect(0, 0, frmbuf_info->width, frmbuf_info->height);

    /* Draw button */
    draw_button(p_canvas2d);

    /* Draw setting menu */
    draw_setting_menu(p_canvas2d);

    /* Complete drawing */
    R_GRAPHICS_Finish(p_canvas2d->c_LanguageContext);
    p_display->Graphics_Read_Change(DisplayBase::GRAPHICS_LAYER_2,
     (void *)frmbuf_info->buffer_address[frmbuf_info->draw_buffer_index]);
    vsync_count = 1;
}

static void set_progress(int x, INT32 * p_data, int min, int max, bool * p_slide, int last_key) {
    int now_pos = POS_PROGRESS_0_X + (int)(SLIDE_BAR_LENGTH * (float)(*p_data - min) / (max - min));

    x -= 5;
    if ((last_key == 0) && (x > (now_pos - 10)) && (x < (now_pos + 20))) {
        *p_slide = true;
    }
    if (x < POS_PROGRESS_0_X) {
        x = POS_PROGRESS_0_X;
    }
    if (x > (POS_PROGRESS_0_X + SLIDE_BAR_LENGTH)) {
        x = (POS_PROGRESS_0_X + SLIDE_BAR_LENGTH);
    }
    if (*p_slide) {
        *p_data = ((float)(x - POS_PROGRESS_0_X) / (float)SLIDE_BAR_LENGTH * (float)(max - min)) + min;
    } else if ((x > now_pos) && (*p_data < max)) {
        *p_data += 1;
    } else if ((x < now_pos) && (*p_data > min)) {
        *p_data -= 1;
    } else {
        /* do nothing */
    }
}

static void init_touch_layer(DisplayBase * p_display, frame_buffer_t * frmbuf_info, Canvas2D_ContextClass * p_canvas2d) {
    errnum_t err;
    Canvas2D_ContextConfigClass config;
    DisplayBase::rect_t rect;

    /* The layer by which the buttons is drawn */
    memset(user_frame_buffer_touch0, 0, sizeof(user_frame_buffer_touch0));
    memset(user_frame_buffer_touch1, 0, sizeof(user_frame_buffer_touch1));
    frmbuf_info->buffer_address[0] = user_frame_buffer_touch0;
    frmbuf_info->buffer_address[1] = user_frame_buffer_touch1;
    frmbuf_info->buffer_count      = 2;
    frmbuf_info->show_buffer_index = 0;
    frmbuf_info->draw_buffer_index = 0;
    frmbuf_info->width             = LCD_PIXEL_WIDTH;
    frmbuf_info->byte_per_pixel    = TOUCH_BUFFER_BYTE_PER_PIXEL;
    frmbuf_info->stride            = TOUCH_BUFFER_STRIDE;
    frmbuf_info->height            = LCD_PIXEL_HEIGHT;
    frmbuf_info->pixel_format      = PIXEL_FORMAT_ARGB8888;

    rect.vs = 0;
    rect.vw = LCD_PIXEL_HEIGHT;
    rect.hs = 0;
    rect.hw = LCD_PIXEL_WIDTH;
    p_display->Graphics_Read_Setting(
        DisplayBase::GRAPHICS_LAYER_2,
        (void *)frmbuf_info->buffer_address[frmbuf_info->draw_buffer_index],
        TOUCH_BUFFER_STRIDE,
        DisplayBase::GRAPHICS_FORMAT_ARGB8888,
        DisplayBase::WR_RD_WRSWA_32BIT,
        &rect
    );
    p_display->Graphics_Start(DisplayBase::GRAPHICS_LAYER_2);

    /* Drawing buttons */
    config.frame_buffer = frmbuf_info;
    *p_canvas2d = R_RGA_New_Canvas2D_ContextClass(config);
    err = R_OSPL_GetErrNum();
    if (err != 0) {
        printf("Line %d, err %d\n", __LINE__, err);
        mbed_die();
    }
}

static void touch_int_callback(void) {
    sem_touch_int.release();
}

void touch_lcd_int(DisplayBase::int_type_t int_type) {
    /* Interrupt callback function for Vsync interruption */
    if (int_type == DisplayBase::INT_TYPE_S0_LO_VSYNC) {
        if (vsync_count > 0) {
            vsync_count--;
        }
    }
}

void touch_task(DisplayBase * p_display) {
    frame_buffer_t frame_buffer_info;
    Canvas2D_ContextClass canvas2d;
    TouchKey::touch_pos_t touch_pos[1];
    int touch_num = 0;
    int touch_num_last = 0;
    bool key_rep = false;
    int func_code;
    int func_code_last = 0;
    bool slide = false;
    Timer key_time;
    int wait_time;
    int last_setting_mode = DISP_MODE_SETTING_1;

    p_setting = GetRecognitionSettingPointer();
    disp_mode = DISP_MODE_NORMAL;

    /* Initializing Touch layer */
    init_touch_layer(p_display, &frame_buffer_info, &canvas2d);
    draw_touch_layer(p_display, &frame_buffer_info, &canvas2d);

    /* Callback setting */
    touch.SetCallback(&touch_int_callback);

    /* Reset touch IC */
    touch.Reset();

    key_time.reset();
    key_time.start();

    while (1) {
        /* Wait touch event */
        sem_touch_int.wait();

        /* Get touch coordinates */
        touch_num = touch.GetCoordinates(1, touch_pos);

        if (slide) {
            wait_time = 80;
        } else {
            wait_time = 250;
        }
        if ((key_time.read_ms() > wait_time) || (touch_num != touch_num_last)) {
            key_time.reset();
            key_time.start();
            if ((touch_num != 0) && ((touch_num_last == 0) || (key_rep == true))) {
                key_rep = false;
                func_code = Scan_Key(p_touch_key_tbl[disp_mode], touch_pos[0].x, touch_pos[0].y);
                if (slide) {
                    func_code = func_code_last;
                }
                if (func_code != 0) {
                    switch (func_code) {
                        case TOUCH_KEY_SETTING_LAST:
                            disp_mode = last_setting_mode;
                            break;
                        case TOUCH_KEY_CLOSE:
                            disp_mode = DISP_MODE_NORMAL;
                            SetSettingReq();
                            break;
                        case TOUCH_KEY_SETTING_1:
                            disp_mode = DISP_MODE_SETTING_1;
                            last_setting_mode = DISP_MODE_SETTING_1;
                            break;
                        case TOUCH_KEY_SETTING_2:
                            disp_mode = DISP_MODE_SETTING_2;
                            last_setting_mode = DISP_MODE_SETTING_2;
                            break;
                        case TOUCH_KEY_SETTING_3:
                            disp_mode = DISP_MODE_SETTING_3;
                            last_setting_mode = DISP_MODE_SETTING_3;
                            break;
                        case TOUCH_KEY_REGISTRATION:
                            if ((p_setting->execFlag & HVC_ACTIV_FACE_RECOGNITION) != 0) {
                                SetRegistrationrReq();
                            }
                            break;
                        case TOUCH_KEY_THRESHOLD_BODY:
                            set_progress(touch_pos[0].x, &p_setting->threshold.bdThreshold,
                                         THRESHOLD_MIN, THRESHOLD_MAX, &slide, touch_num_last);
                            key_rep = true;
                            break;
                        case TOUCH_KEY_THRESHOLD_FACE:
                            set_progress(touch_pos[0].x, &p_setting->threshold.dtThreshold,
                                         THRESHOLD_MIN, THRESHOLD_MAX, &slide, touch_num_last);
                            key_rep = true;
                            break;
                        case TOUCH_KEY_THRESHOLD_RECO:
                            set_progress(touch_pos[0].x, &p_setting->threshold.rsThreshold,
                                         THRESHOLD_MIN, THRESHOLD_MAX, &slide, touch_num_last);
                            key_rep = true;
                            break;
                        case TOUCH_KEY_RANGE_BODY_MIN:
                            set_progress(touch_pos[0].x, &p_setting->sizeRange.bdMinSize,
                                         SIZE_RANGE_MIN, SIZE_RANGE_MAX, &slide, touch_num_last);
                            if (p_setting->sizeRange.bdMinSize > p_setting->sizeRange.bdMaxSize) {
                                p_setting->sizeRange.bdMaxSize = p_setting->sizeRange.bdMinSize;
                            }
                            key_rep = true;
                            break;
                        case TOUCH_KEY_RANGE_BODY_MAX:
                            set_progress(touch_pos[0].x, &p_setting->sizeRange.bdMaxSize,
                                         SIZE_RANGE_MIN, SIZE_RANGE_MAX, &slide, touch_num_last);
                            if (p_setting->sizeRange.bdMaxSize < p_setting->sizeRange.bdMinSize) {
                                p_setting->sizeRange.bdMinSize = p_setting->sizeRange.bdMaxSize;
                            }
                            key_rep = true;
                            break;
                        case TOUCH_KEY_RANGE_FACE_MIN:
                            set_progress(touch_pos[0].x, &p_setting->sizeRange.dtMinSize,
                                         SIZE_RANGE_MIN, SIZE_RANGE_MAX, &slide, touch_num_last);
                            if (p_setting->sizeRange.dtMinSize > p_setting->sizeRange.dtMaxSize) {
                                p_setting->sizeRange.dtMaxSize = p_setting->sizeRange.dtMinSize;
                            }
                            key_rep = true;
                            break;
                        case TOUCH_KEY_RANGE_FACE_MAX:
                            set_progress(touch_pos[0].x, &p_setting->sizeRange.dtMaxSize,
                                         SIZE_RANGE_MIN, SIZE_RANGE_MAX, &slide, touch_num_last);
                            if (p_setting->sizeRange.dtMaxSize < p_setting->sizeRange.dtMinSize) {
                                p_setting->sizeRange.dtMinSize = p_setting->sizeRange.dtMaxSize;
                            }
                            key_rep = true;
                            break;
                        case TOUCH_KEY_FACE_POSE:
                            set_progress(touch_pos[0].x, &p_setting->pose,
                                         POSE_MIN, POSE_MAX, &slide, touch_num_last);
                            if (slide) {
                                key_rep = true;
                            }
                            break;
                        case TOUCH_KEY_FACE_ANGLE:
                            set_progress(touch_pos[0].x, &p_setting->angle,
                                         ANGLE_MIN, ANGLE_MAX, &slide, touch_num_last);
                            if (slide) {
                                key_rep = true;
                            }
                            break;
                        case TOUCH_KEY_BODY_DETECTION:
                            if ((p_setting->execFlag & HVC_ACTIV_BODY_DETECTION) != 0) {
                                p_setting->execFlag &= ~HVC_ACTIV_BODY_DETECTION;
                            } else {
                                p_setting->execFlag |= HVC_ACTIV_BODY_DETECTION;
                            }
                            break;
                        case TOUCH_KEY_FACE_DETECTION:
                            if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
                                p_setting->execFlag |= HVC_ACTIV_FACE_DETECTION;
                            } else if ((p_setting->execFlag & HVC_ACTIV_FACE_RECOGNITION) == 0) {
                                p_setting->execFlag |= HVC_ACTIV_FACE_RECOGNITION;
                            } else {
                                p_setting->execFlag &= ~(HVC_ACTIV_FACE_DETECTION | HVC_ACTIV_FACE_RECOGNITION);
                            }
                            break;
                        case TOUCH_KEY_AGE_ESTIMATION:
                            if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
                                /* do nothing */
                            } else if ((p_setting->execFlag & HVC_ACTIV_AGE_ESTIMATION) != 0) {
                                p_setting->execFlag &= ~HVC_ACTIV_AGE_ESTIMATION;
                            } else {
                                p_setting->execFlag |= HVC_ACTIV_AGE_ESTIMATION;
                            }
                            break;
                        case TOUCH_KEY_GENDER_ESTIMATION:
                            if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
                                /* do nothing */
                            } else if ((p_setting->execFlag & HVC_ACTIV_GENDER_ESTIMATION) != 0) {
                                p_setting->execFlag &= ~HVC_ACTIV_GENDER_ESTIMATION;
                            } else {
                                p_setting->execFlag |= HVC_ACTIV_GENDER_ESTIMATION;
                            }
                            break;
                        case TOUCH_KEY_EXPRESSION_ESTIMATION:
                            if ((p_setting->execFlag & HVC_ACTIV_FACE_DETECTION) == 0) {
                                /* do nothing */
                            } else if ((p_setting->execFlag & HVC_ACTIV_EXPRESSION_ESTIMATION) != 0) {
                                p_setting->execFlag &= ~HVC_ACTIV_EXPRESSION_ESTIMATION;
                            } else {
                                p_setting->execFlag |= HVC_ACTIV_EXPRESSION_ESTIMATION;
                            }
                            break;
                        case TOUCH_KEY_RESET_SETTING:
                            if (disp_mode == DISP_MODE_SETTING_1) {
                                p_setting->threshold.bdThreshold = BODY_THRESHOLD_DEFAULT;
                                p_setting->threshold.hdThreshold = HAND_THRESHOLD_DEFAULT;
                                p_setting->threshold.dtThreshold = FACE_THRESHOLD_DEFAULT;
                                p_setting->threshold.rsThreshold = REC_THRESHOLD_DEFAULT;
                            } else if (disp_mode == DISP_MODE_SETTING_2) {
                                p_setting->sizeRange.bdMinSize = BODY_SIZE_RANGE_MIN_DEFAULT;
                                p_setting->sizeRange.bdMaxSize = BODY_SIZE_RANGE_MAX_DEFAULT;
                                p_setting->sizeRange.hdMinSize = HAND_SIZE_RANGE_MIN_DEFAULT;
                                p_setting->sizeRange.hdMaxSize = HAND_SIZE_RANGE_MAX_DEFAULT;
                                p_setting->sizeRange.dtMinSize = FACE_SIZE_RANGE_MIN_DEFAULT;
                                p_setting->sizeRange.dtMaxSize = FACE_SIZE_RANGE_MAX_DEFAULT;
                            } else if (disp_mode == DISP_MODE_SETTING_3) {
                                p_setting->pose  = FACE_POSE_DEFAULT;
                                p_setting->angle = FACE_ANGLE_DEFAULT;
                            } else {
                                /* do nothing */
                            }
                            break;
                        default:
                            break;
                    }
                    draw_touch_layer(p_display, &frame_buffer_info, &canvas2d);
                }
                func_code_last = func_code;
            } else {
                slide = false;
            }
        }
        touch_num_last = touch_num;
    }
}