]> git.defcon.no Git - avrfbosd/blob - fbosd.c
Demo updated to use new clear_screen()
[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 Delay_ms(100);
149 draw_string( 2, 2, "!\"#$%&'()*+-./");
150 draw_string( 2, 10, "01234567890");
151 draw_string( 2, 18, ":;<=>?@");
152 draw_string( 2, 26, "ABCDEFGHIJKLM");
153 draw_string( 2, 34, "NOPQRSTUVWXYZ");
154 draw_string( 2, 42, "[\\]^_`");
155 draw_string( 2, 50, "ABCDEFGHIJKLM");
156 draw_string( 2, 58, "NOPQRSTUVWXYZ");
157 draw_string( 2, 66, "{|}~");
158
159 draw_char( 10, 80, 127);
160 draw_char( 20, 80, 128);
161 draw_char( 30, 80, 129);
162 draw_char( 40, 80, 130);
163
164 Delay_ms(500);
165 clear_screen();
166
167 // Do some static drawing :P
168 set_pixel(28, 8, 1);
169 set_pixel(92, 82, 1);
170
171 set_pixel(92, 8, 1);
172 set_pixel(28, 82, 1);
173
174 draw_line(0, 0, 128, 92, c_WHITE);
175 draw_line(128, 0, 0, 92, c_WHITE);
176
177 draw_rect( 0, 1, 127, 91, c_WHITE);
178
179 draw_rect( 34, 21, 60, 50, c_WHITE);
180 _draw_rect( 24, 11, 80, 70, 1, c_NONE);
181 draw_rect( 34, 21, 60, 50, c_WHITE);
182
183 fill_circle( 64,46, 45, c_WHITE );
184 fill_circle( 64,46, 40, c_BLACK );
185
186 _draw_circle( 64,46, 35, 1, c_NONE );
187 draw_circle( 64,46, 30, c_WHITE );
188 fill_rect( 38, 25, 52, 42, c_WHITE);
189 fill_rect( 41, 28, 46, 36, c_BLACK);
190
191 for ( int j = 0; j < 92; j++ )
192 {
193 draw_line(0,0,128,j, c_INVERT);
194 draw_line(128,0,0,j, c_INVERT);
195 draw_line(0,92,128,92-j, c_INVERT);
196 draw_line(128,92,0,92-j, c_INVERT);
197
198 Delay_ms(2);
199
200 }
201 for ( int j = 0; j < 92; j++ )
202 {
203 draw_line(0,0,128,j, c_INVERT);
204 draw_line(128,0,0,j, c_INVERT);
205 draw_line(0,92,128,92-j, c_INVERT);
206 draw_line(128,92,0,92-j, c_INVERT);
207
208 Delay_ms(2);
209
210 }
211 Delay_ms(250);
212 clear_screen();
213
214 int8_t hp = 10;
215 int8_t vp = 10;
216
217 int counter = 0;
218 for (counter = 0; counter < 60; counter++)
219 {
220 hp += 2;
221 vp += 1;
222
223 if ( hp > 125 ) hp = 10;
224 if ( vp > VRES ) vp = 10;
225
226 pgm_draw_8bpp_bitmap(hp, vp, testimage_width, testimage_height, testimage);
227 Delay_ms(10);
228 //fill_rect(hp, vp, testimage_width, testimage_height, 0);
229 clear_screen();
230 }
231 clear_screen();
232
233 }
234 }
235