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