#include <16f877.h> #include // 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 (ly0){ 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 1 && (nlen+last+offst+1) 1 && (nlen+last+1)0;x--){ if ((nv_access(VM_OFFSET+offst+x)&31)==sig) { nlen=last-x-1; if (nlen > 6 && nlenMEMSZ) continue; printf("reparseoffset: %ld\r\n",offset); len=nv_access(x+7); first=0; if ((garblen=(offset-garbage)) > 1 && garbage0){ 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) && length0){ // 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_cells0){ // 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;x128) { // 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;x16) { 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>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;xlen 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;x128) 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>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; }