This is a sample program that uses two Si1143 sensors.
Dependencies: GR-PEACH_video SI1143 mbed-rtos mbed
Information
Japanese version is available in lower part of this page.
このページの後半に日本語版が用意されています.
What is this ?
This is a sample program that uses two gesture sensors.
This program displays image of rectangle on the screen of the LCD shield depending on the sensors.
About Si1143
Si1143 is a gesture sensor and can be controlled by using the I2C.
This can be detected from the shortest 1cm up to 200cm.
Si1143 emits three infrared LED that is mounted on a substrate, and detects the movement by measuring the reflected light from the external object.
- Datasheet of Si1143
http://www.silabs.com/Support%20Documents/TechnicalDocs/Si114x.pdf
Composition
GR-PEACH, LCD Shield and two gesture sensors(Si1143).
About wiring
First Sensor
Sensor | GR-PEACH |
VDD | 3.3V |
SCL | D15 |
SDA | D14 |
GND | GND |
Second Sensor
Sensor | GR-PEACH |
VDD | 3.3V |
SCL | P1_6 |
SDA | P1_7 |
GND | GND |
How to use
- Please connect GR-PEACH ,LCD Shield and two jesture sensors. Then turn on the power to GR-PEACH.
- Please press the reset button of GR-PEACH.
- The screen which "Program Setting" is drawn is displayed on the LCD.
- When the sensor of the setting is completed, the screen which "Program Started!!" is drawn is displayed on the LCD.
- When you hold your hand on the upper of LED1 - LED3 of the two jesture sensors, six rectangles is drawn on the screen of LCD Shield.
hand on | Draw |
the upper of LED1 of the first sensor | red rectangle |
the upper of LED2 of the first sensor | green rectangle |
the upper of LED3 of the first sensor | blue rectangle |
the upper of LED1 of the second sensor | yellow rectangle |
the upper of LED2 of the second sensor | light blue rectangle |
the upper of LED3 of the second sensor | pink rectangle |
概要
これは2つのジェスチャーセンサーを使ったサンプルプログラムです。
このプログラムは、センサーに応じて四角形の画像をLCDシールドの画面上に表示します。
Si1143について
Si1143はジェスチャーセンサであり、I2C通信を使ってセンサを制御します。
センサとの距離範囲は1cm200cmです。
Si1143は、基板上に搭載された3つの赤外線LEDを放射し、物体からの反射光を測定することによって、動きを検出します。
構成
GR-PEACH, LCD Shield and two gesture sensors(Si1143).
ジェスチャーセンサとGR-PEACHの接続
1つ目のSensor
Sensor | GR-PEACH |
VDD | 3.3V |
SCL | D15 |
SDA | D14 |
GND | GND |
2つ目のSensor
Sensor | GR-PEACH |
VDD | 3.3V |
SCL | P1_6 |
SDA | P1_7 |
GND | GND |
使い方
- GR-PEACHとLCDシールドを接続し、GR-PEACHに電源を入れます。
- GR-PEACHのリセットボタンを押します。
- "Program Setting"という画面がLCDに表示されます。
- センサのセットアップが終わると、"Program Start!!"という画面がLCDに表示されます。
- 2つのジェスチャーセンサのLED1~LED3に手をかざすと、6種類の四角形がLCD上に描画されます。
手をかざす場所 | 描画 |
1つ目のセンサのLED1の上 | 赤色の四角形 |
1つ目のセンサのLED2の上 | 緑色の四角形 |
1つ目のセンサのLED3の上 | 青色の四角形 |
2つ目のセンサのLED1の上 | 黄色の四角形 |
2つ目のセンサのLED2の上 | 水色の四角形 |
2つ目のセンサのLED3の上 | ピンク色の四角形 |
Diff: main.cpp
- Revision:
- 0:7e5105dee0cb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue May 31 01:54:23 2016 +0000 @@ -0,0 +1,447 @@ +#include "mbed.h" +#include "DisplayBace.h" +#include "rtos.h" +#include "SI1143.h" +#include "image_data.h" + +/**** LCD Parameter **********/ +#define LCD_DE_MODE (0) +#define LCD_SYNC_MODE (1) + +#define LCD_DOT_CLOCK (13.40f) // 13.4MHz + +#define LCD_H_WIDTH (480u) +#define LCD_H_BACK_PORCH (43u) +#define LCD_H_FRONT_PORCH (52u) +#define LCD_H_SYNC_WIDTH (41u) + +#define LCD_V_WIDTH (272u) +#define LCD_V_BACK_PORCH (12u) +#define LCD_V_FRONT_PORCH (2u) +#define LCD_V_SYNC_WIDTH (10u) + +#define LCD_MODE (LCD_SYNC_MODE) + +/*****************************/ + + +#define FRAME_BUFFER_BYTE_PER_PIXEL (2u) +#define VIDEO_BUFFER_STRIDE (((LCD_H_WIDTH * FRAME_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u) +#define VIDEO_BUFFER_HEIGHT (LCD_V_WIDTH) + +#define IMG_RGB565 (0) +#define IMG_ARGB1555 (2) +#define IMG_ARGB4444 (3) +#define IMG_CLUT8 (6) +#define IMG_CLUT4 (7) +#define IMG_CLUT1 (8) +#define IMG_XRGB8888 (9) +#define IMG_ARGB8888 (10) +#define IMG_YUV422 (11) + +enum { + IMG_SETTING, + IMG_START, + IMG_RED, + IMG_GREEN, + IMG_BLUE, + IMG_YELLOW, + IMG_LIGHTBLUE, + IMG_PINK, + IMG_WHITE +}; + +enum { + SENSE1_NON, + SENSE1_1, + SENSE1_2, + SENSE1_3 +}; + +enum { + SENSE2_NON, + SENSE2_1, + SENSE2_2, + SENSE2_3 +}; + +DigitalOut lcd_pwon(P7_15); +DigitalOut lcd_blon(P8_1); +PwmOut lcd_cntrst(P8_15); +SI1143 sensor1(I2C_SDA, I2C_SCL); +SI1143 sensor2(P1_7, P1_6); + +typedef struct { + uint32_t dummy1; + uint32_t offset_to_image; + uint32_t dummy2; + uint16_t width; + uint16_t height; + uint8_t type; + uint8_t dummy3; + uint32_t dummy4; +} graphics_image_t; + +typedef struct { + const graphics_image_t* image; + uint32_t pos_x; + uint32_t pos_y; +} draw_info_t; + +typedef struct { + draw_info_t curr; + draw_info_t last; +} image_draw_t; + +static const graphics_image_t* image_file[9] = { + g_setting, g_start, g_red, g_gren, g_blue, g_yellow, g_lightblue, g_pink, g_white +}; + +static uint8_t user_frame_buffer[VIDEO_BUFFER_STRIDE * VIDEO_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32))); //32 bytes aligned!; +static uint8_t user_frame_buffer2[VIDEO_BUFFER_STRIDE * VIDEO_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32))); //32 bytes aligned!; +static volatile int32_t vsync_count; +static uint8_t* disp_buff_addr; +static int sense1[3] = {0, 0, 0}; +static int sense2[3] = {0, 0, 0}; +static image_draw_t img1_info; +static image_draw_t img2_info; + +static void IntCallbackFunc_Vsync(DisplayBase::int_type_t int_type) +{ + //Interrupt callback function for Vsync interruption + if (vsync_count > 0) { + vsync_count--; + } +} + +static void Wait_Vsync(const int32_t wait_count) +{ + //Wait for the specified number of times Vsync occurs + vsync_count = wait_count; + while (vsync_count > 0) { + /* Do nothing */ + } +} + +static void Clr_FrameBuffer(uint8_t frmbuf_num) { + int vcnt, wcnt; + uint16_t * fb_base; + uint16_t * fb_pos; + + if ((frmbuf_num & 0x01) != 0) { + fb_base = (uint16_t *)user_frame_buffer; + for (vcnt = 0; vcnt < LCD_V_WIDTH; vcnt++) { + fb_pos = fb_base + (vcnt * LCD_H_WIDTH); + for (wcnt = 0; wcnt < LCD_H_WIDTH; wcnt++) { + fb_pos[wcnt] = 0xFFFF; + } + } + } + if ((frmbuf_num & 0x02) != 0) { + fb_base = (uint16_t *)user_frame_buffer2; + for (vcnt = 0; vcnt < LCD_V_WIDTH; vcnt++) { + fb_pos = fb_base + (vcnt * LCD_H_WIDTH); + for (wcnt = 0; wcnt < LCD_H_WIDTH; wcnt++) { + fb_pos[wcnt] = 0xFFFF; + } + } + } +} + +static void Draw_Image(void * dst_buff, uint32_t dst_stride, const graphics_image_t * src_image, uint32_t pos_x, uint32_t pos_y) { + uint32_t offset_to_image; + uint16_t width; + uint16_t height; + uint8_t type; + uint16_t * pSrc16; + uint32_t * pSrc32; + uint16_t * pDst16; + uint32_t * pDst32; + uint32_t x,y; + + if (src_image != NULL) { + offset_to_image = src_image->offset_to_image; + width = src_image->width; + height = src_image->height; + type = src_image->type; + + if (type == IMG_ARGB4444) { + pDst16 = (uint16_t *)dst_buff; + pSrc16 = (uint16_t *)((uint8_t *)src_image + offset_to_image ); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + if ((pSrc16[(y * width) + x] & 0xf000) != 0) { + /* Copy the pixel value if its alpha value is not 0 */ + pDst16[((y + pos_y) * dst_stride / 2) + (x + pos_x)] = pSrc16[(y * width) + x]; + } + } + } + } else if (type == IMG_ARGB8888) { + pDst32 = (uint32_t *)dst_buff; + pSrc32 = (uint32_t *)((uint8_t *)src_image + offset_to_image); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + if ((pSrc32[(y * width) + x] & 0xff000000) != 0) { + /* Copy the pixel value if its alpha value is not 0 */ + pDst32[((y + pos_y) * dst_stride / 4) + (x + pos_x)] = pSrc32[(y * width) + x]; + } + } + } + } else if (type == IMG_RGB565) { + pDst16 = (uint16_t *)dst_buff; + pSrc16 = (uint16_t *)((uint8_t *)src_image + offset_to_image); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + pDst16[((y + pos_y) * dst_stride / 2) + (x + pos_x)] = pSrc16[(y * width) + x]; + } + } + } + } +} + +static int Get_Sensor1(void) { + int sense_num = SENSE1_NON; + + // Read each led sensor + sense1[0] = sensor1.get_ps1(5); + sense1[1] = sensor1.get_ps2(5); + sense1[2] = sensor1.get_ps3(5); + + if (sense1[0] > 500 || sense1[1] > 500 || sense1[2] > 500) { + if (sense1[0] > sense1[1] && sense1[0] > sense1[2]) { + sense_num = SENSE1_1; + } else if (sense1[1] > sense1[0] && sense1[1] > sense1[2]) { + sense_num = SENSE1_2; + } else if (sense1[2] > sense1[0] && sense1[2] > sense1[1]) { + sense_num = SENSE1_3; + } + } + + return sense_num; +} + +static int Get_Sensor2(void) { + int sense_num = SENSE2_NON; + + // Read each led sensor + sense2[0] = sensor2.get_ps1(5); + sense2[1] = sensor2.get_ps2(5); + sense2[2] = sensor2.get_ps3(5); + + if (sense2[0] > 500 || sense2[1] > 500 || sense2[2] > 500) { + if (sense2[0] > sense2[1] && sense2[0] > sense2[2]) { + sense_num = SENSE2_1; + } else if (sense2[1] > sense2[0] && sense2[1] > sense2[2]) { + sense_num = SENSE2_2; + } else if (sense2[2] > sense2[0] && sense2[2] > sense2[1]) { + sense_num = SENSE2_3; + } + } + + return sense_num; +} + +static void Swap_FrameBuffer(void) { + if (disp_buff_addr == user_frame_buffer) { + disp_buff_addr = user_frame_buffer2; + Clr_FrameBuffer(0x02); + } else { + disp_buff_addr = user_frame_buffer; + Clr_FrameBuffer(0x01); + } +} + +int main(void) +{ + /* Create DisplayBase object */ + DisplayBase Display; + DisplayBase::graphics_error_t error; + DisplayBase::lcd_config_t lcd_config; + disp_buff_addr = user_frame_buffer; + int sense1 = SENSE1_NON; + int sense2 = SENSE2_NON; + img1_info.curr.image = image_file[IMG_START]; + img1_info.curr.pos_x = 0; + img1_info.curr.pos_y = 0; + img1_info.last.image = image_file[IMG_WHITE]; + img1_info.last.pos_x = 0; + img1_info.last.pos_y = 0; + img2_info.curr.image = image_file[IMG_START]; + img2_info.curr.pos_x = 0; + img2_info.curr.pos_y = 0; + img2_info.last.image = image_file[IMG_WHITE]; + img2_info.last.pos_x = 240; + img2_info.last.pos_y = 0; + + lcd_pwon = 0; + lcd_blon = 0; + Thread::wait(100); + lcd_pwon = 1; + lcd_blon = 1; + Thread::wait(100); + + // Setup display + vsync_count = 0; + PinName lvds_pin[8] = { + /* data pin */ + P5_7, P5_6, P5_5, P5_4, P5_3, P5_2, P5_1, P5_0 + }; + DisplayBase::rect_t rect; + + lcd_config.lcd_type = DisplayBase::LCD_TYPE_LVDS; + lcd_config.intputClock = 66.67f; + lcd_config.outputClock = LCD_DOT_CLOCK; + lcd_config.lcd_outformat = DisplayBase::LCD_OUTFORMAT_RGB888; + lcd_config.lcd_edge = DisplayBase::EDGE_RISING; +#if(LCD_MODE) //SYNC Mode + lcd_config.h_toatal_period = (LCD_H_BACK_PORCH + LCD_H_WIDTH + LCD_H_FRONT_PORCH); + lcd_config.v_toatal_period = (LCD_V_BACK_PORCH + LCD_V_WIDTH + LCD_V_FRONT_PORCH); + + lcd_config.h_disp_widht = (LCD_H_WIDTH); + lcd_config.v_disp_widht = (LCD_V_WIDTH); + lcd_config.h_back_porch = (LCD_H_BACK_PORCH); + lcd_config.v_back_porch = (LCD_V_BACK_PORCH); + + lcd_config.h_sync_port = DisplayBase::LCD_TCON_PIN_2; + lcd_config.h_sync_port_polarity = DisplayBase::SIG_POL_INVERTED; + lcd_config.h_sync_width = LCD_H_SYNC_WIDTH; + + lcd_config.v_sync_port = DisplayBase::LCD_TCON_PIN_0; + lcd_config.v_sync_port_polarity = DisplayBase::SIG_POL_INVERTED; + lcd_config.v_sync_width = LCD_V_SYNC_WIDTH; + + lcd_config.de_port = DisplayBase::LCD_TCON_PIN_3; + lcd_config.de_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED; +#else //DE Mode + lcd_config.h_toatal_period = (LCD_H_WIDTH + 80u); + lcd_config.v_toatal_period = (LCD_V_WIDTH); + + lcd_config.h_disp_widht = (LCD_H_WIDTH); + lcd_config.v_disp_widht = (LCD_V_WIDTH); + lcd_config.h_back_porch = (68u); + lcd_config.v_back_porch = (18u); + + lcd_config.h_sync_port = DisplayBase::LCD_TCON_PIN_NON; + lcd_config.h_sync_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED; + lcd_config.h_sync_width = 0; + + lcd_config.v_sync_port = DisplayBase::LCD_TCON_PIN_NON; + lcd_config.v_sync_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED; + lcd_config.v_sync_width = 0; + + lcd_config.de_port = DisplayBase::LCD_TCON_PIN_3; + lcd_config.de_port_polarity = DisplayBase::SIG_POL_INVERTED; +#endif + + /* Graphics initialization process */ + error = Display.Graphics_init(&lcd_config); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + while (1); + } + + /* Interrupt callback function setting (Vsync signal output from scaler 0) */ + error = Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_LO_VSYNC, 0, IntCallbackFunc_Vsync); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + while (1); + } + + Display.Graphics_Lvds_Port_Init(lvds_pin, 8); + rect.vs = 0; + rect.vw = LCD_V_WIDTH; + rect.hs = 0; + rect.hw = LCD_H_WIDTH; + + Display.Graphics_Read_Setting( + DisplayBase::GRAPHICS_LAYER_0, + (void *)disp_buff_addr, + VIDEO_BUFFER_STRIDE, + DisplayBase::GRAPHICS_FORMAT_RGB565, + DisplayBase::WR_RD_WRSWA_32_16BIT, + &rect + ); + Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0); + lcd_cntrst.write(1.0); + + // Setup the baseline + Draw_Image(disp_buff_addr, VIDEO_BUFFER_STRIDE, image_file[IMG_SETTING], 0, 0); + printf("SI1143 Gesture Sensor setting...\n"); + sensor1.bias(1,5); + sensor2.bias(1,5); + Thread::wait(1000); + Draw_Image(disp_buff_addr, VIDEO_BUFFER_STRIDE, image_file[IMG_START], 0, 0); + printf("SI1143 Gesture Sensor setting finished!\n"); + while (1) { + sense1 = Get_Sensor1(); + switch (sense1) { + case SENSE1_1 : + img1_info.curr.image = image_file[IMG_RED]; + img1_info.curr.pos_x = 0; + img1_info.curr.pos_y = 0; + break; + case SENSE1_2 : + img1_info.curr.image = image_file[IMG_GREEN]; + img1_info.curr.pos_x = 80; + img1_info.curr.pos_y = 0; + break; + case SENSE1_3 : + img1_info.curr.image = image_file[IMG_BLUE]; + img1_info.curr.pos_x = 160; + img1_info.curr.pos_y = 0; + break; + default : + img1_info.curr.image = NULL; + img1_info.curr.pos_x = 0; + img1_info.curr.pos_y = 0; + break; + } + sense2 = Get_Sensor2(); + switch (sense2) { + case SENSE2_1 : + img2_info.curr.image = image_file[IMG_YELLOW]; + img2_info.curr.pos_x = 240; + img2_info.curr.pos_y = 0; + break; + case SENSE2_2 : + img2_info.curr.image = image_file[IMG_LIGHTBLUE]; + img2_info.curr.pos_x = 320; + img2_info.curr.pos_y = 0; + break; + case SENSE2_3 : + img2_info.curr.image = image_file[IMG_PINK]; + img2_info.curr.pos_x = 400; + img2_info.curr.pos_y = 0; + break; + default : + img2_info.curr.image = NULL; + img2_info.curr.pos_x = 0; + img2_info.curr.pos_y = 0; + break; + } + + if ((sense1 != 0) || (sense2 != 0)) { + /* Draw Image */ + Swap_FrameBuffer(); + if (sense1 != 0) { + Draw_Image(disp_buff_addr, VIDEO_BUFFER_STRIDE, img1_info.curr.image, img1_info.curr.pos_x, img1_info.curr.pos_y); + Draw_Image(disp_buff_addr, VIDEO_BUFFER_STRIDE, img2_info.last.image, img2_info.last.pos_x, img2_info.last.pos_y); + img1_info.last.image = img1_info.curr.image; + img1_info.last.pos_x = img1_info.curr.pos_x; + img1_info.last.pos_y = img1_info.curr.pos_y; + } + if (sense2 != 0) { + Draw_Image(disp_buff_addr, VIDEO_BUFFER_STRIDE, img1_info.last.image, img1_info.last.pos_x, img1_info.last.pos_y); + Draw_Image(disp_buff_addr, VIDEO_BUFFER_STRIDE, img2_info.curr.image, img2_info.curr.pos_x, img2_info.curr.pos_y); + img2_info.last.image = img2_info.curr.image; + img2_info.last.pos_x = img2_info.curr.pos_x; + img2_info.last.pos_y = img2_info.curr.pos_y; + } + Display.Graphics_Read_Change(DisplayBase::GRAPHICS_LAYER_0, (void *)disp_buff_addr); + Wait_Vsync(1); + } + } +}