]> git.defcon.no Git - avrfbosd/blob - draw.c
Timer-code. This works fine with my video-grabber. My LCD struggles, but that may...
[avrfbosd] / draw.c
1 #include "draw.h"
2 #include <stdlib.h>
3
4 extern uint8_t* screen_buffer;
5 extern uint8_t hres_bytes;
6
7 void sp(uint8_t x, uint8_t y, uint8_t color)
8 {
9 if (color==0) screen_buffer[(x/8) + (y*hres_bytes)] &= ~0x80 >> (x&7);
10 else if (color==1) screen_buffer[(x/8) + (y*hres_bytes)] |= 0x80 >> (x&7);
11 else screen_buffer[(x/8) + (y*hres_bytes)] ^= 0x80 >> (x&7);
12 }
13
14 void set_pixel(uint8_t x, uint8_t y, uint8_t color)
15 {
16 if (x >= hres_bytes*8 || y >= VRES)
17 return;
18 sp(x,y,color);
19 }
20
21 void fill(uint8_t color)
22 {
23 switch(color) {
24 case c_BLACK:
25 for (int i = 0; i < (hres_bytes*VRES); i++)
26 screen_buffer[i] = 0;
27 break;
28 case c_WHITE:
29 for (int i = 0; i < (hres_bytes*VRES); i++)
30 screen_buffer[i] = 0xFF;
31 break;
32 case c_INVERT:
33 for (int i = 0; i < (hres_bytes*VRES); i++)
34 screen_buffer[i] = ~screen_buffer[i];
35 break;
36 }
37 }
38
39
40 /*
41 Bresenham's line algorithm, optimized and simplified.
42 function line(x0, y0, x1, y1)
43 dx := abs(x1-x0)
44 dy := abs(y1-y0)
45 if x0 < x1 then sx := 1 else sx := -1
46 if y0 < y1 then sy := 1 else sy := -1
47 err := dx-dy
48
49 loop
50 setPixel(x0,y0)
51 if x0 = x1 and y0 = y1 exit loop
52 e2 := 2*err
53 if e2 > -dy then
54 err := err - dy
55 x0 := x0 + sx
56 end if
57 if e2 < dx then
58 err := err + dx
59 y0 := y0 + sy
60 end if
61 end loop
62 */
63 void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t c)
64 {
65
66 if (x0 > hres_bytes*8 || y0 > VRES || x1 > hres_bytes*8 || y1 > VRES)
67 return;
68
69 int dx, dy, sx, sy, err, p;
70
71 dx = abs( x1-x0 );
72 dy = abs( y1-y0 );
73 if ( x0 < x1 ) sx = 1; else sx = -1;
74 if ( y0 < y1 ) sy = 1; else sy = -1;
75 err = dx - dy;
76
77 while (1)
78 {
79 sp(x0, y0, c);
80 if ( ( x0 == x1 ) && ( y0 == y1 ) ) return;
81 p = 2 * err;
82 if ( p > -dy )
83 {
84 err = err - dy;
85 x0 = x0 + sx;
86 }
87 if ( p < dx )
88 {
89 err = err + dx;
90 y0 = y0 + sy;
91 }
92 }
93 }
94 // draw_row and draw_col ...
95 // These whould really be used for optimization.
96 // As is, they exist for conveniance, not speed :P
97 void draw_col(uint8_t x, uint8_t y0, uint8_t y1, uint8_t c)
98 {
99 draw_line( x, y0, x, y1, c );
100 }
101 void draw_row(uint8_t y, uint8_t x0, uint8_t x1, uint8_t c)
102 {
103 draw_line( x0, y, x1, y, c );
104 }
105
106
107 void _draw_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, int8_t c, int8_t fc )
108 {
109 if ( fc != -1 )
110 for (unsigned char i = 0; i < h; i++)
111 draw_line(x0,y0+i,x0+w,y0+i,c);
112
113 draw_line(x0,y0,x0+w,y0,c);
114 draw_line(x0,y0,x0,y0+h,c);
115 draw_line(x0+w,y0,x0+w,y0+h,c);
116 draw_line(x0,y0+h,x0+w,y0+h,c);
117 }
118
119 void _draw_circle(uint8_t x0, uint8_t y0, uint8_t radius, int8_t c, int8_t fc) {
120
121 int f = 1 - radius;
122 int ddF_x = 1;
123 int ddF_y = -2 * radius;
124 int x = 0;
125 int y = radius;
126 uint8_t pyy = y,pyx = x;
127
128 //there is a fill color
129 if (fc != -1)
130 draw_row(y0,x0-radius,x0+radius,fc);
131
132 sp(x0, y0 + radius,c);
133 sp(x0, y0 - radius,c);
134 sp(x0 + radius, y0,c);
135 sp(x0 - radius, y0,c);
136
137 while(x < y) {
138 if(f >= 0) {
139 y--;
140 ddF_y += 2;
141 f += ddF_y;
142 }
143 x++;
144 ddF_x += 2;
145 f += ddF_x;
146 //there is a fill color
147 if (fc > -1) {
148 //prevent double draws on the same rows
149 if (pyy != y) {
150 draw_row(y0+y,x0-x,x0+x,fc);
151 draw_row(y0-y,x0-x,x0+x,fc);
152 }
153 if (pyx != x && x != y) {
154 draw_row(y0+x,x0-y,x0+y,fc);
155 draw_row(y0-x,x0-y,x0+y,fc);
156 }
157 pyy = y;
158 pyx = x;
159 }
160
161 sp(x0 + x, y0 + y,c);
162 sp(x0 - x, y0 + y,c);
163 sp(x0 + x, y0 - y,c);
164 sp(x0 - x, y0 - y,c);
165 sp(x0 + y, y0 + x,c);
166 sp(x0 - y, y0 + x,c);
167 sp(x0 + y, y0 - x,c);
168 sp(x0 - y, y0 - x,c);
169 }
170 }
171
172 void draw_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, uint8_t c)
173 {
174 _draw_rect(x0, y0, w, h, c, -1);
175 }
176
177 void fill_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, uint8_t c)
178 {
179 _draw_rect(x0, y0, w, h, c, c);
180 }
181
182 void draw_circle(uint8_t x0, uint8_t y0, uint8_t radius, char c)
183 {
184 _draw_circle(x0, y0, radius, c, -1);
185 }
186
187 void fill_circle(uint8_t x0, uint8_t y0, uint8_t radius, char c)
188 {
189 _draw_circle(x0, y0, radius, c, c);
190 }
191
192