(c) dusjagr, gäss, stahl SID-Emulator v1.0: minimalistic By Christoph Haberer,
(c) dusjagr, gäss, stahl SID MOS6581: Overview
(c) dusjagr, gäss, stahl Bits und Register – old school
(c) dusjagr, gäss, stahl Bits und Register – old school
(c) dusjagr, gäss, stahl SID-Emulator v1.8: Implementierung Seriell SID-emulator v1.8 LM386 By Christoph Haberer,
(c) dusjagr, gäss, stahl Arduino & SID-Emulator v1.8
(c) dusjagr, gäss, stahl Arduino USB2serial Spannungs Wandler 9V to 5V ATMEGA168 reset Digital Input/output Analog Input VCC/GN D
(c) dusjagr, gäss, stahl Arduino USB2serial Spannungs Wandler 9V to 5V ATMEGA168 reset Digital Input/output Analog Input VCC/GN D
(c) dusjagr, gäss, stahl /* * Blink * * The basic Arduino example. Turns on an LED on for one second, * then off for one second, and so on... We use pin 13 because, * depending on your Arduino board, it has either a built-in LED * or a built-in resistor so that you need only an LED. * * */ int ledPin = 13; // LED connected to digital pin 13 void setup() // run once, when the sketch starts { pinMode(ledPin, OUTPUT); // sets the digital pin as output } void loop() // run over and over again { digitalWrite(ledPin, HIGH); // sets the LED on delay(1000); // waits for a second digitalWrite(ledPin, LOW); // sets the LED off delay(1000); // waits for a second } Arduino: Blink aka serial
(c) dusjagr, gäss, stahl /* * Button * by DojoDave * * Turns on and off a light emitting diode(LED) connected to digital * pin 13, when pressing a pushbutton attached to pin 7. * * */ int ledPin = 13; // choose the pin for the LED int inputPin = 2; // choose the input pin (for a pushbutton) int val = 0; // variable for reading the pin status void setup() { pinMode(ledPin, OUTPUT); // declare LED as output pinMode(inputPin, INPUT); // declare pushbutton as input } void loop(){ val = digitalRead(inputPin); // read input value if (val == HIGH) { // check if the input is HIGH digitalWrite(ledPin, LOW); // turn LED OFF } else { digitalWrite(ledPin, HIGH); // turn LED ON } Arduino: Digital In VC C GND
(c) dusjagr, gäss, stahl /* * AnalogInput * by DojoDave * * Turns on and off a light emitting diode(LED) connected to digital * pin 13. The amount of time the LED will be on and off depends on * the value obtained by analogRead(). In the easiest case we connect * a potentiometer to analog pin 2. * * */ int potPin = 1; // select the input pin for the potentiometer int ledPin = 13; // select the pin for the LED int val = 0; // variable to store the value coming from the sensor void setup() { pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT } void loop() { val = analogRead(potPin); // read the value from the sensor digitalWrite(ledPin, HIGH); // turn the ledPin on delay(val); // stop the program for some time digitalWrite(ledPin, LOW); // turn the ledPin off delay(val); // stop the program for some time } Arduino: Analog In VC C GND
(c) dusjagr, gäss, stahl /* * AnalogInput * * 1-bit music * attach a speaker to pin 7 and GND * * dusjagr 2008 */ int potPin = 1; // select the input pin for the potentiometer int speakerPin = 7; // select the pin for the speaker int val = 0; // variable to store the value coming from the sensor void setup() { pinMode(speakerPin, OUTPUT); // declare the speakerPin as an OUTPUT } void loop() { val = ((1023-analogRead(potPin))>>4); // read the value from the sensor and shift 4 bits down 0-63 digitalWrite(speakerPin, HIGH); // turn the speakerPin on delay(val); // stop the program for some time digitalWrite(speakerPin, LOW); // turn the speakerPin off delay(val); // stop the program for some time } Arduino: 1-bit music VC C GND
(c) dusjagr, gäss, stahl Tristan Perich Fredrik Oloffson arduino clubtransmediale or for some advanced chiptunes on microcontrollers 1-bit music
(c) dusjagr, gäss, stahl Arduino & SID-Emulator v1.8 USB2serial Spannungs Wandler 9V to 5V ATMEGA168 reset Digital Input/output Analog Input Digital Input/output Analog Input VCC/GN D LM386 amp Debugging LEDS Ser/Voice1/2/3 Pot Vol Audio out pw m out Pin 12 serial line
(c) dusjagr, gäss, stahl SID-Emulator Shield v2.0
(c) dusjagr, gäss, stahl SID-Emulator Shield v2.0
(c) dusjagr, gäss, stahl Make some 8-bit noise Jetzt übel löten SID v1.8 reinstecken Arduino code raufladen.\SID_hello_world\SID_hello_world.pde touch the contacts
(c) dusjagr, gäss, stahl MITTWOCH - Rückblick Arduino – OK Digital Inputs / Outputs – OK Analog Inputs – OK 1-bit music – OK Shield gelötet und getestet – OK "The real power of SID lies in the ability to create original sounds rather than simulations of acoustic instruments." from the SID MOS6581 DATASHEET
(c) dusjagr, gäss, stahl
(c) dusjagr, gäss, stahl Wie mach ich mehr SID chips? hex file of the code Attach:SID_emulator_a168_v1_8.zip command line for avrdude using the mySmartUSB programmer: // set the fuses avrdude -p m168 -P com4 -c avr910 -F -v -e -U lfuse:w:0xff:m -U hfuse:w:0xdf:m -U efuse:w:0x07:m // write the code - change the filepath avrdude -p m168 -P com4 -c avr910 -F -e -U flash:w:"D:/desktop/atmega/SID/SID_emulator_a168_v1_8.hex":a
(c) dusjagr, gäss, stahl DONNERSTAG - Vorschau Simple Interface Erste Codes für Synthesizer Experimentieren im Code Einführung in Bit-Operatoren und Code Experimentieren im Klang "The real power of SID lies in the ability to create original sounds rather than simulations of acoustic instruments." from the english SID MOS6581 DATASHEET
(c) dusjagr, gäss, stahl The SID Interface
(c) dusjagr, gäss, stahl Arduino hardware: buttons & pots
(c) dusjagr, gäss, stahl Arduino hardware: buttons & pots
(c) dusjagr, gäss, stahl Make some 8-bit music Jetzt übel löten 2-3 potis löten, an Pin 1,2,3 (Analog In) 1 button löten, an Pin 6 (Digital In) Arduino code raufladen.\8-bit_SID_emulator\SID_emulator_workshop\SID_synth\SID_synth.pde turn the knobs, press the button and know to the CODE & BITS
(c) dusjagr, gäss, stahl SID-Emulator: Bits und Register 1 Bit 1 Ein/Aus-Schalter 1 Register 8 Bit 8 Ein/Aus-Schalter
(c) dusjagr, gäss, stahl SID-Emulator: Bits und Register 1 Register 8 Bit 8 Ein/Aus-Schalter etwas Mathe... MSB Hexadezimal-Darstellung A-F = 16 Werte = 4Bit 1 Register in Hexadezimaldarstellung 0xFF
(c) dusjagr, gäss, stahl SID-Emulator: Bits und Register
(c) dusjagr, gäss, stahl SID-Emulator: Register Blocks: Register Name VOICE 1= 0:Adresse 0-6 VOICE 2= 7:Adresse 7-13 VOICE 3= 14:Adresse FILTER= 21:Adresse (n. implement.) MISC= 25:Adresse (n. implement.)
(c) dusjagr, gäss, stahl SID-Emulator: Register VOICE1 + / VOICE2 + / VOICE3 + 0:Freq Lo16 bit Frequency 1:Freq HiF out = * F n [Hz] 2:Pulse Width Lo12 bit Pulse Width 3:Pulse Width HiPW out = PW n / 40,95 [%] 4:Control Reg8 bit Select / Gate 5:Attack / Decay4 bit / 4 bit 6:Sustain / Release4 bit / 4 bit
(c) dusjagr, gäss, stahl SID-Emulator: Register Control Register (Nr. 4) Gate:Bit 0= 1 A / D / S= 0 R Ring Mod:Bit 2Ring-Modulation Triangle:Bit 4Dreieck-Welle Saw:Bit 5Sägezahn Square:Bit 6Rechteckwelle Noise:Bit 7Weisses Rauschen
(c) dusjagr, gäss, stahl SID-Emulator: Tonerzeugung Wellenformen A Dreieck Säge Rechteck
(c) dusjagr, gäss, stahl SID-Emulator: Envelope Attack/Decay/Sustain/Release D AR S Gate 0 Volum e 1
(c) dusjagr, gäss, stahl SID-Shield: Bit Operatoren exp1 << X: Linksverschiebung der Bits in exp1 um X Positionen exp1 >> X: Rechtsverschiebung der Bits in exp1 um X Positionen exp1 & exp2: Bitweises AND exp1 ^ exp2: Bitweises exklusives OR exp1 | exp2: Bitweises inklusives OR ~exp1: Bitweise Negation exp1, exp2, X: Integer-Ausdrücke
(c) dusjagr, gäss, stahl SID-Shield: Bit Shift Op. Beispiele Wert dezimal: 11, hexadezimal: 0x0B, Einzelbits: << 4: Links um 4 Positionen: Ergebnis Einzelbits: , hexadezimal: 0xB0, dezimal: 176 (11 * 16) Einzelbits: >> 3: Rechts um 3 Pos.: Ergebnis Einzelbits: , hexadezimal: 0x16, dezimal: 22 (176 / 8)
(c) dusjagr, gäss, stahl SID-Shield: Bit AND Op. Beispiele exp1 & exp2: Bitweises AND und exp1 = = 0x4D= 77 exp2 = = 0x14= 20 exp1 & exp2 = = 0x04= 4 ? Ergebnisbit nur 1, wenn beide verglichenen Bits 1 sind!
(c) dusjagr, gäss, stahl SID-Shield: Bit OR Op. Beispiele exp1 ^ exp2:Bitweises exklusives OR exp1 = = 0x4D= 70 exp2 = = 0x14= 20 exp1 ^ exp2 = = 0x5D= 93 exp1 | exp2:Bitweises inklusives OR exp1 = = 0x4D= 70 exp2 = = 0x14= 20 exp1 | exp2 = = 0x59= 89
(c) dusjagr, gäss, stahl SID-Shield: Datentypen uintX_t:unsigned Integer mit exakt X bit Ganzzahlen von 0 bis 2 X uintX_t*:Pointer auf uintX_t XX intX_t:signed Integer mit exakt X bit Ganzzahlen von 0 bis +/- 2 (X/2) intX_t*:Pointer auf intX_t
(c) dusjagr, gäss, stahl ArduinoCode: header & definitions // Synthesizer for ATMEGA168 SID EMULATOR // SID simple synth #include "D:\desktop\SGMK\sid_shield\SID_emulator_workshop\SID_synth\emu.h" // include definitions for the emulator - check file path on your system #include // mathematik library #include // c library #define bit9600Delay 100 #define halfBit9600Delay 50 #define bit4800Delay 188 #define halfBit4800Delay 94 /* Variable definitions */ byte voice = VOICE3; // run_synth variables uint16_t gatt,pulse; byte oscform; // set_env variables uint16_t readtemp; uint8_t ad,sr; uint8_t sust = 0xA; // set SUSTAIN level // sw_putchar variables byte mask;
(c) dusjagr, gäss, stahl ArduinoCode: pin definitions /* Arduino Pin definitions ****************************************************************************************************************/ /* digital inputs/outputs ********************************/ int ledPin = 7; // defines the Pin for the debugging LED int gate1Pin = 6; // button 1 to gate Voice 1 int ringPin = 5; // swtich for ringmodulation of Oscillator 1 and Oscillator 2 /* analog inputs *********************************/ int freq2Pin = 5; // defines the Pin for frequency/pitch of the Oscillator in Voice 2 int wave2Pin = 4; // defines the Pin for waveform of the Oscillator in Voice 2 int freq1Pin = 1; // defines the Pin for frequency/pitch of the Oscillator in Voice 1 int wave1Pin = 2; // defines the Pin for waveform of the Oscillator in Voice 1 int pwmPin = 3; // defines the Pin for PWM modulation int sensPin = 0; // defines the Pin to add a light-sensor int adPin = 4; // defines the attack and decay simultanously for the envelope /* serial transmission from arduino to SID *******/ byte tx = 12; // transmission pin //****************************************************************************************************************
(c) dusjagr, gäss, stahl ArduinoCode: base functions void sw_putchar(int data) { } void set_adsr ( uint16_t adsr, uint8_t voice) { } void set_waveform ( uint8_t waveform, uint8_t fn, uint8_t voice) { } void set_frequency(uint16_t pitch, uint8_t voice) { } void set_wave(uint8_t waveform, uint8_t gate, uint8_t voice) { } void set_pulse(uint16_t pulsewidth, uint8_t voice) { }
(c) dusjagr, gäss, stahl ArduinoCode: setup / main loop // serial setup void setup() { pinMode(ledPin, OUTPUT); pinMode(tx,OUTPUT); digitalWrite(tx,HIGH); digitalWrite(13,HIGH); //turn on debugging LED }... /************************************************************************ * * main loop * ************************************************************************/ void loop() { delay (1000); // wait until SID-emulator is ready sw_putchar(0xFF); // send two times 0xFF to synchronize SID-data transmission sw_putchar(0xFF); set_wave(VOICE1, 0, 0); // reset all VOICES set_wave(VOICE2, 0, 0); set_wave(VOICE3, 0, 0); while(1) { run_synth(); }
(c) dusjagr, gäss, stahl ArduinoCode: run_synth() void run_synth(void) { /* FREQUENCY ***************/ set_frequency(((((1023-analogRead(freq1Pin)))>>1)<<5)+c0, voice); // read the frequency and map on 5 octaves /* CONTROL ****************/ gatt = 1 - digitalRead(gate1Pin); // read gate pin if (analogRead(wave1Pin)>>8 == 1) { // set the control register: waveform, gate, voice oscform = REC; set_wave(oscform, gatt, voice); // waveform, gate, voice // Pulse Width Modulation - only for Rectangle Waveform **************** set_pulse(analogRead(pwmPin)<<2, voice); } else if (analogRead(wave1Pin)>>8 == 2) { oscform = SAW; set_wave(oscform, gatt, voice); // waveform, gate, voice } else if (analogRead(wave1Pin)>>8 == 3) { oscform = TRI; set_wave(oscform, gatt, voice); // waveform, gate, voice } else { oscform = NOI; set_wave(oscform, gatt, voice); // waveform, gate, voice } delay (5); if (gatt == 1) { digitalWrite(ledPin, HIGH); // button led on if gate is on } else { digitalWrite(ledPin, LOW); // button led off if gate is off set_env(); // set new envelope when gate is off }
(c) dusjagr, gäss, stahl ArduinoCode_synth: Waveforms Die SID-Grundwellenformen: Dreieck / Säge / Rechteck / Rauschen Triangle / Saw / Square / Noise
(c) dusjagr, gäss, stahl ArduinoCode: SID_synth_harmonic Einzige Änderung im Vergleich zu run_synth: void run_synth(void) { /* FREQUENCY ***************/ set_frequency(notes[(1023-analogRead(freq1Pin))>>4], voice); // read the frequency and round down to 6 bit use the given number as array index(...) } Einzige Änderung in emu.h: //notes array uint16_t notes[] = { 0x0112, 0x0123, 0x0134, 0x0146, 0x015A, 0x016E, 0x0184, 0x018B, 0x01B3, 0x01CD, 0x01E9, 0x0206, (...) 0x892B, 0x9153, 0x99F7, 0xA31F, 0xACD2, 0xB719, 0xC1FC, 0xCD85, 0xD9BD, 0xE6B0, 0xF467 };
(c) dusjagr, gäss, stahl ArduinoCode: SID_synth_tables Änderung in run_synth(): void run_synth(void) { if (digitalRead(gate1Pin) == 0) { //play wavetable when gatepin is pressed wav = wavetables[analogRead(wave1Pin)>>8]; //select wavetable from Wave 1 Pin } Ein „wavetable“: int16_t bassdrum[] = { //00 PLAY, 1, +00, TRI, env3, // gate, transpose, waveform, env PLAY, 1, +00, NOI, env3, PLAY, 1, +00, REC, env3, PLAY, 1, -01, REC, env3, END, 1, +00, 0, 0 }; (...) int16_t* wavetables[] = { bassdrum, bleep, shot, bang, arp, sage };
(c) dusjagr, gäss, stahl SID-Emulator: Wavetables...und so sieht der Sound eines Wavetables aus
(c) dusjagr, gäss, stahl ArduinoCode: SID_synth_tables Auslesen der „wavetable“ in run_synth(): void run_synth(void) { (...) for (i = 0 ; (i < 32 * 5) && (wav[i] == true) ; i += 5) { basenote = notes[(1023-analogRead(freq1Pin))>>4]; // read the frequency and round down to 6 bit use the given number as array index if ( wav[i+2] >= 0 ) { detune = basenote + wav[i+2] * basenote / 24; // linear detune +24 is one octave more } else { detune = basenote + wav[i+2] * basenote / 48; // linear detune -24 is one octave less } set_frequency(detune, voice); // note, voice if (wav[i+3]) { set_wave(wav[i+3], wav[i+1], voice); // waveform, gate, voice } delay (50); // wavetable-sampling speed, could be mapped on a poti as well }
(c) dusjagr, gäss, stahl ArduinoCode: SID_drum Auslesen der „wavetable“ in run_drum(): if (digitalRead(drum1Pin) == 0) { wav = wavetables[0]; (...) delay (analogRead(tblspdPin)>>2); // wavetable-sampling speed } // end of wavetable set_adsr(0x0000, voice); // env, voice set_wave(0,0,voice); } if (digitalRead(drum2Pin) == 0) { wav = wavetables[1]; (...) } if (digitalRead(drum3Pin) == 0) { wav = wavetables[3]; (...) }
(c) dusjagr, gäss, stahl ArduinoCode: SID_pattern Auslesen der „wavetable“ über Pattern-Tabelle: int16_t pattern[] = { // note, wav c2,04, 00,00, c3,04, 00,00, f2,02, 00,00, c2,04, 00,00, c3,04, 00,00, f4,00, 00,00, };
(c) dusjagr, gäss, stahl ArduinoCode: Pattern auslesen void run_sound(void) { s = 0; // step counter steps = 16; // define number of steps for ( s = 0; s < steps * 2; s+=2) { d = ( analogRead(bpmPin)); // read speed from potentionmeter (...) if (pattern[s]) { t1 = millis(); wav = wavetables[pattern[s+1]]; // stop wavetable if gate is pressed if (digitalRead(gate1Pin) == 1) { for (i = 0 ; (i < 32 * 5) && (wav[i] == true) ; i += 5) { detune = pattern[s] + wav[i+2] * pattern[s] / 24; set_frequency(detune, voice); // note, voice if (wav[i+4]) { set_adsr(wav[i+4], voice); // env, voice } if (wav[i+3]) { set_wave(wav[i+3], wav[i+1], voice); // waveform, gate, voice } delay (analogRead(tblspdPin)>>2); // wavetable-sampling speed } // end of wavetable } else { set_wave(0,0,voice); } t2 = millis(); // step-timer if ( (rpmdel = d - t2 + t1) > 0 ) { delay(rpmdel); }
(c) dusjagr, gäss, stahl Links Arduino SID Infos and links for SID DIY-Sid Synthesizer, full midi SID Station, Profi Midi-SID sound box USB SID Synthesizer, up to 4 SIDs SID music collection Arduino Midi Input Microcontrollers AVR programmierer Sound
(c) dusjagr, gäss, stahl thx