// Basic demo for configuring the MCP4728 4-Channel 12-bit I2C DAC #include #include Adafruit_MCP4728 mcp; // 1 3 5 7 hexany log2 float hexany[] = { 0.0, 0.12928301694496647, 0.32192809488736235, 0.3923174227787603, 0.5849625007211562, 0.8073549220576041, 0.9068905956085185 }; float tuning[7]; int pitch[] = { 0, -1, 1, 2, -1, 3, -1, 4, 5, -1, 6, 5, -1, 3, -1, 1 }; float dur[] = { 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 }; float gate = 0.5; int bpm = 125; float beat_s = 60.0 / (float)bpm; int beat_m = round(1000.0 * beat_s); float voltrange = 5.0; // measured this, probably not accurate float octave = 4096.0 / voltrange; // number of DAC steps in an octave float mod_b = 3.141592653589793 / 4.0; int s; bool noteon = false; long play_t; long release_t; long last_t; long init_t; void setup(void) { Serial.begin(115200); while (!Serial) delay(10); // will pause Zero, Leonardo, etc until serial console opens if (!mcp.begin(0x64)) { Serial.println("Failed to find MCP4728 chip"); while (1) { delay(10); } Serial.println("MCP4728 initialised"); } mcp.setChannelValue(MCP4728_CHANNEL_B, 0); float n0 = 0; for( int i = 0; i < 7; i++ ) { tuning[i] = round(n0 + octave * hexany[i]); } s = 0; release_t = 0; play_t = 0; last_t = millis(); init_t = last_t; } void loop() { long now = millis(); if( noteon ) { if( now - last_t > release_t ) { noteOff(); last_t = now; play_t = round(beat_m * dur[s] * (1.0 - gate)); noteon = false; s += 1; if( s > 15 ) { s = 0; } } } else { if( now - last_t > play_t ) { noteOn(pitch[s]); last_t = now; release_t = round(beat_m * dur[s] * gate); noteon = true; } } // sychronise this better long mod_t = (now - init_t); float mod = 0.5 + 0.5 * sin(mod_b * (float)mod_t / (float)beat_m); mcp.setChannelValue(MCP4728_CHANNEL_C, round(4095.0 * mod)); } void noteOn(int note) { if( note > -1 ) { mcp.setChannelValue(MCP4728_CHANNEL_A, tuning[note]); mcp.setChannelValue(MCP4728_CHANNEL_B, 4095); } } void noteOff() { mcp.setChannelValue(MCP4728_CHANNEL_B, 0); }