基板図
途中でMCP4922(IC2)を間違えて5ホール分(基板のガイド線1個分)ずれてはんだ付けしてしまったので、急遽部品の配置を変更。R6とC3だがなんとか大事に至らず変更できた。助かった(^q^;;;
部品面
はんだ面
電解コンデンサの正負を間違えてはんだ付けしたり、なんだかんだあったがなんとか完成(^q^/
出力波形
PCM5102AのファンクションジェネレータとNucleoシーケンサーをつないで動作確認。
ch1:入力波形 ch2:出力波形
#include "mbed.h" #include "rtos.h" #define UART_TRACE (0) #include "SpiSequenceSender.h" #include "EnvelopeGenerator.h" #include "SpiAmpController.h" #define SEQUENCE_N (16) #define SPI_RATE (8000000) const int samplingPeriod = 1; // ms const int bpm = 120; const int envelopeLength = (60 * 1000 / (bpm * 4)) / samplingPeriod; AnalogIn levelIn(A0); AnalogIn durationIn(A1); AnalogIn decayIn(A2); AnalogIn sustainIn(A3); SPI spiMaster(SPI_MOSI, SPI_MISO, SPI_SCK); Sequence sequence[SEQUENCE_N]; SpiSequenceSender sequenceSender(&spiMaster, D9, sequence, SEQUENCE_N, samplingPeriod, bpm); Envelope envelope(4095, envelopeLength, envelopeLength*3/4, envelopeLength/2, 2047); EnvelopeGenerator envelopeGenerator; SpiAmpController ampController(&spiMaster, D8, D7); class TestClass { public: void callbackFunction(int ticks) { if (ticks == 0) { envelopeGenerator.init(envelope); } uint16_t level = envelopeGenerator.getModLevel(); //printf("m,%d\r\n", level); ampController.outDca(level); envelopeGenerator.update(); } } testClass; void callbackFunction(int ticks) { if (ticks == 0) { envelopeGenerator.init(envelope); } uint16_t level = envelopeGenerator.getModLevel(); //printf("g,%d\r\n", level); ampController.outDca(level); envelopeGenerator.update(); } int main() { spiMaster.format(8, 0); spiMaster.frequency(SPI_RATE); // Test SequencerSender Run // sequenceSender.setBpm(bpm); for (int i = 0; i < SEQUENCE_N; i++) { Sequence& seq = sequenceSender.getSequences()[i]; seq.setPitch(i); seq.setOctave(-1); seq.tie = true; } sequence[3].setOctave(0); sequence[7].setOctave(0); sequence[11].setOctave(0); sequence[15].setOctave(0); envelopeGenerator.init(envelope); sequenceSender.attachUpdate(&testClass, &TestClass::callbackFunction); //sequenceSender.attachUpdate(&callbackFunction); sequenceSender.setWaveShape(SpiSequenceSender::WAVESHAPE_SAW); sequenceSender.run(0); for (;;) { /* sequenceSender.setPulseWidth(sequenceSender.getPulseWidth() + 4); Thread::wait(500); sequenceSender.setWaveShape(SpiSequenceSender::WAVESHAPE_SAW); Thread::wait(500); sequenceSender.setWaveShape(SpiSequenceSender::WAVESHAPE_SQUARE); */ envelope.setLevel(levelIn * 4095); envelope.setDuration(durationIn * envelopeLength); envelope.setDecay(decayIn * envelopeLength); envelope.setSustain(sustainIn * 4095); } }
#include "mbed.h" #include "rtos.h" #include "AverageAnalogIn.h" #define SPIM_TIMER_PERIOD (5) // 5ms #define SPIM_RATE (8000000) // 8MHz #define SPIM_WAIT /*(wait_us(1))*/ // ピン・アサイン #define PIN_CHECK PA_10 #define PIN_DAC_CS PA_9 #define PIN_DAC_LDAC PA_8 SPI SpiM(SPI_MOSI, SPI_MISO, SPI_SCK); DigitalOut DacCs(PIN_DAC_CS); DigitalOut DacLdac(PIN_DAC_LDAC); DigitalOut CheckPin(PIN_CHECK); AverageAnalogIn DurationIn(A0); AverageAnalogIn DecayIn(A1); AverageAnalogIn SustainIn(A2); int16_t beatLen = 25; int16_t level = 4095; int16_t duration = 400; int16_t decay = 100; int16_t sustain = 2000; int16_t decay_delta; int16_t release_delta = 1000; int16_t mod_value; int16_t tick; // DAC A Channelに出力 // parameter: v: 出力値(0 .. 4095) void writeToDacA(int16_t v) { // Channel A DacLdac = 1; DacCs = 0; SpiM.write((v >> 8) | 0x30); // 0x30: DAC_A(0) | Vref Unbuffered(0) | Vout 1x(1) | !SHDN(1) SpiM.write(v & 0xff); SPIM_WAIT; DacCs = 1; DacLdac = 0; } // DAC B ChannelにA ChannelのVrefを出力 void outVref() { // Channel B DacLdac = 1; DacCs = 0; SpiM.write(0x08 | 0xB0); // 0xB0: DAC_B(1) | Vref Unbuffered(0) | Vout 1x(1) | !SHDN(1) SpiM.write(0x00); SPIM_WAIT; DacCs = 1; DacLdac = 0; } // ADSR波形を出力 void outADSR(void const* arg) { tick++; if (tick > beatLen) { tick = 0; // モジュレーション波形を初期化する mod_value = level; decay_delta = (level - sustain) / decay; } // 出力値補正 if (mod_value < 0) { mod_value = 0; } writeToDacA(mod_value); if (tick < decay) { mod_value -= decay_delta; } /* if (tick >= duration) { mod_value -= release_delta; } */ if (tick == duration) { mod_value = 0; } } int main() { RtosTimer SpiM_timer(outADSR, osTimerPeriodic); SpiM.format(8, 0); SpiM.frequency(SPIM_RATE); outVref(); SpiM_timer.start(SPIM_TIMER_PERIOD); while(true) { duration = DurationIn.read() * beatLen; decay = DecayIn.read() * beatLen; sustain = SustainIn.read() * 4095; printf("%d\t%d\t%d\r\n", duration, decay, sustain); Thread::wait(10); } }
#include <SPI.h> #include <MsTimer2.h> #define MOD_RATE 1 // ms #define PIN_LDAC 9 // MCP4922のラッチ動作出力ピン #define PIN_DURATION A0 #define PIN_DECAY A1 #define PIN_SUSTAIN A2 int16_t beatLen = 500; int16_t level = 4095; int16_t duration = 400; int16_t decay = 100; int16_t sustain = 2000; int16_t decay_delta; int16_t mod_value; int16_t tick; // DACに出力 // parameter: v: 出力値(0 .. 4095) void outDAC(int16_t v) { v >>= 2; digitalWrite(PIN_LDAC, HIGH) ; digitalWrite(SS, LOW) ; SPI.transfer((v >> 8)| 0x30) ; SPI.transfer(v & 0xff) ; digitalWrite(SS, HIGH) ; digitalWrite(PIN_LDAC, LOW) ; } void outADSR() { tick++; if (tick > beatLen) { tick = 0; // モジュレーション波形を初期化する mod_value = level; decay_delta = (level - sustain) / decay; } // 出力値補正 if (mod_value < 0) { mod_value = 0; } outDAC(mod_value); if (tick < decay) { mod_value -= decay_delta; } if (tick == duration) { mod_value = 0; } } void setup() { Serial.begin(9600); // DAC出力の初期化 pinMode(PIN_LDAC, OUTPUT); SPI.begin(); SPI.setBitOrder(MSBFIRST); // ビットオーダー SPI.setClockDivider(SPI_CLOCK_DIV8); // クロック(CLK)をシステムクロックの1/8で使用(16MHz/8) SPI.setDataMode(SPI_MODE0) ; // クロック極性0(LOW) クロック位相0 // Timerの初期化 MsTimer2::set(MOD_RATE, outADSR); MsTimer2::start(); } void loop() { duration = map(analogRead(PIN_DURATION), 0, 1023, 0, beatLen); decay = map(analogRead(PIN_DECAY), 0, 1023, 0, beatLen); sustain = analogRead(PIN_SUSTAIN) << 2; Serial.print(duration); Serial.print("\t"); Serial.print(decay); Serial.print("\t"); Serial.print(sustain); Serial.print("\n"); }