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