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

📄 dismgr.c

📁 蓝牙LCD显示部分的原代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Display manager.
 *
 * This is a beta implementation of VYn_wbu3836 v1.0.
 *
 * Copyright (C) 2004-2005 Cambridge Silicon Radio Ltd.
 */

/*#define NOBF*/
#include "dismgr.h"

#include "lcd.h"
#include <font.h>

#if 0
#include <pio.h>
#else
#define PioSetDir(x,y)
#define PioSet(x,y)
#endif
#include <util.h>
#include <message.h>
#include <vm.h>
#include <panic.h>

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define ASSERT assert

#if LCD_WIDTH <= LCD_COLUMN_LEFT + DISMGR_MAX_COLUMN
#error Display too wide for LCD
#endif
#if LCD_HEIGHT <= 15
#error Display too tall for LCD
#endif

static struct DISMGR_STATE {
    TaskData task;
    /*
     * The prompt to display, its length, the current index within it,
     * its bounds, and its framebuffer.
     */
    const uint16 *prompt;
#ifdef NOBF
    unsigned int prompt_len;
    unsigned int prompt_index;
    unsigned int prompt_first;
    unsigned int prompt_wid;
    unsigned int left_to_right; /* see below */
#else
#   define DISMGR_BITS_PROMPT_LEN 8
    unsigned int prompt_len : DISMGR_BITS_PROMPT_LEN;
    unsigned int prompt_index : DISMGR_BITS_PROMPT_LEN;
#   define DISMGR_BITS_PROMPT_POS 7
    unsigned int prompt_first : DISMGR_BITS_PROMPT_POS;
    unsigned int prompt_wid : DISMGR_BITS_PROMPT_POS;
#   if DISMGR_MAX_COLUMN >= (1 << DISMGR_BITS_PROMPT_POS)
#   error "prompt_first and prompt_last bitfields too small"
#   endif
    unsigned int left_to_right : 1; /* see below */
    /* 1 spare bit */
#endif
    uint16 *framebuf; /* one word per column; NULL iff not scrolling */
    /*
     * The glyph currently being rendered, its width, and the current
     * index within it.
     */
#ifdef NOBF
    uint16 glyph[DISMGR_MAX_GLYPH_WID];
    unsigned int glyph_wid;
    unsigned int glyph_index;
    unsigned int incrementing;
    unsigned int next_thing;
#   define DISMGR_NEXT_THING_STOP_NOW 0
#   define DISMGR_NEXT_THING_STOP 1
#   define DISMGR_NEXT_THING_CHANGE_DIR_THEN_STOP 2
#   define DISMGR_NEXT_THING_CHANGE_DIR 3
#   define DISMGR_NEXT_THING_CONTINUE 4
    unsigned int font;
    unsigned int prompt_font;
#else
#   define DISMGR_BITS_GLYPH_WID 4
    uint16 glyph[DISMGR_MAX_GLYPH_WID];
    unsigned int glyph_wid : DISMGR_BITS_GLYPH_WID;
    unsigned int glyph_index : DISMGR_BITS_GLYPH_WID;
#   if DISMGR_MAX_GLYPH_WID >= (1 << DISMGR_BITS_GLYPH_WID)
#   error "glyph_wid and glyph_index bitfields too small"
#   endif
    /*
     * The scroll state consists of four elements:
     * - which way we're indexing the prompt
     * - which way we started indexing the prompt (variable moved above)
     * - what we should do at the end of the current scroll
     * - whether we need to delay the next step (variable moved below)
     */
    unsigned int incrementing : 1;
    unsigned int next_thing : 3;
#   define DISMGR_NEXT_THING_STOP_NOW 0
#   define DISMGR_NEXT_THING_STOP 1
#   define DISMGR_NEXT_THING_CHANGE_DIR_THEN_STOP 2
#   define DISMGR_NEXT_THING_CHANGE_DIR 3
#   define DISMGR_NEXT_THING_CONTINUE 4
    /*
     * The font selected, and the font currently in use.
     */
#   define DISMGR_BITS_FONT 2
    unsigned int font : DISMGR_BITS_FONT;
    unsigned int prompt_font : DISMGR_BITS_FONT;
    /* 0 spare bits */
    unsigned int delay;
#endif
} dismgr_state;

/*
 * Like FontGetGlyph() but on failure try various other options
 * in increasing order of desperation.
 * If FONT_REPLACEMENT_CHARACTER is #defined then panics on failure,
 * else returns (size_t) -1 on failure.
 */
static size_t FontGetGlyphAny (FontId font, ucs2char c, uint16 *glyph, size_t max_glyph_wid)
{
    size_t wid;

    wid = FontGetGlyph (font, c, glyph, max_glyph_wid);
    if (wid != (size_t) -1)
    {
        return wid;
    }
    wid = FontGetGlyph (0, c, glyph, max_glyph_wid);
    if (wid != (size_t) -1)
    {
        return wid;
    }
#ifdef FONT_REPLACEMENT_CHARACTER
    wid = FontGetGlyph (font, FONT_REPLACEMENT_CHARACTER, glyph, max_glyph_wid);
    if (wid != (size_t) -1)
    {
        return wid;
    }
    wid = FontGetGlyph (0, FONT_REPLACEMENT_CHARACTER, glyph, max_glyph_wid);
    if (wid != (size_t) -1)
    {
        return wid;
    }
    Panic ();
#endif
    return (size_t) -1;
}

/*
 * Render the whole buffer.
 * Returns TRUE iff entire prompt fits.
 * If not_really then only render the last logical column.
 * If dots then add (up to) three dots at the end (even if not_really),
 * starting on a glyph boundary.
 * If the entire prompt fits or dots were added then the final
 * dismgr_state is indeterminate and should not be reused.
 */
static bool DismgrRenderFramebuffer (bool not_really, bool dots)
{
    uint8 prompt_pos;
    uint16 dots_width = 0;
    uint8 prompt_wid = dismgr_state.prompt_wid;
    size_t glyph_wid, glyph_index;
    bool incrementing = dismgr_state.incrementing;

    if (dots)
    {
        glyph_wid = FontGetGlyphAny (dismgr_state.prompt_font, '.', NULL, 0);
        if (glyph_wid != (size_t) -1)
        {
            dots_width = 3 * glyph_wid;
        }
#ifndef FONT_REPLACEMENT_CHARACTER
        else
        {
            /* No dot glyph, no dots! */
            dots = FALSE;
            dots_width = 0;
        }
#endif
    }

    prompt_pos = 0;
    for (dismgr_state.prompt_index = 0;
         dismgr_state.prompt_index < dismgr_state.prompt_len;
         ++dismgr_state.prompt_index)
    {
        glyph_wid = FontGetGlyphAny (dismgr_state.prompt_font,
            dismgr_state.prompt[incrementing ?
                dismgr_state.prompt_index :
                dismgr_state.prompt_len - dismgr_state.prompt_index - 1],
            dismgr_state.glyph, sizeof (dismgr_state.glyph));
        /*
         * The glyph must exist if we get here (otherwise we'd either
         * have rejected the prompt in DismgrDisplayPrompt() or panicked
         * in the FontGetGlyphAny() above).
         */
        if (prompt_pos + glyph_wid + dots_width <= prompt_wid)
        {
            /*
             * Glyph fits entirely -- copy over.
             */
            if (!not_really)
            {
                memcpy (&dismgr_state.framebuf[incrementing ?
                            prompt_pos : prompt_wid - glyph_wid - prompt_pos],
                        dismgr_state.glyph, glyph_wid);
            }
            prompt_pos += glyph_wid;
            continue;
        }
        else if (dots)
        {
            /*
             * Glyph does not fit -- add three dots and padding.
             * Could in principle use 0x2026 HORIZONTAL ELLIPSIS
             * but this might (a) not be present and (b) be more directional.
             */
            uint8 ndots;

            glyph_wid = FontGetGlyphAny (dismgr_state.prompt_font, '.', dismgr_state.glyph, sizeof (dismgr_state.glyph));
            for (ndots = 0; ndots < 3; ++ndots)
            {
                if (prompt_pos + glyph_wid > prompt_wid)
                {
                    /*
                     * Dot glyph does not fit -- copy over the part that fits.
                     */
                    glyph_index = prompt_wid - prompt_pos;
                    if (incrementing)
                    {
                        memcpy (&dismgr_state.framebuf[prompt_pos],
                                dismgr_state.glyph,
                                glyph_index);
                    }
                    else
                    {
                        memcpy (dismgr_state.framebuf,
                                &dismgr_state.glyph[glyph_wid - glyph_index],
                                glyph_index);
                    }
                    return FALSE;
                }
                /*
                 * Dot glyph fits entirely -- copy over.
                 */
                memcpy (&dismgr_state.framebuf[incrementing ?
                            prompt_pos : prompt_wid - glyph_wid - prompt_pos],
                        dismgr_state.glyph,
                        glyph_wid);
                prompt_pos += glyph_wid;
            }
            /*
             * Pad out.
             */
            memset (&dismgr_state.framebuf[incrementing ? prompt_pos : 0],
                    0, prompt_wid - prompt_pos);
            return FALSE;
        }
        /*
         * Glyph does not fit -- copy over the part that fits.
         */
        dismgr_state.glyph_index = glyph_index = prompt_wid - prompt_pos;
        dismgr_state.glyph_wid = glyph_wid;
        if (incrementing)
        {
            memcpy (&dismgr_state.framebuf[prompt_pos],
                    dismgr_state.glyph, glyph_index);
        }
        else
        {
            memcpy (dismgr_state.framebuf,
                    &dismgr_state.glyph[glyph_wid - glyph_index], glyph_index);
        }
        return FALSE;
    }

    /*
     * Prompt fits -- pad out.
     */
    memset (&dismgr_state.framebuf[incrementing ? prompt_pos : 0],
            0, prompt_wid - prompt_pos);

    return TRUE;
}

/*
 * Output the prompt.
 */
static bool DismgrOutputPrompt (void)
{
    bool ok;

    if (!LcdOutput ((const uint8 *) dismgr_state.framebuf,
                    dismgr_state.prompt_wid,
                    LCD_COLUMN_LEFT + dismgr_state.prompt_first,
                    LCD_LINE_BOTTOM))
    {
        /* Try to maintain display integrity -- abort on failure */
        return FALSE;
    }

    ok = TRUE;
    UtilSwap (dismgr_state.framebuf, dismgr_state.prompt_wid);
    if (!LcdOutput ((const uint8 *) dismgr_state.framebuf,
                    dismgr_state.prompt_wid,
                    LCD_COLUMN_LEFT + dismgr_state.prompt_first,
                    LCD_LINE_TOP))
    {
        /* ... of course, this won't work if the second output fails */
        ok = FALSE;
    }
    UtilSwap (dismgr_state.framebuf, dismgr_state.prompt_wid);

    return ok;
}

/*
 * Scroll by one.
 */
static void DismgrScroll (Task task, MessageId id, Message message)
{
#ifndef DISMGR_SCROLL_SIZE
#define DISMGR_SCROLL_SIZE 1
#endif
    uint32 t = VmGetClock ();
#if DISMGR_SCROLL_SIZE > 1
    /*
     * SCROLLING BY MORE THAN ONE PIXEL PER STEP IS NOT FORMALLY SUPPORTED.
     * THE CORRESPONDING CODE IS A PROTOTYPE WHICH IS KNOWN TO BE INCOMPLETE
     * AND MAY NOT BE MAINTAINED.
     */
    uint16 step;
#else
    uint8 prompt_wid_minus_one = dismgr_state.prompt_wid - 1;
#endif
    uint16 glyph_column;

    /*
     * Update the LCD.
     * Do this first so that the LCD is updated as regularly as possible,
     * however long the scrolling takes to perform.
     */
/*
BP
    PioSet (1 << 10, 1 << 10);
    DismgrOutputPrompt ();
    PioSet (1 << 10, 0 << 10);
    */
        PioSet (1 << 8, 1 << 8);
    DismgrOutputPrompt ();
    PioSet (1 << 8, 0 << 8);

    /*
     * Are we just to delay a bit?
     */
    if (dismgr_state.delay)
    {
        if (dismgr_state.next_thing == DISMGR_NEXT_THING_STOP_NOW)
        {
            /* Add the dots and render from the other end */
            dismgr_state.incrementing = dismgr_state.left_to_right;
            DismgrRenderFramebuffer (FALSE, TRUE);
        }
        MessageSendLater (&dismgr_state.task, 0, NULL, dismgr_state.delay);
        dismgr_state.delay = 0;
        return;
    }

    /*
     * Stop if we've reached the end.
     */
    if (dismgr_state.next_thing == DISMGR_NEXT_THING_STOP_NOW)
    {
        free (dismgr_state.framebuf);
        dismgr_state.framebuf = NULL;
        return;
    }

    /*
     * Shift and insert the next glyph column.
     */
  
    /*
BP
    PioSet (1 << 10, 1 << 10);
    
    */
    PioSet (1 << 8, 1 << 8);
    
#if DISMGR_SCROLL_SIZE > 1
    if (dismgr_state.incrementing)
    {
        memmove (dismgr_state.framebuf,
                 dismgr_state.framebuf + DISMGR_SCROLL_SIZE,
                 dismgr_state.prompt_wid - DISMGR_SCROLL_SIZE);
    }
    else
    {
        memmove (dismgr_state.framebuf + DISMGR_SCROLL_SIZE,
                 dismgr_state.framebuf,
                 dismgr_state.prompt_wid - DISMGR_SCROLL_SIZE);
    }
    for (step = 0; step < DISMGR_SCROLL_SIZE; ++step)
    {
        if (dismgr_state.incrementing)
        {
            glyph_column = dismgr_state.glyph[dismgr_state.glyph_index++];
            dismgr_state.framebuf[dismgr_state.prompt_wid - DISMGR_SCROLL_SIZE + step] = glyph_column;
        }
        else
        {
            glyph_column = dismgr_state.glyph[dismgr_state.glyph_wid - dismgr_state.glyph_index++ - 1];
            dismgr_state.framebuf[DISMGR_SCROLL_SIZE - step - 1] = glyph_column;
        }
#else
    if (dismgr_state.incrementing)
    {

⌨️ 快捷键说明

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