View Single Post
Old 05-10-2012, 02:43 AM   #50
kiri87
Member
kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.kiri87 knows what's going on.
 
Posts: 16
Karma: 25544
Join Date: Feb 2012
Device: Kindle 3
Here's a little demo using the code from the first post. I'm not sure if it's the right place for it, but the demo is too small to deserve it's own thread.
You really must see this running, the screens don't do justice.
Spoiler:

Code:
//====================================================
// colorOverflow 1.0 - a kindle demo 
// Copyright (C) 2012 by geekmaster, with MIT license:
// Copyright (C) 2012 by kiri, with MIT license:
// http://www.opensource.org/licenses/mit-license.php
//----------------------------------------------------
// This was tested on K3.
//----------------------------------------------------

#include <stdio.h>      // printf
#include <stdlib.h>    // malloc, free, atoi
#include <string.h>   // memset, memcpy
#include <unistd.h>  // usleep
#include <fcntl.h>  // open, close, write
#include <time.h>  // time
#include <math.h> // sin, cos
#include <sys/ioctl.h>   // ioctl
#include <sys/time.h>   // gettime
#include <sys/mman.h>  // mmap, munmap
typedef unsigned char u8;
unsigned int __invalid_size_argument_for_IOC;
#include <linux/fb.h> // screeninfo
#include <linux/einkfb.h>
#include <linux/mxcfb.h>

#define WIDTH 600
#define HEIGHT 800
#define NUM 8
#define RAD 111

typedef struct {
    float posx, posy, velx, vely;
} blob;

enum GMLIB_op { GMLIB_INIT,GMLIB_CLOSE,GMLIB_UPDATE };

// function prototypes
int gmlib(int);
inline void setpx(int,int,int);
inline int getpx(int,int);
void dblit(void);
int getmsec(void);
void updateBlob(blob *);

// gmlib global vars
static __u8 dt[64]= {
    3,129,34,160,10,136,42,168,192,66,223,97,200,73,231,105,50,
    176,18,144,58,184,26,152,239,113,207,81,247,121,215,89,14,
    140,46,180,7,133,38,164,203,77,235,109,196,70,227,101,62,188,
    30,156,54,180,22,148,251,125,219,93,243,117,211,85
}; // 0-255 dither table
__u8 *psave=NULL;     // screensave pointer
__u8 *fb0=NULL;      // framebuffer pointer
__u8 *wb0=NULL;     // workbuffer pointer
__u32 mpu=100;     // msec/update
int fdFB=0;       // fb0 file descriptor
int fdWB=0;      // wb0 file descriptor
__u32 fs=0;     // fb0 stride
__u32 fb=0;    // fb0 bytes
__u32 MX=0;   // xres (visible)
__u32 MY=0;  // yres (visible)
__u8 ppb=0; // pixels per byte
int bs=340; // border size
__u8 gs=0; // 8-bit grayscale
__u32 teu=0; // eink update time
__u32 tpu=0; // physics update time

void colorOverflow(void) {
    //system("eips -c"); //clear screen
    srand ( time(NULL) );

    int i, j, n, x, y;
    blob blobs[NUM];

    for (i=0; i<NUM; i++) {
        //populate the array
        blob b = {rand()%WIDTH, rand()%HEIGHT, 10+rand()%10, 10+rand()%10};
        blobs[i] = b;
    }
    printf("blobs populated\n");

    //clear 
    for (i=0;i<WIDTH;i++)
    	for (j=0;j<HEIGHT;j++)
    		setpx(i,j,0);

    int radsq = RAD*RAD, dx, dy, dist;

    for (;;) {
        for (n=0; n<NUM; n++) {
            //draw the blobs
            updateBlob(&blobs[n]);
            x = blobs[n].posx;
            y = blobs[n].posy;

            for (j = y-RAD; j <= y; j++) {
                for (i = x-RAD; i <= x; i++) {
                    dx=x-i;
                    dy=y-j;
                    dist = (dx*dx+dy*dy);
                    if (dist<=radsq) {
                        float q = (float)dist/radsq;
                        int c = 10*q;
                        setpx(i,j,c+getpx(i,j));
                        setpx(2*x-i,j,c+getpx(2*x-i,j));
                        setpx(i,2*y-j,c+getpx(i,2*y-j));
                        setpx(2*x-i,2*y-j,c+getpx(2*x-i,2*y-j));
                    }
                }
            }
        }
        gmlib(GMLIB_UPDATE);
    }
}

void updateBlob(blob *b) {
    if (b->posx + b->velx >= WIDTH || b->posx + b->velx < 0)
        b->velx *= -1;

    if (b->posy + b->vely >= HEIGHT || b->posy + b->vely < 0)
        b->vely *= -1;

    b->posx += b->velx;
    b->posy += b->vely;
}

//====================================
// gmlib - geekmaster function library
// op (init, update, close)
//------------------------------------
int gmlib(int op) {
    static struct update_area_t ua= {0,0,600,800,fx_invert,NULL};
    static struct mxcfb_update_data ur= {
        {0,0,600,800},WAVEFORM_MODE_AUTO,0,1,TEMP_USE_AMBIENT,0
    };
    static int eupcode;
    static void *eupdata=NULL;
    struct fb_var_screeninfo screeninfo;
    if (GMLIB_INIT==op) {
        teu=getmsec();
        // save original screen
        fdFB=open("/dev/fb0",O_RDWR); // open eink framebuffer fb0
        ioctl(fdFB,FBIOGET_VSCREENINFO,&screeninfo);
        ppb=8/screeninfo.bits_per_pixel;  // pixels per byte
        fs=screeninfo.xres_virtual/ppb;  // fb0 stride
        fb=screeninfo.yres_virtual/ppb; // fb0 bytes
        MX=screeninfo.xres;            // max X+1
        MY=screeninfo.yres;           // max Y+1
        ua.x2=MX;
        ua.y2=MY;
        ur.update_region.width=MX;
        ur.update_region.height=MY;
        fdWB=open("/tmp/wb0",O_RDWR|O_CREAT); // open work framebuffer wb0
        lseek(fdWB,MY*MX-1,SEEK_SET);
        write(fdWB,"",1); // create work buffer file
        fb0=(__u8 *)mmap(0,MY*fs,PROT_READ|PROT_WRITE,MAP_SHARED,fdFB,0); // map fb0
        wb0=(__u8 *)mmap(0,MY*MX,PROT_READ|PROT_WRITE,MAP_SHARED,fdWB,0); // map wb0
        if (fb>MY) {
            eupcode=MXCFB_SEND_UPDATE;
            eupdata=&ur;
            ur.update_mode=0;
        } else {
            eupcode=FBIO_EINK_UPDATE_DISPLAY_AREA;
            eupdata=&ua;
        }
        psave=malloc(fs*MY);
        memcpy(psave,fb0,fs*MY);
        memset(wb0,0,MY*MX);
        gmlib(GMLIB_UPDATE);
        teu+=300;
        memset(wb0,255,MY*MX);
        gmlib(GMLIB_UPDATE);
        teu+=80;
    } else if (GMLIB_UPDATE==op) {
        while (teu>getmsec()); // async update needs time
        dblit();
        ioctl(fdFB,eupcode,eupdata);
    } else if (GMLIB_CLOSE==op) {
        gmlib(GMLIB_UPDATE); //sleep(3); does it really need to sleep?
        memcpy(fb0,psave,fs*MY); // restore display
        free(psave);
        gmlib(GMLIB_UPDATE);   // update display
        munmap(wb0,MY*MX);    // unmap wb0
        close(fdWB);         // close wb0
        remove("/tmp/wb0"); // remove wb0
        munmap(fb0,MY*fs); // unmap fb0
        close(fdFB);      // close fb0
    } else {
        return -1;
    }
    return 0;
}

//========================================
// setpx - draw pixel to 8-bit work buffer
// x,y:screen coordinates, c:color(0-255).
//----------------------------------------
inline void setpx(int x,int y,int c) {
    if (x>=WIDTH || x<0 || y>=HEIGHT || y<0)
        return;
    wb0[y*MX+x]=c;
}

//========================================
// getpx - returns the value of a pixel 
// from the 8-bit work buffer
// x,y:screen coordinates, returns:color(0-255).
//----------------------------------------
inline int getpx(int x,int y) {
	//all offscreen pixels are returned as white
    if (x>=WIDTH || x<0 || y>=HEIGHT || y<0) return 255;
    return wb0[y*MX+x];
}

//==========================
// dblit - dither wb0 to fb0
//--------------------------
void dblit(void) {
    int x,y,ys;
    __u8 p,d,*pi,*po,*pd;
    pi=wb0-1;
    po=fb0-1;
    if (gs) { // 16-color dither
        if (ppb/2) { // 2 px/byte
            for (y=0; y<MY; y++) {
                pd=dt+(y&7)*8+7;
                for (x=0; x<MX; x+=8) {
                    pd-=8;
                    p=*pi++;
                    d=*pd++;
                    *po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
                          ((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
                    p=*pi++;
                    d=*pd++;
                    *po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
                          ((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
                    p=*pi++;
                    d=*pd++;
                    *po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
                          ((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
                    p=*pi++;
                    d=*pd++;
                    *po++=((p&240)+(d-(*pi&15)*255/15>>4&16)-16)&240|
                          ((*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16)/16&15;
                }
            }
        } else { // 1 px/byte
            for (y=0; y<MY; y++) {
                pd=dt+(y&7)*8+7;
                for (x=0; x<MX; x+=8) {
                    pd-=8;
//                *po++=(*pi++&240)+(*pd++-(*pi&15)*255/15>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                    *po++=(*pi++&240)+(((*pi&15)*4080>>8)+*pd++>>4&16)-16;
                }
                po+=(fs-MX);
            }
        }
    } else { // 2-color dither
        if (ppb/2) { // 2 px/byte *** broken (high contrast) ***
            for (y=0; y<MY; y++) {
                pd=dt+(y&7)*8+7;
                ys=(y&7)*8;
                for (x=0; x<MX; x+=8) {
                    pd-=8;
                    p=*pi++;
                    d=*pd++;
                    *po++=d-p>>4&240|*pd++-*pi++>>8&15;
                    p=*pi++;
                    d=*pd++;
                    *po++=d-p>>4&240|*pd++-*pi++>>8&15;
                    p=*pi++;
                    d=*pd++;
                    *po++=d-p>>4&240|*pd++-*pi++>>8&15;
                    p=*pi++;
                    d=*pd++;
                    *po++=d-p>>4&240|*pd++-*pi++>>8&15;
                }
            }

        } else { // 1 px/byte
            for (y=0; y<MY; y++) {
                pd=dt+(y&7)*8+7;
                for (x=0; x<MX; x+=8) {
                    pd-=8;
                    *po++=*pd++-*pi++>>8;
                    *po++=*pd++-*pi++>>8;
                    *po++=*pd++-*pi++>>8;
                    *po++=*pd++-*pi++>>8;
                    *po++=*pd++-*pi++>>8;
                    *po++=*pd++-*pi++>>8;
                    *po++=*pd++-*pi++>>8;
                    *po++=*pd++-*pi++>>8;
                }
                po+=(fs-MX);
            }
        }
    }
}

//====================================
// getmsec - get msec since first call
// (tick counter wraps every 12 days)
//------------------------------------
int getmsec(void) {
    int tc;
    static int ts=0;
    struct timeval tv;
    gettimeofday(&tv,NULL);
    tc=tv.tv_usec/1000+1000*(0xFFFFF&tv.tv_sec);
    if (0==tc) {
        ts=tc;
    }
    return tc-ts;
}

//==================
// main - start here
//------------------
int main(void) {
    gmlib(GMLIB_INIT);
    gs=0; // 0 for binary dither, 1 for grayscale dither
    colorOverflow();
    gmlib(GMLIB_CLOSE);

    return 0;
}
Attached Thumbnails
Click image for larger version

Name:	screen_shot-8835.gif
Views:	263
Size:	43.3 KB
ID:	86281   Click image for larger version

Name:	screen_shot-8833.gif
Views:	237
Size:	52.6 KB
ID:	86282  
Attached Files
File Type: zip colorOverflow.zip (10.5 KB, 172 views)

Last edited by kiri87; 05-10-2012 at 02:45 AM.
kiri87 is offline   Reply With Quote