crashtest-r0ket/lcd/decoder.c

110 lines
2.2 KiB
C
Raw Normal View History

2011-05-14 20:11:36 +00:00
#include <fonts.h>
#include <render.h>
#define MAXCHR (24*3)
static uint8_t buf[MAXCHR];
2011-05-14 20:32:10 +00:00
uint8_t * pk_decode(const uint8_t * data,int * len){
2011-05-14 20:11:36 +00:00
int length=*len; // Length of character bytestream
int height; // Height of character in bytes
2011-05-14 20:15:30 +00:00
int hoff; // bit position for non-integer heights
2011-05-14 20:11:36 +00:00
uint8_t * bufptr=buf; // Output buffer for decoded character
height=(font->u8Height-1)/8+1;
2011-05-14 20:15:30 +00:00
hoff=font->u8Height%8;
2011-05-14 20:11:36 +00:00
// Local function: Get next nibble.
int ctr=0; // offset for next nibble
int hilo=0; // 0= high nibble next, 1=low nibble next
char gnn(){ // Get next nibble
static int byte;
int val;
hilo=1-hilo;
if(hilo==1){
byte=data[ctr];
ctr++;
val=byte>>4;
}else{
val=byte&0x0f;
};
return val;
};
// Local function: Unpack "long run".
int upl(int off){ // unpack "long" run.
int retval;
while((retval=gnn())==0){
off++;
};
while(off-->0){
retval=retval<<4;
retval+=gnn();
};
return retval;
};
#define DNY (12) // Decoder parameter: Fixed value for now.
int repeat=0; // Decoder internal: repeat colum?
int curbit=0; // Decoder internal: current bit (1 or 0)
int pos=0; // Decoder internal: current bit position (0..7)
int nyb; // Decoder internal: current nibble / value
while(ctr<length){ /* Iterate the whole input stream */
/* Get next encoded nibble and decode */
nyb=gnn();
if(nyb==15){
repeat++;
continue;
}else if(nyb==14){
nyb=upl(0);
nyb+=1;
repeat+=nyb;
continue;
}else if(nyb>DNY){
nyb=(16*(nyb-DNY-1))+gnn()+DNY+1;
}else if(nyb==0){
nyb=upl(1);
nyb+=(16*(13-DNY)+DNY)-16;
};
/* Generate & output bits */
while(nyb-->0){
2011-05-14 20:15:30 +00:00
if(pos==0){
*bufptr=0;
};
2011-05-14 20:11:36 +00:00
if(curbit==1){
*bufptr|=1<<(7-pos);
};
pos++;
2011-05-14 20:15:30 +00:00
if(((bufptr-buf)%height)==(height-1) && (pos==hoff)){
// Finish incomplete last byte per column
pos=8;
};
2011-05-14 20:11:36 +00:00
if(pos==8){
bufptr++;
if((bufptr-buf)%height==0){ // End of column?
while(repeat>0){
for(int y=0;y<height;y++){
bufptr[0]=bufptr[-3];
bufptr++;
};
repeat--;
};
};
pos=0;
};
};
curbit=1-curbit;
};
*len=(bufptr-buf)/height; // return size of output buffer.
return buf;
};