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