//PIC8 code for ILI9341 and XPT2046 modules

#include <xc.h>
#include "backpack.h"
#include <string.h>

unsigned int backpackwidth,backpackheight,backpackrotation;
const unsigned int decPlaces[5]={10000,1000,100,10,1};
unsigned int hBuf[HLINE_BUFSIZE];

void getDigits(unsigned int n,unsigned char* d){
    unsigned char p=0;
    d[0]=0;
    d[1]=0;
    d[2]=0;
    d[3]=0;
    d[4]=0;
    while(n && (p<5)){
        if(n<decPlaces[p]){
            p=p+1;
        }else{
            d[p]=d[p]+1;
            n=n-decPlaces[p];
        }
    }
}

void backpackinit(void){
//used for LCD touch panel:
//5     RC5 LEDCON
//8     RC6 LCD_CS
//9     RC7 MOSI (HW)
//10    RB7 LCD_DC
//11    RB6 SCK (HW)
//12    RB5 TOUCH_CS
//13    RB4 MISO (HW)
//17    RA2 LCD_RST

//backlight PWM
    //backpackBacklightInit();
//backlight on
    anselbits.BACKPACK_BACKLIGHT=0;
    trisbits.BACKPACK_BACKLIGHT=0;
    latbits.BACKPACK_BACKLIGHT=1;        
//LCD controller    
    anselbits.BACKPACK_CS=0;
    anselbits.BACKPACK_DC=0;
    anselbits.BACKPACK_RST=0;
    anselbits.BACKPACK_TOUCHCS=0;
    trisbits.BACKPACK_CS=0;
    trisbits.BACKPACK_DC=0;
    trisbits.BACKPACK_RST=0;
    trisbits.BACKPACK_TOUCHCS=0;
    latbits.BACKPACK_CS=1;  //idle high
    latbits.BACKPACK_TOUCHCS=1; //idle high
    latbits.BACKPACK_DC=1;  //default high for data
    latbits.BACKPACK_RST=0; //keep in reset
    backpackSPIinit();
    delay(100);
    latbits.BACKPACK_RST=1;
    latbits.BACKPACK_DC=0;
    latbits.BACKPACK_CS=0;
    backpackcmd(0x01);           //soft reset
    delay(10);    
    backpackcmd(0xC0);           //power control
    backpackdata(0x23);
    backpackcmd(0xC1);
    backpackdata(0x10);
    backpackcmd(0xC5);           //VCOM control
    backpackdata(0x3e);
    backpackdata(0x28); 
    backpackcmd(0xC7);
    backpackdata(0x86);  
    backpackcmd(0x36);           //Memory Access Control 
    backpackdata(0x28);              //normal orientation=2
    backpackcmd(0x3A);           //Pixel format 0x55=16bpp, 0x66=18bpp
    backpackdata(0x55);              
    backpackcmd(0xB1);           //Frame Control 
    backpackdata(0x00);  
    backpackdata(0x18); 
    backpackcmd(0xB6);           //Display Function Control 
    backpackdata(0x08); 
    backpackdata(0x82);
    backpackdata(0x27);  
    backpackcmd(0x11);           //Sleep out
    delay(120); 
    backpackcmd(0x29);           //Display on
    delay(25);
    latbits.BACKPACK_CS=1;
    backpackwidth=320;
    backpackheight=240;
    backpackrotation=2;
    backpackareaset(0,0,backpackwidth-1,backpackheight-1);
}

void backpackSPIinit(void){
    anselbits.SPI_MOSI=0;
    anselbits.SPI_MISO=0;
    anselbits.SPI_SCK=0;
    trisbits.SPI_MOSI=0;
    trisbits.SPI_MISO=1;    //MISO stays input
    trisbits.SPI_SCK=0;
    wpubits.SPI_MISO=1;     //pullup for floating bus
    PPSLOCK = 0x55; //Required sequence
    PPSLOCK = 0xAA; //Required sequence
    PPSLOCKbits.PPSLOCKED = 0; //clear PPSLOCKED bit
    pps.SPI_MOSI=0x1c;       //MOSI1 output
    SSP1DATPPS=SPI_MISO;     //MISO1 INPUT
    pps.SPI_SCK=0x1b;        //SCK1 output
    PPSLOCK = 0x55; //Required sequence
    PPSLOCK = 0xAA; //Required sequence
    PPSLOCKbits.PPSLOCKED = 1; //set PPSLOCKED bit   
    //SPI on MSSP1
    SSP1CON1bits.SSPEN=0;            //reset MSSP
    SSP1CON1bits.CKP=0;              //idle low
    SPI_BRG=LCD_BRG;
    SSP1STATbits.SMP=1;              //SPI mode
    SSP1STATbits.CKE=1;              //SPI mode
    SSP1CON1bits.WCOL=0;             //clear collision flag
    SSP1BUF;                         //dummy read
    SSP1IE=0;                        //no interrupts
    //SSP1ADD=12;                      //value that seems to work (6 works, so 12 should be safe)
    SSP1CON1bits.SSPEN=1;            //start MSSP    
}

void backpackdata(unsigned char d){
    SSP1BUF=d;           //send byte
    while(SSP1STATbits.BF==0){}      //wait for SPI
    SSP1BUF;      //dummy read
}


void backpackcmd(unsigned char d){
    latbits.BACKPACK_DC=0;
    backpackdata(d);
    latbits.BACKPACK_DC=1;  //default high for data    
}

unsigned int backpackSPI16(unsigned int n){ //for touch, with 16 bit return value
    unsigned int r=0;
    SSP1BUF=(n>>0)&0xFF;           //send byte
    while(SSP1STATbits.BF==0){}      //wait for SPI
    r=(unsigned int)(SSP1BUF<<0);
    SSP1BUF=(n>>8)&0xFF;           //send byte
    while(SSP1STATbits.BF==0){}      //wait for SPI
    r|=(unsigned int)(SSP1BUF<<8);
    return r;    
}

void backpackareaset(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2){
    if(x2<x1){unsigned int i=x1;x1=x2;x2=i;}   //sort x
    if(y2<y1){unsigned int i=y1;y1=y2;y2=i;}   //sort y
    latbits.BACKPACK_CS=0;
    backpackcmd(42);               //set x bounds  
    backpackdata((x1>>8)&0xFF);
    backpackdata(x1&0xFF);
    backpackdata((x2>>8)&0xFF);
    backpackdata(x2&0xFF);
    backpackcmd(43);               //set y bounds
    backpackdata((y1>>8)&0xFF);
    backpackdata(y1&0xFF);
    backpackdata((y2>>8)&0xFF);
    backpackdata(y2&0xFF);
    backpackcmd(44);               //drawing data to follow
    latbits.BACKPACK_CS=1;
}


void backpackbox(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2,unsigned int c){
    unsigned int x,y;
    if(x2<x1){unsigned int i=x1;x1=x2;x2=i;}
    if(y2<y1){unsigned int i=y1;y1=y2;y2=i;}
    backpackareaset(x1,y1,x2,y2);
    x2++;
    y2++;
    latbits.BACKPACK_CS=0;
    for(x=x1;x<x2;x++){
      for(y=y1;y<y2;y++){
        backpackdata(c>>8);
        backpackdata(c&0xFF);  
      }
    }
    latbits.BACKPACK_CS=1;
}

void backpackboxsize(unsigned int x1,unsigned int y1,unsigned int w,unsigned int h,unsigned int c){
    unsigned int x,y;
    backpackareaset(x1,y1,x1+w-1,y1+h-1);
    w++;
    h++;
    latbits.BACKPACK_CS=0;
    for(x=0;x<w;x++){
      for(y=0;y<h;y++){
        backpackdata(c>>8);
        backpackdata(c&0xFF);  
      }
    }
    latbits.BACKPACK_CS=1;
}

void backpackclear(unsigned int c){
  backpackbox(0,0,backpackwidth-1,backpackheight-1,c);
}

void backpackpoint(unsigned int x,unsigned int y, unsigned int c){
  backpackareaset(x,y,x,y);
  latbits.BACKPACK_CS=0;
  backpackdata(c>>8);
  backpackdata(c&0xFF);  
  latbits.BACKPACK_CS=1;
}

unsigned int backpackcharfonts(unsigned int x, unsigned int y, char c, unsigned int f, unsigned int b, const unsigned char* font,unsigned char s){
  unsigned int w,h,c0,c1,p0,xx,p;
  unsigned char d,e,u;
  w=font[0];
  h=font[1];
  c0=font[2];
  c1=font[3]+c0;
  if(c<c0){return 0;}   //out of range
  if(c>c1){return 0;}   //out of range
  p0=4+(w*h/8)*(c-c0);
  backpackareaset(x,y,x+w*s-1,y+h*s-1);    //set area
  latbits.BACKPACK_CS=0;
  p=0;
  xx=w;
  for(y=0;y<h;y++){
    for(xx=xx-w;xx<w;xx=xx+8){  //the -w allows for partial lines to be mapped correctly
        d=font[p0+p];
        if(d&128){hBuf[xx+0]=f;}else{hBuf[xx+0]=b;}
        if(d& 64){hBuf[xx+1]=f;}else{hBuf[xx+1]=b;}
        if(d& 32){hBuf[xx+2]=f;}else{hBuf[xx+2]=b;}
        if(d& 16){hBuf[xx+3]=f;}else{hBuf[xx+3]=b;}
        if(d&  8){hBuf[xx+4]=f;}else{hBuf[xx+4]=b;}
        if(d&  4){hBuf[xx+5]=f;}else{hBuf[xx+5]=b;}
        if(d&  2){hBuf[xx+6]=f;}else{hBuf[xx+6]=b;}
        if(d&  1){hBuf[xx+7]=f;}else{hBuf[xx+7]=b;}
        p=p+1;
    }
    for(e=0;e<s;e++){   //safe to reuse this variable
      for(u=0;u<w;u++){
        for(d=0;d<s;d++){       //and this one, for now
          backpackdata(hBuf[u]>>8);
          backpackdata(hBuf[u]&0xFF);            
        }
      }
    }
    hBuf[0]=hBuf[w];        //save any from beyond end of row
    hBuf[1]=hBuf[w+1];
    hBuf[2]=hBuf[w+2];
    hBuf[3]=hBuf[w+3];
    hBuf[4]=hBuf[w+4];
    hBuf[5]=hBuf[w+5];
    hBuf[6]=hBuf[w+6];
    hBuf[7]=hBuf[w+7];
  }
  latbits.BACKPACK_CS=1;
  return w*s;             //allows arrays to be printed in a row
}

unsigned int backpackcharfont2(unsigned int x, unsigned int y, char c, unsigned int f, unsigned int b, const unsigned char* font){
  unsigned int w,h,c0,c1,p0,xx,p;
  unsigned char d,e,u;
  w=font[0];
  h=font[1];
  c0=font[2];
  c1=font[3]+c0;
  if(c<c0){return 0;}   //out of range
  if(c>c1){return 0;}   //out of range
  p0=4+(w*h/8)*(c-c0);
  backpackareaset(x,y,x+w*2-1,y+h*2-1);    //set area
  latbits.BACKPACK_CS=0;
  p=0;
  xx=w;
  for(y=0;y<h;y++){
    for(xx=xx-w;xx<w;xx=xx+8){  //the -w allows for partial lines to be mapped correctly
        d=font[p0+p];
        if(d&128){hBuf[xx+0]=f;}else{hBuf[xx+0]=b;}
        if(d& 64){hBuf[xx+1]=f;}else{hBuf[xx+1]=b;}
        if(d& 32){hBuf[xx+2]=f;}else{hBuf[xx+2]=b;}
        if(d& 16){hBuf[xx+3]=f;}else{hBuf[xx+3]=b;}
        if(d&  8){hBuf[xx+4]=f;}else{hBuf[xx+4]=b;}
        if(d&  4){hBuf[xx+5]=f;}else{hBuf[xx+5]=b;}
        if(d&  2){hBuf[xx+6]=f;}else{hBuf[xx+6]=b;}
        if(d&  1){hBuf[xx+7]=f;}else{hBuf[xx+7]=b;}
        p=p+1;
    }
    for(e=0;e<2;e++){   //safe to reuse this variable
      for(u=0;u<w;u++){
        backpackdata(hBuf[u]>>8);
        backpackdata(hBuf[u]&0xFF);            
        backpackdata(hBuf[u]>>8);
        backpackdata(hBuf[u]&0xFF);            
      }
    }
    hBuf[0]=hBuf[w];        //save any from beyond end of row
    hBuf[1]=hBuf[w+1];
    hBuf[2]=hBuf[w+2];
    hBuf[3]=hBuf[w+3];
    hBuf[4]=hBuf[w+4];
    hBuf[5]=hBuf[w+5];
    hBuf[6]=hBuf[w+6];
    hBuf[7]=hBuf[w+7];
  }
  latbits.BACKPACK_CS=1;
  return w*2;             //allows arrays to be printed in a row
}

unsigned int backpackcharfont(unsigned int x, unsigned int y, char c, unsigned int f, unsigned int b, const unsigned char* font){
  unsigned int w,h,c0,c1,p0,xx,yy,p;
  unsigned char d;
  w=font[0];
  h=font[1];
  c0=font[2];
  c1=font[3]+c0;
  if(c<c0){return 0;}   //out of range
  if(c>c1){return 0;}   //out of range
  p0=4+(w*h/8)*(c-c0);
  backpackareaset(x,y,x+w-1,y+h-1);    //set area
  latbits.BACKPACK_CS=0;
  p=0;
  for(y=0;y<(w*h/8);y++){
    d=font[p0+p];
    if(d&128){hBuf[0]=f;}else{hBuf[0]=b;}
    if(d& 64){hBuf[1]=f;}else{hBuf[1]=b;}
    if(d& 32){hBuf[2]=f;}else{hBuf[2]=b;}
    if(d& 16){hBuf[3]=f;}else{hBuf[3]=b;}
    if(d&  8){hBuf[4]=f;}else{hBuf[4]=b;}
    if(d&  4){hBuf[5]=f;}else{hBuf[5]=b;}
    if(d&  2){hBuf[6]=f;}else{hBuf[6]=b;}
    if(d&  1){hBuf[7]=f;}else{hBuf[7]=b;}
    p=p+1;
    for(xx=0;xx<8;xx++){
        backpackdata(hBuf[xx]>>8);
        backpackdata(hBuf[xx]&0xFF);            
    }
  }
  latbits.BACKPACK_CS=1;
  return w;             //allows arrays to be printed in a row
}

void backpackchararrayfont(unsigned int x0, unsigned int y0, const char *c, unsigned int f, unsigned int b, const unsigned char* font){
  while(*c){
    x0=x0+backpackcharfont(x0,y0,*c++,f,b,font);
    if(x0>backpackwidth){x0=0;}      //wrap around (will probably look ugly)
  }  
}

void backpackchararrayfont2(unsigned int x0, unsigned int y0, const char *c, unsigned int f, unsigned int b, const unsigned char* font){
  while(*c){
    x0=x0+backpackcharfont2(x0,y0,*c++,f,b,font);
    if(x0>backpackwidth){x0=0;}      //wrap around (will probably look ugly)
  }  
}

unsigned int backpacktouchxraw(void){
  unsigned long n=0;
  int k;
  SPI_BRG=TOUCH_BRG;
  latbits.BACKPACK_TOUCHCS=0;
  backpackdata(0x91);
  n=backpackSPI16(0x91);   //ignore first
  for(k=0;k<TOUCH_OVERSAMPLE-1;k++){
    n=n+backpackSPI16(0x91);
  }
  n=n+backpackSPI16(0x90);   //and one more
  latbits.BACKPACK_TOUCHCS=1;
  SPI_BRG=LCD_BRG;
  return (unsigned int)((n/TOUCH_OVERSAMPLE)>>4);      //only 12 bits resolution
}

unsigned int backpacktouchyraw(void){
  unsigned long n=0;
  int k;
  SPI_BRG=TOUCH_BRG;
  latbits.BACKPACK_TOUCHCS=0;
  backpackdata(0xD1);
  n=backpackSPI16(0xD1);   //ignore first
  for(k=0;k<TOUCH_OVERSAMPLE-1;k++){
    n=n+backpackSPI16(0xD1);
  }
  n=n+backpackSPI16(0xD0);   //and one more
  latbits.BACKPACK_TOUCHCS=1;
  SPI_BRG=LCD_BRG;
  return (unsigned int)((n/TOUCH_OVERSAMPLE)>>4);      //only 12 bits resolution
}

unsigned int backpacktouchzraw(void){
  unsigned int n;
  SPI_BRG=TOUCH_BRG;
  latbits.BACKPACK_TOUCHCS=0;
  backpackdata(0xB1);
  n=backpackSPI16(0xB1);   //ignore first
  n=backpackSPI16(0xB1);
  n=backpackSPI16(0xB0);
  latbits.BACKPACK_TOUCHCS=1;
  SPI_BRG=LCD_BRG;
  return n>>4;      //only 12 bits resolution
}

int backpacktouchx(void){      //correct for rotate=2
   long u;
   if(backpacktouchzraw()<Z_TOUCH_THRESHOLD){return -1;} //no touch    
   u=backpacktouchxraw();
   if(backpacktouchzraw()<Z_TOUCH_THRESHOLD){return -1;} //touch lifted
   return (TOUCH_A*u+TOUCH_C)>>16;
}

int backpacktouchy(){      //correct for rotate=2
   long v;
   if(backpacktouchzraw()<Z_TOUCH_THRESHOLD){return -1;} //no touch    
   v=backpacktouchyraw();
   if(backpacktouchzraw()<Z_TOUCH_THRESHOLD){return -1;} //touch lifted
   return (TOUCH_E*v+TOUCH_F)>>16;    
}

void backpackhline(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int c){
  unsigned int x;
  if(x2<x1){unsigned int i=x1;x1=x2;x2=i;}
  backpackareaset(x1,y1,x2,y1);
  x2++;
  latbits.BACKPACK_CS=0;
  for(x=x1;x<x2;x++){
    backpackdata(c>>8);
    backpackdata(c&0xFF);  
  }
  latbits.BACKPACK_CS=1;
}


void backpackvline(unsigned int x1,unsigned int y1,unsigned int y2,unsigned int c){
  unsigned int y;
  if(y2<y1){unsigned int i=y1;y1=y2;y2=i;}
  backpackareaset(x1,y1,x1,y2);
  y2++;
  latbits.BACKPACK_CS=0;
  for(y=y1;y<y2;y++){
    backpackdata(c>>8);
    backpackdata(c&0xFF);  
  }
  latbits.BACKPACK_CS=1;
}


void backpacktextbutton(unsigned int x1,unsigned int y1,unsigned int w,unsigned int h, const char *c,unsigned int f,unsigned int b,const unsigned char* font){  
    unsigned int tw,th;
    tw=font[0]*strlen(c);    
    th=font[1];
    backpackbox(x1+1,y1+1,x1+w-1,y1+h-1,b);       //background fill
    backpackhline(x1,y1,x1+w,f);      //top line
    backpackhline(x1,y1+h,x1+w,f);      //bottom line
    backpackvline(x1,y1,y1+h,f);      //left line
    backpackvline(x1+w,y1,y1+h,f);      //right line    
    backpackchararrayfont((x1+x1+w-tw)/2,(y1+y1+h-th)/2,c,f,b,font);
}

void backpacksetbuttonobject(struct backpackbutton *b,unsigned int x0,unsigned int y0,unsigned int x1,unsigned int y1, const char *text){
    b->x0=x0;
    b->y0=y0;
    b->w=x1;
    b->h=y1;
    b->text=text;  
    b->p=0;
    b->pp=1;    //different to force draw
}

void backpackbuttonrefresh(struct backpackbutton *b){
    b->p=0;
    b->pp=1;    //different to force draw
}

char backpackbuttonobjecttouched(struct backpackbutton *b){
    int x;
    x=backpacktouchx();
    if(x<b->x0){return 0;}
    if(x>(b->x0+b->w)){return 0;}
    x=backpacktouchy();
    if(x<b->y0){return 0;}
    if(x>(b->y0+b->h)){return 0;}
    return 1;
}

char backpackbuttonobjecttouchedinv(struct backpackbutton *b){  //check for reverse
    int x;
    x=(int)backpackwidth-backpacktouchx();
    if(x<b->x0){return 0;}
    if(x>(b->x0+b->w)){return 0;}
    x=(int)backpackheight-backpacktouchy();
    if(x<b->y0){return 0;}
    if(x>(b->y0+b->h)){return 0;}
    return 1;
}

void backpackdrawbuttonobject(struct backpackbutton *b, unsigned int f,unsigned int bg,const unsigned char* font){
    if(b->pp!=b->p){
        if(b->p){    //draw reversed
            backpacktextbutton(b->x0,b->y0,b->w,b->h,b->text,bg,f,font); 
        }else{          //draw normal
            backpacktextbutton(b->x0,b->y0,b->w,b->h,b->text,f,bg,font);         
        }
        b->pp=b->p;
    }
}

void backpackbuttonupdate(struct backpackbutton *b){
    if(backpackbuttonobjecttouched(b) || backpackbuttonobjecttouchedinv(b)){
        b->p=1;
    }else{
        b->p=0;
    }
}

char backpackbuttowndownevent(struct backpackbutton *b){
    if(b->p){if(!(b->pp)){return 1;}}
    return 0;
}

void backpackBacklightInit(void){
    anselbits.BACKPACK_BACKLIGHT=0;
    trisbits.BACKPACK_BACKLIGHT=0;
    latbits.BACKPACK_BACKLIGHT=0;    
    //PWM1S1
    PWM1CON=0;          //reset
    PWM1ERS=0;
    PWM1CLK=2;          //FOSC (FOSC/4 not available)
    PWM1LDS=0;
    PWM1PR=100;          //100 maps to %
    PWM1CPRE=8;         //prescale
    PWM1S1CFG=0;        //left aligned, normal polarity
    PWM1S1P1=0;          //0% duty
    PWM1GIE=0;          //no ints    
    PWM1CONbits.LD=1;   //load
    PWM1CONbits.EN=1;   //run    
    PPSLOCK = 0x55; //Required sequence
    PPSLOCK = 0xAA; //Required sequence
    PPSLOCKbits.PPSLOCKED = 0; //clear PPSLOCKED bit
    pps.BACKPACK_BACKLIGHT=0x0B;       //PWM1S1P1_OUT
    PPSLOCK = 0x55; //Required sequence
    PPSLOCK = 0xAA; //Required sequence
    PPSLOCKbits.PPSLOCKED = 1; //set PPSLOCKED bit   
}

void backpackBacklight(char n){      //set backlight in %
    PWM1S1P1=n;        //% duty
    PWM1CONbits.LD=1;   //load    
}

void drawbitmapmono(unsigned int x0, unsigned int y0,const unsigned char* bm,unsigned int f,unsigned int b){   //draw mono bitmap with colours f and b
    unsigned char w,h,x,d;      //assume <256, number of pixels must be mult of 8
    unsigned int p,n;
    w=bm[0];
    h=bm[1];
    backpackareaset(x0,y0,x0+w-1,y0+h-1);    //set area
    latbits.BACKPACK_CS=0;
    n=((unsigned int)(w)*(unsigned int)(h))/8+2;
    for(p=2;p<n;p++){
        d=bm[p];
        if(d&128){hBuf[0]=f;}else{hBuf[0]=b;}
        if(d& 64){hBuf[1]=f;}else{hBuf[1]=b;}
        if(d& 32){hBuf[2]=f;}else{hBuf[2]=b;}
        if(d& 16){hBuf[3]=f;}else{hBuf[3]=b;}
        if(d&  8){hBuf[4]=f;}else{hBuf[4]=b;}
        if(d&  4){hBuf[5]=f;}else{hBuf[5]=b;}
        if(d&  2){hBuf[6]=f;}else{hBuf[6]=b;}
        if(d&  1){hBuf[7]=f;}else{hBuf[7]=b;}
        for(x=0;x<8;x++){
            backpackdata(hBuf[x]>>8);
            backpackdata(hBuf[x]&0xFF);            
        }
    }
    latbits.BACKPACK_CS=1;    //done
}

void drawbitmapmonoRLE(unsigned int x0, unsigned int y0,const unsigned char* bm,unsigned int f,unsigned int b){    //draw RLE mono bitmap with colours f and b
//format is w,h,LSB of RLE data size, MSB of RLE data size
    unsigned char w,h,d,i;
    unsigned int size,j,col;
    w=bm[0];
    h=bm[1];
    //size=bm[2]+(bm[3]<<8)+4;
    size=(*((unsigned int*)&bm[2]))+4;  //assumes little-endian
    backpackareaset(x0,y0,x0+w-1,y0+h-1);    //set area
    latbits.BACKPACK_CS=0;
    for(j=4;j<size;j++){
        d=bm[j];
      if(d&128){
          d=d&127;
          col=f;
      }else{
          col=b;
      }
      for(i=0;i<d;i++){
        backpackdata(col>>8);
        backpackdata(col&0xFF);                      
      }
    }
    latbits.BACKPACK_CS=1;    //done
}

unsigned int backpackcharfontRLE(unsigned int x, unsigned int y, char c, unsigned int f, unsigned int b, const unsigned char* font){
  unsigned int w,h,p,col;
  unsigned char c0,c1,d,s,xx;
  w=font[0];
  h=font[1];
  c0=font[2];
  c1=font[3]+c0;
  if(c<c0){return 0;}   //out of range
  if(c>c1){return 0;}   //out of range
  c=c-c0;
  p=4;      //past header
  while(c){ //scan to required character
      s=font[p];
      p=p+s+1;
      c--;
  }
  s=font[p++];
  backpackareaset(x,y,x+w-1,y+h-1);    //set area
  latbits.BACKPACK_CS=0;
  while(s--){
      d=font[p++];
      if(d&128){
          d=d&127;
          col=f;
      }else{
          col=b;
      }
      for(xx=0;xx<d;xx++){
        backpackdata(col>>8);
        backpackdata(col&0xFF);                      
      }
  }
  latbits.BACKPACK_CS=1;
  return w;             //allows arrays to be printed in a row
}

void drawbitmapmonoRLE4(unsigned int x0, unsigned int y0,const unsigned char* bm,unsigned int f,unsigned int b){    //draw RLE4 mono bitmap with colours f and b
//format is w,h, data is null terminated so no need to encode
    unsigned char w,h,d,i;
    unsigned int j;
    w=bm[0];
    h=bm[1];
    backpackareaset(x0,y0,x0+w-1,y0+h-1);    //set area
    latbits.BACKPACK_CS=0;
    d=2;
    j=2;
    while(d){
        d=bm[j];
        j++;
        for(i=(d>>4);i>0;i--){
            backpackdata(b>>8);
            backpackdata(b&0xFF);                      
        }
        for(i=(d&0xF);i>0;i--){
            backpackdata(f>>8);
            backpackdata(f&0xFF);                      
        }
    }
    latbits.BACKPACK_CS=1;    //done
}
