⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 n_conio.c

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 C
字号:
/*
 *  Copyright (c) 2004-2006, Dennis Kuschel.
 *  All rights reserved. 
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote
 *      products derived from this software without specific prior written
 *      permission. 
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 *  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 *  INDIRECT,  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 *  OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


/**
 * @file   n_conio.c
 * @brief  nano layer, console I/O
 * @author Dennis Kuschel
 *
 * This file is originally from the pico]OS realtime operating system
 * (http://picoos.sourceforge.net).
 *
 * CVS-ID $Id: n_conio.c,v 1.8 2006/04/29 15:58:17 dkuschel Exp $
 */

#define _N_CONIO_C
#include "../src/nano/privnano.h"

/* check features */
#if (NOSCFG_FEATURE_CONOUT + NOSCFG_FEATURE_PRINTF + \
     NOSCFG_FEATURE_SPRINTF + NOSCFG_FEATURE_CONIN) != 0
#if POSCFG_FEATURE_SEMAPHORES == 0
#error POSCFG_FEATURE_SEMAPHORES not enabled
#endif
#endif



/*---------------------------------------------------------------------------
 * CONFIGURATION
 *-------------------------------------------------------------------------*/

#define FEAT_XPRINTF    (NOSCFG_FEATURE_PRINTF + NOSCFG_FEATURE_SPRINTF)
#define FEAT_PRINTOUT   (NOSCFG_FEATURE_CONOUT + FEAT_XPRINTF)



/*---------------------------------------------------------------------------
 * IMPORTS
 *-------------------------------------------------------------------------*/



/*---------------------------------------------------------------------------
 * FUNCTION PROTOTYPES
 *-------------------------------------------------------------------------*/

/* exported */
void nos_initConIO(void);

/* private */
#if FEAT_XPRINTF != 0
static void n_printf(const char *fmt, NOSARG_t *args);
#endif
#if NOSCFG_FEATURE_SPRINTF != 0
static UVAR_t n_updstr(char c);
#endif
#if (NOSCFG_FEATURE_CONOUT != 0) && (NOSCFG_CONOUT_HANDSHAKE != 0)
static UVAR_t nos_putchar(char c);
#endif



/*---------------------------------------------------------------------------
 * GLOBAL VARIABLES
 *-------------------------------------------------------------------------*/

#if FEAT_PRINTOUT != 0
static POSSEMA_t    printsema_g;
#endif

#if (NOSCFG_FEATURE_CONOUT != 0) && (NOSCFG_CONOUT_HANDSHAKE != 0)
static POSSEMA_t    stdoutPollsema_g;
static UVAR_t       stdoutWaiting_g;
static char         deferedCharacter_g;
static UVAR_t       deferedCharFlag_g;

#if NOSCFG_CONOUT_FIFOSIZE > 0
static char         cout_fifo_g[NOSCFG_CONOUT_FIFOSIZE + 1];
static UINT_t       cout_inptr_g;
static UINT_t       cout_outptr_g;
#endif

#define HAVEDEFCHAR_NO      0
#define HAVEDEFCHAR_YES     1
#define HAVEDEFCHAR_FLAG    2

#endif


#if FEAT_XPRINTF != 0
static char         nbrbuf_g[(sizeof(INT_t)*5+1)/2];
#endif

#if NOSCFG_FEATURE_CONIN != 0
static UVAR_t       cin_inptr_g;
static UVAR_t       cin_outptr_g;
static UVAR_t       cin_waiting_g;
static char         cin_buf[NOSCFG_CONIO_KEYBUFSIZE + 1];
static POSSEMA_t    cin_sema_g;
#endif



/*---------------------------------------------------------------------------
 * MACROS
 *-------------------------------------------------------------------------*/

#if (NOSCFG_FEATURE_PRINTF != 0) && (NOSCFG_FEATURE_SPRINTF != 0)
typedef UVAR_t (*NPRINTFUNC_t)(char c);
static NPRINTFUNC_t       prf_g;
#define SET_PRFUNC(func)  prf_g = &(func)
#define CALL_PRFUNC(c)    (prf_g)(c)
#else
#define SET_PRFUNC(func)  do { } while(0)
#if NOSCFG_FEATURE_PRINTF != 0
#if NOSCFG_CONOUT_HANDSHAKE == 1
#define CALL_PRFUNC(c)    nos_putchar(c)
#else
#define CALL_PRFUNC(c)    p_putchar(c)
#endif
#else
#define CALL_PRFUNC(c)    n_updstr(c)
#endif
#endif



/*---------------------------------------------------------------------------
 * CONSOLE OUTPUT FUNCTIONS
 *-------------------------------------------------------------------------*/

#if NOSCFG_FEATURE_CONOUT != 0

#if NOSCFG_CONOUT_HANDSHAKE != 0

void  c_nos_putcharReady(void)
{
  register UVAR_t f;
  POS_LOCKFLAGS;

  if (posRunning_g == 0)
    return;

  POS_SCHED_LOCK;
  if (deferedCharFlag_g == HAVEDEFCHAR_YES)
  {
    POS_SCHED_UNLOCK;
    if (p_putchar(deferedCharacter_g) == 0)
    {
      /* We got a wrong callback, stdout is not ready yet. */
      return;
    }
    POS_SCHED_LOCK;
#if NOSCFG_CONOUT_FIFOSIZE > 0
    /* Try to clean the FIFO. The deferedCharFlag_g is set to NO
       when the FIFO is empty again. */
    f = 1;
    while (cout_outptr_g != cout_inptr_g)
    {
      deferedCharacter_g = cout_fifo_g[cout_outptr_g];
      if (++cout_outptr_g >= (NOSCFG_CONOUT_FIFOSIZE + 1))
        cout_outptr_g = 0;
      POS_SCHED_UNLOCK;
      if (p_putchar(deferedCharacter_g) == 0)
      {
        f = 0;
        POS_SCHED_LOCK;
        break;
      }
      POS_SCHED_LOCK;
    }
    if ((cout_outptr_g == cout_inptr_g) && (f != 0))
#endif
      deferedCharFlag_g = HAVEDEFCHAR_NO;
    f = stdoutWaiting_g;
    stdoutWaiting_g = 0;
    POS_SCHED_UNLOCK;
    if (f)
    {
      posSemaSignal(stdoutPollsema_g);
    }
  }
  else
  {
    /* change flag so we are able to detect a race condition */
    deferedCharFlag_g = HAVEDEFCHAR_NO;
    POS_SCHED_UNLOCK;
  }
}

/*-------------------------------------------------------------------------*/

static UVAR_t nos_putchar(char c)
{
  POS_LOCKFLAGS;

  POS_SCHED_LOCK;
  while (deferedCharFlag_g == HAVEDEFCHAR_YES)
  {
#if NOSCFG_CONOUT_FIFOSIZE > 0
    /* try to put character into output FIFO */
    UINT_t n = cout_inptr_g;
    if (++n >= (NOSCFG_CONOUT_FIFOSIZE + 1))
      n = 0;
    if (n != cout_outptr_g)
    {
      cout_fifo_g[cout_inptr_g] = c;
      cout_inptr_g = n;
      POS_SCHED_UNLOCK;
      return 1;
    }
#endif

    /* FIFO full, we have to wait */
    stdoutWaiting_g = 1;
    POS_SCHED_UNLOCK;
    posSemaGet(stdoutPollsema_g);
    POS_SCHED_LOCK;
  }

  deferedCharFlag_g = HAVEDEFCHAR_FLAG; /* we will put a character */
  POS_SCHED_UNLOCK;

  /* try to put the character */
  while (p_putchar(c) == 0)
  {
    POS_SCHED_LOCK;
    if (deferedCharFlag_g != HAVEDEFCHAR_FLAG)
    {
      /* Got a race condition. Try again. */
      deferedCharFlag_g = HAVEDEFCHAR_FLAG;
      POS_SCHED_UNLOCK;
      continue;
    }

    /* store character for later output */
    deferedCharacter_g = c;
    deferedCharFlag_g  = HAVEDEFCHAR_YES;
    POS_SCHED_UNLOCK;
    return 1;
  }

  POS_SCHED_LOCK;
  deferedCharFlag_g = HAVEDEFCHAR_NO;
  POS_SCHED_UNLOCK;
  return 1;
}

#endif /* NOSCFG_CONOUT_HANDSHAKE */

/*-------------------------------------------------------------------------*/

void nosPrintChar(char c)
{
  posSemaGet(printsema_g);
#if NOSCFG_CONOUT_HANDSHAKE != 0
  nos_putchar(c);
#else
  p_putchar(c);
#endif
  posSemaSignal(printsema_g);
}

/*-------------------------------------------------------------------------*/

void nosPrint(const char *str)
{
#if NOSCFG_FEATURE_PRINTF != 0
  NOSARG_t arg;
  posSemaGet(printsema_g);
#if NOSCFG_CONOUT_HANDSHAKE != 0
  SET_PRFUNC(nos_putchar);
#else
  SET_PRFUNC(p_putchar);
#endif
  arg = (NOSARG_t) str;
  n_printf("%s", &arg);
  posSemaSignal(printsema_g);
#else
  char c;
  posSemaGet(printsema_g);
  c = *str;
  while (c != 0)
  {
    if (c == '\n')
#if NOSCFG_CONOUT_HANDSHAKE != 0
      (void) nos_putchar('\r');
    (void) nos_putchar(c);
#else
      (void) p_putchar('\r');
    (void) p_putchar(c);
#endif
    c = *++str;
  }
  posSemaSignal(printsema_g);
#endif
}

#endif /* NOSCFG_FEATURE_CONOUT */

/*-------------------------------------------------------------------------*/

#if FEAT_XPRINTF != 0

void n_printf(const char *fmt, NOSARG_t *args)
{
  char   b, c, *s;
  UVAR_t base;
  UINT_t nbr;
  unsigned char a = 0;
  char   fill = 0;
  char   width = 0;
  UVAR_t i = 0;
  char   *f = (char*) fmt;

  while (*f != 0)
  {
    c = *f++;

    /* print usual characters */
    if (c != '%')
    {
      if (c == '\n')
        CALL_PRFUNC('\r');
      CALL_PRFUNC(c);
      continue;
    }

    /* test if next character is a '%' */
    c = *f++;
    if (c == '%')
    {
      CALL_PRFUNC('%');
      continue;
    }

    /* save index to value in parameter list */
    nbr = (UINT_t) args[a];
    s   = (char*)  args[a];
    a++;

    /* get width. width can be '1'-'9', '01'-'09', or '*' */
    width = 0;
    fill  = c;
    base = 10;
    if ((c >= '1') && (c <= '9'))
    {
      fill = ' ';
      width = c - '0';
      c = *f++;
    }
    else
    {
      if ((c == ' ') || (c == '0'))
      {
        c = *f++;
      }
      else
      if (c == '.')
      {
        fill = '0';
        c = *f++;
      }
      if ((c >= '1') && (c <= '9'))
      {
        width = c - '0';
        c = *f++;
      }
      else
      if (c == '*')
      {
        width = (char) (UINT_t) args[a++];
        c = *f++;
      }
    }

    /* skip size modifiers (we only support INT_t) */
    if ((c == 'h') || (c == 'l'))
    {
      c = *f++;
    }

    /* Get format specifier.
       All not checked specifiers are ignored. */
    if ((c == 'd') || (c == 'i'))
    {
      if ((INT_t)nbr < 0)
      {
        nbr = 0 - nbr;
        CALL_PRFUNC('-');
      }
    }
    else
    if (c == 'u')
    {
    }
    else
    if (c == 'o')
    {
      base = 8;
    }
    else
    if ((c == 'x') || (c == 'X'))
    {
      base = 16;
    }
    else
    if (c == 'c')
    {
      CALL_PRFUNC((char)nbr);
      continue;
    }
    else
    if (c == 's')
    {
      while (*s != 0)
      {
        if (*s == '\n')
          CALL_PRFUNC('\r');
        CALL_PRFUNC(*s++);
      }
      continue;
    }
    else
    {
      continue;
    }

    /* make string from binary number */
    do
    {
      b = (char) (nbr % (UINT_t) base);
      if (b > 9)
      {
        if (c == 'X')
        {
          b += 'A' - 10;
        }
        else
        {
          b += 'a' - 10;
        }
      }
      else
      {
        b += '0';
      }
      nbr /= (UINT_t) base;
      nbrbuf_g[i++] = b;
    }
    while (nbr != 0);

    /* print leading zeros or spaces */
    while ((UVAR_t)width > i)
    {
      CALL_PRFUNC(fill);
      width--;
    }

    /* print number */
    do
    {
      CALL_PRFUNC(nbrbuf_g[--i]);
    }
    while (i != 0);
  }
}

#endif /* FEAT_XPRINTF */

/*-------------------------------------------------------------------------*/

#if NOSCFG_FEATURE_PRINTF != 0

void n_printFormattedN(const char *fmt, NOSARG_t args)
{
  posSemaGet(printsema_g);
#if NOSCFG_CONOUT_HANDSHAKE != 0
  SET_PRFUNC(nos_putchar);
#else
  SET_PRFUNC(p_putchar);
#endif
  n_printf(fmt, args);
  posSemaSignal(printsema_g);
}

#endif /* NOSCFG_FEATURE_PRINTF */

/*-------------------------------------------------------------------------*/

#if NOSCFG_FEATURE_SPRINTF != 0

static char *sprptr_g;

static UVAR_t n_updstr(char c)
{
  *sprptr_g++ = c;
  return 1;
}

void n_sprintFormattedN(char *buf, const char *fmt, NOSARG_t args)
{
  posSemaGet(printsema_g);
  SET_PRFUNC(n_updstr);
  sprptr_g = buf;
  n_printf(fmt, args);
  *sprptr_g = 0;
  posSemaSignal(printsema_g);
}

#endif /* NOSCFG_FEATURE_SPRINTF */



/*---------------------------------------------------------------------------
 * CONSOLE INPUT FUNCTIONS
 *-------------------------------------------------------------------------*/

#if NOSCFG_FEATURE_CONIN != 0

void c_nos_keyinput(UVAR_t key)
{
  UVAR_t n;
  POS_LOCKFLAGS;

  POS_SCHED_LOCK;
  n = cin_inptr_g + 1;
  if (n > NOSCFG_CONIO_KEYBUFSIZE)
    n = 0;
  if (n != cin_outptr_g)
  {
    cin_buf[cin_inptr_g] = key;
    cin_inptr_g = n;
  }
  POS_SCHED_UNLOCK;

  if (cin_waiting_g != 0)
    posSemaSignal(cin_sema_g);
}

/*-------------------------------------------------------------------------*/

char nosKeyGet(void)
{
  char c;
  POS_LOCKFLAGS;

  POS_SCHED_LOCK;
  for(;;)
  {
    if (cin_inptr_g != cin_outptr_g)
    {
      c = cin_buf[cin_outptr_g];
      if (++cin_outptr_g > NOSCFG_CONIO_KEYBUFSIZE)
        cin_outptr_g = 0;
      break;
    }
    ++cin_waiting_g;
    POS_SCHED_UNLOCK;
    posSemaGet(cin_sema_g);
    POS_SCHED_LOCK;
    --cin_waiting_g;
  }
  POS_SCHED_UNLOCK;
  return c;
}

/*-------------------------------------------------------------------------*/

UVAR_t nosKeyPressed(void)
{
  return (cin_inptr_g != cin_outptr_g) ? 1 : 0;
}

#endif /* NOSCFG_FEATURE_CONIN */



/*---------------------------------------------------------------------------
 * INITIALIZATION
 *-------------------------------------------------------------------------*/

#if (NOSCFG_FEATURE_CONIN != 0) || (FEAT_PRINTOUT != 0)

void nos_initConIO(void)
{
#if NOSCFG_FEATURE_CONIN != 0
  cin_inptr_g   = 0;
  cin_outptr_g  = 0;
  cin_waiting_g = 0;
  cin_sema_g    = posSemaCreate(0);
  POS_SETEVENTNAME(cin_sema_g, "conio key wait");
#if (POSCFG_FEATURE_SOFTINTS != 0)
  posSoftIntSetHandler(0, c_nos_keyinput);
#endif
#endif

#if FEAT_PRINTOUT != 0
  printsema_g = posSemaCreate(1);
  POS_SETEVENTNAME(printsema_g, "conio print sync");
#endif
#if (NOSCFG_FEATURE_CONOUT != 0) && (NOSCFG_CONOUT_HANDSHAKE != 0)
  deferedCharFlag_g = HAVEDEFCHAR_NO;
  stdoutWaiting_g = 0;
  stdoutPollsema_g = posSemaCreate(0);
  POS_SETEVENTNAME(cin_sema_g, "conio print wait");
#if NOSCFG_CONOUT_FIFOSIZE > 0
  cout_inptr_g  = 0;
  cout_outptr_g = 0;
#endif
#endif
}

#else

/* this is just a dummy function */
void nos_initConIO(void) {}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -