赤外線パッド

  • タグ:
  • タグはありません
/*
 VISION VJS-372 赤外線レシーバ
	clk50MHz 受信サンプリング38kHz
*/

circuit VJS372_receiver
{
	input IRd;
	reg_ws pre0_IRd, pre1_IRd;

	reg_wr div<10>;

	output dout<16>;
	reg_wr dout_reg<16>;

	instrself ir_negedge, ir_posedge;

	stage_name receive_stg { task do(); }

	par{
		// 76kHzでサンプリング
		if(div==657){
			pre0_IRd := IRd;
			generate receive_stg.do();
			div := 0;
		}
		else div++;

		pre1_IRd := pre0_IRd;
		any{
			pre1_IRd & (^pre0_IRd) : ir_negedge();
			(^pre1_IRd) & pre0_IRd : ir_posedge();
		}

		dout = dout_reg;
	}

	stage receive_stg {
		reg_wr head_count<8>, data_count<8>, recv_data<16>;
		reg_wr bit_count<4>, f_push1, f_push2, f_push3;

		state_name idle, headL, headLt, headH, headHt, dataL, dataLt, dataH, dataHt, strtL, strtLt;
		first_state idle;

		par{
			finish;
		}

		state idle par{ // Low待ち
			head_count := 0;
			if(ir_negedge) goto headL;
		}

		// プリアンブル
		state headL par{
			head_count++;
			if(/&head_count) goto idle; // over (error)
			if(ir_posedge) goto headLt;
		}
		state headLt par{
			if((head_count-0x40)<7>==0b0){ // over
				head_count := 0;
				goto headH;
			}
			else goto idle;
		}
		state headH par{
			head_count++;
			if(/&head_count){
				goto idle; // over (error)
			}
			if(ir_negedge) goto headHt;
		}
		state headHt par{
			alt{
				(head_count-0x60)<7>==0b0 : par{ // over (error)
					goto idle;
				}
				(head_count-0x30)<7>==0b0 : par{ // over
					data_count := 0;
					bit_count := 0;
					recv_data := 0x0000;
					goto dataL;
				}
				else : par{ // error
					goto idle;
				}
			}
		}

		state dataL par{
			data_count++;
			f_push1 := 0;
			f_push2 := 0;
			f_push3 := 0;
			if(ir_posedge) goto dataLt;
		}
		state dataLt par{
			alt{
				(0x20-data_count)<7>==0b0 : par{ // under 0x1F
					goto dataH;
				}
				(data_count-0x60)<7>==0b0 : par{ // over (3同時押し) 0x6E
					f_push3 := 1;
					goto dataH;
				}
				(data_count-0x47)<7>==0b0 : par{ // over (2同時押し) 0x4A 0x50
					f_push2 := 1;
					goto dataH;
				}
				else : par{
					f_push1 := 1;
					goto dataH;
				}
			}
			data_count := 0;
		}
		state dataH par{
			data_count++;
			if(/&data_count) goto idle; // over (end frame)
			if(ir_negedge) goto dataHt;
		}
		state dataHt par{
			data_count := 0;
			any{
				bit_count==0 : goto strtL;
				bit_count==14 : par{
					dout_reg := 0b0 || recv_data<15:1>; // キー情報確定
					goto idle;
				}
				else : goto dataL;
			}
			alt{
				// 隣り合うビットのボタンが押されてるとLowが長い
				f_push3 : par{
					recv_data := recv_data<11:0> || 0b1110;
					bit_count += 4;
				}
				// 隣り合うビットのボタンが押されてるとLowが長い
				f_push2 : par{
					recv_data := recv_data<12:0> || 0b110;
					bit_count += 3;
				}
				// ボタンが押されると次のビット情報がパスされる
				f_push1 : par{
					recv_data := recv_data<13:0> || 0b10;
					bit_count += 2;
				}
				else : par{
					recv_data := recv_data<14:0> || 0b0;
					bit_count++;
				}
			}
		}

		// Startだけ長さが違う
		state strtL par{
			data_count++;
			f_push1 := 0;
			f_push2 := 0;
			f_push3 := 0;
			if(ir_posedge) goto strtLt;
		}
		state strtLt par{
			alt{
				(0x06-data_count)<7>==0b0 : par{ // under (error)
					goto idle;
				}
				(0x33-data_count)<7>==0b0 : par{ // under ok 0x28
					goto dataH;
				}
				(data_count-0x65)<7>==0b0 : par{ // over (同時押し) 0x69
					f_push2 := 1;
					goto dataH;
				}
				else : par{
					f_push1 := 1;
					goto dataH;
				}
			}
			data_count := 0;
		}

	}

}