]> git.defcon.no Git - avrfbosd/commitdiff
Merge branch 'videodetect'
authorJon Langseth <jon.langseth@lilug.no>
Sun, 22 Jul 2012 11:51:58 +0000 (13:51 +0200)
committerJon Langseth <jon.langseth@lilug.no>
Sun, 22 Jul 2012 11:51:58 +0000 (13:51 +0200)
syncgen/main.c

index 3fa6cea892f4c0d790f23942d1c6816ee30a2d2c..1dbfefb67913f324b1f547a93705c4c2b0f05923 100644 (file)
@@ -1,20 +1,21 @@
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include <util/delay.h>
-#define ZERO  PORTB=0b000
-#define BLACK PORTB=0b001
-
-//       -----..-----   ^
-//      |            |  |
-//     -| RST    VCC |-`
-//      |            |
-//   .--| X1     PB2 |-
-//  [ ] |            |  470R
-//   '--| X2     PB1 |--^v^v-.
-//      |            |       |----> VidOut
-//   .--| GND    PB0 |--^v^v-'
-//   |  |            |  1kR
-//-----  ------------
+
+#define ZERO  PORTB &= 0xFC
+#define BLACK PORTB |= 0x01
+
+//          -----..-----   ^
+//          | ___        |  |
+// Com RST -| RST    VCC |-`
+//          |            |
+// MegaClk -| CLKI  ADC1 |---< VidDetect
+//          |            |  470R
+// VSwithc -| PB4    PB1 |--^v^v-.
+//          |            |       |----> VidOut
+//       .--| GND    PB0 |--^v^v-'
+//       |  |            |  1kR
+//      ---  ------------
 
 #include "avrosdlogo.h"
 
@@ -81,7 +82,7 @@ void asm_render_line( void ) {
 
 void hsync(void)
 { 
-       line++;
+       line++; // Bumping the line-counter as part of hsync gives just the right front-porch ;D
        ZERO; _delay_us(4); // sync
        BLACK; _delay_us(8);  // Back porch
 }
@@ -93,38 +94,31 @@ void vsync(uint8_t odd_even)
 
        // Pre-equalization pulses
        b = odd_even ? 6 : 5;
-       for(a=0; a<b ; a++) // 6x short sync
+       for(a=0; a<b ; a++) // short sync
        {
                ZERO;
                _delay_us(2);
-
                BLACK;
                _delay_us(30);
-
        }
 
        // VSYNC
-       for(a=0; a<5 ; a++) // 5x long sync
+       for(a=0; a<5 ; a++) // long sync
        {
-
                ZERO;
                _delay_us(30);
-
                BLACK;
                _delay_us(2);
-
        }
 
        // Post-equalization pulses
        b = odd_even ? 5 : 4;
-       for(a=0; a<b ; a++) // 5x short sync
+       for(a=0; a<b ; a++) // short sync
        {
                ZERO;
                _delay_us(2);
-
                BLACK;
                _delay_us(30);
-
        }
        line = odd_even ? 5 : 317;
        renderLine = 0;
@@ -134,23 +128,27 @@ void vsync(uint8_t odd_even)
 
 ISR (TIMER0_COMPA_vect) 
 {
-       if(line == 310) vsync(0);
-       else if(line == 622) vsync(1);
-       else
+       if(line == 310) vsync(0); // End of ODD fields, start vsync'ing
+       else if(line == 622) vsync(1); // End of EVEN, start vsync'ing
+       else // In frame. Generate a hsync pulse, then do some drawing :)
        {
                hsync();
-               int t_line = line;
+
+               int t_line = line; // Reducing line-count complexity by half ;)
                t_line = ( line > 312 ) ? line - 312 : line;
 
+               // Draw the logo-image centered vertically
                if ( t_line > 118 && t_line < 118 + (2*testimg_height) )
                {
                        _delay_us(12.3);
                        asm_render_line();
 
+                       // Stretch the image vertically by repeating the same line twice
                        if( !stretch )
                        {
                                stretch = 1;
                                renderLine += hres;
+                               // Make sure we don't draw anything from RAM after the end of the image
                                if ( renderLine > ((testimg_height*hres)-1) ) renderLine = 0;
                        } else stretch--;
                }
@@ -158,6 +156,18 @@ ISR (TIMER0_COMPA_vect)
        return;
 }
 
+ISR (TIMER1_OVF_vect) 
+{
+       // If this interrupt-vector is run, Timer1 has overflowed, and that means
+       // we have not seen any signal of significant level for quite a while.
+       // This means Sync-generation is needed...
+
+       // Make sure sync-gen is running...
+       TIMSK |= (1<<OCIE0A); // Enable compare-mach-a interrupt for Timer0
+       // Open up the switch blocking attiny-generated video:
+       PORTB |= 0x10;
+}
+
 int main(void)
 {  
        rasterline = 0;
@@ -165,15 +175,52 @@ int main(void)
 
        hres = testimg_width / 8;
 
-       DDRB =0b111;  
+       DDRB |= (1<<PB0); // Black/zero level pin/resistor
+       DDRB |= (1<<PB1); // Color-pin, adds to black level ;)
+       DDRB |= (1<<PB4); // Control of video-switching. Fuse-bits changes this pin from XTAL2 to PB4
 
-       TCCR0A |= (1<<WGM01)|(0<<WGM00);
-       TCCR0B |= (0<<WGM02)|(0<<CS02)|(1<<CS01)|(0<<CS00);
-       TIMSK |= (1<<OCIE0A);
-       OCR0A = 159;
+       // Timer0 is used to generate hsync (and vsync)
+       TCCR0A |= (1<<WGM01)|(0<<WGM00); // Set Clear on compare match
+       TCCR0B |= (0<<WGM02);            // using WGM bits ...
+       TCCR0B |= (0<<CS02)|(1<<CS01)|(0<<CS00); // Set prescaler to CLK/8
+       TIMSK |= (1<<OCIE0A); // Enable compare-mach-a interrupt
+       OCR0A = 159; // 160 "ticks" on 20MHz/8 => 64us. Trigger one early..
 
-       sei();
+       // Video detection is done using ADC1 on PB2...
+       ADMUX |= (1<<ADLAR);   // Left-shifted result.
+       ADMUX |= (1<<MUX0);    // Select ADC for PB2
+       ADCSRA |= (1 << ADEN); // Enable ADC 
+       ADCSRA |= (1 << ADPS2)|(1 << ADPS1)|(0<<ADPS0); // set prescaler to 64
+       DIDR0 |= (1<<ADC1D);   // Disable logic input for PB2
+
+       TCCR1 |= (1<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10); // Prescale Timer1 to CK/256
+       // CK/32 @ 20MHz gives 0.05us*256*256 = 3276.8us per Overflow, or 51 lines.
+       TIMSK |= (1<<TOIE1); // Enable Timer Overflow interrupts for Timer1
+
+       sei(); // We are ready to fire interrupts.
 
        // Here, we continue to do nothing...
-       while(1);
+       while(1)
+       {
+               ADCSRA |= (1 << ADSC); // start ADC measurement
+               while (ADCSRA & (1 << ADSC) ); // wait till conversion complete 
+               {
+                       // We are detecting "video" if we have a value
+                       // greater than some minimal value on ADC1/PB2.
+                       // This approach requires a weak pulldown on the relevant
+                       // video input to the circuit, but it beats not detecting anything.
+                       // 255/50*4=20, thus 0.4V
+                       if (ADCH > 20)
+                       {
+                               // Make sure any signal generated by us does not leak back
+                               PORTB &= 0xEF; // Switch OFF VOut-switch for ATtiny
+                               // The next statement stops sync-generation, thus also image-generation..
+                               TIMSK &= ~(1<<OCIE0A); // Enable compare-mach-a interrupt
+                               // Reset Timer1 so we don't generate a TOVF..
+                               TCNT1 = 0;
+                       }
+                       // If we did not see a signal above the treshold, TCNT1 will continue
+                       // to count up, until a TOV1 interrupt is generated.
+               }
+       };
 }