2012年9月23日日曜日

MSP430時計のソフトウェアをアップデート

昨年製作して、MTM07とC81で展示していたMSP430を使った時計のソフトウェアを更新し、時刻合わせの機能を付加しました。

最近の電子式時計では操作用の押しボタンスイッチが機能別に複数取り付けられているようで、1つのボタンを長押しとそれ以外で機能を共用させる方式は流行らない様なのですが、汎用ポートの数が限られているのでスイッチの数を抑制する方向で設計しました。

コメント等がほとんど無く、不要なマクロ定義がありますが、暫定版として公開いたします。


#include  

// State Machines That Gray Coded Style
#define INITIAL   0x00 // bin 0000_0000
#define HOLD      0x01 // bin 0000_0001
#define MIN_SET   0x03 // bin 0000_0011
#define HUR_SET   0x04 // bin 0000_0100
#define CNT_DN    0x07 // bin 0000_0111
#define ALARM     0x06 // bin 0000_0110
#define STOP      0x05 // bin 0000_0101
#define SET_CLOCK 0x08 // bin 0000_1000

unsigned char state; // External Variable Used to Keep State 
unsigned int set_min;
unsigned int set_hour;
unsigned char cnt_dn;
unsigned char intf;
unsigned char ccintf;
unsigned char sec;

unsigned char length;

unsigned char gstate;

static unsigned char hour,min,min_base,hour_base;

void sr164_set (unsigned char hour, unsigned char min) {
 unsigned char i,h,m,s;
  h = hour;
  m = min;
 
 for(i=0;i<16;i++){
  if(i<8){
   P1OUT &= 0x2F;
   s = 0x80 & h;
   if(s){
    P1OUT |= 0x80 + 0x20 + 0x0C;
   }else{
    P1OUT &= 0x7F;
   }
   h = h * 2;
   P1OUT |= 0x4C;
  }
  else{
   P1OUT &= 0x2F;
   s = 0x80 & m;
   if(s){
    P1OUT |= 0x80 + 0x20 + 0x0C;
   }else{
    P1OUT &= 0x7F;
   }
   m = m * 2;
   P1OUT |= 0x4C;
  }
 }

}

void set_clock(void){
 unsigned char lstate;
 P1IE &=~0x0C;
 lstate = 0;
 
 while ((P1IN & 0x08)==0);
 
 while (lstate < 2){
  while(lstate == 0){
   if(((P1IN & 0x04)==0)){
    if(min_base<59){
       min_base++;
      }else{
       min_base=0;
    }
    min = ((min_base/10) * 16) + (min_base % 10);   
    sr164_set(hour,min);
    while((P1IN & 0x04)==0);
   }else if((P1IN & 0x08)==0){
    lstate++;
   }
  }
  
  while ((P1IN & 0x08)==0);
  P1OUT &=0x2C;
  
  while(lstate == 1){
   if(((P1IN & 0x04)==0)){
    if(hour_base<23){
       hour_base++;
      }else{
       hour_base=0;
    }
    hour = ((hour_base/10) * 16) + (hour_base % 10);   
    sr164_set(hour,min);   
    while((P1IN & 0x04)==0);
   }else if((P1IN & 0x08)==0){
    lstate++;
   }
  }
 }
 TACCTL0 |= CCIE;
 gstate = INITIAL;
}

void main (void)
{
  volatile unsigned int i,j,m,n,p,q;
  
  // Initial Settings
  cnt_dn = 0;
  intf = 0;
  ccintf = 0;
  sec = 0x00;
  set_min = 0x00;
  set_hour = 0x00;
  length = 0;
  gstate = INITIAL;
  //state = INITIAL; // State Machine Initialize
  
  // X'tal and Timer Settings
  WDTCTL = WDTPW + WDTHOLD;                        // Stop watchdog timer
  BCSCTL3 |= XCAP_3;                               // Set X_CAP 12.5pF
  TACTL = TASSEL_1 + MC_1 + TACLR;                 // ACLK, up mode, Timer CLR
  TACCTL0 = CCIE;
  CCR0 = 0x7FFF;                                   // Set TACCR0 to 16383
  
  // GPIO Settings
  P1DIR |= 0xF3;                                   // Set LED Port Output
  P1IE |= 0x0C;                                    // P1.3, P1.4 Interrupt Enable
  P1IES |= 0x0C;                                   // P1.3, P1.4 Fall Edge Interrupt Enable
  P1IFG &= ~0x0C;                                  // P1 Interrupt state Cleared
  P1OUT=0xEF;
  
  // When X'tal OSC is fault, Red LED Blink
  while (BCSCTL3 & LFXT1OF) {
    // Blink LED and Buzzer
    for(j=80;j>0;j--){
     P1OUT ^= 0x03;
     for(i=63;i>0;i--){;}
    }
  }

  /* Assign Slow Clock to System Clock */
  BCSCTL2 |= SELM_3 + SELS; // MCLK and SMCLK assigned to CPU and Peripheral Clock
  _BIS_SR(LPM3_bits - CPUOFF + GIE);

 P1OUT &= 0xAC;
 P1OUT |= 0x2C;
 
 sr164_set(0xFF, 0xFF);

// sr164_set(0x00,0x00);
 
 hour = 0x00;
 min = 0x00;
 hour_base = 0;
 min_base = 0;
 i = 0;

 while(1){
  
  if(ccintf==1){
     ccintf=0;

     if(((P1IN & 0x08)==0) && (length < 3)){
      length++;
     }else if(length > 2){
      length = 0;
      gstate = SET_CLOCK;
     }else if(P1IN & 0x08){
      length = 0;
     }
    
     if(intf>0){
    if(sec & 0x0001){P1OUT &= 0xAC;}
    else if(~(sec & 0x0001)){P1OUT |= 0x2F;}
     }
     if(gstate == SET_CLOCK){
      P1OUT |=0x2F;
      set_clock();
     }else if((cnt_dn>0) && (sec==0)){
    sr164_set(hour,min);
    cnt_dn--;
   }else if(cnt_dn == 0){
    sr164_set(0xFF,0xFF);
    P1OUT &= 0xAC;
    intf=0;
      P1IE |= 0x0C;
   }
  }
    if((TAR & 0xFFFF)!=0){
   TACCTL0 |= CCIE;
    }

  if(intf==1){
   sr164_set(hour,min);
   intf = 2;
  }     
 }
}

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void){
  volatile unsigned int i,j;
  P1IE &=~0x0C;
  if(~(P1IFG & 0x08)|~(P1IFG & 0x04)){
   P1IFG &= ~0x0C;
   cnt_dn = 3;
   intf = 1;
  }
}

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A(void){
   TACCTL0 &= ~CCIE;
   TACCTL0 &= ~CCIFG;
   if(sec<59){
    sec++;
   }else{
    sec=0;
    if(min_base<59){
   min_base++;
  }else{
   min_base=0;
   if(hour_base<23){
    hour_base++;
     }else{
    hour_base=0;
    }
  }
   }
   
   //  sr164_set(0xFF,sec);
 min = ((min_base/10) * 16) + (min_base % 10);
 hour = ((hour_base/10) * 16) + (hour_base % 10);
   
   ccintf = 1;
}


フォロワー