]> bicyclesonthemoon.info Git - staf/staf/commitdiff
First version. v1.0
authorb <rowerynaksiezycu@gmail.com>
Wed, 25 Mar 2015 18:42:12 +0000 (19:42 +0100)
committerb <rowerynaksiezycu@gmail.com>
Wed, 25 Mar 2015 18:42:12 +0000 (19:42 +0100)
.gitignore [new file with mode: 0644]
definitions.h [new file with mode: 0644]
main.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..f039d96
--- /dev/null
@@ -0,0 +1,2 @@
+*.a43
+
diff --git a/definitions.h b/definitions.h
new file mode 100644 (file)
index 0000000..bc5b5b4
--- /dev/null
@@ -0,0 +1,68 @@
+//RTC commands:\r
+#define RTC_EEREAD  0x03\r
+#define RTC_EEWRITE 0x02\r
+#define RTC_EEWRDI  0x04\r
+#define RTC_EEWREN  0x06\r
+#define RTC_SRREAD  0x05\r
+#define RTC_SRWRITE 0x01\r
+#define RTC_READ    0x13\r
+#define RTC_WRITE   0x12\r
+#define RTC_UNLOCK  0x14\r
+#define RTC_IDWRITE 0x32\r
+#define RTC_IDREAD  0x33\r
+#define RTC_CLRRAM  0x54\r
+\r
+//SPI function flags:\r
+#define ADDRFLAG  0x01\r
+#define WRITEFLAG 0x02\r
+#define READFLAG  0x04\r
+\r
+//7 segment display\r
+\r
+#define SEG_A 0xdf\r
+#define SEG_B 0xef //    aaaa\r
+#define SEG_C 0xbf //   f    b\r
+#define SEG_D 0x7f //   f    b\r
+#define SEG_E 0xfd //hh  gggg\r
+#define SEG_F 0xfb //   e    c\r
+#define SEG_G 0xf7 //   e    c\r
+#define SEG_H 0xfe //    dddd \r
+\r
+#define SYMB_0   (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F        )\r
+#define SYMB_1   (        SEG_B & SEG_C                                )\r
+#define SYMB_2   (SEG_A & SEG_B         & SEG_D & SEG_E         & SEG_G)\r
+#define SYMB_3   (SEG_A & SEG_B & SEG_C & SEG_D                 & SEG_G)\r
+#define SYMB_4   (        SEG_B & SEG_C                 & SEG_F & SEG_G)\r
+#define SYMB_5   (SEG_A         & SEG_C & SEG_D         & SEG_F & SEG_G)\r
+#define SYMB_6   (SEG_A         & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G)\r
+#define SYMB_7   (SEG_A & SEG_B & SEG_C                                )\r
+#define SYMB_8   (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G)\r
+#define SYMB_9   (SEG_A & SEG_B & SEG_C                 & SEG_F & SEG_G)\r
+#define SYMB_A   (SEG_A & SEG_B & SEG_C         & SEG_E & SEG_F & SEG_G)\r
+#define SYMB_B   (                SEG_C & SEG_D & SEG_E & SEG_F & SEG_G)\r
+#define SYMB_C   (                        SEG_D & SEG_E         & SEG_G)\r
+#define SYMB_D   (        SEG_B & SEG_C & SEG_D & SEG_E         & SEG_G)\r
+#define SYMB_E   (SEG_A                 & SEG_D & SEG_E & SEG_F & SEG_G)\r
+#define SYMB_F   (SEG_A                         & SEG_E & SEG_F & SEG_G)\r
+#define SYMB_NUL (0xFF)\r
+#define SYMB_o   (SEG_A & SEG_B                         & SEG_F & SEG_G)\r
+#define SYMB_n   (SEG_A & SEG_B                         & SEG_F        )\r
+#define SYMB_g   (SEG_A & SEG_B & SEG_C & SEG_D         & SEG_F & SEG_G)\r
+#define SYMB_MIN (                                                SEG_G)\r
+#define SYMB_DOT (SEG_H)\r
+\r
+//operation modes\r
+#define MODE_INIT 0\r
+#define MODE_TIME 1\r
+#define MODE_SETTIME 2\r
+#define MODE_SETALARM 3\r
+#define MODE_ALARM 4\r
+#define MODE_DATE 5\r
+#define MODE_SETDATE 6\r
+#define MODE_SETYEAR 7\r
+#define MODE_COUNTUP 8\r
+#define MODE_SETCOUNTDOWN 9\r
+#define MODE_COUNTDOWN 10\r
+#define MODE_CALIBRATE 11\r
+\r
+#define ALARMVALUE 0xa5
\ No newline at end of file
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..a15d25c
--- /dev/null
+++ b/main.c
@@ -0,0 +1,736 @@
+#include "msp430.h"\r
+#include "definitions.h"\r
+\r
+unsigned char inbuf[8];\r
+unsigned char outbuf[8];\r
+unsigned char dispvalue[4];\r
+unsigned char time[8];\r
+unsigned char leap;\r
+unsigned char settime[3];\r
+unsigned char mode;\r
+unsigned char alarm[3];\r
+unsigned char digit;\r
+unsigned char changed;\r
+unsigned char run;\r
+unsigned char symbol[16] ={\r
+  SYMB_0,\r
+  SYMB_1,\r
+  SYMB_2,\r
+  SYMB_3,\r
+  SYMB_4,\r
+  SYMB_5,\r
+  SYMB_6,\r
+  SYMB_7,\r
+  SYMB_8,\r
+  SYMB_9,\r
+  SYMB_A,\r
+  SYMB_B,\r
+  SYMB_C,\r
+  SYMB_D,\r
+  SYMB_E,\r
+  SYMB_F};\r
+\r
+__interrupt void P2_ISR();\r
+void display(\r
+  unsigned char *data);\r
+void spi(\r
+  unsigned char command,\r
+  unsigned char addr,\r
+  unsigned char *inbuf,\r
+  unsigned char *outbuf,\r
+  unsigned short n);\r
+int main( void );\r
+\r
+void display(unsigned char *data)\r
+{\r
+  //lsd\r
+  P1OUT =data[0];\r
+  P3OUT |=0x80; //74hc373 latch enable\r
+  P3OUT &=0x0f;\r
+  \r
+  P1OUT =data[1];\r
+  P3OUT |=0x40;\r
+  P3OUT &=0x0f;\r
+  \r
+  P1OUT =data[2];\r
+  P3OUT |=0x20;\r
+  P3OUT &=0x0f;\r
+  \r
+  //msd\r
+  P1OUT =data[3];\r
+  P3OUT |=0x10;\r
+  P3OUT &=0x0f;\r
+}\r
+\r
+void spi(\r
+  unsigned char command,\r
+  unsigned char addr,\r
+  unsigned char *inbuf,\r
+  unsigned char *outbuf,\r
+  unsigned short n)\r
+{\r
+  unsigned short i;\r
+  unsigned char nul;\r
+  unsigned char flags;\r
+  \r
+  switch (command)\r
+  {\r
+  case RTC_EEREAD:\r
+  case RTC_IDREAD:\r
+  case RTC_READ:\r
+    flags= ADDRFLAG|READFLAG;\r
+    break;\r
+    \r
+  case RTC_EEWRITE:\r
+  case RTC_IDWRITE:\r
+    n=(n>8)?8:n;\r
+  case RTC_WRITE:\r
+    flags= ADDRFLAG|WRITEFLAG;\r
+    break;\r
+    \r
+  case RTC_EEWREN:\r
+  case RTC_EEWRDI:\r
+    flags=0;\r
+    break;\r
+    \r
+  case RTC_SRREAD:\r
+    n=(n>1)?1:n;\r
+    flags=READFLAG;\r
+    break;\r
+  \r
+  case RTC_SRWRITE: //1\r
+  case RTC_CLRRAM: //data ignored but has to be\r
+  case RTC_UNLOCK: //1\r
+     n=(n>1)?1:n;\r
+    flags=WRITEFLAG;\r
+    break;\r
+  default:\r
+    return;\r
+  }\r
+  \r
+  P3OUT&=0xfe; //chip select down\r
+   \r
+  while((IFG2&UTXIFG0)==0); // wait until can be sent\r
+  U0TXBUF=command; // send command\r
+  while((IFG2&UTXIFG0)==0); // wait until received\r
+  nul=U0RXBUF; //pretend to read "data"\r
+  \r
+  if(flags&ADDRFLAG)\r
+  {\r
+    while((IFG2&UTXIFG0)==0); // wait until can be sent\r
+    U0TXBUF=addr; // send address\r
+    while((IFG2&UTXIFG0)==0); // wait until received\r
+    nul=U0RXBUF; //pretend to read "data"\r
+  }\r
+  if(flags&(READFLAG|WRITEFLAG))\r
+  {\r
+    for(i=0;i<n;++i)\r
+    {\r
+      while((IFG2&UTXIFG0)==0); // wait until can be sent\r
+      U0TXBUF=(flags&WRITEFLAG)?outbuf[i]:0xff; // send data\r
+      while((IFG2&UTXIFG0)==0); // wait until received\r
+      if(flags&READFLAG)\r
+        inbuf[i]=U0RXBUF; //read data\r
+      else\r
+        nul=U0RXBUF;\r
+    }\r
+  }\r
+  P3OUT|=0x01; //chip select up\r
+}\r
+\r
+#pragma vector=PORT2_VECTOR\r
+__interrupt void P2_ISR()\r
+{\r
+  if(P2IFG&0x08) // RTC\r
+  {\r
+    P2IFG &= ~0x08;\r
+    spi(RTC_READ,0x00,inbuf,outbuf,8);\r
+  \r
+    time[0]=inbuf[0]; //1/100 s\r
+    time[1]=inbuf[1]&0x7f; //seconds\r
+    time[2]=inbuf[2]&0x7f; //minutes\r
+    time[3]=inbuf[3]&0x3f; //hours\r
+    time[4]=inbuf[4]&0x07; //dow\r
+    time[5]=inbuf[5]&0x3f; //dom\r
+    time[6]=inbuf[6]&0x1f; //mon\r
+    time[7]=inbuf[7];//year\r
+    leap=inbuf[6]&0x20;\r
+    \r
+    spi(RTC_READ,0x0f,inbuf,outbuf,1);\r
+    if(!((time[2]^alarm[1])|(time[3]^alarm[2])) && alarm[0])\r
+    {\r
+      mode=MODE_ALARM;\r
+      alarm[0]=0; //alarm removed after activated\r
+      spi(RTC_WRITE,0x20,inbuf,alarm,1);\r
+    }\r
+    \r
+    if(mode==MODE_COUNTUP && run)\r
+    {\r
+      if(settime[1]<0x59)\r
+        settime[1]=__bcd_add_short(settime[1],0x01);\r
+      else\r
+      {\r
+        settime[1]=0x00;\r
+        settime[2]=__bcd_add_short(settime[2],0x01);\r
+      }\r
+    }\r
+    else if(mode==MODE_COUNTDOWN && run && (settime[1]|settime[2]))\r
+    {\r
+      if(settime[1])\r
+        settime[1]=__bcd_add_short(settime[1],0x99);\r
+      else\r
+      {\r
+        settime[1]=0x59;\r
+        settime[2]=__bcd_add_short(settime[2],0x99);\r
+      }\r
+    }\r
+    \r
+    if (mode==MODE_ALARM || (mode==MODE_COUNTDOWN && !(settime[1]|settime[2])))\r
+    {\r
+      TACTL^=MC_1;\r
+      //P2DIR^=0x40;\r
+      //P2SEL^=0x40;\r
+    }\r
+    else if(TACTL & MC_3)\r
+    {\r
+      TACTL&= ~MC_3;\r
+      //P2DIR&= ~0x40;\r
+      //P2SEL&= ~0x40;\r
+    }\r
+  }\r
+  else if(P2IFG&0x02) // button A\r
+  {\r
+    P2IFG &= ~0x02;\r
+    switch(mode)\r
+    {\r
+    case MODE_TIME:\r
+    case MODE_SETDATE:\r
+    case MODE_SETYEAR:\r
+      mode=MODE_DATE;\r
+      break;\r
+    case MODE_DATE:\r
+      mode=MODE_COUNTUP;\r
+      settime[1]=0x00;\r
+      settime[2]=0x00;\r
+      run=0;\r
+      break;\r
+    case MODE_COUNTUP:\r
+      if(run)\r
+      {\r
+        settime[1]=0x00;\r
+        settime[2]=0x00;\r
+        run=0;\r
+      }\r
+      else\r
+      {\r
+        mode=MODE_SETCOUNTDOWN;\r
+        settime[1]=0x00;\r
+        settime[2]=0x00;\r
+        digit=3;\r
+      }\r
+      break;\r
+    case MODE_SETCOUNTDOWN:\r
+    case MODE_COUNTDOWN:\r
+      if((settime[1] | settime[2])||digit!=3||mode==MODE_COUNTDOWN)\r
+      {\r
+        mode=MODE_SETCOUNTDOWN;\r
+        settime[1]=0x00;\r
+        settime[2]=0x00;\r
+        digit=3;\r
+        break;\r
+      }\r
+    //case MODE_SETTIME:\r
+    //case MODE_SETALARM:\r
+    //case MODE_ALARM:\r
+    //case MODE_CALIBRATE:\r
+    default:\r
+      mode=MODE_TIME;\r
+      break;\r
+    }\r
+  }\r
+  else if(P2IFG&0x01) // button B\r
+  {\r
+    P2IFG &= ~0x01;\r
+    \r
+    switch(mode)\r
+    {\r
+    case MODE_TIME:\r
+      mode=MODE_SETTIME;\r
+      digit=3;\r
+      changed=0;\r
+      settime[0]=0;\r
+      settime[1]=time[2];\r
+      settime[2]=time[3];\r
+      break;\r
+    case MODE_DATE:\r
+      mode=MODE_SETDATE;\r
+      digit=2;\r
+      changed=0;\r
+      settime[0]=time[5];\r
+      settime[1]=time[6];\r
+      break;\r
+    case MODE_COUNTUP:\r
+    case MODE_COUNTDOWN:\r
+      run=!run;\r
+      break;\r
+    case MODE_SETCOUNTDOWN:\r
+      if(digit)\r
+        --digit;\r
+      else\r
+      {\r
+        mode=MODE_COUNTDOWN;\r
+        run=0;\r
+      }\r
+      break;\r
+    case MODE_CALIBRATE:\r
+      if(digit)\r
+        --digit;\r
+      else\r
+      {\r
+        spi(RTC_WRITE,0x09,inbuf,settime,1);\r
+        outbuf[0]=time[3]|settime[1];\r
+        spi(RTC_WRITE,0x03,inbuf,outbuf,1);\r
+        digit=3;\r
+      }\r
+      break;\r
+    case MODE_SETTIME:\r
+      if(digit)\r
+      {\r
+        if(digit==3&&settime[2]>0x23)\r
+           settime[2]&=0xf0;\r
+        --digit;\r
+      }\r
+      else\r
+      {\r
+        if(changed)\r
+        {\r
+          outbuf[0]=0x00;\r
+          outbuf[1]=0x00;\r
+          outbuf[2]=settime[1]&0x7f;\r
+          outbuf[3]=settime[2]&0x3f;\r
+          \r
+          spi(RTC_WRITE,0x01,inbuf,outbuf,1);//stop osc.\r
+          spi(RTC_READ,0x03,inbuf,outbuf,1);\r
+          outbuf[3]|=(inbuf[0]&0x80);//keep the calsgn bit.\r
+        \r
+          spi(RTC_WRITE,0x00,inbuf,outbuf,4);//write new time\r
+        \r
+          outbuf[0]=0x80;\r
+          spi(RTC_WRITE,0x01,inbuf,outbuf,1);//start osc;\r
+          \r
+          time[1]=0;\r
+          time[2]=settime[1];\r
+          time[3]=settime[2];\r
+        }\r
+        mode=MODE_TIME;\r
+      }\r
+      break;\r
+    case MODE_SETYEAR:\r
+      if(digit)\r
+        --digit;\r
+      else\r
+      {\r
+        if(changed)\r
+        {\r
+          time[7]=settime[0];\r
+          spi(RTC_WRITE,0x07,inbuf,settime,1);\r
+        }\r
+        mode=MODE_DATE; \r
+      }\r
+      break;\r
+    case MODE_SETDATE:\r
+      if(digit)\r
+      {\r
+        --digit;\r
+        if(settime[0]>((settime[1]==0x02)?(leap?0x29:0x28):(((settime[1]&0x18) && !(settime[1]&0x01) || !(settime[1]&0x18) && (settime[1]&0x01))?0x31:0x30)))\r
+          settime[0]&=(digit?0x00:0xf0);\r
+      }\r
+      else\r
+      {\r
+        if (changed)\r
+        {\r
+          time[5]=settime[0];\r
+          time[6]=settime[1];\r
+          settime[2]=time[7];\r
+          spi(RTC_WRITE,0x05,inbuf,settime,3);\r
+        }\r
+        mode=MODE_DATE;\r
+      }\r
+      \r
+      break;\r
+    case MODE_SETALARM:\r
+      if(digit)\r
+      {\r
+        if(digit==3&&settime[2]>0x23)\r
+           settime[2]&=0xf0;\r
+        --digit;\r
+      }\r
+      else\r
+      {\r
+        if(changed|| !alarm[0])\r
+        {\r
+          alarm[0]=ALARMVALUE;\r
+          alarm[1]=settime[1];\r
+          alarm[2]=settime[2];\r
+          \r
+          spi(RTC_WRITE,0x20,inbuf,alarm,3);\r
+        }\r
+        else\r
+        {\r
+          alarm[0]=0;\r
+          spi(RTC_WRITE,0x20,inbuf,outbuf,1);\r
+        }\r
+        mode=MODE_TIME;\r
+      }\r
+      break;\r
+    case MODE_ALARM:\r
+      alarm[0]=0;\r
+      spi(RTC_WRITE,0x20,inbuf,outbuf,1);\r
+      mode=MODE_TIME;\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+  else if(P2IFG&0x20) // button C\r
+  {\r
+    P2IFG &= ~0x20;\r
+    \r
+    switch(mode)\r
+    {\r
+    case MODE_COUNTUP:\r
+      settime[1]=0x00;\r
+      settime[2]=0x00;\r
+      break;\r
+    case MODE_COUNTDOWN:\r
+      mode=MODE_SETCOUNTDOWN;\r
+      digit=3;\r
+      break;\r
+    case MODE_CALIBRATE:\r
+      if(digit==2)\r
+        settime[1]^=0x80;\r
+      else if(digit<2)\r
+        settime[0]+=(digit==1?0x10:(((settime[0]&0x0f)==0x0f)?0xf1:0x01));\r
+      break;\r
+    case MODE_SETTIME:\r
+    case MODE_SETALARM:\r
+      changed=1;\r
+    case MODE_SETCOUNTDOWN:\r
+      //these 4 lines replaced a larger switch structure\r
+      if((settime[digit&0x02?2:1]&((digit&0x01)?0xf0:0x0f))<(digit==1?0x50:(digit==3?((mode==MODE_SETCOUNTDOWN)?0x90:0x20):((mode!=MODE_SETCOUNTDOWN&&digit==2&&settime[2]>0x19)?0x03:0x09))))\r
+        settime[digit&0x02?2:1]+=((digit&0x01)?0x10:0x01);\r
+      else\r
+        settime[digit&0x02?2:1]&=((digit&0x01)?0x0f:0xf0);\r
+      break;\r
+    case MODE_SETYEAR:\r
+      changed=1;\r
+      if(digit)\r
+      {\r
+        if(settime[0]<0x90)\r
+          settime[0]+=0x10;\r
+        else\r
+          settime[0]&=0x0f;\r
+      }\r
+      else\r
+      {\r
+        if((settime[0]&0x0f)<0x09)\r
+          ++settime[0];\r
+        else\r
+          settime[0]&=0xf0;\r
+      }\r
+      break;\r
+    case MODE_SETDATE:\r
+      changed=1;\r
+      switch (digit)\r
+      {\r
+      case 2:\r
+        if(settime[1]<0x12)\r
+          settime[1]=__bcd_add_short(settime[1],0x01);\r
+        else\r
+          settime[1]=0x01;\r
+        break;\r
+      case 1:\r
+        if((settime[0]&0xf0)<((settime[1]==0x02)?0x20:0x30))\r
+          settime[0]+=0x10;\r
+        else\r
+          settime[0]&=0x0f;\r
+        break;\r
+        \r
+      case 0:\r
+        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)\r
+          ++settime[0];\r
+        else\r
+          settime[0]&=0xf0;\r
+        break;\r
+      }\r
+      break;\r
+    case MODE_DATE:\r
+      mode=MODE_SETYEAR;\r
+      digit=1;\r
+      changed=0;\r
+      \r
+      settime[0]=time[7];\r
+      break;\r
+    case MODE_TIME:\r
+      mode=MODE_SETALARM;\r
+      digit=3;\r
+      changed=0;\r
+      \r
+      settime[0]=0;\r
+      settime[1]=alarm[1]; //get last alarm time\r
+      if(settime[1]>0x59 || (settime[1]&0x0f)>0x09)\r
+        settime[1]=0x00;\r
+      settime[2]=alarm[2];\r
+      if(settime[2]>0x23 || (settime[2]&0x0f)>0x09)\r
+        settime[2]=0x00;\r
+      break;\r
+    case MODE_ALARM:\r
+      alarm[0]=0;\r
+      spi(RTC_WRITE,0x20,inbuf,outbuf,1);\r
+      mode=MODE_TIME;\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+  else\r
+    P2IFG=0;\r
+  \r
+  switch(mode)\r
+  {\r
+  case MODE_SETTIME:\r
+  case MODE_SETALARM:\r
+  case MODE_SETCOUNTDOWN:\r
+    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)?SYMB_NUL:SYMB_DOT);\r
+    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)?SYMB_NUL:SYMB_DOT);\r
+    dispvalue[2]=(symbol[settime[2]&0x0f]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8));\r
+    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);\r
+    break;\r
+  case MODE_SETYEAR:\r
+    dispvalue[0]=(symbol[settime[0]&0x0f]|((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8));\r
+    dispvalue[1]=(symbol[(settime[0]&0xf0)>>4]|((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8));\r
+    dispvalue[2]=(SYMB_0|((time[1]&0x01)?SYMB_NUL:SYMB_8));\r
+    dispvalue[3]=(SYMB_2|((time[1]&0x01)?SYMB_NUL:SYMB_8))&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
+    break;\r
+  case MODE_SETDATE:\r
+    dispvalue[0]=(symbol[settime[1]&0x0f]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8));\r
+    dispvalue[1]=(symbol[(settime[1]&0xf0)>>4]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&SYMB_DOT;\r
+    dispvalue[2]=(symbol[settime[0]&0x0f]|((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8));\r
+    dispvalue[3]=(symbol[(settime[0]&0xf0)>>4]|((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
+    break;\r
+  case MODE_CALIBRATE:\r
+    dispvalue[0]=symbol[settime[0]&0x0f]|((digit!=0 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8);\r
+    dispvalue[1]=symbol[(settime[0]&0xf0)>>4]|((digit!=1 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8);\r
+    dispvalue[2]=(settime[1]?SYMB_MIN:SYMB_NUL)|((digit!=2 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8);\r
+    dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL;\r
+    break;\r
+  case MODE_DATE:\r
+    if((time[1]&0x03)==((time[1]&0x10)?0x01:0x03))\r
+    {\r
+      dispvalue[0]=symbol[time[7]&0x0f];\r
+      dispvalue[1]=symbol[(time[7]&0xf0)>>4];\r
+      dispvalue[2]=SYMB_0;\r
+      dispvalue[3]=SYMB_2&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
+    }\r
+    else\r
+    {\r
+      dispvalue[0]=symbol[time[6]&0x0f];\r
+      dispvalue[1]=symbol[(time[6]&0xf0)>>4]&SYMB_DOT;\r
+      dispvalue[2]=symbol[time[5]&0x0f];\r
+      dispvalue[3]=((time[5]&0xf0)?symbol[(time[5]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
+    }\r
+    break;\r
+  case MODE_COUNTDOWN:\r
+    if(!(settime[1]|settime[2]))\r
+    {\r
+      if(!run)\r
+      {\r
+        dispvalue[0]=SYMB_g&SYMB_DOT;\r
+        dispvalue[1]=SYMB_n&SYMB_DOT;\r
+        dispvalue[2]=SYMB_o;\r
+        dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL;\r
+        break;\r
+      }\r
+      run=0;\r
+    }\r
+  case MODE_COUNTUP:\r
+    dispvalue[0]=symbol[settime[1]&0x0f]&SYMB_DOT;\r
+    dispvalue[1]=symbol[(settime[1]&0xf0)>>4]&SYMB_DOT;\r
+    dispvalue[2]=symbol[settime[2]&0x0f];\r
+    dispvalue[3]=((settime[2]&0xf0)?symbol[(settime[2]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
+    break;\r
+  case MODE_ALARM:\r
+    if(time[1]&0x01)\r
+    {\r
+      dispvalue[0]=SYMB_g;\r
+      dispvalue[1]=SYMB_n;\r
+      dispvalue[2]=SYMB_o;\r
+      dispvalue[3]=SYMB_DOT;\r
+      break;\r
+    }\r
+  case MODE_TIME:\r
+  default:\r
+    dispvalue[0]=symbol[time[2]&0x0f]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT);\r
+    dispvalue[1]=symbol[(time[2]&0xf0)>>4]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT);\r
+    dispvalue[2]=symbol[time[3]&0x0f];\r
+    dispvalue[3]=((time[3]&0xf0)?symbol[(time[3]&0xf0)>>4]:SYMB_NUL)&((alarm[0] || mode==MODE_ALARM)?SYMB_DOT:SYMB_NUL);\r
+    break;\r
+  }\r
+  \r
+  display(dispvalue);\r
+  \r
+  \r
+  return;\r
+}\r
+\r
+int main( void )\r
+{\r
+  unsigned char delay;\r
+  \r
+  //watchdog:\r
+  WDTCTL = WDTPW + WDTHOLD;\r
+  \r
+  mode=MODE_INIT;\r
+  \r
+  //init 7 segment display\r
+  \r
+  P1OUT =0xff; //display data on p1\r
+  P1DIR =0xff;\r
+  \r
+  P3OUT &=0x0f; //display control on p3.4-7\r
+  P3DIR |=0xf0; \r
+  \r
+  dispvalue[0]=SYMB_NUL;\r
+  dispvalue[1]=SYMB_o;\r
+  dispvalue[2]=SYMB_o;\r
+  dispvalue[3]=SYMB_NUL;\r
+  \r
+  display(dispvalue);  \r
+  \r
+  //clocking:\r
+    \r
+  BCSCTL2 |= DIVM_3; //errata sheet recommends this here \r
+  \r
+  DCOCTL =0x00;\r
+  BCSCTL1 =\r
+    RSEL2| //in the\r
+    XTS| //hi freq\r
+    DIVA_1; //ACLK = 6/2 MHz\r
+  \r
+  do\r
+  {\r
+    IFG1 &= ~OFIFG;\r
+    for (delay = 0xFF; delay > 0; --delay);\r
+  }\r
+  while ((IFG1 & OFIFG)); \r
+  \r
+  BCSCTL2 =\r
+    SELM_2| //MCLK from XT2\r
+    DIVM_1| //MCLK = 6/2 MHz\r
+    SELS| //SMCLK from XT2\r
+    DIVS_0; //SMCLK = 6/1 MHz\r
+    \r
+  //init SPI\r
+  \r
+  P3SEL =0x0e; // SPI on p3.1, 3.2, 3.3\r
+  P3OUT |=0x01;\r
+  P3DIR |=0x01; //RTC CS on p3.0\r
+  \r
+  U0CTL =\r
+    SWRST| //reset\r
+    MM| //master\r
+    SYNC| //SPI mode\r
+    CHAR; //8 bit data\r
+  U0TCTL=\r
+    CKPH| //polarity and phase\r
+    SSEL0|SSEL1| //SMCLK\r
+    STC; //3 pin mode\r
+  U0BR1=0x00;\r
+  U0BR0=0x02; //baudrate = SMCLK/2 = 3MHz\r
+  U0MCTL=0x00;\r
+  ME2|=USPIE0;\r
+  U0CTL &= ~SWRST;\r
+  \r
+  //init RTC\r
+  \r
+  //set 24 hour mode\r
+  spi(RTC_READ,0x03,inbuf,outbuf,1);\r
+  if(inbuf[0]&0x40)\r
+  {\r
+    outbuf[0]=inbuf[0]&(~0x40);\r
+    spi(RTC_WRITE,0x03,inbuf,outbuf,1);\r
+  }\r
+    \r
+  //enable battery\r
+  spi(RTC_READ,0x04,inbuf,outbuf,1);\r
+  if(!(inbuf[0]&0x08))\r
+  {\r
+    outbuf[0]=inbuf[0]|0x08; //enable battery\r
+    spi(RTC_WRITE,0x04,inbuf,outbuf,1);\r
+  }\r
+  \r
+  //set control register\r
+  //spi(RTC_READ,0x08,inbuf,outbuf,1);\r
+  outbuf[0]=\r
+    0x40| //squarewave enable\r
+    0x04; //1Hz\r
+  //no hardware alarms :(\r
+  spi(RTC_WRITE,0x08,inbuf,outbuf,1);\r
+  \r
+  //get (soft) alarm from RTC SRAM\r
+  spi(RTC_READ,0x20,inbuf,outbuf,3);\r
+  \r
+  alarm[0]=(inbuf[0]==ALARMVALUE)?ALARMVALUE:0;\r
+  alarm[1]=inbuf[1];\r
+  alarm[2]=inbuf[2];\r
+  \r
+  //start oscillator\r
+  spi(RTC_READ,0x01,inbuf,outbuf,1);\r
+  if(!(inbuf[0]&0x80))\r
+  {\r
+    outbuf[0]=inbuf[0]|0x80;\r
+    spi(RTC_WRITE,0x01,inbuf,outbuf,1);\r
+  }\r
+  \r
+  //init timer:\r
+  TACCR0 = 375-1; //3MHz/375/2=4kHz\r
+  TACCTL0=   //also, compare, not capture\r
+    OUTMOD_4; //toggle\r
+  TACTL=\r
+    TASSEL_1| //ACLK, 3MHz\r
+    ID_0| //3MHz/1\r
+    //MC_1| //up mode\r
+    TACLR; //reset\r
+  P2SEL|=0x04; //P2.2 timer output.\r
+  P2DIR|=0x04;\r
+  \r
+  // Init interrupts\r
+  P2IE=\r
+    0x08| //p2.3 - int. from RTC\r
+    0x02| //p2.1 - int. from button A\r
+    0x01| //p2.0 - int. from button B\r
+    0x20; //p2.5 - int. from button C\r
+  P2IES|=0x01|0x02|0x20; //button int. on falling edge\r
+  P2IES&= ~0x08; //RTC int. on rising edge\r
+  P2IFG=0x00;\r
+  \r
+  if(P2IN&0x02) //button A pressed at start?\r
+    mode=MODE_TIME;\r
+  else\r
+  {\r
+    mode=MODE_CALIBRATE;\r
+    spi(RTC_READ,0x03,inbuf,outbuf,1);\r
+    settime[1]=inbuf[0]&0x80;\r
+    spi(RTC_READ,0x09,inbuf,outbuf,1);\r
+    settime[0]=inbuf[0];\r
+    digit=3;\r
+  }\r
+     \r
+  __enable_interrupt();\r
+  \r
+  \r
+  while(1)\r
+  {\r
+    __low_power_mode_3();\r
+  }\r
+}\r