bullshit commit, sync for travel (to zn00H!) :)
[my-code/arm.git] / betty / display.c
index 210cd17..46e8480 100644 (file)
  *
  */
 
+/*
+ * some comments on alpha blending!
+ * ################################
+ *
+ * if c is the result of layer a over layer b with opacity alpha:
+ * 
+ * c=alpha*a+(1-alpha)*b and if alpha is a byte (0-255)
+ * => c=alpha*a+(255-alpha)*b
+ * 
+ */
+
 #include "display.h"
 
+// debug
+#include "uart.h"
+
 /*
  * functions
  */
 
+void display_fill_screen(u8 fill) {
+
+       u8 page,width;
+       u8 buf[2];
+
+       buf[0]=0;
+       buf[1]=0;
+
+       switch(fill) {
+               case DISPLAY_FILL_LG:
+                       buf[1]=0xff;
+                       break;
+               case DISPLAY_FILL_DG:
+                       buf[0]=0xff;
+                       break;
+               case DISPLAY_FILL_B:
+                       buf[0]=0xff;
+                       buf[1]=0xff;
+                       break;
+               case DISPLAY_FILL_W:
+               default:
+                       break;
+       }
+
+       for(page=0;page<DISPLAY_PAGE_MAX;page++) {
+               DISPLAY_SET_COL_ADDR(0);
+               DISPLAY_SET_PAGE_ADDR(page);
+               for(width=0;width<DISPLAY_DIMX;width++) {
+                       DISPLAY_DATA=buf[0];
+                       DISPLAY_DATA=buf[1];
+               }
+       }
+}
+
+void display_clear_screen(void) {
+
+       display_fill_screen(DISPLAY_FILL_W);
+}
+
 void display_init(void) {
 
-       BCFG1=0x00000c42;
+       /* oscillator, regulator, boost, opamp, contrast */
+       DISPLAY_START_OSCILLATOR;
+       DISPLAY_SET_REGULATOR(7);
+       DISPLAY_SET_CONTRAST(0x38);
+       DISPLAY_SET_CONV_FACTOR(0x01);
+       DISPLAY_SET_POWER(DISPLAY_V_BOOST|DISPLAY_REGULATOR|DISPLAY_OPAMP);
+
+       // gray scale palette
+       DISPLAY_SET_WHITE(0,0,0,0);
+       DISPLAY_SET_LGRAY(5,5,5,5);     // obviously 3, but it's too bright!
+       DISPLAY_SET_DGRAY(7,7,7,7);     // obviously 6, but again too bright!
+       DISPLAY_SET_BLACK(9,9,9,9);
+
+       /* normal mode, display depending ram content */
+       DISPLAY_RAM_CONTENTS_ON;
+       display_clear_screen();
+       DISPLAY_NORMAL;                 // 00 -> white, 11 -> black
+       DISPLAY_SET_COM_ODIR_REMAPPED;  // start counting at the top
+
+       /* switch on the display */
+       DISPLAY_SET_ON;
+}
+
+void display_logo(u8 *src) {
+
+       u8 page,width;
+
+       for(page=0;page<DISPLAY_PAGE_MAX;page++) {
+               DISPLAY_SET_COL_ADDR(0);
+               DISPLAY_SET_PAGE_ADDR(page);
+               for(width=0;width<DISPLAY_DIMX;width++) {
+                       DISPLAY_DATA=*src++;
+                       DISPLAY_DATA=*src++;
+               }
+       }
+}
+
+#define display_m2i(m,r) (((((m)[0]>>r)&1)<<1)|(((m)[1]>>r)&1))
+
+void display_draw_rectangle(u8 x,u8 y,u8 w,u8 h,u8 fill,u8 alpha) {
+
+       u8 page,col,row,rmax,cnt;
+       u8 d[2];
+       int ca,cb;
+       u8 a,b,c;                       // c = a over b
+
+       a=fill&0x03;
+       ca=0;
+       for(cnt=0;cnt<a;cnt++)          // contribution of a: alpha*a
+               ca+=alpha;
+
+       for(page=(y>>3);page<=((y+h)>>3);page++) {      // page = y/8
+               DISPLAY_SET_PAGE_ADDR(page);
+               rmax=(page+1)<<3;                       // row max
+               if(rmax>y+h)
+                       rmax=y+h;
+               for(col=x;col<x+w;col++) {
+                       DISPLAY_SET_COL_ADDR(col);
+                       d[0]=DISPLAY_DATA; // dummy read (p.16)
+                       d[0]=DISPLAY_DATA;
+                       d[1]=DISPLAY_DATA;
+                       row=DISPLAY_DATA; // aligne
+                       for(row=y;row<rmax;row++) {
+                               // contribution of b: (255-alpha)*b
+                               b=display_m2i(d,row);
+                               cb=0;
+                               for(cnt=0;cnt<b;cnt++)
+                                       cb+=(255-alpha);
+                               // finally there is c
+                               c=(ca+cb)>>8;
+                               d[0]&=~(1<<row);
+                               d[1]&=~(1<<row);
+                               d[0]|=((c>>1)&1)<<row;
+                               d[1]|=(c&1)<<row;
+                       }
+                       DISPLAY_SET_COL_ADDR(col);
+                       DISPLAY_DATA=d[0];
+                       DISPLAY_DATA=d[1];
+               }
+               h-=(rmax-y);
+               y=rmax;
+       }
+}
+
+void display_rectangle_page(u8 x,u8 p,u8 w,u8 h,u8 fill,u8 alpha) {
+
+       u8 page,col,row;
+       u8 buf[2];
+       u8 b,c;
+
+       for(page=p;page<p+h;page++) {
+               DISPLAY_SET_PAGE_ADDR(page);
+               for(col=x;col<x+w;col++) {
+                       DISPLAY_SET_COL_ADDR(col);
+                       buf[0]=DISPLAY_DATA; // dummy read
+                       buf[0]=DISPLAY_DATA;
+                       buf[1]=DISPLAY_DATA;
+                       row=DISPLAY_DATA; // aligne dummy read
+                       for(row=0;row<8;row++) {
+                               b=display_m2i(buf,row);
+                               c=(b*(255-alpha)+fill*alpha)>>8;
+                               buf[0]&=~(1<<row);
+                               buf[1]&=~(1<<row);
+                               if(c&2)
+                                       buf[0]|=(1<<row);
+                               if(c&1)
+                                       buf[1]|=(1<<row);
+                       }
+                       DISPLAY_SET_COL_ADDR(col);
+                       DISPLAY_DATA=buf[0];
+                       DISPLAY_DATA=buf[1];
+               }
+       }
+}
+
+void display_font_page(u8 x,u8 page,u8 *font,u8 fill) {
+
+       /* this only draws page aligned fonts! */
+       u8 cnt,row;
+       u8 c[16];
+
+       /* set the page */
+       DISPLAY_SET_PAGE_ADDR(page);
+
+       /* read old content */
+       DISPLAY_SET_COL_ADDR(x);
+       c[0]=DISPLAY_DATA; // dummy read
+       for(cnt=0;cnt<16;cnt++) {
+               c[cnt++]=DISPLAY_DATA;
+               c[cnt]=DISPLAY_DATA;
+       }
+       cnt=DISPLAY_DATA; // 2 byte aligne dummy read
+
+       /* write new content */
+       DISPLAY_SET_COL_ADDR(x);
+       for(cnt=0;cnt<16;cnt++) {
+               for(row=0;row<8;row++) {
+                       if((font[cnt>>1]>>row)&1) {
+                               c[cnt]&=~(1<<row);
+                               c[cnt+1]&=~(1<<row);
+                               c[cnt]|=(((fill>>1)&1)<<row);
+                               c[cnt+1]|=((fill&1)<<row);
+                       }
+               }
+               DISPLAY_DATA=c[cnt++];
+               DISPLAY_DATA=c[cnt];
+       }
+}
+
+void display_draw_font(u8 x,u8 y,u8 *font,u8 fill,u8 alpha) {
+
+       u8 page,col,row,rmax,cnt,left,cf,rf;
+       u8 d[2];
+       int ca,cb;
+       u8 a,b,c;                       // c = a over b
+
+       left=8;
+
+       a=fill&0x03;
+       ca=0;
+       for(cnt=0;cnt<a;cnt++)          // contribution of a: alpha*a
+               ca+=alpha;
+
+       for(page=(y>>3);page<=((y+8)>>3);page++) {      // page = y/8
+               DISPLAY_SET_PAGE_ADDR(page);
+               rmax=(page+1)<<3;                       // row max
+               if(rmax>y+left)
+                       rmax=y+left;
+               cf=0;
+               for(col=x;col<x+8;col++) {
+                       DISPLAY_SET_COL_ADDR(col);
+                       d[0]=DISPLAY_DATA;              // dummy read (p.16)
+                       d[0]=DISPLAY_DATA;
+                       d[1]=DISPLAY_DATA;
+                       rf=0;
+                       for(row=y;row<rmax;row++) {
+                               // contribution of b: (255-alpha)*b
+                               b=display_m2i(d,row);
+                               cb=0;
+                               for(cnt=0;cnt<b;cnt++)
+                                       cb+=(255-alpha);
+                               // finally there is c
+                               if((font[cf]>>row)&1) {
+                                       c=(ca+cb)>>8;
+                                       d[0]&=~(1<<row);
+                                       d[1]&=~(1<<row);
+                                       d[0]|=((c>>1)&1)<<row;
+                                       d[1]|=(c&1)<<row;
+                               }
+                               rf+=1;
+                       }
+                       DISPLAY_SET_COL_ADDR(col);
+                       DISPLAY_DATA=d[0];
+                       DISPLAY_DATA=d[1];
+                       cf+=1;
+               }
+               left-=(rmax-y);
+               y=rmax;
+       }
 }
 
 void display_bl_init(void) {
 
-       PINSEL0&=~(1<<9|(1<<8));
        IODIR0|=(1<<4);
+       IOSET0=(1<<4);  // off by default
 }
 
 void display_bl_toggle(void) {