C Source Code - MSP430 Launchpad with Digital Caliper

This is full C source code for MSP430 Launchpad project described in post Interfacing TI Launchpad to Digital Caliper.

Full source code of project bellow.
//*******************************************
// Running on Launchpad
//                MSP430G2231
//             ------------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//    Vin+ -->|A1+ P1.2         |
//            |A1- = VSS    P1.0|-->LED
//            |             P1.1|-->TX RS232
//            |             P1.4|<--CLOCK CALIPER
//            |             P1.5|<--DATA CALIPER
//
// Maris Sprancis  viltnieks@gmail.com  http://robocombo.blogspot.com
//*******************************************
#include <msp430g2231.h>

int value = 0;                   // value received from caliper
unsigned char clock_active = 0;  // any clock activity during last 32msec?
unsigned char ready_for_data = 0;// idle between clock burts, ready for next one
unsigned char bits_so_far = 0;   // current bit count during value "assembly"

// how many CPU cycles between bits
#define Bitime      104          //9600 Baud, SMCLK=1MHz (1MHz/9600)=104
unsigned char BitCnt;            // Bit count, used when transmitting byte
unsigned int TXByte;             // Value sent over UART when Transmit() is called

#define LED         BIT0         // LED on P1.0
#define TXPIN      BIT1          // RS232 TX on P1.1
#define CLOCK      BIT4          // Clock on P1.4
#define DATA      BIT5           // Data on P1.5

void Transmit(void);

void main(void)
{
   DCOCTL = 0x00;                // Safe Flow
   BCSCTL1 = CALBC1_1MHZ;        // run at 1Mhz
   DCOCTL = CALDCO_1MHZ;

   //WDT as 32 ms interval counter. If no action on clock withing 32msec,
   // we are ready to receive next "number"
   WDTCTL = WDT_MDLY_32;         // default timer 32 msec
   IE1 |= WDTIE;                 // Enable WDT interrupt

   P1DIR |= LED;                 // Set P1.0 to output direction
   P1OUT |= LED;                 // LED ON, we'r ready
   P1SEL |= TXPIN;
   P1DIR |= TXPIN;               // Set P1.1 to output direction

   // Set up CLOCK input pin
   P1DIR &= ~CLOCK;        // sets input direction
   P1OUT |= CLOCK;         // pull-up is selected
   P1REN |= CLOCK;         // pull-up/pull-down enabled
   P1IES &= ~CLOCK;        // interrupt triggered on low-to-high
   P1IFG &= ~CLOCK;        // reset interrupt flag to 0. needs to be reset on start
   P1IE |= CLOCK;          // interrupt enabled for CLOCK

   // Set up DATA input pin
   P1DIR &= ~DATA;         // sets input direction
   P1OUT |= DATA;          // pull-up is selected
   P1REN |= DATA;          // pull-up/pull-down enabled
   P1IES &= ~DATA;         // interrupt triggered on low-to-high
   P1IFG &= ~DATA;         // reset interrupt flag to 0. needs to be reset on start
   P1IE &= ~DATA;          // interrupt disabled for DATA

   // sending something over serial
   while (1)
   {
      __bis_SR_register(LPM0_bits + GIE);

      // after we went into low power mode, program counter is at this instruction
      // (next one after where you entered LPM), but it's not moving until you enable active mode
      // within main loop. That can be done with __bic_SR_register_on_exit(LPM0_bits) in ISR
      _NOP();

      // sending next value. value has been assembled by CLOCL interrupt function
      // value is 16 bit, TXByte should be 8, sending in two parts
      TXByte = value >> 8;    // first byte (most significant bits)
      Transmit();
      TXByte = value & 0xFF;  // second byte (least significant)
      Transmit();
      P1OUT ^= LED;           // blink LED
   }
}

// Function Transmits Character from TXByte
void Transmit()
{
   CCTL0 = OUT;               // TXD Idle as Mark
   TACTL = TASSEL_2 + MC_2;   // SMCLK, continuous mode

   BitCnt = 0xA;              // Load Bit counter, 8 bits + ST/SP
   CCR0 = TAR;

   CCR0 += Bitime;            // Set time till first bit
   TXByte |= 0x100;           // Add stop bit to TXByte (which is logical 1)
   TXByte = TXByte << 1;      // Add start bit (which is logical 0)

   CCTL0 =  CCIS0 + OUTMOD0 + CCIE; // Set signal, intial value, enable interrupts
   while ( CCTL0 & CCIE );    // Wait for TX completion
   TACTL = TASSEL_2;          // SMCLK, timer off (for power consumption)
}

// Timer A0 interrupt service routine. Used to send bits over RS232
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
   CCR0 += Bitime;            // Add Offset to CCR0
   if ( BitCnt == 0)          // If all bits TXed, disable interrupt
      CCTL0 &= ~ CCIE;
   else
   {
      CCTL0 |=  OUTMOD2;                    // TX Space
      if (TXByte & 0x01)
         CCTL0 &= ~ OUTMOD2;                // TX Mark
      TXByte = TXByte >> 1;
      BitCnt --;
   }
}

// Button is pressed
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
   static unsigned char port;

   port = P1IN; // read DATA port value as soon as possible (otherwise it might be gone)

   P1IFG &= ~CLOCK;           // Clear interrupt flag
   clock_active = 1;

   if (ready_for_data)
   {
      if (bits_so_far && bits_so_far <= 16){  // first bit is start bit, ignore it. Total we have 24 bits. But we need only 16
         if (!(port & DATA))           // if 0 recived, invert = >1
            value |=0x8000;            // then set most significant bit
         value = value >> 1;           // and move it one right
      }else if (bits_so_far == 21){             // 21st bit indicates sighn (+/-)
         if (!(port & DATA))
            value = (~value)+1;                 // make it negative
      }else   if (bits_so_far >= 23){           // we'r done, got all bits
         ready_for_data = 0;                    // warchdog timer will set it
         __bic_SR_register_on_exit(LPM0_bits);  // wake up main from LPM sleep
      }
      bits_so_far++;
   }
}

// watchdog used as 30msec timer for detecting start of new bit burst on clock
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
   if (ready_for_data)
      return;

   if (clock_active){
      clock_active = 0;       // clear flag, will wait another 32msec to see if there have been any activity of clock
      ready_for_data = 0;     // not yet ready
   }else{
      ready_for_data = 1;     // nothing within last 32msec, ready for next clock burst
      value = 0;              // init of value
      bits_so_far = 0;        // init of bit counter
   }
}