赤外線学習リモコンの信号定義データの合成/ソニーフォーマット編

はじめに

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

信号データが合成できると、以下のようなメリットが期待できます。

  • なまっていない、きれいな信号が出せるようになるので、機器の反応が良くなる。
  • いつでも欲しいときにデータが合成できるので、学習したデータの保存に気を使わなくてもよくなる。
  • 機器付属のリモコンでは送れない、未知のコマンドを探求できる(笑)。

このページではソニーフォーマットを取り上げます (動作確認はSONY製スカパーチューナー [DST-D900] で行ないました)。

リモコン信号の詳細

「ソニー (SIRC) フォーマット」と呼ばれているもの。

フォーマット

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

リーダー部

ON(4T)→OFF(1T)
Tは0.6ms。

データ部

12ビット、15ビット、または20ビットの送信データ。
データ「0」は ON(1T)→OFF(1T)
データ「1」は ON(2T)→OFF(1T)

なお、データの内容は

  • 最初の7ビットが機能コード
  • 残りが機器の識別コード

である (LSB first)。コードの具体的な値は後述。

トレーラー部

OFF(nnT)
nnは、リーダー+データ+トレーラーの合計が75T (45ms)になるように決める。

キャリア周波数

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

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

データ形式

ソニーフォーマットのクロッサム2+用信号定義データは以下のようになる (20bitコードの場合)。
00            ; おまじない。
04            ; 信号波形定義の数。
                ひと組の波形定義で「ON→OFF→」の一周期分を定義する。
1f            ; キャリア周波数を決める分周比
                 [2.5MHz/40kHz/2=31.25≒0x1f]。
              ; --- ここから信号波形定義 ---
dc0500 dc0500 ; データ「0」の波形。ON(1T)→ON(1T)、すなわち
                ONが0x0005dcクロック継続したあとOFFが0x0005dcクロック継続
                 [1T=0.6ms*2.5MHz=1500=0x5dc]。
b80b00 dc0500 ; データ「1」の波形。ON(2T)→OFF(1T)。
701700 dc0500 ; リーダーの波形。ON(4T)→OFF(1T)。
dc0500 0c7b00 ; トレーラーの波形。トレーラーにはON部分がないため、
                データの最終ビットと融合させてひとつの波形とする。
                ON(1T/2T)→OFF(nnT)。
              ; --- ここから送信信号の定義 ---
2             ; リーダー(波形「2」)
1010100       ; データ/機能コード(0=波形「0」/1=波形「1」)
0101110001113 ; データ/機器識別コード。
                最終ビットはトレーラと融合するため波形「3」。
fe15          ; 直前の0x15波形を永久に繰り返す、という制御コード。
                これにより、ボタンを押している間リーダー~トレーラーの信号が出続ける。
0             ; バイト境界に合わせるための詰め物

サンプルコード

送信データをソニーフォーマットにエンコードするperlのサンプルコードを示す。
#! /usr/bin/perl
sub bn {
    local($_, $n) = @_;
    return substr(join("", reverse(split("", sprintf("%0${n}b", $_)))), 0, $n);
}
sub hh3 {
    local($_) = shift;
    return join("", (split("", sprintf("%06x", $_)))[4,5,2,3,0,1]);
}

# データはコマンド行引数に16進数×2(機器コード+コマンド)で与える。
($id, $com) = map(hex, @ARGV[0..1]);

# データを0/1列に変換
$com = bn($com, 7);
if ($id >= 0x100) {  # 20bitコード
    $id = bn($id, 13);
    $len = 20;
} elsif ($id >= 0x20) { # 15bitコード
    $id = bn($id, 8);
    $len = 15;
} else {                # 12bitコード
    $id = bn($id, 5);
    $len = 12;
}

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

# 出力の作成
$f = int(2500 / 40 / 2 + 0.5);  # キャリア周波数=40kHz
$t = 0.6 * 2500;                # T=0.6ms
$nn = 75 - 5 - $n0 * 2 - $n1 * 3 + 1; # トレーラー長の計算
$out = "00\n";
$out .= "04\n";
$out .= sprintf("%02x\n", $f);
$out .= hh3(1*$t)." ".hh3(1*$t)."\n";
$out .= hh3(2*$t)." ".hh3(1*$t)."\n";
$out .= hh3(4*$t)." ".hh3(1*$t)."\n";
if ($id =~ /0$/) {
    $out .= hh3(1*$t)." ".hh3($nn*$t)."\n";
} else {
    $out .= hh3(2*$t)." ".hh3($nn*$t)."\n";
}
$out .= "2\n";
$out .= $com."\n";
$id =~ s/.$/3/;
$out .= $id."\n";
$out .= sprintf("fe%02x\n", $len + 1);
if ($len % 2 == 0) {
    $out .= "0\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+に転送する。

SONY製スカパーチューナー [DST-D900] のリモコンコード

機器コード

e3a

各ボタンの機能コード

コード ボタン コード ボタン
00 1 30 予約一覧
01 2 31 好み一覧
02 3 38 メニュー
03 4 3a 画面表示
04 5 48 JskyB
05 6 49 PerfecTV
06 7 4a ラジオ
07 8 61 スチル
08 9 6f 現在番組
09 0 70 週間番組
0b 選局 72 カーソル ↑
10 CH ↑ 73 カーソル ↓
11 CH ↓ 74 カーソル →
15 電源 75 カーソル ←
17 二重音声 76 決定
29 番組説明 77 ジャンル
2b プロモ 78 日付

改版履歴

Ver 1.0: 2004/1/22 - クロッサム2+向けに執筆
Ver 1.1: 2014/11/24 - IRKit、KURO-RS/PC-OP-RS1向けに加筆 (家製協のみ)、信号解析のページを追加

本稿の内容は、独自の調査・解析の結果にもとづくものであり、内容の正確性については保証いたしません。自己責任にてご利用ください。