display extended (untested!)
[my-code/arm.git] / betty / display.c
1 /*
2  * display.c - handling the display
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  */
7
8 /*
9  * some comments on alpha blending!
10  * ################################
11  *
12  * if c is the result of layer a over layer b with opacity alpha:
13  * 
14  * c=alpha*a+(1-alpha)*b and if alpha is a byte (0-255)
15  * => c=alpha*a+(255-alpha)*b
16  * 
17  */
18
19 #include "display.h"
20 #include "system.h"
21 #include "default_logo.h"
22 #include "uart.h"
23
24 /*
25  * functions
26  */
27
28 void display_fill_screen(u8 fill) {
29
30         u8 page,width;
31         u8 buf[2];
32
33         buf[0]=0;
34         buf[1]=0;
35
36         switch(fill) {
37                 case DISPLAY_FILL_LG:
38                         buf[1]=0xff;
39                         break;
40                 case DISPLAY_FILL_DG:
41                         buf[0]=0xff;
42                         break;
43                 case DISPLAY_FILL_B:
44                         buf[0]=0xff;
45                         buf[1]=0xff;
46                         break;
47                 case DISPLAY_FILL_W:
48                 default:
49                         break;
50         }
51
52         for(page=0;page<DISPLAY_PAGE_MAX;page++) {
53                 DISPLAY_SET_COL_ADDR(0);
54                 DISPLAY_SET_PAGE_ADDR(page);
55                 for(width=0;width<DISPLAY_DIMX;width++) {
56                         DISPLAY_DATA=buf[0];
57                         DISPLAY_DATA=buf[1];
58                 }
59         }
60 }
61
62 void display_clear_screen(void) {
63
64         display_fill_screen(DISPLAY_FILL_W);
65 }
66
67 void display_init(void) {
68
69         /* oscillator, regulator, boost, opamp, contrast */
70         DISPLAY_START_OSCILLATOR;
71         DISPLAY_SET_REGULATOR(7);
72         DISPLAY_SET_CONTRAST(0x38);
73         DISPLAY_SET_CONV_FACTOR(0x01);
74         DISPLAY_SET_POWER(DISPLAY_V_BOOST|DISPLAY_REGULATOR|DISPLAY_OPAMP);
75
76         // gray scale palette
77         DISPLAY_SET_WHITE(0,0,0,0);
78         DISPLAY_SET_LGRAY(5,5,5,5);     // obviously 3, but it's too bright!
79         DISPLAY_SET_DGRAY(7,7,7,7);     // obviously 6, but again too bright!
80         DISPLAY_SET_BLACK(9,9,9,9);
81
82         /* normal mode, display depending ram content */
83         DISPLAY_RAM_CONTENTS_ON;
84         display_clear_screen();
85         DISPLAY_NORMAL;                 // 00 -> white, 11 -> black
86         DISPLAY_SET_COM_ODIR_REMAPPED;  // start counting at the top
87
88         /* switch on the display */
89         DISPLAY_SET_ON;
90 }
91
92 void display_load_logo(u8 *src) {
93
94         u8 *s;
95         u8 page,width;
96
97         s=src;
98         if(s==0)
99                 s=default_logo;
100
101         for(page=0;page<DISPLAY_PAGE_MAX;page++) {
102                 DISPLAY_SET_COL_ADDR(0);
103                 DISPLAY_SET_PAGE_ADDR(page);
104                 for(width=0;width<DISPLAY_DIMX;width++) {
105                         DISPLAY_DATA=*s++;
106                         DISPLAY_DATA=*s++;
107                 }
108         }
109 }
110
111 #define display_m2i(m,r) (((((m)[0]>>r)&1)<<1)|(((m)[1]>>r)&1))
112
113 void display_draw_rectangle(u8 x,u8 y,u8 w,u8 h,u8 fill,u8 alpha) {
114
115         u8 page,col,row,rmax,cnt;
116         u8 d[2];
117         int ca,cb;
118         u8 a,b,c;                       // c = a over b
119
120         a=fill&0x03;
121         ca=0;
122         for(cnt=0;cnt<a;cnt++)          // contribution of a: alpha*a
123                 ca+=alpha;
124
125         for(page=(y>>3);page<=((y+h)>>3);page++) {      // page = y/8
126                 DISPLAY_SET_PAGE_ADDR(page);
127                 rmax=(page+1)<<3;                       // row max
128                 if(rmax>y+h)
129                         rmax=y+h;
130                 for(col=x;col<x+w;col++) {
131                         DISPLAY_SET_COL_ADDR(col);
132                         d[0]=DISPLAY_DATA;              // dummy read (p.16)
133                         d[0]=DISPLAY_DATA;
134                         d[1]=DISPLAY_DATA;
135                         for(row=y;row<rmax;row++) {
136                                 // contribution of b: (255-alpha)*b
137                                 b=display_m2i(d,row);
138                                 cb=0;
139                                 for(cnt=0;cnt<b;cnt++)
140                                         cb+=(255-alpha);
141                                 // finally there is c
142                                 c=(ca+cb)>>8;
143                                 d[0]&=~(1<<row);
144                                 d[1]&=~(1<<row);
145                                 d[0]|=((c>>1)&1)<<row;
146                                 d[1]|=(c&1)<<row;
147                         }
148                         DISPLAY_SET_COL_ADDR(col);
149                         DISPLAY_DATA=b[0];
150                         DISPLAY_DATA=b[1];
151                 }
152                 h-=(rmax-y);
153                 y=rmax;
154         }
155 }
156
157 void display_draw_font(u8 x,u8 y,u8 *font,u8 fill,u8 alpha) {
158
159         u8 page,col,row,rmax,cnt,left;
160         u8 d[2];
161         int ca,cb;
162         u8 a,b,c;                       // c = a over b
163
164         left=8;
165
166         a=fill&0x03;
167         ca=0;
168         for(cnt=0;cnt<a;cnt++)          // contribution of a: alpha*a
169                 ca+=alpha;
170
171         for(page=(y>>3);page<=((y+8)>>3);page++) {      // page = y/8
172                 DISPLAY_SET_PAGE_ADDR(page);
173                 rmax=(page+1)<<3;                       // row max
174                 if(rmax>y+left)
175                         rmax=y+left;
176                 cf=0;
177                 for(col=x;col<x+8;col++) {
178                         DISPLAY_SET_COL_ADDR(col);
179                         d[0]=DISPLAY_DATA;              // dummy read (p.16)
180                         d[0]=DISPLAY_DATA;
181                         d[1]=DISPLAY_DATA;
182                         rf=0;
183                         for(row=y;row<rmax;row++) {
184                                 // contribution of b: (255-alpha)*b
185                                 b=display_m2i(d,row);
186                                 cb=0;
187                                 for(cnt=0;cnt<b;cnt++)
188                                         cb+=(255-alpha);
189                                 // finally there is c
190                                 if((font[cf]>>row)&1) {
191                                         c=(ca+cb)>>8;
192                                         d[0]&=~(1<<row);
193                                         d[1]&=~(1<<row);
194                                         d[0]|=((c>>1)&1)<<row;
195                                         d[1]|=(c&1)<<row;
196                                 }
197                                 rf+=1;
198                         }
199                         DISPLAY_SET_COL_ADDR(col);
200                         DISPLAY_DATA=b[0];
201                         DISPLAY_DATA=b[1];
202                         cf+=1;
203                 }
204                 left-=(rmax-y);
205                 y=rmax;
206         }
207 }
208
209 void display_draw_buf(u8 x,u8 y,u8 w,u8 h,u8 *buf,u8 alpha) {
210
211         u8 page,col,row,rmax,cnt;
212         u8 d[2];
213         int ca,cb;
214         u8 a,b,c;
215
216         for(page=(y>>3);page<=((y+h)>>3);page++) {
217                 DISPLAY_SET_PAGE_ADDR(page);
218                 for(col=x;col<x+w;col++) {
219                         DISPLAY_SET_COL_ADDR(col);
220                         d[0]=DISPLAY_DATA;
221                         d[0]=DISPLAY_DATA;
222                         d[1]=DISPLAY_DATA;
223                         for(row=y;row<rmax;row++) {
224                         }
225                 }
226         }
227 }
228
229 void display_bl_init(void) {
230
231         IODIR0|=(1<<4);
232         IOSET0=(1<<4);  // off by default
233 }
234
235 void display_bl_toggle(void) {
236
237         if(IOPIN0&(1<<4))
238                 IOCLR0=(1<<4);
239         else
240                 IOSET0=(1<<4);
241 }
242
243 void display_bl_on(void) {
244
245         IOCLR0=(1<<4);
246 }
247
248 void display_bl_off(void) {
249
250         IOSET0=(1<<4);
251 }
252