]> git.defcon.no Git - avrfbosd/blob - fbosd.c
c30ee9b5aa3606601ef10f6c07168f890560ca64
[avrfbosd] / fbosd.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <util/delay.h>
4 #include <stdlib.h>
5
6 #include "video_properties.h"
7 #include "render.h"
8 #include "draw.h"
9
10 void (*line_handler)( void );
11
12 const int vres_scale = ( SCREEN_LINES / VRES -1 );
13 const int hres_bytes = HRES / 8;
14
15 volatile uint8_t* screen_buffer;
16
17 volatile int line;
18 volatile int buffer_position;
19
20 void Delay_ms(int cnt)
21 {
22 while(cnt-->0) _delay_ms(1);
23 }
24
25 void set_busy ( uint8_t busy)
26 {
27 if ( busy )
28 {
29 // Set busy signal
30 PORTB |= (1 << PB1);
31
32 // TODO: Disable SPI communication here...
33 }
34 else
35 {
36 // Clear Busy signal
37 PORTB &= ~(uint8_t)(1 << PB1);
38
39 // TODO: Enable SPI communication here...
40 }
41 }
42
43 void active_lines ( void )
44 {
45 static uint8_t rept;
46
47 _delay_us(4);
48
49 // Set Busy signal. Line rendering is time-critical.
50 set_busy(1);
51 asm_render_line();
52 set_busy(0);
53
54 if( !rept )
55 {
56 if ( buffer_position < ((VRES*hres_bytes)) )
57 buffer_position += hres_bytes;
58 rept = vres_scale;
59 }
60 else rept--;
61
62 }
63
64 void blank_lines ( void )
65 {
66 // Do nothing on the "lead-in" lines
67 if ( line < FIRST_LINE )
68 return;
69
70 // Clear Frame Ready signal
71 PORTD &= ~(uint8_t)(1 << PD5);
72
73 // Activate rendering
74 line_handler = active_lines;
75 }
76
77 ISR (INT1_vect)
78 {
79 line_handler();
80 line++;
81 if( line > LAST_LINE)
82 {
83 line = 0;
84 buffer_position = 0;
85 line_handler = &blank_lines;
86 EIMSK &= ~(uint8_t)(1<<INT1);
87
88 // Set Frame Ready signal
89 PORTD |= (1 << PD5);
90
91 }
92 }
93
94 ISR (INT0_vect)
95 {
96 // VSync is getting close to done.
97 // Set line-handler to blank-handler to count-up the undesired lines,
98 // and enable HSync interrupts.
99
100 line_handler = &blank_lines;
101
102 EIMSK |= (1<<INT1);
103
104 }
105
106 //Main Function
107 int main(void)
108 {
109 // Note: PB0 is used as CLKO outputting 20MHz clock to ATtiny
110
111 // Set PB2 as Output for BUSY signal
112 DDRB = (1 << PB1);
113
114 // Set PD5 as Output for FR signal
115 // Set PD6 as Output for Status LED
116 // Using pin 7 on PD to clock out pixels \o/
117 DDRD = (1<<PD5)|(1<<PD6)|(1<<PD7);
118
119 // Clear PORTB and PORTD
120 PORTB = 0x0;
121 PORTD = 0x0;
122
123 // Allocate the framebuffer :D
124 screen_buffer = (uint8_t*) malloc( hres_bytes * VRES * sizeof(uint8_t) );
125 // And make sure it's cleared
126 fill(c_BLACK);
127
128 /* LM1881 pins are connected to:
129 INT0 / PCINT18 / PD2 <- VSYNC
130 INT1 / PCINT19 / PD3 <- CSYNC
131 PCINT20 / PD4 <- ODD/EVEN
132 */
133 EICRA |= (1<<ISC01)|(1<<ISC00); // Select Rising-edge interrupt for VSync
134 EICRA |= (1<<ISC11)|(1<<ISC10); // Select Rising-edge interrupt for HSync
135 EIMSK |= (1<<INT0); // Enable VSync-interrupts
136
137 // Enable interrupts globally.
138 sei();
139
140 // Do some static drawing :P
141 set_pixel(28, 8, 1);
142 set_pixel(92, 82, 1);
143
144 set_pixel(92, 8, 1);
145 set_pixel(28, 82, 1);
146
147 draw_line(0, 0, 128, 92, 1);
148 draw_line(128, 0, 0, 92, 1);
149
150 draw_rect( 0, 1, 127, 91, 1);
151
152 draw_rect( 34, 21, 60, 50, 1);
153 _draw_rect( 24, 11, 80, 70, 1, -1);
154 draw_rect( 34, 21, 60, 50, 1);
155
156 fill_circle( 64,46, 45, 1 );
157 fill_circle( 64,46, 40, 0 );
158
159 _draw_circle( 64,46, 35, 1, -1 );
160 draw_circle( 64,46, 30, 1 );
161 fill_rect( 38, 25, 52, 42, 1);
162 fill_rect( 41, 28, 46, 36, 0);
163
164 for (;;)
165 {
166 // Toggle status LED
167 PORTD ^= (uint8_t)(1 << PD6);
168
169 for ( int j = 0; j < 92; j++ )
170 {
171 draw_line(0,0,128,j, 2);
172 draw_line(128,0,0,j, 2);
173 draw_line(0,92,128,92-j, 2);
174 draw_line(128,92,0,92-j, 2);
175
176 Delay_ms(2);
177
178 }
179 for ( int j = 0; j < 92; j++ )
180 {
181 draw_line(0,0,128,j, 2);
182 draw_line(128,0,0,j, 2);
183 draw_line(0,92,128,92-j, 2);
184 draw_line(128,92,0,92-j, 2);
185
186 Delay_ms(2);
187
188 }
189 Delay_ms(250);
190 }
191 }
192
193
194