sbit ir_in at RA1_bit;                     // Infrared receiver input
sbit ir_in_direction at TRISA1_bit;         // Infrared receiver input

unsigned char readbuff[64] absolute 0x500;
unsigned char writebuff[64] absolute 0x540;


// global variables
unsigned int retint;
unsigned char ir_result[6];
char _dat[100];
unsigned char modifier = 0b00000000;
unsigned char volctrl = 0b00000000;
unsigned char key;
unsigned char ID;
int Repeat = 1;

// functions
int get_mark(void);
int get_space(void);
void nec_read(void);
unsigned char get_nec_byte(void);
void SendKeyCode(unsigned char _device, unsigned char _modifier, unsigned char _volctrl, unsigned char _key);
void SendKeyCode_func(int _repeat, unsigned char _device, unsigned char _modifier, unsigned char _volctrl, unsigned char _key);

void Interrupt(){
    USB_Interrupt_Proc();

    if (INT1IF_bit){
        INT1IF_bit = 0;
        INT1IE_bit = 0;
        ir_result[0] = 0;
        ir_result[1] = 0;
        ir_result[2] = 0;
        ir_result[3] = 0 ;
        nec_read();
    }
}


void main() {
    //Analog pins as digital
    ANCON0 = 0x1F;
    ANCON1 =  0x1F;

    PLLEN_bit = 1;
    Delay_ms(150);

    HID_Enable(&readbuff,&writebuff);

    writebuff[3]=0;
    writebuff[4]=0;
    writebuff[5]=0;
    writebuff[6]=0;
    writebuff[7]=0;

    ir_in_direction = 1;          // IR input

    T0CON = 0x85;               //enable Timer0 module
    TMR0L = 96;                 // Timer0 initial value
    TMR0H = 0xff;

    //Initialize INT1 with Peripheral Pin Select
    Unlock_IOLOCK();
    PPS_Mapping_NoLock(1, _INPUT , _INT1);
    Lock_IOLOCK();

    //Enable INT1 Module
    INT1IF_bit = 0;
    INT1IE_bit = 1;
    INTEDG1_bit = 0;
    GIE_bit = 1;
    delay_ms(10);

    //keep program running
    while (1);
}

// print out NEC values - 16 bit address, 8 bit command, 8 bit inverted command
void nec_read(void){
    signed int temp_nec;
    int count_byte;

    temp_nec = get_mark();
    if ((temp_nec > 1150) && (temp_nec < 1840)){       // expect 9mS mark
        temp_nec = get_space();
        if ((temp_nec > 460) && (temp_nec < 920)){   // expect 4.5mS space
            for(count_byte = 0 ; count_byte < 4 ; count_byte++ ){
                ir_result[count_byte] = get_nec_byte();
            }
        }
        
        switch(ir_result[2]){
                              //Repeat, ID , Modifer  , Volctrl  , key//
            case  2:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x51); break; 			//down
            case  5:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x52); break; 			//up
            case  9:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x2a); break; 			//backspace
            case 10:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x50); break; 			//left
            case 12:SendKeyCode_func(0,0x02,0b00001000,0b00000000,0x07); break; 			//show desktop
            case 13:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x4b); break; 			//pageup
            case 16:SendKeyCode_func(1,0x01,0b00000000,0b00000010,0x00); break; 			//volume-
            case 17:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x4e); break; 			//pagedown
            case 18:SendKeyCode_func(0,0x02,0b00000000,0b00000000,0x29); break; 			//esc
            case 21:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x4d); break; 			//end
            case 22:SendKeyCode_func(0,0x01,0b00000000,0b00000100,0x00); break; 			//mute
            case 23:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x4c); break; 			//delete
            case 25:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x4a); break; 			//home
            case 27:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x49); break; 			//insert
            case 28:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x28); break; 			//enter
            case 29:SendKeyCode_func(0,0x02,0b00000000,0b00000000,0x2b); break; 			//tab
            case 30:SendKeyCode_func(1,0x02,0b00000000,0b00000000,0x4f); break; 			//right
            case 31:SendKeyCode_func(0,0x02,0b00000000,0b00000000,0x65); break; 			//context menu
            case 64:SendKeyCode_func(0,0x02,0b00000100,0b00000000,0x28); break; 			//alt+enter
            case 76:SendKeyCode_func(1,0x01,0b00000000,0b00000001,0x00); break; 			//volume+
            case 77:SendKeyCode_func(0,0x02,0b00000100,0b00000000,0x3d); break; 			//alt+f4
            case 84:SendKeyCode_func(0,0x02,0b00001000,0b00000000,0x46); break; 			//print screen
            case 0:if(Repeat)SendKeyCode(ID, modifier, volctrl, key);delay_ms(10); break; 	//Repeat Code
            
            default:Repeat = 0;ID = 0x02;modifier = 0b00000000;volctrl = 0b00000000;key = 0x00;
        }
        Delay_ms(10);// wait for repeat messages to clear
    }
    INT1IE_bit = 1;
}

// get one byte of NEC
unsigned char get_nec_byte(void){
char n;
unsigned char ir_byte;
signed int temp_ir;

    for(n=0 ; n<8 ; n++){
        temp_ir = get_mark();                         // expect ~600uS
        temp_ir = get_space();                        // 500uS = 0, 1.6uS = 1
        ir_byte >>= 1;                                // shift in a zero
        if (temp_ir > 160){                            // check > 900uS
            ir_byte += 0x80;                          // change 0 to a 1 if so
        }
    }
    return ir_byte;                                   // return final byte
}


// get IR mark time (low)
int get_mark(void){
        TMR0H = 0;
        TMR0L = 0;
        while(!ir_in);                       // wait for IR to go high
        retint = TMR0L;
        retint += (TMR0H<<8);
        return retint;
}

// get IR space time (high)
int get_space(void){
        TMR0H = 0;
        TMR0L = 0;
        while(ir_in);                        // wait for IR to go low
        retint = TMR0L;
        retint += (TMR0H<<8);
        return retint;
}

void SendKeyCode(unsigned char _device, unsigned char _modifier, unsigned char _volctrl, unsigned char _key){
        writebuff[0] = _device;
        if (_device == 0x01){
            writebuff[1] = _volctrl;
            while(!HID_Write(writebuff,2));
            delay_ms(10);
            writebuff[1] = 0b00000000;
            while(!HID_Write(writebuff,2));
            delay_ms(10);
        }else if(_device == 0x02){
            writebuff[1] = _modifier;
            writebuff[2] = _key;
            while(!HID_Write(writebuff,8));
            delay_ms(10);
            writebuff[1] = 0b00000000;
            writebuff[2] = 0x00;
            while(!HID_Write(writebuff,8));
            delay_ms(10);
        }
}

void SendKeyCode_func(int _repeat, unsigned char _device, unsigned char _modifier, unsigned char _volctrl, unsigned char _key){
    Repeat = _repeat;
    ID = _device;
    modifier = _modifier;
    volctrl = _volctrl;
    key = _key;
    SendKeyCode(ID, modifier, volctrl, key);
    if(Repeat)delay_ms(200);else delay_ms(10);
}