原文转载于:[URL=http://bird.dip.jp/mt/archives/2007/03/17/2121.html]http://bird.dip.jp/mt/archives/2007/03/17/2121.html[/URL]
有懂日文的网友或有朋友懂日文的,麻烦翻译一下供国内网友参考吧。先谢谢!
[IMGA=0,absMiddle]http://bird.dip.jp/mt/archives/2007/03/17/MSP430-QSTEER.jpg[/IMGA]
「Q-STEER 赤外線信号解析」の説明から、キャリア周波数38KHz、0.425msを on/off の時間隔単位として on-off でビット0を、on-onでビット1を表現すると解釈したのだが、PIECEソフトのコードによるとビット1はon-on-offとなるようだ。またon-on-on-onのヘッダの後にもoffが入る。自前で信号の解析をすれば良いのだろうが、そこは「適当も甚だしい電子工作研究所」と言うことでひとつよろしく。赤外線LEDは不要のリモコンを分解して取り出したもの。赤外線は肉眼では見えないからオシロスコープでモニタ。デジカメのモニタを通すと確認できたりもする。
プログラムはTimerA3により38KHzのキャリア周波数でLED点燈をおこない、0.425ms毎のWDT割込みでコマンドに応じて信号のオンオフをする。とりあえず最小限の動作確認ができただけで、スイッチなどによるコマンドインターフェース等はまだ無い。続く、かも。
[2007.03.18]
サンプルプログラム。このままだとひたすら前進のみ。動作を変更する場合は next_cmd に設定する。UI は適当によろしく。赤外線LEDはP1.2に付けたが、これは学習用マザーボードに実装されているLED(緑1)との差し替え。電流制限抵抗も適当に付けておく。
//******************************************************************************
// MSP430-CQ
// P1.2 に赤外線LED をつないで Q-STEER を動かすサンプル
// 2007.03 masato@bird.email.ne.jp
//******************************************************************************
#include "msp430x42x0.h"
// QSCMD: Q-STEER の信号パターンを bit で表現する
typedef struct _QSCMD {
unsigned int cmd; // MSB から 1/0 パターンを埋める
unsigned int len; // 有効ビット数
} QSCMD;
const QSCMD cmds[] = {
{ 0x0000, 0 }, // dummy
// ヘッダとバンド指定
{ 0xf500, 9 }, // Header - Band A
{ 0xf580, 10 }, // Header - Band B
{ 0xf680, 10 }, // Header - Band C
{ 0xf6c0, 11 }, // Header - Band D
// 操作コマンド
{ 0xaa00, 8 }, // 0000 reserved
{ 0xab00, 9 }, // 0001 forward
{ 0xad00, 9 }, // 0010 backward
{ 0xad80, 10 }, // 0011 left
{ 0xb500, 9 }, // 0100 right
{ 0xb580, 10 }, // 0101 dash forward
{ 0xb680, 10 }, // 0110 forward / left
{ 0xb6c0, 11 }, // 0111 forward / right
{ 0xd500, 9 }, // 1000 dash / left
{ 0xd580, 10 }, // 1001 dash / right
{ 0xd680, 10 }, // 1010 back / left
{ 0xd6c0, 11 }, // 1011 back / right
{ 0xda80, 10 }, // 1100 dash back
{ 0xdac0, 11 }, // 1101 dash back / left
{ 0xdb60, 12 }, // 1111 stop
};
enum Command {
CMD_NONE = 0,
CMD_HDA, CMD_HDB, CMD_HDC,CMD_HDD, // ヘッダとバンド指定
CMD_RSV, CMD_FW, CMD_BK, CMD_LT, // コマンド
CMD_RT, CMD_FF, CMD_FL, CMD_FR,
CMD_FFL, CMD_FFR, CMD_BL, CMD_BR,
CMD_FB, CMD_FBL, CMD_FBR,CMT_STP
};
#define BITON(X) ((X) & 0x8000) // bit on / off 判定
#define LEDON P1DIR |= 0x04 // LED on
#define LEDOFF P1DIR &= ~0x04 // LED off
unsigned int tick = 0; // 0.425ms 単位ステップカウント
unsigned int tick2 = 0; // 127ms 単位ステップカウント(テスト用)
enum Command band = CMD_HDA; // バンド指定
enum Command cmd = CMD_FW; // コマンド
enum Command next_cmd = CMD_BK; // 次コマンド
int gap = 19; // 信号セット間隔 Band-A:19 tick, B:47, C:75, D:104
//
void main(void)
{
/* WDT により 0.425ms 毎に LED の on/off 制御をする。*/
SCFQCTL = 38 - 1; // 38 * ACLK = 1.246MHz - 38KHz キャリアと 0.425ms 割込周期を作りやすそうに
WDTCTL = WDT_MDLY_0_5; // 0.5ms@1MHz → 0.421ms@1.246MHz 細かいずれには目をつむる。
// P1.2 に赤外線 LED をつなぐよ
P1DIR |= 0x04; // P1.2 as output
P1SEL |= 0x04; // P1.2 as TA1 output
/* Timer_A3 を用いてキャリア周波数(38KHz)で赤外線 LED を点燈 */
CCTL1 = OUTMOD_7; // Reset on EQU2(TAR = CCR2), Set on EQU0(TAR = CCR0)
CCR1 = 16; // on time
CCR0 = 33; // interval time : 38KHz
TACTL = TASSEL_2 + MC_1; // source:SMCLK, up to CCR0
IE1 |= WDTIE; // WDT 割込み許可
_BIS_SR(LPM0_bits + GIE); // LPM0
}
#pragma vector=WDT_VECTOR
__interrupt void WDT(void)
{
const QSCMD *hp = &(cmds[band]);
const QSCMD *cp = &(cmds[cmd]);
int t;
if (cmd == CMD_NONE)
return; // no-op
if (tick < hp->len) {
// Header - Band
if (BITON(hp->cmd << tick)) LEDON;
else LEDOFF;
} else if (tick < hp->len + cp->len) {
// Command
t = tick - hp->len;
if (BITON(cp->cmd << t)) LEDON;
else LEDOFF;
} else if (tick < hp->len + cp->len + gap) {
// Gap
LEDOFF;
} else if (tick < hp->len * 2 + cp->len + gap) {
// Header - Band (2)
t = tick - (hp->len + cp->len + gap);
if (BITON(hp->cmd << t)) LEDON;
else LEDOFF;
} else if (tick < hp->len * 2 + cp->len + gap) {
// Command (2)
t = tick - (hp->len * 2 + cp->len + gap);
if (BITON(cp->cmd << t)) LEDON;
else LEDOFF;
} else {
LEDOFF; // nop
}
tick++;
if (tick > 300) {
// 127ms 周期で連続させる。
tick = 0;
tick2++;
#if TEST // テスト用に 1.27s 周期で前進(CMD_FW)と前進+左(CMD_FL)を切り替え
t = tick2 / 10;
next_cmd = (t % 2)? CMD_FL: CMD_FW;;
#endif
if (next_cmd != cmd)
cmd = next_cmd;
}
}
/* EOF */実際の Q-STEER リモコンではコマンドボタンを離した時に停止コマンドが出されるそうだ。このプログラムでは WDT 割込みでコマンド処理をおこなっているが、メインルーチンあるいは別の割込み処理でコマンドを送るときには cmd == next_cmd を待って next_cmd に次のコマンドを設定すること。
信号の on/off 制御をもっと汎用的にして UI を工夫することで他の赤外線リモコンにも使える、かも知れない。なお、デジQは信号の仕様が異なり、このプログラムでは動かない。