• Column

【HAGIWO MOD1】 ウィンドウ・コンパレータ× シフトレジスタ/プログラムコード [モジュラーシンセ]

HAGIWO MOD1用にプログラミングしたウィンドウ・コンパレータ×シフトレジスタです。

ウィンドウ・コンパレータは、ある一定の電圧の間にある電気信号をゲート信号に変換するモジュールです。

例えば、5VのLFOを入力し、3V以上でウィンドウを設定した場合、出力からは3−5Vの範囲内に電気信号がある時のみゲート信号が出力されます。

用途としては、CVシーケンスで1オクターブ以上でエフェクトをかけたい、などのシーンで役立ちます。

また、本モジュールにはシフトレジスト機能も追加しています。通常のウィンドウコンパレータでは、入力電圧によってテンポシンクが難しいですが、F2にトリガーを入力することで、トリガーのタイミングでゲートが出力されます。ゲートはPOT3ノブによって最大8ビット遅延可能です。

注意事項:chatGPTで作成したプロンプトです。プログラミング知識は一切ないため、動作の安定性は保証はできません。趣味用途でお使いください

[機能紹介]

※0V-5Vの範囲で入力電圧を測定し、5Vのゲート信号を出力する。

※トリガーを入力した場合、出力がシフトレジスタを通過して、トリガータイミングに揃ったゲート信号が出力される。

POT1:SHIFT(ウィンドウの中心を決定)

POT2:SIZE(ウィンドウの幅を制御)

POT3:F2にトリガーを入力したとき、F3、F4はシフトレジストして出力される。出力タイミングはノブで1ビット-8ビットまで選択可能

F1:CV IN

F2:トリガーIN(入力がない場合は通常のコンパレータとして使える)

F3:コンパレート出力

F4:F3のNOT出力

LEDF3に連動する

[プログラム](ArduinoでMOD1にプログラミングしてください)

// Pin definitions

const int shiftKnob = A0;  // SHIFT control knob

const int sizeKnob = A1;   // SIZE control knob

const int shiftRegKnob = A2; // Shift register control knob

const int inputVoltage = A3; // Voltage input pin (D17 on Nano)

const int triggerInput = 9;  // Trigger input pin

const int gateOutput = 10;   // Gate output pin

const int notOutput = 11;    // NOT gate output pin

const int ledIndicator = 3;  // LED indicator output pin (same PWM as D10)

// Variables

float shiftValue = 0;

float sizeValue = 0;

int shiftRegValue = 0;

bool shiftRegisterEnabled = false;

byte shiftRegisterState = 0;

bool lastTriggerState = LOW;

unsigned long lastTriggerTime = 0;

const unsigned long triggerTimeout = 500; // Timeout in ms to return to normal mode

float smoothShift = 0;

float smoothSize = 0;

const float alpha = 0.05; // Smoothing factor (0: no smoothing, 1: instant)

void setup() {

    pinMode(triggerInput, INPUT);

    pinMode(gateOutput, OUTPUT);

    pinMode(notOutput, OUTPUT);

    pinMode(ledIndicator, OUTPUT);

}

void loop() {

    // Read and smooth control knobs

    int rawShift = analogRead(shiftKnob);

    int rawSize = analogRead(sizeKnob);

    // Apply exponential smoothing

    smoothShift = alpha * rawShift + (1 – alpha) * smoothShift;

    smoothSize = alpha * rawSize + (1 – alpha) * smoothSize;

    // Map smoothed values from 0–1023 to 0–5000 mV for 0–5V input range

    shiftValue = map(smoothShift, 0, 1023, 0, 5000);

    sizeValue = map(smoothSize, 0, 1023, 0, 5000); // Max window width 5V

    shiftRegValue = constrain(analogRead(shiftRegKnob) / 128, 1, 8); // 1-8 bit range

    // Read input voltage assuming 0V to 5V mapped to 0–1023

    int inputVal = analogRead(inputVoltage); // 0-1023

    int voltage = map(inputVal, 0, 1023, 0, 5000); // 0 to 5000 mV (0V to 5V)

    // Calculate window in mV

    int lowerBound = shiftValue – (sizeValue / 2);

    int upperBound = shiftValue + (sizeValue / 2);

    // Determine comparator result

    bool gateState = (voltage >= lowerBound && voltage <= upperBound);

    // Read trigger

    bool triggerState = digitalRead(triggerInput);

    // On rising edge, sample gate state and shift

    if (triggerState == HIGH && lastTriggerState == LOW) {

        shiftRegisterEnabled = true;

        lastTriggerTime = millis();

        bool sampledGateState = gateState;

        shiftRegisterState = (shiftRegisterState << 1) | sampledGateState;

        shiftRegisterState &= (1 << shiftRegValue) – 1;

    }

    lastTriggerState = triggerState;

    // Disable shift register mode after timeout

    if (millis() – lastTriggerTime > triggerTimeout) {

        shiftRegisterEnabled = false;

    }

    // Output gate or shifted gate

    bool finalGateState;

    if (shiftRegisterEnabled) {

        finalGateState = (shiftRegisterState >> (shiftRegValue – 1)) & 1;

    } else {

        finalGateState = gateState;

    }

    digitalWrite(gateOutput, finalGateState);

    digitalWrite(notOutput, !finalGateState);

    // LED indicator follows gate output (PWM)

    analogWrite(ledIndicator, finalGateState ? 255 : 0);

}