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

📄 lcd.c

📁 蓝牙LCD显示部分的原代码
💻 C
字号:
/*
 * I2C LCD driver.
 *
 * Copyright (C) 2004 Cambridge Silicon Radio Ltd.
 */

#include "lcd.h"

#include <csrtypes.h>
#include <i2c.h>
#if 0
#include <pio.h>
#else
#define PioSet(x,y)
#endif

#include <stdlib.h>

/* Address octet */
#define LCD_ADDR ((0x3c | LCD_SA) << 1)

/* Control octet */
#define LCD_CONTIN 0x80
#define LCD_LAST 0x00
#define LCD_DATA 0x40
#define LCD_COMMAND 0x00

/* H-independent commands */
#define LCD_NOP 0

#define LCD_FUNCTION_SET 0x20
#define LCD_FUNCTION_SET_MX 0x10 /* MX=1 => mirrored X addressing */
#define LCD_FUNCTION_SET_MY 0x08 /* MY=1 => display vertically mirrored */
#define LCD_FUNCTION_SET_PD 0x04 /* PD=1 => power-down mode */

/* H=[0]0 commands */
#define LCD_SET_V_LCD_RANGE 0x04 /* default: voltage base low */
#define LCD_SET_V_LCD_RANGE_PRS 0x01 /* PRS=1 => voltage base high */

#define LCD_DISPLAY_CONTROL 0x08 /* default: blank */
#define LCD_DISPLAY_CONTROL_BLANK 0x00
#define LCD_DISPLAY_CONTROL_NORMAL 0x04
#define LCD_DISPLAY_CONTROL_BLACK 0x01
#define LCD_DISPLAY_CONTROL_INVERSE 0x05

#define LCD_SET_Y 0x40

#define LCD_SET_X 0x80

/* H=[0]1 commands */
#define LCD_DISPLAY_CONFIGURATION 0x08 /* default: MSB on top, no mirroring */
#define LCD_DISPLAY_CONFIGURATION_DO 0x04 /* DO=1 => LSB on top */

#define LCD_BIAS_SYSTEM 0x10 /* very mysterious */

#define LCD_SET_V_OP 0x80 /* V_LCD = ((PRS ? 6.75 : 2.94) + V_OP * 0.03) *
                                           (1 + (T - 27) * TC)               */

/* Controller-dependent stuff */
#if defined LCD_PCF8548_LDA33S481J1D

/* Slave address select */
#define LCD_SA 0

/* H-independent commands */
#define LCD_FUNCTION_SET_V 0x02 /* V=0 => horizontal addressing */
#define LCD_FUNCTION_SET_H0 0x00 /* see below */
#define LCD_FUNCTION_SET_H1 0x01 /* see below */

/* H=0 commands */
#define LCD_SET_HVGEN_STAGES 0x10 /* default: 2 */
#define LCD_SET_HVGEN_STAGES_2 0x00
#define LCD_SET_HVGEN_STAGES_3 0x01
#define LCD_SET_HVGEN_STAGES_4 0x02
#define LCD_SET_HVGEN_STAGES_5 0x03

/* H=1 commands */
#define LCD_TEMPERATURE_CONTROL 0x04 /* default: coefficient 0 */

#define LCD_DISPLAY_CONFIGURATION_TRS 0x02 /* TRS=1 => top rows mirrored */
#define LCD_DISPLAY_CONFIGURATION_BRS 0x01 /* BRS=1 => bottom rows mirrored */

#define LCD_BIAS_SYSTEM_1_64 0x02
#define LCD_BIAS_1_7 0x04

#else
#error Unknown LCD controller/module
#endif

#define LcdTransfer(a) I2cTransfer (LCD_ADDR, (a), sizeof (a), NULL, 0)
#define LcdTransferOK(a) (LcdTransfer (a) == 1 + sizeof (a))

#define I2C_MAX_LEN 64
#if LCD_MAX_LEN > I2C_MAX_LEN
#error LCD_MAX_LEN > I2C_MAX_LEN
#endif

bool LcdClear (void)
{
    static const uint8 zeroes[1 + LCD_WIDTH / 3] = { LCD_DATA | LCD_LAST /* , 0, 0, 0... */ };
    uint16 u;

    /* Need to zap 102 * 9 = 34 * 27 octets */
    for (u = 0; u < LCD_WIDTH * (LCD_HEIGHT + 7) / 8 / (LCD_WIDTH / 3); ++u)
    {
        if (!LcdTransferOK (zeroes)) /* HERE optimise LCD_DATA | LCD_LAST into addr? */
        {
            return FALSE;
        }
    }

    return TRUE;
}

bool LcdInit (void)
{
    static const uint8 init[] = {
        LCD_COMMAND | LCD_LAST,
#if defined LCD_PCF8548_LDA33S481J1D
        LCD_FUNCTION_SET | LCD_FUNCTION_SET_H1 | LCD_FUNCTION_SET_PD,
        LCD_TEMPERATURE_CONTROL | 2, /* as recommended by sample code */
        LCD_BIAS_SYSTEM | LCD_BIAS_1_7, /* works much better than LCD_BIAS_SYSTEM_1_64 as recommended by PCF8548 datasheet -- sample code does this too */
        LCD_SET_V_OP | 25, /* => 7500 mV (when PRS=1 set below, if TC=0 (or 27C!)) -- sample code uses 24 => 7470 mV for some reason */
        LCD_FUNCTION_SET | LCD_FUNCTION_SET_H0 | LCD_FUNCTION_SET_MX, /* set MX otherwise X axis is all screwy -- sample code does this too */
        LCD_SET_V_LCD_RANGE | LCD_SET_V_LCD_RANGE_PRS,
        LCD_SET_HVGEN_STAGES | LCD_SET_HVGEN_STAGES_3, /* otherwise can't get enough juice out -- sample code does this too */
#endif
        LCD_DISPLAY_CONTROL | LCD_DISPLAY_CONTROL_NORMAL
    };

    /* HERE need to optionally do the PIO nRES thing */

    return LcdClear () && LcdTransferOK (init);
}

bool LcdOutput (const uint8 *data, uint16 len, uint16 pos, uint16 line)
{
    uint8 set_xy[3];

    PioSet (1 << 10, 0 << 10);
    PioSet (1 << 10, 1 << 10);
    /*
     * Validate the input arguments.
     */
    if (line >= (LCD_HEIGHT + 7) / 8 || pos >= LCD_WIDTH || len > LCD_WIDTH || pos + len > LCD_WIDTH || data == NULL)
    {
        return FALSE;
    }

    PioSet (1 << 10, 0 << 10);
    PioSet (1 << 10, 1 << 10);
    /*
     * Move to the requested position.
     */
    set_xy[0] = LCD_COMMAND | LCD_LAST;
    set_xy[1] = LCD_SET_X | pos;
    set_xy[2] = LCD_SET_Y | line;
    if (!LcdTransferOK (set_xy))
    {
        return FALSE;
    }

    /*
     * Squirt out the data, in chunks to avoid locking out background too much.
     * Use a sneaky trick: pretend we're using 10-bit addressing
     * so that we can insert the extra control octet (LCD_DATA | LCD_LAST)
     * required after the address and before the RAM data.
     */
    while (len > LCD_MAX_LEN)
    {
        if (I2cTransfer (LCD_ADDR << 8 | LCD_DATA | LCD_LAST, data, LCD_MAX_LEN, NULL, 0) != 2 + LCD_MAX_LEN)
        {
            return FALSE;
        }
        data += LCD_MAX_LEN;
        len -= LCD_MAX_LEN;
    }
    return I2cTransfer (LCD_ADDR << 8 | LCD_DATA | LCD_LAST, data, len, NULL, 0) == 2 + len;
}

⌨️ 快捷键说明

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