2. NEC フォーマットの信号データ合成

黒豆や IRKit, KURO-RS, クロッサム2+ などのプログラマブルな学習リモコン (スマートリモコン) の信号データを、リモコン同士ツノつき合わせて学習させるのではなく、PC 上で理想的な波形に合成するためのノウハウです。

  1. 赤外線リモコンの信号定義データの合成 [表紙]
  2. 家製協フォーマットの信号データ合成
  3. NEC フォーマットの信号データ合成 (このページ)
  4. ソニーフォーマットの信号データ合成
  5. SHARP フォーマットの信号データ合成
  6. リモコン信号定義データの相互変換
  7. リモコン信号の解析
  8. メーカー純正リモコンのコード

このページでは NEC フォーマットを取り上げます。

2.1. リモコン信号の詳細

「NEC フォーマット」と呼ばれているもの。家製協フォーマット登場以前の業界標準で、現在も世界的に広く使用されている。

フォーマット

+---------------------------------------------------------------------
| リーダー部 | データ部          | トレーラー部 | リピートコード | ...
+---------------------------------------------------------------------

リーダー部

ON(16T)→OFF(8T)
Tは(9/16)msec。

データ部

4バイト (32 bit) の送信データ。
データ「0」は ON(1T)→OFF(1T)
データ「1」は ON(1T)→OFF(3T)

なお、データの内容は

  • 最初の2バイトがカスタムコード (ベンダー/機器の識別)
  • 3バイト目がデータコード (コマンド等)
  • 4バイト目が3バイト目の補数 (チェック用)

である (LSB first)。コードの具体的な値 (東芝製 DVD/HDD レコーダーの例) は後述。

トレーラー部

ON(1T)→OFF(nnT)
nnは、リーダー+データ+トレーラーの合計が192T (108msec)になるように決める。

リピートコード

リモコンのボタンを押している間、出続けるコード。
ON(16T)→OFF(4T)→ON(1T)→OFF(171T)

キャリア周波数

赤外線 LED の発光時 (ON時) の点滅周波数。38kHz。

2.2. 汎用信号定義への変換方法

黒豆, IRKit, Pronto 等の定義データへ変換する方法は「リモコン信号定義データの相互変換」を参照のこと。

データ形式

38            ; キャリア周波数 (kHz)
1             ; 信号送出の繰り返し回数。通常 1
              ; ---- リーダー部 ----
9000 4500     ; ON(16T)->OFF(8T)。T=(9/16)msec
              ; ---- データ部 ----
562.5 1687.5  ; 信号「1」。ON(1T)->OFF(3T)
562.5 562.5   ; 信号「0」。ON(1T)->OFF(1T)
  :           ;   (ビット数分続く)
              ; ---- トレーラー部 ----
562.5 39937.5 : ON(1T)->OFF(総信号長が108msecになるまで)

サンプルコード

送信データを NEC フォーマットにエンコードする perl のサンプルコードを示す。

#! /usr/bin/perl
#
#  Usage: irnec hex hex hex ...

# データはコマンド行引数に16進数の列で与える
@data = (map { hex($_) & 0xff } @ARGV)[0..3];
$data[3] = 0xff - $data[2] if (@ARGV < 4);

# データを0/1列に変換
$bytes = scalar (@data); $bits = $bytes * 8;
$data = unpack ("b$bits", pack ("C" x $bytes, @data));

# 出力の作成
$t = 9000 / 16;         # T = (9/16)msec
$len = 108000;          # 総信号長 108msec

# ヘッダ
@run = (38, 1);         # キャリア周波数 38kHz, 繰返し回数 1

# 信号部
# --- リーダー部 ON(16T)->OFF(8T)
push (@run, $n_on  = 16 * $t); $len -= $n_on;
push (@run, $n_off =  8 * $t); $len -= $n_off;

# --- データ部 0:ON(1T)->OFF(1T), 1:ON(1T)->OFF(3T)
foreach $bit (split ("", $data)) {
    if ($bit eq "0") {
        push (@run, $n_on  = 1 * $t); $len -= $n_on;
        push (@run, $n_off = 1 * $t); $len -= $n_off;
    } else {
        push (@run, $n_on  = 1 * $t); $len -= $n_on;
        push (@run, $n_off = 3 * $t); $len -= $n_off;
    }
}

# --- トレーラー部 ON(1T)->OFF(総信号長まで)
push (@run, $n_on  = 1 * $t); $len -= $n_on;
push (@run, $n_off = $len);

print join (" ", @run), "\n";

このようにして作成した汎用信号定義は「リモコン信号定義データの相互変換」に示すスクリプトで黒豆, IRKit, Pronto 等の定義へ変換できる。

2.3. クロッサム2+ 用信号定義データへの変換方法

データ形式

NEC フォーマットのクロッサム2+ 用信号定義データは以下のようになる。

00            ; おまじない。
06            ; 信号波形定義の数。
                ひと組の波形定義で「ON→OFF→」の一周期分を定義する。
21            ; キャリア周波数を決める分周比
                 [2.5MHz/38kHz/2=32.9≒0x21]。
              ; --- ここから信号波形定義 ---
7e0500 7e0500 ; データ「0」の波形。ON(1T)→ON(1T)、すなわち
                ONが0x00057eクロック継続したあとOFFが0x00057eクロック継続
                 [1T=(9/16)msec*2.5MHz=1406.25=0x57e]。
7e0500 7a1000 ; データ「1」の波形。ON(1T)→OFF(3T)。
e45700 f22b00 ; リーダーの波形。ON(16T)→OFF(8T)。
7e0500 038601 ; トレーラーの波形。ON(1T)→OFF(nnT)。
e45700 f91500 ; リピートコードの波形その1。ON(16T)→OFF(4T)。
7e0500 54ab03 ; リピートコードの波形その1。ON(1T)→OFF(171T)。
              ; --- ここから送信信号の定義 ---
2             ; リーダー (波形「2」)
10100010      ; データ1バイト目 (0=波形「0」/1=波形「1」)
00111101      ; データ2バイト目
01001000      ; データ3バイト目
10110111      ; データ4バイト目 (3バイト目の補数)
3             ; トレーラー (波形「3」)
45            ; リピートコード (波形「45」)
fe02          ; 直前の2波形を永久に繰り返す、という制御コード。
                これにより、ボタンを押している間リピートコードの信号が出続ける。

サンプルコード

送信データを NEC フォーマットにエンコードする perl のサンプルコードを示す。

#! /usr/bin/perl
sub b8 {
    local($_) = shift;
    return join("", reverse(split("", sprintf("%08b", $_))));
}
sub hh3 {
    local($_) = shift;
    return join("", (split("", sprintf("%06x", $_)))[4,5,2,3,0,1]);
}

# データはコマンド行引数に16進数×3バイトで与える
@data = map { hex($_) & 0xff } @ARGV[0..2];
$data[3] = 0xff - $data[2];    # 4バイト目は3バイト目の補数

# データを0/1列に変換
@data = map { b8($_) } @data;

# データ中の「0」「1」の数をかぞえる
$_ = join("", @data);
$n0 = tr/0/0/;
$n1 = tr/1/1/;

# 出力の作成
$t = 9 / 16 * 2500;                     # T=(9/16)msec
$f = int (2500 / 38 / 2 + 0.5);         # キャリア周波数=38kHz
$nn = 192 - 24 - $n0 * 2 - $n1 * 4 - 1; # トレーラー長の計算
$out = "00\n";
$out .= "06\n";
$out .= sprintf ("%02x\n", $f);
$out .= hh3(  1*$t)." ".hh3(  1*$t)."\n";
$out .= hh3(  1*$t)." ".hh3(  3*$t)."\n";
$out .= hh3( 16*$t)." ".hh3(  8*$t)."\n";
$out .= hh3(  1*$t)." ".hh3($nn*$t)."\n";
$out .= hh3( 16*$t)." ".hh3(  4*$t)."\n";
$out .= hh3(  1*$t)." ".hh3(171*$t)."\n";
$out .= "2\n";
foreach (@data) {
    $out .= $_."\n";
}
$out .= "3\n";
$out .= "45\n";
$out .= "fe02\n";

# ベタ書きにしたいとき (クロッサム・エクスプローラ風)
#$out =~ s/[^0-9a-f]//g;
#$out .= "\n";

# バイトごとに分かち書きしたいとき (Sweet Memories風)
#$out =~ s/[^0-9a-f]//g;
#$out =~ s/(..)/$&,/g;
#$out =~ s/.*/"$&"\n/;

print $out;

このようにして作成したデータを、Sweet Memories 等によりクロッサム2+ に転送する。

2.4. 例: 東芝製 DVD/HDD レコーダー [RD-XS30] のリモコンコード

カスタムコード

45 bc

各ボタンの機能コード

コード ボタン コード ボタン
00 0 52 初期設定
01 1 53 クリア
02 2 55 ワンタッチリプレイ
03 3 56 ダビング
04 4 57 修正/削除
05 5 5a 表示
06 6 5b ワンタッチスキップ
07 7 5c 残量表示
08 8 5e ズーム
09 9 80 スキップ >>|
0d +10 84 スキップ |<<
0e サーチ/転送 88 スロー >|
0f 入力切替 8c スロー <|
11 オープン/クローズ 98 ピクチャーサーチ/頁 >>
12 電源 9a ピクチャーサーチ/頁 <<
13 再生 9d フレーム/値編集 >||
15 録画 9e フレーム/値編集 ||<
16 停止 a3 延長
17 一時停止 a7 録画モード
18 DVD b1 表示窓切替
19 HDD c0 カーソル ↑
1a タイムスリップ c4 カーソル →
1e チャンネル ↑ c8 カーソル ↓
1f チャンネル ↓ cc カーソル ←
40 録るナビ d0 トップメニュー
41 編集ナビ d1 メニュー
42 見るナビ d2 リターン
44 決定 d3 音声/音多
45 クイックメニュー d4 アングル
46 V-リモート d5 字幕
47 ライブラリ d7 P in P
4a A d9 チャプター分割
4b B da タイムバー

G コード予約

8単位の NEC フォーマットのデータを連続的に送信 (リピートコードなし)。カスタムコード「45 b1」のヘッダのあとに、「45 b2」のデータ列が続く。詳細は以下の例を参照。

45 b1 08 f7  ; ヘッダ
45 b2 99 66  ; Gコードが「99502」の場合
45 b2 50 af  ; ・8桁のGコードを左詰めで2桁ずつ
45 b2 2f d0  ; ・余分な桁には「f」を詰める
45 b2 ff 00  ;
45 b2 fc 03  ; 録画先。DVDのとき「fc」、HDDのとき「fe」
45 b2 00 ff  ; いつも「00」
45 b2 00 ff  ; 録画モード。SPのとき「00」、LPのとき「02」