YAMAHA DSP-1のリモコンの製作
注意:このサイトの内容を鵜呑みにし、事故や損失を招いた場合でも当方は一切の責任は負いかねます。自己責任でお願いします。
YAMAHAのデジタル・サウンドフィールド・プロセッサ「DSP-1」は、リモコンが無いと操作が一切できません。
本体を手に入れてもリモコンが無くどうしようもなくなっている方もいるでしょう。
リモコンを入手しようとオークションサイトで探しても、本体よりリモコンの方が価格が高くなってしまっています。
そこで、DSP-1のリモコンを作ることにしました。
・DSP-1のリモコン仕様
型番 : RS-DSP-1
使用IC : μPD1943G
リモコンフォーマット : NECフォーマット
カスタムコード : 1バイトカスタムコード 0x7D
ボタン数 : 30
回路上の ボタン番号 |
リモコン コード 16進 |
ボタンの場所 (左上から0,0) |
ボタン名 |
---|---|---|---|
S0 | 00 | ||
S1 | 01 | 0,1 | ACOUSTIC/SURROUND |
S2 | 02 | 0,2 | SOUND EFFECTOR |
S3 | 03 | 0,3 | USER PROGRAM |
S4 | 04 | 1,0 | 1 (HALL 1/DELAY) |
S5 | 05 | 1,1 | 2 (HALL 2/ST ECHO) |
S6 | 06 | 1,2 | 3 (HALL 3/ST FLANGE A) |
S7 | 07 | 1,3 | 4 (CHAMBER/ST FLANGE B) |
S8 | 08 | 2,0 | 5 (MÜNSTER/CHORUS A) |
S9 | 09 | 2,1 | 6 (CHURCH/CHORUS B) |
S10 | 0A | 2,2 | 7 (JAZZ CLUB/ST PHASING) |
S11 | 0B | 2,3 | 8 (ROCK CNCT/TREMOLO) |
S12 | 0C | 3,0 | 9 (DISCO/SYMPHONIC) |
S13 | 0D | 3,1 | 10 (PAVILION/ECHO ROOM) |
S14 | 0E | 3,2 | 11 (WHSE LOFT/PITCH CHANGE A) |
S15 | 0F | 3,3 | 12 (STADIUM/PITCH CHANGE B) |
S16 | 10 | 4,0 | 13 (PRESENCE/L TURN) |
S17 | 11 | 4,1 | 14 (SUR 1/R TURN) |
S18 | 12 | 4,2 | 15 (SUR 2/F-R) |
S19 | 13 | 4,3 | 16(Dolby SUR/L-R) |
S20 | 14 | 5,0 | PARAMETER |
S_DGS | 15 | DIAGNOSTIC | |
S21 | 16 | 5,2 | DEC |
S22 | 17 | 5,3 | INC |
S23 | 18 | 6,0 | TITLE EDIT |
S24 | 19 | 0,0 | MEMORY |
S25 | 1A | 6,2 | BALANCE (FRONT) |
S26 | 1B | 6,3 | LEVEL (UP) |
S27 | 1C | 7,0 | MUTE (MAIN) |
S28 | 1D | 7,1 | MUTE (EFFECT) |
S29 | 1E | 7,2 | BALANCE (REAR) |
S30 | 1F | 7,3 | LEVEL (DOWN) |
μPD1943Gは32キーリモコン用送信用ICです。
機器メーカにそれぞれ割り当てられるカスタムコードをダイオードで設定できます。
ですので、別のリモコンを分解してμPD1943Gを手に入れればDSP-1を作ることができます。
今回はArduino(ATmega328p)でリモコンを作ってみます。
・回路図
ATmrga328p、ATmrga168p、ATmrga88pを単体で使う場合
一部のボタン(S24:MEMORY)はRS-DSP-1と配置が異なるので注意してください。
また、RS-DSP-1にはないボタン(S0、S_DGS:診断)も一応配置しています。
・プログラム(Arduino ATmrga328p、ATmrga168p、ATmrga88p用)
// YAMAHA DSP-1 リモコン
// 詳細はμPD1943のデータシートを参照
// ©oy
// https://oykenkyu.blogspot.com/2023/07/psg-ssg.html
// UARTでも操作可('0'~'9'は0x00~0x09、'a'~は0x0A~に割り当て)
#define XTAL 16000000 // 水晶振動子の周波数
#define SERIALSPEED 38400 // UARTのボーレート
unsigned char data[8]; // ボタン状態保存
void setup()
{
Serial.begin(SERIALSPEED * (16000000.0 / XTAL)); // シリアル通信開始
DDRB |= 0x03; // pin8~pin9_Ko6~Ko7 ボタンスキャン出力
DDRD |= 0xFC; // pin2~pin7_Ko0~Ko5 ボタンスキャン出力
DDRC &= 0xF0; // pin14~pin17_Ki0~Ki3 ボタンスキャン入力
PORTC |= 0x0F; // pin14~pin17_Ki0~Ki3 ボタンスキャン入力プルアップ
DDRB |= 0x04; // 赤外線LED
for (int i = 0; i < 8; i++)
{
data[i] = 0x00;
}
}
void loop()
{
unsigned char scan_data = 0;
int tx_time = 0; // 押しっぱなし時間カウント
unsigned int custom_code = 0x827D; // DSP-1
while (1)
{
// スキャンと送信
for (unsigned char i = 0; i < 8; i++)
{
scan_data = scan_4bit_tr(key_scan(i));
if ((scan_data >> 4) != 0x0F) // スキャンデータと保存しているデータを比較
{
tx_time += nec_frame_send(custom_code, (i << 2) | scan_data); // データ送信
delay(70);//押しっぱなしで連打の場合有効
while (scan_4bit_tr(key_scan(i)) != 0xF0)
{
// 押しっぱなしの時
delay(1);
tx_time++;
// リピート
if (tx_time >= 108)
{
//準フォーマット
tx_time = 0;
tx_time += nec_repeat_send(); // 約11ms
//押しっぱなしで連打の場合
//tx_time = 255;// 待機時間なし
//tx_time += nec_frame_send(custom_code, (i << 2) | scan_data); // データ送信
}
}
delay(30); // チャタリング防止
}
}
// uartで操作
if (Serial.available() > 0)
{
scan_data = Serial.read();
if ((scan_data <= '9') && (scan_data >= '0'))
{
nec_frame_send(custom_code, scan_data - '0'); // データ送信
}
else if ((scan_data <= 'z') && (scan_data >= 'a'))
{
nec_frame_send(custom_code, scan_data - 'a' + 10); // データ送信
}
}
}
}
// 4bit分スキャン
unsigned char key_scan(unsigned char line)
{
unsigned char sel_temp = 0;
sel_temp = 1 << line;
PORTB = (PORTB & 0xFC) | 0x03; // すべてH
PORTD = (PORTD & 0x03) | 0xFC; // すべてH
DDRD = (PORTB & 0xFC); // すべて入力(プルアップ)
DDRD = (PORTD & 0x03); // すべて入力(プルアップ)
PORTB = (PORTB & 0xFC) | ((~(sel_temp>>6)) & 0x03); // pin8~pin9_D6~D7
PORTD = (PORTD & 0x03) | ((~(sel_temp<<2)) & 0xFC); // pin2~pin7_D0~D5
DDRD = (PORTB & 0xFC) | ((sel_temp>>6) & 0x03); // 指定した行のみ出力に設定
DDRD = (PORTD & 0x03) | ((sel_temp<<2) & 0xFC); // 指定した行のみ出力に設定
delayMicroseconds(10);
return 0x0F & (~PINC);
}
// スキャンデータから押されたボタンの番号を返す(同時押し無効)
unsigned char scan_4bit_tr(unsigned char data)
{
unsigned char ret_num = 0xFF; // 同時押しの場合
if (data == 0x08)
{
ret_num = 3;
}
else if (data == 0x04)
{
ret_num = 2;
}
else if (data == 0x02)
{
ret_num = 1;
}
else if (data == 0x01)
{
ret_num = 0;
}
else if (data == 0x00)
{
// 押していない時
ret_num = 0xF0;
}
return ret_num;
}
/////////////////////////////////////////////////////////////
// NECフォーマット_データ送信
int nec_frame_send(unsigned int custom, unsigned char data)
{
// 50ms前後
int ret_tim=0;
ret_tim += nec_leader(); // リーダー送信
ret_tim += nec_byte_send(custom); // カスタムコードbit0~bit7
ret_tim += nec_byte_send(custom >> 8); // カスタムコード(16bitカスタムコードの場合はbit8~bit15、8bitカスタムコードの場合はbit0~bit7の反転)
ret_tim += nec_byte_send(data); // データ
ret_tim += nec_byte_send(~data); // データ反転
ret_tim += nec_bit_l(); // ストップビット
Serial.print("custom: 0x");
Serial.print(custom, HEX);
Serial.print(" key: 0x");
Serial.print(data, HEX);
Serial.print("\r\n");
return ret_tim;//送信時間
}
// NECフォーマット_リピート送信
int nec_repeat_send()
{
// NECフォーマット_リピート
// T=562μs、H:16T、L:4T
//
for (int i = 0; i < 356; i++) // 約9.27ms
{
ir_38khz_prd();
}
for (int i = 0; i < 4; i++) // 約2.25ms
{
delayMicroseconds(562);
}
nec_bit_h();
Serial.print("repeat\r\n");
return 11;//送信時間
}
int nec_byte_send(unsigned char data)
{
// NECフォーマット_バイト送信
int ret_tim=0;
for (int i = 0; i < 8; i++)
{
if (((data >> i) & 0x01) == 1)
{
ret_tim += nec_bit_h();
}
else
{
ret_tim += nec_bit_l();
}
}
return ret_tim;//送信時間
}
int nec_bit_h()
{
// NECフォーマット_ビットH
// T=562μs、H:T、L:3T
//
for (int i = 0; i < 21; i++) // 約546μs
{
ir_38khz_prd();
}
delayMicroseconds(15);
delayMicroseconds(562);
delayMicroseconds(562);
delayMicroseconds(562);
return 2;//送信時間
}
int nec_bit_l()
{
// NECフォーマット_ビットL
// T=562μs、H:T、L:T
//
for (int i = 0; i < 21; i++) // 約546μs
{
ir_38khz_prd();
}
delayMicroseconds(15);
delayMicroseconds(562);
return 1;//送信時間
}
int nec_leader()
{
// NECフォーマット_リーダー
// T=562μs、H:16T、L:8T
//
for (int i = 0; i < 356; i++) // 約9.27ms
{
ir_38khz_prd();
}
for (int i = 0; i < 8; i++) // 約4.50ms
{
delayMicroseconds(562);
}
return 11;//送信時間
}
// サブキャリア
inline void ir_38khz_prd()
{
// 本当はタイマーで作ると良い
// 38.46kHz
PORTB |= 0x04; // pin10=H
delayMicroseconds(9); // 本当は8.772μs
PORTB &= ~0x04; // pin102=L
delayMicroseconds(17); // 本当は17.54μs
}
0 件のコメント:
コメントを投稿