-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
260 lines (200 loc) · 5.53 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
//-----------------------------------------------------------------
// Name: Brian Yarbrough
// Class: ECE 382 Section T5, Capt Trimble
// Start: Coulston
// File: lab5.c
// Date: Fall 2014
// Purp: Implement LCD Etch-a-Sketch with the IR remote
//-----------------------------------------------------------------
#include <msp430g2553.h>
#include "head06.h"
int16 packetData[34];
int8 packetIndex = 0;
/*
* main.c
* Initializes the robot
* Waits for a new IR packet to be recieved, then handles the request
*/
void main(void) {
initMSP430(); //initialize system
initIR();
P1DIR |= BIT0 | BIT6; // Enable updates to the LED
P1OUT &= ~(BIT0 | BIT6); // An turn the LED off
GO_STOP;
while(1){
if(packetIndex == 34){
handlePress();
_delay_cycles(LONG_T);
initIR();
}
}
}
/*
* initMSP430()
* Responsible for configuring pins to timers and enables interrupts
* Must be called prior to driving motors
* TACCR1 is the duty cycle %.
* It must be < 60 to prevent burning the motor chip
*/
void initMSP430(){
IFG1=0; // clear interrupt flag1
WDTCTL=WDTPW+WDTHOLD; // stop WD
BCSCTL1 = CALBC1_8MHZ; //calibrate clock
DCOCTL = CALDCO_8MHZ;
P1DIR &= ~BIT3;
P1REN |= BIT3;
P2DIR |= BIT2; // P2.2 is associated with TA1CCR1
P2SEL |= BIT2; // P2.2 is associated with TA1CCTL1
P2DIR |= BIT4; // P2.4 is associated with TA1CCR2
P2SEL |= BIT4; // P2.4 is associated with TA1CCTL2
//ports for direction
P2DIR |= BIT0 | BIT1 | BIT3 | BIT5;
TA1CTL = ID_3 | TASSEL_2 | MC_1; // Use 1:8 presclar off MCLK
TA1CCR0 = 1000; // set signal period
TA1CCR1 = 500;
TA1CCTL1 = OUTMOD_3; // set TACCTL1 to Reset / Set mode
TA1CCR2 = 500;
TA1CCTL2 = OUTMOD_3; // set TACCTL1 to Reset / Set mode
}
/*
* initIR()
*readies the IR sensor to recieve a signal from the remote
* must be recalled after initMSP430() is called
*/
void initIR(){
//IR Pins
P2SEL &= ~BIT6; // Setup P2.6 as GPIO not XIN
P2SEL2 &= ~BIT6;
P2DIR &= ~BIT6;
P2IFG &= ~BIT6; // Clear any interrupt flag
P2IE |= BIT6; // Enable PORT 2 interrupt on pin change
TACTL &= ~TAIFG; // clear flag before enabling interrupts = good practice
TACTL = ID_3 | TASSEL_2 | MC_1 | TAIE; // Use 1:1 presclar off MCLK and enable interrupts
_enable_interrupt();
}
/*
* handlePress()
* copied from Lab05
* decodes which button was pressed on remote
* modified to call appropriate drive function
*/
void handlePress(){
_disable_interrupt();
int32 result = 0;
int32 setter = 0x80000000; //1 in the MSB
char i;
for(i = 2; i<34; i++){ //traverse array
int16 current = packetData[i]; //current element
packetData[0] = 0; //clear element
if(current/10 < 100){ //is a zero
result &= ~setter; //clear bit
}
else {
result |= setter; //set bit
}
setter >>= 1; //rotate setter
}
packetIndex++; //ensure the loop is not reentered
switch(result){ //take appropriate action
case UP:
P1OUT ^= BIT0;
drive(FORWARD);
break;
case DOWN:
P1OUT ^= BIT6;
drive(BACKWARD);
break;
case LEFT:
P1OUT |= (BIT0 | BIT6);
drive(LEFT_T);
break;
case RIGHT:
P1OUT ^= (BIT0 | BIT6);
drive(RIGHT_T);
break;
case EXIT:
drive(STOP);
break;
case CH_UP:
break;
case CH_DW:
break;
case MUTE:
break;
}
initIR();
}
/*
* drive()
* accepts a direction and moves the robot in that direction
*/
void drive(direction movement){
GO_STOP;
_delay_cycles(SHORT_T);
switch(movement){
case FORWARD:
TA1CCTL1 = OUTMOD_7;
TA1CCTL2 = OUTMOD_7;
GO_FORWARD;
break;
case BACKWARD:
TA1CCTL1 = OUTMOD_3;
TA1CCTL2 = OUTMOD_3;
GO_BACKWARD;
break;
case LEFT_T:
TA1CCTL1 = OUTMOD_7;
TA1CCTL2 = OUTMOD_3;
GO_FORWARD;
GO_LEFT;
break;
case RIGHT_T:
TA1CCTL1 = OUTMOD_3;
TA1CCTL2 = OUTMOD_7;
GO_FORWARD;
GO_RIGHT;
break;
case STOP:
GO_STOP;
break;
}//end switch
ENABLE_MOTORS;
}
/*
* interrupt for the PWM
*/
#pragma vector = PORT2_VECTOR // This is from the MSP430G2553.h file
__interrupt void pinChange (void) {
int8 pin;
int16 pulseDuration; // The timer is 16-bits
if (IR_PIN) pin=1; else pin=0;
switch (pin) { // read the current pin level
case 0: // !!!!!!!!!NEGATIVE EDGE!!!!!!!!!!
pulseDuration = TAR;
TACTL = 0;
packetData[packetIndex++] = pulseDuration;
LOW_2_HIGH; // Setup pin interrupr on positive edge
break;
case 1: // !!!!!!!!POSITIVE EDGE!!!!!!!!!!!
TAR = 0x0000; // time measurements are based at time 0
TA0CCR0 = 0xFF00; // create a 16mS roll-over period
TACTL &= ~TAIFG; // clear flag before enabling interrupts = good practice
TACTL = ID_3 | TASSEL_2 | MC_1 | TAIE; // Use 1:1 presclar off MCLK and enable interrupts
HIGH_2_LOW; // Setup pin interrupr on positive edge
break;
} // end switch
P2IFG &= ~BIT6; // Clear the interrupt flag to prevent immediate ISR re-entry
} // end pinChange ISR
// -----------------------------------------------------------------------
// This interrupt is a way of reseting the reciever when something gets messed up
// It also resets packetIndex after the final pulse is recieved
// It is only active while IRPIN is high
//
// Only active when IR pin is being read
// -----------------------------------------------------------------------
#pragma vector = TIMER0_A1_VECTOR // This is from the MSP430G2553.h file
__interrupt void timerOverflow (void) {
initMSP430();
packetIndex = 0;
TACTL &= ~TAIFG; //clear flag
}