Sinneb Aurora :: proto 5, one voice with ASR
Where’s the quantize when you need it the most? ;)
Proto 5 has a first ASR (attack sustain release). The MCP42100 (the programmable potentiometer from a previous prototype) generates the enveloppe. Sounds pretty ok, though the attack is a little off which made the playing difficult ;). I will start working on a logarithmic scale instead of a linear scale.
Checkin’ “legato” also.
The schematic:
The semi cleaned up code:
// sinneb.com
// arduino interface code for the Sinneb Aurora 6
// Midi library from http://timothytwillman.com
// MCP42100 code from http://little-scale.blogspot.com/
// 82c54 code from sinneb.com
#include "Midi.h"
// Midi note 0 - 127 LSB & MSB values
// http://www.decisioncards.com/io/tutorials/8254_tut2.html
// Divide value by 256. i.e. 10000 / 256 gives 39.0625
// Use the whole value to load your MSB i.e. MSB=39
// Subtract the whole number i.e. 39.0625 - 39=0.0625
// Multiply by 256 to obtain remainder i.e. 0.0625 x 256=16
// Use the value diplayed as your LSB i.e. LSB=16
int midi_divides_lsb[] = {66, 182, 65, 33, 183, 116, 192, 11, 222, 186, 44, 195, 33, 222, 160, 16,
221, 186, 94, 135, 240, 93, 150, 99, 144, 239, 80, 136, 111, 221, 176, 195,
248, 47, 75, 49, 200, 247, 168, 196, 55, 239, 216, 226, 252, 23, 37, 25, 228,
124, 212, 226, 156, 247, 236, 113, 126, 12, 19, 140, 114, 190, 106, 113, 206,
124, 118, 184, 63, 6, 9, 70, 185, 95, 53, 56, 103, 190, 59, 220, 159, 131, 133,
163, 221, 47, 154, 28, 179, 95, 29, 238, 208, 193, 194, 210, 238, 24, 77, 142,
218, 47, 143, 247, 104, 225, 97, 233, 119, 12, 167, 71, 237, 152, 71, 252, 180, 112,
49, 244, 188, 134, 83, 36, 246, 204, 164, 126};
int midi_divides_msb[] = {3822, 3607, 3405, 3214, 3033, 2863, 2702, 2551, 2407, 2272, 2145, 2024,
1911, 1803, 1702, 1607, 1516, 1431, 1351, 1275, 1203, 1136, 1072, 1012,
955, 901, 851, 803, 758, 715, 675, 637, 601, 568, 536, 506, 477, 450,
425, 401, 379, 357, 337, 318, 300, 284, 268, 253, 238, 225, 212, 200,
189, 178, 168, 159, 150, 142, 134, 126, 119, 112, 106, 100, 94, 89, 84,
79, 75, 71, 67, 63, 59, 56, 53, 50, 47, 44, 42, 39, 37, 35, 33, 31, 29,
28, 26, 25, 23, 22, 21, 19, 18, 17, 16, 15, 14, 14, 13, 12, 11, 11, 10,
9, 9, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2};
// 74HC595 pins
int latchPin = 8;
int dataPin = 11;
int clockPin = 12;
// 42100 pins
int select42100 = 5;
int clock42100 = 6;
int data42100 = 7;
byte pot0 = B00010001; // write to pot 0
byte pot1 = B00010010; // write to pot 1
// various vars
int statusled = 13;
int incomingByte = 0;
// ADSR vars
float potcurrent = 0;
float pottarget = 0;
class MyMidi : public Midi {
public:
MyMidi(HardwareSerial &s) : Midi(s) {}
void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
{
digitalWrite(13, HIGH);
data_transfer(midi_divides_lsb[note],midi_divides_msb[note]);
pottarget=245;
}
void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
{
digitalWrite(13, LOW);
pottarget=0;
}
/* You can define any of these functions and they will be called when the
matching message type is received. Otherwise those types of Midi messages
are just ignored.
For C++ folks: these are all declared virtual in the base class
void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
void handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value);
void handleProgramChange(unsigned int channel, unsigned int program);
void handleAfterTouch(unsigned int channel, unsigned int velocity);
void handlePitchChange(unsigned int pitch);
void handleSongPosition(unsigned int position);
void handleSongSelect(unsigned int song);
void handleTuneRequest(void);
void handleSync(void);
void handleStart(void);
void handleContinue(void);
void handleStop(void);
void handleActiveSense(void);
void handleReset(void);
*/
};
MyMidi midi(Serial);
void setup() {
// init all pin
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(statusled, OUTPUT);
digitalWrite(statusled,HIGH);
// init 8254 control ports 2,3,4
pinMode(2, OUTPUT); // WR
digitalWrite(2, HIGH); // disabled
pinMode(3, OUTPUT); // A0
pinMode(4, OUTPUT); // A1
digitalWrite(3, LOW);
digitalWrite(4, LOW);
// init 42100
pinMode(select42100, OUTPUT);
pinMode(clock42100, OUTPUT);
pinMode(data42100, OUTPUT);
digitalWrite(select42100, HIGH);
midi.begin(0);
firstrun();
spi_out(select42100, pot0, 245);
}
void loop() {
//if(Serial.available() > 0)
// {
// incomingByte = Serial.read();
// if (incomingByte == 49) { // 1
// potinit--;
// spi_out(select42100, pot0, potinit);
// Serial.println(potinit);
// }
// }
midi.poll();
if (potcurrent != pottarget) {
if (potcurrent > pottarget) {
potcurrent = potcurrent - 0.01;
} else {
potcurrent = potcurrent + 1;
}
}
spi_out(select42100, pot0, potcurrent);
}
void firstrun() {
// control word sequence
Serial.println("A0A1 -> 1");
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
Serial.println("2 low");
digitalWrite(2, LOW);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, B01101100);
digitalWrite(latchPin, HIGH);
Serial.println("595 loaded");
Serial.println("2 high");
digitalWrite(2, HIGH);
// end control word sequence
// start data transfer, LSB MSB
// 18181 for 400hz
data_transfer( 5, 71);
}
void data_transfer(int LSB, int MSB) {
Serial.println("A0A1 -> 0");
digitalWrite(3, LOW);
digitalWrite(4, LOW);
Serial.println("2 low");
digitalWrite(2, LOW);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, LSB);
digitalWrite(latchPin, HIGH);
Serial.println("595 LSB");
Serial.println("2 high");
digitalWrite(2, HIGH);
Serial.println("2 low");
digitalWrite(2, LOW);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, MSB);
digitalWrite(latchPin, HIGH);
Serial.println("595 MSB");
Serial.println("2 high");
digitalWrite(2, HIGH);
}
/* FUNCTIONS */
void spi_transfer(byte working) {
for(int i = 1; i <= 8; i++) {
if (working > 127) {
digitalWrite (data42100,HIGH);
}
else {
digitalWrite (data42100, LOW);
}
digitalWrite (clock42100,HIGH);
working = working << 1;
digitalWrite(clock42100,LOW);
}
}
void spi_out(int ss, byte cmd_byte, byte data_byte) {
digitalWrite (select42100, LOW);
spi_transfer(cmd_byte);
spi_transfer(data_byte);
digitalWrite(select42100, HIGH);
}

