/* Preprocessors */ #define MAXLOGS 201 /* Public variables */ /* Pointers */ unsigned char *lcdc, *lcdd, *latch, *rtc, *flash, *da, *dtmf; /* Log variables */ unsigned char logged_nbr[MAXLOGS+1][14]; unsigned char log_nbr[17]; /* ASCII */ unsigned char log_date[10]; /*YYMMDDhhmm*/ unsigned char nbr_log; /* Read Only */ unsigned char cur_log; /* R/W */ /* Menu variables */ unsigned char oldButtons; unsigned long buttonRep; unsigned long menuState; unsigned int curContact; /* Date/Time variables */ unsigned char dateTime[10]; /*yymmddhhmm*/ unsigned char last_min; unsigned int rtc_update; unsigned char inc_nbr[17]; int inc_idx; /* Functions */ /*** RTC ***/ void init_rtc(); unsigned char read_rtc(int reg); void write_rtc(int reg, unsigned char data); void write_date(); void read_date(); int rtc_data_changed(); void rtc_int_dis(); void rtc_int_en(); /*** LCD/Print functions ***/ void clr_lcd(); void init_lcd(); void wait_lcd(); void hide_cursor(); void show_cursor(short int row, short int pos); void println0(char s[]); void println1(char s[]); void print(unsigned char c, unsigned short int row, unsigned short int pos); void print_from_mem(unsigned long addr, unsigned short int row, unsigned short int pos, int nbrChars); void printbyte(unsigned short int b, unsigned short int row); void printhex(unsigned long int l, unsigned short int row); void print_date(unsigned char d[], unsigned short int row); /*** Input/Output Latches ***/ unsigned char get_latch(); void set_latch(unsigned char c); /*** Sound ***/ void play_sound(int songNbr); /* Play song (songNbr = 1-7) */ /*** Contact handling ***/ unsigned int nbr_contacts(); unsigned long find_contact(char number[]); /*** Logged numbers ***/ void init_log(); unsigned char last_log(); unsigned char first_log(); unsigned char next_log(unsigned char idx); unsigned char prev_log(unsigned char idx); unsigned char remove_log(unsigned char idx); unsigned char add_log(unsigned char nbr[]); void decode_log(unsigned char idx); void encode_log(unsigned char idx); unsigned char free_logidx(); /*** Menu ***/ void button_handler(unsigned char b); void print_menu(); unsigned short int dateAddr(int i); unsigned short int dateMin(int i); unsigned short int dateMax(int i); /*** Misc ***/ void idle_loop(); /* Main idle loop */ void wait(unsigned int n); int exp2(); int exp5(); /* Main function */ main() { int i; /* Set pointers */ lcdc = (unsigned char *) 0x00030000; /* LCD control register */ lcdd = (unsigned char *) 0x00030001; /* LCD data register */ latch = (unsigned char *) 0x00040000; /* latch (buttons)*/ rtc = (unsigned char *) 0x00028000; /* real time clock*/ flash = (unsigned char *) 0x00080000; /* flash*/ da = (unsigned char *) 0x00020000; /* D/A-converter*/ dtmf = (unsigned char *) 0x00038000; /* DTMF */ /* Init public variables */ oldButtons=0; buttonRep=0; menuState=0x00; /* Main menu */ curContact=0; last_min=70; inc_idx=0; for(i=0;i<16;i++) { inc_nbr[i]=0x20; } rtc_update=0; /* Init hardware */ *da=0; init_lcd(); init_rtc(); set_latch(0); /* Init software */ init_log(); print_menu(); /* Enter the endless idle loop */ /* idle_loop(); */ _inten(); /* Endless idle loop */ while(1); } void idle_loop() { unsigned char b; unsigned long m1; m1=menuState & 0xf0; if(m1 != 0x20) { rtc_update++; if(rtc_update>30) { /* Update only each 300 interrupts, ~3 sec */ rtc_update=0; read_date(); if((m1==0) && (dateTime[9]!=last_min)) { last_min=dateTime[9]; print_menu(); } } } b=get_latch(); button_handler(b); } void init_log() { unsigned char i; for(i=1;i47) log_nbr[i]=nbr[i]-48; /* ASCII */ else log_nbr[i]=10; i++; } while(i<16) { log_nbr[i]=10; /* space */ i++; } for(i=0;i<10;i++) log_date[i]=dateTime[i]; encode_log(idx); nbr_log++; return idx; } void decode_log(unsigned char idx) { unsigned char y, m, d, h, min, i, j, k; y=logged_nbr[idx][2]>>1; m=((logged_nbr[idx][2] & 1)<<3) + ((logged_nbr[idx][3] & 0xE0)>>5); d=logged_nbr[idx][3] & 0x1F; h=logged_nbr[idx][4] & 0x1F; min=logged_nbr[idx][5] & 0x3F; log_date[0]=y / 10; log_date[1]=y % 10; log_date[2]=m / 10; log_date[3]=m % 10; log_date[4]=d / 10; log_date[5]=d % 10; log_date[6]=h / 10; log_date[7]=h % 10; log_date[8]=min / 10; log_date[9]=min % 10; j=0; for(i=6;i<14;i++) { k=logged_nbr[idx][i]>>4; if (k>9) log_nbr[j]=0x20; else log_nbr[j]=k+48; k=logged_nbr[idx][i] & 15; if (k>9) log_nbr[j+1]=0x20; else log_nbr[j+1]=k+48; j=j+2; } } void encode_log(unsigned char idx) { unsigned char y, m, d, h, min, i, j; y=log_date[0]*10+log_date[1]; m=log_date[2]*10+log_date[3]; d=log_date[4]*10+log_date[5]; h=log_date[6]*10+log_date[7]; min=log_date[8]*10+log_date[9]; logged_nbr[idx][2]=(y<<1)+((m & 8)>>3); logged_nbr[idx][3]=((m & 7)<<5)+d; logged_nbr[idx][4]=0x80+h; logged_nbr[idx][5]=min; j=0; for(i=6;i<14;i++) { logged_nbr[idx][i]=(log_nbr[j]<<4)+log_nbr[j+1]; j=j+2; } } unsigned char free_logidx() { unsigned char i; for(i=1;i>4; int m2=menuState & 0x0f; if(oldButtons == b) { if (b!=0) buttonRep=buttonRep+1; /*TODO: Handle repetitions...*/ } else { buttonRep=0; switch(m1) { case 0x0: if(b & 0x10) { menuState=0x20; print_menu(); } else if(b & 0x20) { } else if(b !=0) { /* Scroll number */ if(nbr_log) { menuState=0x10; cur_log=last_log(); print_menu(); } } break; case 0x1: if(b & 0x10) { menuState=0x20; print_menu(); } else if(b & 0x20) { cur_log=remove_log(cur_log); if(nbr_log==0) menuState=0x0; print_menu(); } else if(b !=0) { if(b & 0x40) { cur_log=prev_log(cur_log); if(cur_log==0) cur_log=last_log(); } else if(b & 0x80) { cur_log=next_log(cur_log); if(cur_log==MAXLOGS) cur_log=first_log(); } print_menu(); } break; case 0x2: if(b & 0x10) { if(m2) { write_date(); } menuState=0x30; hide_cursor(); print_menu(); } else if(b & 0x20) { m2++; if(m2>10) m2=1; menuState=0x20+m2; print_menu(); } else if(b !=0) { if(m2) { if(b & 0x40) { if(dateTime[m2-1]<=dateMin(m2-1)) dateTime[m2-1]=dateMax(m2-1); else dateTime[m2-1]--; } else if(b & 0x80) { dateTime[m2-1]++; if(dateTime[m2-1]>dateMax(m2-1)) dateTime[m2-1]=dateMin(m2-1); } } else { menuState=0x21; } print_menu(); } break; case 0x3: if(b & 0x10) { menuState=0x41; print_menu(); } else if(b & 0x20) { menuState=0x31; } else if(b !=0) { if(b & 0x40) { if (curContact==0) curContact=nbr_contacts()-1; else curContact--; menuState=0x31; } else if(b & 0x80) { curContact++; if (curContact>=nbr_contacts()) curContact=0; menuState=0x31; } print_menu(); } break; case 0x4: /* This piece of code only allows one button at the time, and the most left button got highest priority and the most right button got lowest */ if(b & 0x10) { menuState=0x00; print_menu(); } else if(b & 0x20) { println1("Playing..."); play_sound((unsigned char)(menuState & 15)); print_menu(); } else if(b !=0) { /* Scroll number */ if(b & 0x40) { menuState=menuState-1; if (menuState<0x41) menuState=0x47; } else if(b & 0x80) { menuState=menuState+1; if (menuState>0x47) menuState=0x41; } print_menu(); } break; } } oldButtons=b; } /* TODO: Fix dateMin() and dateMax() functions */ unsigned short int dateMin(int i) { switch(i) { case 0: case 1: case 2: return 0; case 3: if (dateTime[2]==1) return 0; else return 1; case 4: case 5: case 6: case 7: case 8: case 9: return 0; } } unsigned short int dateMax(int i) { switch(i) { case 0: case 1: return 9; case 2: return 1; case 3: if (dateTime[2]==1) return 2; else return 9; case 4: return 3; case 5: return 9; case 6: return 2; case 7: return 9; case 8: return 5; case 9: return 9; } } unsigned short int dateAddr(int i) { switch(i) { case 0: return 0; case 1: return 1; case 2: return 3; case 3: return 4; case 4: return 6; case 5: return 7; case 6: return 11; case 7: return 12; case 8: return 14; case 9: return 15; } } void print_menu() { int m1=(menuState & 0xf0)>>4; int m2=menuState & 0x0f; unsigned long l; unsigned char c, d; int i; unsigned int j; unsigned char *fp; switch(m1){ case 0x0: if(m2==0) { println0("Samtal: xxx"); print((nbr_log % 10)+48,0,10); print(((nbr_log / 10)%10)+48,0,9); print((nbr_log / 100)+48,0,8); print_date(dateTime,1); } else { println1("Ring ring!!!"); l=find_contact(log_nbr); if(l==0x40) println0(log_nbr); else { print_from_mem(l+0x80010,0,0,14); print(0x20,0,14); print(0x20,0,15); } fp=(unsigned char *) l+0x8001E; c=*fp; set_latch(c & 0xF0); d=(c & 7); if(d) play_sound(d); else wait(0xffffffff); set_latch(0); menuState=0x0; print_menu(); } break; case 0x1: decode_log(cur_log); l=find_contact(log_nbr); if(l==0x40) println0(log_nbr); else { print_from_mem(l+0x80010,0,0,14); print(0x20,0,14); print(0x20,0,15); } print_date(log_date,1); break; case 0x2: if(m2) { i=m2-1; print(dateTime[i]+48,1,dateAddr(i)); show_cursor(1,dateAddr(i)); } else { println0("Datum/Tid"); print_date(dateTime,1); } break; case 0x3: if(m2) { print_from_mem(curContact*0x20+0x80210,0,0,14); print_from_mem(curContact*0x20+0x80200,1,0,16); } else { curContact=0; println0("Telefonbok"); println1("0000 nummer"); j=nbr_contacts(); for(i=3;i>=0;i--) { c=(j % 10)+48; print(c,1,i); j=j/10; } } break; case 0x4: println0("JukeBox (x/7)"); print(m2+48,0,12); l=m2; print_from_mem(((l+8)<<16),1,0,16); break; } } /* Check what Number Chunk address a phone number can be found at */ unsigned long find_contact(char *number) { unsigned char *flashp, *fp; unsigned int nbrNumbers; unsigned int i, j, eq; nbrNumbers=nbr_contacts(); i=0; flashp=(unsigned char *) 0x80200; while (i>3; /* Return 1/0 */ } /*** LCD ***/ void init_lcd() { wait_lcd(); *lcdc=0x38; /* 8-bit data transfer and address type b */ clr_lcd(); wait_lcd(); *lcdc=0x0c; /* Turn on */ wait_lcd(); *lcdc=0x06; /* Increment address counter on write */ } void hide_cursor() { wait_lcd(); *lcdc=0x0c; } void show_cursor(short int row, short int pos) { unsigned char b; unsigned short int i; i = row<<6; i += pos; if(i<16 || (i>=0x40 && i<=0x4F)) { do { b = *lcdc; }while (b & 0x80); if(b!=i) { *lcdc = i+0x80; wait_lcd(); } } *lcdc = 0x0d; } void clr_lcd() { wait_lcd(); *lcdc=0x01; } void wait_lcd() { while ((*lcdc & 0x80) == 0x80); } void println0(char s[]) { int i = 0; wait_lcd(); *lcdc=0x80; /*set adresscounter to 0x00*/ while(i<16 && s[i]!='\0') { wait_lcd(); *lcdd=s[i]; i++; } for(i;i<16;i++) { wait_lcd(); *lcdd=0x20; } } void println1(char s[]) { int i = 0; wait_lcd(); *lcdc=0xC0; /*set adresscounter to 0x40*/ while(i<16 && s[i]!='\0') { wait_lcd(); *lcdd=s[i]; i++; } for(i;i<16;i++) { wait_lcd(); *lcdd=0x20; } } void printhex(unsigned long int l, unsigned short int row) { unsigned short int i; unsigned short int v; unsigned char t[] = "Hex: 0x00000000"; for(i=15;i>=8;i--) { v=(unsigned short) (l & 15); if(v<10) t[i]=(unsigned char)(v+48); else t[i]=(unsigned char)(v+55); l=l>>4; } if(row==0) { println0(t); }else { println1(t); } } void print_date(unsigned char d[], unsigned short int row) { int i; if(row==0) println0("yy-mm-dd hh:mm"); else println1("yy-mm-dd hh:mm"); for(i=0;i<10;i++) { print(d[i]+48,row,dateAddr(i)); } } void printbyte(unsigned short int b, unsigned short int row) { unsigned short int i; unsigned short int s; unsigned char l[] = "Byte: "; s=0x80; for(i=0;i<8;i++) { if(b&s) l[6+i]='1'; else l[6+i]='0'; s=s>>1; } if(row==0) { println0(l); }else { println1(l); } } void print(unsigned char c, unsigned short int row, unsigned short int pos) { unsigned char b; unsigned short int i; i = row<<6; i += pos; if(i<16 || (i>=0x40 && i<=0x4F)) { do { b = *lcdc; }while ((b & 0x80) == 0x80); if(b!=i) { *lcdc = i+0x80; wait_lcd(); } *lcdd = c; } } void print_from_mem(unsigned long addr, unsigned short int row, unsigned short int pos, int nbrChars) { int i; unsigned char *fp; fp=(unsigned char *)addr; for(i=0;i