]> 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)
1  2 
syncgen/main.c

diff --combined syncgen/main.c
index 3fa6cea892f4c0d790f23942d1c6816ee30a2d2c,e67d582bd0b1a1f15259934e26d1604af55f6846..1dbfefb67913f324b1f547a93705c4c2b0f05923
@@@ -1,20 -1,21 +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 +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 +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;
  
  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);
 +                      _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--;
                }
        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;
  
        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.
+               }
+       };
  }