1/*----------------------------------------------------------------------------
2 *         ATMEL Microcontroller Software Support  -  ROUSSET  -
3 *----------------------------------------------------------------------------
4 * The software is delivered "AS IS" without warranty or condition of any
5 * kind, either express, implied or statutory. This includes without
6 * limitation any warranty or condition with respect to merchantability or
7 * fitness for any particular purpose, or against the infringements of
8 * intellectual property rights of others.
9 *----------------------------------------------------------------------------
10 * File Name           : com.c
11 * Object              :
12 * Creation            : HIi   03/27/2003
13 *
14 *----------------------------------------------------------------------------
15 */
16#include "AT91RM9200.h"
17#include "lib_AT91RM9200.h"
18#include "config.h"
19#include "com.h"
20#include "stdio.h"
21
22static char erase_seq[] = "\b \b";		/* erase sequence	*/
23
24#define MAX_UARTS 1
25
26//unsigned int usa[2] = {(unsigned int)AT91C_BASE_DBGU, (unsigned int)AT91C_ALTERNATE_USART};
27unsigned int usa[1] = {(unsigned int)AT91C_BASE_DBGU};
28unsigned int us;
29int port_detected;
30
31void at91_init_uarts(void)
32{
33	int i;
34
35	port_detected = 0;
36	AT91F_DBGU_CfgPIO();
37	AT91F_US0_CfgPIO();
38	AT91F_US0_CfgPMC();
39
40	for(i=0; i<MAX_UARTS; i++) {
41		us = usa[i];
42		AT91F_US_ResetRx((AT91PS_USART)us);
43		AT91F_US_ResetTx((AT91PS_USART)us);
44
45		// Configure DBGU
46		AT91F_US_Configure(
47			(AT91PS_USART)us, // DBGU base address
48			AT91C_MASTER_CLOCK,            // 60 MHz
49			AT91C_US_ASYNC_MODE,           // mode Register to be programmed
50			115200,                        // baudrate to be programmed
51			0                              // timeguard to be programmed
52			);
53
54		// Enable Transmitter
55		AT91F_US_EnableTx((AT91PS_USART)us);
56		// Enable Receiver
57		AT91F_US_EnableRx((AT91PS_USART)us);
58	}
59	us = usa[0];
60}
61
62int at91_serial_putc(int ch)
63{
64	if (ch == '\n')
65		at91_serial_putc('\r');
66	while (!AT91F_US_TxReady((AT91PS_USART)us));
67	AT91F_US_PutChar((AT91PS_USART)us, (char)ch);
68	return ch;
69}
70
71/* This getc is modified to be able work on more than one port. On certain
72 * boards (i.e. Figment Designs VersaLink), the debug port is not available
73 * once the unit is in it's enclosure, so, if one needs to get into dfboot
74 * for any reason it is impossible. With this getc, it scans between the debug
75 * port and another port and once it receives a character, it sets that port
76 * as the debug port. */
77int at91_serial_getc()
78{
79	while(1) {
80#if 0
81		if (!port_detected) {
82			if (us == usa[0]) {
83				us = usa[1];
84			}
85			else {
86				us = usa[0];
87			}
88		}
89#endif
90		if(AT91F_US_RxReady((AT91PS_USART)us)) {
91#if 0
92			port_detected = 1;
93#endif
94			return((int)AT91F_US_GetChar((AT91PS_USART)us));
95		}
96	}
97}
98
99/*-----------------------------------------------------------------------------
100 * Function Name       : AT91F_ReadLine()
101 * Object              :
102 * Input Parameters    :
103 * Return value		:
104 *-----------------------------------------------------------------------------
105 */
106int AT91F_ReadLine (const char *const prompt, char *console_buffer)
107{
108	char *p = console_buffer;
109	int	n = 0;					/* buffer index		*/
110	int	plen = strlen (prompt);	/* prompt length	*/
111	int	col;					/* output column cnt	*/
112	char	c;
113
114	/* print prompt */
115	if (prompt)
116		printf(prompt);
117	col = plen;
118
119	for (;;) {
120		c = getc();
121
122		switch (c) {
123			case '\r':				/* Enter		*/
124			case '\n':
125				*p = '\0';
126				puts ("\n");
127				return (p - console_buffer);
128
129			case 0x03:				/* ^C - break	*/
130				console_buffer[0] = '\0';	/* discard input */
131				return (-1);
132
133			case 0x08:				/* ^H  - backspace	*/
134			case 0x7F:				/* DEL - backspace	*/
135				if (n) {
136					--p;
137					printf(erase_seq);
138					col--;
139					n--;
140					}
141				continue;
142
143			default:
144			/*
145			 * Must be a normal character then
146			 */
147			if (n < (AT91C_CB_SIZE -2))
148			{
149				++col;		/* echo input		*/
150				putc(c);
151				*p++ = c;
152				++n;
153			}
154			else
155			{			/* Buffer full		*/
156				putc('\a');
157			}
158		}
159	}
160}
161
162
163/*-----------------------------------------------------------------------------
164 * Function Name       : AT91F_WaitKeyPressed()
165 * Object              :
166 * Input Parameters    :
167 * Return value		:
168 *-----------------------------------------------------------------------------
169 */
170void AT91F_WaitKeyPressed(void)
171{
172	int c;
173    	puts("KEY");
174		c = getc();
175	putc('\n');
176}
177
178int puts(const char *str)
179{
180  while(*str != 0) {
181		at91_serial_putc(*str);
182		str++;
183		}
184	return 1;
185}
186
187int putc(int c)
188{
189  return at91_serial_putc(c);
190}
191
192int putchar(c)
193{
194	return putc(c);
195}
196
197int getc()
198{
199  return at91_serial_getc();
200}
201
202int strlen(const char *str)
203{
204  int len = 0;
205
206  if(str == (char *)0)
207    return 0;
208
209  while(*str++ != 0)
210    len++;
211
212  return len;
213}
214
215#define ZEROPAD 1               /* pad with zero */
216#define SIGN    2               /* unsigned/signed long */
217#define LEFT    4              /* left justified */
218#define LARGE   8              /* use 'ABCDEF' instead of 'abcdef' */
219
220#define do_div(n,base) ({ \
221        int __res; \
222        __res = ((unsigned) n) % (unsigned) base; \
223        n = ((unsigned) n) / (unsigned) base; \
224        __res; \
225})
226
227static int number(int num, int base, int size,
228                  int precision, int type)
229{
230  char c, sign, tmp[66];
231  const char *digits="0123456789ABCDEF";
232  int i;
233
234  if (type & LEFT)
235    type &= ~ZEROPAD;
236  if (base < 2 || base > 16)
237    return 0;
238  c = (type & ZEROPAD) ? '0' : ' ';
239  sign = 0;
240
241  if(type & SIGN && num < 0)
242    {
243      sign = '-';
244      num = -num;
245      size--;
246    }
247
248  i = 0;
249  if(num == 0)
250    tmp[i++] = digits[0];
251  else while(num != 0)
252    tmp[i++] = digits[do_div(num, base)];
253
254  if(i > precision)
255    precision = i;
256  size -= precision;
257
258  if(!(type&(ZEROPAD+LEFT)))
259    while(size-->0)
260      putc(' ');
261
262  if(sign)
263    putc(sign);
264
265  if (!(type & LEFT))
266    while (size-- > 0)
267      putc(c);
268
269  while (i < precision--)
270    putc('0');
271
272  while (i-- > 0)
273    putc(tmp[i]);
274
275  while (size-- > 0)
276    putc(' ');;
277
278  return 1;
279}
280
281int hvfprintf(const char *fmt, va_list va)
282{
283  char *s;
284
285	do {
286		if(*fmt == '%')	{
287			bool done = false;
288
289			int type = 0;
290			int precision = 0;
291
292			do {
293				fmt++;
294				switch(*fmt) {
295				case '0' :
296					if(!precision)
297						type |= ZEROPAD;
298				case '1' :
299				case '2' :
300				case '3' :
301				case '4' :
302				case '5' :
303				case '6' :
304				case '7' :
305				case '8' :
306				case '9' :
307					precision = precision * 10 + (*fmt - '0');
308					break;
309				case '.' :
310					break;
311				case 's' :
312					s = va_arg(va, char *);
313					if(!s)
314						puts("<NULL>");
315					else
316						puts(s);
317					done = true;
318					break;
319				case 'c' :
320					putc(va_arg(va, int));
321					done = true;
322					break;
323				case 'd' :
324					number(va_arg(va, int), 10, 0, precision, type);
325					done = true;
326					break;
327				case 'x' :
328				case 'X' :
329					number(va_arg(va, int), 16, 0, precision, type);
330					done = true;
331					break;
332				case '%' :
333					putc(*fmt);
334					done = true;
335				default:
336					putc('%');
337					putc(*fmt);
338					done = true;
339					break;
340				}
341			} while(!done);
342		} else if(*fmt == '\\') {
343			fmt++;
344			if(*fmt == 'r') {
345				putc('\r');
346			} else if(*fmt == 'n') {
347				putc('\n');
348			}
349        	} else {
350         		putc(*fmt);
351        	}
352		fmt++;
353	} while(*fmt != 0);
354
355  return 0;
356}
357
358int printf(const char *fmt, ...)
359{
360  va_list ap;
361  int i;
362
363  va_start(ap, fmt);
364  i = hvfprintf(fmt, ap);
365  va_end(ap);
366
367  return i;
368}
369