//AV1BIT Audiovisual MonoChord 1Bit Synthesizer //VGA Sync Generator by DWAN //Faster AnalogRead code by jmknapp //Ramps code by Emanuelle Mazza /* VGA Sync Generator * 11/11/08 - dwan : dwanafite@yahoo.fr * * Based on : * - RG Matrix Example v.2 8/1/08, by BroHogan, from the Arduino Playground * - Simplest universal VGA/PAL terminal, by Ibragimov Maxim Rafikovich, http://www.vga-avr.narod.ru/main.html * - the very useful Timer/Counter/Prescaler Calculator, http://www.et06.dk/atmega_timers/ * - Arduino.cc Port Manipulation Tutorial * * This program outputs pretty accurate VGA syncronization signals. It's using a timer interrupt on timer2, so hopefully you can make other cool things in loop(). */ // 640 * 480 @ 60Hz - FvSync = 60.3 Hz / FhSync = 31.3 kHz // HSync : pin 7 Arduino, pin 13 VGA // VSync : pin 6 Arduino, pin 14 VGA // Arduino's pin 5 is HIGH when video can be sent, LOW otherwise. I use it to power a transistor. See this wonderful page : http://www.anatekcorp.com/driving.htm // 1 NOP = 62,5 ns wasted #define NOP asm("nop") #define vga_field_line_count 525 // number of VGA lines #define ISR_FREQ 0x3F // Sets the speed of the ISR - LOWER IS FASTER - 62 volatile unsigned int linecount; //FASTER ANALOG READS //Prescaler/16 (faster analogReads) #define FASTADC 1 // defines for setting and clearing register bits #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif // Pins per a sortida (RGB i àudio): const byte R = 9; const byte G = 10; const byte B = 11; const byte A = 12; //pins d'entrada digital (switch) const int Rswitch1 = 1; // output as an input const int Rswitch2 = 4; // output as an input const int Gswitch1 = 2; // output as an input const int Gswitch2 = 5; // output as an input const int Bswitch1 = 3; // output as an input const int Bswitch2 = 8; // output as an input const int Randomizer = 13; // Variables d'estat: byte RState = LOW; byte GState = LOW; byte BState = LOW; unsigned long previousMicros=0; unsigned long previousMillis=0; unsigned long interval=0; //declara temps d'inicialitzacio de les rampes long unsigned int initRamp1; long unsigned int initRamp2; long unsigned int initRamp3; //Llegeix els potes unsigned long int Rpote1(){ unsigned long int r= analogRead(0); return r; } unsigned long int Rpote2(){ unsigned long int r= analogRead(3); return r; } unsigned long int Gpote1(){ unsigned long int g= analogRead(1); return g; } unsigned long int Gpote2(){ unsigned long int g= analogRead(4); return g; } unsigned long int Bpote1(){ unsigned long int b= analogRead(2); return b; } unsigned long int Bpote2(){ unsigned long int b= analogRead(5); return b; } //declara randoms int random1=0; int random2=0; int random3=0; void setup() { // Serial.begin(115200); DDRD |= B11100000; // it sets pins 7, 6 and 5 as output without changing the value of pins 0 & 1, which are RX & TX // 76543210 <- pin translation PORTD |= B11000000; // sets pins 7 (hSync) and 6 (vSync) HIGH // 76543210; setISRtimer(); // setup the timer startISR(); // start the timer to toggle shutdown // set prescale to 16: faster analog reads #if FASTADC sbi(ADCSRA,ADPS2) ; cbi(ADCSRA,ADPS1) ; cbi(ADCSRA,ADPS0) ; #endif pinMode(R, OUTPUT); pinMode(G, OUTPUT); pinMode(B, OUTPUT); pinMode(Rswitch1, INPUT); pinMode(Rswitch2, INPUT); pinMode(Gswitch1, INPUT); pinMode(Gswitch2, INPUT); pinMode(Bswitch1, INPUT); pinMode(Bswitch2, INPUT); pinMode(Randomizer, INPUT); initRamp1 = millis(); initRamp2 = millis(); initRamp3 = millis(); } void loop() { long unsigned int a= Rpote1(); long unsigned int b= Rpote2(); long unsigned int c= Gpote1(); long unsigned int d= Gpote2(); long unsigned int e= Bpote1(); long unsigned int f= Bpote2(); if (a+b <=2044){ Rswitch(a,b); } if (c+d <=2044){ Gswitch(c,d); } if (e+f <=2044){ Bswitch(e,f); } } //Gestio dels modes de funcionament (a través dels switches) void Rswitch(long unsigned int pote1, long unsigned int pote2){ byte Rsw1 = digitalRead(Rswitch1); byte Rsw2 = digitalRead(Rswitch2); if (Rsw1==HIGH && Rsw2==HIGH){ RandRampR(pote1, pote2); } if (Rsw1==HIGH && Rsw2==LOW){ RampR(pote1, pote2); } if (Rsw1==LOW && Rsw2==LOW){ SimpleR(pote1, pote2); } if (Rsw1==LOW && Rsw2==HIGH){ RandomR(pote1, pote2); } } void Gswitch(long unsigned int pote1, long unsigned int pote2){ byte Gsw1 = digitalRead(Gswitch1); byte Gsw2 = digitalRead(Gswitch2); if (Gsw1==HIGH && Gsw2==HIGH){ RandRampG(pote1, pote2); } if (Gsw1==HIGH && Gsw2==LOW){ RampG(pote1, pote2); } if (Gsw1==LOW && Gsw2==LOW){ SimpleG(pote1, pote2); } if (Gsw1==LOW && Gsw2==HIGH){ RandomG(pote1, pote2); } } void Bswitch(long unsigned int pote1, long unsigned int pote2){ byte Bsw1 = digitalRead(Bswitch1); byte Bsw2 = digitalRead(Bswitch2); if (Bsw1==HIGH && Bsw2==HIGH){ RandRampB(pote1, pote2); } if (Bsw1==HIGH && Bsw2==LOW){ RampB(pote1, pote2); } if (Bsw1==LOW && Bsw2==LOW){ SimpleB(pote1, pote2); } if (Bsw1==LOW && Bsw2==HIGH){ RandomB(pote1, pote2); } } //Modes de funcionament void RampR(long unsigned int a, long unsigned int b){ SimpleR(0,ramp1(0,a*100,b*10)); } void RandomR(long unsigned int a, long unsigned int b){ SimpleR(0,randomize1(a*100,b)); } void RandRampR(long unsigned int a, long unsigned int b){ SimpleR(0,randomize1(a*50,0)+ramp1(0,50000,b)); } void RampG(long unsigned int a, long unsigned int b){ SimpleG(0,ramp2(0,a*100,b*10)); } void RandomG(long unsigned int a, long unsigned int b){ SimpleG(0,randomize2(a*100,b)); } void RandRampG(long unsigned int a, long unsigned int b){ SimpleG(0,randomize2(a*50,0)+ramp2(0,50000,b)); } void RampB(long unsigned int a, long unsigned int b){ SimpleB(0,ramp3(0,a*100,b*10)); } void RandomB(long unsigned int a, long unsigned int b){ SimpleB(0,randomize3(a*100,b)); } void RandRampB(long unsigned int a, long unsigned int b){ SimpleB(0,randomize3(a*50,0)+ramp3(0,50000,b)); } ////modes Simples void SimpleR(long unsigned int a, long unsigned int b){ unsigned long int rdel=(a*500)+b; unsigned long currentMicros = micros(); if (micros() - previousMicros >= rdel) { previousMicros = previousMicros+rdel; if (rdel <512000){ RState =! RState; digitalWrite(R, RState); digitalWrite(A, RState); } } } void SimpleG(long unsigned int a, long unsigned int b){ unsigned long int gdel=(a*500)+b; unsigned long currentMicros = micros(); if (micros() - previousMicros >= gdel) { previousMicros = previousMicros+gdel; if (gdel <512000){ GState =! GState; digitalWrite(G, GState); digitalWrite(A, GState); } } } void SimpleB(long unsigned int a, long unsigned int b){ unsigned long int bdel=(a*500)+b; unsigned long currentMicros = micros(); if (micros() - previousMicros >= bdel) { previousMicros = previousMicros+bdel; if (bdel <512000){ BState =! BState; digitalWrite(B, BState); digitalWrite(A, BState); } } } /////Rampes unsigned int ramp1(unsigned int inicio, unsigned int fin, long unsigned int duracion){ unsigned int frecuencia = inicio; if((millis() - initRamp1) < duracion){ frecuencia = map((millis() - initRamp1),0,duracion,inicio,fin); }else{ initRamp1 = millis(); } return frecuencia; } unsigned int ramp2(unsigned int inicio, unsigned int fin, long unsigned int duracion){ unsigned int frecuencia = inicio; if((millis() - initRamp2) < duracion){ frecuencia = map((millis() - initRamp2),0,duracion,inicio,fin); }else{ initRamp2 = millis(); } return frecuencia; } unsigned int ramp3(unsigned int inicio, unsigned int fin, long unsigned int duracion){ unsigned int frecuencia = inicio; if((millis() - initRamp3) < duracion){ frecuencia = map((millis() - initRamp3),0,duracion,inicio,fin); }else{ initRamp3 = millis(); } return frecuencia; } ///Randomitzador int randomize1(unsigned int v, unsigned int n){ if (millis() - previousMillis >= n) { previousMillis = previousMillis+n; random1=random(v); } return random1; } int randomize2(unsigned int v, unsigned int n){ if (millis() - previousMillis >= n) { previousMillis = previousMillis+n; random2=random(v); } return random2; } int randomize3(unsigned int v, unsigned int n){ if (millis() - previousMillis >= n) { previousMillis = previousMillis+n; random3=random(v); } return random3; } //Timer per a VGA ///////////////////////////// ISR Timer Functions /////////////////////////// ISR(TIMER2_COMPA_vect) { // Stop video // pin 5 LOW PORTD &= ~(1 << 5); // Front porch NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; // Count number of lines if (++linecount == vga_field_line_count) { linecount = 0; } // can it be vsync tiem nao ? if ((linecount == 10 )||(linecount == 11 )) { // hsync LOW // vsync LOW PORTD &= ~(1 << 7); PORTD &= ~(1 << 6); } else // ,hsync only { // hsync LOW // vsync HIGH PORTD &= ~(1 << 7); PORTD |= (1 << 6); } NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; // nonetheless, // hsync HIGH PORTD |= (1 << 7); NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; // Start video if we are in a visible area if (linecount > 45) { // pin 5 HIGH PORTD |= (1 << 5); } } void setISRtimer(){ // setup ISR timer controling toggleing TCCR2A = 0x02; // WGM22=0 + WGM21=1 + WGM20=0 = Mode2 (CTC) TCCR2B = (1 << CS01); // /8 prescaler (2MHz) TCNT2 = 0; // clear counter OCR2A = ISR_FREQ; // set TOP (divisor) - see #define } void startISR(){ // Starts the ISR TCNT2 = 0; // clear counter (needed here also) TIMSK2|=(1<