/*
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;
}
}
}