SHOW:
|
|
- or go back to the newest paste.
| 1 | #include <msp430.h> | |
| 2 | #include <signal.h> | |
| 3 | ||
| 4 | #define IR_LED BIT6 | |
| 5 | #define TRIGGER BIT3 | |
| 6 | #define STATUS_LED BIT0 | |
| 7 | ||
| 8 | static volatile int cycle_count; // IR carrier cycle count | |
| 9 | unsigned long time = 0; // current time, 1 click = 32.8ms | |
| 10 | unsigned long last_shot = 0; // time of last manual shot | |
| 11 | unsigned long interval = 100; // currently set interval | |
| 12 | unsigned long trigger_down_time = 0; // time button was depressed | |
| 13 | int trigger_down = 0; | |
| 14 | int interval_on = 0; | |
| 15 | int manual_shot = 0; | |
| 16 | ||
| 17 | #pragma vector = WDT_VECTOR | |
| 18 | __interrupt void wdt_isr(void) | |
| 19 | {
| |
| 20 | time++; | |
| 21 | __bic_SR_register_on_exit(LPM1_bits); | |
| 22 | } | |
| 23 | ||
| 24 | #pragma vector = TIMERA0_VECTOR // Timer A Capture/Compare 0 interrupt | |
| 25 | __interrupt void timera0_isr(void) // This ISR must be very simple because there may | |
| 26 | // be as few as 16 cycles available for it to complete | |
| 27 | { //
| |
| 28 | --cycle_count; // Decrement cycle count | |
| 29 | } | |
| 30 | ||
| 31 | #pragma vector = PORT1_VECTOR | |
| 32 | __interrupt void port1_isr(void) | |
| 33 | {
| |
| 34 | if (P1IFG & TRIGGER) | |
| 35 | {
| |
| 36 | P1IES ^= TRIGGER; // switch interrupt direction | |
| 37 | trigger_down = !trigger_down; // toggle state | |
| 38 | trigger_down_time = time; | |
| 39 | manual_shot = trigger_down; | |
| 40 | __bic_SR_register_on_exit(LPM1_bits); | |
| 41 | } | |
| 42 | ||
| 43 | P1IFG = 0; // clear p1 interrupts | |
| 44 | } | |
| 45 | ||
| 46 | ||
| 47 | ||
| 48 | static const int pentax[] = {
| |
| 49 | 26, // Carrier period in us ( 1 MHz / 38 kHz ~= 26 ) | |
| 50 | 8, // Number of pairs | |
| 51 | 500, 115, // 13 ms on, 3 ms off | |
| 52 | 38, 39, // 1 ms on, 1 ms off | |
| 53 | 38, 39, // 1 ms on, 1 ms off | |
| 54 | 38, 39, // 1 ms on, 1 ms off | |
| 55 | 38, 39, // 1 ms on, 1 ms off | |
| 56 | 38, 39, // 1 ms on, 1 ms off | |
| 57 | 38, 39, // 1 ms on, 1 ms off | |
| 58 | 38, 39 // 1 ms on, 1 ms off | |
| 59 | }; | |
| 60 | ||
| 61 | static const int nikon[] = {
| |
| 62 | 26, | |
| 63 | 4, | |
| 64 | 76, 1064, | |
| 65 | 15, 60, | |
| 66 | 15, 136, | |
| 67 | 15, 38 | |
| 68 | }; | |
| 69 | ||
| 70 | static const int canon[] = {
| |
| 71 | 30, | |
| 72 | 2, | |
| 73 | 16, 231, | |
| 74 | 16, 33 | |
| 75 | }; | |
| 76 | ||
| 77 | void send_code(const int *code) | |
| 78 | {
| |
| 79 | TACCR0 = *code++ - 1 ; // Set timer period | |
| 80 | TACCR1 = TACCR0 >> 1; // Set timer on duration - 50% duty cycle | |
| 81 | int pair = *code++; // Get pair count | |
| 82 | cycle_count = 5; // Setup some initial IR off lead in | |
| 83 | TACCTL0 = CCIE; // Enable Timer A CC0 interrupt | |
| 84 | do { // Do all pairs
| |
| 85 | int cc = *code++; // Get on cycles | |
| 86 | while(cycle_count > 0); // Wait for off cycles to complete | |
| 87 | TACCTL1 = OUTMOD_7; // Turn on IR | |
| 88 | cycle_count += cc; // Set on cycle count | |
| 89 | cc = *code++; // Get off cycles | |
| 90 | while(cycle_count > 0); // Wait for on cycles to complete | |
| 91 | TACCTL1 = OUTMOD_0; // Turn off IR | |
| 92 | cycle_count += cc; // Set off cycle count | |
| 93 | } while(--pair); // Decrement pair count, do next pair if not zero | |
| 94 | while(cycle_count > 0); // Wait for off cycles to complete | |
| 95 | TACCTL0 = 0; // Turn off Timer A CC0 interrupt | |
| 96 | } | |
| 97 | ||
| 98 | void send_all_codes() | |
| 99 | {
| |
| 100 | send_code(pentax); | |
| 101 | send_code(nikon); | |
| 102 | send_code(canon); | |
| 103 | } | |
| 104 | ||
| 105 | int main(void) | |
| 106 | {
| |
| 107 | WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset | |
| 108 | DCOCTL = 0; // Run at 1 MHz | |
| 109 | - | send_code(pentax); // Send Pentax IR code |
| 109 | + | |
| 110 | DCOCTL = CALDCO_1MHZ; // | |
| 111 | ||
| 112 | P1DIR |= TRIGGER; // Set P1.3 to input | |
| 113 | P1IE |= TRIGGER; // P1.3 enabled interrupts | |
| 114 | P1IES |= TRIGGER; // P1.3 Hi/lo edge | |
| 115 | P1IFG &= ~TRIGGER; // P1.3 clear IFG | |
| 116 | - | send_code(pentax); |
| 116 | + | |
| 117 | TACTL = TASSEL_2 | MC_1; // Timer A config: SMCLK, count up | |
| 118 | TACCTL1 = OUTMOD_0; // Make sure IR is off | |
| 119 | ||
| 120 | P1OUT = IR_LED; | |
| 121 | P1DIR = STATUS_LED | IR_LED; // Enable PWM output on P1.6 | |
| 122 | P1SEL = IR_LED; | |
| 123 | ||
| 124 | WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL; | |
| 125 | IE1 |= WDTIE; | |
| 126 | ||
| 127 | eint(); // Enable global interrupts | |
| 128 | ||
| 129 | while(1) {
| |
| 130 | if (interval_on && (time - last_shot >= interval)) // intervalometer | |
| 131 | {
| |
| 132 | send_all_codes(); // Send Pentax IR code | |
| 133 | last_shot = time; | |
| 134 | } | |
| 135 | ||
| 136 | if (manual_shot) // manual triggering | |
| 137 | {
| |
| 138 | manual_shot = 0; | |
| 139 | send_all_codes(); | |
| 140 | interval = time - last_shot; // save interval | |
| 141 | interval = (interval > 15? interval: 15); | |
| 142 | last_shot = time; | |
| 143 | } | |
| 144 | ||
| 145 | if (trigger_down && (time - trigger_down_time) > 30) | |
| 146 | // hold button for 1 sec to switch modes | |
| 147 | {
| |
| 148 | trigger_down_time = time; | |
| 149 | interval_on = !interval_on; | |
| 150 | if (interval_on) | |
| 151 | P1OUT ^= STATUS_LED; | |
| 152 | else | |
| 153 | P1OUT &= ~STATUS_LED; | |
| 154 | } | |
| 155 | ||
| 156 | __bis_SR_register(LPM1_bits + GIE); | |
| 157 | } | |
| 158 | return 1; | |
| 159 | } |