// main.c
// The main c file.
//
-// 17.07.2017
-// Copyright (C) 2014-2017 Balthasar Szczepański
+// 03.05.2020
+// Copyright (C) 2014-2017, 2020 Balthasar Szczepański
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
#include "msp430.h"
#include "definitions.h"
- unsigned char inbuf[8];
- unsigned char outbuf[8] __attribute__ ((aligned (2)));
- unsigned char dispvalue[4];
- volatile unsigned char time[8];
- unsigned char leap;
- unsigned char settime[3];
- volatile unsigned char mode;
+ unsigned char calcdata[8] __attribute__ ((aligned (2))); //data for calculator operation
+ unsigned char inbuf[8]; //SPI input buffer
+ unsigned char outbuf[8]; //SPI output buffer
+ unsigned char dispvalue[10]; //data to display
+ unsigned char forcedisp[5]={0,0,0,0,0}; //forcing the display
+ unsigned char time[8];
+ unsigned char leap; //leap year
+ unsigned char step; //constant count 0 1 2 3 0 1 2 3 ...
+ unsigned char settime[3]; //for editing values
+ unsigned char limit[3]; //limits for editing
+ unsigned char decimal; //if edited value is BCD
+ volatile unsigned char mode; //main state
unsigned char alarm[3];
- unsigned char lastcdn[2];
+ unsigned char lastcdn[2]; //last countdown
unsigned char lastyear[5];
- unsigned char digit;
- unsigned char changed;
- unsigned char run;
+ unsigned char digit; //currently selected digit
+ unsigned char changed; //changed value during edit
+ unsigned char run; //switch used in some states
+ unsigned char cont; //continued calculation
+
+ //for RS232 receiving
+ volatile unsigned char rxbyte=0;
+ volatile unsigned char rxcount=0;
+ volatile unsigned char rxind=0;
+ volatile unsigned char rxpin;
+ volatile unsigned char rxbuf[RXBUFSIZE];
+ unsigned char rxdata[RXDATASIZE];
+ unsigned char rxcmd;
+
+ volatile unsigned char event=0;
+
const unsigned char symbol[16] ={
SYMB_0,
SYMB_1,
SYMB_F};
__interrupt void P2_ISR();
+ __interrupt void TA0_ISR();
+
+ void gettime(void);
+ void exec(void);
+ void enter(void);
+ void leave(void);
+ void showvalue(void);
+
void display(
unsigned char *data);
void spi(
unsigned char *inbuf,
unsigned char *outbuf,
unsigned short n);
+
int main( void );
void display(unsigned char *data)
for(i=0;i<255;++i); //looks like the RTC might not like another SPI transmission exactly before the previous one, sometimes.
}
- #pragma vector=PORT2_VECTOR
- __interrupt void P2_ISR()
+ // interrupt for timer A
+ // timing for RS232 sampling
+ #pragma vector=TIMERA0_VECTOR
+ __interrupt void TA0_ISR()
{
- if(P2IFG&0x08) // RTC
- {
- P2IFG &= ~0x08;
- spi(RTC_READ,0x00,inbuf,outbuf,8);
+ rxpin = P2IN & 0x10; //quickly capture state of P2.4
- time[0]=inbuf[0]; //1/100 s
- time[1]=inbuf[1]&0x7f; //seconds
- time[2]=inbuf[2]&0x7f; //minutes
- time[3]=inbuf[3]&0x3f; //hours
- time[4]=inbuf[4]&0x07; //dow
- time[5]=inbuf[5]&0x3f; //dom
- time[6]=inbuf[6]&0x1f; //mon
- time[7]=inbuf[7];//year
- leap=inbuf[6]&0x20;
-
- spi(RTC_READ,0x0f,inbuf,outbuf,1); // <- because of RTC bug (probably not needed anymore?)
- if(!((time[2]^alarm[1])|(time[3]^alarm[2])) && alarm[0])
- {
- mode=MODE_ALARM;
- alarm[0]=0; //alarm removed after activated
- spi(RTC_WRITE,0x20,inbuf,alarm,1);
- }
-
- if(mode==MODE_COUNTUP && run)
+ TACCTL0 &= ~CCIFG;
+
+ ++rxcount;
+
+ if (!(rxcount & 0x01)) //only every second count
+ {
+ if (rxcount == 2) //start bit
{
- if(settime[1]<0x59)
- settime[1]=bcd_add_byte(settime[1],0x01);
- else
+ if (rxpin) //start fail
{
- settime[1]=0x00;
- settime[2]=bcd_add_byte(settime[2],0x01);
+ rxcount = 0;
+ TACCTL0 &= ~CCIE; //abort
}
}
- else if(mode==MODE_COUNTDOWN && run && (settime[1]|settime[2]))
+ else if (rxcount >= 20) //stop bit
{
- if(settime[1])
- settime[1]=bcd_add_byte(settime[1],0x99);
- else
+ if (rxpin) //correct stop bit
{
- settime[1]=0x59;
- settime[2]=bcd_add_byte(settime[2],0x99);
+ if (rxbyte == 0x0d || rxbyte == 0x0a) // CR or NL, end of frame
+ {
+ if(rxind)
+ {
+ rxind = 0;
+ event |= EVENT_RS; //signal
+ }
+ }
+ else
+ {
+ if (rxbyte >= 'g' && rxbyte <= 'z') //new command
+ {
+ rxind=0;
+ }
+ if (rxind < RXBUFSIZE) //still place in buffer
+ {
+ rxbuf[rxind] = rxbyte; //put byte to buffer
+ ++rxind;
+ }
+ }
}
+ rxcount = 0;
+ TACCTL0 &= ~CCIE; //stop receiving
}
-
- if (mode==MODE_ALARM || (mode==MODE_COUNTDOWN && !(settime[1]|settime[2])))
- {
- TACTL^=MC_1;
- //P2DIR^=0x40;
- //P2SEL^=0x40;
- }
- else if(TACTL & MC_3)
+ else //receive single bit
{
- TACTL&= ~MC_3;
- //P2DIR&= ~0x40;
- //P2SEL&= ~0x40;
+ rxbyte >>= 1;
+ rxbyte |= rxpin ? 0x80 : 0x00;
}
+ }
+ if(event)
+ _BIC_SR_IRQ(OSCOFF|CPUOFF|SCG1|SCG0);
+ return;
+ }
+
+ #pragma vector=PORT2_VECTOR
+ __interrupt void P2_ISR()
+ {
+ if(P2IFG&0x08) // RTC
+ {
+ P2IFG &= ~0x08;
+ event |= EVENT_RTC;
+ }
+ else if(P2IFG&0x02) // button A
+ {
+ P2IFG &= ~0x02;
+ event |= EVENT_A;
+ }
+ else if(P2IFG&0x01) // button B
+ {
+ P2IFG &= ~0x01;
+ event |= EVENT_B;
+ }
+ else if(P2IFG&0x20) // button C
+ {
+ P2IFG &= ~0x20;
+ event |= EVENT_C;
+ }
+ else if(P2IFG&0x10) // RS232
+ {
+ P2IFG &= ~0x10;
- lastyear[4]=(time[7]==0x00 && lastyear[0]==0x99)?bcd_add_byte(lastyear[1],0x01):lastyear[1];
- if (time[7]!=lastyear[0])
+ if(!rxcount) //start bit detected
{
- if(time[7]==lastyear[2])
- ++(lastyear[3]);
- else
- lastyear[3]=0;
-
- lastyear[2]=time[7];
+ TACTL |= TACLR; //reset timer
+ TACCTL0 &= ~CCIFG; //clear any waiting timer interrupt
+ TACCTL0 |= CCIE; //enable timer interrupts
- if(lastyear[3]>55)
- {
- lastyear[3]=0;
-
- if(time[7]==0x00 && lastyear[0]==0x99)
- lastyear[1]=bcd_add_byte(lastyear[1],0x01);
-
- lastyear[0]=time[7];
-
- outbuf[0]=ALARMVALUE;
- outbuf[1]=lastyear[0];
- outbuf[2]=lastyear[1];
- spi(RTC_WRITE,0x26,inbuf,outbuf,3);
- }
+ rxcount = 1;
+ rxbyte = 0;
}
+ }
+ else
+ P2IFG=0;
+
+ if(event)
+ _BIC_SR_IRQ(OSCOFF|CPUOFF|SCG1|SCG0); //escaoe low power mode
+ return;
+ }
+
+void gettime(void)
+{
+ P2IFG &= ~0x08;
+
+ //get latest time from RTC
+ spi(RTC_READ,0x00,inbuf,outbuf,8);
+
+ time[0]=inbuf[0]; //1/100 s
+ time[1]=inbuf[1]&0x7f; //seconds
+ time[2]=inbuf[2]&0x7f; //minutes
+ time[3]=inbuf[3]&0x3f; //hours
+ time[4]=inbuf[4]&0x07; //dow
+ time[5]=inbuf[5]&0x3f; //dom
+ time[6]=inbuf[6]&0x1f; //mon
+ time[7]=inbuf[7];//year
+ leap=inbuf[6]&0x20;
+
+ step = (time[1]&0x03)^((time[1]&0x10)?0x02:0x00);
+
+
+ spi(RTC_READ,0x0f,inbuf,outbuf,1); // <- because of RTC bug (probably not needed anymore?)
+
+ //check if trigger alarm
+ if(!((time[2]^alarm[1])|(time[3]^alarm[2])) && alarm[0])
+ {
+ mode=MODE_ALARM;
+ alarm[0]=0; //alarm removed after activated
+ spi(RTC_WRITE,0x20,inbuf,alarm,1);
+ }
+
+
+ //code to deal with centuries, functionality missing from RTC
+ //has to avoid accidentally reacting in case of transmission error
+
+ lastyear[4]=(time[7]==0x00 && lastyear[0]==0x99)?bcd_add_byte(lastyear[1],0x01):lastyear[1];
+ if (time[7]!=lastyear[0])
+ {
+ if(time[7]==lastyear[2])
+ ++(lastyear[3]);
+ else
+ lastyear[3]=0;
+
+ lastyear[2]=time[7];
+
+ if(lastyear[3]>55)
+ {
+ lastyear[3]=0;
+ if(time[7]==0x00 && lastyear[0]==0x99)
+ lastyear[1]=bcd_add_byte(lastyear[1],0x01);
- if(mode==MODE_DEBUG && changed)
- spi(RTC_READ,settime[1],settime,outbuf,1);
+ lastyear[0]=time[7];
- if(mode==MODE_RESET && P2IN&0x02 && P2IN&0x01 && P2IN&0x20) {
- WDTCTL = ALARMVALUE;
- }
- }
- else if(P2IFG&0x02) // button A
+ outbuf[0]=ALARMVALUE;
+ outbuf[1]=lastyear[0];
+ outbuf[2]=lastyear[1];
+ spi(RTC_WRITE,0x26,inbuf,outbuf,3);
+ }
+ }
+
+}
+
+void leave (void) //to execute when leaving an edit state
+{
+ switch (mode)
+ {
+ case MODE_EDIT | MODE_SETCALCOPER:
+ calcdata[6] &= ~0xc0;
+ calcdata[6] |= settime[0]<<6;
+ mode=MODE_EDIT | MODE_SETCALCNUM;
+ break;
+ case MODE_EDIT | MODE_SETCALCNUM:
+ if (run)
{
- P2IFG &= ~0x02;
- switch(mode)
+ if(cont != 0xff) //skip if triggered externally
{
- case MODE_CALCSETNUM:
- case MODE_CALCSETOPER:
- mode=MODE_CALC;
- break;
- case MODE_CALC:
- if(outbuf[7] || outbuf[1]!=0 || outbuf[0]!=0)
+ calcdata[2]=settime[0];
+ calcdata[3]=settime[1];
+ if ((settime[1] & 0xF0)==0xA0) //minus sign encoded as 0xA
{
- outbuf[7]=0x00;
- outbuf[6]=0x00;
- outbuf[3]=0x00;
- outbuf[2]=0x00;
- outbuf[1]=0x00;
- outbuf[0]=0x00;
+ calcdata[6] |= 0x04;
+ calcdata[3] &= 0x0f;
}
- else
- mode=MODE_TIME;
- break;
- case MODE_TIME:
- case MODE_SETDATE:
- case MODE_SETYEAR:
- mode=MODE_DATE;
- break;
- case MODE_DATE:
- mode=MODE_COUNTUP;
- settime[1]=0x00;
- settime[2]=0x00;
- run=0;
+ if (settime[2]) //decimal point
+ calcdata[6] |= 0x08;
+ }
+ switch(calcdata[6]&0xc0)
+ {
+ case 0xc0:
+ calc_div(calcdata);
break;
- case MODE_COUNTUP:
- if(run)
- {
- settime[1]=0x00;
- settime[2]=0x00;
- run=0;
- }
- else
- {
- mode=MODE_SETCOUNTDOWN;
- settime[1]=lastcdn[0];
- settime[2]=lastcdn[1];
- changed=0;
- digit=3;
- }
+ case 0x80:
+ calc_mul(calcdata);
break;
- case MODE_DEBUGADDR:
- settime[1]=settime[2];
- case MODE_DEBUGVAL:
- spi(RTC_READ,settime[1],settime,outbuf,1);
- mode=MODE_DEBUG;
+ case 0x40:
+ calcdata[6]^=0x04;
+ calc_add(calcdata);
+ calcdata[6]^=0x04;
break;
- case MODE_DEBUG:
- case MODE_RESET:
- mode=MODE_RESET;
+ case 0x00:
+ calc_add(calcdata);
break;
- case MODE_SETCOUNTDOWN:
- case MODE_COUNTDOWN:
- if(changed || mode==MODE_COUNTDOWN)
- {
- mode=MODE_SETCOUNTDOWN;
- settime[1]=lastcdn[0];
- settime[2]=lastcdn[1];
- changed=0;
- digit=3;
- break;
- }
default:
- mode=MODE_TIME;
- break;
+ calcdata[7]=0xff;
}
+ mode=MODE_CALC;
}
- else if(P2IFG&0x01) // button B
+ else
{
- P2IFG &= ~0x01;
+ calcdata[4]=settime[0];
+ calcdata[5]=settime[1];
+ calcdata[6] &= ~0x30;
+ if ((settime[1] & 0xF0)==0xA0) //minus sign encoded as 0xA
+ {
+ calcdata[6] |= 0x10;
+ calcdata[5] &= 0x0f;
+ }
+ if (settime[2]) //decimal point
+ calcdata[6] |= 0x20;
+ mode=MODE_EDIT | MODE_SETCALCOPER;
+ }
+ break;
+ case MODE_EDIT | MODE_SETDEBUGVAL:
+ spi(RTC_WRITE,settime[1],inbuf,settime,1);
+ mode=MODE_DEBUG;
+ break;
+ case MODE_EDIT | MODE_SETDEBUGADDR:
+ settime[1]=settime[0];
+ run=1;
+ mode=MODE_DEBUG;
+ break;
+ case MODE_EDIT | MODE_SETCALIB:
+ spi(RTC_WRITE,0x09,inbuf,settime,1);
+ outbuf[0]=time[3]|(settime[1]?0x80:0x00);
+ spi(RTC_WRITE,0x03,inbuf,outbuf,1);
+ mode=MODE_CALIB;
+ break;
+ case MODE_EDIT | MODE_SETDOWN:
+ lastcdn[0]=settime[0];
+ lastcdn[1]=settime[1];
+
+ outbuf[0]=ALARMVALUE;
+ outbuf[1]=settime[0];
+ outbuf[2]=settime[1];
+ spi(RTC_WRITE,0x23,inbuf,outbuf,3);
+
+ mode=MODE_DOWN;
+ break;
+ case MODE_EDIT | MODE_SETYEAR:
+ if(changed)
+ {
+ time[7]=settime[0];
+ spi(RTC_WRITE,0x07,inbuf,settime,1);
+
+ lastyear[0]=settime[0];
+ lastyear[1]=settime[1];
+ lastyear[2]=settime[1];
+ lastyear[3]=0;
+ lastyear[4]=settime[1];
+
+ outbuf[0]=ALARMVALUE;
+ outbuf[1]=settime[0];
+ outbuf[2]=settime[1];
+ spi(RTC_WRITE,0x26,inbuf,outbuf,3);
+ }
+ mode=MODE_DATE;
+ break;
+ case MODE_EDIT | MODE_SETDATE:
+ if (changed)
+ {
+ time[5]=settime[0]; //day
+ time[6]=settime[1]; //month
+ settime[2]=time[7]; //year
+ spi(RTC_WRITE,0x06,inbuf,settime+1,2); //write month and year first
+ spi(RTC_WRITE,0x05,inbuf,settime,1); //and only then the day
+ //otherwise rtc can reject the date
+ }
+ mode=MODE_DATE;
+ break;
+ case MODE_EDIT | MODE_SETALARM:
+ if(changed|| !alarm[0])
+ {
+ alarm[0]=ALARMVALUE;
+ alarm[1]=settime[0];
+ alarm[2]=settime[1];
+
+ spi(RTC_WRITE,0x20,inbuf,alarm,3);
+ }
+ else
+ {
+ alarm[0]=0;
+ spi(RTC_WRITE,0x20,inbuf,outbuf,1);
+ }
+ mode=MODE_TIME;
+ break;
+ case MODE_EDIT | MODE_SETTIME:
+ if (changed)
+ {
+ outbuf[0]=0x00;
+ outbuf[1]=0x00;
+ outbuf[2]=settime[0]&0x7f;
+ outbuf[3]=settime[1]&0x3f;
+
+ spi(RTC_WRITE,0x01,inbuf,outbuf,1);//stop osc.
+ spi(RTC_READ,0x03,inbuf,outbuf,1);
+ outbuf[3]|=(inbuf[0]&0x80);//keep the calsgn bit.
+
+ spi(RTC_WRITE,0x00,inbuf,outbuf,4);//write new time
+
+ outbuf[0]=0x80;
+ spi(RTC_WRITE,0x01,inbuf,outbuf,1);//start osc;
- switch(mode)
+ time[1]=0;
+ time[2]=settime[0];
+ time[3]=settime[1];
+ }
+ mode = MODE_TIME;
+ break;
+ }
+}
+
+void enter (void) //to execute when entering a state
+{
+ if (mode & MODE_EDIT)
+ {
+ digit = 3;
+ changed = 0;
+ limit[0]=0x59;
+ limit[1]=0x23;
+ decimal = 1;
+ switch (mode)
+ {
+ case MODE_EDIT | MODE_SETCALCOPER:
+ digit=0;
+ limit[0]=0x03;
+ settime[0] = cont ? (calcdata[6]>>6) : 0x00;
+ run = 1;
+ break;
+ case MODE_EDIT | MODE_SETCALCNUM:
+ digit=4;
+ limit[0]=0x99;
+ limit[1]=0xA9;
+ limit[2]=0x01;
+ if (run && cont)
{
- case MODE_CALCSETOPER:
- outbuf[6]&=0x3f;
- outbuf[6]|=settime[2];
- mode=MODE_CALCSETNUM;
- digit=4;
- if(changed)
- {
- settime[0]=outbuf[2];
- settime[1]=outbuf[3];
- settime[2]=(outbuf[6]&0x0c)>>2;
- }
- else
- {
- settime[0]=0x00;
- settime[1]=0x00;
- settime[2]=0x00;
- }
- changed=1;
- break;
- case MODE_CALCSETNUM:
- if(digit)
- --digit;
- else
+ settime[0] = calcdata[2];
+ settime[1] = calcdata[3];
+ settime[2] = (calcdata[6]>>2)&0x03;
+ }
+ else
+ {
+ settime[0] = 0x00;
+ settime[1] = 0x00;
+ settime[2] = 0x00;
+ }
+ break;
+ case MODE_EDIT | MODE_SETDEBUGADDR:
+ if(run)
+ {
+ settime[2] = settime[0];
+ settime[0] = settime[1];
+ }
+ else
+ {
+ settime[0] = 0x00;
+ settime[2] = 0x00;
+ }
+ case MODE_EDIT | MODE_SETDEBUGVAL:
+ digit=1;
+ limit[0]=0xff;
+ decimal=0;
+ break;
+ case MODE_EDIT | MODE_SETYEAR:
+ limit[0]=0x99;
+ limit[1]=0x99;
+ settime[0] = time[7]; //year L
+ settime[1] = lastyear[4]; //year H
+ break;
+ case MODE_EDIT | MODE_SETDATE:
+ digit = 2;
+ // limit[0]=0x31;
+ // limit[1]=0x12; not needed will be dynamically done later
+ settime[0] = time[5]; //day
+ settime[1] = time[6]; //month
+ break;
+ case MODE_EDIT | MODE_SETCALIB:
+ limit[0]=0xff;
+ limit[1]=0x01;
+ decimal=0;
+ digit=2;
+ spi(RTC_READ,0x03,inbuf,outbuf,1);
+ settime[1]=(inbuf[0]&0x80)?0x01:0x00;
+ spi(RTC_READ,0x09,inbuf,outbuf,1);
+ settime[0]=inbuf[0];
+ break;
+ case MODE_EDIT | MODE_SETDOWN:
+ limit[1] = 0x99;
+ settime[0] = lastcdn[0];
+ settime[1] = lastcdn[1];
+ break;
+ case MODE_EDIT | MODE_SETALARM:
+ settime[0] = (alarm[1]>0x59 || (settime[1]&0x0f)>0x09) ? 0x00 : alarm[1];
+ settime[1] = (alarm[2]>0x59 || (settime[2]&0x0f)>0x09) ? 0x00 : alarm[2];
+ break;
+ case MODE_EDIT | MODE_SETTIME:
+ settime[0] = time[2]; //minute
+ settime[1] = time[3]; //hour
+ break;
+ }
+ }
+ else
+ {
+ switch(mode)
+ {
+ case MODE_CALC:
+ run=0;
+ break;
+ case MODE_DEBUG:
+ event |= EVENT_RTC;
+ break;
+ case MODE_VER:
+ run=0;
+ break;
+ case MODE_CALIB:
+ spi(RTC_READ,0x03,inbuf,outbuf,1);
+ settime[1]=(inbuf[0]&0x80)?0x01:0x00;
+ spi(RTC_READ,0x09,inbuf,outbuf,1);
+ settime[0]=inbuf[0];
+ break;
+ case MODE_DOWN:
+ run=0;
+ settime[0] = lastcdn[0];
+ settime[1] = lastcdn[1];
+ break;
+ case MODE_UP:
+ run=0;
+ settime[0] = 0;
+ settime[1] = 0;
+ break;
+ // default:
+ }
+ }
+}
+
+void exec (void) //execute every second
+{
+ switch(mode)
+ {
+ case MODE_RESET:
+ if(P2IN&0x02 && P2IN&0x01 && P2IN&0x20) //perform a reset when no button pressed
+ WDTCTL = ALARMVALUE;
+ break;
+ case MODE_DEBUG:
+ spi(RTC_READ,settime[1],settime,outbuf,1);
+ event |= EVENT_RTC;
+ break;
+ case MODE_DOWN:
+ if(run && (settime[1] | settime[0]))
+ {
+ if(settime[0])
+ settime[0]=bcd_add_byte(settime[0],0x99);
+ else
+ {
+ settime[0]=0x59;
+ settime[1]=bcd_add_byte(settime[1],0x99);
+ }
+ }
+ else
+ run=0;
+ break;
+ case MODE_UP:
+ if(run)
+ {
+ if(settime[0]<0x59)
+ settime[0]=bcd_add_byte(settime[0],0x01);
+ else
+ {
+ settime[0]=0x00;
+ settime[1]=bcd_add_byte(settime[1],0x01);
+ }
+ }
+ break;
+ // default:
+ }
+}
+
+void showvalue () //determine what to show on display
+{
+ unsigned char dot=0;
+ unsigned char zero=0;
+ unsigned char i;
+
+ dispvalue[4]=0;
+ dispvalue[5]=0;
+ dispvalue[6]=0;
+ dispvalue[7]=0;
+
+ if (mode == (MODE_EDIT | MODE_SETCALCOPER))
+ {
+ switch (settime[0])
+ {
+ case 3:
+ dispvalue[4] = SYMB_U;
+ dispvalue[5] = SYMB_I;
+ dispvalue[6] = SYMB_D;
+ dispvalue[7] = SYMB_NUL;
+ break;
+ case 2:
+ dispvalue[4] = SYMB_L;
+ dispvalue[5] = SYMB_U;
+ dispvalue[6] = SYMB_M2;
+ dispvalue[7] = SYMB_M1;
+ break;
+ case 1:
+ dispvalue[4] = SYMB_B;
+ dispvalue[5] = SYMB_U;
+ dispvalue[6] = SYMB_5;
+ dispvalue[7] = SYMB_NUL;
+ break;
+ case 0:
+ dispvalue[4] = SYMB_D;
+ dispvalue[5] = SYMB_D;
+ dispvalue[6] = SYMB_A;
+ dispvalue[7] = SYMB_NUL;
+ break;
+ }
+ }
+ else if (mode & MODE_EDIT)
+ {
+ dispvalue[8] = settime[0];
+ dispvalue[9] = settime[1];
+
+ switch (mode)
+ {
+ case MODE_EDIT | MODE_SETCALCNUM:
+ if ((settime[1]&0xF0) == 0xA0) //minus sign
+ dispvalue[7] = SYMB_MIN;
+ if (settime[2]) //decimal point
+ dot |= 0x02;
+ break;
+ case MODE_EDIT | MODE_SETDEBUGADDR:
+ dispvalue[6] = SYMB_A;
+ case MODE_EDIT | MODE_SETDEBUGVAL:
+ dispvalue[9]=0x00;
+ zero=2;
+ dot |= 0x03; //:
+ break;
+ case MODE_EDIT | MODE_CALIB:
+ if (settime[1] && (!(step&0x01) || digit==2))
+ dispvalue[6] = SYMB_MIN;
+ zero=2;
+ break;
+ case MODE_EDIT | MODE_SETDOWN:
+ dot |= ((step & 0x02)?0x00:002) | ((step==0 || step==3)?0x01:00);
+ break;
+ case MODE_EDIT | MODE_SETDATE:
+ dispvalue[8] = settime[1];
+ dispvalue[9] = settime[0];
+ dot |= 0x02;
+ break;
+ case MODE_EDIT | MODE_SETALARM:
+ if(!(step & 0x01))
+ dot |= 0x08;
+ case MODE_EDIT | MODE_SETTIME:
+ dot |= 0x03;
+ break;
+ }
+
+
+ if (step&0x01)
+ {
+ for(i=0; i<4; ++i)
+ {
+ if (i != digit)
{
- if(changed)
+ if(mode== (MODE_EDIT | MODE_SETDATE))
{
- outbuf[6]&=0xf3;
- outbuf[6]|=settime[2]<<2;
- outbuf[3]=settime[1];
- outbuf[2]=settime[0];
-
-
- switch(outbuf[6]&0xc0)
+ switch(i)
{
- case 0xc0:
- calc_div(outbuf);
- break;
- case 0x80:
- calc_mul(outbuf);
+ case 2:
+ dispvalue[4] = SYMB_NUL;
+ dispvalue[5] = SYMB_NUL;
break;
- case 0x40:
- outbuf[6]^=0x04;
- calc_add(outbuf);
- outbuf[6]^=0x04;
+ case 1:
+ case 0:
+ dispvalue[6+i] = SYMB_NUL;
break;
- case 0x00:
- calc_add(outbuf);
- break;
- default:
- outbuf[7]=0xff;
}
- mode=MODE_CALC;
}
else
- {
- outbuf[6]&=0xcf;
- outbuf[6]|=settime[2]<<4;
- outbuf[5]=settime[1];
- outbuf[4]=settime[0];
- mode=MODE_CALCSETOPER;
- settime[2]=0x00;
- }
- }
- break;
- case MODE_CALC:
- if(outbuf[7])
- {
- outbuf[0]=0x00;
- outbuf[1]=0x00;
- outbuf[2]=0x00;
- outbuf[3]=0x00;
- outbuf[6]=0x00;
- outbuf[7]=0x00;
- }
- else
- {
- outbuf[6]&=0xcf;
- outbuf[6]|=(outbuf[6]&0x03)<<4;
- outbuf[5]=outbuf[1];
- outbuf[4]=outbuf[0];
- mode=MODE_CALCSETOPER;
- settime[2]=outbuf[6]&0xc0;
- changed=1;
+ dispvalue[i+4] = SYMB_NUL;
}
- break;
- case MODE_TIME:
- mode=MODE_SETTIME;
- digit=3;
- changed=0;
- settime[0]=0;
- settime[1]=time[2];
- settime[2]=time[3];
- break;
- case MODE_DATE:
- mode=MODE_SETDATE;
- digit=2;
- changed=0;
- settime[0]=time[5];
- settime[1]=time[6];
- break;
- case MODE_COUNTDOWN:
- if(settime[1]==0 && settime[2]==0)
- {
- settime[1]=lastcdn[0];
- settime[2]=lastcdn[1];
- run=0;
- break;
- }
- case MODE_COUNTUP:
- run=!run;
- break;
- case MODE_SETCOUNTDOWN:
- if(digit)
- {
- --digit;
- changed=1;
- }
- else
- {
- lastcdn[0]=settime[1];
- lastcdn[1]=settime[2];
-
- outbuf[0]=ALARMVALUE;
- outbuf[1]=settime[1];
- outbuf[2]=settime[2];
- spi(RTC_WRITE,0x23,inbuf,outbuf,3);
-
- mode=MODE_COUNTDOWN;
- run=0;
- }
- break;
- case MODE_CALIBRATE:
- if(digit)
- --digit;
- else
- {
- spi(RTC_WRITE,0x09,inbuf,settime,1);
- outbuf[0]=time[3]|settime[1];
- spi(RTC_WRITE,0x03,inbuf,outbuf,1);
- digit=3;
- }
- break;
- case MODE_DEBUGADDR:
- if(digit)
- --digit;
- else
+ }
+ }
+ }
+ else
+ {
+ switch (mode)
+ {
+ case MODE_CALC:
+ if (calcdata[7])
+ {
+ dispvalue[4] = SYMB_E;
+ dispvalue[5] = SYMB_E;
+ dispvalue[6] = SYMB_E;
+ dispvalue[7] = SYMB_NUL;
+ dot |= 0x03; //:
+ }
+ else
+ {
+ dispvalue[8] = calcdata[0];
+ dispvalue[9] = calcdata[1];
+
+ if(calcdata[6] & 0x02) //decimal point
{
- spi(RTC_READ,settime[1],settime,outbuf,1);
- mode=MODE_DEBUG;
- changed=1;
+ dot |= 0x02;
+ zero=1;
}
- break;
- case MODE_DEBUGVAL:
- if(digit)
- --digit;
else
- {
- spi(RTC_WRITE,settime[1],inbuf,settime,1);
- mode=MODE_DEBUG;
- }
- break;
- case MODE_SETTIME:
- if(digit)
- {
- if(digit==3&&settime[2]>0x23)
- settime[2]&=0xf0;
- --digit;
+ zero=3;
+ if(calcdata[6] & 0x01) //minus
+ dispvalue[7] = SYMB_MIN;
+ }
+ break;
+ case MODE_RESET:
+ dispvalue[4] = SYMB_NUL;
+ dispvalue[5] = SYMB_NUL;
+ dispvalue[6] = SYMB_NUL;
+ dispvalue[7] = SYMB_NUL;
+ break;
+ case MODE_VER:
+ dispvalue[4] = SYMB_NUL;
+ dispvalue[5] = SYMB_0;
+ dispvalue[6] = SYMB_2;
+ dispvalue[7] = SYMB_NUL;
+ dot |= 0x02; //.
+ break;
+ case MODE_CALIB:
+ dispvalue[8]=settime[0];
+ dispvalue[9]=settime[1];
+ if (settime[1])
+ dispvalue[6] = SYMB_MIN;
+ zero=2;
+ break;
+ case MODE_DOWN:
+ if (!settime[0] && !settime[1])
+ {
+ dot |= 0x80; //buzz.
+ if(!run) {
+ dispvalue[4] = SYMB_g;
+ dispvalue[5] = SYMB_n;
+ dispvalue[6] = SYMB_o;
+ dispvalue[7] = SYMB_NUL;
}
- else
+ }
+ case MODE_UP:
+ zero=1;
+ case MODE_DEBUG:
+ dispvalue[8]=settime[0]; //second /value
+ dispvalue[9]=settime[1]; //minute /address
+ dot |= 0x03; //:
+ break;
+ case MODE_DATE:
+ if(step==3)
+ {
+ dispvalue[8]= time[7]; //year L
+ dispvalue[9]= lastyear[4]; //year H
+ zero=3;
+ }
+ else
+ {
+ dispvalue[8]= time[6]; //month
+ dispvalue[9]= time[5]; //day
+ dot=0x02; //.
+ zero=1;
+ }
+ break;
+ case MODE_ALARM:
+ dot |= 0x88;
+ if(step&0x01)
+ {
+ dispvalue[4] = SYMB_g;
+ dispvalue[5] = SYMB_n;
+ dispvalue[6] = SYMB_o;
+ dispvalue[7] = SYMB_NUL;
+ }
+ case MODE_TIME:
+ dispvalue[8] = time[2]; //minute
+ dispvalue[9] = time[3]; //hour
+ dot|=(step&0x01)?0x00:0x03; //:
+ zero=1;
+ break;
+ default:
+ dispvalue[8] = 0xEE;
+ dispvalue[9] = 0xEE;
+ }
+ }
+
+ dispvalue[0] = symbol[dispvalue[8]&0x0f];
+ dispvalue[1] = symbol[dispvalue[8]>>4];
+ dispvalue[2] = symbol[dispvalue[9]&0x0f];
+ dispvalue[3] = symbol[dispvalue[9]>>4];
+
+ if (alarm[0] && (mode != (MODE_EDIT | MODE_SETALARM)))
+ dot |= 0x08;
+
+ for(i=0; i<zero; ++i)
+ {
+ if(dispvalue[3-i] == SYMB_0)
+ dispvalue[3-i] = SYMB_NUL;
+ else
+ break;
+ }
+
+ for(i=0; i<4; ++i)
+ {
+ if(dispvalue[i+4])
+ dispvalue[i]=dispvalue[i+4];
+ if(dot & (1<<i))
+ dispvalue[i] &= SYMB_DOT;
+ }
+ if (dot & 0x80)
+ P2SEL ^= 0x04;
+ else
+ P2SEL &= ~0x04;
+
+}
+
+int main( void )
+{
+ unsigned char i,j;
+
+ //watchdog:
+ WDTCTL = WDTPW + WDTHOLD;
+
+ //init 7 segment display
+
+ P1OUT =0xff; //display data on p1
+ P1DIR =0xff;
+
+ P3OUT &=0x0f; //display control on p3.4-7
+ P3DIR |=0xf0;
+
+ dispvalue[0]=SYMB_NUL;
+ dispvalue[1]=SYMB_o;
+ dispvalue[2]=SYMB_o;
+ dispvalue[3]=SYMB_NUL;
+
+ display(dispvalue);
+
+ //clocking:
+
+ BCSCTL2 |= DIVM_3; //errata sheet recommends this here
+
+ DCOCTL =0x00;
+ BCSCTL1 =
+ RSEL2| //in the
+ XTS| //hi freq
+ 0; //ACLK = 6/1 MHz
+
+ #if !(defined DEBAG)
+ do
+ {
+ IFG1 &= ~OFIFG;
+ for (i = 0xFF; i > 0; --i);
+ }
+ while ((IFG1 & OFIFG));
+ #endif
+
+ BCSCTL2 =
+ SELM_2| //MCLK from XT2
+ DIVM_1| //MCLK = 6/2 MHz
+ SELS| //SMCLK from XT2
+ DIVS_0; //SMCLK = 6/1 MHz
+
+ //init SPI
+
+ P3SEL =0x0e; // SPI on p3.1, 3.2, 3.3
+ P3OUT |=0x01;
+ P3DIR |=0x01; //RTC CS on p3.0
+
+ U0CTL =
+ SWRST| //reset
+ MM| //master
+ SYNC| //SPI mode
+ CHAR; //8 bit data
+ U0TCTL=
+ CKPH| //polarity and phase
+ SSEL0|SSEL1| //SMCLK
+ STC; //3 pin mode
+ U0BR1=0x00;
+ U0BR0=0x02; //baudrate = SMCLK/2 = 3MHz
+ U0MCTL=0x00;
+ ME2|=USPIE0;
+ U0CTL &= ~SWRST;
+
+
+ //init RTC
+
+ //Looks like sometimes the first SPI reads from the RTC may be incorrect.
+ //To be sure, let's do a few redundant reads before starting the real work
+
+ #if !(defined DEBAG)
+ for (i = 0xFF; i > 0; --i)
+ spi(RTC_READ,0x00,inbuf,outbuf,1);
+ #endif
+
+ //set 24 hour mode
+ spi(RTC_READ,0x03,inbuf,outbuf,1);
+ if(inbuf[0]&0x40)
+ {
+ outbuf[0]=inbuf[0]&(~0x40);
+ spi(RTC_WRITE,0x03,inbuf,outbuf,1);
+ }
+
+ //enable battery
+ spi(RTC_READ,0x04,inbuf,outbuf,1);
+ if(!(inbuf[0]&0x08))
+ {
+ outbuf[0]=inbuf[0]|0x08; //enable battery
+ spi(RTC_WRITE,0x04,inbuf,outbuf,1);
+ }
+
+ //set control register
+ //spi(RTC_READ,0x08,inbuf,outbuf,1);
+ outbuf[0]=
+ 0x40| //squarewave enable
+ 0x04; //1Hz
+ //no hardware alarms :(
+ spi(RTC_WRITE,0x08,inbuf,outbuf,1);
+
+ //get (soft) alarm from RTC SRAM
+ spi(RTC_READ,0x20,inbuf,outbuf,3);
+
+ alarm[0]=(inbuf[0]==ALARMVALUE)?ALARMVALUE:0;
+ alarm[1]=inbuf[1];
+ alarm[2]=inbuf[2];
+
+ spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)
+
+ //get last countdown value from RTC SRAM
+ spi(RTC_READ,0x23,inbuf,outbuf,3);
+ if(inbuf[0]==ALARMVALUE)
+ {
+ lastcdn[0]=inbuf[1];
+ lastcdn[1]=inbuf[2];
+ }
+ else
+ {
+ lastcdn[0]=0;
+ lastcdn[1]=0;
+ }
+
+ spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)
+
+ //get last year value from RTC SRAM
+ spi(RTC_READ,0x26,inbuf,outbuf,3);
+ if(inbuf[0]==ALARMVALUE)
+ {
+ lastyear[0]=inbuf[1];
+ lastyear[1]=inbuf[2];
+ }
+ else
+ {
+ lastyear[0]=0x00;
+ lastyear[1]=0x20;
+ //also clear calibration
+ outbuf[0]=0x00;
+ spi(RTC_WRITE,0x09,inbuf,outbuf,1);
+ }
+ lastyear[3]=0;
+
+ //start oscillator
+ spi(RTC_READ,0x01,inbuf,outbuf,1);
+ if(!(inbuf[0]&0x80))
+ {
+ outbuf[0]=inbuf[0]|0x80;
+ spi(RTC_WRITE,0x01,inbuf,outbuf,1);
+ }
+
+ //init timer:
+ TACCR0 = 625-1; //6MHz/625 = 9600Hz (buzz. 4.8kHz)
+ TACCTL0= //also, compare, not capture
+ // CCIE| //enable interupt
+ OUTMOD_4; //toggle
+ TACTL=
+ TASSEL_1| //ACLK, 6MHz
+ ID_0| //6MHz/1
+ MC_1| //up mode
+ TACLR; //reset
+ // P2SEL|=0x04; //P2.2 timer output.
+ P2OUT &= ~0x04;
+ P2SEL &= ~0x04;
+ P2DIR |= 0x04;
+
+ // Init interrupts
+ P2IE=
+ 0x10| //p2.4 - int. from RS232
+ 0x08| //p2.3 - int. from RTC
+ 0x02| //p2.1 - int. from button A
+ 0x01| //p2.0 - int. from button B
+ 0x20; //p2.5 - int. from button C
+ P2IES|=0x01|0x02|0x20|0x10; //button int. on falling edge
+ P2IES&= ~0x08; //RTC int. on rising edge
+ P2IFG=0x00;
+
+ if(!(P2IN&0x02)) //button A pressed at start?
+ mode=MODE_CALIB;
+ else if(!(P2IN&0x01)) //button B pressed at start?
+ {
+ calcdata[0] = 0x00;
+ calcdata[1] = 0x00;
+ calcdata[2] = 0x00;
+ calcdata[3] = 0x00;
+ calcdata[4] = 0x00;
+ calcdata[5] = 0x00;
+ calcdata[6] = 0x00;
+ calcdata[7] = 0x00;
+ mode=MODE_CALC;
+ }
+ else if(!(P2IN&0x20)) //button C pressed at start?
+ mode=MODE_VER;
+ else
+ mode=MODE_TIME;
+
+ enter();
+
+ __enable_interrupt();
+
+ while(1)
+ {
+ event &= EVENTS; //to cancel undefined events
+ if(event)
+ {
+ i=0; //block state setup;
+
+ if (event & EVENT_A)
+ {
+ event &= ~ EVENT_A;
+
+ if (mode & MODE_EDIT)
{
- if(changed)
- {
- outbuf[0]=0x00;
- outbuf[1]=0x00;
- outbuf[2]=settime[1]&0x7f;
- outbuf[3]=settime[2]&0x3f;
-
- spi(RTC_WRITE,0x01,inbuf,outbuf,1);//stop osc.
- spi(RTC_READ,0x03,inbuf,outbuf,1);
- outbuf[3]|=(inbuf[0]&0x80);//keep the calsgn bit.
-
- spi(RTC_WRITE,0x00,inbuf,outbuf,4);//write new time
- outbuf[0]=0x80;
- spi(RTC_WRITE,0x01,inbuf,outbuf,1);//start osc;
-
- time[1]=0;
- time[2]=settime[1];
- time[3]=settime[2];
+ switch (mode)
+ {
+ case MODE_EDIT | MODE_SETCALCOPER:
+ case MODE_EDIT | MODE_SETCALCNUM:
+ mode = MODE_CALC;
+ break;
+ case MODE_EDIT | MODE_SETDEBUGADDR:
+ settime[0]=settime[2];
+ case MODE_EDIT | MODE_SETDEBUGVAL:
+ mode = run ? MODE_DEBUG : MODE_VER;
+ break;
+ case MODE_EDIT | MODE_SETYEAR:
+ case MODE_EDIT | MODE_SETDATE:
+ mode=MODE_DATE;
+ break;
+ case MODE_EDIT | MODE_SETDOWN:
+ if(changed)
+ break;
+ default:
+ mode=MODE_TIME;
}
- mode=MODE_TIME;
+ enter();
}
- break;
- case MODE_SETYEAR:
- if(digit)
- --digit;
else
{
- if(changed)
+ switch (mode)
{
- time[7]=settime[1];
- spi(RTC_WRITE,0x07,inbuf,settime+1,1);
-
- lastyear[0]=settime[1];
- lastyear[1]=settime[2];
- settime[0]=ALARMVALUE;
-
- spi(RTC_WRITE,0x26,inbuf,settime,3);
+ case MODE_CALC:
+ if (calcdata[7] || calcdata[1] || calcdata[0]) //if error on non-0
+ {
+ calcdata[0]=0x00;
+ calcdata[1]=0x00;
+ calcdata[2]=0x00;
+ calcdata[3]=0x00;
+ calcdata[4]=0x00;
+ calcdata[5]=0x00;
+ calcdata[6]=0x00;
+ calcdata[7]=0x00;
+ }
+ else
+ mode = MODE_TIME;
+ break;
+ case MODE_RESET:
+ case MODE_DEBUG:
+ case MODE_VER:
+ mode = MODE_RESET;
+ break;
+ case MODE_DOWN:
+ mode = MODE_EDIT | MODE_SETDOWN;
+ case MODE_UP:
+ if(run || settime[0] || settime [1]) //reset
+ {}
+ else
+ mode = MODE_EDIT | MODE_SETDOWN;
+ break;
+ case MODE_DATE:
+ mode = MODE_UP;
+ break;
+ case MODE_TIME:
+ mode = MODE_DATE;
+ break;
+ default:
+ mode = MODE_TIME;
}
- mode=MODE_DATE;
+ enter();
}
- break;
- case MODE_SETDATE:
- if(digit)
+ }
+ else if (event & EVENT_B)
+ {
+ event &= ~ EVENT_B;
+
+ if (mode & MODE_EDIT)
{
- --digit;
- if(settime[0]>((settime[1]==0x02)?(leap?0x29:0x28):(((settime[1]&0x18) && !(settime[1]&0x01) || !(settime[1]&0x18) && (settime[1]&0x01))?0x31:0x30)))
- settime[0]&=(digit?0x00:0xf0);
- if(settime[0]==0x00)
- settime[0]=0x01;
+ if (digit)
+ {
+ switch(mode)
+ {
+ case MODE_EDIT | MODE_SETDATE:
+ if (digit==2)
+ {
+ limit[0] = (settime[1]==0x02) ?
+ (leap?0x29:0x28) :
+ (
+ (((settime[1]&0x18) && !(settime[1]&0x01)) || (!(settime[1]&0x18) && (settime[1]&0x01))) ? 0x31 : 0x30
+ );
+ if (settime[0] > (limit[0]|0xf))
+ settime[0] = 0x01;
+ }
+ break;
+ case MODE_EDIT | MODE_SETDOWN:
+ changed=1;
+ break;
+ }
+ --digit;
+ i = digit >> 1;
+ if(!(digit&0x01))
+ {
+ if ((settime[i] > limit [i]) && (mode!=(MODE_EDIT | MODE_SETDOWN))) //don't check for countdown!
+ settime[i] &= 0xf0;
+ }
+ if ((settime[i]==0) && (mode == (MODE_EDIT | MODE_SETDATE)))
+ settime[i] = 0x01;
+ }
+ else
+ {
+ leave();
+ enter();
+ }
}
else
{
- if (changed)
+ switch (mode)
{
- time[5]=settime[0];
- time[6]=settime[1];
- settime[2]=time[7];
- spi(RTC_WRITE,0x06,inbuf,settime+1,2);
- spi(RTC_WRITE,0x05,inbuf,settime,1);
+ case MODE_CALC:
+ if(calcdata[7])
+ {
+ calcdata[0]=0x00;
+ calcdata[1]=0x00;
+ calcdata[2]=0x00;
+ calcdata[3]=0x00;
+ calcdata[4]=0x00;
+ calcdata[5]=0x00;
+ calcdata[6]=0x00;
+ calcdata[7]=0x00;
+ }
+ else
+ {
+ calcdata[4]=calcdata[0];
+ calcdata[5]=calcdata[1];
+ calcdata[6]&= ~0x30;
+ calcdata[6]|=(calcdata[6]&0x03)<<4;
+ cont=1;
+ mode=MODE_EDIT | MODE_SETCALCOPER;
+ }
+ break;
+ case MODE_DEBUG:
+ case MODE_VER:
+ mode = MODE_EDIT | MODE_SETDEBUGADDR;
+ break;
+ case MODE_CALIB:
+ mode = MODE_EDIT | MODE_SETCALIB;
+ break;
+ case MODE_DOWN:
+ if(!settime[0] & !settime[1])
+ break;
+ case MODE_UP:
+ run = !run;
+ i = 1;
+ break;
+ case MODE_DATE:
+ mode = MODE_EDIT | MODE_SETDATE;
+ break;
+ case MODE_ALARM:
+ mode = MODE_TIME;
+ break;
+ case MODE_TIME:
+ mode = MODE_EDIT | MODE_SETTIME;
+ break;
+ default:
+ i = 1;
}
- mode=MODE_DATE;
+
+ if(!i)
+ enter();
}
+ }
+ else if (event & EVENT_C)
+ {
+ event &= ~ EVENT_C;
- break;
- case MODE_SETALARM:
- if(digit)
- {
- if(digit==3&&settime[2]>0x23)
- settime[2]&=0xf0;
- --digit;
- }
- else
+ if (mode & MODE_EDIT)
{
- if(changed|| !alarm[0])
+ changed = 1;
+ i = digit >> 1;
+ j = settime[i];
+ if (digit & 0x01)
{
- alarm[0]=ALARMVALUE;
- alarm[1]=settime[1];
- alarm[2]=settime[2];
-
- spi(RTC_WRITE,0x20,inbuf,alarm,3);
+ j += 0x10;
+ if (j> (limit [i] | 0x0f))
+ j &= 0x0F;
}
else
{
- alarm[0]=0;
- spi(RTC_WRITE,0x20,inbuf,outbuf,1);
+ if ((mode == (MODE_EDIT | MODE_SETDATE)) && (digit == 2))
+ {
+ j = bcd_add_byte(j,0x01);
+ if (j>0x12)
+ j=0x01;
+ }
+ else
+ {
+ j = (j&0xf0) | ((j+0x01)&0x0f);
+ if((j>limit[i]) || (decimal && ((j&0x0f)>0x09)))
+ j &= 0xF0;
+ }
+ if ((mode == (MODE_EDIT | MODE_SETDATE)) && (j == 0))
+ j = 0x01;
}
- mode=MODE_TIME;
- }
- break;
- case MODE_ALARM:
- alarm[0]=0;
- spi(RTC_WRITE,0x20,inbuf,outbuf,1);
- mode=MODE_TIME;
- break;
- case MODE_DEBUG:
- //changed=1;
- digit=1;
- settime[2]=settime[1];
- mode=MODE_DEBUGADDR;
- break;
- default:
- break;
- }
- }
- else if(P2IFG&0x20) // button C
- {
- P2IFG &= ~0x20;
-
- switch(mode)
- {
- case MODE_CALC:
- if(outbuf[7])
- {
- outbuf[0]=0x00;
- outbuf[1]=0x00;
- outbuf[2]=0x00;
- outbuf[3]=0x00;
- outbuf[6]=0x00;
- outbuf[7]=0x00;
+ settime[i] = j;
}
else
{
- mode=MODE_CALCSETNUM;
- changed=0;
- digit=4;
- settime[0]=0x00;
- settime[1]=0x00;
- settime[2]=0x00;
- }
- break;
- case MODE_CALCSETNUM:
- if (digit==4)
- settime[2]^=0x02;
- else if (digit==3)
- {
- if((settime[1]&0xf0)==0x90)
+ switch (mode)
{
- settime[1]&=0x0f;
- settime[2]|=0x01;
+ case MODE_CALC:
+ if(calcdata[7])
+ {
+ calcdata[0]=0x00;
+ calcdata[1]=0x00;
+ calcdata[2]=0x00;
+ calcdata[3]=0x00;
+ calcdata[4]=0x00;
+ calcdata[5]=0x00;
+ calcdata[6]=0x00;
+ calcdata[7]=0x00;
+ }
+ else
+ {
+ cont=0;
+ mode=MODE_EDIT | MODE_SETCALCNUM;
+ }
+ break;
+ case MODE_DEBUG:
+ mode = MODE_EDIT | MODE_SETDEBUGVAL;
+ break;
+ case MODE_DOWN:
+ if(!run && !settime[0] && !settime[1])
+ run=1;
+ settime[0]=lastcdn[0];
+ settime[1]=lastcdn[1];
+ i = 1;
+ break;
+ case MODE_UP:
+ settime[0]=0;
+ settime[1]=0;
+ i = 1;
+ break;
+ case MODE_DATE:
+ mode = MODE_EDIT | MODE_SETYEAR;
+ break;
+ case MODE_ALARM:
+ mode = MODE_TIME;
+ break;
+ case MODE_TIME:
+ mode = MODE_EDIT | MODE_SETALARM;
+ break;
+ default:
+ i = 1;
}
- else if (settime[2]&0x01)
- settime[2]&=0xfe;
- else
- settime[1]+=0x10;
+
+ if(!i)
+ enter();
}
- else
+ }
+ else if (event & EVENT_RS) //received frame
+ {
+ event &= ~ EVENT_RS;
+
+ rxcmd = rxbuf[0]; //get command
+ for(i=0; i<(RXBUFSIZE-1); ++i) //decode arguments: hex digits
{
- if ((settime[(digit&0x02)?1:0]&((digit&0x01)?0xf0:0x0f)) == ((digit&0x01)?0x90:0x09))
- settime[(digit&0x02)?1:0]&=((digit&0x01)?0x0f:0xf0);
+ j=rxbuf[i+1];
+
+ if(j>='a') //decode digits
+ j-= 87;
+ else if(j>='A')
+ j-= 55;
+ else
+ j-= 48;
+
+ if(i&0x01)
+ rxdata[i>>1] |= j&0x0f;
else
- settime[(digit&0x02)?1:0]+=((digit&0x01)?0x10:0x01);
+ rxdata[i>>1] = j<<4;
}
- break;
- case MODE_CALCSETOPER:
- settime[2]+=0x40;
- break;
- case MODE_COUNTUP:
- settime[1]=0x00;
- settime[2]=0x00;
- break;
- case MODE_COUNTDOWN:
- settime[1]=lastcdn[0];
- settime[2]=lastcdn[1];
- //changed=0;
- //mode=MODE_SETCOUNTDOWN;
- //digit=3;
- break;
- case MODE_CALIBRATE:
- if(digit==2)
- settime[1]^=0x80;
- if(digit>=2)
- break;
- case MODE_DEBUGADDR:
- case MODE_DEBUGVAL:
- settime[(mode==MODE_DEBUGADDR)?1:0]+=(digit==1?0x10:(((settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f)==0x0f)?0xf1:0x01));
- break;
- case MODE_SETTIME:
- case MODE_SETALARM:
- case MODE_SETYEAR:
- case MODE_SETCOUNTDOWN:
- changed=1;
- //these 4 lines replaced a larger switch structure
- if((settime[digit&0x02?2:1]&((digit&0x01)?0xf0:0x0f))<(digit==1?((mode==MODE_SETYEAR)?0x90:0x50):(digit==3?((mode==MODE_SETCOUNTDOWN||mode==MODE_SETYEAR)?0x90:0x20):((mode!=MODE_SETCOUNTDOWN&&mode!=MODE_SETYEAR&&digit==2&&settime[2]>0x19)?0x03:0x09))))
- settime[digit&0x02?2:1]+=((digit&0x01)?0x10:0x01);
- else
- settime[digit&0x02?2:1]&=((digit&0x01)?0x0f:0xf0);
- break;
- case MODE_SETDATE:
- changed=1;
- switch (digit)
+
+ switch (rxcmd)
{
- case 2:
- if(settime[1]<0x12)
- settime[1]=bcd_add_byte(settime[1],0x01);
- else
- settime[1]=0x01;
+ case 'g': //force display value
+ forcedisp[0]=rxdata[0];
+ forcedisp[1]=rxdata[1];
+ forcedisp[2]=rxdata[2];
+ forcedisp[3]=rxdata[3];
+ forcedisp[4]=1;
break;
- case 1:
- if((settime[0]&0xf0)<((settime[1]==0x02)?0x20:0x30))
- settime[0]+=0x10;
- else
- settime[0]&=0x0f;
+ case 'h': //free display value
+ forcedisp[4]=0;
break;
-
- case 0:
- if((settime[0]<((settime[1]==0x02)?(leap?0x29:0x28):(((settime[1]&0x18) && !(settime[1]&0x01) || !(settime[1]&0x18) && (settime[1]&0x01))?0x31:0x30))) && (settime[0]&0x0f)<0x09)
- ++settime[0];
+ case 'i': //trigger event
+ event |= rxdata[0];
+ break;
+ case 'j': //go to mode
+ mode = rxdata[0];
+ enter();
+ break;
+ case 'k': //select digit
+ digit = rxdata[0];
+ break;
+ case 'l': //value under digit
+ i = digit >> 1;
+ j = settime[i];
+ if (digit & 0x01)
+ {
+ j &= 0x0f;
+ j |= rxdata[0]<<4;
+ }
else
- settime[0]&=0xf0;
- if(settime[0]==0x00)
- settime[0]=0x01;
+ {
+ j &= 0xf0;
+ j |= rxdata[0]&0x0f;
+ }
+ settime[i] = j;
break;
- }
- break;
- case MODE_DATE:
- mode=MODE_SETYEAR;
- digit=3;
- changed=0;
-
- settime[1]=time[7];
- settime[2]=lastyear[1];
- break;
- case MODE_TIME:
- mode=MODE_SETALARM;
- digit=3;
- changed=0;
-
- settime[0]=0;
- settime[1]=alarm[1]; //get last alarm time
- if(settime[1]>0x59 || (settime[1]&0x0f)>0x09)
- settime[1]=0x00;
- settime[2]=alarm[2];
- if(settime[2]>0x23 || (settime[2]&0x0f)>0x09)
- settime[2]=0x00;
- break;
- case MODE_ALARM:
- alarm[0]=0;
- spi(RTC_WRITE,0x20,inbuf,outbuf,1);
- mode=MODE_TIME;
- break;
- case MODE_DEBUG:
- if(changed)
- {
- digit=1;
- mode=MODE_DEBUGVAL;
- }
- break;
- default:
- break;
- }
- }
- else
- P2IFG=0;
-
- switch(mode)
- {
- case MODE_CALC:
- if(outbuf[7])
- {
- dispvalue[0]=SYMB_E & SYMB_DOT;
- dispvalue[1]=SYMB_E & SYMB_DOT;
- dispvalue[2]=SYMB_E;
- dispvalue[3]=SYMB_NUL;
- }
- else
- {
- dispvalue[0]=symbol[outbuf[0]&0x0f] | (((outbuf[0]&0x0f)==0x00 && (outbuf[6]&0x02))?SYMB_NUL:SYMB_8);
- dispvalue[1]=(symbol[(outbuf[0]&0xf0)>>4] | (((outbuf[0]&0xf0)==0x00 && outbuf[1]==0x00 && !(outbuf[6]&0x02))?SYMB_NUL:SYMB_8)) & ((outbuf[6]&0x02)?SYMB_DOT:SYMB_NUL);
- dispvalue[2]=symbol[outbuf[1]&0x0f] | ((outbuf[1]==0x00 && !(outbuf[6]&0x02))?SYMB_NUL:SYMB_8);
- dispvalue[3]=(outbuf[6]&0x01)?SYMB_MIN:(symbol[(outbuf[1]&0xf0)>>4] | (((outbuf[1]&0xf0)==0x00)?SYMB_NUL:SYMB_8));
- }
- if(alarm[0])
- dispvalue[3]&=SYMB_DOT;
- break;
- case MODE_CALCSETNUM:
- dispvalue[0]=(symbol[settime[0]&0x0f] | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8));
- dispvalue[1]=(symbol[(settime[0]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & ((settime[2]&0x02)?SYMB_DOT:SYMB_NUL);
- dispvalue[2]=(symbol[settime[1]&0x0f] | ((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8));
- dispvalue[3]=(((settime[2]&0x01)?SYMB_MIN:symbol[(settime[1]&0xf0)>>4]) | ((digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & (alarm[0]?SYMB_DOT:SYMB_NUL);
- break;
- case MODE_CALCSETOPER:
- switch (settime[2] & 0xc0)
- {
- case 0xc0:
- dispvalue[0]=SYMB_U;
- dispvalue[1]=SYMB_I;
- dispvalue[2]=SYMB_D;
- dispvalue[3]=SYMB_NUL;
- break;
- case 0x80:
- dispvalue[0]=SYMB_L;
- dispvalue[1]=SYMB_U;
- dispvalue[2]=SYMB_M2;
- dispvalue[3]=SYMB_M1;
- break;
- case 0x40:
- dispvalue[0]=SYMB_B;
- dispvalue[1]=SYMB_U;
- dispvalue[2]=SYMB_5;
- dispvalue[3]=SYMB_NUL;
- break;
- default:
- dispvalue[0]=SYMB_D;
- dispvalue[1]=SYMB_D;
- dispvalue[2]=SYMB_A;
- dispvalue[3]=SYMB_NUL;
- }
- if(alarm[0])
- dispvalue[3]&=SYMB_DOT;
- break;
- case MODE_SETTIME:
- case MODE_SETALARM:
- case MODE_SETCOUNTDOWN:
- case MODE_SETYEAR:
- dispvalue[0]=(symbol[settime[1]&0x0f] | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & ((((((time[1]+0x01)&0x02)^((time[1]&0x10)>>3))&&mode==MODE_SETCOUNTDOWN)||mode==MODE_SETYEAR)?SYMB_NUL:SYMB_DOT);
- dispvalue[1]=(symbol[(settime[1]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & (((((time[1]&0x02)^((time[1]&0x10)>>3))&&mode==MODE_SETCOUNTDOWN)||mode==MODE_SETYEAR)?SYMB_NUL:SYMB_DOT);
- dispvalue[2]=(symbol[settime[2]&0x0f] | ((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) ;
- dispvalue[3]=(symbol[(settime[2]&0xf0)>>4] | ((digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & ((mode!=MODE_SETALARM && alarm[0] || mode==MODE_SETALARM && !(time[1]&0x01))?SYMB_DOT:SYMB_NUL);
- break;
- case MODE_DEBUGADDR:
- case MODE_DEBUGVAL:
- dispvalue[0]=(symbol[settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f] | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT;
- dispvalue[1]=(symbol[(settime[(mode==MODE_DEBUGADDR)?1:0]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT;
- dispvalue[2]=(mode==MODE_DEBUGADDR)?SYMB_A:SYMB_NUL;
- dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL;
- break;
- case MODE_SETDATE:
- dispvalue[0]=(symbol[settime[1]&0x0f]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8));
- dispvalue[1]=(symbol[(settime[1]&0xf0)>>4]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&SYMB_DOT;
- dispvalue[2]=(symbol[settime[0]&0x0f]|((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8));
- dispvalue[3]=(symbol[(settime[0]&0xf0)>>4]|((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&(alarm[0]?SYMB_DOT:SYMB_NUL);
- break;
- case MODE_CALIBRATE:
- dispvalue[0]=symbol[settime[0]&0x0f]|((digit!=0 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8);
- dispvalue[1]=symbol[(settime[0]&0xf0)>>4]|((digit!=1 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8);
- dispvalue[2]=(settime[1]?SYMB_MIN:SYMB_NUL)|((digit!=2 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8);
- dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL;
- break;
- case MODE_DATE:
- if((time[1]&0x03)==((time[1]&0x10)?0x01:0x03))
- {
- dispvalue[0]=symbol[time[7]&0x0f];
- dispvalue[1]=symbol[(time[7]&0xf0)>>4];
- dispvalue[2]=symbol[lastyear[4]&0x0f];
- dispvalue[3]=symbol[(lastyear[4]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL);
- }
- else
- {
- dispvalue[0]=symbol[time[6]&0x0f];
- dispvalue[1]=symbol[(time[6]&0xf0)>>4]&SYMB_DOT;
- dispvalue[2]=symbol[time[5]&0x0f];
- dispvalue[3]=((time[5]&0xf0)?symbol[(time[5]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL);
- }
- break;
- case MODE_COUNTDOWN:
- if(!(settime[1]|settime[2]))
- {
- if(!run)
- {
- dispvalue[0]=SYMB_g&SYMB_DOT;
- dispvalue[1]=SYMB_n&SYMB_DOT;
- dispvalue[2]=SYMB_o;
- dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL;
+ case 'm': //confirm editing
+ changed=1;
+ leave();
+ enter();
+ break;
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v': //enter values
+ changed = 1;
+ settime[0] = rxdata[0];
+ settime[1] = rxdata[1];
+ settime[2] = rxdata[2];
+ switch (rxcmd)
+ {
+ case 'n': //set time
+ mode = MODE_EDIT | MODE_SETTIME;
+ break;
+ case 'o': //set alarm
+ mode = MODE_EDIT | MODE_SETALARM;
+ if(settime[0]==0xff && settime[1]==0xff)
+ changed=0;
+ break;
+ case 'p': //set date
+ mode = MODE_EDIT | MODE_SETDATE;
+ break;
+ case 'q': //set year
+ mode = MODE_EDIT | MODE_SETYEAR;
+ break;
+ case 'r': //set countdown
+ mode = MODE_EDIT | MODE_SETDOWN;
+ run=0;
+ break;
+ case 's': //set calibration
+ mode = MODE_EDIT | MODE_SETCALIB;
+ break;
+ case 't': //set debug address
+ mode = MODE_EDIT | MODE_SETDEBUGADDR;
+ break;
+ case 'u': //set debug value
+ mode = MODE_EDIT | MODE_SETDEBUGVAL;
+ break;
+ case 'v': //perform calculation
+ calcdata[0]=0x00;
+ calcdata[1]=0x00;
+ calcdata[2]=rxdata[0];
+ calcdata[3]=rxdata[1];
+ calcdata[4]=rxdata[2];
+ calcdata[5]=rxdata[3];
+ calcdata[6]=rxdata[4];
+ calcdata[7]=0;
+ run = 1;
+ cont = 0xFF;
+ mode = MODE_EDIT | MODE_SETCALCNUM;
+ }
+ leave();
break;
}
- run=0;
- }
- case MODE_COUNTUP:
- dispvalue[0]=symbol[settime[1]&0x0f]&SYMB_DOT;
- dispvalue[1]=symbol[(settime[1]&0xf0)>>4]&SYMB_DOT;
- dispvalue[2]=symbol[settime[2]&0x0f];
- dispvalue[3]=((settime[2]&0xf0)?symbol[(settime[2]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL);
- break;
- case MODE_RESET:
- dispvalue[0]=SYMB_NUL;
- dispvalue[1]=SYMB_NUL;
- dispvalue[2]=SYMB_NUL;
- dispvalue[3]=SYMB_NUL;
- break;
- case MODE_DEBUG:
- if(changed)
- {
- dispvalue[0]=symbol[settime[0]&0x0f]&SYMB_DOT;
- dispvalue[1]=symbol[(settime[0]&0xf0)>>4]&SYMB_DOT;
- dispvalue[2]=symbol[settime[1]&0x0f];
- dispvalue[3]=symbol[(settime[1]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL);
- }
- else
- {
- dispvalue[0]=SYMB_NUL;
- dispvalue[1]=SYMB_6&SYMB_DOT;
- dispvalue[2]=SYMB_1;
- dispvalue[3]=SYMB_NUL&(alarm[0]?SYMB_DOT:SYMB_NUL);
}
- break;
- case MODE_ALARM:
- case MODE_TIME:
- if(((time[1]&0x01) && mode==MODE_ALARM) || (time[3]==0x04 && time[2]==0x33 && time[1]==0x00))
+ else if (event & EVENT_RTC)
{
- dispvalue[0]=SYMB_g;
- dispvalue[1]=SYMB_n;
- dispvalue[2]=SYMB_o;
- dispvalue[3]=SYMB_DOT;
- break;
+ event &= ~ EVENT_RTC;
+ gettime();
+ exec();
}
- default:
- dispvalue[0]=symbol[time[2]&0x0f]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT);
- dispvalue[1]=symbol[(time[2]&0xf0)>>4]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT);
- dispvalue[2]=symbol[time[3]&0x0f];
- dispvalue[3]=((time[3]&0xf0)?symbol[(time[3]&0xf0)>>4]:SYMB_NUL)&((alarm[0] || mode==MODE_ALARM)?SYMB_DOT:SYMB_NUL);
- break;
- }
-
- display(dispvalue);
-
-
- return;
- }
-
- int main( void )
- {
- unsigned char delay;
-
- //watchdog:
- WDTCTL = WDTPW + WDTHOLD;
-
- mode=MODE_INIT;
-
- //init 7 segment display
-
- P1OUT =0xff; //display data on p1
- P1DIR =0xff;
-
- P3OUT &=0x0f; //display control on p3.4-7
- P3DIR |=0xf0;
-
- dispvalue[0]=SYMB_NUL;
- dispvalue[1]=SYMB_o;
- dispvalue[2]=SYMB_o;
- dispvalue[3]=SYMB_NUL;
-
- display(dispvalue);
-
- //clocking:
-
- BCSCTL2 |= DIVM_3; //errata sheet recommends this here
-
- DCOCTL =0x00;
- BCSCTL1 =
- RSEL2| //in the
- XTS| //hi freq
- DIVA_1; //ACLK = 6/2 MHz
-
- #if !(defined DEBAG)
- do
- {
- IFG1 &= ~OFIFG;
- for (delay = 0xFF; delay > 0; --delay);
- }
- while ((IFG1 & OFIFG));
- #endif
-
- BCSCTL2 =
- SELM_2| //MCLK from XT2
- DIVM_1| //MCLK = 6/2 MHz
- SELS| //SMCLK from XT2
- DIVS_0; //SMCLK = 6/1 MHz
- //init SPI
-
- P3SEL =0x0e; // SPI on p3.1, 3.2, 3.3
- P3OUT |=0x01;
- P3DIR |=0x01; //RTC CS on p3.0
-
- U0CTL =
- SWRST| //reset
- MM| //master
- SYNC| //SPI mode
- CHAR; //8 bit data
- U0TCTL=
- CKPH| //polarity and phase
- SSEL0|SSEL1| //SMCLK
- STC; //3 pin mode
- U0BR1=0x00;
- U0BR0=0x02; //baudrate = SMCLK/2 = 3MHz
- U0MCTL=0x00;
- ME2|=USPIE0;
- U0CTL &= ~SWRST;
-
-
- //init RTC
-
- //Looks like sometimes the first SPI reads rom the RTC may be incorrect.
- //To be sure, let's do a few redundant reads before starting the real work
-
- #if !(defined DEBAG)
- for (delay = 0xFF; delay > 0; --delay)
- spi(RTC_READ,0x00,inbuf,outbuf,1);
- #endif
-
- //set 24 hour mode
- spi(RTC_READ,0x03,inbuf,outbuf,1);
- if(inbuf[0]&0x40)
- {
- outbuf[0]=inbuf[0]&(~0x40);
- spi(RTC_WRITE,0x03,inbuf,outbuf,1);
- }
+ showvalue();
- //enable battery
- spi(RTC_READ,0x04,inbuf,outbuf,1);
- if(!(inbuf[0]&0x08))
- {
- outbuf[0]=inbuf[0]|0x08; //enable battery
- spi(RTC_WRITE,0x04,inbuf,outbuf,1);
- }
-
- //set control register
- //spi(RTC_READ,0x08,inbuf,outbuf,1);
- outbuf[0]=
- 0x40| //squarewave enable
- 0x04; //1Hz
- //no hardware alarms :(
- spi(RTC_WRITE,0x08,inbuf,outbuf,1);
-
- //get (soft) alarm from RTC SRAM
- spi(RTC_READ,0x20,inbuf,outbuf,3);
-
- alarm[0]=(inbuf[0]==ALARMVALUE)?ALARMVALUE:0;
- alarm[1]=inbuf[1];
- alarm[2]=inbuf[2];
-
- spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)
-
- //get last countdown value from RTC SRAM
- spi(RTC_READ,0x23,inbuf,outbuf,3);
- if(inbuf[0]==ALARMVALUE)
- {
- lastcdn[0]=inbuf[1];
- lastcdn[1]=inbuf[2];
- }
- else
- {
- lastcdn[0]=0;
- lastcdn[1]=0;
- }
-
- spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)
-
- //get last year value from RTC SRAM
- spi(RTC_READ,0x26,inbuf,outbuf,3);
- if(inbuf[0]==ALARMVALUE)
- {
- lastyear[0]=inbuf[1];
- lastyear[1]=inbuf[2];
- }
- else
- {
- lastyear[0]=0x00;
- lastyear[1]=0x20;
- //also clear calibration
- outbuf[0]=0x00;
- spi(RTC_WRITE,0x09,inbuf,outbuf,1);
- }
- lastyear[3]=0;
-
- //start oscillator
- spi(RTC_READ,0x01,inbuf,outbuf,1);
- if(!(inbuf[0]&0x80))
- {
- outbuf[0]=inbuf[0]|0x80;
- spi(RTC_WRITE,0x01,inbuf,outbuf,1);
- }
-
- //init timer:
- TACCR0 = 375-1; //3MHz/375/2=4kHz
- TACCTL0= //also, compare, not capture
- OUTMOD_4; //toggle
- TACTL=
- TASSEL_1| //ACLK, 3MHz
- ID_0| //3MHz/1
- //MC_1| //up mode
- TACLR; //reset
- P2SEL|=0x04; //P2.2 timer output.
- P2DIR|=0x04;
-
- // Init interrupts
- P2IE=
- 0x08| //p2.3 - int. from RTC
- 0x02| //p2.1 - int. from button A
- 0x01| //p2.0 - int. from button B
- 0x20; //p2.5 - int. from button C
- P2IES|=0x01|0x02|0x20; //button int. on falling edge
- P2IES&= ~0x08; //RTC int. on rising edge
- P2IFG=0x00;
-
- if(!(P2IN&0x02)) //button A pressed at start?
- {
- mode=MODE_CALIBRATE;
- spi(RTC_READ,0x03,inbuf,outbuf,1);
- settime[1]=inbuf[0]&0x80;
- spi(RTC_READ,0x09,inbuf,outbuf,1);
- settime[0]=inbuf[0];
- digit=3;
- }
- else if(!(P2IN&0x01)) //button B pressed at start?
- {
- mode=MODE_CALC;
- outbuf[0]=0x00;
- outbuf[1]=0x00;
- outbuf[2]=0x00;
- outbuf[3]=0x00;
- outbuf[6]=0x00;
- outbuf[7]=0x00;
+ display(forcedisp[4]?forcedisp:dispvalue);
}
- else if(!(P2IN&0x20)) //button C pressed at start?
+ else //go to low power mode if nothing's going on
{
- mode=MODE_DEBUG;
- settime[1]=0x00;
- changed=0;
- }
- else
- mode=MODE_TIME;
-
- __enable_interrupt();
-
-
- while(1)
- {
- switch(mode)
- {
- case MODE_DEBUG:
- P2IFG|=0x08;
- case MODE_DEBUGADDR:
- case MODE_DEBUGVAL:
- break;
- default:
- lpm3();
- break;
- }
+ lpm3();
}
}
+}