PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ledsw1_timer.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 #include "pic24_all.h"
31 
32 /** \file
33 Demonstrates the use of a period interrupt to sample a switch
34 input, removes the need for debounce delays.
35 Uses a semaphore for press & release.
36 */
37 
38 /// LED1
39 #define CONFIG_LED1() CONFIG_RB14_AS_DIG_OUTPUT()
40 #define LED1 _LATB14 //led1 state
41 
42 /// Switch1 configuration
43 inline void CONFIG_SW1() {
44  CONFIG_RB13_AS_DIG_INPUT(); //use RB13 for switch input
45  ENABLE_RB13_PULLUP(); //enable the pullup
46  DELAY_US(1); // Wait for pullup
47 }
48 
49 #define SW1_RAW _RB13 //raw switch value
50 #define SW1 u8_valueSW1 //switch state
51 #define SW1_PRESSED() (SW1==0) //switch test
52 #define SW1_RELEASED() (SW1==1) //switch test
53 
54 typedef enum {
55  STATE_WAIT_FOR_PRESS = 0,
56  STATE_WAIT_FOR_RELEASE,
57 } ISRSTATE;
58 
59 volatile uint8_t u8_valueSW1 = 1; //initially high
60 volatile uint8_t u8_pnrSW1 = 0; ///< True when SW1 has been Pressed-N-Released
61 
62 //Interrupt Service Routine for Timer3
63 void _ISRFAST _T3Interrupt (void) {
64  static ISRSTATE e_isrState = STATE_WAIT_FOR_PRESS;
65  u8_valueSW1 = SW1_RAW; //sample the switch
66  switch (e_isrState) {
67  case STATE_WAIT_FOR_PRESS:
68  if (SW1_PRESSED() && (u8_pnrSW1 == 0))
69  e_isrState = STATE_WAIT_FOR_RELEASE;
70  break;
71  case STATE_WAIT_FOR_RELEASE:
72  if (SW1_RELEASED()) {
73  e_isrState = STATE_WAIT_FOR_PRESS;
74  u8_pnrSW1 = 1; //set press & release semaphore
75  break;
76  }
77  default:
78  e_isrState = STATE_WAIT_FOR_RELEASE;
79  }
80  _T3IF = 0; //clear the timer interrupt bit
81 }
82 
83 
84 /// Switch2 configuration, does not have to be debounced
85 inline void CONFIG_SW2() {
86  CONFIG_RB12_AS_DIG_INPUT(); //use RB12 for switch input
87  ENABLE_RB12_PULLUP(); //enable the pullup
88  DELAY_US(1); //wait for pullup to drive pin high
89 }
90 
91 #define SW2 _RB12 //switch state
92 
93 
94 typedef enum {
95  STATE_RESET = 0,
96  STATE_WAIT_FOR_PNR1,
97  STATE_WAIT_FOR_PNR2,
98  STATE_BLINK,
99  STATE_WAIT_FOR_RELEASE3
100 } STATE;
101 
102 //print debug message for state when it changes
103 void printNewState (STATE e_currentState) {
104  static STATE e_LastState = STATE_RESET;
105  if (e_LastState != e_currentState) {
106  switch (e_currentState) {
107  case STATE_WAIT_FOR_PNR1:
108  outString("STATE_WAIT_FOR_PNR1 - LED is off\n");
109  break;
110  case STATE_WAIT_FOR_PNR2:
111  outString("STATE_WAIT_FOR_PNR2 - SW2 on goes to blink else go to PNR1\n");
112  break;
113  case STATE_BLINK:
114  outString("STATE_BLINK - LED blinks, waiting for SW1 press\n");
115  break;
116  case STATE_WAIT_FOR_RELEASE3:
117  outString("STATE_WAIT_FOR_RELEASE3 - LED is on\n");
118  break;
119  default:
120  break;
121  }
122  }
123  e_LastState = e_currentState; //remember last state
124 }
125 
126 
127 #define ISR_PERIOD 15 // in ms
128 void configTimer3(void) {
129  //ensure that Timer2,3 configured as separate timers.
130  T2CONbits.T32 = 0; // 32-bit mode off
131  //T3CON set like this for documentation purposes.
132  //could be replaced by T3CON = 0x0020
133  T3CON = T3_OFF |T3_IDLE_CON | T3_GATE_OFF
134  | T3_SOURCE_INT
135  | T3_PS_1_64 ; //results in T3CON= 0x0020
136  PR3 = msToU16Ticks (ISR_PERIOD, getTimerPrescale(T3CONbits)) - 1;
137  TMR3 = 0; //clear timer3 value
138  _T3IF = 0; //clear interrupt flag
139  _T3IP = 1; //choose a priority
140  _T3IE = 1; //enable the interrupt
141  T3CONbits.TON = 1; //turn on the timer
142 }
143 
144 int main (void) {
145  STATE e_mystate;
146  configBasic(HELLO_MSG);
147 
148  /** PIO config ******/
149  CONFIG_SW1(); //configure switch
150  CONFIG_SW2(); //configure switch
151  CONFIG_LED1(); //config the LED
152  /** Configure the Timer */
153  configTimer3();
154  /*****Toggle LED each time switch is pressed and released ******************************/
155  e_mystate = STATE_WAIT_FOR_PNR1;
156 
157  /* Observe that use of a periodic interrupt for sampling the
158  switch value means that all of the debounce delays can be removed
159  */
160  while (1) {
161  printNewState(e_mystate); //debug message when state changes
162  switch (e_mystate) {
163  case STATE_WAIT_FOR_PNR1:
164  LED1 = 0; //turn off the LED
165  if (u8_pnrSW1) {
166  u8_pnrSW1 = 0; //clear semaphore
167  e_mystate = STATE_WAIT_FOR_PNR2;
168  }
169  break;
170  case STATE_WAIT_FOR_PNR2:
171  LED1 = 1; //turn on the LED
172  if (u8_pnrSW1) {
173  u8_pnrSW1 = 0; //clear semaphore
174  //decide where to go
175  if (SW2) e_mystate = STATE_BLINK;
176  else e_mystate = STATE_WAIT_FOR_PNR1;
177  }
178  break;
179  case STATE_BLINK:
180  LED1 = !LED1; //blink while not pressed
181  DELAY_MS(100); //blink delay
182  if (SW1_PRESSED()) e_mystate = STATE_WAIT_FOR_RELEASE3;
183  break;
184  case STATE_WAIT_FOR_RELEASE3:
185  LED1 = 1; //Freeze LED1 at 1
186  //use u8_pnrSW1 instead of SW1_RELEASED because
187  //u8_pnrSW1 is set on a release, and must be cleared.
188  if (u8_pnrSW1) {
189  u8_pnrSW1 = 0;
190  e_mystate = STATE_WAIT_FOR_PNR1;
191  }
192  break;
193  default:
194  e_mystate = STATE_WAIT_FOR_PNR1;
195  }//end switch(e_mystate)
196  doHeartbeat(); //ensure that we are alive
197  } // end while (1)
198 }