]> bicyclesonthemoon.info Git - staf/staf/commitdiff
switch to gcc, gpl license, BCD addition v1.4
authorb <rowerynaksiezycu@gmail.com>
Fri, 26 Feb 2016 19:14:20 +0000 (20:14 +0100)
committerb <rowerynaksiezycu@gmail.com>
Fri, 26 Feb 2016 19:14:20 +0000 (20:14 +0100)
.gitignore
asm.S [new file with mode: 0644]
definitions.h [changed mode: 0755->0644]
main.c [changed mode: 0755->0644]
makefile [new file with mode: 0644]

index f039d9676879b7628cc75b02b442644b786922bf..6c90a9d1e5e3c50027aeb38ccf44dcacdbe0084e 100644 (file)
@@ -1,2 +1,3 @@
 *.a43
-
+*.elf
+*.hex
diff --git a/asm.S b/asm.S
new file mode 100644 (file)
index 0000000..e577970
--- /dev/null
+++ b/asm.S
@@ -0,0 +1,37 @@
+; SilentTimer Action Figure software, v1.4
+; asm.S
+; things that can't be done in C
+; 
+; Copyright (C) 2014-2016  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
+; the Free Software Foundation, either version 3 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; 
+; You should have received a copy of the GNU General Public License
+; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "msp430.h"
+;Why do I even have to define this?!
+#define SR R2
+
+.section .text
+.global bcd_add_byte
+.global lpm3
+
+;function to add 2-digit BCD numbers
+bcd_add_byte:
+       clrc
+       dadd.b R14, R15
+       ret
+
+;function to enter low power mode 3
+lpm3:
+       bis.w #SCG1|SCG0|CPUOFF, SR
+       ret
old mode 100755 (executable)
new mode 100644 (file)
index a869b44..94217cf
@@ -1,3 +1,22 @@
+// SilentTimer Action Figure software, v1.4\r
+// definitions.h\r
+// Definitions used by the code.\r
+// \r
+// Copyright (C) 2014-2016  Balthasar Szczepański\r
+//\r
+// This program is free software: you can redistribute it and/or modify\r
+// it under the terms of the GNU General Public License as published by\r
+// the Free Software Foundation, either version 3 of the License, or\r
+// (at your option) any later version.\r
+//\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+//\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
+\r
 //RTC commands:\r
 #define RTC_EEREAD  0x03\r
 #define RTC_EEWRITE 0x02\r
@@ -69,4 +88,8 @@
 #define MODE_DEBUGADDR 13\r
 #define MODE_DEBUGVAL 14\r
 \r
-#define ALARMVALUE 0xa5
\ No newline at end of file
+#define ALARMVALUE 0xa5\r
+\r
+unsigned char bcd_add_byte (unsigned char, unsigned char);\r
+void          lpm3         ();\r
+\r
diff --git a/main.c b/main.c
old mode 100755 (executable)
new mode 100644 (file)
index c2e9f14..62b27d1
--- a/main.c
+++ b/main.c
-#include "msp430.h"\r
-#include "definitions.h"\r
+// SilentTimer Action Figure software, v1.4\r
+// main.c\r
+// The main c file.\r
+// \r
+// Copyright (C) 2014-2016  Balthasar Szczepański\r
+// \r
+// This program is free software: you can redistribute it and/or modify\r
+// it under the terms of the GNU General Public License as published by\r
+// the Free Software Foundation, either version 3 of the License, or\r
+// (at your option) any later version.\r
+// \r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+// \r
+// You should have received a copy of the GNU General Public License\r
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.\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 lastcdn[2];\r
-unsigned char lastyear[5];\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
+       #include "msp430.h"\r
+       #include "definitions.h"\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
+       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 lastcdn[2];\r
+       unsigned char lastyear[5];\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
-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
+       __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 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
-  for(i=0;i<255;++i); //looks like the RTC might not like another SPI transmission exactly before the previous one, sometimes.\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
-#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); // <- because of RTC bug (probably not needed anymore?)\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
-    lastyear[4]=(time[7]==0x00 && lastyear[0]==0x99)?__bcd_add_short(lastyear[1],0x01):lastyear[1];\r
-    if (time[7]!=lastyear[0])\r
-    {\r
-      if(time[7]==lastyear[2])\r
-        ++(lastyear[3]);\r
-      else\r
-        lastyear[3]=0;\r
-      \r
-      lastyear[2]=time[7];\r
-      \r
-      if(lastyear[3]>55)\r
-      {\r
-        lastyear[3]=0;\r
-        \r
-        if(time[7]==0x00 && lastyear[0]==0x99)\r
-          lastyear[1]=__bcd_add_short(lastyear[1],0x01);\r
-        \r
-        lastyear[0]=time[7];\r
-        \r
-        outbuf[0]=ALARMVALUE;\r
-        outbuf[1]=lastyear[0];\r
-        outbuf[2]=lastyear[1];\r
-        spi(RTC_WRITE,0x26,inbuf,outbuf,3);\r
-      }      \r
-    }\r
-    \r
-    \r
-    if(mode==MODE_DEBUG && changed)\r
-      spi(RTC_READ,settime[1],settime,outbuf,1);\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]=lastcdn[0];\r
-        settime[2]=lastcdn[1];\r
-        changed=0;\r
-        digit=3;\r
-      }\r
-      break;\r
-    case MODE_DEBUGADDR:\r
-    case MODE_DEBUGVAL:\r
-      mode=MODE_DEBUG;\r
-      break;\r
-    case MODE_SETCOUNTDOWN:\r
-    case MODE_COUNTDOWN:\r
-      if(changed || mode==MODE_COUNTDOWN)\r
-      {\r
-        mode=MODE_SETCOUNTDOWN;\r
-        settime[1]=lastcdn[0];\r
-        settime[2]=lastcdn[1];\r
-        changed=0;\r
-        digit=3;\r
-        break;\r
-      }\r
-    //case MODE_SETTIME:\r
-    //case MODE_SETALARM:\r
-    //case MODE_ALARM:\r
-    //case MODE_CALIBRATE:\r
-    //case MODE_DEBUG:\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
-      {\r
-        --digit;\r
-        changed=1;\r
-      }\r
-      else\r
-      {\r
-        lastcdn[0]=settime[1];\r
-        lastcdn[1]=settime[2];\r
-        \r
-        outbuf[0]=ALARMVALUE;\r
-        outbuf[1]=settime[1];\r
-        outbuf[2]=settime[2];\r
-        spi(RTC_WRITE,0x23,inbuf,outbuf,3);\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
+               for(i=0;i<255;++i); //looks like the RTC might not like another SPI transmission exactly before the previous one, sometimes.\r
+       }\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_DEBUGADDR:\r
-      if(digit)\r
-        --digit;\r
-      else\r
-      {\r
-        spi(RTC_READ,settime[1],settime,outbuf,1);\r
-        mode=MODE_DEBUG;\r
-        changed=1;\r
-      }\r
-      break;\r
-    case MODE_DEBUGVAL:\r
-      if(digit)\r
-        --digit;\r
-      else\r
-      {\r
-        spi(RTC_WRITE,settime[1],inbuf,settime,1);\r
-        mode=MODE_DEBUG;\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[1];\r
-          spi(RTC_WRITE,0x07,inbuf,settime+1,1);\r
-          \r
-          lastyear[0]=settime[1];\r
-          lastyear[1]=settime[2];\r
-          settime[0]=ALARMVALUE;\r
-          \r
-          spi(RTC_WRITE,0x26,inbuf,settime,3);\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
-        if(settime[0]==0x00)\r
-          settime[0]=0x01;\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,0x06,inbuf,settime+1,2);\r
-          spi(RTC_WRITE,0x05,inbuf,settime,1);\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
-    case MODE_DEBUG:\r
-      //changed=1;\r
-      digit=1;\r
-      mode=MODE_DEBUGADDR;\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
-      settime[1]=lastcdn[0];\r
-      settime[2]=lastcdn[1];\r
-      changed=0;\r
-      mode=MODE_SETCOUNTDOWN;\r
-      digit=3;\r
-      break;\r
-    case MODE_CALIBRATE:\r
-      if(digit==2)\r
-        settime[1]^=0x80;\r
-      if(digit>=2)\r
-        break;\r
-    case MODE_DEBUGADDR:\r
-    case MODE_DEBUGVAL:\r
-      settime[(mode==MODE_DEBUGADDR)?1:0]+=(digit==1?0x10:(((settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f)==0x0f)?0xf1:0x01));\r
-      break;\r
-    case MODE_SETTIME:\r
-    case MODE_SETALARM:\r
-    case MODE_SETYEAR:\r
-    case MODE_SETCOUNTDOWN:\r
-      changed=1;\r
-      //these 4 lines replaced a larger switch structure\r
-      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))))\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_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
-        if(settime[0]==0x00)\r
-          settime[0]=0x01;\r
-        break;\r
-      }\r
-      break;\r
-    case MODE_DATE:\r
-      mode=MODE_SETYEAR;\r
-      digit=3;\r
-      changed=0;\r
-      \r
-      settime[1]=time[7];\r
-      settime[2]=lastyear[1];\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
-    case MODE_DEBUG:\r
-      if(changed)\r
-      {\r
-        digit=1;\r
-        mode=MODE_DEBUGVAL;\r
-      }\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
-  case MODE_SETYEAR:\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)||mode==MODE_SETYEAR)?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)||mode==MODE_SETYEAR)?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_DEBUGADDR:\r
-  case MODE_DEBUGVAL:\r
-    dispvalue[0]=(symbol[settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f]      | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT;\r
-    dispvalue[1]=(symbol[(settime[(mode==MODE_DEBUGADDR)?1:0]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT;\r
-    dispvalue[2]=(mode==MODE_DEBUGADDR)?SYMB_A:SYMB_NUL;   \r
-    dispvalue[3]=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]=symbol[lastyear[4]&0x0f];\r
-      dispvalue[3]=symbol[(lastyear[4]&0xf0)>>4]&(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_DEBUG:\r
-    if(changed)\r
-    {\r
-      dispvalue[0]=symbol[settime[0]&0x0f]&SYMB_DOT;\r
-      dispvalue[1]=symbol[(settime[0]&0xf0)>>4]&SYMB_DOT;\r
-      dispvalue[2]=symbol[settime[1]&0x0f];\r
-      dispvalue[3]=symbol[(settime[1]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
-    }\r
-    else\r
-    {\r
-      dispvalue[0]=SYMB_NUL;\r
-      dispvalue[1]=SYMB_4&SYMB_DOT;\r
-      dispvalue[2]=SYMB_1;\r
-      dispvalue[3]=SYMB_NUL&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
-    }\r
-    break;\r
-  case MODE_ALARM:\r
-  case MODE_TIME:\r
-    if(((time[1]&0x01) && mode==MODE_ALARM) || (time[3]==0x04 && time[2]==0x33 && time[1]==0x00))\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
-  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
+       #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); // <- because of RTC bug (probably not needed anymore?)\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_byte(settime[1],0x01);\r
+                               else\r
+                               {\r
+                                       settime[1]=0x00;\r
+                                       settime[2]=bcd_add_byte(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_byte(settime[1],0x99);\r
+                               else\r
+                               {\r
+                                       settime[1]=0x59;\r
+                                       settime[2]=bcd_add_byte(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
+                       lastyear[4]=(time[7]==0x00 && lastyear[0]==0x99)?bcd_add_byte(lastyear[1],0x01):lastyear[1];\r
+                       if (time[7]!=lastyear[0])\r
+                       {\r
+                               if(time[7]==lastyear[2])\r
+                                       ++(lastyear[3]);\r
+                               else\r
+                                       lastyear[3]=0;\r
+                               \r
+                               lastyear[2]=time[7];\r
+                               \r
+                               if(lastyear[3]>55)\r
+                               {\r
+                                       lastyear[3]=0;\r
+                                       \r
+                                       if(time[7]==0x00 && lastyear[0]==0x99)\r
+                                               lastyear[1]=bcd_add_byte(lastyear[1],0x01);\r
+                                       \r
+                                       lastyear[0]=time[7];\r
+                                       \r
+                                       outbuf[0]=ALARMVALUE;\r
+                                       outbuf[1]=lastyear[0];\r
+                                       outbuf[2]=lastyear[1];\r
+                                       spi(RTC_WRITE,0x26,inbuf,outbuf,3);\r
+                               }      \r
+                       }\r
+                       \r
+                       \r
+                       if(mode==MODE_DEBUG && changed)\r
+                               spi(RTC_READ,settime[1],settime,outbuf,1);\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]=lastcdn[0];\r
+                                       settime[2]=lastcdn[1];\r
+                                       changed=0;\r
+                                       digit=3;\r
+                               }\r
+                               break;\r
+                       case MODE_DEBUGADDR:\r
+                       case MODE_DEBUGVAL:\r
+                               mode=MODE_DEBUG;\r
+                               break;\r
+                       case MODE_SETCOUNTDOWN:\r
+                       case MODE_COUNTDOWN:\r
+                               if(changed || mode==MODE_COUNTDOWN)\r
+                               {\r
+                                       mode=MODE_SETCOUNTDOWN;\r
+                                       settime[1]=lastcdn[0];\r
+                                       settime[2]=lastcdn[1];\r
+                                       changed=0;\r
+                                       digit=3;\r
+                                       break;\r
+                               }\r
+                       //case MODE_SETTIME:\r
+                       //case MODE_SETALARM:\r
+                       //case MODE_ALARM:\r
+                       //case MODE_CALIBRATE:\r
+                       //case MODE_DEBUG:\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
+                               {\r
+                                       --digit;\r
+                                       changed=1;\r
+                               }\r
+                               else\r
+                               {\r
+                                       lastcdn[0]=settime[1];\r
+                                       lastcdn[1]=settime[2];\r
+                                       \r
+                                       outbuf[0]=ALARMVALUE;\r
+                                       outbuf[1]=settime[1];\r
+                                       outbuf[2]=settime[2];\r
+                                       spi(RTC_WRITE,0x23,inbuf,outbuf,3);\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
-  \r
-  //init RTC\r
-  \r
-  //Looks like sometimes the first SPI reads rom the RTC may be incorrect.\r
-  //To be sure, let's do a few redundant reads before starting the real work\r
-  \r
-  for (delay = 0xFF; delay > 0; --delay)\r
-     spi(RTC_READ,0x00,inbuf,outbuf,1);\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
-  spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)\r
-  \r
-  //get last countdown value from RTC SRAM\r
-  spi(RTC_READ,0x23,inbuf,outbuf,3);\r
-  if(inbuf[0]==ALARMVALUE)\r
-  {\r
-    lastcdn[0]=inbuf[1];\r
-    lastcdn[1]=inbuf[2];\r
-  }\r
-  else\r
-  {\r
-    lastcdn[0]=0;\r
-    lastcdn[1]=0;\r
-  }\r
-  \r
-  spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)\r
-  \r
-  //get last year value from RTC SRAM\r
-  spi(RTC_READ,0x26,inbuf,outbuf,3);\r
-  if(inbuf[0]==ALARMVALUE)\r
-  {\r
-    lastyear[0]=inbuf[1];\r
-    lastyear[1]=inbuf[2];\r
-  }\r
-  else\r
-  {\r
-    lastyear[0]=0x00;\r
-    lastyear[1]=0x20;\r
-  }\r
-  lastyear[3]=0;\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
-  {\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
-  else if(!(P2IN&0x20)) //button C pressed at start?\r
-  {\r
-    mode=MODE_DEBUG;\r
-    settime[1]=0x00;\r
-    changed=0;\r
-  }\r
-  else\r
-    mode=MODE_TIME;\r
-  \r
-  __enable_interrupt();\r
-  \r
-  \r
-  while(1)\r
-  {\r
-    __low_power_mode_3();\r
-  }\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_DEBUGADDR:\r
+                               if(digit)\r
+                                       --digit;\r
+                               else\r
+                               {\r
+                                       spi(RTC_READ,settime[1],settime,outbuf,1);\r
+                                       mode=MODE_DEBUG;\r
+                                       changed=1;\r
+                               }\r
+                               break;\r
+                       case MODE_DEBUGVAL:\r
+                               if(digit)\r
+                                       --digit;\r
+                               else\r
+                               {\r
+                                       spi(RTC_WRITE,settime[1],inbuf,settime,1);\r
+                                       mode=MODE_DEBUG;\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[1];\r
+                                               spi(RTC_WRITE,0x07,inbuf,settime+1,1);\r
+                                               \r
+                                               lastyear[0]=settime[1];\r
+                                               lastyear[1]=settime[2];\r
+                                               settime[0]=ALARMVALUE;\r
+                                               \r
+                                               spi(RTC_WRITE,0x26,inbuf,settime,3);\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
+                                       if(settime[0]==0x00)\r
+                                               settime[0]=0x01;\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,0x06,inbuf,settime+1,2);\r
+                                               spi(RTC_WRITE,0x05,inbuf,settime,1);\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
+                       case MODE_DEBUG:\r
+                               //changed=1;\r
+                               digit=1;\r
+                               mode=MODE_DEBUGADDR;\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
+                               settime[1]=lastcdn[0];\r
+                               settime[2]=lastcdn[1];\r
+                               changed=0;\r
+                               mode=MODE_SETCOUNTDOWN;\r
+                               digit=3;\r
+                               break;\r
+                       case MODE_CALIBRATE:\r
+                               if(digit==2)\r
+                                       settime[1]^=0x80;\r
+                               if(digit>=2)\r
+                                       break;\r
+                       case MODE_DEBUGADDR:\r
+                       case MODE_DEBUGVAL:\r
+                               settime[(mode==MODE_DEBUGADDR)?1:0]+=(digit==1?0x10:(((settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f)==0x0f)?0xf1:0x01));\r
+                               break;\r
+                       case MODE_SETTIME:\r
+                       case MODE_SETALARM:\r
+                       case MODE_SETYEAR:\r
+                       case MODE_SETCOUNTDOWN:\r
+                               changed=1;\r
+                               //these 4 lines replaced a larger switch structure\r
+                               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))))\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_SETDATE:\r
+                               changed=1;\r
+                               switch (digit)\r
+                               {\r
+                               case 2:\r
+                                       if(settime[1]<0x12)\r
+                                               settime[1]=bcd_add_byte(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
+                                       if(settime[0]==0x00)\r
+                                               settime[0]=0x01;\r
+                                       break;\r
+                               }\r
+                               break;\r
+                       case MODE_DATE:\r
+                               mode=MODE_SETYEAR;\r
+                               digit=3;\r
+                               changed=0;\r
+                               \r
+                               settime[1]=time[7];\r
+                               settime[2]=lastyear[1];\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
+                       case MODE_DEBUG:\r
+                               if(changed)\r
+                               {\r
+                                       digit=1;\r
+                                       mode=MODE_DEBUGVAL;\r
+                               }\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
+               case MODE_SETYEAR:\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)||mode==MODE_SETYEAR)?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)||mode==MODE_SETYEAR)?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_DEBUGADDR:\r
+               case MODE_DEBUGVAL:\r
+                       dispvalue[0]=(symbol[settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f]      | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT;\r
+                       dispvalue[1]=(symbol[(settime[(mode==MODE_DEBUGADDR)?1:0]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT;\r
+                       dispvalue[2]=(mode==MODE_DEBUGADDR)?SYMB_A:SYMB_NUL;   \r
+                       dispvalue[3]=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]=symbol[lastyear[4]&0x0f];\r
+                               dispvalue[3]=symbol[(lastyear[4]&0xf0)>>4]&(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_DEBUG:\r
+                       if(changed)\r
+                       {\r
+                               dispvalue[0]=symbol[settime[0]&0x0f]&SYMB_DOT;\r
+                               dispvalue[1]=symbol[(settime[0]&0xf0)>>4]&SYMB_DOT;\r
+                               dispvalue[2]=symbol[settime[1]&0x0f];\r
+                               dispvalue[3]=symbol[(settime[1]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
+                       }\r
+                       else\r
+                       {\r
+                               dispvalue[0]=SYMB_NUL;\r
+                               dispvalue[1]=SYMB_4&SYMB_DOT;\r
+                               dispvalue[2]=SYMB_1;\r
+                               dispvalue[3]=SYMB_NUL&(alarm[0]?SYMB_DOT:SYMB_NUL);\r
+                       }\r
+                       break;\r
+               case MODE_ALARM:\r
+               case MODE_TIME:\r
+                       if(((time[1]&0x01) && mode==MODE_ALARM) || (time[3]==0x04 && time[2]==0x33 && time[1]==0x00))\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
+               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
+               \r
+               //init RTC\r
+               \r
+               //Looks like sometimes the first SPI reads rom the RTC may be incorrect.\r
+               //To be sure, let's do a few redundant reads before starting the real work\r
+               \r
+               for (delay = 0xFF; delay > 0; --delay)\r
+                        spi(RTC_READ,0x00,inbuf,outbuf,1);\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
+               spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)\r
+               \r
+               //get last countdown value from RTC SRAM\r
+               spi(RTC_READ,0x23,inbuf,outbuf,3);\r
+               if(inbuf[0]==ALARMVALUE)\r
+               {\r
+                       lastcdn[0]=inbuf[1];\r
+                       lastcdn[1]=inbuf[2];\r
+               }\r
+               else\r
+               {\r
+                       lastcdn[0]=0;\r
+                       lastcdn[1]=0;\r
+               }\r
+               \r
+               spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?)\r
+               \r
+               //get last year value from RTC SRAM\r
+               spi(RTC_READ,0x26,inbuf,outbuf,3);\r
+               if(inbuf[0]==ALARMVALUE)\r
+               {\r
+                       lastyear[0]=inbuf[1];\r
+                       lastyear[1]=inbuf[2];\r
+               }\r
+               else\r
+               {\r
+                       lastyear[0]=0x00;\r
+                       lastyear[1]=0x20;\r
+               }\r
+               lastyear[3]=0;\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
+               {\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
+               else if(!(P2IN&0x20)) //button C pressed at start?\r
+               {\r
+                       mode=MODE_DEBUG;\r
+                       settime[1]=0x00;\r
+                       changed=0;\r
+               }\r
+               else\r
+                       mode=MODE_TIME;\r
+               \r
+               __enable_interrupt();\r
+               \r
+               \r
+               while(1)\r
+               {\r
+                       lpm3();\r
+               }\r
+       }\r
diff --git a/makefile b/makefile
new file mode 100644 (file)
index 0000000..6c04be1
--- /dev/null
+++ b/makefile
@@ -0,0 +1,30 @@
+# SilentTimer Action Figure software, v1.4
+# makefile
+# 
+# Copyright (C) 2014-2016  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
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+CC=msp430-gcc
+CF=-Os -mmcu=msp430f1232
+OC=msp430-objcopy
+OF=-O ihex
+
+all: st.elf st.hex
+
+st.elf: main.c asm.S definitions.h makefile
+       $(CC) $(CF) -o st.elf asm.S main.c
+       
+st.hex: st.elf makefile
+       $(OC) $(OF) st.elf st.hex