//PAL/NTSC interlaced sync generator, Gijs Gieskes 2013/2014 //For use with: 3TrinsRGB+1c //Based on arduino TVout library: //https://code.google.com/p/arduino-tvout/ //Interlaced video information used: //http://www.batsocks.co.uk/readme/video_timing.htm //http://martin.hinner.info/vga/pal.html volatile boolean STANDART = true; //PAL #define pSCANLINE 863 #define pHALFSCAN (pSCANLINE / 2) #define pSYNC 63 #define pSHORTSYNC (pSYNC / 2) #define pBREOADYNC 367 #define pLINEEND 319 #define pPICTURE 85 #define pWUNTIL 84 //NTSC #define nSCANLINE 857 #define nHALFSCAN (nSCANLINE / 2) #define nSYNC 63 #define nSHORTSYNC (nSYNC / 2) #define nBREOADYNC 367 #define nLINEEND1 270 #define nLINEEND2 271 #define nPICTURE 84 #define nWUNTIL 101 //PINS const byte LEDrP = 1; //C const byte LEDgP = 2; //C const byte LEDbP = 4; //C const byte SCRLP = 0; //B const byte SCRLB = 7; //D const byte CAPrP = 5; //C const byte CAPgP = 4; //C const byte CAPbP = 3; //C const byte BUTrP = 3; //D const byte BUTgP = 5; //D const byte BUTbP = 6; //D const byte SYNrP = 5; //B const byte SYNgP = 4; //B const byte SYNbP = 3; //B //ISR variables volatile boolean hzflip; volatile boolean hzfliper; volatile int linecount; volatile boolean render; volatile boolean interflip; volatile boolean beamhack = 0; volatile int plineend = pLINEEND; volatile int nlineend1 = nLINEEND1; volatile int nlineend2 = nLINEEND2; volatile byte diodeR = 1; volatile byte diodeG = 1; volatile byte diodeB = 1; //menu variables boolean prevG = false; boolean prevR = false; boolean prevB = false; //capFLipRcitor selection switch boolean capFLipR = true; boolean capFLipG = true; boolean capFLipB = true; void setup() { cli(); //select NTSC or PAL pinMode(16, INPUT); STANDART = digitalRead(16); DDRB = B11111111; //BUTTONS pinMode(3, INPUT); digitalWrite(3, HIGH); pinMode(5, INPUT); digitalWrite(5, HIGH); pinMode(6, INPUT); digitalWrite(6, HIGH); pinMode(7, INPUT); digitalWrite(7, HIGH); //RGB LED's pinMode(1, OUTPUT); pinMode(2, OUTPUT); pinMode(4, OUTPUT); //CAPACITOR INPUTS pinMode(17, INPUT); digitalWrite(17, LOW); pinMode(18, INPUT); digitalWrite(18, LOW); pinMode(19, INPUT); digitalWrite(19, LOW); //no interupts timer 0 TIMSK0 = 0; OCR0A = 0; OCR0B = 0; //inverted fast pwm mode on timer 1 TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11); TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); if(!STANDART){ ICR1 = pSCANLINE; }else{ ICR1 = nSCANLINE; } TIMSK1 = _BV(TOIE1); sei(); } ISR(TIMER1_OVF_vect) { if(!STANDART){ wait_until(pWUNTIL); bitWrite(PORTB, 0, 0); //interlaced PAL switch (linecount){ case 0: diodeAB1(); interflip = !interflip; break; case 1: diodeAB0(); ICR1 = pHALFSCAN; OCR1A = pBREOADYNC; break; case 6: OCR1A = pSHORTSYNC; break; case 11: if(!interflip){ ICR1 = pSCANLINE; } OCR1A = pSYNC; break; case 12: hzflip = false; ICR1 = pSCANLINE; break; case 22: diodeAB2P(); //hack voor geen 50hz.. render = true; break; case 316: hzflip = true; render = false; if(!interflip){ ICR1 = pHALFSCAN; } OCR1A = pSHORTSYNC; break; case 317: ICR1 = pHALFSCAN; break; } linecount++; if(linecount > plineend){ linecount = 0; } if(render){ bitWrite(PORTB, 2, 1); for(byte i=0; i nlineend1){ linecount = 0; } }else{ if(linecount > nlineend2){ linecount = 0; } } } } void loop() { if(!digitalRead(3)){ if(prevR){ prevR = false; capFLipR = !capFLipR; if(capFLipR){ diodeR = 1; pinMode(19, INPUT); digitalWrite(1, LOW); }else{ diodeR = 0; pinMode(19, OUTPUT); digitalWrite(19, LOW); digitalWrite(1, HIGH); } } }else{ prevR = true; } if(!digitalRead(5)){ if(prevG){ prevG = false; capFLipG = !capFLipG; if(capFLipG){ diodeG = 1; pinMode(18, INPUT); digitalWrite(2, LOW); }else{ diodeG = 0; pinMode(18, OUTPUT); digitalWrite(18, LOW); digitalWrite(2, HIGH); } } }else{ prevG = true; } if(!digitalRead(6)){ if(prevB){ prevB = false; capFLipB = !capFLipB; if(capFLipB){ diodeB = 1; pinMode(17, INPUT); digitalWrite(4, LOW); }else{ diodeB = 0; pinMode(17, OUTPUT); digitalWrite(17, LOW); digitalWrite(4, HIGH); } } }else{ prevB = true; } if(!digitalRead(7)){ plineend = pLINEEND + 2; nlineend1 = nLINEEND1 + 1; }else{ plineend = pLINEEND; nlineend1 = nLINEEND1; } } static void inline wait_until(unsigned char time) { __asm__ __volatile__ ( "sub %[time], %[tcnt1l]\n\t" "subi %[time], 10\n" "100:\n\t" "subi %[time], 3\n\t" "brcc 100b\n\t" "subi %[time], 0-3\n\t" "breq 101f\n\t" "dec %[time]\n\t" "breq 102f\n\t" "rjmp 102f\n" "101:\n\t" "nop\n" "102:\n" : : [time] "a" (time), [tcnt1l] "a" (TCNT1L) ); } inline void diodeAB1(){ if(diodeR == 0){ bitWrite(PORTB, SYNrP, 1); } if(diodeG == 0){ bitWrite(PORTB, SYNgP, 1); } if(diodeB == 0){ bitWrite(PORTB, SYNbP, 1); } } inline void diodeAB0(){ if(diodeR == 0){ bitWrite(PORTB, SYNrP, 0); } if(diodeG == 0){ bitWrite(PORTB, SYNgP, 0); } if(diodeB == 0){ bitWrite(PORTB, SYNbP, 0); } } inline void diodeAB2P(){ if(diodeR == 1){ bitWrite(PORTB, SYNrP, 1); bitWrite(PORTB, SYNrP, 0); } if(diodeG == 1){ bitWrite(PORTB, SYNgP, 1); bitWrite(PORTB, SYNgP, 0); } if(diodeB == 1){ bitWrite(PORTB, SYNbP, 1); bitWrite(PORTB, SYNbP, 0); } } inline void diodeAB2N(){ if(diodeR == 1){ bitWrite(PORTB, SYNrP, 1); bitWrite(PORTB, SYNrP, 0); } if(diodeG == 1){ bitWrite(PORTB, SYNgP, 1); bitWrite(PORTB, SYNgP, 0); } if(diodeB == 1){ bitWrite(PORTB, SYNbP, 1); bitWrite(PORTB, SYNbP, 0); } }