AppleRemote receive library.

AppleRemote.cpp

Committer:
tosihisa
Date:
2010-10-09
Revision:
1:6d06459fb6db
Parent:
0:a5f26ed3f510

File content as of revision 1:6d06459fb6db:

/**
 * @section LICENSE
 *
 * This source code is "zlib" license. 
 * Of course, this is not a part of the zlib software. 
 * The license is zlib license. 
 *
 * Copyright (C) 2010 tosihisa
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 * @section DESCRIPTION
 *
 * Apple Remote Decoder
 * http://en.wikipedia.org/wiki/Apple_Remote
 *
 */

#include "mbed.h"
#include "AppleRemote.h"

AppleRemote::AppleRemote( PinName _ir ) : IR(_ir) , nowStart(0) , _repeatEnable(0)
{
    reset();
    stop();
}

void AppleRemote::reset()
{
    IR_Timer.reset();
    cjobst = WAIT_READER;
    bit_index = 0;
    pre_IR_code = IR_code = 0;
    pre_timer = 0;
}

void AppleRemote::start()
{
    if(nowStart == 0){
        reset();
        IR.fall(this,&AppleRemote::IR_fall);
        IR.rise(this,&AppleRemote::IR_rise);
        IR_Timer.start();
        nowStart = 1;
    }
}

void AppleRemote::stop()
{
    nowStart = 0;
    IR_Timer.stop();
    IR.fall(NULL);
    IR.rise(NULL);
}

int AppleRemote::readable()
{
    return (widx == ridx) ? 0 : 1;
}

int AppleRemote::getc()
{
    int retval = -1;
    if(readable()){
        retval = static_cast<unsigned short>(buf[ridx]);
        ridx = (ridx + 1) & (bufsize-1);
    }
    return retval;
}

void AppleRemote::repeat(int enable)
{
    _repeatEnable = enable;
}

void AppleRemote::IR_fall()
{
    int us;
    if(cjobst == WAIT_READER){
        IR_Timer.reset();
        pre_timer = 0;
        cjobst = CHK_READER_1ST;
    } else if(cjobst == CHK_READER_2ND){
        us = IR_Timer.read_us();
        if(((us - pre_timer) > 4400) && ((us - pre_timer) < 4600)){
            //printf("Get Reader-code\n");
            cjobst = CHK_CODE_1ST;
            pre_timer = us;
        } else if(((us - pre_timer) > 1900) && ((us - pre_timer) < 2350)){
            //printf("Get Repeat-code\n");
            if((_repeatEnable != 0) && (pre_IR_code != 0)){
                if((widx + 1) != ridx){
                    buf[widx] = static_cast<unsigned short>(pre_IR_code >> 16);
                    widx = (widx + 1) & (bufsize-1);
                }
            }
            cjobst = WAIT_READER;
        } else {
            cjobst = WAIT_READER;
        }
    } else if(cjobst == CHK_CODE_2ND){
        us = IR_Timer.read_us();
        if((us - pre_timer) > 3000){
            /* Error. too long (over 3msec). */
            cjobst = WAIT_READER;
        } else {
            IR_code |= (((us - pre_timer) < (1125+(1125/2))) ? (0) : (1)) << bit_index;
            bit_index++;
            pre_timer = us;
            cjobst = CHK_CODE_1ST;
            if(bit_index >= 32){
                cjobst = CHK_STOP_1ST;
            }
        }
    } else if(cjobst == CHK_STOP_2ND){
        //printf("CODE:[%08lX]\n",IR_code);
        if((IR_code & 0xffff) == ID){
            if((widx + 1) != ridx){
                buf[widx] = static_cast<unsigned short>(IR_code >> 16);
                widx = (widx + 1) & (bufsize-1);
            }
            pre_IR_code = IR_code;
        }
        cjobst = WAIT_READER;
        bit_index = 0;
        IR_code = 0;
    }
}

void AppleRemote::IR_rise()
{
    int us;
    if(cjobst == CHK_READER_1ST){
        us = IR_Timer.read_us();
        if((us > 8800) && (us < 9500)){
            cjobst = CHK_READER_2ND;
            pre_timer = us;
        } else {
            cjobst = WAIT_READER;
        }
    } else if(cjobst == CHK_CODE_1ST){
        cjobst = CHK_CODE_2ND;
    } else if(cjobst == CHK_STOP_1ST){
        cjobst = CHK_STOP_2ND;
    } else {
        cjobst = WAIT_READER;
    }
}