Maker Faire Tokyo 2016 森のタクトについての詳細記事です。
#概要
手元のハードウェアボタンを押すと、それに対応したスピーカーをミュートにしたり、再びミュートを解除したりという機能を実装していますが、ここではこの機能について説明します。今回5つのボタンを用意しました。
#詳細
LED付きボタン回路の作成
ただの、タクトスイッチを使用してもよいのですがそれだと今Muteなのか、Mute解除なのかが視覚的にわかりにくいのでLED付きボタンを使うことにしました。
回路図が2枚になっているのは、1枚目の基板は極力ボタン以外の部品は載せず、2枚目の基板はそれ以外の部品を載せ、2枚を積み重ねる構成にしているためです。
回路は、ローパスフィルタとシュミットトリガでチャタリング回避、フリップフロップで状態の保持などを行っています。フリップフロップの出力はは外に引き出してクライアント(RaspberryPi)への入力になります。
回路その1
### 回路その2 SWx_AとSWx_Bという信号は実際はショートされています。ボタンからの入力に応じて音をMuteにする
上記回路からの5つのInputに対して割り込みを設定とハンドラーを追加します。
あとは、GPIOの状態をslave_en_flagとして保持し、note_onイベントのvelocityにかけるようにします。
そうするともしインプットがLowの場合はflagが0になっているので、velocityも0になりMuteになります。
unsigned char slave_en_flags[6] = {1, 1, 1, 1, 1, 1};
void sw1_event(){
slave_en_flags[0] = digitalRead(BCM_SW1);
printf("Detect SW1 Event: %d");
}
void sw2_event(){
slave_en_flags[1] = digitalRead(BCM_SW2);
printf("Detect SW2 Event: %d");
}
void sw3_event(){
slave_en_flags[2] = digitalRead(BCM_SW3);
printf("Detect SW3 Event: %d");
}
void sw4_event(){
slave_en_flags[3] = digitalRead(BCM_SW4);
printf("Detect SW4 Event: %d");
}
void sw5_event(){
slave_en_flags[4] = digitalRead(BCM_SW5);
printf("Detect SW5 Event: %d");
}
int main(){
//省略
wiringPiISR(BCM_SW1, INT_EDGE_BOTH, sw1_event);
wiringPiISR(BCM_SW2, INT_EDGE_BOTH, sw2_event);
wiringPiISR(BCM_SW3, INT_EDGE_BOTH, sw3_event);
wiringPiISR(BCM_SW4, INT_EDGE_BOTH, sw4_event);
wiringPiISR(BCM_SW5, INT_EDGE_BOTH, sw5_event);
//省略
//再生
for(p = datahead->next; p != NULL; p = p->next){
switch(0xf0 & p->sendbuf[0]){
case 0xc0:
//program Change
pgm_change(slave_num, 0x0f & p->sendbuf[0], p->sendbuf[1]);
break;
case 0x80:
//note off
note_off(slave_num, 0x0f & p->sendbuf[0], p->sendbuf[1], p->sendbuf[2]);
break;
case 0x90:
//note on
note_on(slave_num, 0x0f & p->sendbuf[0], p->sendbuf[1], p->sendbuf[2]*slave_en_flags[slave_num]);
break;
default:
//printf("Other events\n");
break;
}
usleep(p->wait_time * coeff);
}
}