Control light via motion or web
[Items]
1. PHPoC Blue
2. Relay Board (4-Port Digital Output Board)
3. mikroBUS Board
4. mikroBUS IR Gesture click made by MikroElektronika
5. light
[How it works]
Once the sensor reports that gesture has occurred, PHPoC Blue reads the direction.
When gesture occurred from the left direction, the lamp will be turned on.
It reads the right direction for the light to be turned off.
When you open a webpage, you can connect PHPoC Blue though websocket automatically.
If you click the light image on the web, you can control the light to be turned on and off.
[Video clip]
[Source Code]
1. task0.php
Code:
<?php if(_SERVER("REQUEST_METHOD")) exit; // avoid php execution via http request include_once "vd_ir_gesture_click.php"; include_once "/lib/sd_340.php"; include_once "/lib/sd_spc.php"; include_once "/lib/sn_tcp_ws.php"; define("SLOT_INT", 8); define("RELAY_OUT", 19); define("RELAY_STATUS", 16); $sid = 1; $rwbuf = ""; $return_value = ""; uio_setup(0, SLOT_INT, "in"); // INT uio_setup(0, RELAY_OUT, "OUT"); uio_setup(0, RELAY_STATUS, "IN"); uio_out(0, RELAY_OUT, LOW); spc_reset(); spc_sync_baud(115200); spc_scan(); spc_request($sid, 4, "set 0 output low"); ir_gesture_setup(0); ws_setup(0, "gesture", "csv.phpoc"); function check_light_status() { if("200,1" == spc_request(1, 4, "get 3 output")) return "on"; else return "off"; } while(1) { $ws_state = ws_state(0); if($ws_state == TCP_CONNECTED) { $return_value = check_light_status(); ws_write(0, $return_value); $rlen = ws_read_line(0, $rwbuf); if($rlen) { //$rwcmd = rtrim($rwbuf, "\r\n"); $rwcmd = (int)$rwbuf; switch ($rwcmd) { case 0: uio_out(0, RELAY_OUT, LOW); break; case 1: uio_out(0, RELAY_OUT, HIGH); break; case 2: $return_value = check_light_status(); if ( "on" == $return_value ) spc_request($sid, 4, "set 3 output low"); else spc_request($sid, 4, "set 3 output high"); break; default: $gesture = "none"; break; } $return_value = check_light_status(); } ws_write(0, $return_value); } else { if(uio_in(0, SLOT_INT) == 0) { if(is_status_register_gint()) { if(is_gesture_status_register_gvalid()) { $res = read_gesture(); $gesture = ""; switch($res) { case DIRECTION_UP: $gesture = "up"; break; case DIRECTION_DOWN: $gesture = "down"; break; case DIRECTION_LEFT: $gesture = "left"; spc_request($sid, 4, "set 3 output high"); break; case DIRECTION_RIGHT: $gesture = "right"; spc_request($sid, 4, "set 3 output low"); break; case DIRECTION_NEAR: $gesture = "near"; break; case DIRECTION_FAR: $gesture = "far"; break; default: $gesture = "none"; break; } } } } } } ?>
Code:
<!DOCTYPE html> <html> <head> <title>PHPoC / <?echo system("uname -i")?></title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"> <style> body { text-align: center; } </style> <script> var ws; function init() { imgChange("light_on.jpg"); var button = document.getElementById("light_canvas"); button.addEventListener("touchstart", mouse_down); // button.addEventListener("touchend", mouse_up); // button.addEventListener("touchcancel", mouse_up); button.addEventListener("mousedown", mouse_down); // button.addEventListener("mouseup", mouse_up); // button.addEventListener("mouseout", mouse_up); connect_onclick(); } function imgChange(imagePath) { var canvas = document.getElementById("light_canvas"); var context = canvas.getContext("2d"); var imageObject = new Image(); imageObject.onload = function(){ context.drawImage(imageObject,0,0); }; imageObject.src=imagePath; } function connect_onclick() { if(ws == null) { var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>"; if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "[")) { // network resource identifier to UNC path name conversion ws_host_addr = ws_host_addr.replace(/[\[\]]/g, ''); ws_host_addr = ws_host_addr.replace(/:/g, "-"); ws_host_addr += ".ipv6-literal.net"; } ws = new WebSocket("ws://" + ws_host_addr + "/gesture", "csv.phpoc"); document.getElementById("ws_state").innerHTML = "CONNECTING"; ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; } else ws.close(); } function mouse_down() { if(ws.readyState == 1) ws.send("2\r\n"); event.preventDefault(); } function mouse_up() { } function ws_onopen() { document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>"; document.getElementById("bt_connect").innerHTML = "Disconnect"; } function ws_onclose() { document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>"; document.getElementById("bt_connect").innerHTML = "Connect"; ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; // document.getElementById("msg").hidden = false; } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; // MessageEvent switch(e_msg.data) { case "on": // on imgChange("light_on.jpg"); break; case "off": // off imgChange("light_off.jpg"); break; default: break; } } window.onload = init; </script> </head> <body> <canvas id="light_canvas" width="194" height="605"></canvas> <br/><br/> <h2>WebSocket <font id="ws_state" color="gray">CLOSED</font></h2> <button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button> </body> </html>
Code:
<?php include_once "/lib/sd_340.php"; define("APDS9960_I2C_ADDRESS", 0x39); define("REGISTER_ENABLE", "\x80"); define("REGISTER_ADC_INTEGRATION_TIME", "\x81"); define("REGISTER_WAIT_TIME", "\x83"); define("REGISTER_ALS_INT_LOW_THRE_LOW", "\x84"); define("REGISTER_ALS_INT_LOW_THRE_HIGH", "\x85"); define("REGISTER_ALS_INT_HIGH_THRE_LOW", "\x86"); define("REGISTER_ALS_INT_HIGH_THRE_HIGH", "\x87"); define("REGISTER_P_INT_LOW_THRESHOLD", "\x89"); define("REGISTER_P_INT_HIGH_THRESHOLD", "\x8B"); define("REGISTER_PERSISTENCE", "\x8C"); define("REGISTER_CONFIG1", "\x8D"); define("REGISTER_P_PULSE_COUNT", "\x8E"); define("REGISTER_CONTROL1", "\x8F"); define("REGISTER_CONFIG2", "\x90"); define("REGISTER_ID", "\x92"); define("REGISTER_STATUS", "\x93"); define("REGISTER_P_OFFSET_UP_RIGHT", "\x9D"); define("REGISTER_P_OFFSET_DOWN_LEFT", "\x9E"); define("REGISTER_CONFIG3", "\x9F"); define("REGISTER_G_P_ENTER_THRESHOLD", "\xA0"); define("REGISTER_G_EXIT_THRESHOLD", "\xA1"); define("REGISTER_G_CONFIG1", "\xA2"); define("REGISTER_G_CONFIG2", "\xA3"); define("REGISTER_G_UP_OFFSET", "\xA4"); define("REGISTER_G_DOWN_OFFSET", "\xA5"); define("REGISTER_G_LEFT_OFFSET", "\xA7"); define("REGISTER_G_RIGHT_OFFSET", "\xA9"); define("REGISTER_G_PULSE_COUNT_AND_LEN", "\xA6"); define("REGISTER_G_CONFIG3", "\xAA"); define("REGISTER_G_CONFIG4", "\xAB"); define("REGISTER_G_FIFO_LEVEL", "\xAE"); define("REGISTER_G_STATUS", "\xAF"); define("REGISTER_G_FIFO_UP", "\xFC"); define("REGISTER_G_FIFO_DOWN", "\xFD"); define("REGISTER_G_FIFO_LEFT", "\xFE"); define("REGISTER_G_FIFO_RIGHT", "\xFF"); define("GESTURE_THRESHOLD_OUT", 10); define("GESTURE_SENSITIVITY_1", 50); define("GESTURE_SENSITIVITY_2", 20); define("DIRECTION_NONE", 0); define("DIRECTION_LEFT", 1); define("DIRECTION_RIGHT", 2); define("DIRECTION_UP", 3); define("DIRECTION_DOWN", 4); define("DIRECTION_NEAR", 5); define("DIRECTION_FAR", 6); define("DIRECTION_ALL", 7); define("PROXIMITY_NA_STATE", 0); define("PROXIMITY_NEAR_STATE", 1); define("PROXIMITY_FAR_STATE", 2); define("PROXIMITY_ALL_STATE", 3); $vd_gesture_fifo_up = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); $vd_gesture_fifo_down = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); $vd_gesture_fifo_left = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); $vd_gesture_fifo_right = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); $vd_i2c_id = 0; $vd_total_gestures = 0; $vd_direction = DIRECTION_NONE; $vd_up_down_delta = 0; $vd_left_right_delta = 0; $vd_up_down_count = 0; $vd_left_right_count = 0; $vd_near_count = 0; $vd_far_count = 0; $vd_proximity_state = PROXIMITY_NA_STATE; function vd_write_register($register_address, $buf) { $wbuf = $register_address.$buf; return i2c_write(0, $wbuf); } function vd_read_register($register_address, &$buf, $length) { global $vd_i2c_id; $wbuf = $register_address; $read = i2c_write_read($vd_i2c_id, $wbuf, $buf, $length); return $read; } define("POWER_ON", 0); define("ALS_ENABLE", 1); define("PROXIMITY_DETECT_ENABLE", 2); define("WAIT_ENABLE", 3); define("ALS_INTERRUPT_ENABLE", 4); define("PROXIMITY_INTERRUPT_ENABLE", 5); define("GESTURE_ENABLE", 6); define("ALL", 7); function vd_set_enable_register($field, $enable) { $rbuf = ""; $read = vd_read_register(REGISTER_ENABLE, $rbuf, 1); if($read == 0) return; $reg_val = bin2int($rbuf, 0, 1); if($field == ALL) { $reg_val = 0x00; if($enable == true) $reg_val = 0x7F; } else { $reg_val &= ~(1 << $field); if($enable == true) $reg_val |= (1 << $field); } return vd_write_register(REGISTER_ENABLE, int2bin($reg_val, 1)); } define("LED_DRIVE_STRENGTH", 0); define("PROXIMITY_GAIN_CONTROL", 1); define("ALS_COLOR_GAIN_CONTROL", 2); function vd_write_control_register1($field, $value) { $rbuf = ""; vd_read_register(REGISTER_CONTROL1, $rbuf, 1); $reg_val = bin2int($rbuf, 0, 1); switch($field) { case LED_DRIVE_STRENGTH: $reg_val &= ~(1 << 6) | (1 << 7); $value = ($value << 6) | $reg_val; break; case PROXIMITY_GAIN_CONTROL: $reg_val &= ~(1 << 2) | (1 << 3); $value = ($value << 2) | $reg_val; break; case ALS_COLOR_GAIN_CONTROL: $reg_val &= ~(1 << 0) | (1 << 1); $value |= $reg_val; break; } return vd_write_register(REGISTER_CONTROL1, int2bin($value, 1)); } function vd_write_als_low_int_threshold($value) { $val_low = ($value & 0x00ff); $val_high = ($value & 0xff00) >> 8; vd_write_register(REGISTER_ALS_INT_LOW_THRE_LOW, int2bin($val_low, 1)); vd_write_register(REGISTER_ALS_INT_LOW_THRE_HIGH, int2bin($val_high, 1)); } function vd_write_als_high_int_threshold($value) { $val_low = ($value & 0x00ff); $val_high = ($value & 0xff00) >> 8; vd_write_register(REGISTER_ALS_INT_HIGH_THRE_HIGH, int2bin($val_high, 1)); vd_write_register(REGISTER_ALS_INT_HIGH_THRE_LOW, int2bin($val_low, 1)); } define("GESTURE_WAIT_TIME", 0); define("GESTURE_LED_DRIVE_STRENGTH", 1); define("GESTURE_GAIN_CONTROL", 2); function vd_write_gesture_config2_register($field, $value) { $rbuf = ""; vd_read_register(REGISTER_G_CONFIG2, $rbuf, 1); $reg_val = bin2int($rbuf, 0, 1); switch($field) { case GESTURE_GAIN_CONTROL: $reg_val &= ~(1 << 5) | (1 << 6); $value = ($value << 5) | $reg_val; break; case GESTURE_LED_DRIVE_STRENGTH: $reg_val &= ~(1 << 3) | (1 << 4); $value = ($value << 3) | $reg_val; break; case GESTURE_WAIT_TIME: $reg_val &= ~(1 << 0) | (1 << 1) | (1 << 2); $value |= $reg_val; break; } return vd_write_register(REGISTER_G_CONFIG2, int2bin($value, 1)); } define("GESTURE_MODE", 0); define("GESTURE_INTERRUPT_ENABLE", 1); function vd_write_gesture_config4_register($field, $value) { $rbuf = ""; vd_read_register(REGISTER_G_CONFIG4, $rbuf, 1); $reg_val = bin2int($rbuf, 0, 1); switch($field) { case GESTURE_MODE: $reg_val &= ~(1 << 0); $value = ($value << 0) | $reg_val; break; case GESTURE_INTERRUPT_ENABLE: $reg_val &= ~(1 << 1); $value = ($value << 1) | $reg_val; break; } return vd_write_register(REGISTER_G_CONFIG4, int2bin($value, 1)); } function vd_write_gesture_led_boost($value) { $rbuf = ""; vd_read_register(REGISTER_CONFIG2, $rbuf, 1); $reg_val = bin2int($rbuf, 0, 1); $reg_val &= ~(1 << 4) | (1 << 5); $reg_val = ($value << 4) | $reg_val; return vd_write_register(REGISTER_G_CONFIG4, int2bin($value, 1)); } function ir_gesture_setup($i2c_id) { global $vd_i2c_id; $vd_i2c_id = $i2c_id; i2c_setup($i2c_id, APDS9960_I2C_ADDRESS, "sm"); // read chip id. $rbuf = ""; $read = vd_read_register(REGISTER_ID, $rbuf, 1); if($read == 0) { echo "Reading ID register has failed.\r\n"; exit; } //---------------------------------------------------------------------------------------------------------------- // Disable all features. vd_set_enable_register(ALL, false); //---------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------- /// Set default values for ambient light and proximity registers vd_write_register(REGISTER_ADC_INTEGRATION_TIME, int2bin(219, 1)); // 219 - 103ms vd_write_register(REGISTER_WAIT_TIME, int2bin(246, 1)); // 246 - 27ms ((256 - 246) * 2.78ms) vd_write_register(REGISTER_P_PULSE_COUNT, "\x87"); // proximity pulse count register: 0x87, 16us, 8 pulses vd_write_register(REGISTER_P_OFFSET_UP_RIGHT, "\x00"); //0 - 0 offset vd_write_register(REGISTER_P_OFFSET_DOWN_LEFT, "\x00"); // 0 - 0 offset vd_write_register(REGISTER_CONFIG1, "\x60"); // do not use 12x wait (WTIME) factor //----------------------------------------------------------------------------------- // Control Register One(0x8F) // LDRIVE - bits 7:6, 0 - 100 mA, 1 - 50 mA, 2 - 25 mA, 3 - 12.5 mA vd_write_control_register1(LED_DRIVE_STRENGTH, 0); // PGAIN - bits 3:2, 0 - 1x, 1 - 2x, 2 - 4x, 3 - 8x vd_write_control_register1(PROXIMITY_GAIN_CONTROL, 2); // AGAIN - bits 1:0, 0 - 1x, 1 - 4x, 2 - 16x, 3 - 64x vd_write_control_register1(ALS_COLOR_GAIN_CONTROL, 1); //----------------------------------------------------------------------------------- vd_write_register(REGISTER_P_INT_LOW_THRESHOLD, "\x00"); // Low proximity threshold vd_write_register(REGISTER_P_INT_HIGH_THRESHOLD, int2bin(50, 1)); // High proximity threshold vd_write_als_low_int_threshold(0xffff); vd_write_als_high_int_threshold(0); vd_write_register(REGISTER_PERSISTENCE, "\x22"); //0x22 // 2 consecutive prox or ALS for int. vd_write_register(REGISTER_CONFIG2, "\x01"); // Configuration Register Two(0x90): no saturation interrupts or LED boost vd_write_register(REGISTER_CONFIG3, "\x00"); // Configuration Three Register(0x9F): Enable all photodiodes, no SAI //---------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------- // Set default values for gesture sense registers vd_write_register(REGISTER_G_P_ENTER_THRESHOLD, int2bin(40, 1)); // Threshold for entering gesture mode vd_write_register(REGISTER_G_EXIT_THRESHOLD, int2bin(30, 1)); // threshold for exit gesture proximity vd_write_register(REGISTER_G_CONFIG1, "\x40"); // Gesture Configuration One Register(0xA2): interrupt is generated after 4 datasets are added to FIFO. //----------------------------------------------------------------------------------- // Gesture Configuration Two Register(0xA3) // GGAIN - bits 6:5, 0 - 1x, 1 - 2x, 2 - 4x, 3 - 8x vd_write_gesture_config2_register(GESTURE_GAIN_CONTROL, 2); // GLDRIVE - bits 4:3, 0 - 100mA, 1 - 50mA, 2 - 25mA, 3 - 12.5mA vd_write_gesture_config2_register(GESTURE_LED_DRIVE_STRENGTH, 0); // GWTIME - bits 2:0, 0 - 0ms, 1 - 2.8ms, 2 - 5.6ms, 3 - 8.4ms, 4 - 14.0ms, 5 - 22.4ms, 6 - 30.8ms, 7 - 39.2ms vd_write_gesture_config2_register(GESTURE_WAIT_TIME, 1); //----------------------------------------------------------------------------------- vd_write_register(REGISTER_G_UP_OFFSET, "\x00"); vd_write_register(REGISTER_G_DOWN_OFFSET, "\x00"); vd_write_register(REGISTER_G_LEFT_OFFSET, "\x00"); vd_write_register(REGISTER_G_RIGHT_OFFSET, "\x00"); // Gesture Pulse Count and Length Register(0xA6) // GPLEN : bits 7:6, 0 - 4us, 1 - 8us(default), 2 - 16us, 3 - 32us // GPULSE : bits 5:0, 0 - 1, 1 - 2, 2 - 3, ..... 63 - 64. vd_write_register(REGISTER_G_PULSE_COUNT_AND_LEN, "\xC9"); // 32us, 10 pulses // Gesture Configuration Three Register(0xAA) vd_write_register(REGISTER_G_CONFIG3, "\x00"); // All photodiodes active during gesture //----------------------------------------------------------------------------------- // Gesture Configuration Four Register(0xAB) // GIEN(Gesture interrupt enable) bits 1. vd_write_gesture_config4_register(GESTURE_INTERRUPT_ENABLE, 0); // Disable gesture interrupts //----------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------- // enable gesture sensor vd_write_register(REGISTER_WAIT_TIME, "\xff"); // ((256 - 255) * 2.78ms) = 2.78ms vd_write_register(REGISTER_P_PULSE_COUNT, "\x89"); // proximity pulse count register: 16us, 10 pulses vd_write_gesture_led_boost(3); //LED_BOOST: bits 5:4, 0 - 100%, 1 - 150%, 2 - 200%, 3 - 300% //----------------------------------------------------------------------------------- // Gesture Configuration Four Register(0xAB) // GIEN(Gesture interrupt enable) bits 1. vd_write_gesture_config4_register(GESTURE_INTERRUPT_ENABLE, 1); // GMODE(Gesture mode) bits 0. vd_write_gesture_config4_register(GESTURE_MODE, 1); //----------------------------------------------------------------------------------- //----------------------------------------------------------------------------------- // Enable Register(0x80) vd_set_enable_register(POWER_ON, true); // PON(power on) bits 0. vd_set_enable_register(WAIT_ENABLE, true);// WEN(wait enable) bits 3. vd_set_enable_register(PROXIMITY_DETECT_ENABLE, true); // PEN(proximity detect enable) bits 2. vd_set_enable_register(GESTURE_ENABLE, true); // GEN(gesture enable) bits 6. //----------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------- } function read_enable_register() { $rbuf = ""; vd_read_register(REGISTER_ENABLE, $rbuf, 1); return bin2int($rbuf, 0, 1); } function is_gesture_status_register_gvalid() { $rbuf = ""; vd_read_register(REGISTER_G_STATUS, $rbuf, 1); $status = bin2int($rbuf, 0, 1); $status &= 0b00000001; return $status == 1 ? true : false; } function is_status_register_gint() { $rbuf = ""; vd_read_register(REGISTER_STATUS, $rbuf, 1); $status = bin2int($rbuf, 0, 1); return ($status & (1 << 2)) ? true : false; } function process_gesture_data() { global $vd_gesture_fifo_up, $vd_gesture_fifo_down, $vd_gesture_fifo_left, $vd_gesture_fifo_right; global $vd_total_gestures; global $vd_up_down_delta; global $vd_left_right_delta; global $vd_up_down_count; global $vd_left_right_count; global $vd_near_count; global $vd_far_count; global $vd_proximity_state; $first_up = $first_down = $first_left = $first_right = 0; $last_up = $last_down = $last_left = $last_right = 0; /* If we have less than 4 total gestures, that's not enough */ if($vd_total_gestures <= 4) return -1; /* Check to make sure our data isn't out of bounds */ if(($vd_total_gestures <= 32 ) && ($vd_total_gestures > 0)) { /* Find the first value in U/D/L/R above the threshold */ for($i = 0;$i < $vd_total_gestures;$i++) { if(($vd_gesture_fifo_up[$i] > GESTURE_THRESHOLD_OUT) && ($vd_gesture_fifo_down[$i] > GESTURE_THRESHOLD_OUT) && ($vd_gesture_fifo_left[$i] > GESTURE_THRESHOLD_OUT) && ($vd_gesture_fifo_right[$i] > GESTURE_THRESHOLD_OUT)) { $first_up = $vd_gesture_fifo_up[$i]; $first_down = $vd_gesture_fifo_down[$i]; $first_left = $vd_gesture_fifo_left[$i]; $first_right = $vd_gesture_fifo_right[$i]; break; } } /* If one of the _first values is 0, then there is no good data */ if(($first_up == 0) || ($first_down == 0) || ($first_left == 0) || ($first_right == 0)) return -1; /* Find the last value in U/D/L/R above the threshold */ for($i = $vd_total_gestures - 1;$i >= 0;$i--) { if(($vd_gesture_fifo_up[$i] > GESTURE_THRESHOLD_OUT) && ($vd_gesture_fifo_down[$i] > GESTURE_THRESHOLD_OUT) && ($vd_gesture_fifo_left[$i] > GESTURE_THRESHOLD_OUT) && ($vd_gesture_fifo_right[$i] > GESTURE_THRESHOLD_OUT)) { $last_up = $vd_gesture_fifo_up[$i]; $last_down = $vd_gesture_fifo_down[$i]; $last_left = $vd_gesture_fifo_left[$i]; $last_right = $vd_gesture_fifo_right[$i]; break; } } } /* Calculate the first vs. last ratio of up/down and left/right */ $up_down_ratio_first = (($first_up - $first_down) * 100) / ($first_up + $first_down); $left_right_ratio_first = (($first_left - $first_right) * 100) / ($first_left + $first_right); $up_down_ratio_last = (($last_up - $last_down) * 100) / ($last_up + $last_down); $left_right_ratio_last = (($last_left - $last_right) * 100) / ($last_left + $last_right); /* Determine the difference between the first and last ratios */ $delta1 = $up_down_ratio_last - $up_down_ratio_first; $delta2 = $left_right_ratio_last - $left_right_ratio_first; /* Accumulate the UD and LR delta values */ $vd_up_down_delta += $delta1; $vd_left_right_delta += $delta2; /* Determine U/D gesture */ if($vd_up_down_delta >= GESTURE_SENSITIVITY_1) $vd_up_down_count = 1; else if($vd_up_down_delta <= -GESTURE_SENSITIVITY_1) $vd_up_down_count = -1; else $vd_up_down_count = 0; /* Determine L/R gesture */ if($vd_left_right_delta >= GESTURE_SENSITIVITY_1) $vd_left_right_count = 1; else if($vd_left_right_delta <= -GESTURE_SENSITIVITY_1) $vd_left_right_count = -1; else $vd_left_right_count = 0; /* Determine Near/Far gesture */ if(($vd_up_down_count == 0) && ($vd_left_right_count == 0)) { if((abs($vd_up_down_delta) < GESTURE_SENSITIVITY_2 ) && (abs($vd_left_right_delta) < GESTURE_SENSITIVITY_2)) { if(($vd_up_down_delta == 0) && ($vd_left_right_delta == 0)) $vd_near_count++; else if(($vd_up_down_delta != 0) || ($vd_left_right_delta != 0)) $vd_far_count++; if(($vd_near_count >= 10) && ($vd_far_count >= 2)) { if(($vd_up_down_delta == 0) && ($vd_left_right_delta == 0)) $vd_proximity_state = PROXIMITY_NEAR_STATE; else if(($vd_up_down_delta != 0) && ($vd_left_right_delta != 0)) $vd_proximity_state = PROXIMITY_FAR_STATE; return 0; } } } else { if((abs($vd_up_down_delta) < GESTURE_SENSITIVITY_2) && (abs($vd_left_right_delta) < GESTURE_SENSITIVITY_2)) { if(($vd_up_down_delta == 0) && ($vd_left_right_delta == 0)) $vd_near_count++; if($vd_near_count >= 10) { $vd_up_down_count = 0; $vd_left_right_count = 0; $vd_up_down_delta = 0; $vd_left_right_delta = 0; } } } return -1; } function decode_gesture() { global $vd_proximity_state; global $vd_direction; global $vd_up_down_count, $vd_left_right_count; global $vd_up_down_delta, $vd_left_right_delta; if($vd_proximity_state == PROXIMITY_NEAR_STATE) { $vd_direction = DIRECTION_NEAR; return 0; } else if($vd_proximity_state == PROXIMITY_FAR_STATE) { $vd_direction = DIRECTION_FAR; return 0; } /* Determine swipe direction */ if(($vd_up_down_count == -1) && ($vd_left_right_count == 0)) $vd_direction = DIRECTION_UP; else if(($vd_up_down_count == 1) && ($vd_left_right_count == 0)) $vd_direction = DIRECTION_DOWN; else if(($vd_up_down_count == 0) && ($vd_left_right_count == 1)) $vd_direction = DIRECTION_RIGHT; else if(($vd_up_down_count == 0) && ($vd_left_right_count == -1)) $vd_direction = DIRECTION_LEFT; else if(($vd_up_down_count == -1) && ($vd_left_right_count == 1)) { if(abs($vd_up_down_delta) > abs($vd_left_right_delta)) $vd_direction = DIRECTION_UP; else $vd_direction = DIRECTION_RIGHT; } else if(($vd_up_down_count == 1) && ($vd_left_right_count == -1)) { if(abs($vd_up_down_delta) > abs($vd_left_right_delta)) $vd_direction = DIRECTION_DOWN; else $vd_direction = DIRECTION_LEFT; } else if(($vd_up_down_count == -1) && ($vd_left_right_count == -1)) { if(abs($vd_up_down_delta) > abs($vd_left_right_delta)) $vd_direction = DIRECTION_UP; else $vd_direction = DIRECTION_LEFT; } else if(($vd_up_down_count == 1) && ($vd_left_right_count == 1)) { if(abs($vd_up_down_delta) > abs($vd_left_right_delta)) $vd_direction = DIRECTION_DOWN; else $vd_direction = DIRECTION_RIGHT; } else return -1; return 0; } function read_gesture() { global $vd_gesture_fifo_up, $vd_gesture_fifo_down, $vd_gesture_fifo_left, $vd_gesture_fifo_right; global $vd_total_gestures; global $vd_direction; global $vd_up_down_delta; global $vd_left_right_delta; global $vd_up_down_count; global $vd_left_right_count; global $vd_near_count; global $vd_far_count; global $vd_proximity_state; if(!is_gesture_status_register_gvalid() || !(read_enable_register() & 0b01000001)) return DIRECTION_NONE;; $rbuf = ""; $fifo_count = 0; $index = 0; $vd_total_gestures = 0; $vd_direction = DIRECTION_NONE; $vd_up_down_delta = 0; $vd_left_right_delta = 0; $vd_up_down_count = 0; $vd_left_right_count = 0; $vd_near_count = 0; $far_counbt = 0; $vd_proximity_state = PROXIMITY_NA_STATE; while(1) { if(is_gesture_status_register_gvalid()) { $rbuf = ""; $wbuf = REGISTER_G_FIFO_LEVEL; $read = i2c_write_read(0, $wbuf, $rbuf, 1); if($read == 0) $fifo_count = 0; else $fifo_count = bin2int($rbuf, 0, 1); if($fifo_count > 0) { $rbuf = ""; $wbuf = REGISTER_G_FIFO_UP; $read = i2c_write_read(0, $wbuf, $rbuf, $fifo_count * 4); for($i = 0;$i < $fifo_count * 4;$i += 4) { $vd_gesture_fifo_up[$index] = bin2int($rbuf[$i], 0, 1); $vd_gesture_fifo_down[$index] = bin2int($rbuf[$i + 1], 0, 1); $vd_gesture_fifo_left[$index] = bin2int($rbuf[$i + 2], 0, 1); $vd_gesture_fifo_right[$index] = bin2int($rbuf[$i + 3], 0, 1); $index++; $vd_total_gestures++; } //------------------------------------------------- if(!process_gesture_data()) { if(!decode_gesture()) { } } //------------------------------------------------- $index = 0; $vd_total_gestures = 0; } } else { decode_gesture(); return $vd_direction; } } } ?>