]>
git.defcon.no Git - avrfbosd/blob - syncgen/main.c
1dbfefb67913f324b1f547a93705c4c2b0f05923
2 #include <avr/interrupt.h>
3 #include <util/delay.h>
5 #define ZERO PORTB &= 0xFC
6 #define BLACK PORTB |= 0x01
10 // Com RST -| RST VCC |-`
12 // MegaClk -| CLKI ADC1 |---< VidDetect
14 // VSwithc -| PB4 PB1 |--^v^v-.
16 // .--| GND PB0 |--^v^v-'
20 #include "avrosdlogo.h"
22 volatile int rasterline
;
23 volatile uint16_t line
;
25 volatile uint8_t hres
;
26 volatile int renderLine
;
29 void asm_render_line( void ) {
30 __asm__
__volatile__ (
31 ".macro outbit p" "\n\t"
32 "BST __tmp_reg__,7" "\n\t" // Store bit 7 to T
33 "BLD r16,1" "\n\t" // Load bit T into r16 bit number 4
34 "OUT \\p,r16" "\n\t" // Send contents of r16 to %[port]
38 "ADD r26,r28" "\n\t" // Add register Y to register X, low part
39 "ADC r27,r29" "\n\t" // Add high Y to X with carry from low part
41 "IN r16,%[port]" "\n\t" // Save port content to register 16
42 "RJMP start_line" "\n\t"
44 "loop_byte:" "\n\t" // Notice that in the macro we always use bit 7 and left-shift
45 "BST __tmp_reg__,6" "\n\t" // Here we use bit 6 without left-shift to output bit 0
46 "BLD r16,1" "\n\t" // of each byte (except the last bit on the line)
47 "OUT %[port],r16" "\n\t" // We do not have time for a left-shift, teh "extra cycle" was used for "dec-branch"
51 "LD __tmp_reg__,X+" "\n\t" // Load from address pointed to by X into temporary register, then increment X-pointer
53 "outbit %[port]" "\n\t" // Output bit 7 using Macro
54 "LSL __tmp_reg__" "\n\t" // Left-shift for next bit
55 "outbit %[port]" "\n\t" // Output bit 6 using Macro
56 "LSL __tmp_reg__" "\n\t" // Left-shift for next bit
57 "outbit %[port]" "\n\t" // Output bit 5 using Macro
58 "LSL __tmp_reg__" "\n\t" // Left-shift for next bit
59 "outbit %[port]" "\n\t" // Output bit 4 using Macro
60 "LSL __tmp_reg__" "\n\t" // Left-shift for next bit
61 "outbit %[port]" "\n\t" // Output bit 3 using Macro
62 "LSL __tmp_reg__" "\n\t" // Left-shift for next bit
63 "outbit %[port]" "\n\t" // Output bit 2 using Macro
64 "LSL __tmp_reg__" "\n\t" // Left-shift for next bit
65 "outbit %[port]" "\n\t" // Output bit 1 using Macro
67 "DEC %[hres]" "\n\t" // Decrement num-bytes-remaining-in-resolution
68 "BRNE loop_byte" "\n\t" // Branch to loop6 if %[hres] != zero
70 "LSL __tmp_reg__" "\n\t" // Left-shift for last bit on the line
71 "outbit %[port]" "\n\t" // Output bit 0 using Macro.
73 "CBI %[port],1" "\n\t" // Clear our "display bit" to ensure we end on black
76 : [port
] "i" (_SFR_IO_ADDR(PORTB
)),
85 line
++; // Bumping the line-counter as part of hsync gives just the right front-porch ;D
86 ZERO
; _delay_us(4); // sync
87 BLACK
; _delay_us(8); // Back porch
90 void vsync(uint8_t odd_even
)
95 // Pre-equalization pulses
97 for(a
=0; a
<b
; a
++) // short sync
106 for(a
=0; a
<5 ; a
++) // long sync
114 // Post-equalization pulses
115 b
= odd_even
? 5 : 4;
116 for(a
=0; a
<b
; a
++) // short sync
123 line
= odd_even
? 5 : 317;
129 ISR (TIMER0_COMPA_vect
)
131 if(line
== 310) vsync(0); // End of ODD fields, start vsync'ing
132 else if(line
== 622) vsync(1); // End of EVEN, start vsync'ing
133 else // In frame. Generate a hsync pulse, then do some drawing :)
137 int t_line
= line
; // Reducing line-count complexity by half ;)
138 t_line
= ( line
> 312 ) ? line
- 312 : line
;
140 // Draw the logo-image centered vertically
141 if ( t_line
> 118 && t_line
< 118 + (2*testimg_height
) )
146 // Stretch the image vertically by repeating the same line twice
151 // Make sure we don't draw anything from RAM after the end of the image
152 if ( renderLine
> ((testimg_height
*hres
)-1) ) renderLine
= 0;
159 ISR (TIMER1_OVF_vect
)
161 // If this interrupt-vector is run, Timer1 has overflowed, and that means
162 // we have not seen any signal of significant level for quite a while.
163 // This means Sync-generation is needed...
165 // Make sure sync-gen is running...
166 TIMSK
|= (1<<OCIE0A
); // Enable compare-mach-a interrupt for Timer0
167 // Open up the switch blocking attiny-generated video:
176 hres
= testimg_width
/ 8;
178 DDRB
|= (1<<PB0
); // Black/zero level pin/resistor
179 DDRB
|= (1<<PB1
); // Color-pin, adds to black level ;)
180 DDRB
|= (1<<PB4
); // Control of video-switching. Fuse-bits changes this pin from XTAL2 to PB4
182 // Timer0 is used to generate hsync (and vsync)
183 TCCR0A
|= (1<<WGM01
)|(0<<WGM00
); // Set Clear on compare match
184 TCCR0B
|= (0<<WGM02
); // using WGM bits ...
185 TCCR0B
|= (0<<CS02
)|(1<<CS01
)|(0<<CS00
); // Set prescaler to CLK/8
186 TIMSK
|= (1<<OCIE0A
); // Enable compare-mach-a interrupt
187 OCR0A
= 159; // 160 "ticks" on 20MHz/8 => 64us. Trigger one early..
189 // Video detection is done using ADC1 on PB2...
190 ADMUX
|= (1<<ADLAR
); // Left-shifted result.
191 ADMUX
|= (1<<MUX0
); // Select ADC for PB2
192 ADCSRA
|= (1 << ADEN
); // Enable ADC
193 ADCSRA
|= (1 << ADPS2
)|(1 << ADPS1
)|(0<<ADPS0
); // set prescaler to 64
194 DIDR0
|= (1<<ADC1D
); // Disable logic input for PB2
196 TCCR1
|= (1<<CS13
)|(0<<CS12
)|(0<<CS11
)|(1<<CS10
); // Prescale Timer1 to CK/256
197 // CK/32 @ 20MHz gives 0.05us*256*256 = 3276.8us per Overflow, or 51 lines.
198 TIMSK
|= (1<<TOIE1
); // Enable Timer Overflow interrupts for Timer1
200 sei(); // We are ready to fire interrupts.
202 // Here, we continue to do nothing...
205 ADCSRA
|= (1 << ADSC
); // start ADC measurement
206 while (ADCSRA
& (1 << ADSC
) ); // wait till conversion complete
208 // We are detecting "video" if we have a value
209 // greater than some minimal value on ADC1/PB2.
210 // This approach requires a weak pulldown on the relevant
211 // video input to the circuit, but it beats not detecting anything.
212 // 255/50*4=20, thus 0.4V
215 // Make sure any signal generated by us does not leak back
216 PORTB
&= 0xEF; // Switch OFF VOut-switch for ATtiny
217 // The next statement stops sync-generation, thus also image-generation..
218 TIMSK
&= ~(1<<OCIE0A
); // Enable compare-mach-a interrupt
219 // Reset Timer1 so we don't generate a TOVF..
222 // If we did not see a signal above the treshold, TCNT1 will continue
223 // to count up, until a TOV1 interrupt is generated.