引用まず、cv発生器では4つのピンからの信号で1オクターブを操作しているようなので、これを5つのピンで操作するようにおそらく大丈夫だと思います。このピンはシリアルの出力を使う場合にはふさがってしまうので、何か MIDI 出力をするような改造はできなくなりますが、今回の改造では大丈夫でしょう。ピン数をケチる方法は他にいくつかありますが ピン 3 を使うのが一番簡単だと思います。
しないといけないと思います。attiny2313の3ピンは使ってないようですのでこれを使えるでしょうか?
void iosetup(void) {
/* setup output data port */
DDRB = _BV(PB0) | // tuning tone
_BV(PB1) | // gate out
_BV(PB2) | // note CV
_BV(PB3); // pitch bend
PORTB = 0xf0; // ここで PB4, PB5, PB6, PB7 に 1 が設定される。このことによりこれらのピンがプルアップされる
PORTD = _BV(PD2) | _BV(PD3) | _BV(PD4) | _BV(PD5) | _BV(PD6);
}
void iosetup(void) {
/* setup output data port */
DDRB = _BV(PB0) | // tuning tone
_BV(PB1) | // gate out
_BV(PB2) | // note CV
_BV(PB3); // pitch bend
PORTB = 0xf0; // ここで PB4, PB5, PB6, PB7 に 1 が設定される。このことによりこれらのピンがプルアップされる
PORTD = _BV(PD1) | _BV(PD2) | _BV(PD3) | _BV(PD4) | _BV(PD5) | _BV(PD6); // PD1 が加わった
}
key = ((PINB >> 4) ^ 0x0f);
key = (((PIND & _BV(PD1)) << 3) ^ 0x10) + ((PINB >> 4) ^ 0x0f);
引用
あとオクターブスイッチで変わるのは1オクターブですのでこれも2オクターブに変更しないといけません。
octave = ((PIND >> 3) ^ 0x0f) * 12;
octave = ((PIND >> 3) ^ 0x0f) * 24;
int main(void) {
iosetup(); // IO ポートを初期化
init_uart(); // シリアルを初期化
init_timer(); // タイマーを初期化
init_midi_decoder(); // MIDI デコーダモジュールを初期化
init_midi_controllers(); // MIDI コントローラモジュールを初期化
key_prev = 0;
tone_factor = 0;
sei();
// このループでは、MIDI 入力を監視し続けて入力があればデコードし CV と Gate として出力する
while (true) {
uint16_t rxByte = uart_getchar();
if (rxByte != -1) {
digest(rxByte);
}
}
}
状態 | PB7 | PB6 | PB5 | PB4 | 値 | 値(反転) |
何も押していない | 1 | 1 | 1 | 1 | 0xf | 0x0 |
lowC | 1 | 1 | 1 | 0 | 0xe | 0x1 |
C# | 1 | 1 | 0 | 1 | 0xd | 0x2 |
D | 1 | 1 | 0 | 0 | 0xc | 0x3 |
D# | 1 | 0 | 1 | 1 | 0xb | 0x4 |
E | 1 | 0 | 1 | 0 | 0xa | 0x5 |
F | 1 | 0 | 0 | 1 | 0x9 | 0x6 |
F# | 1 | 0 | 0 | 0 | 0x8 | 0x7 |
G | 0 | 1 | 1 | 1 | 0x7 | 0x8 |
G# | 0 | 1 | 1 | 0 | 0x6 | 0x9 |
A | 0 | 1 | 0 | 1 | 0x5 | 0xa |
A# | 0 | 1 | 0 | 0 | 0x4 | 0xb |
B | 0 | 0 | 1 | 1 | 0x3 | 0xc |
highC | 0 | 0 | 1 | 0 | 0x2 | 0xd |
ISR(TIMER1_OVF_vect) {
static uint16_t button_count = 0;
uint8_t key;
uint8_t octave;
// ピッチベンド更新部は省略
// check the keyboard
octave = ((PIND >> 3) ^ 0x0f) * 12; // オクターブスイッチを読み取り
key = ((PINB >> 4) ^ 0x0f); // PB4, PB5, PB6, PB7 を読み取り <-- キー数を拡張する場合ここを変更する必要あり
if (key) {
key += octave;
}
if (key != key_prev) {
if (key_prev) {
note_off(key_prev + C0);
}
if (key) {
note_on(key + C0, 127);
}
}
key_prev = key;
if (! (PIND & _BV(PD2))) {
++button_count;
}
else {
button_count = 0;
}
if (button_count >= 19531) {
tone_factor ^= _BV(PORTB0);
button_count = 0;
}
}
key = ((PINB >> 4) ^ 0x0f);
uint8_t pin_values = PINB; // PINB レジスタからピン情報を読む。4, 5, 6, 7 ビット目にキー情報が入っている。
// 例えば lowC キーが押された場合、この時点で pin_values は 0xe0 (16進数) あるいは 11100000 (2進数)
pin_values = (pin_values >> 4); // 4ビット右にシフトして 4, 5, 6, 7 ビット目を 0, 1, 2, 3 ビット目に移動する。 4, 5, 6, 7 ビット目には 0 が入る
// 例えば lowC の場合この時点で pin_values は 0x0e (16進数) あるいは 00001110 (2進数)
key = pin_values ^ 0x0f; // 0x0f は二進数であらわすと 00001111。 ^ は xor 演算子で 1111 を掛け合わせると入力ビットが反転する。
// 例えば、lowC の入力値はこの段階で 00001110 で、00001111 と掛け合わせると 00000001 になる。(0xe -> 0x1)