PIC24 Support Libraries
pic24_serial.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 
31 // Documentation for this file. If the \file tag isn't present,
32 // this file won't be documented.
33 /** \file
34  * Implementation of serial I/O functions prototyped in pic24_serial.h
35  */
36 
37 #include "pic24_serial.h"
38 #include "pic24_uart.h"
39 #include "pic24_unittest.h"
40 #include <libpic30.h>
41 
42 /*********************************************************
43  * Public functions intended to be called by other files *
44  *********************************************************/
45 
46 #ifndef BOOTLOADER
47 # ifdef BUILT_ON_ESOS
48 # include "esos.h"
49 # define outChar __esos_unsafe_PutUint8
50 # else
51 /** Write a character to the serial port.
52  * This function blocks until a character is
53  * written. The UART used
54  * is determined by the __C30_UART variable, which
55  * defaults to 1.
56  * \param u8_c Character to write
57  */
58 void outChar(uint8_t u8_c) {
59  switch (__C30_UART) {
60 # if (NUM_UART_MODS >= 1)
61  case 1 :
62  outChar1(u8_c);
63  break;
64 # endif
65 # if (NUM_UART_MODS >= 2)
66  case 2 :
67  outChar2(u8_c);
68  break;
69 # endif
70 # if (NUM_UART_MODS >= 3)
71  case 3 :
72  outChar3(u8_c);
73  break;
74 # endif
75 # if (NUM_UART_MODS >= 4)
76  case 4 :
77  outChar4(u8_c);
78  break;
79 # endif
80  default :
81  REPORT_ERROR("Invalid UART");
82  }
83 }
84 # endif
85 
86 /** Write a null-terminated string to the serial port.
87 See file documentation for End-of-line behavior when passed a "\n" (newline).
88 \param psz_s Pointer to null-terminated string to print.
89 */
90 void outString(const char* psz_s) {
91  while (*psz_s) {
92 
93 # if (SERIAL_EOL_DEFAULT == SERIAL_EOL_CR_LF)
94  if (*psz_s == '\n') outChar(0x0D);
95  outChar(*psz_s);
96 # elif (SERIAL_EOL_DEFAULT == SERIAL_EOL_CR)
97  if (*psz_s == '\n') outChar(0x0D);
98  else outChar(*psz_s);
99 # elif (SERIAL_EOL_DEFAULT == SERIAL_EOL_LF)
100 //no translation
101  outChar(*psz_s);
102 # else
103 # error "Invalid SERIAL_EOL_DEFAULT."
104 #endif
105  psz_s++;
106  }
107 }
108 
109 
110 
111 
112 static uint16_t inStringInternal(char *psz_buff, uint16_t u16_maxCount, uint8_t echoFlag) {
113  uint8_t u8_c;
114  uint16_t u16_i;
115 
116  if (!u16_maxCount) return 0;
117  u16_i = 0;
118  for (u16_i = 0; u16_i < u16_maxCount; u16_i++) {
119  if (echoFlag) u8_c = inCharEcho();
120  else u8_c = inChar();
121  if (u8_c == '\n' ||u8_c == '\r' ) break; //terminate loop
122  *psz_buff = u8_c; //save character
123  psz_buff++;
124  }
125  //stop reading, terminate, return characters read.
126  *psz_buff = 0;
127  return(u16_i);
128 }
129 
130 /**
131 Reads a string into psz_buff, assumes psz_buff can
132 hold at least u16_maxCount+1 characters. String reading
133 halts when either a newline or carriage return is read, or u16_maxCount
134 characters is read. The return string is always null-terminated.
135 The return count does not includes the null terminator.
136 An input string of just '\n' returns a null string.
137 \param psz_buff pointer to buffer for storing string read from console
138 \param u16_maxCount maximum number of characters to read from console.
139 */
140 uint16_t inString(char *psz_buff, int16_t u16_maxCount) {
141  return inStringInternal(psz_buff,u16_maxCount,0);
142 }
143 
144 /**
145 Same as inString(), except echoes characters to console as they are read.
146 */
147 uint16_t inStringEcho (char *psz_buff, int16_t u16_maxCount) {
148  return inStringInternal(psz_buff,u16_maxCount,1);
149 }
150 
151 
152 void outUint8NoLeader(uint8_t u8_x) {
153  uint8_t u8_c;
154  u8_c = (u8_x>>4)& 0xf;
155  if (u8_c > 9) outChar('A'+u8_c-10);
156  else outChar('0'+u8_c);
157  //LSDigit
158  u8_c= u8_x & 0xf;
159  if (u8_c > 9) outChar('A'+u8_c-10);
160  else outChar('0'+u8_c);
161 }
162 
163 /**
164 Output u8_x as formatted hex value with leading "0x".
165 \param u8_x value to output.
166 */
167 void outUint8(uint8_t u8_x) {
168  outString("0x");
169  outUint8NoLeader(u8_x);
170 }
171 
172 /**
173 Output u16_x as formatted hex value with leading "0x".
174 \param u16_x value to output.
175 */
176 void outUint16(uint16_t u16_x) {
177  uint8_t u8_c;
178 
179  outString("0x");
180  u8_c = (u16_x >> 8);
181  outUint8NoLeader(u8_c);
182  u8_c = (uint8_t) u16_x;
183  outUint8NoLeader(u8_c);
184 }
185 
186 /**
187 Output u32_x as formatted hex value with leading "0x".
188 \param u32_x value to output.
189 */
190 void outUint32(uint32_t u32_x) {
191  uint8_t u8_c;
192  outString("0x");
193  u8_c = (u32_x >> 24);
194  outUint8NoLeader(u8_c);
195  u8_c = (u32_x >> 16);
196  outUint8NoLeader(u8_c);
197  u8_c = (u32_x >> 8);
198  outUint8NoLeader(u8_c);
199  u8_c = u32_x;
200  outUint8NoLeader(u8_c);
201 }
202 
203 /**
204 Output u8_x as decimal value.
205 \param u8_x value to output.
206 */
208  static const uint8_t u8_d[]= {50, 30, 20, 10, 5, 3, 2, 1 };
209  static const uint8_t u8_f[]= {5, 3, 2, 1, 5, 3, 2, 1 };
210 
211  char psz_out[5];
212  uint8_t u8_i, u8_destroy;
213 
214  u8_i = 0;
215  u8_destroy = u8_x;
216  psz_out[0] = '0';
217  psz_out[1] = '0';
218  psz_out[2] = '0';
219  psz_out[3] = 0;
220  if (u8_destroy >= 200) {
221  psz_out[0] += 2;
222  u8_destroy -= 200;
223  } // end if()
224  if (u8_destroy >= 100) {
225  psz_out[0] += 1;
226  u8_destroy -= 100;
227  } // end if()
228  for (u8_i=0; u8_i<8; u8_i++) {
229  if (u8_destroy >= u8_d[u8_i]) {
230  psz_out[1+(u8_i/4)] += u8_f[u8_i];
231  u8_destroy -= u8_d[u8_i];
232  }
233  } //end for()
234  psz_out[3] = 0;
235  outString( psz_out );
236 }
237 
238 /**
239 Output u16_x as decimal value.
240 \param u16_x value to output.
241 */
242 void outUint16Decimal(uint16_t u16_x) {
243  static const uint16_t u16_d[]= {50000, 30000, 20000, 10000, 5000, 3000, 2000, 1000, \
244  500, 300, 200, 100, 50, 30, 20, 10, 5, 3, 2, 1
245  };
246  static const uint8_t u8_f[]= {5, 3, 2, 1 };
247 
248  uint8_t u8_i;
249  uint16_t u16_destroy;
250  char psz_out[5];
251 
252  u8_i = 0;
253  u16_destroy = u16_x;
254  psz_out[0] = '0';
255  psz_out[1] = '0';
256  psz_out[2] = '0';
257  psz_out[3] = '0';
258  psz_out[4] = '0';
259 
260  for (u8_i=0; u8_i<20; u8_i++) {
261  if (u16_destroy >= u16_d[u8_i]) {
262  psz_out[u8_i/4] += u8_f[u8_i % 4];
263  u16_destroy -= u16_d[u8_i];
264  }
265  } //end for()
266  psz_out[5] = 0;
267  outString( psz_out );
268 }
269 
270 /** Read a character from the serial port.
271  * This function blocks until a character is
272  * read.
273  * The serial port used is selected by the
274  * __C30_UART variable, which defaults to 1.
275  * \return Character read from the serial port.
276  */
278  switch (__C30_UART) {
279 # if (NUM_UART_MODS >= 1)
280  case 1 :
281  return inChar1();
282 # endif
283 # if (NUM_UART_MODS >= 2)
284  case 2 :
285  return inChar2();
286 # endif
287 # if (NUM_UART_MODS >= 3)
288  case 3 :
289  return inChar3();
290 # endif
291 # if (NUM_UART_MODS >= 4)
292  case 4 :
293  return inChar4();
294 # endif
295  default :
296  REPORT_ERROR("Invalid UART");
297  return 0;
298  }
299 }
300 
301 /**
302 Same as inChar(), except echo character that is back to console
303 */
304 
306  uint8_t u8_c;
307  u8_c = inChar(); //get character
308  outChar(u8_c); //echo
309  return u8_c;
310 }
311 
312 /** Determine if a character is ready to be read
313  * from the serial port.
314  * \return non-zero value if character is ready, zero otherwise..
315  */
317  switch (__C30_UART) {
318 # if (NUM_UART_MODS >= 1)
319  case 1 :
320  return isCharReady1();
321 # endif
322 # if (NUM_UART_MODS >= 2)
323  case 2 :
324  return isCharReady2();
325 # endif
326 # if (NUM_UART_MODS >= 3)
327  case 3 :
328  return isCharReady3();
329 # endif
330 # if (NUM_UART_MODS >= 4)
331  case 4 :
332  return isCharReady4();
333 # endif
334  default :
335  REPORT_ERROR("Invalid UART");
336  return 0;
337  }
338 }
339 #endif
340 
341 
342 /** Configures a UART based compiler setting of DEFAULT_UART
343  * and sets __C30_UART to the default UART.
344  * If you want to configure a different UART, then call the configUARTx function explicitly.
345  * \param u32_baudRate The baud rate to use.
346  */
347 void configDefaultUART(uint32_t u32_baudRate) {
348 #ifndef BOOTLOADER
349  __C30_UART = DEFAULT_UART;
350 #endif
351 
352 #if DEFAULT_UART == 1
353  configUART1(u32_baudRate);
354 #elif DEFAULT_UART == 2
355  configUART2(u32_baudRate);
356 #elif DEFAULT_UART == 3
357  configUART3(u32_baudRate);
358 #elif DEFAULT_UART == 4
359  configUART4(u32_baudRate);
360 #else
361 # error "Invalid DEFAULT_UART."
362 #endif
363 }
void outUint16Decimal(uint16_t u16_x)
Definition: pic24_serial.c:242
#define DEFAULT_UART
void outUint32(uint32_t u32_x)
Definition: pic24_serial.c:190
#define REPORT_ERROR(msg)
Definition: pic24_util.h:72
uint8_t isCharReady(void)
Definition: pic24_serial.c:316
uint16_t inString(char *psz_buff, int16_t u16_maxCount)
Definition: pic24_serial.c:140
void outUint8Decimal(uint8_t u8_x)
Definition: pic24_serial.c:207
uint8_t inChar1(void)
Definition: pic24_uart.c:214
uint8_t inChar(void)
Definition: pic24_serial.c:277
void outUint16(uint16_t u16_x)
Definition: pic24_serial.c:176
void configDefaultUART(uint32_t u32_baudRate)
Definition: pic24_serial.c:347
void outString(const char *psz_s)
Definition: pic24_serial.c:90
void configUART1(uint32_t u32_baudRate)
Definition: pic24_uart.c:250
void outChar1(uint8_t u8_c)
Definition: pic24_uart.c:145
uint16_t inStringEcho(char *psz_buff, int16_t u16_maxCount)
Definition: pic24_serial.c:147
void outChar(uint8_t u8_c)
A system-dependent macro to output one character.
Definition: pic24_serial.c:58
unsigned char uint8_t
An abbreviation for an 8-bit unsigned integer.
Definition: dataXferImpl.h:194
void outUint8(uint8_t u8_x)
Definition: pic24_serial.c:167
uint8_t inCharEcho(void)
Definition: pic24_serial.c:305
uint8_t isCharReady1(void)
Definition: pic24_uart.c:206