PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_reverse.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 /** \file
31  * ESOS application program to recreate the "reverse" program
32  * \ref reverse_string.c
33  * in Chapter 10. (See Figure 10.16 in the text.)
34  * "Reverse" program waits for a string from the UART, reverses the string
35  * using the reverseString() function, and then sends the reversed string
36  * out to the UART.
37  *
38  * Use this program to test your UART connection under ESOS
39  *
40  * Application also has a flashing LED on RB15. Flashing LED is generated
41  * by an <em>user task</em> that runs simultaneously with the echo task above.
42  *
43  * \note Demonstrates multitasking and communications services under ESOS
44  */
45 
46 
47 // INCLUDEs go here (First include the main esos.h file)
48 // After that, the user can include what they need
49 #include "esos.h"
50 #ifdef __linux
51 #include "esos_pc.h"
52 #include "esos_pc_stdio.h"
53 
54 // INCLUDE these so that printf() and our PC hacks work
55 #include <stdio.h>
56 #include <sys/select.h>
57 #include <termios.h>
58 #include <unistd.h>
59 #else
60 #include "esos_pic24.h"
61 #include "esos_pic24_rs232.h"
62 #endif
63 
64 // DEFINEs go here
65 #ifndef __linux
66 #define CONFIG_LED1() CONFIG_RB15_AS_DIG_OUTPUT()
67 #define LED1 _LATB15
68 #else
69 #define CONFIG_LED1() printf("called CONFIG_LED1()\n");
70 uint8_t LED1 = TRUE; // LED1 is initially "on"
71 #endif
72 
73 // PROTOTYPEs go here
74 void reverseString(char *psz_s1, char *psz_s2);
75 
76 // GLOBALs go here
77 // Generally, the user-created semaphores will be defined/allocated here
78 
79 #ifdef __linux
80 /*
81  * Simulate the timer ISR found on a MCU
82  * The PC doesn't have a timer ISR, so this task will periodically
83  * call the timer services callback instead.
84  * USED ONLY FOR DEVELOPMENT AND TESTING ON PC.
85  * Real MCU hardware doesn't need this task
86  */
87 ESOS_USER_TASK( __simulated_isr ) {
89  while (TRUE) {
90  // call the ESOS timer services callback just like a real H/W ISR would
91  __esos_tmrSvcsExecute();
93 
94  } // endof while(TRUE)
95  ESOS_TASK_END();
96 } // end child_task
97 #endif
98 
99 /************************************************************************
100  * User supplied functions
101  ************************************************************************
102  */
103 
104 /**
105  * An ESOS task to mimic the heartbeat LED found
106  * in the PIC24 support library code used in Chapters 8-13.
107  *
108  * Toggle LED1, wait 250ms, repeat forever.
109  *
110  * \note Since this heartbeat is performed in an ESOS task,
111  * a flashing LED indicates that the ESOS scheduler is still
112  * running properly. If the LED quits flashing, the ESOS
113  * scheduler is no longer rotating through the runnable task
114  * list. The most likely reason is that some task has ceased
115  * "yielding" the processor, and is caught in some deadlock
116  * or otherwise infinite loop.
117  * \hideinitializer
118  */
119 ESOS_USER_TASK(heartbeat_LED) {
120  ESOS_TASK_BEGIN();
121  while (TRUE) {
122  LED1 = !LED1;
123 #ifdef __linux
124  if (LED1) {
125  printf("\a");
126  fflush(stdout);
127  }
128 #endif
129  ESOS_TASK_WAIT_TICKS( 500 );
130  } // endof while(TRUE)
131  ESOS_TASK_END();
132 } // end upper_case()
133 
134 /**
135  * Read an entire string from the "in" stream, reverse the string
136  * and send new string out the "out" stream
137  */
138 ESOS_USER_TASK( reverse_string ) {
139  static char sz_in[257];
140  static char sz_out[257];
141 
142  ESOS_TASK_BEGIN();
143  while (TRUE) {
147  reverseString( sz_in, sz_out );
152  } // endof while(TRUE)
153  ESOS_TASK_END();
154 } // end reverse_string()
155 
156 
157 /*
158  * Inputs a string, outputs the reverse. This file is used
159  * in three MPLAB projects:
160  * reverse_string.mcp - polled RX, TX I/O
161  * uartrx_fifo.mcp - interrupt RX, polled TX I/O
162  * uartrxtx_fifo.mcp - interrupt RX, interrupt TX I/O
163  * Interrupt RX inChar1() is selected by defining UART1_RX_INTERRUPT macro
164  * Interrupt TX outChar1() is selected by defining UART1_TX_INTERRUPT macro
165  * These macros are defined in their respective MPLAB projects.
166  *
167  * EXACTLY THE SAME ROUTINE AS USED IN CHAPTER 10. PLACED IN
168  * THIS SOURCE FILE FOR CONVENIENCE ONLY!!!
169  */
170 void reverseString(char *psz_s1, char *psz_s2) {
171  char *psz_s1end;
172  if (!(*psz_s1)) {
173  *psz_s2 = 0; //psz_s1 is empty, return.
174  return;
175  }
176  psz_s1end = psz_s1;
177  //find end of first string
178  while (*psz_s1end) psz_s1end++;
179  psz_s1end--; //backup one to first non-zero byte
180  //now copy to S2 in reverse order
181  while (psz_s1end != psz_s1) {
182  *psz_s2 = *psz_s1end;
183  psz_s1end--;
184  psz_s2++;
185  }
186  //copy last byte
187  *psz_s2 = *psz_s1end;
188  psz_s2++;
189  //mark end of string
190  *psz_s2 = 0;
191 }
192 
193 
194 /****************************************************
195  * user_init()
196  ****************************************************
197  */
198 void user_init(void) {
199 
200  // Call the hardware-provided routines to print the
201  // HELLO_MSG to the screen. Must use this call because
202  // the ESOS communications subsystems is not yet fully
203  // initialized, since this call is in user_init()
204  //
205  // In general, users should call hardware-specific
206  // function like this.
207  __esos_unsafe_PutString( HELLO_MSG );
208 
209 #ifdef __linux
210  // register our little ESOS task to mimic MCU's TIMER T1 IRQ which kicks off
211  // the ESOS S/W timers when they expire
212  esos_RegisterTask( __simulated_isr );
213 #endif
214 
215  // configure our hardware to support to support our application
216  CONFIG_LED1();
217 
218  // user_init() should register at least one user task
219  esos_RegisterTask(heartbeat_LED);
220  esos_RegisterTask(reverse_string);
221 
222 } // end user_init()