From 7f23e3ef17d66e69cf0b0e656a0712b9470c2d5e Mon Sep 17 00:00:00 2001 From: b Date: Fri, 26 Feb 2016 20:14:20 +0100 Subject: [PATCH] switch to gcc, gpl license, BCD addition --- .gitignore | 3 +- asm.S | 37 ++ definitions.h | 25 +- main.c | 1769 +++++++++++++++++++++++++------------------------ makefile | 30 + 5 files changed, 987 insertions(+), 877 deletions(-) create mode 100644 asm.S mode change 100755 => 100644 definitions.h mode change 100755 => 100644 main.c create mode 100644 makefile diff --git a/.gitignore b/.gitignore index f039d96..6c90a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.a43 - +*.elf +*.hex diff --git a/asm.S b/asm.S new file mode 100644 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 . + +#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 diff --git a/definitions.h b/definitions.h old mode 100755 new mode 100644 index a869b44..94217cf --- a/definitions.h +++ b/definitions.h @@ -1,3 +1,22 @@ +// SilentTimer Action Figure software, v1.4 +// definitions.h +// Definitions used by the code. +// +// 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 . + //RTC commands: #define RTC_EEREAD 0x03 #define RTC_EEWRITE 0x02 @@ -69,4 +88,8 @@ #define MODE_DEBUGADDR 13 #define MODE_DEBUGVAL 14 -#define ALARMVALUE 0xa5 \ No newline at end of file +#define ALARMVALUE 0xa5 + +unsigned char bcd_add_byte (unsigned char, unsigned char); +void lpm3 (); + diff --git a/main.c b/main.c old mode 100755 new mode 100644 index c2e9f14..62b27d1 --- a/main.c +++ b/main.c @@ -1,882 +1,901 @@ -#include "msp430.h" -#include "definitions.h" +// SilentTimer Action Figure software, v1.4 +// main.c +// The main c file. +// +// 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 . -unsigned char inbuf[8]; -unsigned char outbuf[8]; -unsigned char dispvalue[4]; -unsigned char time[8]; -unsigned char leap; -unsigned char settime[3]; -unsigned char mode; -unsigned char alarm[3]; -unsigned char lastcdn[2]; -unsigned char lastyear[5]; -unsigned char digit; -unsigned char changed; -unsigned char run; -unsigned char symbol[16] ={ - SYMB_0, - SYMB_1, - SYMB_2, - SYMB_3, - SYMB_4, - SYMB_5, - SYMB_6, - SYMB_7, - SYMB_8, - SYMB_9, - SYMB_A, - SYMB_B, - SYMB_C, - SYMB_D, - SYMB_E, - SYMB_F}; + #include "msp430.h" + #include "definitions.h" -__interrupt void P2_ISR(); -void display( - unsigned char *data); -void spi( - unsigned char command, - unsigned char addr, - unsigned char *inbuf, - unsigned char *outbuf, - unsigned short n); -int main( void ); + unsigned char inbuf[8]; + unsigned char outbuf[8]; + unsigned char dispvalue[4]; + unsigned char time[8]; + unsigned char leap; + unsigned char settime[3]; + unsigned char mode; + unsigned char alarm[3]; + unsigned char lastcdn[2]; + unsigned char lastyear[5]; + unsigned char digit; + unsigned char changed; + unsigned char run; + unsigned char symbol[16] ={ + SYMB_0, + SYMB_1, + SYMB_2, + SYMB_3, + SYMB_4, + SYMB_5, + SYMB_6, + SYMB_7, + SYMB_8, + SYMB_9, + SYMB_A, + SYMB_B, + SYMB_C, + SYMB_D, + SYMB_E, + SYMB_F}; -void display(unsigned char *data) -{ - //lsd - P1OUT =data[0]; - P3OUT |=0x80; //74hc373 latch enable - P3OUT &=0x0f; - - P1OUT =data[1]; - P3OUT |=0x40; - P3OUT &=0x0f; - - P1OUT =data[2]; - P3OUT |=0x20; - P3OUT &=0x0f; - - //msd - P1OUT =data[3]; - P3OUT |=0x10; - P3OUT &=0x0f; -} + __interrupt void P2_ISR(); + void display( + unsigned char *data); + void spi( + unsigned char command, + unsigned char addr, + unsigned char *inbuf, + unsigned char *outbuf, + unsigned short n); + int main( void ); -void spi( - unsigned char command, - unsigned char addr, - unsigned char *inbuf, - unsigned char *outbuf, - unsigned short n) -{ - unsigned short i; - unsigned char nul; - unsigned char flags; - - switch (command) - { - case RTC_EEREAD: - case RTC_IDREAD: - case RTC_READ: - flags= ADDRFLAG|READFLAG; - break; - - case RTC_EEWRITE: - case RTC_IDWRITE: - n=(n>8)?8:n; - case RTC_WRITE: - flags= ADDRFLAG|WRITEFLAG; - break; - - case RTC_EEWREN: - case RTC_EEWRDI: - flags=0; - break; - - case RTC_SRREAD: - n=(n>1)?1:n; - flags=READFLAG; - break; - - case RTC_SRWRITE: //1 - case RTC_CLRRAM: //data ignored but has to be - case RTC_UNLOCK: //1 - n=(n>1)?1:n; - flags=WRITEFLAG; - break; - default: - return; - } - - P3OUT&=0xfe; //chip select down - - while((IFG2&UTXIFG0)==0); // wait until can be sent - U0TXBUF=command; // send command - while((IFG2&UTXIFG0)==0); // wait until received - nul=U0RXBUF; //pretend to read "data" - - if(flags&ADDRFLAG) - { - while((IFG2&UTXIFG0)==0); // wait until can be sent - U0TXBUF=addr; // send address - while((IFG2&UTXIFG0)==0); // wait until received - nul=U0RXBUF; //pretend to read "data" - } - if(flags&(READFLAG|WRITEFLAG)) - { - for(i=0;i55) - { - lastyear[3]=0; - - if(time[7]==0x00 && lastyear[0]==0x99) - lastyear[1]=__bcd_add_short(lastyear[1],0x01); - - lastyear[0]=time[7]; - - outbuf[0]=ALARMVALUE; - outbuf[1]=lastyear[0]; - outbuf[2]=lastyear[1]; - spi(RTC_WRITE,0x26,inbuf,outbuf,3); - } - } - - - if(mode==MODE_DEBUG && changed) - spi(RTC_READ,settime[1],settime,outbuf,1); - } - else if(P2IFG&0x02) // button A - { - P2IFG &= ~0x02; - switch(mode) - { - case MODE_TIME: - case MODE_SETDATE: - case MODE_SETYEAR: - mode=MODE_DATE; - break; - case MODE_DATE: - mode=MODE_COUNTUP; - settime[1]=0x00; - settime[2]=0x00; - run=0; - break; - case MODE_COUNTUP: - if(run) - { - settime[1]=0x00; - settime[2]=0x00; - run=0; - } - else - { - mode=MODE_SETCOUNTDOWN; - settime[1]=lastcdn[0]; - settime[2]=lastcdn[1]; - changed=0; - digit=3; - } - break; - case MODE_DEBUGADDR: - case MODE_DEBUGVAL: - mode=MODE_DEBUG; - break; - case MODE_SETCOUNTDOWN: - case MODE_COUNTDOWN: - if(changed || mode==MODE_COUNTDOWN) - { - mode=MODE_SETCOUNTDOWN; - settime[1]=lastcdn[0]; - settime[2]=lastcdn[1]; - changed=0; - digit=3; - break; - } - //case MODE_SETTIME: - //case MODE_SETALARM: - //case MODE_ALARM: - //case MODE_CALIBRATE: - //case MODE_DEBUG: - default: - mode=MODE_TIME; - break; - } - } - else if(P2IFG&0x01) // button B - { - P2IFG &= ~0x01; - - switch(mode) - { - case MODE_TIME: - mode=MODE_SETTIME; - digit=3; - changed=0; - settime[0]=0; - settime[1]=time[2]; - settime[2]=time[3]; - break; - case MODE_DATE: - mode=MODE_SETDATE; - digit=2; - changed=0; - settime[0]=time[5]; - settime[1]=time[6]; - break; - case MODE_COUNTUP: - case MODE_COUNTDOWN: - run=!run; - break; - case MODE_SETCOUNTDOWN: - if(digit) - { - --digit; - changed=1; - } - else - { - lastcdn[0]=settime[1]; - lastcdn[1]=settime[2]; - - outbuf[0]=ALARMVALUE; - outbuf[1]=settime[1]; - outbuf[2]=settime[2]; - spi(RTC_WRITE,0x23,inbuf,outbuf,3); + void spi( + unsigned char command, + unsigned char addr, + unsigned char *inbuf, + unsigned char *outbuf, + unsigned short n) + { + unsigned short i; + unsigned char nul; + unsigned char flags; + + switch (command) + { + case RTC_EEREAD: + case RTC_IDREAD: + case RTC_READ: + flags= ADDRFLAG|READFLAG; + break; + + case RTC_EEWRITE: + case RTC_IDWRITE: + n=(n>8)?8:n; + case RTC_WRITE: + flags= ADDRFLAG|WRITEFLAG; + break; + + case RTC_EEWREN: + case RTC_EEWRDI: + flags=0; + break; + + case RTC_SRREAD: + n=(n>1)?1:n; + flags=READFLAG; + break; + + case RTC_SRWRITE: //1 + case RTC_CLRRAM: //data ignored but has to be + case RTC_UNLOCK: //1 + n=(n>1)?1:n; + flags=WRITEFLAG; + break; + default: + return; + } + + P3OUT&=0xfe; //chip select down + + while((IFG2&UTXIFG0)==0); // wait until can be sent + U0TXBUF=command; // send command + while((IFG2&UTXIFG0)==0); // wait until received + nul=U0RXBUF; //pretend to read "data" + + if(flags&ADDRFLAG) + { + while((IFG2&UTXIFG0)==0); // wait until can be sent + U0TXBUF=addr; // send address + while((IFG2&UTXIFG0)==0); // wait until received + nul=U0RXBUF; //pretend to read "data" + } + if(flags&(READFLAG|WRITEFLAG)) + { + for(i=0;i0x23) - settime[2]&=0xf0; - --digit; - } - else - { - if(changed) - { - outbuf[0]=0x00; - outbuf[1]=0x00; - outbuf[2]=settime[1]&0x7f; - outbuf[3]=settime[2]&0x3f; - - spi(RTC_WRITE,0x01,inbuf,outbuf,1);//stop osc. - spi(RTC_READ,0x03,inbuf,outbuf,1); - outbuf[3]|=(inbuf[0]&0x80);//keep the calsgn bit. - - spi(RTC_WRITE,0x00,inbuf,outbuf,4);//write new time - - outbuf[0]=0x80; - spi(RTC_WRITE,0x01,inbuf,outbuf,1);//start osc; - - time[1]=0; - time[2]=settime[1]; - time[3]=settime[2]; - } - mode=MODE_TIME; - } - break; - case MODE_SETYEAR: - if(digit) - --digit; - else - { - if(changed) - { - time[7]=settime[1]; - spi(RTC_WRITE,0x07,inbuf,settime+1,1); - - lastyear[0]=settime[1]; - lastyear[1]=settime[2]; - settime[0]=ALARMVALUE; - - spi(RTC_WRITE,0x26,inbuf,settime,3); - } - mode=MODE_DATE; - } - break; - case MODE_SETDATE: - if(digit) - { - --digit; - if(settime[0]>((settime[1]==0x02)?(leap?0x29:0x28):(((settime[1]&0x18) && !(settime[1]&0x01) || !(settime[1]&0x18) && (settime[1]&0x01))?0x31:0x30))) - settime[0]&=(digit?0x00:0xf0); - if(settime[0]==0x00) - settime[0]=0x01; - } - else - { - if (changed) - { - time[5]=settime[0]; - time[6]=settime[1]; - settime[2]=time[7]; - spi(RTC_WRITE,0x06,inbuf,settime+1,2); - spi(RTC_WRITE,0x05,inbuf,settime,1); - } - mode=MODE_DATE; - } - - break; - case MODE_SETALARM: - if(digit) - { - if(digit==3&&settime[2]>0x23) - settime[2]&=0xf0; - --digit; - } - else - { - if(changed|| !alarm[0]) - { - alarm[0]=ALARMVALUE; - alarm[1]=settime[1]; - alarm[2]=settime[2]; - - spi(RTC_WRITE,0x20,inbuf,alarm,3); - } - else - { - alarm[0]=0; - spi(RTC_WRITE,0x20,inbuf,outbuf,1); - } - mode=MODE_TIME; - } - break; - case MODE_ALARM: - alarm[0]=0; - spi(RTC_WRITE,0x20,inbuf,outbuf,1); - mode=MODE_TIME; - break; - case MODE_DEBUG: - //changed=1; - digit=1; - mode=MODE_DEBUGADDR; - break; - default: - break; - } - } - else if(P2IFG&0x20) // button C - { - P2IFG &= ~0x20; - - switch(mode) - { - case MODE_COUNTUP: - settime[1]=0x00; - settime[2]=0x00; - break; - case MODE_COUNTDOWN: - settime[1]=lastcdn[0]; - settime[2]=lastcdn[1]; - changed=0; - mode=MODE_SETCOUNTDOWN; - digit=3; - break; - case MODE_CALIBRATE: - if(digit==2) - settime[1]^=0x80; - if(digit>=2) - break; - case MODE_DEBUGADDR: - case MODE_DEBUGVAL: - settime[(mode==MODE_DEBUGADDR)?1:0]+=(digit==1?0x10:(((settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f)==0x0f)?0xf1:0x01)); - break; - case MODE_SETTIME: - case MODE_SETALARM: - case MODE_SETYEAR: - case MODE_SETCOUNTDOWN: - changed=1; - //these 4 lines replaced a larger switch structure - if((settime[digit&0x02?2:1]&((digit&0x01)?0xf0:0x0f))<(digit==1?((mode==MODE_SETYEAR)?0x90:0x50):(digit==3?((mode==MODE_SETCOUNTDOWN||mode==MODE_SETYEAR)?0x90:0x20):((mode!=MODE_SETCOUNTDOWN&&mode!=MODE_SETYEAR&&digit==2&&settime[2]>0x19)?0x03:0x09)))) - settime[digit&0x02?2:1]+=((digit&0x01)?0x10:0x01); - else - settime[digit&0x02?2:1]&=((digit&0x01)?0x0f:0xf0); - break; - case MODE_SETDATE: - changed=1; - switch (digit) - { - case 2: - if(settime[1]<0x12) - settime[1]=__bcd_add_short(settime[1],0x01); - else - settime[1]=0x01; - break; - case 1: - if((settime[0]&0xf0)<((settime[1]==0x02)?0x20:0x30)) - settime[0]+=0x10; - else - settime[0]&=0x0f; - break; - - case 0: - if((settime[0]<((settime[1]==0x02)?(leap?0x29:0x28):(((settime[1]&0x18) && !(settime[1]&0x01) || !(settime[1]&0x18) && (settime[1]&0x01))?0x31:0x30))) && (settime[0]&0x0f)<0x09) - ++settime[0]; - else - settime[0]&=0xf0; - if(settime[0]==0x00) - settime[0]=0x01; - break; - } - break; - case MODE_DATE: - mode=MODE_SETYEAR; - digit=3; - changed=0; - - settime[1]=time[7]; - settime[2]=lastyear[1]; - break; - case MODE_TIME: - mode=MODE_SETALARM; - digit=3; - changed=0; - - settime[0]=0; - settime[1]=alarm[1]; //get last alarm time - if(settime[1]>0x59 || (settime[1]&0x0f)>0x09) - settime[1]=0x00; - settime[2]=alarm[2]; - if(settime[2]>0x23 || (settime[2]&0x0f)>0x09) - settime[2]=0x00; - break; - case MODE_ALARM: - alarm[0]=0; - spi(RTC_WRITE,0x20,inbuf,outbuf,1); - mode=MODE_TIME; - break; - case MODE_DEBUG: - if(changed) - { - digit=1; - mode=MODE_DEBUGVAL; - } - break; - default: - break; - } - } - else - P2IFG=0; - - switch(mode) - { - case MODE_SETTIME: - case MODE_SETALARM: - case MODE_SETCOUNTDOWN: - case MODE_SETYEAR: - dispvalue[0]=(symbol[settime[1]&0x0f] | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & ((((((time[1]+0x01)&0x02)^((time[1]&0x10)>>3))&&mode==MODE_SETCOUNTDOWN)||mode==MODE_SETYEAR)?SYMB_NUL:SYMB_DOT); - dispvalue[1]=(symbol[(settime[1]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & (((((time[1]&0x02)^((time[1]&0x10)>>3))&&mode==MODE_SETCOUNTDOWN)||mode==MODE_SETYEAR)?SYMB_NUL:SYMB_DOT); - dispvalue[2]=(symbol[settime[2]&0x0f] | ((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) ; - dispvalue[3]=(symbol[(settime[2]&0xf0)>>4] | ((digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & ((mode!=MODE_SETALARM && alarm[0] || mode==MODE_SETALARM && !(time[1]&0x01))?SYMB_DOT:SYMB_NUL); - break; - case MODE_DEBUGADDR: - case MODE_DEBUGVAL: - dispvalue[0]=(symbol[settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f] | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT; - dispvalue[1]=(symbol[(settime[(mode==MODE_DEBUGADDR)?1:0]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT; - dispvalue[2]=(mode==MODE_DEBUGADDR)?SYMB_A:SYMB_NUL; - dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL; - break; - case MODE_SETDATE: - dispvalue[0]=(symbol[settime[1]&0x0f]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8)); - dispvalue[1]=(symbol[(settime[1]&0xf0)>>4]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&SYMB_DOT; - dispvalue[2]=(symbol[settime[0]&0x0f]|((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)); - dispvalue[3]=(symbol[(settime[0]&0xf0)>>4]|((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&(alarm[0]?SYMB_DOT:SYMB_NUL); - break; - case MODE_CALIBRATE: - dispvalue[0]=symbol[settime[0]&0x0f]|((digit!=0 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8); - dispvalue[1]=symbol[(settime[0]&0xf0)>>4]|((digit!=1 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8); - dispvalue[2]=(settime[1]?SYMB_MIN:SYMB_NUL)|((digit!=2 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8); - dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL; - break; - case MODE_DATE: - if((time[1]&0x03)==((time[1]&0x10)?0x01:0x03)) - { - dispvalue[0]=symbol[time[7]&0x0f]; - dispvalue[1]=symbol[(time[7]&0xf0)>>4]; - dispvalue[2]=symbol[lastyear[4]&0x0f]; - dispvalue[3]=symbol[(lastyear[4]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL); - } - else - { - dispvalue[0]=symbol[time[6]&0x0f]; - dispvalue[1]=symbol[(time[6]&0xf0)>>4]&SYMB_DOT; - dispvalue[2]=symbol[time[5]&0x0f]; - dispvalue[3]=((time[5]&0xf0)?symbol[(time[5]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL); - } - break; - case MODE_COUNTDOWN: - if(!(settime[1]|settime[2])) - { - if(!run) - { - dispvalue[0]=SYMB_g&SYMB_DOT; - dispvalue[1]=SYMB_n&SYMB_DOT; - dispvalue[2]=SYMB_o; - dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL; - break; - } - run=0; - } - case MODE_COUNTUP: - dispvalue[0]=symbol[settime[1]&0x0f]&SYMB_DOT; - dispvalue[1]=symbol[(settime[1]&0xf0)>>4]&SYMB_DOT; - dispvalue[2]=symbol[settime[2]&0x0f]; - dispvalue[3]=((settime[2]&0xf0)?symbol[(settime[2]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL); - break; - case MODE_DEBUG: - if(changed) - { - dispvalue[0]=symbol[settime[0]&0x0f]&SYMB_DOT; - dispvalue[1]=symbol[(settime[0]&0xf0)>>4]&SYMB_DOT; - dispvalue[2]=symbol[settime[1]&0x0f]; - dispvalue[3]=symbol[(settime[1]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL); - } - else - { - dispvalue[0]=SYMB_NUL; - dispvalue[1]=SYMB_4&SYMB_DOT; - dispvalue[2]=SYMB_1; - dispvalue[3]=SYMB_NUL&(alarm[0]?SYMB_DOT:SYMB_NUL); - } - break; - case MODE_ALARM: - case MODE_TIME: - if(((time[1]&0x01) && mode==MODE_ALARM) || (time[3]==0x04 && time[2]==0x33 && time[1]==0x00)) - { - dispvalue[0]=SYMB_g; - dispvalue[1]=SYMB_n; - dispvalue[2]=SYMB_o; - dispvalue[3]=SYMB_DOT; - break; - } - default: - dispvalue[0]=symbol[time[2]&0x0f]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT); - dispvalue[1]=symbol[(time[2]&0xf0)>>4]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT); - dispvalue[2]=symbol[time[3]&0x0f]; - dispvalue[3]=((time[3]&0xf0)?symbol[(time[3]&0xf0)>>4]:SYMB_NUL)&((alarm[0] || mode==MODE_ALARM)?SYMB_DOT:SYMB_NUL); - break; - } - - display(dispvalue); - - - return; -} + #pragma vector=PORT2_VECTOR + __interrupt void P2_ISR() + { + if(P2IFG&0x08) // RTC + { + P2IFG &= ~0x08; + spi(RTC_READ,0x00,inbuf,outbuf,8); + + time[0]=inbuf[0]; //1/100 s + time[1]=inbuf[1]&0x7f; //seconds + time[2]=inbuf[2]&0x7f; //minutes + time[3]=inbuf[3]&0x3f; //hours + time[4]=inbuf[4]&0x07; //dow + time[5]=inbuf[5]&0x3f; //dom + time[6]=inbuf[6]&0x1f; //mon + time[7]=inbuf[7];//year + leap=inbuf[6]&0x20; + + spi(RTC_READ,0x0f,inbuf,outbuf,1); // <- because of RTC bug (probably not needed anymore?) + if(!((time[2]^alarm[1])|(time[3]^alarm[2])) && alarm[0]) + { + mode=MODE_ALARM; + alarm[0]=0; //alarm removed after activated + spi(RTC_WRITE,0x20,inbuf,alarm,1); + } + + if(mode==MODE_COUNTUP && run) + { + if(settime[1]<0x59) + settime[1]=bcd_add_byte(settime[1],0x01); + else + { + settime[1]=0x00; + settime[2]=bcd_add_byte(settime[2],0x01); + } + } + else if(mode==MODE_COUNTDOWN && run && (settime[1]|settime[2])) + { + if(settime[1]) + settime[1]=bcd_add_byte(settime[1],0x99); + else + { + settime[1]=0x59; + settime[2]=bcd_add_byte(settime[2],0x99); + } + } + + if (mode==MODE_ALARM || (mode==MODE_COUNTDOWN && !(settime[1]|settime[2]))) + { + TACTL^=MC_1; + //P2DIR^=0x40; + //P2SEL^=0x40; + } + else if(TACTL & MC_3) + { + TACTL&= ~MC_3; + //P2DIR&= ~0x40; + //P2SEL&= ~0x40; + } + + lastyear[4]=(time[7]==0x00 && lastyear[0]==0x99)?bcd_add_byte(lastyear[1],0x01):lastyear[1]; + if (time[7]!=lastyear[0]) + { + if(time[7]==lastyear[2]) + ++(lastyear[3]); + else + lastyear[3]=0; + + lastyear[2]=time[7]; + + if(lastyear[3]>55) + { + lastyear[3]=0; + + if(time[7]==0x00 && lastyear[0]==0x99) + lastyear[1]=bcd_add_byte(lastyear[1],0x01); + + lastyear[0]=time[7]; + + outbuf[0]=ALARMVALUE; + outbuf[1]=lastyear[0]; + outbuf[2]=lastyear[1]; + spi(RTC_WRITE,0x26,inbuf,outbuf,3); + } + } + + + if(mode==MODE_DEBUG && changed) + spi(RTC_READ,settime[1],settime,outbuf,1); + } + else if(P2IFG&0x02) // button A + { + P2IFG &= ~0x02; + switch(mode) + { + case MODE_TIME: + case MODE_SETDATE: + case MODE_SETYEAR: + mode=MODE_DATE; + break; + case MODE_DATE: + mode=MODE_COUNTUP; + settime[1]=0x00; + settime[2]=0x00; + run=0; + break; + case MODE_COUNTUP: + if(run) + { + settime[1]=0x00; + settime[2]=0x00; + run=0; + } + else + { + mode=MODE_SETCOUNTDOWN; + settime[1]=lastcdn[0]; + settime[2]=lastcdn[1]; + changed=0; + digit=3; + } + break; + case MODE_DEBUGADDR: + case MODE_DEBUGVAL: + mode=MODE_DEBUG; + break; + case MODE_SETCOUNTDOWN: + case MODE_COUNTDOWN: + if(changed || mode==MODE_COUNTDOWN) + { + mode=MODE_SETCOUNTDOWN; + settime[1]=lastcdn[0]; + settime[2]=lastcdn[1]; + changed=0; + digit=3; + break; + } + //case MODE_SETTIME: + //case MODE_SETALARM: + //case MODE_ALARM: + //case MODE_CALIBRATE: + //case MODE_DEBUG: + default: + mode=MODE_TIME; + break; + } + } + else if(P2IFG&0x01) // button B + { + P2IFG &= ~0x01; + + switch(mode) + { + case MODE_TIME: + mode=MODE_SETTIME; + digit=3; + changed=0; + settime[0]=0; + settime[1]=time[2]; + settime[2]=time[3]; + break; + case MODE_DATE: + mode=MODE_SETDATE; + digit=2; + changed=0; + settime[0]=time[5]; + settime[1]=time[6]; + break; + case MODE_COUNTUP: + case MODE_COUNTDOWN: + run=!run; + break; + case MODE_SETCOUNTDOWN: + if(digit) + { + --digit; + changed=1; + } + else + { + lastcdn[0]=settime[1]; + lastcdn[1]=settime[2]; + + outbuf[0]=ALARMVALUE; + outbuf[1]=settime[1]; + outbuf[2]=settime[2]; + spi(RTC_WRITE,0x23,inbuf,outbuf,3); -int main( void ) -{ - unsigned char delay; - - //watchdog: - WDTCTL = WDTPW + WDTHOLD; - - mode=MODE_INIT; - - //init 7 segment display - - P1OUT =0xff; //display data on p1 - P1DIR =0xff; - - P3OUT &=0x0f; //display control on p3.4-7 - P3DIR |=0xf0; - - dispvalue[0]=SYMB_NUL; - dispvalue[1]=SYMB_o; - dispvalue[2]=SYMB_o; - dispvalue[3]=SYMB_NUL; - - display(dispvalue); - - //clocking: - - BCSCTL2 |= DIVM_3; //errata sheet recommends this here - - DCOCTL =0x00; - BCSCTL1 = - RSEL2| //in the - XTS| //hi freq - DIVA_1; //ACLK = 6/2 MHz - - do - { - IFG1 &= ~OFIFG; - for (delay = 0xFF; delay > 0; --delay); - } - while ((IFG1 & OFIFG)); - - BCSCTL2 = - SELM_2| //MCLK from XT2 - DIVM_1| //MCLK = 6/2 MHz - SELS| //SMCLK from XT2 - DIVS_0; //SMCLK = 6/1 MHz - - //init SPI - - P3SEL =0x0e; // SPI on p3.1, 3.2, 3.3 - P3OUT |=0x01; - P3DIR |=0x01; //RTC CS on p3.0 - - U0CTL = - SWRST| //reset - MM| //master - SYNC| //SPI mode - CHAR; //8 bit data - U0TCTL= - CKPH| //polarity and phase - SSEL0|SSEL1| //SMCLK - STC; //3 pin mode - U0BR1=0x00; - U0BR0=0x02; //baudrate = SMCLK/2 = 3MHz - U0MCTL=0x00; - ME2|=USPIE0; - U0CTL &= ~SWRST; - - - //init RTC - - //Looks like sometimes the first SPI reads rom the RTC may be incorrect. - //To be sure, let's do a few redundant reads before starting the real work - - for (delay = 0xFF; delay > 0; --delay) - spi(RTC_READ,0x00,inbuf,outbuf,1); - - //set 24 hour mode - spi(RTC_READ,0x03,inbuf,outbuf,1); - if(inbuf[0]&0x40) - { - outbuf[0]=inbuf[0]&(~0x40); - spi(RTC_WRITE,0x03,inbuf,outbuf,1); - } - - //enable battery - spi(RTC_READ,0x04,inbuf,outbuf,1); - if(!(inbuf[0]&0x08)) - { - outbuf[0]=inbuf[0]|0x08; //enable battery - spi(RTC_WRITE,0x04,inbuf,outbuf,1); - } - - //set control register - //spi(RTC_READ,0x08,inbuf,outbuf,1); - outbuf[0]= - 0x40| //squarewave enable - 0x04; //1Hz - //no hardware alarms :( - spi(RTC_WRITE,0x08,inbuf,outbuf,1); - - //get (soft) alarm from RTC SRAM - spi(RTC_READ,0x20,inbuf,outbuf,3); - - alarm[0]=(inbuf[0]==ALARMVALUE)?ALARMVALUE:0; - alarm[1]=inbuf[1]; - alarm[2]=inbuf[2]; - - spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?) - - //get last countdown value from RTC SRAM - spi(RTC_READ,0x23,inbuf,outbuf,3); - if(inbuf[0]==ALARMVALUE) - { - lastcdn[0]=inbuf[1]; - lastcdn[1]=inbuf[2]; - } - else - { - lastcdn[0]=0; - lastcdn[1]=0; - } - - spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?) - - //get last year value from RTC SRAM - spi(RTC_READ,0x26,inbuf,outbuf,3); - if(inbuf[0]==ALARMVALUE) - { - lastyear[0]=inbuf[1]; - lastyear[1]=inbuf[2]; - } - else - { - lastyear[0]=0x00; - lastyear[1]=0x20; - } - lastyear[3]=0; - - //start oscillator - spi(RTC_READ,0x01,inbuf,outbuf,1); - if(!(inbuf[0]&0x80)) - { - outbuf[0]=inbuf[0]|0x80; - spi(RTC_WRITE,0x01,inbuf,outbuf,1); - } - - //init timer: - TACCR0 = 375-1; //3MHz/375/2=4kHz - TACCTL0= //also, compare, not capture - OUTMOD_4; //toggle - TACTL= - TASSEL_1| //ACLK, 3MHz - ID_0| //3MHz/1 - //MC_1| //up mode - TACLR; //reset - P2SEL|=0x04; //P2.2 timer output. - P2DIR|=0x04; - - // Init interrupts - P2IE= - 0x08| //p2.3 - int. from RTC - 0x02| //p2.1 - int. from button A - 0x01| //p2.0 - int. from button B - 0x20; //p2.5 - int. from button C - P2IES|=0x01|0x02|0x20; //button int. on falling edge - P2IES&= ~0x08; //RTC int. on rising edge - P2IFG=0x00; - - if(!(P2IN&0x02)) //button A pressed at start? - { - mode=MODE_CALIBRATE; - spi(RTC_READ,0x03,inbuf,outbuf,1); - settime[1]=inbuf[0]&0x80; - spi(RTC_READ,0x09,inbuf,outbuf,1); - settime[0]=inbuf[0]; - digit=3; - } - else if(!(P2IN&0x20)) //button C pressed at start? - { - mode=MODE_DEBUG; - settime[1]=0x00; - changed=0; - } - else - mode=MODE_TIME; - - __enable_interrupt(); - - - while(1) - { - __low_power_mode_3(); - } -} + mode=MODE_COUNTDOWN; + run=0; + } + break; + case MODE_CALIBRATE: + if(digit) + --digit; + else + { + spi(RTC_WRITE,0x09,inbuf,settime,1); + outbuf[0]=time[3]|settime[1]; + spi(RTC_WRITE,0x03,inbuf,outbuf,1); + digit=3; + } + break; + case MODE_DEBUGADDR: + if(digit) + --digit; + else + { + spi(RTC_READ,settime[1],settime,outbuf,1); + mode=MODE_DEBUG; + changed=1; + } + break; + case MODE_DEBUGVAL: + if(digit) + --digit; + else + { + spi(RTC_WRITE,settime[1],inbuf,settime,1); + mode=MODE_DEBUG; + } + break; + case MODE_SETTIME: + if(digit) + { + if(digit==3&&settime[2]>0x23) + settime[2]&=0xf0; + --digit; + } + else + { + if(changed) + { + outbuf[0]=0x00; + outbuf[1]=0x00; + outbuf[2]=settime[1]&0x7f; + outbuf[3]=settime[2]&0x3f; + + spi(RTC_WRITE,0x01,inbuf,outbuf,1);//stop osc. + spi(RTC_READ,0x03,inbuf,outbuf,1); + outbuf[3]|=(inbuf[0]&0x80);//keep the calsgn bit. + + spi(RTC_WRITE,0x00,inbuf,outbuf,4);//write new time + + outbuf[0]=0x80; + spi(RTC_WRITE,0x01,inbuf,outbuf,1);//start osc; + + time[1]=0; + time[2]=settime[1]; + time[3]=settime[2]; + } + mode=MODE_TIME; + } + break; + case MODE_SETYEAR: + if(digit) + --digit; + else + { + if(changed) + { + time[7]=settime[1]; + spi(RTC_WRITE,0x07,inbuf,settime+1,1); + + lastyear[0]=settime[1]; + lastyear[1]=settime[2]; + settime[0]=ALARMVALUE; + + spi(RTC_WRITE,0x26,inbuf,settime,3); + } + mode=MODE_DATE; + } + break; + case MODE_SETDATE: + if(digit) + { + --digit; + if(settime[0]>((settime[1]==0x02)?(leap?0x29:0x28):(((settime[1]&0x18) && !(settime[1]&0x01) || !(settime[1]&0x18) && (settime[1]&0x01))?0x31:0x30))) + settime[0]&=(digit?0x00:0xf0); + if(settime[0]==0x00) + settime[0]=0x01; + } + else + { + if (changed) + { + time[5]=settime[0]; + time[6]=settime[1]; + settime[2]=time[7]; + spi(RTC_WRITE,0x06,inbuf,settime+1,2); + spi(RTC_WRITE,0x05,inbuf,settime,1); + } + mode=MODE_DATE; + } + + break; + case MODE_SETALARM: + if(digit) + { + if(digit==3&&settime[2]>0x23) + settime[2]&=0xf0; + --digit; + } + else + { + if(changed|| !alarm[0]) + { + alarm[0]=ALARMVALUE; + alarm[1]=settime[1]; + alarm[2]=settime[2]; + + spi(RTC_WRITE,0x20,inbuf,alarm,3); + } + else + { + alarm[0]=0; + spi(RTC_WRITE,0x20,inbuf,outbuf,1); + } + mode=MODE_TIME; + } + break; + case MODE_ALARM: + alarm[0]=0; + spi(RTC_WRITE,0x20,inbuf,outbuf,1); + mode=MODE_TIME; + break; + case MODE_DEBUG: + //changed=1; + digit=1; + mode=MODE_DEBUGADDR; + break; + default: + break; + } + } + else if(P2IFG&0x20) // button C + { + P2IFG &= ~0x20; + + switch(mode) + { + case MODE_COUNTUP: + settime[1]=0x00; + settime[2]=0x00; + break; + case MODE_COUNTDOWN: + settime[1]=lastcdn[0]; + settime[2]=lastcdn[1]; + changed=0; + mode=MODE_SETCOUNTDOWN; + digit=3; + break; + case MODE_CALIBRATE: + if(digit==2) + settime[1]^=0x80; + if(digit>=2) + break; + case MODE_DEBUGADDR: + case MODE_DEBUGVAL: + settime[(mode==MODE_DEBUGADDR)?1:0]+=(digit==1?0x10:(((settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f)==0x0f)?0xf1:0x01)); + break; + case MODE_SETTIME: + case MODE_SETALARM: + case MODE_SETYEAR: + case MODE_SETCOUNTDOWN: + changed=1; + //these 4 lines replaced a larger switch structure + if((settime[digit&0x02?2:1]&((digit&0x01)?0xf0:0x0f))<(digit==1?((mode==MODE_SETYEAR)?0x90:0x50):(digit==3?((mode==MODE_SETCOUNTDOWN||mode==MODE_SETYEAR)?0x90:0x20):((mode!=MODE_SETCOUNTDOWN&&mode!=MODE_SETYEAR&&digit==2&&settime[2]>0x19)?0x03:0x09)))) + settime[digit&0x02?2:1]+=((digit&0x01)?0x10:0x01); + else + settime[digit&0x02?2:1]&=((digit&0x01)?0x0f:0xf0); + break; + case MODE_SETDATE: + changed=1; + switch (digit) + { + case 2: + if(settime[1]<0x12) + settime[1]=bcd_add_byte(settime[1],0x01); + else + settime[1]=0x01; + break; + case 1: + if((settime[0]&0xf0)<((settime[1]==0x02)?0x20:0x30)) + settime[0]+=0x10; + else + settime[0]&=0x0f; + break; + + case 0: + if((settime[0]<((settime[1]==0x02)?(leap?0x29:0x28):(((settime[1]&0x18) && !(settime[1]&0x01) || !(settime[1]&0x18) && (settime[1]&0x01))?0x31:0x30))) && (settime[0]&0x0f)<0x09) + ++settime[0]; + else + settime[0]&=0xf0; + if(settime[0]==0x00) + settime[0]=0x01; + break; + } + break; + case MODE_DATE: + mode=MODE_SETYEAR; + digit=3; + changed=0; + + settime[1]=time[7]; + settime[2]=lastyear[1]; + break; + case MODE_TIME: + mode=MODE_SETALARM; + digit=3; + changed=0; + + settime[0]=0; + settime[1]=alarm[1]; //get last alarm time + if(settime[1]>0x59 || (settime[1]&0x0f)>0x09) + settime[1]=0x00; + settime[2]=alarm[2]; + if(settime[2]>0x23 || (settime[2]&0x0f)>0x09) + settime[2]=0x00; + break; + case MODE_ALARM: + alarm[0]=0; + spi(RTC_WRITE,0x20,inbuf,outbuf,1); + mode=MODE_TIME; + break; + case MODE_DEBUG: + if(changed) + { + digit=1; + mode=MODE_DEBUGVAL; + } + break; + default: + break; + } + } + else + P2IFG=0; + + switch(mode) + { + case MODE_SETTIME: + case MODE_SETALARM: + case MODE_SETCOUNTDOWN: + case MODE_SETYEAR: + dispvalue[0]=(symbol[settime[1]&0x0f] | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & ((((((time[1]+0x01)&0x02)^((time[1]&0x10)>>3))&&mode==MODE_SETCOUNTDOWN)||mode==MODE_SETYEAR)?SYMB_NUL:SYMB_DOT); + dispvalue[1]=(symbol[(settime[1]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & (((((time[1]&0x02)^((time[1]&0x10)>>3))&&mode==MODE_SETCOUNTDOWN)||mode==MODE_SETYEAR)?SYMB_NUL:SYMB_DOT); + dispvalue[2]=(symbol[settime[2]&0x0f] | ((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) ; + dispvalue[3]=(symbol[(settime[2]&0xf0)>>4] | ((digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) & ((mode!=MODE_SETALARM && alarm[0] || mode==MODE_SETALARM && !(time[1]&0x01))?SYMB_DOT:SYMB_NUL); + break; + case MODE_DEBUGADDR: + case MODE_DEBUGVAL: + dispvalue[0]=(symbol[settime[(mode==MODE_DEBUGADDR)?1:0]&0x0f] | ((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT; + dispvalue[1]=(symbol[(settime[(mode==MODE_DEBUGADDR)?1:0]&0xf0)>>4] | ((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8)) &SYMB_DOT; + dispvalue[2]=(mode==MODE_DEBUGADDR)?SYMB_A:SYMB_NUL; + dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL; + break; + case MODE_SETDATE: + dispvalue[0]=(symbol[settime[1]&0x0f]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8)); + dispvalue[1]=(symbol[(settime[1]&0xf0)>>4]|((digit!=2 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&SYMB_DOT; + dispvalue[2]=(symbol[settime[0]&0x0f]|((digit!=0 && (time[1]&0x01))?SYMB_NUL:SYMB_8)); + dispvalue[3]=(symbol[(settime[0]&0xf0)>>4]|((digit!=1 && (time[1]&0x01))?SYMB_NUL:SYMB_8))&(alarm[0]?SYMB_DOT:SYMB_NUL); + break; + case MODE_CALIBRATE: + dispvalue[0]=symbol[settime[0]&0x0f]|((digit!=0 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8); + dispvalue[1]=symbol[(settime[0]&0xf0)>>4]|((digit!=1 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8); + dispvalue[2]=(settime[1]?SYMB_MIN:SYMB_NUL)|((digit!=2 && digit!=3 && (time[1]&0x01))?SYMB_NUL:SYMB_8); + dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL; + break; + case MODE_DATE: + if((time[1]&0x03)==((time[1]&0x10)?0x01:0x03)) + { + dispvalue[0]=symbol[time[7]&0x0f]; + dispvalue[1]=symbol[(time[7]&0xf0)>>4]; + dispvalue[2]=symbol[lastyear[4]&0x0f]; + dispvalue[3]=symbol[(lastyear[4]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL); + } + else + { + dispvalue[0]=symbol[time[6]&0x0f]; + dispvalue[1]=symbol[(time[6]&0xf0)>>4]&SYMB_DOT; + dispvalue[2]=symbol[time[5]&0x0f]; + dispvalue[3]=((time[5]&0xf0)?symbol[(time[5]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL); + } + break; + case MODE_COUNTDOWN: + if(!(settime[1]|settime[2])) + { + if(!run) + { + dispvalue[0]=SYMB_g&SYMB_DOT; + dispvalue[1]=SYMB_n&SYMB_DOT; + dispvalue[2]=SYMB_o; + dispvalue[3]=alarm[0]?SYMB_DOT:SYMB_NUL; + break; + } + run=0; + } + case MODE_COUNTUP: + dispvalue[0]=symbol[settime[1]&0x0f]&SYMB_DOT; + dispvalue[1]=symbol[(settime[1]&0xf0)>>4]&SYMB_DOT; + dispvalue[2]=symbol[settime[2]&0x0f]; + dispvalue[3]=((settime[2]&0xf0)?symbol[(settime[2]&0xf0)>>4]:SYMB_NUL)&(alarm[0]?SYMB_DOT:SYMB_NUL); + break; + case MODE_DEBUG: + if(changed) + { + dispvalue[0]=symbol[settime[0]&0x0f]&SYMB_DOT; + dispvalue[1]=symbol[(settime[0]&0xf0)>>4]&SYMB_DOT; + dispvalue[2]=symbol[settime[1]&0x0f]; + dispvalue[3]=symbol[(settime[1]&0xf0)>>4]&(alarm[0]?SYMB_DOT:SYMB_NUL); + } + else + { + dispvalue[0]=SYMB_NUL; + dispvalue[1]=SYMB_4&SYMB_DOT; + dispvalue[2]=SYMB_1; + dispvalue[3]=SYMB_NUL&(alarm[0]?SYMB_DOT:SYMB_NUL); + } + break; + case MODE_ALARM: + case MODE_TIME: + if(((time[1]&0x01) && mode==MODE_ALARM) || (time[3]==0x04 && time[2]==0x33 && time[1]==0x00)) + { + dispvalue[0]=SYMB_g; + dispvalue[1]=SYMB_n; + dispvalue[2]=SYMB_o; + dispvalue[3]=SYMB_DOT; + break; + } + default: + dispvalue[0]=symbol[time[2]&0x0f]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT); + dispvalue[1]=symbol[(time[2]&0xf0)>>4]&((time[1]&0x01)?SYMB_NUL:SYMB_DOT); + dispvalue[2]=symbol[time[3]&0x0f]; + dispvalue[3]=((time[3]&0xf0)?symbol[(time[3]&0xf0)>>4]:SYMB_NUL)&((alarm[0] || mode==MODE_ALARM)?SYMB_DOT:SYMB_NUL); + break; + } + + display(dispvalue); + + + return; + } + + int main( void ) + { + unsigned char delay; + + //watchdog: + WDTCTL = WDTPW + WDTHOLD; + + mode=MODE_INIT; + + //init 7 segment display + + P1OUT =0xff; //display data on p1 + P1DIR =0xff; + + P3OUT &=0x0f; //display control on p3.4-7 + P3DIR |=0xf0; + + dispvalue[0]=SYMB_NUL; + dispvalue[1]=SYMB_o; + dispvalue[2]=SYMB_o; + dispvalue[3]=SYMB_NUL; + + display(dispvalue); + + //clocking: + + BCSCTL2 |= DIVM_3; //errata sheet recommends this here + + DCOCTL =0x00; + BCSCTL1 = + RSEL2| //in the + XTS| //hi freq + DIVA_1; //ACLK = 6/2 MHz + + do + { + IFG1 &= ~OFIFG; + for (delay = 0xFF; delay > 0; --delay); + } + while ((IFG1 & OFIFG)); + + BCSCTL2 = + SELM_2| //MCLK from XT2 + DIVM_1| //MCLK = 6/2 MHz + SELS| //SMCLK from XT2 + DIVS_0; //SMCLK = 6/1 MHz + + //init SPI + + P3SEL =0x0e; // SPI on p3.1, 3.2, 3.3 + P3OUT |=0x01; + P3DIR |=0x01; //RTC CS on p3.0 + + U0CTL = + SWRST| //reset + MM| //master + SYNC| //SPI mode + CHAR; //8 bit data + U0TCTL= + CKPH| //polarity and phase + SSEL0|SSEL1| //SMCLK + STC; //3 pin mode + U0BR1=0x00; + U0BR0=0x02; //baudrate = SMCLK/2 = 3MHz + U0MCTL=0x00; + ME2|=USPIE0; + U0CTL &= ~SWRST; + + + //init RTC + + //Looks like sometimes the first SPI reads rom the RTC may be incorrect. + //To be sure, let's do a few redundant reads before starting the real work + + for (delay = 0xFF; delay > 0; --delay) + spi(RTC_READ,0x00,inbuf,outbuf,1); + + //set 24 hour mode + spi(RTC_READ,0x03,inbuf,outbuf,1); + if(inbuf[0]&0x40) + { + outbuf[0]=inbuf[0]&(~0x40); + spi(RTC_WRITE,0x03,inbuf,outbuf,1); + } + + //enable battery + spi(RTC_READ,0x04,inbuf,outbuf,1); + if(!(inbuf[0]&0x08)) + { + outbuf[0]=inbuf[0]|0x08; //enable battery + spi(RTC_WRITE,0x04,inbuf,outbuf,1); + } + + //set control register + //spi(RTC_READ,0x08,inbuf,outbuf,1); + outbuf[0]= + 0x40| //squarewave enable + 0x04; //1Hz + //no hardware alarms :( + spi(RTC_WRITE,0x08,inbuf,outbuf,1); + + //get (soft) alarm from RTC SRAM + spi(RTC_READ,0x20,inbuf,outbuf,3); + + alarm[0]=(inbuf[0]==ALARMVALUE)?ALARMVALUE:0; + alarm[1]=inbuf[1]; + alarm[2]=inbuf[2]; + + spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?) + + //get last countdown value from RTC SRAM + spi(RTC_READ,0x23,inbuf,outbuf,3); + if(inbuf[0]==ALARMVALUE) + { + lastcdn[0]=inbuf[1]; + lastcdn[1]=inbuf[2]; + } + else + { + lastcdn[0]=0; + lastcdn[1]=0; + } + + spi(RTC_READ,0x2f,inbuf,outbuf,1); // <- because of RTC bug (?) + + //get last year value from RTC SRAM + spi(RTC_READ,0x26,inbuf,outbuf,3); + if(inbuf[0]==ALARMVALUE) + { + lastyear[0]=inbuf[1]; + lastyear[1]=inbuf[2]; + } + else + { + lastyear[0]=0x00; + lastyear[1]=0x20; + } + lastyear[3]=0; + + //start oscillator + spi(RTC_READ,0x01,inbuf,outbuf,1); + if(!(inbuf[0]&0x80)) + { + outbuf[0]=inbuf[0]|0x80; + spi(RTC_WRITE,0x01,inbuf,outbuf,1); + } + + //init timer: + TACCR0 = 375-1; //3MHz/375/2=4kHz + TACCTL0= //also, compare, not capture + OUTMOD_4; //toggle + TACTL= + TASSEL_1| //ACLK, 3MHz + ID_0| //3MHz/1 + //MC_1| //up mode + TACLR; //reset + P2SEL|=0x04; //P2.2 timer output. + P2DIR|=0x04; + + // Init interrupts + P2IE= + 0x08| //p2.3 - int. from RTC + 0x02| //p2.1 - int. from button A + 0x01| //p2.0 - int. from button B + 0x20; //p2.5 - int. from button C + P2IES|=0x01|0x02|0x20; //button int. on falling edge + P2IES&= ~0x08; //RTC int. on rising edge + P2IFG=0x00; + + if(!(P2IN&0x02)) //button A pressed at start? + { + mode=MODE_CALIBRATE; + spi(RTC_READ,0x03,inbuf,outbuf,1); + settime[1]=inbuf[0]&0x80; + spi(RTC_READ,0x09,inbuf,outbuf,1); + settime[0]=inbuf[0]; + digit=3; + } + else if(!(P2IN&0x20)) //button C pressed at start? + { + mode=MODE_DEBUG; + settime[1]=0x00; + changed=0; + } + else + mode=MODE_TIME; + + __enable_interrupt(); + + + while(1) + { + lpm3(); + } + } diff --git a/makefile b/makefile new file mode 100644 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 . + +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 -- 2.30.2