Esempio n. 1
0
void nxgl_circlepts(FAR const struct nxgl_point_s *center, nxgl_coord_t radius,
                    FAR struct nxgl_point_s *circle)
{
  nxgl_coord_t xoffs;
  nxgl_coord_t yoffs;

  /* 0, 90, 180, and 270 degrees are the easiest */

  circle[POINT_0p0].x   = center->x + radius;
  circle[POINT_0p0].y   = center->y;
  circle[POINT_90p0].x  = center->x;
  circle[POINT_90p0].y  = center->y + radius;
  circle[POINT_180p0].x = center->x - radius;
  circle[POINT_180p0].y = center->y;
  circle[POINT_270p0].x = center->x;
  circle[POINT_270p0].y = center->y - radius;

  /* Now 22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, and 337.5 */

  xoffs = b16toi(b16muli(COS_22p5, radius) + b16HALF);
  yoffs = b16toi(b16muli(SIN_22p5, radius) + b16HALF);

  circle[POINT_22p5].x  = center->x + xoffs;
  circle[POINT_22p5].y  = center->y + yoffs;
  circle[POINT_157p5].x = center->x - xoffs;
  circle[POINT_157p5].y = center->y + yoffs;
  circle[POINT_202p5].x = center->x - xoffs;
  circle[POINT_202p5].y = center->y - yoffs;
  circle[POINT_337p5].x = center->x + xoffs;
  circle[POINT_337p5].y = center->y - yoffs;

  circle[POINT_67p5].x  = center->x + yoffs;
  circle[POINT_67p5].y  = center->y + xoffs;
  circle[POINT_112p5].x = center->x - yoffs;
  circle[POINT_112p5].y = center->y + xoffs;
  circle[POINT_247p5].x = center->x - yoffs;
  circle[POINT_247p5].y = center->y - xoffs;
  circle[POINT_292p5].x = center->x + yoffs;
  circle[POINT_292p5].y = center->y - xoffs;

  /* Finally, 45.0, 135.0, 225.0, 315.0 */

  xoffs = b16toi(b16muli(COS_45p0, radius) + b16HALF);

  circle[POINT_45p0].x  = center->x + xoffs;
  circle[POINT_45p0].y  = center->y + xoffs;
  circle[POINT_135p0].x = center->x - xoffs;
  circle[POINT_135p0].y = center->y + xoffs;
  circle[POINT_225p0].x = center->x - xoffs;
  circle[POINT_225p0].y = center->y - xoffs;
  circle[POINT_315p0].x = center->x + xoffs;
  circle[POINT_315p0].y = center->y - xoffs;
}
Esempio n. 2
0
void nxgl_rgb2yuv(uint8_t r, uint8_t g, uint8_t b,
                  uint8_t *y, uint8_t *u, uint8_t *v)
{
  /* Per the JFIF specification:
   *
   * Y =       (0.2990 * R) + (0.5870 * G) + (0.1140 * B)
   * U = 128 - (0.1687 * R) - (0.3313 * G) + (0.5000 * B)
   * V = 128 + (0.5000 * R) - (0.4187 * G) - (0.0813 * B);
   */

  *y = (uint8_t)b16toi(b16muli(b16_P2990, r) + b16muli(b16_P5870, g) + b16muli(b16_P1140, b));
  *u = (uint8_t)b16toi(b16_128P0 - b16muli(b16_P1687, r) - b16muli(b16_P3313, g) + b16muli(b16_P5000, b));
  *v = (uint8_t)b16toi(b16_128P0 + b16muli(b16_P5000, r) - b16muli(b16_P4187, g) - b16muli(b16_P0813, b));
}
Esempio n. 3
0
void nxgl_yuv2rgb(uint8_t y, uint8_t u, uint8_t v,
                  uint8_t *r, uint8_t *g, uint8_t *b)
{
  b16_t vm128 = itob16(v) - b16_128P0;
  b16_t um128 = itob16(u) - b16_128P0;

  /* Per the JFIF specification:
   *
   * R = Y                         + 1.40200 * (V - 128.0)
   * G = Y - 0.34414 * (U - 128.0) - 0.71414 * (V - 128.0)
   * B = Y + 1.77200 * (U - 128.0)
   */

  *r = (uint8_t)b16toi(itob16(y) +                             b16muli(b16_1P402, vm128));
  *g = (uint8_t)b16toi(itob16(y) - b16muli(b16_P3441, um128) - b16muli(b16_P7141, vm128));
  *b = (uint8_t)b16toi(itob16(y) + b16muli(b16_1P772, um128));
}
Esempio n. 4
0
static int trv_scale_input_pitch(FAR const struct ajoy_sample_s *sample)
{
  int tmp;
  b16_t pitch16;
  int pitch;

  trv_vdebug("  RAW: Y=%d\n", sample->as_y);

  tmp = sample->as_y - g_trv_joystick.centery;
  if ((g_trv_joystick.fplus && tmp >= 0) || (!g_trv_joystick.fplus && tmp < 0))
    {
       pitch16 = tmp * g_trv_joystick.uturnslope;
    }
  else
    {
       pitch16 = tmp * g_trv_joystick.dturnslope;
    }

  pitch = b16toi(pitch16 + b16HALF);
  trv_vdebug("  Calibrated: pitch=%d\n", pitch);
  return pitch;
}
Esempio n. 5
0
static int trv_scale_input_yaw(FAR const struct ajoy_sample_s *sample)
{
  int tmp;
  b16_t yaw16;
  int yaw;

  trv_vdebug("  RAW: X=%d\n", sample->as_x);

  tmp = sample->as_x - g_trv_joystick.centerx;
  if ((g_trv_joystick.lplus && tmp >= 0) || (!g_trv_joystick.lplus && tmp < 0))
    {
       yaw16 = tmp * g_trv_joystick.lturnslope;
    }
  else
    {
       yaw16 = tmp * g_trv_joystick.rturnslope;
    }

  yaw = -b16toi(yaw16 + b16HALF);
  trv_vdebug("  Calibrated: pitch=%d\n", yaw);
  return yaw;
}
Esempio n. 6
0
static int trv_scale_input_y(FAR const struct ajoy_sample_s *sample)
{
  int tmp;
  b16_t y16;
  int y;

  trv_vdebug("  RAW: Y=%d\n", sample->as_y);

  tmp = sample->as_y - g_trv_joystick.centery;
  if ((g_trv_joystick.fplus && tmp >= 0) || (!g_trv_joystick.fplus && tmp < 0))
    {
       y16 = tmp * g_trv_joystick.fwdslope;
    }
  else
    {
       y16 = tmp * g_trv_joystick.backslope;
    }

  y = b16toi(y16 + b16HALF);
  trv_vdebug("  Calibrated: Y=%d\n", y);
  return y;
}
Esempio n. 7
0
static int trv_scale_input_x(FAR const struct ajoy_sample_s *sample)
{
  int tmp;
  b16_t x16;
  int x;

  trv_vdebug("  RAW: X=%d\n", sample->as_x);

  tmp = sample->as_x - g_trv_joystick.centerx;
  if ((g_trv_joystick.lplus && tmp >= 0) || (!g_trv_joystick.lplus && tmp < 0))
    {
       x16 = tmp * g_trv_joystick.leftslope;
    }
  else
    {
       x16 = tmp * g_trv_joystick.rightslope;
    }

  x = b16toi(x16 + b16HALF);

  trv_vdebug("  Calibrated: X=%d\n", x);
  return x;
}
Esempio n. 8
0
void nxbe_filltrapezoid(FAR struct nxbe_window_s *wnd,
                        FAR const struct nxgl_rect_s *clip,
                        FAR const struct nxgl_trapezoid_s *trap,
                        nxgl_mxpixel_t color[CONFIG_NX_NPLANES])
{
  struct nxbe_filltrap_s info;
  struct nxgl_rect_s remaining;
  int i;

#ifdef CONFIG_DEBUG
  if (!wnd || !trap)
    {
      return;
    }
#endif

  /* Offset the trapezoid by the window origin to position it within
   * the framebuffer region
   */

  nxgl_trapoffset(&info.trap, trap, wnd->bounds.pt1.x, wnd->bounds.pt1.y);

  /* Create a bounding box that contains the trapezoid */

  remaining.pt1.x = b16toi(ngl_min(info.trap.top.x1, info.trap.bot.x1));
  remaining.pt1.y = info.trap.top.y;
  remaining.pt2.x = b16toi(ngl_max(info.trap.top.x2, info.trap.bot.x2));
  remaining.pt2.y = info.trap.bot.y;

  /* Clip to any user specified clipping window */

  if (clip)
    {
      struct nxgl_rect_s tmp;
      nxgl_rectoffset(&tmp, clip, wnd->bounds.pt1.x, wnd->bounds.pt1.y);
      nxgl_rectintersect(&remaining, &remaining, &tmp);
    }

  /* Clip to the limits of the window and of the background screen */

  nxgl_rectintersect(&remaining, &remaining, &wnd->bounds);
  nxgl_rectintersect(&remaining, &remaining, &wnd->be->bkgd.bounds);

  if (!nxgl_nullrect(&remaining))
    {
      info.cops.visible  = nxbe_clipfilltrapezoid;
      info.cops.obscured = nxbe_clipnull;

      /* Then process each color plane */

#if CONFIG_NX_NPLANES > 1
      for (i = 0; i < wnd->be->vinfo.nplanes; i++)
#else
      i = 0;
#endif
        {
          info.color = color[i];
          nxbe_clipper(wnd->above, &remaining, NX_CLIPORDER_DEFAULT,
                       &info.cops, &wnd->be->plane[i]);
        }
    }
}
Esempio n. 9
0
void NXGL_FUNCNAME(nxgl_filltrapezoid,NXGLIB_SUFFIX)
(FAR struct lcd_planeinfo_s *pinfo,
 FAR const struct nxgl_trapezoid_s *trap,
 FAR const struct nxgl_rect_s *bounds,
 NXGL_PIXEL_T color)
{
    unsigned int ncols;
    unsigned int topy;
    unsigned int boty;
    unsigned int row;
    unsigned int botw;
    b16_t        topx1;
    b16_t        topx2;
    b16_t        botx1;
    b16_t        botx2;
    b16_t        dx1dy;
    b16_t        dx2dy;
    int          dy;
    int          ix1;
    int          ix2;

    /* Get the top run endpoints */

    topx1 = trap->top.x1;
    topx2 = trap->top.x2;

    /* Calculate the number of rows to render */

    topy  = trap->top.y;
    boty  = trap->bot.y;

    /* Get the bottom run endpoints */

    botx1  = trap->bot.x1;
    botx2  = trap->bot.x2;

    /* Calculate the slope of the left and right side of the trapezoid */

    dy     = boty - topy;
    dx1dy  = b16divi((botx1 - topx1), dy);
    dx2dy  = b16divi((botx2 - topx2), dy);

    /* Perform vertical clipping */

    if (topy < bounds->pt1.y)
    {
        /* Is the entire trapezoid "above" the clipping window? */

        if (boty < bounds->pt1.y)
        {
            /* Yes.. then do nothing */

            return;
        }

        /* Calculate the x values for the new top run */

        dy      = bounds->pt1.y - topy;
        topx1  += dy * dx1dy;
        topx2  += dy * dx2dy;

        /* Clip the top row to render */

        topy    = bounds->pt1.y;
    }

    if (boty > bounds->pt2.y)
    {
        /* Is the entire trapezoid "below" the clipping window? */

        if (topy > bounds->pt2.y)
        {
            /* Yes.. then do nothing */

            return;
        }

        /* Calculate the x values for the new bottom run */

        dy      = boty - bounds->pt2.y;
        botx1  -= dy * dx1dy;
        botx2  -= dy * dx2dy;

        /* Clip the bottom row to render */

        boty    = bounds->pt2.y;
    }

    /* Handle the special case where the sides cross (as in an hourglass) */

    if (botx1 > botx2)
    {
        b16_t tmp;
        ngl_swap(botx1, botx2, tmp);
    }

    /* Fill the run buffer for the maximum run that we will need */

    ix1    = b16toi(topx1);
    ix1    = ngl_clipl(ix1, bounds->pt1.x);
    ix2    = b16toi(topx2);
    ix2    = ngl_clipr(ix2, bounds->pt2.x);
    ncols  = ix2 - ix1 + 1;

    ix1    = b16toi(botx1);
    ix1    = ngl_clipl(ix1, bounds->pt1.x);
    ix2    = b16toi(botx2);
    ix2    = ngl_clipr(ix2, bounds->pt2.x);
    botw   = ix2 - ix1 + 1;

    if (ncols < botw)
    {
        ncols = botw;
    }

    NXGL_FUNCNAME(nxgl_fillrun,NXGLIB_SUFFIX)((NXGLIB_RUNTYPE*)pinfo->buffer, color, ncols);

    /* Then fill the trapezoid row-by-row */

    for (row = topy; row <= boty; row++)
    {
        /* Handle the special case where the sides cross (as in an hourglass) */

        if (topx1 > topx2)
        {
            b16_t tmp;
            ngl_swap(topx1, topx2, tmp);
            ngl_swap(dx1dy, dx2dy, tmp);
        }

        /* Convert the positions to integer and get the run width, clipping to
         * fit within the bounding box.
         */

        ix1 = b16toi(topx1);
        ix1 = ngl_clipl(ix1, bounds->pt1.x);
        ix2 = b16toi(topx2);
        ix2 = ngl_clipr(ix2, bounds->pt2.x);

        /* Handle some corner cases where we draw nothing.  Otherwise, we will
         * always draw at least one pixel.
         */

        if (ix1 <= ix2)
        {
            /* Then draw the run from ix1 to ix2 at row */

            ncols = ix2 - ix1 + 1;
            (void)pinfo->putrun(row, ix1, pinfo->buffer, ncols);
        }

        /* Add the dx/dy value to get the run positions on the next row */

        topx1 += dx1dy;
        topx2 += dx2dy;
    }
}
Esempio n. 10
0
void nxgl_circletraps(FAR const struct nxgl_point_s *center, nxgl_coord_t radius,
                      FAR struct nxgl_trapezoid_s *circle)
{
  nxgl_coord_t xoffs;
  nxgl_coord_t yoffs;

  circle[0].top.x1      = itob16(center->x);
  circle[0].top.x2      = circle[0].top.x1;
  circle[0].top.y       = center->y - radius;

  circle[7].bot.x1      = circle[0].top.x1;
  circle[7].bot.x2      = circle[0].top.x1;
  circle[7].bot.y       = center->y + radius;

  circle[3].bot.x1      = itob16(center->x - radius);
  circle[3].bot.x2      = itob16(center->x + radius);
  circle[3].bot.y       = center->y;

  circle[4].top.x1      = circle[3].bot.x1;
  circle[4].top.x2      = circle[3].bot.x2;
  circle[4].top.y       = circle[3].bot.y;

  /* Now 22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, and 337.5 */

  xoffs = b16toi(b16muli(COS_22p5, radius) + b16HALF);
  yoffs = b16toi(b16muli(SIN_22p5, radius) + b16HALF);

  circle[2].bot.x1      = itob16(center->x - xoffs);
  circle[2].bot.x2      = itob16(center->x + xoffs);
  circle[2].bot.y       = center->y - yoffs;

  circle[3].top.x1      = circle[2].bot.x1;
  circle[3].top.x2      = circle[2].bot.x2;
  circle[3].top.y       = circle[2].bot.y;

  circle[4].bot.x1      = circle[2].bot.x1;
  circle[4].bot.x2      = circle[2].bot.x2;
  circle[4].bot.y       = center->y + yoffs;

  circle[5].top.x1      = circle[4].bot.x1;
  circle[5].top.x2      = circle[4].bot.x2;
  circle[5].top.y       = circle[4].bot.y;

  circle[0].bot.x1      = itob16(center->x - yoffs);
  circle[0].bot.x2      = itob16(center->x + yoffs);
  circle[0].bot.y       = center->y - xoffs;

  circle[1].top.x1      = circle[0].bot.x1;
  circle[1].top.x2      = circle[0].bot.x2;
  circle[1].top.y       = circle[0].bot.y;

  circle[6].bot.x1      = circle[1].top.x1;
  circle[6].bot.x2      = circle[1].top.x2;
  circle[6].bot.y       = center->y + xoffs;

  circle[7].top.x1      = circle[6].bot.x1;
  circle[7].top.x2      = circle[6].bot.x2;
  circle[7].top.y       = circle[6].bot.y;

  /* Finally, 45.0, 135.0, 225.0, 315.0 */

  xoffs = b16toi(b16muli(COS_45p0, radius) + b16HALF);

  circle[1].bot.x1      = itob16(center->x - xoffs);
  circle[1].bot.x2      = itob16(center->x + xoffs);
  circle[1].bot.y       = center->y - xoffs;

  circle[2].top.x1      = circle[1].bot.x1;
  circle[2].top.x2      = circle[1].bot.x2;
  circle[2].top.y       = circle[1].bot.y;
  
  circle[5].bot.x1      = circle[1].bot.x1;
  circle[5].bot.x2      = circle[1].bot.x2;
  circle[5].bot.y       = center->y + xoffs;

  circle[6].top.x1      = circle[5].bot.x1;
  circle[6].top.x2      = circle[5].bot.x2;
  circle[6].top.y       = circle[5].bot.y;
}
Esempio n. 11
0
void NXGL_FUNCNAME(nxgl_filltrapezoid,NXGLIB_SUFFIX)(
  FAR struct fb_planeinfo_s *pinfo,
  FAR const struct nxgl_trapezoid_s *trap,
  FAR const struct nxgl_rect_s *bounds,
  NXGL_PIXEL_T color)
{
  unsigned int stride;
  unsigned int width;
  FAR uint8_t *dest;
  FAR uint8_t *line;
  int nrows;
  b16_t x1;
  b16_t x2;
  nxgl_coord_t y1;
  nxgl_coord_t y2;
  b16_t dx1dy;
  b16_t dx2dy;

#if NXGLIB_BITSPERPIXEL < 8
  uint8_t mpixel = NXGL_MULTIPIXEL(color);
  uint8_t mask;
  int lnlen;
#endif

  /* Get the width of the framebuffer in bytes */

  stride = pinfo->stride;

  /* Get the top run position and the number of rows to draw */

  x1    = trap->top.x1;
  x2    = trap->top.x2;

  /* Calculate the number of rows to render */

  y1    = trap->top.y;
  y2    = trap->bot.y;
  nrows = y2 - y1 + 1;

  /* Calculate the slope of the left and right side of the trapezoid */

  if (nrows > 1)
    {
      dx1dy = b16divi((trap->bot.x1 - x1), nrows - 1);
      dx2dy = b16divi((trap->bot.x2 - x2), nrows - 1);
    }
  else
    {
      /* The trapezoid is a run! Use the average width. */

      x1    = (x1 + trap->bot.x1) >> 1;
      x2    = (x2 + trap->bot.x2) >> 1;
      dx1dy = 0;
      dx2dy = 0;
    }

  /* Perform vertical clipping */

  if (y1 < bounds->pt1.y)
    {
      /* Is the entire trapezoid "above" the clipping window? */

      if (y2 < bounds->pt1.y)
        {
          /* Yes.. then do nothing */

          return;
        }

      /* Calculate the x values for the new top run */

      int dy = bounds->pt1.y - y1;
      x1    += dy * dx1dy;
      x2    += dy * dx2dy;

      /* Clip and re-calculate the number of rows to render */

      y1     = bounds->pt1.y;
      nrows  = y2 - y1 + 1;
    }

  if (y2 > bounds->pt2.y)
    {
      /* Is the entire trapezoid "below" the clipping window? */

      if (y1 > bounds->pt2.y)
        {
          /* Yes.. then do nothing */

          return;
        }

      /* Clip and re-calculate the number of rows to render */

      y2     = bounds->pt2.y;
      nrows  = y2 - y1 + 1;
    }

  /* Get the address of the first byte on the first line */

  line = pinfo->fbmem + y1 * stride ;

  /* Then fill the trapezoid line-by-line */

  while (nrows--)
    {
      int ix1;
      int ix2;

      /* Handle the special case where the sides cross (as in an hourglass) */

      if (x1 > x2)
        {
          b16_t tmp;
          ngl_swap(x1, x2, tmp);
          ngl_swap(dx1dy, dx2dy, tmp);
        }

      /* Convert the positions to integer */

      ix1 = b16toi(x1);
      ix2 = b16toi(x2);

      /* Handle some corner cases where we draw nothing.  Otherwise, we will
       * always draw at least one pixel.
       */

      if (x1 <= x2 && ix2 >= bounds->pt1.x && ix1 <= bounds->pt2.x)
        {
          /* Get a clipped copies of the starting and ending X positions.  This
           * clipped truncates "down" and gives the quantized pixel holding the
           * fractional X position
           */

          ix1 = ngl_clipl(ix1, bounds->pt1.x);
          ix2 = ngl_clipr(ix2, bounds->pt2.x);

          /* Get the run length for the clipped row */

          width = ix2 - ix1 + 1;

#if NXGLIB_BITSPERPIXEL < 8
          /* Handle masking of the fractional initial byte */

#ifdef CONFIG_NX_PACKEDMSFIRST
          mask  = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix1));
#else
          mask  = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix1)));
#endif
          dest  = line;
          lnlen = width;

          if (lnlen > 1 && mask)
            {
              dest[0] = (dest[0] & ~mask) | (mpixel & mask);
              mask = 0xff;
              dest++;
              lnlen--;
            }

          /* Handle masking of the fractional final byte */

#ifdef CONFIG_NX_PACKEDMSFIRST
          mask &= (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix2)));
#else
          mask &= (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix2)));
#endif
          if (lnlen > 0 && mask)
            {
              dest[lnlen-1] = (dest[lnlen-1] & ~mask) | (mpixel & mask);
              lnlen--;
            }

          /* Handle all of the unmasked bytes in-between */

          if (lnlen > 0)
            {
              NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, lnlen);
            }

#else
          /* Then draw the run from (line + ix1) to (line + ix2) */

          dest = line + NXGL_SCALEX(ix1);
          NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, width);
#endif
        }

      /* Move to the start of the next line */

      line += stride;

      /* Add the dx/dy value to get the run positions on the next row */

      x1   += dx1dy;
      x2   += dx2dy;
    }
Esempio n. 12
0
static int up_setup(struct uart_dev_s *dev)
{
#ifndef CONFIG_SUPPRESS_UART_CONFIG
    struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
    uint64_t tmp;
    uint32_t regval;
    uint32_t ucr2;
    uint32_t refclk;
    uint32_t div;
    uint32_t num;
    uint32_t den;
    b16_t ratio;

    /* Disable the UART */

    up_serialout(priv, UART_UCR1, 0);
    up_serialout(priv, UART_UCR2, 0);
    up_serialout(priv, UART_UCR3, 0);
    up_serialout(priv, UART_UCR4, 0);

    /* Set up UCR2 */

    ucr2  = up_serialin(priv, UART_UCR2);
    ucr2 |= (UART_UCR2_SRST | UART_UCR2_IRTS)

            /* Select the number of data bits */

            DEBUGASSERT(priv->bits == 7 || priv->bits == 8);
    if (priv->bits == 8)
    {
        ucr2 |= UART_UCR2_WS;
    }

    /* Select the number of stop bits */

    if (priv->stopbits2)
    {
        ucr2 |= UART_UCR2_STPB;
    }

    /* Select even/odd parity */

    if (priv->parity)
    {
        DEBUGASSERT(priv->parity == 1 || priv->parity == 2);
        ucr2 |= UART_UCR2_PREN;
        if (priv->parity == 1)
        {
            ucr2 |= UART_UCR2_PROE;
        }
    }

    /* Setup hardware flow control */

    regval = 0;

#if 0
    if (priv->hwfc)
    {
        /* Don't ignore RTS */

        ucr2 &= ~UART_UCR2_IRTS;

        /* CTS controled by Rx FIFO */

        ucr2 |= UART_UCR2_CTSC;

        /* Set CTS trigger level */

        regval |= 30 << UART_UCR4_CTSTL_SHIFT;
    }
#endif

    /* i.MX reference clock (PERCLK1) is configured for 16MHz */

    up_serialout(priv, UART_UCR4, regval | UART_UCR4_REF16);

    /* Setup the new UART configuration */

    up_serialout(priv, UART_UCR2, ucr2);

    /* Select a reference clock divider.
     * REVISIT:  For now we just use a divider of 3.  That might not be
     * optimal for very high or very low baud settings.
     */

    div    = 3;
    refclk = (IMX_PERCLK1_FREQ / 3);

    /* Set the baud.
     *
     *   baud    = REFFREQ / (16 * NUM/DEN)
     *   baud    = REFFREQ / 16 / RATIO
     *   RATIO   = REFREQ / 16 / baud;
     *
     *   NUM     = SCALE * RATIO
     *   DEN     = SCALE
     *
     *   UMBR    = NUM-1
     *   UBIR    = DEN-1;
     */

    tmp   = ((uint64_t)refclk << (16 - 4)) / config->baud;
    DEBUGASSERT(tmp < 0x0000000100000000LL);
    ratio = (b16_t)tmp;

    /* Pick a scale factor that gives us about 14 bits of accuracy.
     * REVISIT:  Why not go all the way to 16-bits?
     */

    if (ratio < b16HALF)
    {
        den = (1 << 15);
        num = b16toi(ratio << 15);
        DEBUGASSERT(num > 0);
    }
    else if (ratio < b16ONE)
    {
        den = (1 << 14);
        num = b16toi(ratio << 14);
    }
    else if (ratio < itob16(2))
    {
        den = (1 << 13);
        num = b16toi(ratio << 13);
    }
    else if (ratio < itob16(4))
    {
        den = (1 << 12);
        num = b16toi(ratio << 12);
    }
    else if (ratio < itob16(8))
    {
        den = (1 << 11);
        num = b16toi(ratio << 11);
    }
    else if (ratio < itob16(16))
    {
        den = (1 << 10);
        num = b16toi(ratio << 10);
    }
    else if (ratio < itob16(32))
    {
        den = (1 << 9);
        num = b16toi(ratio << 9);
    }
    else if (ratio < itob16(64))
    {
        den = (1 << 8);
        num = b16toi(ratio << 8);
    }
    else if (ratio < itob16(128))
    {
        den = (1 << 7);
        num = b16toi(ratio << 7);
    }
    else if (ratio < itob16(256))
    {
        den = (1 << 6);
        num = b16toi(ratio << 6);
    }
    else if (ratio < itob16(512))
    {
        den = (1 << 5);
        num = b16toi(ratio << 5);
    }
    else if (ratio < itob16(1024))
    {
        den = (1 << 4);
        num = b16toi(ratio << 4);
    }
    else if (ratio < itob16(2048))
    {
        den = (1 << 3);
        num = b16toi(ratio << 3);
    }
    else if (ratio < itob16(4096))
    {
        den = (1 << 2);
        num = b16toi(ratio << 2);
    }
    else if (ratio < itob16(8192))
    {
        den = (1 << 1);
        num = b16toi(ratio << 1);
    }
    else /* if (ratio < itob16(16384)) */
    {
        DEBUGASSERT(ratio < itob16(16384));
        den = (1 << 0);
        num = b16toi(ratio);
    }

    /* Reduce if possible without losing accuracy. */

    while ((num & 1) == 0 && (den & 1) == 0)
    {
        num >>= 1;
        den >>= 1;
    }

    /* The actual values are we write to the registers need to be
     * decremented by 1.  NOTE that the UBIR must be set before
     * the UBMR.
     */

    up_serialout(priv, UART_UBIR, den - 1);
    up_serialout(priv, UART_UBMR, num - 1);

    /* Fixup the divisor, the value in the UFCR regiser is
     *
     *   000 = Divide input clock by 6
     *   001 = Divide input clock by 5
     *   010 = Divide input clock by 4
     *   011 = Divide input clock by 3
     *   100 = Divide input clock by 2
     *   101 = Divide input clock by 1
     *   110 = Divide input clock by 7
     */

    if (div == 7)
    {
        div = 6;
    }
    else
    {
        div = 6 - div;
    }
    regval = div << UART_UFCR_RFDIV_SHIFT;

    /* Set the TX trigger level to interrupt when the TxFIFO has 2 or fewer characters.
     * Set the RX trigger level to interrupt when the RxFIFO has 1 character.
     */

    regval |= ((2 << UART_UFCR_TXTL_SHIFT) | (1 << UART_UFCR_RXTL_SHIFT));
    up_serialout(priv, UART_UFCR, regval);

    /* Initialize the UCR1 shadow register */

    priv->ucr1 = up_serialin(priv, UART_UCR1);

    /* Enable the UART
     *
     *  UART_UCR1_UARTCLEN = Enable UART clocking
     */

    ucr2 |= (UART_UCR2_TXEN | UART_UCR2_RXEN);
    up_serialout(priv, UART_UCR1, ucr2);

    priv->ucr1 |= UART_UCR1_UARTCLEN;
    up_serialout(priv, UART_UCR1, priv->ucr1);
#endif
    return OK;
}