/* mini3.c Firmware for MiniLogger V3.0 89C51RD2+ICL7109+128kB SRAM+RTC+LCD+GPIO Copyright (C) 2003 WICHIT SIRICHOTE, 29 June 2003 Department of Applied Physics Faculty of Science King Mongkut's Institute of Technology Ladkrabang, Bangkok 10250 THAILAND */ #include <8051io.h> #include <8051reg.h> #include <8051int.h> #include <8051bit.h> // require preprocessor -P when compiling #include "c:\mc\tiny\minilcd.c" #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 #define adc 0x08 // ICL7109 12-bit ADC #define gpio1 0x0c // 8-bit output port #define gpio2 0x0e // 8-bit input port #define lcd 0x0a // LCD // flag1 bit usages #define keypressed 0x01 extern register char cputick; register unsigned char sec100,sec,sec5,min,hour,day,month,year,flag1,ACCU,temp,led; register unsigned char i,command,counter3; register unsigned char BUFFER[30],mode,key; register char n,page,channel,POL,OV; register int temp3, temp4,k; register int buffer[4]; register unsigned char tbuffer[8]; extern register char lastread // flag for last byte to be read char title[] = "\n\nMiniLOGGER V3.0 (C) 2003 W.SIRICHOTE Dept.of Applied Physics KMITL"; 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\ \nb terminal connection\ \nn New record\ \na ALL read: sample real-time and data\ \nx Read All: sample and data\ \nu About MiniLOGGER V3.0\ \n? help"; char _about[] = "\nMiniLOGGER was desinged by W.SIRICHOTE 28 June 2003\ \nURL: www.kmitl.ac.th/~kswichit email: kswichit@kmitl.ac.th"; char _terminal[] = "\n 1 2 3 4 5 6 7 8 9 10 11 12\ \nIN1+ IN1- IN2+ IN2- IN3+ IN3- IN4+ IN4- -5V +5V 0V +V"; register unsigned int blink_every; register unsigned int count,number_of_record,counter1,counter2,interval,temp16,j; register unsigned char pointer[3]; // 24 bit long number for external RAM pointer register unsigned char temp1[3], temp2[3]; // temp1 and temp2 are used for 24-bit storage extern register char Longreg[]; register unsigned char channel_display; /*-------------------- constant definition -------------------------*/ #define XOFF 0x13 // transmission flow control #define XON 0x11 #define adj 2 #define LED P1.7 #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() { asm" MOV $8E,#3"; // normal access to external memory, emits ALE when access ram IE |= 0x81; // enable external interrupt0 TCON |= 0x01; // edge trigger channel = 0; channel_display = 0; xpoke(gpio1,0,channel); // select mux channel 0 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 InitLcd(); Puts("MiniLOGG"); goto_xy(0,1); Puts("ER V3.0"); serinit(9600); putstr(title); sendprompt(); // clr_screen(); while(1) { tick_wait(); /*------------- the following tasks execute every 10ms ------*/ cputick = 0; 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(); xread_all(); manual_start_stop(); about(); get_key(); key_released(); execute_key(); terminal_signal(); prompting(); print_adc(); print_no_record(); } /************************************************************/ } INTERRUPT(_IE0_) service_adc() { P1 &= ~0x40; // hold ADC // asm" MOV $8F,#0"; // x1 mode temp3 = xpeek(adc,2); // get low byte temp4 = xpeek(adc,1); // get high byte // asm" MOV $8F,#1"; // x2 mode // printf("\r %02x %02x",temp1,temp2); POL = temp4 &0x10; OV = temp4 &0x20; temp4 &= 0x0f; temp4 <<= 8; temp3 |= temp4; if(!POL) temp3*=-1; if(OV) temp3 = 9999; buffer[channel] = temp3; channel++; channel&= 0x03; // channel increment will be 0-3 xpoke(gpio1,0,channel); // select next channel delay(10); // wait for mux settled P1 |= 0x40; // run ADC after mux settled for next channel scanning if(channel == 0) { P1 &= ~0x40; //stop ADC flag1 |= 0x80; // set ADC result bit // printf(" %d %d %d %d",buffer[0],buffer[1],buffer[2],buffer[3]); } } terminal_signal() { if(command == 'b') { putstr(_terminal); sendprompt(); } } setpage(char x) // emit A16,A17,A18,A19 to P1.0-P1.3 { temp = x; asm{ MOV A,temp MOV C,ACC.0 MOV P1.0,C MOV C,ACC.1 MOV P1.1,C MOV C,ACC.2 MOV P1.2,C MOV C,ACC.3 MOV P1.3,C } } xpeek(char x,int y) // read byte with page, address { setpage(x); return peek(y); } xpoke(char x,int y,char z) // write byte with page,address,data { setpage(x); poke(y,z); } output_1Hz() { send_start(); send_byte(0xd0); send_byte(0x07); // pointed to address 7 send_byte(0x90); // enable 1Hz output send_stop(); } readRTC() { send_start(); send_byte(0xD0); send_byte(0x00); send_stop(); send_start(); send_byte(0xD1); lastread = 0; for(i=0; i<6 ; i++) tbuffer[i] = read_byte(); lastread = 1; tbuffer[i] = read_byte(); send_stop(); // printf("\n %02x-%02x-%02x %02x:%02x:%02x",tbuffer[4],tbuffer[5],tbuffer[6],tbuffer[2],tbuffer[1],tbuffer[0]); } initRTC() { send_start(); send_byte(0xD0); send_byte(0x00); send_byte(0x00); send_byte(0x30); send_byte(0x12); send_byte(0x03); send_byte(0x25); send_byte(0x07); send_byte(0x00); send_stop(); } send_time() { readRTC(); } about() { if(command == 'u') { putstr(_about); sendprompt(); } } settime() { if (command == 't') { putstr("\nenter current time HH:MM:SS >"); hour = getbyte(); putch(':'); min = getbyte(); putch(':'); sec = getbyte(); send_start(); send_byte(0xD0); send_byte(0x00); send_byte(sec); send_byte(min); send_byte(hour); send_stop(); sendprompt(); } } 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)); } 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 1-600 sec > "); setpage(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){ counter2--; if(counter2 <= 0){ counter2 = interval; flag1 |= 0x04; } } } start_record(){ counter3--; if ( counter3 <= 0){ counter3 = 100; // run this task every 1 second readRTC(); setpage(0); if((tbuffer[2] == peek(start_hour)) && (tbuffer[1]== peek(start_min))) {flag1 |= 0x08; // start dec counter2 blink_every = recording_blink; } if ((tbuffer[2] == peek(stop_hour)) && (tbuffer[1] == peek(stop_min))) {flag1 &= ~0x08; // disable running dec_counter2 blink_every = standby_blink; } } } setdate() { if (command == 'd') { putstr("\nenter current date DD-MM-YR >"); day = getbyte(); putch('-'); month = getbyte(); putch('-'); year = getbyte(); send_start(); send_byte(0xD0); send_byte(0x04); send_byte(day); send_byte(month); send_byte(year); send_stop(); sendprompt(); } } prompting() { if (command == 13) { putstr(title); sendprompt(); } } printtime() { if (command == '/') { readRTC(); printf("\n%02x-%02x-%02x ",tbuffer[4],tbuffer[5],tbuffer[6]); printf("%02x:%02x:%02x ",tbuffer[2],tbuffer[1],tbuffer[0]); read_ICL7109(); printf(" %d %d %d %d",buffer[0],buffer[1],buffer[2],buffer[3]); sendprompt(); } } getcommand() { if (SCON&0x01) 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) { led--; if (led == 0) { setbit(LED) //asm " SETB P3.4"; flag1 &= ~0x40; } } } read_ICL7109() /* read analog from ICL7109, save in BUFFER */ { clrbit(LED) // while reading ADC turns LED on P1 |= 0x40; // star ADC while((flag1&0x80)==0) ; flag1 &= ~0x80; // clear flag1 setbit(LED) // printf(" %d %d %d %d",buffer[0],buffer[1],buffer[2],buffer[3]); } tick_wait() { asm { JNB TCON.5,* /* wait for timer0 overflow */ CLR TCON.5 ORL TH0,#$DC /* reload $DC00, i.e., for 10ms overflow */ } } 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 SRAM */ { inc_pointer(); setpage(pointer[2]); return(get_address()); } int iset_RAM_address() /* increment next address word based */ { inc_pointer(); inc_pointer(); setpage(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); } // format raw data saved in external ram // number day month year hr min sec adc0 adc1 adc2 adc3 * // number = 16-bit // adc0-adc3 = 16-bit // 17 bytes each record save_record() { if(flag1&0x04) { read_ICL7109(); readRTC(); pokew(iset_RAM_address(),number_of_record); // save date & time poke(set_RAM_address(),tbuffer[4]); // save day poke(set_RAM_address(),tbuffer[5]); // save month poke(set_RAM_address(),tbuffer[6]); // save year poke(set_RAM_address(),tbuffer[2]); // save hr poke(set_RAM_address(),tbuffer[1]); // save min poke(set_RAM_address(),tbuffer[0]); // save sec // now save the buffer read from ICL7109 pokew(iset_RAM_address(),buffer[0]); pokew(iset_RAM_address(),buffer[1]); pokew(iset_RAM_address(),buffer[2]); pokew(iset_RAM_address(),buffer[3]); flag1 &= ~0x04; ++number_of_record; max_limit(); // check maximum for 5000 records setpage(0); pokew(record_saved,number_of_record); // save available records // printf("%u",number_of_record); } } 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(); } } */ get_key() { if((xpeek(gpio2,0) != 0xff)&& ((flag1&keypressed)==0)) { flag1 |= keypressed; // enter only after key was pressed key = xpeek(gpio2,0); // printf("%x", key); } else key = -1; } key_released() { if(xpeek(gpio2,0) == 0xff) flag1 &= ~keypressed; } execute_key() { if(key != -1) { switch (key) { case 0x7f: channel_display++; break; case 0xbf: flag1^=0x02; flag1 &= ~0x10; // show unit clr_screen(); goto_xy(0,1); Puts("x0.1mV "); if(flag1&0x02) { putch_lcd('*'); } else { clr_screen(); show_mode_on_lcd(); goto_xy(0,0); Puts("Record= "); flag1 |= 0x10; // show number of record on LCD } break; case 0xdf: break; case 0xef: break; } } } set_start_stop() { if (command == 's'){ setpage(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 == '='){ setpage(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(){ setpage(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; setpage(0); pokew(record_saved,0); // reset number of record to 0 // printf("%d",peekw(record_saved)); longset(pointer,base); enter_description(); } sendprompt(); } } print_menu(){ if (command == '?'){ putstr(menu); sendprompt(); } } clock(){ if (command == 'c'){ readRTC(); printf("\n%02x-%02x-%02x ",tbuffer[4],tbuffer[5],tbuffer[6]); printf("%02x:%02x:%02x ",tbuffer[2],tbuffer[1],tbuffer[0]); 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 0) for(j=0; j\n"); _getstr(BUFFER,30); // get string max 30 characters setpage(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); setpage(0); for (j = 0; (c = peek(description+j)) != '\0'; j++) putch(c); } manual_start_stop(){ setpage(0); if (peek(mode_saved)==1){ if((P3&0x08) == 0) {flag1 |= 0x08; // start dec counter2 blink_every = recording_blink; } else {flag1 &= ~0x08; // disable running dec_counter2 blink_every = standby_blink; } } } show_mode_on_lcd() { setpage(0); if (peek(mode_saved)==1) { goto_xy(7,1); putch_lcd('M'); } else { goto_xy(7,1); putch_lcd('A'); } } print_adc() { if(flag1&0x02) { read_ICL7109(); goto_xy(0,0); channel_display &= 0x03; // only 0-3 can be used putch_lcd(channel_display+49); // show channel 1 to 4 instead putch_lcd(' '); print_4digit(buffer[channel_display]); } } print_no_record() { if(flag1&0x10) // print number of record on lcd { goto_xy(0,1); print_4digit(number_of_record); } }