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 | } |