Introduction

In a previous article, I introduced internet IR solution. It has advantage and disadvantages as follows:

Advantages:
  • Extend the control distance to unlimited, allowing controlling devices everywhere.
Disadvantages:
  • Require to capture IR signal, analyze it to get data (devices address and command), it may be difficult for a newbie to understand.
  • Specific to a kind of device, it need to capture IR signal, analyze again for new devices.

To take advantage and overcome the shortcoming of the previous solution, I introduce a new method: IR imitator. This solution allows imitating IR signal of any controller, save it in memory and then control it through internet.

There are two more advantages:
  • No need to analyze IR signal.
  • Work with every device.

The following image illustrates how system work.

Click image for larger version  Name:	imitator_how_system_work.gif Views:	1 Size:	580.4 KB ID:	494

User can use smart phone, computer or any kind devices which support web browser to access web application. This web application can switch between two modes: imitating mode (setting mode) and control mode.

Setting mode:
  • Capture IR pulse chain from any remote controller,
  • Assign a button to this pulse chain,
  • Save this chain in FLASH memory along with a selected button.
Control mode:
  • Buttons which were assigned to pulse chain will be activated
  • If an activated button is clicked, the control command will be sent along with the button name to PHPoC. PHPoC lookup the pulse chain with respect to button name in memory. And then the pulse chain will be outputted to IR emitter. Therefore, you can control your devices.


Demo





Things Used In This Project

Wiring Diagram

Click image for larger version  Name:	IR_repeater_wiring.PNG Views:	2 Size:	59.9 KB ID:	488



Working Flow

Setting mode
Click image for larger version  Name:	image_267.png Views:	43 Size:	84.3 KB ID:	496


Controlling mode

Click image for larger version  Name:	image_269.png Views:	62 Size:	78.1 KB ID:	495


Source Code

Client side (index.php)

PHP Code:
<!DOCTYPE html>
<html>
<head>
    <title>PHPoC</title>
    <meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=1.0, minimum-scale=0.5, user-scalable=yes">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style type="text/css">
        body { font-family: verdana, Helvetica, Arial, sans-serif, gulim; }                        
        .superHeader {height: 2em; color: white; background-color: rgb(0,153,153);; z-index:5;}        
        .gap {height: 5px;z-index:0;}
        .midHeader {color: white; background-color: rgb(6, 38, 111);  z-index:3;}
        .headerTitle {
            font-size: 250%;
            font-weight: normal;
            font-family: impact;
            padding: 5px;
        }
        .headerMenu{        
            width: 450px;
            padding: 5px;
        }
        #footer{margin:0 auto; height:auto !important; height:100%; margin-bottom:-100px;  }
        .superFooter {
            height: 2em; color: white; background-color: rgb(6, 38, 111); font-size:9pt; position:fixed; left:0; right:0; bottom:0; z-index:4;
        }    
        #control_area {
            margin-right: auto;
            margin-left: auto;
            width: 480px;
            height: 480px;
            position: relative;            
        }
        .button1, .button2 {
            background-color: LightGray;
            border-width:2px;    
            border-style:groove;
            color: white;

            text-align: center;
            text-decoration: none;
            display: inline-block;
            cursor: pointer;
            position: absolute;    
            z-index:3;            
        }
        .button1 {            
            font-size: 20px;                
            border-radius: 50%;            
        }

        #setup_area {
            margin-top: 10px;
            margin-right: auto;
            margin-left: auto;
            width: 480px;
            height: 100px;
            position: relative;
            margin-bottom: 10px;
            display: none;
        }
        .button2 {
            float: right;    
            margin: 5px;
            margin-right:10px;
            width: 80px;
            height: 40px;    
            line-height: 40px;            
            font-size: 18px;                        
            border-radius: 50%;
        }
        #SCAN {
            float: right;            
        }    
        #SAVE {
            float: right;            
        }        
        #bar {
            background-color : rgb(6, 38, 111);
            width: 350px; height: 5px;
            z-index:3;
        }        
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script type="text/javascript">

    //command sent from client to PHPoC
    var CMD_GET_CONFIG = 0x01;
    var CMD_CONTROL = 0x02;
    var CMD_UPDATE = 0x03;
    var CMD_SCAN = 0x04;
    var CMD_TEST = 0x05;
    var CMD_SCAN_CANCEL = 0x06;

    //command sent from PHPoC to client
    var _CMD_CONFIG_DATA = 0x11;
    var _CMD_SCANNED = 0x12;
    var _CMD_UPDATED = 0x13;

    var MODE_NOMAL = 0;
    var MODE_SETTING = 1;

    var STATE_UNSCAN = 0x01;
    var STATE_SCANNING = 0x02;
    var STATE_SCANNED = 0x03;

    var setup_state = STATE_UNSCAN;// state of setup mode

    var btn_states = null; // an array to store button state (clickable or unclickable)
    var mode = MODE_NOMAL;

    var color_clickable = "DarkCyan";
    var color_clicked = "Aqua";
    var color_unclickable = "LightGray";
    var color_setup = "OrangeRed";

    var btn_array = [
        ["A", "B", "C"],
        ["D", "E", "F"],
        ["G", "H", "I"]
    ];

    var setup_button_id = null;
    var connected = false;

    var ws = null;

    function init()
    {
        var view = document.querySelector("#mode_option");
        view.onclick = option_onclick;

        var controls = document.querySelector("#control_area");
        var setups = document.querySelector("#setup_area");

        controls.ontouchstart = setups.ontouchstart = mouse_down;
        controls.ontouchend = setups.ontouchend = mouse_up;
        controls.ontouchcancel = setups.ontouchcancel = mouse_up;
        controls.onmousedown = setups.onmousedown = mouse_down;
        controls.onmouseup = setups.onmouseup = mouse_up;
        controls.onmouseout = setups.onmouseout = mouse_up;  

        var btn_width = 70;
        var btn_height = 70;
        var gap = 30;

        controls.style.width = (3*btn_width + 4*gap) + "px";
        controls.style.height = (3*btn_height + 4*gap) + "px";

        var y = gap;
        var x = gap;

        for(var j = 0; j < 3; j++)
        {
            for(var i = 0; i < 3; i++)
            {
                var button = document.getElementById(btn_array[i][j]);
                button.style.width = btn_width + "px";
                button.style.height = btn_height + "px";
                button.style.lineHeight = btn_height + "px";
                button.style.left = x + "px";
                button.style.top = y + "px";
                y += btn_height + gap;
            }
            x += btn_width + gap;
            y = gap;
        }

        var width = (3*btn_width + 4*gap);
        setups.style.width = width + "px";
        setups.style.height = (100 + gap) + "px";    

        var button = document.getElementById("SCAN");
        button.style.left = 2*gap + "px";
        button.style.top = "0px";

        button = document.getElementById("TEST");
        button.style.left = (width-2*gap-80) + "px";
        button.style.top = "0px";

        button = document.getElementById("SAVE");
        button.style.left = (width/2 - 40) + "px";
        button.style.top = "50px";

    }

    function ws_onmessage(e_msg)
    {
        var arr = JSON.parse(e_msg.data);

        switch(arr.cmd)
        {
            case _CMD_CONFIG_DATA:
                btn_states = arr.data;
                break;
            case _CMD_SCANNED:
                setup_state = STATE_SCANNED;
                break;
            case _CMD_UPDATED:
                setup_state = STATE_UNSCAN;
                setup_button_id = null;
                btn_states = arr.data;                
                break;
        }
        update_view();
    }

    function ws_onopen()
    {
        document.getElementById("ws_state").innerHTML = "OPEN";
        document.getElementById("wc_conn").innerHTML = "Disconnect";
        send_command(CMD_GET_CONFIG);
        connected = true;
    }

    function ws_onclose()
    {
        document.getElementById("ws_state").innerHTML = "CLOSED";
        document.getElementById("wc_conn").innerHTML = "Connect";
        console.log("socket was closed");

        ws.onopen = null;
        ws.onclose = null;
        ws.onmessage = null;
        ws = null;

        connected = false;
        setup_state = STATE_UNSCAN;

        update_view();
    }

    function wc_onclick()
    {
        if(ws == null)
        {
            ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/phpoc_infrared", "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(event)
    {
        if (connected && event.target !== event.currentTarget)
        {
            var id = event.target.id;
            if(event.currentTarget.id == "control_area")
            {
                if(mode == MODE_NOMAL)
                {
                    if (btn_states != null && btn_states[id])
                    {
                        event.target.style.backgroundColor = color_clicked;
                        send_command(CMD_CONTROL + " " + id);
                    }
                }
                else
                {
                    setup_button_id = id;
                    update_view();                    
                }
            }
            else if (event.currentTarget.id == "setup_area")
            {
                switch (id)
                {
                    case "SCAN":
                        setup_state = STATE_SCANNING;
                        send_command(CMD_SCAN);
                        event.target.style.backgroundColor = color_clicked;
                        break;
                    case "SAVE":
                        if(setup_button_id != null && setup_state == STATE_SCANNED)
                        {
                            send_command(CMD_UPDATE + " " + setup_button_id);

                            document.getElementById("SCAN").style.backgroundColor = color_clicked;
                            document.getElementById("SAVE").style.backgroundColor = color_clicked;
                            document.getElementById("TEST").style.backgroundColor = color_unclickable;
                        }
                        break;
                    case "TEST":
                        if(setup_button_id != null && setup_state == STATE_SCANNED)
                        {
                            send_command(CMD_TEST);
                            event.target.style.backgroundColor = color_clicked;
                        }
                        break;
                }
            }
        }
        event.stopPropagation();    
        event.preventDefault();    
    }

    function mouse_up(event)
    {
        if (connected && event.target !== event.currentTarget)
        {
            if(mode == MODE_NOMAL)
            {
                var id = event.target.id;
                if (btn_states != null && btn_states[id])
                    event.target.style.backgroundColor = color_clickable;
            }
            else if(setup_button_id != null && setup_state == STATE_SCANNED)
                document.getElementById("TEST").style.backgroundColor = color_clickable;            
        }
        event.stopPropagation();  
        event.preventDefault();    
    }    

    function option_onclick(event)
    {
        if (event.target !== event.currentTarget)
        {
            var id = event.target.id;

            setup_state = STATE_UNSCAN;
            setup_button_id = null;

            if(id == "setup")
            {                
                mode = MODE_SETTING;                
                $("#setup_area").show();        
            }
            else
            {
                mode = MODE_NOMAL;
                send_command(CMD_SCAN_CANCEL);
                $("#setup_area").hide();                
            }

            update_view();
        }
    }

    function send_command(cmd)
    {    
        if(ws != null)
            if(ws.readyState == 1)
                ws.send(cmd + " \r\n");    
        console.log("send comand" + cmd);
    }

    function update_view()
    {
        if(connected)
        {
            if(mode == MODE_NOMAL)
            {
                for (btn in btn_states)
                {
                    if (btn_states[btn])
                        document.getElementById(btn).style.backgroundColor = color_clickable;
                    else
                        document.getElementById(btn).style.backgroundColor = color_unclickable;
                }

                document.getElementById("SCAN").style.backgroundColor = color_unclickable;
                document.getElementById("SAVE").style.backgroundColor = color_unclickable;
                document.getElementById("TEST").style.backgroundColor = color_unclickable;
            }                
            else
            {
                for (btn in btn_states)
                {
                    if (btn_states[btn])
                        document.getElementById(btn).style.backgroundColor = color_clickable;
                    else
                        document.getElementById(btn).style.backgroundColor = color_unclickable;

                    if (setup_button_id != null && btn == setup_button_id)
                        document.getElementById(btn).style.backgroundColor = color_setup;

                }

                switch(setup_state)
                {
                    case STATE_UNSCAN:
                        document.getElementById("SCAN").style.backgroundColor = color_clickable;
                        document.getElementById("SAVE").style.backgroundColor = color_unclickable;
                        document.getElementById("TEST").style.backgroundColor = color_unclickable;
                        break;
                    case STATE_SCANNING:
                        // SCAN button is blinking. see setInterval function
                        document.getElementById("SAVE").style.backgroundColor = color_unclickable;
                        document.getElementById("TEST").style.backgroundColor = color_unclickable;
                        break;
                    case STATE_SCANNED:
                        document.getElementById("SCAN").style.backgroundColor = color_clicked;
                        document.getElementById("SAVE").style.backgroundColor = color_clickable;
                        document.getElementById("TEST").style.backgroundColor = color_clickable;
                        break;
                }                
            }
        }
        else
        {
            for(var j = 0; j < 3; j++)
                for(var i = 0; i < 3; i++)
                    document.getElementById(btn_array[i][j]).style.backgroundColor = color_unclickable;

            document.getElementById("SAVE").style.backgroundColor = color_unclickable;
            document.getElementById("SCAN").style.backgroundColor = color_unclickable;
            document.getElementById("TEST").style.backgroundColor = color_unclickable;
        }
    }

    setInterval(function () {
        $("#SCAN").css("background-color", function () {
            if(setup_state == STATE_SCANNING)
            {
                this.switch = !this.switch
                return this.switch ? color_clickable : color_clicked;
            }
        });
    }, 500);

    window.onload = init;
    </script>
</head>
<body>
    <center>
        <div class="superHeader"></div>
        <div class="gap"></div>
        <div class="midHeader">        
            <div class="headerTitle">PHPoC Smart IR</div>
            <div class="headerMenu">
                <div id="mode_option" >
                    <input type="radio" id="normal" name="mode" value="normal" checked> REMOTE CON
                    <input type="radio" id="setup" name="mode" value="setup"> SETTUP
                </div>                    
            </div>                    
        </div>                            
        <div id="control_area">
            <div id ="A" class="button1">A</div>
            <div id ="B" class="button1">B</div>
            <div id ="C" class="button1">C</div>
            <div id ="D" class="button1">D</div>
            <div id ="E" class="button1">E</div>
            <div id ="F" class="button1">F</div>
            <div id ="G" class="button1">G</div>
            <div id ="H" class="button1">H</div>
            <div id ="I" class="button1">I</div>

        </div>    
        <div id="bar"></div>
        <div id="setup_area">
            <div id ="SAVE" class="button2">save</div>
            <div id ="TEST" class="button2">test</div>
            <div id ="SCAN" class="button2">scan</div>
        </div>    
        <p>
        WebSocket : <span id="ws_state">null</span><br>
        </p>
        <button id="wc_conn" type="button" onclick="wc_onclick();">Connect</button>
        <div id="footer">
            <div class="superFooter">
            </div>
        </div>    
    </center>    
</body>
</html>




Server side (task0.php)

PHP Code:
<?php

if(_SERVER("REQUEST_METHOD"))
    exit; 
// avoid php execution via http request

include_once "/lib/sd_340.php";
include_once 
"/lib/sc_envu.php";
include_once 
"/lib/sn_tcp_ws.php";
include_once 
"/lib/vd_nec_infrared.php";

define("CMD_GET_CONFIG",   0x01); // client to server
define("CMD_CONTROL",   0x02);
define("CMD_UPDATE",   0x03);
define("CMD_SCAN",   0x04);
define("CMD_TEST",   0x05);
define("CMD_SCAN_CANCEL",   0x06);

define("_CMD_CONFIG_DATA",   0x11); // server to client
define("_CMD_SCANNED",   0x12);
define("_CMD_UPDATED",   0x13);

$nvp_list "";

/**
    This function is used to load data from flash memory right after bootup.
**/
function load_data()
{
    global 
$nvp_list;

    
$envu =  envu_read("envu");
    if( 
$envu === "")
    {
        
$envu "A=>0=>0=>0=>0\r\nB=>0=>0=>0=>0\r\nC=>0=>0=>0=>0\r\nD=>0=>0=>0=>0\r\nE=>0=>0=>0=>0\r\nF=>0=>0=>0=>0\r\nG=>0=>0=>0=>0\r\nH=>0=>0=>0=>0\r\nI=>0=>0=>0=>0";
        
envu_write("envu"$envustrlen($envu), 0);
        
$envu =  envu_read("envu");
    }

    
$nvp_list explode("\r\n"$envu9);    

    for(
$i 0$i count($nvp_list); $i++)
    {
        
$nvp explode("=>"$nvp_list[$i], 5);
        
$nvp_list[$i] = $nvp;
    }
}

/**
    This function get button state and format it to json string.
**/
function get_config($cmd _CMD_CONFIG_DATA)
{
    global 
$nvp_list;

    
$json_str '{"cmd":' sprintf("%d"$cmd1)  . ', "data":{';

    for(
$i 0$i count($nvp_list); $i++)
    {
        
$nvp $nvp_list[$i];
        
//$nvp[0] is button name, $nvp[1] is buton's state: 0->unset,  1:->set
        
$json_str .= ('"' $nvp[0]. '":' .$nvp[1]. ',');
    }

    
$json_str rtrim($json_str","); // remove the last comma
    
$json_str .= "}}";

    return  
$json_str;
}

function 
control($button)
{
    global 
$nvp_list;

    for(
$i 0$i count($nvp_list); $i++)
    {
        
$nvp $nvp_list[$i];

        if( (
$nvp[0] == $button) && ((int)$nvp[1] == 1))
        {
            
infrared_emit($nvp[4], (int)$nvp[2], (float)$nvp[3]);  
            break;
        }
    }
}

function 
update($btn_name$btn_state$count_buf$count$unit)
{
    global 
$nvp_list;

    
$btn_name  ltrim(rtrim($btn_name));
    
$btn_state sprintf("%d"$btn_state1);
    
$count sprintf("%d"$count);
    
$unit sprintf("%.1f"$unit);            

    
$envu "";

    for(
$i 0$i count($nvp_list); $i++)
    {        
        if(
$nvp_list[$i][0] == $btn_name)
        {                        
            
$nvp_list[$i][0] = $btn_name// button name
            
$nvp_list[$i][1] = $btn_state// button state: 0->unset, 1->set
            
$nvp_list[$i][2] = $count;
            
$nvp_list[$i][3] = $unit;
            
$nvp_list[$i][4] = $count_buf;                        
        }    

        
$envu .= ($nvp_list[$i][0] . "=>" $nvp_list[$i][1] . "=>" $nvp_list[$i][2] . "=>" $nvp_list[$i][3] . "=>" $nvp_list[$i][4]."\r\n");
    }    

    
$envu rtrim($envu"\r\n");

    
envu_write("envu"$envustrlen($envu), 0);

    
envu_read("envu");
}

$rbuf "";
$unit 562.5 5;
$repc 80;
$lower_bound 1000;
$upper_bound 14000;
$min_count 15;

$count_buf "";
$cnt_buf_len 0;

$is_scanning false;

ws_setup(0"phpoc_infrared""csv.phpoc");

load_data();
//hexdump( get_config());

while(1)
{        
    if(
ws_state(0) == TCP_CONNECTED)
    {
        
$rlen ws_read_line(0$rbuf);

        if(
$rlen)
        {
            
$data explode(" "$rbuf);
            
$cmd = (int)$data[0];
            switch(
$cmd)
            {
                case 
CMD_GET_CONFIG:
                    
ws_write(0get_config());
                    break;    

                case 
CMD_CONTROL:
                    
control($data[1]);
                    break;

                case 
CMD_TEST:
                    
infrared_emit($count_buf$cnt_buf_len$unit);  
                    break;

                case 
CMD_UPDATE:                                    
                    
//update
                    
update($data[1], 1$count_buf$cnt_buf_len$unit);                    
                    
ws_write(0get_config(_CMD_UPDATED));        

                    
$is_scanning false;                    
                    break;

                case 
CMD_SCAN:
                    
$is_scanning true;                    
                    break;

                case 
CMD_SCAN_CANCEL:
                    
$is_scanning false;                    
                    break;                    
            }            
        }
    }
    else
        
$is_scanning false;

    if(
$is_scanning)
    {
        
infrared_capture_start($unit$repc);
        
usleep(500000);    
        
infrared_recv_stop();

        if(
infrared_available($lower_bound$upper_bound))
        {
            echo 
"\r\n";
            
$count_buf int2bin(12);    // first value is dummy.
            
$cnt_buf_len 1;

            for(
$i 0$i <= $repc$i++)
            {
                
//get width of pulses
                
$count infrared_get_raw_count($i);

                if(
$count && $count <100)
                {
                    
$count_buf .= int2bin($count2);  
                    
$cnt_buf_len++;
                    echo 
"$count, ";
                }
            }

            if( 
$cnt_buf_len >= $min_count)
            {
                if(
ws_state(0) == TCP_CONNECTED)
                {
                    
ws_write(0'{"cmd":' sprintf("%d"_CMD_SCANNED1) . '}');
                }

                
$is_scanning false;
            }
        }  
    }        
}

?>




Library (vd_nec_infrared.php)

PHP Code:
<?php

if(_SERVER("REQUEST_METHOD"))
    exit; 
// avoid php execution via http request

include_once "/lib/sd_340.php";

define("BASIC_CLOCK",   42000000); // basic clock of PHPoC 42MHz

$recv_ht_id 0// timer id which connect to an infrared receiver to capture data
$emit_control_ht_id 1// timer id which control an infrared emitter
$emit_carrier_ht_id 2// timer id which create the carier for infrared modulation

function infrared_setup($rec_ht_id$control_ht_id$carrier_ht_id)
{
    global 
$recv_ht_id;
    global 
$emit_control_ht_id;
    global 
$emit_carrier_ht_id;

    
$recv_ht_id $rec_ht_id;
    
$emit_control_ht_id $control_ht_id;
    
$emit_carrier_ht_id $carrier_ht_id;
}
/*
This function make timer to start capturing signal from an infrared receiver.
It is used to analyze the pulse chain, so it it set to capture toggle mode.
Paramerer:
    -$unit (microsecond);
    -$repc: the number of pulse need to be captured
*/
function infrared_capture_start($unit$repc)
{
    global 
$recv_ht_id;

    
$repc++; // plus one dummy pulse
    
$unit $unit BASIC_CLOCK 1000000;
    
// setup capture timer
    
ht_ioctl($recv_ht_id"reset");
    
ht_ioctl($recv_ht_id"set div $unit");
    
ht_ioctl($recv_ht_id"set mode capture toggle");
    
ht_ioctl($recv_ht_id"set trigger from pin fall");
    
ht_ioctl($recv_ht_id"set repc $repc");
    
ht_ioctl($recv_ht_id"start"); // start trigger pulse    
}

/*
This function make timer to start capturing signal from an infrared receiver.
It is used to get data, so it it set to capture fall mode.
Paramerer:
    -$unit (microsecond);
    -$repc: the number of pulse need to be captured
*/
function infrared_recv_start($unit$repc)
{
    global 
$recv_ht_id;

    
$repc++; // plus one dummy pulse
    
$unit $unit BASIC_CLOCK 1000000;
    
// setup capture timer
    
ht_ioctl($recv_ht_id"reset");
    
ht_ioctl($recv_ht_id"set div $unit");
    
ht_ioctl($recv_ht_id"set mode capture fall");
    
ht_ioctl($recv_ht_id"set trigger from pin fall");
    
ht_ioctl($recv_ht_id"set repc $repc");
    
ht_ioctl($recv_ht_id"start"); // start trigger pulse    
}

function 
infrared_recv_stop()
{
    global 
$recv_ht_id;

    
ht_ioctl($recv_ht_id"stop");
}

function 
infrared_carrier_start($freq)
{
    global 
$emit_carrier_ht_id;

    
$div BASIC_CLOCK / ($freq 2);

    
ht_ioctl($emit_carrier_ht_id"reset");
    
ht_ioctl($emit_carrier_ht_id"set div $div"); // div 13.14us
    
ht_ioctl($emit_carrier_ht_id"set mode output pwm");
    
ht_ioctl($emit_carrier_ht_id"set output od");
    
ht_ioctl($emit_carrier_ht_id"set count 1 1");
    
ht_ioctl($emit_carrier_ht_id"start");
}

function 
infrared_carrier_stop()
{
    global 
$emit_carrier_ht_id;

    
ht_ioctl($emit_carrier_ht_id"stop");
    
ht_ioctl($emit_carrier_ht_id"set output high");
}

/*
see nec_infrared_send($data, $bit_length) function to know how to use this function
*/
function infrared_emit($count_buf$cnt_buf_len$unit)
{
    global 
$emit_control_ht_id;

    
$unit $unit BASIC_CLOCK 1000000;

    
infrared_carrier_start(38000); //enable 38KHz PWM signal - carrier frequency

    //ht_ioctl($emit_control_ht_id, "reset");
    
ht_ioctl($emit_control_ht_id"set div $unit");
    
ht_ioctl($emit_control_ht_id"set mode output toggle"); // set mode: toggle
    
ht_ioctl($emit_control_ht_id"set output od");

    
$pid_ht pid_open("/mmap/ht$emit_control_ht_id");
    
pid_write($pid_ht$count_buf);
    
pid_ioctl($pid_ht"set repc $cnt_buf_len");
    
pid_close($pid_ht);

    
ht_ioctl($emit_control_ht_id"start"); // start HT

    
while(ht_ioctl($emit_control_ht_id"get state"));

    
ht_ioctl($emit_control_ht_id"stop");

    
infrared_carrier_stop(); // stop to save energy.
}

/*
Paramerer:
    -$lower_bound: minimum value of the first captured pulse in microsecond
    -$upper_bound: minimum value of the first captured pulse in microsecond
Return:
    -true: value of the first captured pulse varies from $lower_bound to $upper_bound
    -false: otherwise.
*/
function infrared_available($lower_bound$upper_bound)
{
    global 
$recv_ht_id;

    
$unit ht_ioctl($recv_ht_id"get div"); // in number clock stick
    
$unit $unit 1000000 BASIC_CLOCK// in microsecond
    
$lower_bound /= $unit;
    
$upper_bound /= $unit;

    
$count ht_ioctl($recv_ht_id"get count 1");

    if( (
$count >= $lower_bound) && ($count <= $upper_bound))
        return 
true;

    return 
false;
}

/*
Paramerer: $count_id start from 0.
Return: width of captured pulse in microsecond
*/
function infrared_get_count($count_id)
{
    global 
$recv_ht_id;

    
$count_id++; // due to the dummy value (first value)
    
$unit ht_ioctl($recv_ht_id"get div");
    
$count ht_ioctl($recv_ht_id"get count $count_id");
    
$reval $unit $count 1000000 BASIC_CLOCK;

    return 
$reval;
}

/*
Paramerer: $count_id start from 0.
Return: width of captured pulse in unit
*/
function infrared_get_raw_count($count_id)
{
    global 
$recv_ht_id;

    
$count_id++; // due to the dummy value (first value)
    
$count ht_ioctl($recv_ht_id"get count $count_id");

    return 
$count;
}

function 
nec_infrared_send($data$bit_length)
{

    
$unit 562.5;// 562.5¥ìs

    
$count_buf int2bin(12);    // first value is dummy.
    
$count_buf .= int2bin(162);   // 9ms leading pulse burst (16 * 562.5us)
    
$count_buf .= int2bin(82);    //  4.5ms space (8 * 562.5us)
    
$cnt_buf_len 3;


    
$mask << ($bit_length-1);

    while(
$mask)
    {
        
$count_buf .= int2bin(12);    // 562.5¥ìs pulse burst
        
$cnt_buf_len++;

        if(
$data $mask)
        {
            
$count_buf .= int2bin(32);    // logical 1: 1.6875ms space
        
}
        else
        {
             
$count_buf .= int2bin(12);    // Logical 0 562.5¥ìs space
        
}
        
$cnt_buf_len++;

        
$mask $mask >> 1;
    }

    
$count_buf .= int2bin(12);    // 562.5¥ìs stop code
    
$cnt_buf_len++;

    
infrared_emit($count_buf$cnt_buf_len$unit);    
}

function 
nec_infrared_recv($bit_length)
{    
    
$data 0;
    
$mask << ($bit_length -1);
    for(
$i 1$i <= $bit_length$i++)
    {
        
$us infrared_get_count($i);
        if(
$us 2500)
        if(
$us 1500)
        {
            
$data |= ($mask>> ($i-1));
        }
    }
    return 
$data;
}


?>



If you have any question, please feel free to give the comment