Hackster is hosting Hackster Holidays, Finale: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Tuesday!Stream Hackster Holidays, Finale on Tuesday!
Gyusik Song
Published © GPL3+

Control Light via Motion or Web

This project uses the web or motion to control a light.

IntermediateShowcase (no instructions)6 hours837
Control Light via Motion or Web

Things used in this project

Hardware components

PHPoC Blue
PHPoC Blue
×1
PHPoC mikroBUS Expansion Board
PHPoC mikroBUS Expansion Board
×1
MIKROE IR Gesture click
×1
Light
×1
PHPoC 4-Port Relay Expansion Board (S-type or T-type)
PHPoC 4-Port Relay Expansion Board (S-type or T-type)
×1

Story

Read more

Code

task0.php

PHP
<?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;
                    }
                }
            }
        }        
    }
}
 
?>

index.php

PHP
<!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>

vd_ir_gesture_click.php

PHP
<?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;
		}
	}
}
?>

Credits

Gyusik Song
5 projects • 9 followers

Comments