Browse Source

Added usart/printf for debugging.

Vladimir N. Shilov 4 months ago
parent
commit
459a7f5fb4
7 changed files with 789 additions and 34 deletions
  1. 1 0
      Makefile
  2. 1 0
      inc/board.h
  3. 8 2
      inc/main.h
  4. 50 0
      inc/xprintf.h
  5. 3 2
      src/board.c
  6. 71 30
      src/main.c
  7. 655 0
      src/xprintf.c

+ 1 - 0
Makefile

@@ -41,6 +41,7 @@ BUILD_DIR = build
 C_SOURCES =  \
 src/main.c \
 src/board.c \
+src/xprintf.c \
 src/stm32g0xx_it.c \
 src/system_stm32g0xx.c
 

+ 1 - 0
inc/board.h

@@ -6,6 +6,7 @@
 /* Includes */
 #include "main.h"
 #include "gpio.h"
+#include "xprintf.h"
 
 /* Type Defs */
 /* Exported macros */

+ 8 - 2
inc/main.h

@@ -26,9 +26,8 @@ extern "C" {
 #endif
 
 /* Includes ------------------------------------------------------------------*/
+#include <stdbool.h>
 #include "stm32g0xx.h"
-
-/* Private includes ----------------------------------------------------------*/
 #include "board.h"
 
 /* Exported types ------------------------------------------------------------*/
@@ -92,6 +91,13 @@ typedef union {
 } nt32_t;
 
 /* Exported constants --------------------------------------------------------*/
+#ifndef true
+  #define true 1
+#endif
+#ifndef false
+  #define false 0
+#endif
+
 /* Exported macro ------------------------------------------------------------*/
 /* Exported functions prototypes ---------------------------------------------*/
 void Error_Handler(void);

+ 50 - 0
inc/xprintf.h

@@ -0,0 +1,50 @@
+/*------------------------------------------------------------------------*/
+/* Universal string handler for user console interface  (C)ChaN, 2021     */
+/*------------------------------------------------------------------------*/
+
+#ifndef XPRINTF_DEF
+#define XPRINTF_DEF
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XF_USE_OUTPUT	1	/* 1: Enable output functions */
+#define	XF_CRLF			1	/* 1: Convert \n ==> \r\n in the output char */
+#define	XF_USE_DUMP		1	/* 1: Enable put_dump function */
+#define	XF_USE_LLI		1	/* 1: Enable long long integer in size prefix ll */
+#define	XF_USE_FP		0	/* 1: Enable support for floating point in type e and f */
+#define XF_DPC			'.'	/* Decimal separator for floating point */
+#define XF_USE_INPUT	1	/* 1: Enable input functions */
+#define	XF_INPUT_ECHO	1	/* 1: Echo back input chars in xgets function */
+
+#if defined(__GNUC__) && __GNUC__ >= 10
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
+#if XF_USE_OUTPUT
+#define xdev_out(func) xfunc_output = (void(*)(int))(func)
+extern void (*xfunc_output)(int);
+void xputc (int chr);
+void xfputc (void (*func)(int), int chr);
+void xputs (const char* str);
+void xfputs (void (*func)(int), const char* str);
+void xprintf (const char* fmt, ...);
+void xsprintf (char* buff, const char* fmt, ...);
+void xfprintf (void (*func)(int), const char* fmt, ...);
+void put_dump (const void* buff, unsigned long addr, int len, int width);
+#endif
+
+#if XF_USE_INPUT
+#define xdev_in(func) xfunc_input = (int(*)(void))(func)
+extern int (*xfunc_input)(void);
+int xgets (char* buff, int len);
+int xatoi (char** str, long* res);
+int xatof (char** str, double* res);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 3 - 2
src/board.c

@@ -129,11 +129,12 @@ static void ADC_Init(void)
   ADC1->CFGR2 |= ADC_CFGR2_CKMODE_0;
 
   /* Poll for ADC channel configuration ready */
-  while ((ADC1->ISR & ADC_ISR_CCRDY) == 0) {};
+  //while ((ADC1->ISR & ADC_ISR_CCRDY) == 0) {};
   /* Clear flag ADC channel configuration ready */
   ADC1->ISR |= ADC_ISR_CCRDY;
 
-  ADC1->CFGR1 |= (ADC_CFGR1_EXTSEL_1 | ADC_CFGR1_EXTSEL_0 | ADC_CFGR1_EXTEN_0) | ADC_CFGR1_OVRMOD | ADC_CFGR1_EXTEN_0;
+  /* External trigger - Tim3 */
+  ADC1->CFGR1 |= (ADC_CFGR1_EXTSEL_1 | ADC_CFGR1_EXTSEL_0 | ADC_CFGR1_EXTEN_0 | ADC_CFGR1_OVRMOD);
 
    /* Enable ADC internal voltage regulator */
    ADC1->CR |= ADC_CR_ADVREGEN; // ???

+ 71 - 30
src/main.c

@@ -31,7 +31,12 @@ volatile flag_t Flag = {0};
 volatile uint32_t photo_Value;
 
 /* Private function prototypes -----------------------------------------------*/
-static void servo_demo(void);
+static void servo_open(void);
+static void servo_close(void);
+static void uart_puts(char *s);
+static void uart_putc(char c);
+static void uart_init(uint32_t baud);
+
 /* Private user code ---------------------------------------------------------*/
 
 /**
@@ -42,23 +47,36 @@ int main(void)
 {
   /* Initialize onBoard Hardware */
   Board_Init();
+  uart_init(115200);
+  uart_puts("\033[2J\033[1;1H"); // clear screen
+  xdev_out(uart_putc);
+  xputs("Skid\n");
 
-  servo_demo();
+  delay_ms(500);
+  servo_open();
+  delay_ms(500);
+  servo_close();
+  delay_ms(1000);
 
-  //while (photo_Value <= PHOTO_LEVEL) {
+  uart_putc('0');
+  xputc('\n');
+  while (photo_Value <= PHOTO_LEVEL) {
   //  IWDG->KR = 0xAAAA;
   //  __WFI();
-  //}
+    delay_ms(1000);
+    xprintf("photo_Value: %u\n", photo_Value);
+  }
+  uart_putc('1');
 
-  //LED_ON();
   /* Infinite loop */
   while (1)
   {
     /* wait for light on */
     while (photo_Value > PHOTO_LEVEL) {
-    IWDG->KR = 0xAAAA;
-    __WFI();
+      IWDG->KR = 0xAAAA;
+      __WFI();
     }
+    uart_putc('2');
     /* open servo 1 */
     TIM1->CCR1 = SERVO_OPEN_VAL;
     /* wait for light off */
@@ -66,14 +84,16 @@ int main(void)
       IWDG->KR = 0xAAAA;
       __WFI();
     }
+    uart_putc('3');
     /* close servo 1 */
     TIM1->CCR1 = SERVO_INIT_VAL;
     
     /* wait for light on */
     while (photo_Value > PHOTO_LEVEL) {
-    IWDG->KR = 0xAAAA;
-    __WFI();
+      IWDG->KR = 0xAAAA;
+      __WFI();
     }
+    uart_putc('4');
     /* open servo 2 */
     TIM1->CCR4 = SERVO_OPEN_VAL;
     /* wait for light off */
@@ -81,21 +101,58 @@ int main(void)
       IWDG->KR = 0xAAAA;
       __WFI();
     }
+    uart_putc('5');
     /* close servo 2 */
     TIM1->CCR4 = SERVO_INIT_VAL;
 
     /* end of life */
     while (1) {
-      char * msg = msg1;
-      while (*msg) {
-        USART1->TDR = *msg++;
-      }
-      IWDG->KR = 0xAAAA;
       __WFI();
     }
   }
 } /* End of mine() */
 
+static void servo_open(void) {
+  int i;
+  for (i=SERVO_INIT_VAL; i <= SERVO_OPEN_VAL; i+=20) {
+    TIM1->CCR1 = i;
+    TIM1->CCR4 = i;
+    delay_ms(40);
+  }
+}
+
+static void servo_close(void) {
+  int i;
+  for (i=SERVO_OPEN_VAL; i >= SERVO_INIT_VAL; i-=20) {
+    TIM1->CCR1 = i;
+    TIM1->CCR4 = i;
+    delay_ms(40);
+  }
+}
+
+static void uart_init(uint32_t baud)
+{
+  GPIO_SetPinMode(GPIOB, GPIO_PIN_6, GPIO_MODE_AFF);
+
+  RCC->APBENR2 |= RCC_APBENR2_USART1EN;
+
+  USART1->CR1 = USART_CR1_RE | USART_CR1_TE | USART_CR1_FIFOEN;
+  USART1->BRR = (SystemCoreClock / baud);
+  USART1->CR1 |= USART_CR1_UE;
+}
+
+static void uart_putc(char c)
+{
+  while (0 == (USART1->ISR & USART_ISR_TXE_TXFNF));
+  USART1->TDR = c;
+}
+
+static void uart_puts(char *s)
+{
+  while (*s)
+    uart_putc(*s++);
+}
+
 /**
   * @brief  This function is executed in case of error occurrence.
   * @retval None
@@ -109,22 +166,6 @@ void Error_Handler(void)
   }
 }
 
-static void servo_demo(void) {
-  int i;
-  for (i=SERVO_INIT_VAL; i <= SERVO_OPEN_VAL; i++) {
-    TIM1->CCR1 = i;
-    TIM1->CCR4 = i;
-    delay_ms(100);
-  }
-
-  delay_ms(10000);
-  for (i=SERVO_OPEN_VAL; i >= SERVO_INIT_VAL; i--) {
-    TIM1->CCR1 = i;
-    TIM1->CCR4 = i;
-    delay_ms(100);
-  }
-}
-
 #ifdef  USE_FULL_ASSERT
 /**
   * @brief  Reports the name of the source file and the source line number

+ 655 - 0
src/xprintf.c

@@ -0,0 +1,655 @@
+/*------------------------------------------------------------------------/
+/  Universal String Handler for Console Input and Output
+/-------------------------------------------------------------------------/
+/
+/ Copyright (C) 2021, ChaN, all right reserved.
+/
+/ xprintf module is an open source software. Redistribution and use of
+/ xprintf module in source and binary forms, with or without modification,
+/ are permitted provided that the following condition is met:
+/
+/ 1. Redistributions of source code must retain the above copyright notice,
+/    this condition and the following disclaimer.
+/
+/ This software is provided by the copyright holder and contributors "AS IS"
+/ and any warranties related to this software are DISCLAIMED.
+/ The copyright owner or contributors be NOT LIABLE for any damages caused
+/ by use of this software.
+/
+/-------------------------------------------------------------------------*/
+
+#include "xprintf.h"
+
+#define SZB_OUTPUT	32
+
+
+#if XF_USE_OUTPUT
+#include <string.h>
+#include <stdarg.h>
+void (*xfunc_output)(int);	/* Pointer to the default output device */
+static char *strptr;		/* Pointer to the output memory (used by xsprintf) */
+
+
+#if XF_USE_FP
+/*----------------------------------------------*/
+/* Floating point output                        */
+/*----------------------------------------------*/
+#include <math.h>
+
+
+static int ilog10 (double n)	/* Calculate log10(n) in integer output */
+{
+	int rv = 0;
+
+	while (n >= 10) {	/* Decimate digit in right shift */
+		if (n >= 100000) {
+			n /= 100000; rv += 5;
+		} else {
+			n /= 10; rv++;
+		}
+	}
+	while (n < 1) {		/* Decimate digit in left shift */
+		if (n < 0.00001) {
+			n *= 100000; rv -= 5;
+		} else {
+			n *= 10; rv--;
+		}
+	}
+	return rv;
+}
+
+
+static double i10x (int n)	/* Calculate 10^n */
+{
+	double rv = 1;
+
+	while (n > 0) {		/* Left shift */
+		if (n >= 5) {
+			rv *= 100000; n -= 5;
+		} else {
+			rv *= 10; n--;
+		}
+	}
+	while (n < 0) {		/* Right shift */
+		if (n <= -5) {
+			rv /= 100000; n += 5;
+		} else {
+			rv /= 10; n++;
+		}
+	}
+	return rv;
+}
+
+
+static void ftoa (
+	char* buf,	/* Buffer to output the generated string */
+	double val,	/* Real number to output */
+	int prec,	/* Number of fractinal digits */
+	char fmt	/* Notation */
+)
+{
+	int d;
+	int e = 0, m = 0;
+	char sign = 0;
+	double w;
+	const char *er = 0;
+
+
+	if (isnan(val)) {			/* Not a number? */
+		er = "NaN";
+	} else {
+		if (prec < 0) prec = 6;	/* Default precision (6 fractional digits) */
+		if (val < 0) {			/* Nagative value? */
+			val = -val; sign = '-';
+		} else {
+			sign = '+';
+		}
+		if (isinf(val)) {		/* Infinite? */
+			er = "INF";
+		} else {
+			if (fmt == 'f') {	/* Decimal notation? */
+				val += i10x(-prec) / 2;	/* Round (nearest) */
+				m = ilog10(val);
+				if (m < 0) m = 0;
+				if (m + prec + 3 >= SZB_OUTPUT) er = "OV";	/* Buffer overflow? */
+			} else {			/* E notation */
+				if (val != 0) {		/* Not a true zero? */
+					val += i10x(ilog10(val) - prec) / 2;	/* Round (nearest) */
+					e = ilog10(val);
+					if (e > 99 || prec + 6 >= SZB_OUTPUT) {	/* Buffer overflow or E > +99? */
+						er = "OV";
+					} else {
+						if (e < -99) e = -99;
+						val /= i10x(e);	/* Normalize */
+					}
+				}
+			}
+		}
+		if (!er) {	/* Not error condition */
+			if (sign == '-') *buf++ = sign;	/* Add a - if negative value */
+			do {				/* Put decimal number */
+				w = i10x(m);				/* Snip the highest digit d */
+				d = val / w; val -= d * w;
+				if (m == -1) *buf++ = XF_DPC;	/* Insert a decimal separarot if get into fractional part */
+				*buf++ = '0' + d;			/* Put the digit */
+			} while (--m >= -prec);			/* Output all digits specified by prec */
+			if (fmt != 'f') {	/* Put exponent if needed */
+				*buf++ = fmt;
+				if (e < 0) {
+					e = -e; *buf++ = '-';
+				} else {
+					*buf++ = '+';
+				}
+				*buf++ = '0' + e / 10;
+				*buf++ = '0' + e % 10;
+			}
+		}
+	}
+	if (er) {	/* Error condition? */
+		if (sign) *buf++ = sign;		/* Add sign if needed */
+		do *buf++ = *er++; while (*er);	/* Put error symbol */
+	}
+	*buf = 0;	/* Term */
+}
+#endif	/* XF_USE_FLOAT */
+
+
+/*----------------------------------------------*/
+/* Put a character                              */
+/*----------------------------------------------*/
+
+void xputc (
+	int chr				/* Character to be output */
+)
+{
+	xfputc(xfunc_output, chr);	/* Output it to the default output device */
+}
+
+
+void xfputc (			/* Put a character to the specified device */
+	void(*func)(int),	/* Pointer to the output function (null:strptr) */
+	int chr				/* Character to be output */
+)
+{
+	if (XF_CRLF && chr == '\n') xfputc(func, '\r');	/* CR -> CRLF */
+
+	if (func) {
+		func(chr);		/* Write a character to the output device */
+	} else if (strptr) {
+		 *strptr++ = chr;	/* Write a character to the memory */
+	}
+}
+
+
+
+/*----------------------------------------------*/
+/* Put a null-terminated string                 */
+/*----------------------------------------------*/
+
+void xputs (			/* Put a string to the default device */
+	const char* str		/* Pointer to the string */
+)
+{
+	xfputs(xfunc_output, str);
+}
+
+
+void xfputs (			/* Put a string to the specified device */
+	void(*func)(int),	/* Pointer to the output function */
+	const char*	str		/* Pointer to the string */
+)
+{
+	while (*str) {			/* Put the string */
+		xfputc(func, *str++);
+	}
+}
+
+
+
+/*----------------------------------------------*/
+/* Formatted string output                      */
+/*----------------------------------------------*/
+/*  xprintf("%d", 1234);			"1234"
+    xprintf("%6d,%3d%%", -200, 5);	"  -200,  5%"
+    xprintf("%-6u", 100);			"100   "
+    xprintf("%ld", 12345678);		"12345678"
+    xprintf("%llu", 0x100000000);	"4294967296"	<XF_USE_LLI>
+    xprintf("%lld", -1LL);			"-1"			<XF_USE_LLI>
+    xprintf("%04x", 0xA3);			"00a3"
+    xprintf("%08lX", 0x123ABC);		"00123ABC"
+    xprintf("%016b", 0x550F);		"0101010100001111"
+    xprintf("%*d", 6, 100);			"   100"
+    xprintf("%s", "String");		"String"
+    xprintf("%5s", "abc");			"  abc"
+    xprintf("%-5s", "abc");			"abc  "
+    xprintf("%-5s", "abcdefg");		"abcdefg"
+    xprintf("%-5.5s", "abcdefg");	"abcde"
+    xprintf("%-.5s", "abcdefg");	"abcde"
+    xprintf("%-5.5s", "abc");		"abc  "
+    xprintf("%c", 'a');				"a"
+    xprintf("%12f", 10.0);			"   10.000000"	<XF_USE_FP>
+    xprintf("%.4E", 123.45678);		"1.2346E+02"	<XF_USE_FP>
+*/
+
+static void xvfprintf (
+	void(*func)(int),	/* Pointer to the output function */
+	const char*	fmt,	/* Pointer to the format string */
+	va_list arp			/* Pointer to arguments */
+)
+{
+	unsigned int r, i, j, w, f;
+	int n, prec;
+	char str[SZB_OUTPUT], c, d, *p, pad;
+#if XF_USE_LLI
+	long long v;
+	unsigned long long uv;
+#else
+	long v;
+	unsigned long uv;
+#endif
+
+	for (;;) {
+		c = *fmt++;					/* Get a format character */
+		if (!c) break;				/* End of format? */
+		if (c != '%') {				/* Pass it through if not a % sequense */
+			xfputc(func, c); continue;
+		}
+		f = w = 0;			 		/* Clear parms */
+		pad = ' '; prec = -1;
+		c = *fmt++;					/* Get first char of the sequense */
+		if (c == '0') {				/* Flag: left '0' padded */
+			pad = '0'; c = *fmt++;
+		} else {
+			if (c == '-') {			/* Flag: left justified */
+				f = 2; c = *fmt++;
+			}
+		}
+		if (c == '*') {				/* Minimum width from an argument */
+			n = va_arg(arp, int);
+			if (n < 0) {			/* Flag: left justified */
+				n = 0 - n; f = 2;
+			}
+			w = n; c = *fmt++;
+		} else {
+			while (c >= '0' && c <= '9') {	/* Minimum width */
+				w = w * 10 + c - '0';
+				c = *fmt++;
+			}
+		}
+		if (c == '.') {				/* Precision */
+			c = *fmt++;
+			if (c == '*') {				/* Precision from an argument */
+				prec = va_arg(arp, int);
+				c = *fmt++;
+			} else {
+				prec = 0;
+				while (c >= '0' && c <= '9') {
+					prec = prec * 10 + c - '0';
+					c = *fmt++;
+				}
+			}
+		}
+		if (c == 'l') {		/* Prefix: Size is long */
+			f |= 4; c = *fmt++;
+#if XF_USE_LLI
+			if (c == 'l') {	/* Prefix: Size is long long */
+				f |= 8; c = *fmt++;
+			}
+#endif
+		}
+		if (!c) break;				/* End of format? */
+		switch (c) {				/* Type is... */
+		case 'b':					/* Unsigned binary */
+			r = 2; break;
+		case 'o':					/* Unsigned octal */
+			r = 8; break;
+		case 'd':					/* Signed decimal */
+		case 'u':					/* Unsigned decimal */
+			r = 10; break;
+		case 'x':					/* Hexdecimal (lower case) */
+		case 'X':					/* Hexdecimal (upper case) */
+			r = 16; break;
+		case 'c':					/* A character */
+			xfputc(func, (char)va_arg(arp, int)); continue;
+		case 's':					/* String */
+			p = va_arg(arp, char*);		/* Get a pointer argument */
+			if (!p) p = "";				/* Null ptr generates a null string */
+			j = strlen(p);
+			if (prec >= 0 && j > (unsigned int)prec) j = prec;	/* Limited length of string body */
+			for ( ; !(f & 2) && j < w; j++) xfputc(func, pad);	/* Left pads */
+			while (*p && prec--) xfputc(func, *p++);/* String body */
+			while (j++ < w) xfputc(func, ' ');		/* Right pads */
+			continue;
+#if XF_USE_FP
+		case 'f':					/* Float (decimal) */
+		case 'e':					/* Float (e) */
+		case 'E':					/* Float (E) */
+			ftoa(p = str, va_arg(arp, double), prec, c);	/* Make fp string */
+			for (j = strlen(p); !(f & 2) && j < w; j++) xfputc(func, pad);	/* Left pads */
+			while (*p) xfputc(func, *p++);		/* Value */
+			while (j++ < w) xfputc(func, ' ');	/* Right pads */
+			continue;
+#endif
+		default:					/* Unknown type (passthrough) */
+			xfputc(func, c); continue;
+		}
+
+		/* Get an integer argument and put it in numeral */
+#if XF_USE_LLI
+		if (f & 8) {	/* long long argument? */
+			v = (long long)va_arg(arp, long long);
+		} else {
+			if (f & 4) {	/* long argument? */
+				v = (c == 'd') ? (long long)va_arg(arp, long) : (long long)va_arg(arp, unsigned long);
+			} else {		/* int/short/char argument */
+				v = (c == 'd') ? (long long)va_arg(arp, int) : (long long)va_arg(arp, unsigned int);
+			}
+		}
+#else
+		if (f & 4) {	/* long argument? */
+			v = (long)va_arg(arp, long);
+		} else {		/* int/short/char argument */
+			v = (c == 'd') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int);
+		}
+#endif
+		if (c == 'd' && v < 0) {	/* Negative value? */
+			v = 0 - v; f |= 1;
+		}
+		i = 0; uv = v;
+		do {	/* Make an integer number string */
+			d = (char)(uv % r); uv /= r;
+			if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
+			str[i++] = d + '0';
+		} while (uv != 0 && i < sizeof str);
+		if (f & 1) str[i++] = '-';					/* Sign */
+		for (j = i; !(f & 2) && j < w; j++) xfputc(func, pad);	/* Left pads */
+		do xfputc(func, str[--i]); while (i != 0);	/* Value */
+		while (j++ < w) xfputc(func, ' ');			/* Right pads */
+	}
+}
+
+
+void xprintf (			/* Put a formatted string to the default device */
+	const char*	fmt,	/* Pointer to the format string */
+	...					/* Optional arguments */
+)
+{
+	va_list arp;
+
+
+	va_start(arp, fmt);
+	xvfprintf(xfunc_output, fmt, arp);
+	va_end(arp);
+}
+
+
+void xfprintf (			/* Put a formatted string to the specified device */
+	void(*func)(int),	/* Pointer to the output function */
+	const char*	fmt,	/* Pointer to the format string */
+	...					/* Optional arguments */
+)
+{
+	va_list arp;
+
+
+	va_start(arp, fmt);
+	xvfprintf(func, fmt, arp);
+	va_end(arp);
+}
+
+
+void xsprintf (			/* Put a formatted string to the memory */
+	char* buff,			/* Pointer to the output buffer */
+	const char*	fmt,	/* Pointer to the format string */
+	...					/* Optional arguments */
+)
+{
+	va_list arp;
+
+
+	strptr = buff;		/* Enable destination for memory */
+	va_start(arp, fmt);
+	xvfprintf(0, fmt, arp);
+	va_end(arp);
+	*strptr = 0;		/* Terminate output string */
+	strptr = 0;			/* Disable destination for memory */
+}
+
+
+
+#if XF_USE_DUMP
+/*----------------------------------------------*/
+/* Dump a line of binary dump                   */
+/*----------------------------------------------*/
+
+void put_dump (
+	const void* buff,		/* Pointer to the array to be dumped */
+	unsigned long addr,		/* Heading address value */
+	int len,				/* Number of items to be dumped */
+	int width				/* Size of buff[0] (1, 2, 4) */
+)
+{
+	int i;
+	const unsigned char *bp;
+	const unsigned short *sp;
+	const unsigned long *lp;
+
+
+	xprintf("%08lX ", addr);		/* address */
+
+	switch (width) {
+	case 1:
+		bp = buff;
+		for (i = 0; i < len; i++) {		/* Hexdecimal dump */
+			xprintf(" %02X", bp[i]);
+		}
+		xputs("  ");
+		for (i = 0; i < len; i++) {		/* ASCII dump */
+			xputc((unsigned char)((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.'));
+		}
+		break;
+	case 2:
+		sp = buff;
+		do {							/* Hexdecimal dump */
+			xprintf(" %04X", *sp++);
+		} while (--len);
+		break;
+	case 4:
+		lp = buff;
+		do {							/* Hexdecimal dump */
+			xprintf(" %08LX", *lp++);
+		} while (--len);
+		break;
+	}
+
+	xputc('\n');
+}
+#endif	/* XF_USE_DUMP */
+
+#endif	/* XF_USE_OUTPUT */
+
+
+
+#if XF_USE_INPUT
+int (*xfunc_input)(void);	/* Pointer to the default input stream */
+
+/*----------------------------------------------*/
+/* Get a line from the input                    */
+/*----------------------------------------------*/
+
+
+int xgets (			/* 0:End of stream, 1:A line arrived */
+	char* buff,		/* Pointer to the buffer */
+	int len			/* Buffer length */
+)
+{
+	int c, i;
+
+
+	if (!xfunc_input) return 0;	/* No input function is specified */
+
+	i = 0;
+	for (;;) {
+		c = xfunc_input();			/* Get a char from the incoming stream */
+		if (c < 0 || c == '\r') break;	/* End of stream or CR? */
+		if (c == '\b' && i) {		/* BS? */
+			i--;
+			if (XF_INPUT_ECHO) xputc(c);
+			continue;
+		}
+		if (c >= ' ' && i < len - 1) {	/* Visible chars? */
+			buff[i++] = c;
+			if (XF_INPUT_ECHO) xputc(c);
+		}
+	}
+	if (XF_INPUT_ECHO) {
+		xputc('\r');
+		xputc('\n');
+	}
+	buff[i] = 0;	/* Terminate with a \0 */
+	return (int)(c == '\r');
+}
+
+
+/*----------------------------------------------*/
+/* Get a value of integer string                */
+/*----------------------------------------------*/
+/*	"123 -5   0x3ff 0b1111 0377  w "
+	    ^                           1st call returns 123 and next ptr
+	       ^                        2nd call returns -5 and next ptr
+                   ^                3rd call returns 1023 and next ptr
+                          ^         4th call returns 15 and next ptr
+                               ^    5th call returns 255 and next ptr
+                                  ^ 6th call fails and returns 0
+*/
+
+int xatoi (			/* 0:Failed, 1:Successful */
+	char **str,		/* Pointer to pointer to the string */
+	long *res		/* Pointer to the valiable to store the value */
+)
+{
+	unsigned long val;
+	unsigned char c, r, s = 0;
+
+
+	*res = 0;
+
+	while ((c = **str) == ' ') (*str)++;	/* Skip leading spaces */
+
+	if (c == '-') {		/* negative? */
+		s = 1;
+		c = *(++(*str));
+	}
+
+	if (c == '0') {
+		c = *(++(*str));
+		switch (c) {
+		case 'x':		/* hexdecimal */
+			r = 16; c = *(++(*str));
+			break;
+		case 'b':		/* binary */
+			r = 2; c = *(++(*str));
+			break;
+		default:
+			if (c <= ' ') return 1;	/* single zero */
+			if (c < '0' || c > '9') return 0;	/* invalid char */
+			r = 8;		/* octal */
+		}
+	} else {
+		if (c < '0' || c > '9') return 0;	/* EOL or invalid char */
+		r = 10;			/* decimal */
+	}
+
+	val = 0;
+	while (c > ' ') {
+		if (c >= 'a') c -= 0x20;
+		c -= '0';
+		if (c >= 17) {
+			c -= 7;
+			if (c <= 9) return 0;	/* invalid char */
+		}
+		if (c >= r) return 0;		/* invalid char for current radix */
+		val = val * r + c;
+		c = *(++(*str));
+	}
+	if (s) val = 0 - val;			/* apply sign if needed */
+
+	*res = val;
+	return 1;
+}
+
+
+#if XF_USE_FP
+/*----------------------------------------------*/
+/* Get a value of the real number string        */
+/*----------------------------------------------*/
+/* Float version of xatoi
+*/
+
+int xatof (			/* 0:Failed, 1:Successful */
+	char **str,		/* Pointer to pointer to the string */
+	double *res		/* Pointer to the valiable to store the value */
+)
+{
+	double val;
+	int s, f, e;
+	unsigned char c;
+
+
+	*res = 0;
+	s = f = 0;
+
+	while ((c = **str) == ' ') (*str)++;	/* Skip leading spaces */
+	if (c == '-') {			/* Negative? */
+		c = *(++(*str)); s = 1; 
+	} else if (c == '+') {	/* Positive? */
+		c = *(++(*str));
+	}
+	if (c == XF_DPC) {		/* Leading dp? */
+		f = -1; 			/* Start at fractional part */
+		c = *(++(*str));
+	}
+	if (c <= ' ') return 0;	/* Wrong termination? */
+	val = 0;
+	while (c > ' ') {		/* Get a value of decimal */
+		if (c == XF_DPC) {	/* Embedded dp? */
+			if (f < 0) return 0;	/* Wrong dp? */
+			f = -1;			/* Enter fractional part */
+		} else {
+			if (c < '0' || c > '9') break;	/* End of decimal? */
+			c -= '0';
+			if (f == 0) {	/* In integer part */
+				val = val * 10 + c;
+			} else {		/* In fractional part */
+				val += i10x(f--) * c;
+			}
+		}
+		c = *(++(*str));
+	}
+	if (c > ' ') {	/* It may be an exponent */
+		if (c != 'e' && c != 'E') return 0;	/* Wrong character? */
+		c = *(++(*str));
+		if (c == '-') {
+			c = *(++(*str)); s |= 2;	/* Negative exponent */
+		} else if (c == '+') {
+			c = *(++(*str));			/* Positive exponent */
+		}
+		if (c <= ' ') return 0;	/* Wrong termination? */
+		e = 0;
+		while (c > ' ') {		/* Get value of exponent */
+			c -= '0';
+			if (c > 9) return 0;	/* Not a numeral? */
+			e = e * 10 + c;
+			c = *(++(*str));
+		}
+		val *= i10x((s & 2) ? -e : e);	/* Apply exponent */
+	}
+
+	if (s & 1) val = -val;	/* Negate sign if needed */
+
+	*res = val;
+	return 1;
+}
+#endif /* XF_USE_FP */
+
+#endif /* XF_USE_INPUT */