//******************************************************************************
//
//  GoPro HD Camera Control using BUS connector
//
//  Uses PWR/MODE button to wake camera up and take photo in One Button Mode
//
//  Set SHOT_RATE for number of seconds between shots
//
//  upon detecting a pulse on P1.6 take a photo or start video
//  close PWR button for 250 mSec to wake up camera
//  wait TIME_ON seconds as defined below
//  close PWR button for 3 seconds to turn camera off
//  flash LED to indicate finished and waiting
//
//  P1.0 is LED
//  P1.4 is camera shutter (PWR button)
//  P1.6 is input from remote control
//
//  by Peter Jennings  http://benlo.com/msp430
//
//******************************************************************************

#include "msp430.h"

#define TIME_ON 30     // length of time on ( 3 for photo longer or video)

#define WAITING 0    //   waiting for next cycle
#define STARTING 1   //   button down to start
#define WAITING_CAMERA 2  //   waiting for camera to take pic
#define STOPPING 3   //   button down to stop

static int tick;
static int state;

static int time;  // seconds since last save


void main(void)
  {
  WDTCTL = WDTPW + WDTHOLD;           // Stop watchdog timer

  P1SEL |= 0x00;                      // P1.1 option select - just I/O
  P1DIR |= 0x11;                      // Set P1.0 P1.4 to output direction
  P1OUT |= 0x11;                      // LED on, GoPro button off

  BCSCTL2 |= DIVS_3;                  // SMCLK/8
  WDTCTL = WDT_MDLY_32;               // WDT Timer interval 32mS

  tick = 0;
  state = WAITING;

  P1IE  |= 0x40;                   // P1.4 interrupt enabled
  P1IES |= 0x00;                   // P1.4 Lo->Hi transition
  P1IFG &= ~0x40;                  // P1.4 IFG cleared

  IE1   |= WDTIE;                  // Enable WDT interrupt 256 mSec
  _BIS_SR(LPM0_bits + GIE);        // Enter LPM0 with interrupt
  }

// Watchdog Timer interrupt service routine

#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
  {
  if ( (state == STARTING) && (tick >= 1 ) )  // start takes .25 seconds
      {
      state = WAITING_CAMERA;
      P1OUT  |= 0x10;           // button up
      }
  if ( tick & 0x03 )            // most of the time
     {
     P1OUT &= ~0x01;            // LED off and go back to sleep
     }
  else                          // about once very 1.024 seconds
     {
     time++;
     if ((state == WAITING_CAMERA) && (time >= TIME_ON) ) // time to turn off
         {
         state = STOPPING;
         P1OUT &= ~0x10;             // button down
         time = 0;
         }
     else if ((state == STOPPING) && (time >= 3)) // should be off by now
         {
         state = WAITING;
         P1OUT  |= 0x10;             // button up
         P1OUT  |= 0x01;           // LED flash to indicate done cycle
         }
     }
  tick++;                  // 256 mSec ticks
  }


// Port 1 interrupt service routine         remote signal detected
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
    {
    if ( state == WAITING )         // only take photo when ready
        {
        P1OUT &= ~0x10;             // GoPro button down
        tick = 0;
        time = 0;
        state = STARTING;
        }
    P1IFG &= ~0x40;            // P1.4 IFG cleared
    }