`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:33:14 11/28/2014 
// Design Name: 
// Module Name:    IR_Receiver 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module IR_Receiver
(
	input clk_main,   
	input reset,
	input IR_Remote_Sig,
	output [31:0]PrintfData
);

reg [31:0]timer_cnt = 0;
reg [3:0]state = 0;
reg [3:0]state_ff = 0;
wire [31:0]buff;
//always@(posedge clk_main)
//begin
//	if(reset)
//	state_ff <= 4'd0;
//	else state_ff <= state;
//
//end 

//wire tick1;
//wire tick2;
//assign tick1 = (state == 4'd1)? 1'b1: 1'b0;
//assign tick2 = (state == 4'd3)? 1'b1: 1'b0;
reg Start = 0;
//always@(posedge clk_main)
//begin
//	case(state)
//		0: 
//		begin
//			if(IR_Remote_Sig == 1'b0)
//			begin
//				state = 4'd1;
//			end 
//			else state = 4'd0;
//		end
//		1: 
//		begin
//			if(IR_Remote_Sig == 1'b1)
//			begin
//				state = 4'd3;
//			end 
//			else state = 4'd1;
//		end
////		2: 
////		begin
////			if(IR_Remote_Sig == 1'b1)
////			begin
////				state = 4'd3;
////			end 
////			else state = 4'd2;
////		end 
//		3: 
//		begin
//			if(IR_Remote_Sig == 1'b0)
//			begin
//			state = 4'd4;
//			end 
//			else state = 4'd3;
//		end
//		4:
//		begin
//			state = 4'd0;
//		end 
//		//default: state = 4'd0;
//		endcase 
//end 

reg [31:0]period = 0;
reg [31:0]timer_period_cnt = 0;
reg [3:0]state_period = 0;
reg [15:0]resetCnt = 0;

reg [31:0]IR_Receive_Value = 0;
reg [31:0]IR_Trans_Value = 0;
reg [7:0]IR_Receive_cnt = 0;
reg IR_Remote_Sig_1 = 0;
reg IR_Remote_Sig_2 = 0;
reg IR_Remote_Sig_3 = 0;
wire IR_Remote_Sig_Real;


always@(posedge clk_main)
IR_Remote_Sig_1 <= IR_Remote_Sig;

always@(posedge clk_main)
IR_Remote_Sig_2 <= IR_Remote_Sig_1;

always@(posedge clk_main)
IR_Remote_Sig_3 <= IR_Remote_Sig_2;

assign IR_Remote_Sig_Real = (IR_Remote_Sig_1 & IR_Remote_Sig_2 & IR_Remote_Sig_3);

//reg SigOut=0;
//wire tick;
//always@(negedge IR_Remote_Sig)
//begin
//	
//	if(SigOut == 2'b01)
//	begin
//		SigOut <= 2'b00;
//	end 
//	else SigOut <= SigOut+ 1'b1;
//end 
//assign tick = (SigOut == 2'b1)? 1'b1: 1'b0;

always@(posedge clk_main)
begin
	case(state_period)
	4'd0:
	begin
		resetCnt <= resetCnt + 1'b1;
		if(resetCnt == 32'd500)
		begin
			timer_period_cnt <= 32'd0;
			state_period <= 4'd1;
		end
	end 
	4'd1:
	begin
		if(IR_Remote_Sig_Real == 1'b0)
		begin
				state_period <= 4'd2;
		end 
	end 
	4'd2:
	begin
		timer_period_cnt <= timer_period_cnt + 1'b1;
		if(IR_Remote_Sig_Real == 1'b1)
		begin
			state_period <= 4'd3;
			timer_period_cnt <= 32'd0;
			period <= timer_period_cnt;
		end 
	end
	4'd3:
	begin
//		if((period >=32'd90000) && (period <=32'd135000)) //112500
		if((period >=32'd202500) && (period <=32'd247500)) //112500
		begin
//			IR_Trans_Value <=	IR_Receive_Value;				
			state_period <= 4'd4;
		end 
		else state_period <= 4'd1;
	end 
	
	4'd4:
	begin
		if(IR_Remote_Sig_Real == 1'b1)
		begin
			state_period <= 4'd5;
		end 
	end 
	4'd5:
	begin
		timer_period_cnt <= timer_period_cnt + 1'b1;
		if(IR_Remote_Sig_Real == 1'b0)
		begin
			state_period <= 4'd6;
			timer_period_cnt <= 32'd0;
			period <= timer_period_cnt;
		end 
	end
	4'd6:
	begin
		if((period >=32'd202500) && (period <=32'd247500)) //112500
		begin
//			IR_Trans_Value <=	IR_Receive_Value;				
			state_period <= 4'd7;
		end 
		else state_period <= 4'd1;
	end 
	
	4'd7:
	begin
			if(IR_Remote_Sig_Real == 1'b1)
		begin
				state_period <= 4'd8;
		end 
	end 
	4'd8:
	begin
		timer_period_cnt <= timer_period_cnt + 1'b1;
		if(IR_Remote_Sig_Real == 1'b0)
		begin
			state_period <= 4'd9;
			timer_period_cnt <= 32'd0;
			period <= timer_period_cnt;
		end 
	end 
	4'd9:
	begin
//		if(period >= 32'd11299 && period <= 32'd50700) //0.452~2.028
//		begin
		IR_Receive_Value <= (IR_Receive_Value>> 1'b1);
		state_period <= 4'd10;
//		end 
//		else state_period <= 4'd7;
	end
	4'd10:
	begin
	   if((period >= 32'd76050) && (period <= 32'd92950))  //5.4~3.6
		begin
		IR_Receive_Value <= (IR_Receive_Value| 32'h80000000);
		end 
	  else if((period >= 32'd25425) && (period <= 32'd31075))//0.452~0.678
	  begin
	  	IR_Receive_Value <= (IR_Receive_Value| 32'h00000000);
	  end 
	  	state_period <= 4'd11;
//	  else state_period <= 4'd4;
	end 
	4'd11:
	begin
		IR_Receive_cnt <= IR_Receive_cnt + 1'b1;
		state_period <= 4'd12;
	end 
	4'd12:
	begin
		if(IR_Receive_cnt ==8'd32)
		begin
			IR_Receive_cnt <=8'd0;
			state_period <= 4'd13;
			IR_Trans_Value <=IR_Receive_Value;
		end
		else state_period <= 4'd7;
		
	end 
	4'd13:
	begin	
		IR_Receive_Value <= 32'd0;
		state_period <= 4'd1;
	end 
	endcase
end 

//assign buff = IR_Trans_Value&32'h0000ff00;
//assign PrintfData = (buff>>16);
//assign PrintfData = {IR_Trans_Value[19:16],IR_Trans_Value[23:20]};
assign PrintfData = IR_Trans_Value[23:16];

endmodule
