#include <16f877.h>
#include <stdlib.h>

// for bootloader::

#ORG 0x1F00,0x1FFF {}//for the 8k 16F876/7

#fuses XT, NOWDT, NOPROTECT, PUT, NOLVP, NOCPD, WRT, BROWNOUT //irrelevant with bootloader
#use delay(clock=4000000)
#zero_ram
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) 

#define bit short
#define uint8 char
#define uint16 long

#define TX_PAGE 251
#define RX_PAGE 223

#define RX_PIN pin_B0
#define TX_PIN pin_C1

#define INST_TOT 34
#define MAX_LEN 128
#define MAX_CELLS 400
#define VM_OFFSET 3200
#define MEMSZ 26000
#define TOTSZ MEMSZ+VM_OFFSET
#define INITLIVELY 1000
//#define SLPVAL 614 // 3.0 v value 0-03ff = 0->1024 against 5v // ??? > to change 
#define SLPVAL 39203 // is use 0->ffc0 which is 16 bit return value max for 10 bit device

//unsigned char MEM[255][128];

// RF

#define BUFFER_SIZE 128

bit transmitting_data=0;	// in tx mode if high
bit transmitted_data=0;	// tx mode completed if high
bit receiving_data=0;		// in rx mode if high
bit received_data=0;		// we have received data
bit receive_error=0;		// There is a problem with the byte received
bit receive_buffer_error=0;	// we had a rx buffer overrun
uint16 rx_data,tx_data=0;		// holds the data being received or transmitted
uint8 rx_counter,tx_counter=0;	//counts the # of bits sent or received
uint8 start_bit_counter=0;	// valid start bit counter
bit blip=1;				// high/low thing for start header
bit togg=0;
bit send_start_bit=0;		// whether we are tx'ing the start 'bit'
bit send_stop_bit=0;		// yadda yadda yadda yadda  stop 'bit'
bit send_junk_stuff=0;
uint8 junkcounter=0;
uint8 stop_bit_counter=0;		// number of stop bits tx'd
// uint8 rxtx_buffer[BUFFER_SIZE];	// a buffer to hold the RX data - hold in nvram
uint8 rx_buf_counter,tx_buf_counter=0;		// current position in the buffer
bit first_byte=0;			// the first byte of rf data = TRUE
uint8 lcd_bytes[16];
int safexx;

// vm

int bitflip(int value);
void delete_cell(int16 index);
void mutate(void);
int nv_access(int16 wher);
void nv_set(int16 wher, int what);
void init_mem(void);
void gcollect(void);
void reparse(int16 offst, int16 ln, int sig);
void reparsebac(int16 offst, int16 ln, int sig, int index);
void add_new_cell(int length, int16 offs);
void retrieve_cell(int16 cur_off);
void putback_cell(int16 cur_off);
void do_function(int ins);
void insert_cell(int16 index,int length, int16 offs);
void do_lcd(void);
void init_lcd(void);
void pulse(void);
void maddress(int addr);
void orreset(void);
void sleeper(void);
void page_wr(int pag);
uint8 read_me(void);
//rf

uint16 man_encode(uint8 unenc);
uint8 man_decode(uint16 enc);
bit transmit_data(void);
bit receive_data(void);



int xx,len,lively, offsett;
int16 offset;
int16 cur_cell;
int inst;
int16 total_cells;
int16 vmcount;
int TXcounter,RXcounter,LCcounter;
int xp, mp, wp, rp; // registers


int main(void){
  int16 z,uther,ly;
  int x,y;

  TXcounter=RXcounter=LCcounter=vmcount=0;
  cur_cell=0;
  total_cells=0;
  uther=255;


  // other inits eg. trises
  set_tris_a(0b00100011); 
  set_tris_b(0b00000001); 
  set_tris_c(0b00000000); 
  set_tris_d(0b00000000);
  set_tris_e(0b00000000);

  //RA4 as digital  output and driven low
  
  setup_port_a( A_ANALOG );
  setup_adc(ADC_CLOCK_INTERNAL);
  output_low(PIN_A4);
  output_low(PIN_C1);
  init_lcd();
  
  disable_interrupts(GLOBAL);
      
    ext_int_edge(L_TO_H);
  // set up the RTCC and EXT_B0 interrupts
  setup_counters(RTCC_INTERNAL,RTCC_DIV_8);
  enable_interrupts(INT_RTCC);
  enable_interrupts(INT_EXT);

  enable_interrupts(GLOBAL);
  
  // check cell space on PIC - here just init
  //  if (nv_access(0)==0 && nv_access(VM_OFFSET)==0){

  //        printf("reset ");

  // sleep test 

  // if RA0 less than 3.0 v sleep

  

  set_adc_channel(0);
   delay_us(50);

// what is less than 3.0v + needs to be checked regularly

ly=read_adc();

if (ly<SLPVAL) sleeper();

 set_adc_channel(1);
   delay_us(50);
 srand(read_adc());
  
  init_mem();
  reparse(0, MEMSZ, 6);
    // }
  vmcount=0;


  //  set_adc_channel(1);
  // delay_us(50);

  while(1){


    if (nv_access((int16)cur_cell*8)>0){
      
      retrieve_cell((int16)cur_cell*8);
          printf("cell number %ld .. xp %u.. mp %u \r\n",cur_cell,xp,mp);
      if (xx<255){
	//      printf("main1:xx %u offsett %u\r\n",xx,offsett);
      offset=((int16)xx*128)+(int16)offsett;
      //      printf("offset %ld\r\n",offset);
      inst=nv_access(VM_OFFSET+(int16)offset+(int16)xp);

            do_function(inst%INST_TOT);
	    //      printf("main2:xx %u offsett %u\r\n",xx,offsett);

      //      if (uther==0){
      lively--;
      // uther=255;
      // }

      //uther--;
      //advance xp in buffer - against len, and end of mem  

      xp++;
      if (xp>len) xp=0;
      if ((int16)xp+(int16)offset>MEMSZ) xp=0;
      // copy back
      //      printf("main3:xx %u offsett %u\r\n",xx,offsett);
      putback_cell((int16)cur_cell*8);

      }
      else delete_cell(cur_cell);


    }
    
    else {
      if (total_cells>2){
	//		printf("deleting %u\r\n",cur_cell);
	delete_cell(cur_cell);
	//cur_cell=0;
	}
      // otherwise reset
      else {
	cur_cell=0;
	init_mem();
	reparse(0, MEMSZ, 6);
    }
    }

    // check voltage

    cur_cell++;
    if (cur_cell>=total_cells) {
cur_cell=0;
    if (vmcount>=1000){
      // gcollect whenever & mutate 
      //      printf("gcollect\r\n");
      gcollect();
      vmcount=0;
      }

    }



  set_adc_channel(0);
   delay_us(50);

    
ly=read_adc();

if (ly<SLPVAL) sleeper();
    

 if ((vmcount%100)==0)      { mutate();
 // printf("mutate");
 }
    vmcount++;
        
    //  ** take care of charging stuff

  }

}


void init_mem(void){
  int16 fx;

  set_adc_channel(1);
   delay_us(50);

   //      printf("init-mem");
   //possible clear structure memory first
  for (fx=0;fx<VM_OFFSET;fx++){
      //nvram access
    nv_set(fx,0);
  }

  for (fx=VM_OFFSET;fx<TOTSZ;fx++){
      //nvram access
    // nv_set(fx,rand()%255); // test


    	nv_set(fx,read_me());
	//nv_set(fx,read_adc());
    delay_us(50);
    //        printf("no: %ld CELLS:: %U\r\n",fx,nv_access(fx));
      
  }
  // reparse whole vm space


}

void reparse(int16 offst, int16 ln, int sig){


   int16 x=0,last=0,nlen=0,count=0;

           printf("reparse %ld %ld\r\n",offst,ln);
  for (x=0;x<ln;x++){
    //    printf("rep %ld  cell %u\r\n",VM_OFFSET+offst+x,nv_access(VM_OFFSET+offst+x));

    if (total_cells<MAX_CELLS){

        if ((nv_access(VM_OFFSET+offst+x)&31)==sig) { 



      nlen=x-last;  

      if (nlen > 1 && (nlen+last+offst+1)<MEMSZ) {
	//	printf(" add new cell\r\n");
	add_new_cell(nlen-1,last+offst+1);
	last=x;
	count++;
      }

	}}}
  //  printf("total: %u\r\n", total_cells);
//  if (count==0 && flag==1) reparse(offst,ln,rand()%(sig+1));
//  else return;
}

void gcollect(void){

  int flagy=0;
   int16 x=0,y=0,last=0,nlen=0,count=0;

   //           printf("reparse %ld\r\n",offst,ln);
  for (x=0;x<MEMSZ;x++){
    //    printf("rep %ld  cell %u\r\n",VM_OFFSET+offst+x,nv_access(VM_OFFSET+offst+x));

    if (total_cells<MAX_CELLS){
        if ((nv_access(VM_OFFSET+x)&31)==6) { 



      nlen=x-last;  

      if (nlen > 1 && (nlen+last+1)<MEMSZ) {
	//	printf(" add new cell\r\n");
	// if we don't have this cell add it 
	flagy=0;
for (y=0;y<(int16)total_cells*8;y+=8){
    offset=((int16)(nv_access(y+1))*128)+(int16)nv_access(y+2);
    if (offset==last+1) {
 flagy=1;
 break;
    }
}

	if (flagy==0) add_new_cell(nlen-1,last+1);
	last=x;
	//	count++;
      }

	}}}
}

/*
void reparsebac(int16 offst, int16 ln, int sig, int index){

  int16 indx;
   int16 x=0,last=0,nlen=0,count=0;

  last=ln;

  for (x=ln;x>0;x--){

    if ((nv_access(VM_OFFSET+offst+x)&31)==sig) { 

      nlen=last-x-1;  

      if (nlen > 6  && nlen<MEMSZ) {
	printf("inserting %ld",x+offst+1);
	insert_cell(index, nlen,x+offst+1);
	last=x;       
      }

    }}
}

void gcollect(void){
  int16 x;
   int16 garbage = 0, garblen = 0, first = 0;
  int croff = 0;



  for (x=0;x<(int16)total_cells*8;x+=8){
    offset=((int16)(nv_access(x+1))*128)+(int16)nv_access(x+2);
    if (offset>MEMSZ) continue;
    printf("reparseoffset: %ld\r\n",offset);
    len=nv_access(x+7);
    first=0;
    if ((garblen=(offset-garbage)) > 1 && garbage<offset){

      if (garblen<MEMSZ && garblen>0){
		reparsebac(garbage,garblen,6,x);
		
    }
    
    garbage = offset + (int16)len;
    first++;
  }
  }
  garblen = (MEMSZ - garbage);
  if ( garblen > 2 ) {

        printf("garblen: %ld\r\n",garblen);
    reparse(garbage,garblen,6);
    
}

  }
*/



void mutate(void){

int16 x;
x=rand()%MEMSZ;

// nv_set(VM_OFFSET+x,bitflip(nv_access(VM_OFFSET+x)));

 nv_set(VM_OFFSET+x,rand()%255);

 // printf("bitflip: %u %ld\r\n ",bitflip(nv_access(VM_OFFSET+x)),x);

}

void insert_cell(int16 index,int length, int16 offs){
  int16 x;
  
  if (total_cells<(MAX_CELLS-1) && length<MAX_LEN && length>0){

    // shunt over and insert new cell
    
      for (x=total_cells;x--;x>index){
	retrieve_cell((x-1)*8);
	putback_cell(x*8);
      }
      // insert
      xx=(int16)offs/128;
      offsett=(int16)offs%128;
      x=(index)*8;
      printf("inserted %ld %ld",index,total_cells);  
      nv_set(x,INITLIVELY);
      nv_set(x+1,xx);
      nv_set(x+2,offsett);
      nv_set(x+3,0);
      nv_set(x+4,0);
      nv_set(x+5,0);
      nv_set(x+6,0);
      nv_set(x+7,length);
      
    
 total_cells++;  
 }
  
}

void delete_cell(int16 index){
  int16 x;
  //shunt all back unless last cell
  if (index<=total_cells) 
    {
      for (x=index;x<(total_cells-1);x++){
	retrieve_cell((x+1)*8);
	putback_cell(x*8);
      }
      total_cells--;
    }

}

void add_new_cell(int length, int16 offs){
  int16 x;
  xx=(int16)offs/128;
  offsett=(int16)offs%128;
      printf("added %u %u total: %ld\r\n",xx,offsett,total_cells);  
  if (total_cells<MAX_CELLS && length<MAX_LEN && length>0){
      // fill out structure
    x=(int16)total_cells*8;
      nv_set(x,INITLIVELY);
      nv_set(x+1,xx);
      nv_set(x+2,offsett);
      nv_set(x+3,0);
      nv_set(x+4,0);
      nv_set(x+5,0);
      nv_set(x+6,0);
      nv_set(x+7,length);
 total_cells++;
 
}

}

void retrieve_cell(int16 cur_off){
  lively=nv_access(cur_off);
      xx=nv_access(cur_off+1);
      offsett=nv_access(cur_off+2);
      xp=nv_access(cur_off+3);
      mp=nv_access(cur_off+4);
      wp=nv_access(cur_off+5);
      rp=nv_access(cur_off+6);
      len=nv_access(cur_off+7);
      //      printf("ret: xx %u offsett %u\r\n",xx,offsett);
}

void putback_cell(int16 cur_off){
  //  printf("putback-lively %u\r\n",lively);
  //  printf("back: xx %u offsett %u\r\n",xx,offsett);
  nv_set(cur_off,lively);
  nv_set(cur_off+1,xx);
  nv_set(cur_off+2,offsett);
  nv_set(cur_off+3,xp);
  nv_set(cur_off+4,mp);
  nv_set(cur_off+5,wp);
  nv_set(cur_off+6,rp);
  nv_set(cur_off+7,len);
}

void do_function(int ins){
  int tmp,len; int16 x;
  int16 tmp1,tmp2;
  
         printf("ins: %d\r\n", ins);
  switch(ins){
  case 0:
    break;

  case 1:
    // btr1fn
    xp=xp>>1;    
    break;

  case 2:
    // btr2fn
    mp=mp>>1;
    break;

  case 3:
    // btr3fn
    wp=wp>>1;
    break;

  case 4:
    // btr4fn
    rp=rp>>1;
    break;

  case 5:
    // btl1fn
    xp=xp<<1;
    break;

  case 6:
    // btl2fn
    mp=mp<<1;
    break;

  case 7:
    // btl3fn
    wp=wp<<1;
    break;

  case 8:
    // btl4fn
    rp=rp>>1;
    break;

  case 9:
    // inc1fn
    xp++;
    break;

  case 10:
    // inc2fn
    mp++;
    break;

  case 11:
    // inc3fn
    wp++;
    break;

  case 12:
    // inc4fn
    rp++;
    break;

  case 13:
    // dec1fn
    //    if (xp!=0) xp--;
    break;

  case 14:
    // dec2fn
    if (mp!=0) mp--;
    break;

  case 15:
    // dec3fn
        if (wp!=0) wp--;
    break;

  case 16:
    // dec4fn
    if (rp!=0) rp--;
    break;

  case 17:
    // set1fn
    xp=nv_access(VM_OFFSET+offset+(int16)(mp%len));
    break;

  case 18:
    // set2fn
    mp=nv_access(VM_OFFSET+offset+(int16)(rp%len));
    break;

  case 19:
    // set3fn
    wp=nv_access(VM_OFFSET+offset+(int16)(mp%len));
    break;

  case 20:
    // set4fn
    rp=nv_access(VM_OFFSET+offset+(int16)(mp%len));
    break;
  case 21:
    // put1fn
    nv_set(VM_OFFSET+offset+(int16)(mp%len),xp);
    break;

  case 22:
    // put2fn
    nv_set(VM_OFFSET+offset+(int16)(mp%len),mp);
    break;

  case 23:
    // put3fn
    nv_set(VM_OFFSET+offset+(int16)(mp%len),wp);
    break;

  case 24:
    // put4fn
    nv_set(VM_OFFSET+offset+(int16)(mp%len),rp);
    break;

  case 25:
    // rllfn - rotates all regs
    tmp=xp;
    xp=mp;
    mp=wp;
    wp=rp;
    rp=tmp;

    break;

  case 26:
    // say1fn - TX (TX buffer in NVRAM) - size=128 - starts at page 226
    for (x=0;x<mp;x++){
      nv_set((TX_PAGE*128)+TXcounter,nv_access(VM_OFFSET+offset+(((int16)(rp+x))%len)));
      TXcounter++;
      if (TXcounter>128) {
	// unless we're recieving set TRANSMIT BUFFER thing to on
	// Q is to whether send full buffer or just len/mp bytes at a time
				if ((transmitting_data==FALSE) && (receiving_data==FALSE)) transmit_data();
TXcounter=0;
      }
    }
    lively+=2;
    break;
    
  case 27:
    // say2fn - LCD (probably still buffer) - size=16 - starts at page 227
    //          printf(":::%d",mp);
    for (x=0;x<mp;x++){
      //      nv_set((LCD_PAGE*128)+LCcounter,nv_access(VM_OFFSET+offset+(rp+x)%len));
              lcd_bytes[LCcounter]=nv_access(VM_OFFSET+offset+(((int16)(rp+x))%len));

      LCcounter++;

     if (LCcounter>16) {
      do_lcd();  
	LCcounter=0;
      // for test - write all to LCD or just char at a time
      }


	}
	    lively+=2;
    
    break;

  case 28:
    // lsnfn ADC

   set_adc_channel(1);
   delay_us(50);

    for (x=0;x<mp;x++){
      //      ly=read_adc();
      //            nv_set(VM_OFFSET+offset+( (( (int16)rp+x)%len)),(int16)read_adc()>>7);
            nv_set(VM_OFFSET+offset+( (( (int16)(rp+x))%len)),read_me());
      //nv_set(VM_OFFSET+offset+((int16)rp+x)%len,rand()%255);
      delay_us(50);
          }
    lively+=2;
    break;

    /*  case 29:
    // splfn ???? given current - tricky
    // insert cell following this cur_cell
    
    tmp1=offset+xp;
    tmp=len-xp;

    if (tmp>2 && tmp1>offset){
    // insert cell after cur_cell? -- copy back question
      putback_cell(VM_OFFSET+offset);
      insert_cell(cur_cell,tmp,tmp1);

      // if too small - delete - else shrink it
      if (xp>1){

	// copy back question
	retrieve_cell(VM_OFFSET+offset);
	len=xp;
      } else { 
	//delete cell
	delete_cell(cur_cell);
      retrieve_cell(VM_OFFSET+tmp1);
      }}
    
    break;
    */
  case 29:
    // cpyfn len=mp, copies rp in mem -> wp in mem
    tmp=mp%len;
    if (tmp<1) return;
    for (x=0;x<tmp;x++){
      nv_set(VM_OFFSET+offset+((wp+x)%len),nv_access(VM_OFFSET+offset+((rp+x)%len)));
    }
    break;

  case 30:
    // jizfn - addr= mp%cl->len if gp==0 xp=addr
    tmp=mp%len;
    if (rp==0 && tmp>0) xp=tmp;
    break;

  case 31:
    // ldtfn - searches from xp to end cell and back to find 21 then sets mp/xp to this
    for (x=0;x<len;x++){
      if (((nv_access(VM_OFFSET+offset+(int16)x))&ins)==21) {
	xp=x;
      }
    }
    break;
    /* - ROM space -?
  case 33:
    //  mrgfn - merges with next cell/garbage - both tricky
    break;

  case 34:
    // mrbfn - merges back
    break;
    */
  case 32:
    // cpofn - copies other cell from cellstart into wp+ location

    for (x=0;x<mp%len;x++){
      nv_set((VM_OFFSET+offset+((int16)(x+wp)%len)),nv_access(VM_OFFSET+((offset+(int16)len+(int16)rp)%MEMSZ)));

    }
    break;

  case 33:
    // for RX we also need counter for int-based routine to update the buffer
    // lsn2fn - read in RX buffer to cellspace - [start this at 228 ??]
      if (received_data==TRUE){
    //    printf("received");
    for (x=0;x<mp;x++){
      nv_set(VM_OFFSET+offset+((int16)((rp+x)%len)),nv_access((RX_PAGE*128)+RXcounter));
      RXcounter++;
      if (RXcounter>128) RXcounter=0;
}}
lively+=2;
    break;

}

}



int nv_access(int16 wher){
int value;
 int16 x,y;

// 255 x 128 pages

 x=(wher/128);
 y=wher%128; // use AND ?
 // zzz=total_cells
 // ;
 // value=MEM[x][y];
 //  printf("x: %ld y: %ld\r\n",x,y);
 page_wr(x);
 orreset();
 maddress(y);
 set_tris_d(0b11111111);
 output_low(PIN_E0);
 delay_cycles(4);
 value=input_d();
 output_high(PIN_E0);
 set_tris_d(0b00000000);
return value;
}


void nv_set(int16 wher, int what){
 int16 x,y;

 // printf("nvset:%ld", wher);
// 255 x 128 pages

 x=wher/128;
 y=wher%128;

 // MEM[x][y]=what;
 //   printf("x: %ld y: %ld\r\n",x,y);
 page_wr(x);
 orreset();
 maddress(y);
 output_low(PIN_E1);
 output_d(what);
 delay_cycles(4);
 output_high(PIN_E1);

}

int bitflip(int value){
  int i,j,k;
  k=1;  
  i=rand()%6;
  for (j=0;j<i;j++){
    k=k*2;
  }
  value=value^k;
  return value;
}


// + LCD access, charging, TX/RX on interrupts

void do_lcd(void){
  int x;
  // - size=16 
  output_low(PIN_E1);
  output_low(PIN_C0); // ale low
  output_low(PIN_E2); // en low
  output_low(PIN_E0); // rs low for control
  output_d(0x80);
  pulse();
  output_high(PIN_E0); // rs hi for control
  delay_us(125);

  // output 1st eight
  for (x=0;x<8;x++){
    output_d(lcd_bytes[x]);
  pulse();
  }
  output_low(PIN_E0);
  delay_us(125);
  output_d(0xc0);
  pulse();
  output_high(PIN_E0);
  delay_us(125);
  for (x=8;x<16;x++){
    output_d(lcd_bytes[x]);
  pulse();
  }


}

void init_lcd(void){
  delay_ms(10);
  output_low(PIN_E1);
  output_low(PIN_C0); // ale low
  output_low(PIN_E2); // en low
  output_low(PIN_E0); // rs low for control
  delay_us(125);
  output_d(0x38);
  pulse();
  output_d(0x0c);
  pulse();
  output_d(0x06);
  pulse();
  delay_ms(5);
}

void pulse(void){
  output_high(PIN_E2);
  delay_cycles(1);
  output_low(PIN_E2);
 delay_us(125);

}


void page_wr(int pag){
  orreset();
  output_high(PIN_C0);
  output_d(pag);
  delay_cycles(4);
  output_low(PIN_C0);
}


void orreset(void){
  output_low(PIN_C0);
  output_low(PIN_E2);
  output_high(PIN_E1);
  output_high(PIN_E0);
}


void maddress(int addr){

  //	printf("addr: %u\r\n", addr);
	addr=addr<<1;
    //                 bit_set(addr,input(PIN_B1));
    //    if (input(PIN_B0)) bit_set(addr,0);
    //	else bit_clear(addr,0);  
        bit_clear(addr,0);
	output_b(addr); // as rb0 is our fm
	delay_cycles(2);
 }

//---------------------------------------------------------------------
// ext_isr()
//
// If a B0 interrupt occurs, then we are may be starting to receive a
// transmission. If we are transmitting, we ignore anything on the
// RX pin. If not, we load the clock so that it interrupts in half
// the time. This resynchs our rx'r clk with the tx'r clk.
//----------------------------------------------------------------------


#INT_EXT
ext_isr() {
	if (transmitting_data) return;

	// else resynch the clock just in case.. let the rtcc take care of
	// the rest of the nasty business. We are using a prescale of 2
	// on the rtcc, and when we load the clock with a value, it resets
	// the prescaler too... by setting it at 253 or so, it will roll over
	// right away, and then only have to do one more set of 256 counts
	// before interrupting
	set_rtcc(253);
}

//------------------------------------------------------------------------
// rtcc_isr()
//
// This routine decides whether we are transmitting or receiving, and
// acts on that. Receiving takes precedence over transmitting. If for
// some reason we are trying to do both at the same time (shouldn't 
// happen as we will attempt to trap for that in the main code), the
// receive section will be executed and the transmit will be ignored.
//------------------------------------------------------------------------
#INT_RTCC
rtcc_isr() {
	// --------LOOKING FOR START BIT---------
	if ((receiving_data==FALSE)&(transmitting_data==FALSE)) {
		// not receiving or transmitting, therefore we must check for
		// a valid start bit (4 highs in a row)
		if (input(RX_PIN)) {
			start_bit_counter++;
			if (start_bit_counter==4) {
				receiving_data=TRUE; //valid start bit
				start_bit_counter=0; //reset counter for next time
				first_byte=TRUE; // we will be getting the first byte
				return;
			}
		} else start_bit_counter=0;
		return;
	}


	// ------RECEIVING-----
	if (receiving_data) {
		// we are in receiving mode
		rx_counter++;

		// shift the data on pin B0 into the rx_data variable
		// Basically we shift rx_data 1 to the left, then
		// OR it with the input of pin B0 (which has been cast
		// uint16 so that it will either be a 0x0001 or 0x0000)
		rx_data=(rx_data<<1)|((uint16)input(RX_PIN));

		// we need to check if we have received 16 bits of data yet
		if (rx_counter==16) {
			// we have all 16 bits of data, so we need to decode it
			// from the manchester encoding and put it into the
			// rx_buffer.
			nv_set((RX_PAGE*128)+rx_buf_counter,man_decode(rx_data));
			// if the received_data flag is still high at this point,
			// then we need to report a receive buffer error, as we
			// haven't read the previous data from the rx_data_buffer
			// yet, and we just overwrote it... whoops!
			if (received_data) receive_buffer_error=TRUE;

			rx_counter=0;
			rx_buf_counter++;
			if (rx_buf_counter==BUFFER_SIZE) {
				// we have all the data
				receiving_data=FALSE;
				received_data=TRUE;
				rx_buf_counter=0;
			}
			return;
		}
		return;
	}

	// -------TRANSMITTING--------
	if (transmitting_data) {
		// We are in transmitting mode

	  //send junk

	  if (send_junk_stuff){
		output_bit(TX_PIN,blip);
		blip=!blip;
	    junkcounter++;
	    if (junkcounter==220){
	      send_junk_stuff=FALSE;
	    send_start_bit=TRUE;
	    }
	    return;
	  }
		if (send_start_bit) {
			// CAREFUL... if the last start header bit is a high,
			// our rx detector will see it as the first bit of
			// the 4 start bits, and all data after that will
			// be mis-detected
			start_bit_counter++;
			if (start_bit_counter==1) {
				output_low(TX_PIN);
			} else {
				output_high(TX_PIN);
			}
			if (start_bit_counter==5) {
				// we have now sent the 4 start bits, so now tx data next interrupt
				start_bit_counter=0;
				send_start_bit=FALSE;
			}
			return;
		}
		if (send_stop_bit) {
			stop_bit_counter++;
			output_low(TX_PIN);
			if (stop_bit_counter==4) {
				stop_bit_counter=0;
				send_stop_bit=FALSE;
				tx_counter=0;
				tx_buf_counter=0;
				transmitting_data=FALSE;
				transmitted_data=TRUE;
			}
			return;
		}
		// If the tx_counter is equal to 16, then we need to
		// prepare for the next byte of data after sending the last
		// bit of data from the current byte.
		// Otherwise we just send out the next bit of data for the
		// current byte.
		tx_counter++;
		// transmit MSB first
		output_bit(TX_PIN,bit_test(tx_data,15));
		// shift out the MSB and get tx_data ready for next time
		tx_data=tx_data<<1;

		if (tx_counter==16) {
			// we just tx'd the last bit of data from the current byte
			// Set up for the next byte
			tx_counter=0;
			tx_buf_counter++;
			if (tx_buf_counter==BUFFER_SIZE) {
				// we have sent all the data in the buffer
				// and now we need to send the stop bit
				send_stop_bit=TRUE;
				//				printf("transmitted");
				return;
			}
			tx_data=man_encode(nv_access((TX_PAGE*128)+tx_buf_counter));
			return;
		}
		return;
	}
}


//--------------------------------------------------------------
// bit transmit_data(void)
//
// This routine sets up the buffer to be transmitted and the
// various flags that need to be set in order to TX stuff...
// This code assumes that we are at the robot and tx'ing 
// position data, etc... back to the main CPU
//----------------------------------------------------
bit transmit_data(void) {
	uint8 counter=0;

	// Check to make sure we are not already tx'ing or rx'ing
	if ((transmitting_data)|(receiving_data))
		//already transmitting or receiving
		return(0);
	else {

		// code to set up rxtx_buffer[] here - not implemented in this demo

		// load tx_data with the first byte to send
		tx_data=man_encode(nv_access(TX_PAGE*128));

		// enable the tx'ing by setting transmitting_data high
		send_junk_stuff=TRUE;
		//send_start_bit=TRUE;
		set_rtcc(0); //make sure timer0 starts at 0
		transmitting_data=TRUE;
		
		return(1);
	}
	}

//-------------------------------------------------------------
// bit receive_data(void)
//
// This procedure will get called by the main loop when 
// the received_data flag goes high. It should check the
// CRC to make sure that everything was received correctly
// break everything apart into the instructions or data that
// the buffer now contains....
//-------------------------------------------------------------
bit receive_data(void) {
	// do something with the data in the receive buffer
}	


//-------------------------------------------------------------
// uint16 man_encode(int enc)
//
// This function encodes a 8 bit value into a 16 bit manchester
// encoded variable which it then returns.
//
// This function encodes the bits in a unique way. The odd
// bits (7,5,3,1) are encoded into the msb 8 bits of data to
// return and the even bits (6,4,2,0) are encoded into the
// lsb 8 bits of data to return. Encoding this way saves alot
// of bit testing and flipping.
//
// 0x0E (00001110) encodes into 0x5AA6 (0101101010100110)
// instead of the more natural 0x55A9 (0101010110101001)
//
//-------------------------------------------------------------
uint16 man_encode(uint8 unenc) {
	uint8 odd_byte,even_byte,temp;

	// what I really want to do was this...
	//		odd_byte=(unenc&0xAA)|(~unenc&0xAA)>>1);
	// but the CCS compiler didn't like it all on one line
	// so I had to use an intermediate variable to get around it
	
	odd_byte=unenc&0xAA;
	temp=(~unenc&0xAA)>>1;
	odd_byte=odd_byte|temp;
	
	// what I really want to do was this...
	//		even_byte=(unenc&0x55)|(~unenc&0x55)>>1);
	// but the CCS compiler didn't like it all on one line
	// so I had to use an intermediate variable to get around it

	even_byte=unenc&0x55;
	temp=(~unenc&0x55)<<1;
	even_byte=even_byte|temp;
	return((uint16)odd_byte<<8)|even_byte;
}


//-------------------------------------------------------------
// uint8 man_decode(uint16 enc)
//
// This function decodes a 16 bit manchester encoded variable
// and returns the actual 8 bit unencoded value.
// See man_encode for a description of the encoding technique.
//-------------------------------------------------------------
uint8 man_decode(uint16 enc) {
	uint8 odd_byte,even_byte,temp;
	
	odd_byte=(uint8)(enc>>8);
	if((odd_byte&0xAA)^((~odd_byte&0x55)<<1)) {
		receive_error=1;
		return(0);
	} else odd_byte&=0xAA;
	even_byte=(uint8)enc;
	if((even_byte&0x55)^((~even_byte&0xAA)>>1)) {
		receive_error=1;
		return(0);
	} else even_byte&=0x55;
	receive_error=0;
	return(odd_byte|even_byte);
}



void sleeper(void) {
  printf("asleep");
  // RA4 as input
  
    set_tris_a(0b00110011); 
  //sleep
    sleep();
}

uint8 read_me(void) {
  uint8 x;
  x=(int16)read_adc()>>6;

   printf("%u\r\n",x);
 return x;
}


