]> git.defcon.no Git - avrfbosd/blob - syncgen/main.c
8ad9cb339f0e8dd686fabcbc9bdf323bec843121
[avrfbosd] / syncgen / main.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <util/delay.h>
4
5 #define ZERO PORTB &= 0xFC
6 #define BLACK PORTB |= 0x01
7
8 // -----..----- ^
9 // | | |
10 // -| RST VCC |-`
11 // | |
12 // .--| X1 PB2 |-
13 // [ ] | | 470R
14 // '--| X2 PB1 |--^v^v-.
15 // | | |----> VidOut
16 // .--| GND PB0 |--^v^v-'
17 // | | | 1kR
18 //----- ------------
19
20 #include "avrosdlogo.h"
21
22 volatile int rasterline;
23 volatile uint16_t line;
24
25 volatile uint8_t hres;
26 volatile int renderLine;
27 int stretch;
28
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]
35 "NOP" "\n\t"
36 ".endm" "\n\t"
37
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
40
41 "IN r16,%[port]" "\n\t" // Save port content to register 16
42 "RJMP start_line" "\n\t"
43
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"
48 "NOP" "\n\t"
49
50 "start_line:" "\n\t"
51 "LD __tmp_reg__,X+" "\n\t" // Load from address pointed to by X into temporary register, then increment X-pointer
52
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
66
67 "DEC %[hres]" "\n\t" // Decrement num-bytes-remaining-in-resolution
68 "BRNE loop_byte" "\n\t" // Branch to loop6 if %[hres] != zero
69
70 "LSL __tmp_reg__" "\n\t" // Left-shift for last bit on the line
71 "outbit %[port]" "\n\t" // Output bit 0 using Macro.
72
73 "CBI %[port],1" "\n\t" // Clear our "display bit" to ensure we end on black
74
75 :
76 : [port] "i" (_SFR_IO_ADDR(PORTB)),
77 "x" (testimg_data),
78 "y" (renderLine),
79 [hres] "d" (hres)
80 );
81 }
82
83 void hsync(void)
84 {
85 line++;
86 ZERO; _delay_us(4); // sync
87 BLACK; _delay_us(8); // Back porch
88 }
89
90 void vsync(uint8_t odd_even)
91 {
92 uint8_t a,b;
93 cli();
94
95 // Pre-equalization pulses
96 b = odd_even ? 6 : 5;
97 for(a=0; a<b ; a++) // 6x short sync
98 {
99 ZERO;
100 _delay_us(2);
101
102 BLACK;
103 _delay_us(30);
104
105 }
106
107 // VSYNC
108 for(a=0; a<5 ; a++) // 5x long sync
109 {
110
111 ZERO;
112 _delay_us(30);
113
114 BLACK;
115 _delay_us(2);
116
117 }
118
119 // Post-equalization pulses
120 b = odd_even ? 5 : 4;
121 for(a=0; a<b ; a++) // 5x short sync
122 {
123 ZERO;
124 _delay_us(2);
125
126 BLACK;
127 _delay_us(30);
128
129 }
130 line = odd_even ? 5 : 317;
131 renderLine = 0;
132
133 sei();
134 }
135
136 ISR (TIMER0_COMPA_vect)
137 {
138 if(line == 310) vsync(0);
139 else if(line == 622) vsync(1);
140 else
141 {
142 hsync();
143 int t_line = line;
144 t_line = ( line > 312 ) ? line - 312 : line;
145
146 if ( t_line > 118 && t_line < 118 + (2*testimg_height) )
147 {
148 _delay_us(12);
149 asm_render_line();
150
151 if( !stretch )
152 {
153 stretch = 1;
154 renderLine += hres;
155 if ( renderLine > ((testimg_height*hres)-1) ) renderLine = 0;
156 } else stretch--;
157 }
158 }
159 return;
160 }
161
162 /*
163 ISR (INT0_vect)
164 {
165 //PORTB ^= 0x10;
166 PORTB |= 0x10;
167 }
168 */
169
170 int main(void)
171 {
172 rasterline = 0;
173 line = 0;
174
175 hres = testimg_width / 8;
176
177 DDRB |= (1<<PB0); // Black/zero level pin/resistor
178 DDRB |= (1<<PB1); // Color-pin, adds to black level ;)
179 DDRB |= (1<<PB4); // Control of video-switching. Fuse-bits changes this pin from XTAL2 to PB4
180
181 // Timer0 is used to generate hsync (and vsync)
182 TCCR0A |= (1<<WGM01)|(0<<WGM00); // Set Clear on compare match
183 TCCR0B |= (0<<WGM02); // using WGM bits ...
184 TCCR0B |= (0<<CS02)|(1<<CS01)|(0<<CS00); // Set prescaler to CLK/8
185 TIMSK |= (1<<OCIE0A); // Enable compare-mach-a interrupt
186 OCR0A = 159; // 160 "ticks" on 20MHz/8 => 64us. Trigger one early..
187
188 // Video detection is done using ADC1 on PB2...
189 ADMUX |= (1<<ADLAR); // Left-shifted result.
190 ADMUX |= (1<<MUX0); // Select ADC for PB2
191 ADCSRA |= (1 << ADEN); // Enable ADC
192 ADCSRA |= (1 << ADPS2)|(1 << ADPS1)|(0<<ADPS0); // set prescaler to 64
193 DIDR0 |= (1<<ADC1D); // Disable logic input for PB2
194
195 sei(); // We are ready to fire interrupts.
196
197 // Here, we continue to do nothing...
198 while(1)
199 {
200 ADCSRA |= (1 << ADSC); // start ADC measurement
201 while (ADCSRA & (1 << ADSC) ); // wait till conversion complete
202 {
203 // We are detecting "video" if we have a value
204 // greater than some minimal value on ADC1/PB2.
205 // This approach requires a weak pulldown on the relevant
206 // video input to the circuit, but it beats not detecting anything.
207 if (ADCH > 10)
208 {
209 // Dummy code.
210 // This needs to be replaced with something that triggers a timer ...
211 /// Simply indicate on PB4 that we are seeing somethin.
212 PORTB |= 0x10;
213 // The next statement stops sync-generation, thus also image-generation..
214 TIMSK &= ~(1<<OCIE0A); // Enable compare-mach-a interrupt
215 }
216 else
217 {
218 // Dummy code. Simply indicate on PB4 that we are below the threshold.
219 PORTB &= 0xEF;
220
221 // Make sure sync-gen is running...
222 TIMSK |= (1<<OCIE0A); // Enable compare-mach-a interrupt
223 }
224 }
225 };
226 }