/* mini1.c limited version of code size for 89C52 MiniLOGGER V1.0 ADC: Dual-slope integrating type, CA3162 -10mV to +1000mV 1mV resolution MUX: CD4051 8-channel RTC: DS1202 Serial timekeeping Memory: Battery Backup 256kB (628128x2) approx. 5000 records Interfacing: MAX232 */ #include "c:\mc\8051io.h" #include "c:\mc\8051reg.h" #include "c:\mc\8051bit.h" // require preprocessor -P when compiling #define word unsigned int #define byte unsigned char #define beginsysdata 0 #define beginrecord 100 #define begincrc 1000 #define status 0 /* system status eg., main/battery power, door open/close , digital input, analog input */ #define name 2 /*------------------------ DS1202 setting parameters -----------*/ #define rdsec 0x81 #define rdmin 0x83 #define rdhour 0x85 #define rddate 0x87 #define rdmonth 0x89 #define rdyear 0x8d #define secu 0x8e #define wrdate 0x86 #define wrmonth 0x88 #define wryear 0x8c #define wrhour 0x84 #define wrmin 0x82 #define wrsec 0x80 #define unlock 0 #define lock 0x80 /*--------------------------------------------------------------*/ extern register char cputick; unsigned register char sec100,sec,sec5,min,hour,day,month,year,flag1,ACCU,temp,led; unsigned register char command,counter3; unsigned register char BUFFER[50],mode; char *title[] = "\n\nMiniLOGGER V1.0 COPYRIGHT (C) 1999,2000 WICHIT SIRICHOTE"; char *prompt[] = "\n>>"; /* char *menu[] = "\n\nHELP MENU\ \n/ read once\ \nt TIME set\ \nd DATE set\ \nc Clock display\ \ns START/STOP recording time\ \ni Interval\ \n= setting parameters\ \nr number of record\ \ng Get record\ \nn New record\ \na ALL read\ \n? help"; */ unsigned register int blink_every; unsigned register int count,number_of_record,counter1,counter2,interval,temp16,j; unsigned register char pointer[3]; // 24 bit long number for external RAM pointer unsigned register char temp1[3], temp2[3]; extern register char Longreg[]; /*-------------------- constant definition -------------------------*/ #define XOFF 0x13 // transmission flow control #define XON 0x11 #define adj 2 #define LED P3.4 #define trigger P3.5 #define standby_blink 100 #define recording_blink 300 #define base 100 // start address for NVRAM storage #define max_record 5000 //limit maximum record for 256kB SRAM (5000*50) /*-------- address for setting parameters saved in NVSRAM 256 bytes page 0--*/ #define start_hour 0 #define start_min 1 #define stop_hour 2 #define stop_min 3 #define interval_saved 4 // 4-5 (16-bit) #define record_saved 6 // 6-7 (16-bit) #define description 8 // 8-58 (max description string 50 characters) #define mode_saved 60 // mode 1 manual, -1 auto main() { flag1 = 0; interval = 6000; // 60000 ms = 1 min blink_every = standby_blink; longset(pointer,100); /* initialize pointer to 100 */ reload_setting(); // reload previous recording setting disable(); serinit(9600); putstr(*title); sendprompt(); while(1) { tick_wait(); // 10 ms tasks tick /*------------- the following tasks execute every 10ms ------*/ cpubeat(); getcommand(); printtime(); settime(); setdate(); set_interval(); dec_counter2(); start_record(); save_record(); print_number_of_record(); set_start_stop(); new_record(); show_setting(); // print_menu(); clock(); read_all(); manual_start_stop(); prompting(); } /************************************************************/ } int getnum() { char s[6]; /* five characters plus terminator */ char c; int i; for (i = 0; (c = putch(getch())) != 13; i++) s[i] = c; s[i] = '\0'; if (i==0) return (-1); else return (_atoi(s)); } char getbyte() { char s[3]; /* two characters plus terminator */ int i; for (i = 0; i < 2; i++) /* read two characters then return value */ s[i] = putch(getch()); // echo to terminal s[i] = '\0'; return(((s[0]-0x30)<<4)|(s[1]-0x30)); // return BCD // return (_atoi(s)); // return binary } set_interval() { if(command == 'i'){ putstr("\n interval 10-600 sec > "); set_page(0); pokew(interval_saved,(getnum()*100)); // convert to *10 ms interval = peekw(interval_saved); counter2 = interval; // load interval to counter2 sendprompt(); } } dec_counter2() { if ((flag1 & 0x08) != 0){ counter2--; if(counter2 <= 0){ counter2 = interval; flag1 |= 0x04; } } } start_record(){ counter3--; if ( counter3 <= 0){ counter3 = 100; // run this task every 1 second if((rdds1202(rdhour) == peek(start_hour)) && (rdds1202(rdmin) == peek(start_min))) {flag1 |= 0x08; // start dec counter2 blink_every = recording_blink; } if ((rdds1202(rdhour) == peek(stop_hour)) && (rdds1202(rdmin) == peek(stop_min))) {flag1 &= ~0x08; // disable running dec_counter2 blink_every = standby_blink; } } } settime() { if (command == 't') { command = '/'; // printtime(); putstr(" HH:MM:SS = "); writertc(secu,unlock); writertc(wrhour,getbyte()); putch(':'); writertc(wrmin,getbyte()); putch(':'); writertc(wrsec,getbyte()); writertc(secu,lock); sendprompt(); } } setdate() { if (command == 'd') { command = '/'; // printtime(); putstr(" DD/MM/YR = "); writertc(secu,unlock); writertc(wrdate,getbyte()); putch('/'); writertc(wrmonth,getbyte()); putch('/'); writertc(wryear,getbyte()); writertc(secu,lock); sendprompt(); } } prompting() { if (command == 13) { putstr(*title); sendprompt(); } } printtime() { if (command == '/') { printf("\n%02x/%02x/%02x ",rdds1202(rddate),rdds1202(rdmonth),rdds1202(rdyear)); printf("%02x:%02x:%02x ",rdds1202(rdhour),rdds1202(rdmin),rdds1202(rdsec)); read_DVM(); printf("%i",BUFFER); /* for testing */ sendprompt(); } } getcommand() { if ((SCON & 0x01) != 0) command = putch(getch()); else command = -1; /* no cammand has entered */ } sendprompt() { putstr(*prompt); } pause(int j) { int i; for (i = 0; i < j; i++) ; } cpubeat() { beat5sec(); livecpu(); } beat5sec() /* clear P3.4 every 500 tocks */ { counter1++; if (counter1 > blink_every ) { counter1 = 0; flag1 |= 0x40; /* set bit 6 of flag1 to signal livecpu task */ clrbit(LED) //asm " CLR P3.4"; led = 5; /* 5*10ms = 50ms LED on */ } } livecpu() { if ((flag1 & 0x40) != 0) { led--; if (led == 0) { setbit(LED) //asm " SETB P3.4"; flag1 &= ~0x40; } } } read_DVM() /* read digital data from SOLAR3, save in BUFFER */ { int i; char c; clrbit(trigger) //asm" CLR P3.5"; // trigger read clrbit(LED) //asm" CLR P3.4"; // while reading turn LED on for (i = 0; (c = getchr()) != 0; i++) BUFFER[i] = c; BUFFER[i] = '\0'; setbit(trigger) //asm" SETB P3.5"; setbit(LED) //asm" SETB P3.4"; // then off // printf("%i",BUFFER); /* for testing */ } tick_wait() { asm { JNB TCON.5,* /* wait for timer0 overflow */ CLR TCON.5 ORL TH0,#$DC /* reload $DC00, i.e., for 10ms overflow */ } } /*---------------------- DS1202 RTC driver routine ------------------*/ writertc(char a, char b) { int i; i = a; i <<= 8; i |= b; wrds1202(i); } set_page(unsigned char p) /* set page address for A16 (P1.0), CHIP SELECT P1.1 and P1.2 */ /* pointer[0] and [1] 16 bit are used for low 16-bit addressing pointer[1] bit 0 is for A16 bit 1 is for A17 if A17 = 0 then SETB P1.1 & CLR P1.2 if A17 = 1 then CLR P1.1 & SETB P1.2 */ { temp = p; //pointer[2]; asm { MOV A,temp MOV C,ACC.0 emits A16 MOV P1.0,C JB ACC.1,A17_HIGH SETB P1.1 A17 low then select chip #1 CLR P1.2 SJMP SET_ADDRESS_OK A17_HIGH SETB P1.2 A17 high then select chip #2 CLR P1.1 SET_ADDRESS_OK NOP } } int get_address() /* return address pointer */ { int i; i = pointer[1]; i <<= 8; return(i|pointer[0]); } inc_pointer() { asm{ MOV A,#$1 ADD A,pointer MOV pointer,A CLR A ADDC A,pointer+1 MOV pointer+1,A CLR A ADDC A,pointer+2 MOV pointer+2,A } } int set_RAM_address() /* increment next address for external 256kB SRAM */ { inc_pointer(); set_page(pointer[2]); return(get_address()); } char convert_hi_nibble(unsigned char c) { return((c>>=4)+0x30); } char convert_lo_nibble(char c) { return((c&0x0f)+0x30); } save_record() { if((flag1 & 0x04) != 0) { read_DVM(); // save date & time in ASCII poke(set_RAM_address(),convert_hi_nibble(rdds1202(rddate))); poke(set_RAM_address(),convert_lo_nibble(rdds1202(rddate))); poke(set_RAM_address(),convert_hi_nibble(rdds1202(rdmonth))); poke(set_RAM_address(),convert_lo_nibble(rdds1202(rdmonth))); poke(set_RAM_address(),convert_hi_nibble(rdds1202(rdyear))); poke(set_RAM_address(),convert_lo_nibble(rdds1202(rdyear))); poke(set_RAM_address(),convert_hi_nibble(rdds1202(rdhour))); poke(set_RAM_address(),convert_lo_nibble(rdds1202(rdhour))); poke(set_RAM_address(),convert_hi_nibble(rdds1202(rdmin))); poke(set_RAM_address(),convert_lo_nibble(rdds1202(rdmin))); poke(set_RAM_address(),convert_hi_nibble(rdds1202(rdsec))); poke(set_RAM_address(),convert_lo_nibble(rdds1202(rdsec))); // now save the BUFFER for (j = 0; BUFFER[j] != '\0'; j++) poke(set_RAM_address(),BUFFER[j]); poke(set_RAM_address(),'\0'); // put line terminator flag1 &= ~0x04; ++number_of_record; max_limit(); // check maximum for 5000 records set_page(0); pokew(record_saved,number_of_record); // save available records printf("%u",number_of_record); // putch('.'); // sending flag to host after record has been saved } } max_limit(){ // disable recording mode if number of record > max_record if(number_of_record > max_record) {flag1 &= ~0x08; // disable running dec_counter2 blink_every = standby_blink; poke(mode_saved,-1); // change to auto mode indicating maximum limited } } print_number_of_record() { if (command == 'r') { printf("\n%u records available",number_of_record); sendprompt(); } } /* get_record() // test reading until found record terminator { char i; if (command == 'g') { putch('\n'); j = 101; for (j = 101; j< 101+(number_of_record*46); j = j+46) { for ( i = 0; i <46; i++) { if(peek(i+j) != 0) putch(peek(i+j)); else putch('\n'); } } sendprompt(); } } */ set_start_stop() { if (command == 's'){ set_page(0); printf("\nSTART %02x:%02x >",peek(start_hour),peek(start_min)); poke(start_hour,getbyte()); // save new start time putch(':'); poke(start_min,getbyte()); printf("\nSTOP %02x:%02x >",peek(stop_hour),peek(stop_min)); poke(stop_hour,getbyte()); putch(':'); poke(stop_min,getbyte()); printf("\n %02x:%02x %02x:%02x",peek(start_hour),peek(start_min),peek(stop_hour),peek(stop_min)); swapping_mode(); sendprompt(); } } swapping_mode() // enable/disable manual check { if (peek(start_hour) == 0x99) poke(mode_saved,1); // manual mode else (poke(mode_saved,-1)); // automatic mode } show_setting(){ if (command == '='){ set_page(0); printf("\n START %02x:%02x",peek(start_hour),peek(start_min)); printf("\n STOP %02x:%02x",peek(stop_hour),peek(stop_min)); printf("\n SAMPLING INTERVAL(sec) = %u",peekw(interval_saved)/100); if (peek(mode_saved) == 1) printf("\n MANUAL"); else (printf("\n AUTO")); sendprompt(); } } reload_setting(){ set_page(0); interval = peekw(interval_saved); counter2 = interval; number_of_record= peekw(record_saved); longset(temp2,46); // temp2 = 46 longset(temp1,number_of_record); // temp1 = number of record longmul(temp1,temp2); // Longreg = temp1*temp2 longset(temp1,base); // temp1 = base = 100 longadd(Longreg,temp1); // Longreg = Longreg + temp1 longcpy(pointer,Longreg); // restore pointer } new_record() { if (command == 'n') { putstr("\n New record?(Y/N)"); if (getch() == 'y') { flag1 &= ~0x08; // reset start bit enable number_of_record = 0; pokew(record_saved,0); // reset number of record to 0 longset(pointer,base); enter_description(); } sendprompt(); } } /* print_menu(){ if (command == '?'){ putstr(*menu); sendprompt(); } } */ clock(){ if (command == 'c'){ printf("\n %02x/%02x/%02x ",rdds1202(rddate),rdds1202(rdmonth),rdds1202(rdyear)); printf("%02x:%02x:%02x ",rdds1202(rdhour),rdds1202(rdmin),rdds1202(rdsec)); sendprompt(); } } read_all() // read all record from 100 to current pointer { if (command == 'a'){ send_description(); longset(temp1,1); // decrement pointer longsub(pointer,temp1); longcpy(temp1,pointer); // copy end address to temp1 longset(pointer,100); // point to start of NVRAM while (longcmp(temp1,pointer) > 0) { for (j = 0; j < 46; j++) BUFFER[j] = peek(set_RAM_address()); BUFFER[j] = 0; // printf("\n %i",BUFFER); send_formatted_record(); see_XOFF(); } sendprompt(); } } send_formatted_record() { send(0x0d); send(0x0a); printf("%c%c/%c%c/%c%c",BUFFER[0],BUFFER[1],BUFFER[2],BUFFER[3],BUFFER[4],BUFFER[5]); printf(",%c%c:%c%c:%c%c",BUFFER[6],BUFFER[7],BUFFER[8],BUFFER[9],BUFFER[10],BUFFER[11]); for(j = 0; j< 24; j+=3) // skip BUFFER[12] = * printf(",%c%c%c",BUFFER[13+j],BUFFER[14+j],BUFFER[15+j]); printf(",%c%c%c%c%c%c",BUFFER[37],BUFFER[38],BUFFER[39],BUFFER[40],BUFFER[41],BUFFER[42]); } see_XOFF() { char c; if ( chkchr() == XOFF) { while( c != XON) c = chkchr(); } } send(char a) // Dave's putch() automatically send 0x0d after 0x0a { temp = a; asm{ JNB SCON.1,* CLR SCON.1 MOV A,temp MOV SBUF,A } } enter_description() { putstr("\n<-- Enter description text (max 50 characters)-->\n"); _getstr(BUFFER,50); // get string max 50 characters set_page(0); for (j = 0; BUFFER[j] != '\0'; j++) // save to NVRAM poke((description+j),BUFFER[j]); poke((description+j),'\0'); // put line terminator // sendprompt(); } send_description() { char c; send(0x0d); send(0x0a); set_page(0); for (j = 0; (c = peek(description+j)) != '\0'; j++) putch(c); } manual_start_stop(){ set_page(0); if (peek(mode_saved) == 1){ if((P3 & 0x04) == 0) {flag1 |= 0x08; // start dec counter2 blink_every = recording_blink; } else {flag1 &= ~0x08; // disable running dec_counter2 blink_every = standby_blink; } } }