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

📄 pc16552d.c

📁 用于TM1300/PNX1300系列DSP(主要用于视频处理)的设备库的源码
💻 C
字号:
/*
 *  +-------------------------------------------------------------------+
 *  | Copyright (c) 1999 by TriMedia Technologies.                      |
 *  |                                                                   |
 *  | This software  is furnished under a license  and may only be used |
 *  | and copied in accordance with the terms  and conditions of such a |
 *  | license  and with  the inclusion of this  copyright notice.  This |
 *  | software or any other copies of this software may not be provided |
 *  | or otherwise  made available  to any other person.  The ownership |
 *  | and title of this software is not transferred.                    |
 *  |                                                                   |
 *  | The information  in this software  is subject  to change  without |
 *  | any  prior notice  and should not be consTrued as a commitment by |
 *  | TriMedia Technologies.                                            |
 *  |                                                                   |
 *  | This  code  and  information  is  provided  "as is"  without  any |
 *  | warranty of any kind,  either expressed or implied, including but |
 *  | not limited  to the implied warranties  of merchantability and/or |
 *  | fitness for any particular purpose.                               |
 *  +-------------------------------------------------------------------+
 *
 *  Module name          : pc16552D.c    1.6
 *
 *  Last update          : 18:43:42 - 00/11/09
 */

#include "pc16552D.h"
#include <tm1/tsaUart.h>
#include <tm1/tmAssert.h>
#include <tmlib/dprintf.h>

#define regTHR		0		/* Transmit Buffer Reg */
#define regRBR		0		/* Receive Buffer Reg */
#define regDLL		0		/* Divisor Latch LSB */
#define regDLM		1		/* Divisor Latch MSB */
#define regIER		1		/* Interrupt Enable Reg */
#define regIIR		2		/* Intr Idetification Reg */
#define regFCR		2		/* Fifo control Reg */
#define regLCR		3		/* Line control Reg */
#define regMCR		4		/* Modem Control Reg */
#define regLSR		5		/* Line Status Reg */
#define regMSR		6		/* Modem Status Reg */
#define regSCR		7		/* Scratch Register. */

#define regMCR_DTR      (1 << 0)
#define regMCR_RTS      (1 << 1)
#define regMCR_LOOP     (1 << 4)

#define regIIR_INT      (1 << 0)
#define regIIR_LSR      (1 << 1 | 1 << 2)
#define regIIR_RD       (1 << 2)
#define regIIR_TIMEOUT  (1 << 2 | 1 << 3)
#define regIIR_TD       (1 << 1)
#define regIIR_MSR       0

#define regMSR_DCTS     (1 << 0)
#define regMSR_DDSR     (1 << 1)
#define regMSR_TERI     (1 << 2)
#define regMSR_DDCD     (1 << 3)
#define regMSR_CTS      (1 << 4)
#define regMSR_DSR      (1 << 5)
#define regMSR_RI       (1 << 6)
#define regMSR_DCD      (1 << 7)

#define regIER_RD       (1 << 0)
#define regIER_TD       (1 << 1)
#define regIER_LSR      (1 << 2)
#define regIER_MSR      (1 << 3)

#define regLSR_RD       (1 << 0)
#define regLSR_OVERRUN  (1 << 1)
#define regLSR_PARITY   (1 << 2)
#define regLSR_FRAMING  (1 << 3)
#define regLSR_BREAK    (1 << 4)
#define regLSR_TD       (1 << 5)

#define regLCR_DATA     (1 << 0 | 1 << 1)
#define regLCR_STOP     (1 << 2)
#define regLCR_PARITY   (1 << 3)
#define regLCR_EVEN     (1 << 4)
#define regLCR_SPACE    (1 << 4)
#define regLCR_STICK    (1 << 5)
#define regLCR_BREAK    (1 << 6)
#define regLCR_DLAB     (1 << 7)

static pc16552DReadRegisterFunc_t  readRegister  = Null;
static pc16552DWriteRegisterFunc_t writeRegister = Null;
static Int                         crystalType;
volatile static UInt8              iirStore      = 0;

static Int baudDivisorTable[3][5] = 
{{
	12,
	6,
	3,
	2,
	0
},
{
	20,
	10,
	5,
    0,
    0
},
{
	120,
	60,
	30,
	21,
	9
}};

static UInt32 pc16552DSupportedBaudRates[3] = 
{
    PC16552D_BAUD_RATES_1_8432,
    PC16552D_BAUD_RATES_3_072,
    PC16552D_BAUD_RATES_18_432
};

/************************************************************************************************/
extern Bool pc16552DPICSourceDetect(UInt32 * source)
{
    UInt8 reg;
    
    reg = readRegister(unit0, regIIR);
    if (!(reg & regIIR_INT))
    {
        iirStore = reg;
        *source  = 0;
        return True;
    }

    reg = readRegister(unit1, regIIR);
    if (!(reg & regIIR_INT))
    {
        iirStore = reg;
        *source  = 1;
        return True;
    }

    return False;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DInit(ppc16552DParams_t params)
{
    tmAssert(params->readRegisterFunc, BOARD_ERR_NULL_FUNCTION);
    tmAssert(params->writeRegisterFunc, BOARD_ERR_NULL_FUNCTION);
    tmAssert(params->crystalType < 3, -1);
    
    readRegister  = params->readRegisterFunc;
    writeRegister = params->writeRegisterFunc;
    crystalType   = params->crystalType;
    
    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DReadData(unitSelect_t portID, Address data)
{
    *data = readRegister(portID, regRBR);

    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DWriteData(unitSelect_t portID, Char data)
{
    writeRegister(portID, regTHR, data);

    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DUartConfig (unitSelect_t portID,
        tsaUartConfig_t command, Pointer value)
{
    UInt8         reg1;
    tmLibdevErr_t err = TMLIBDEV_OK;

    switch (command)
    {
    case UART_DTR_ON:
        reg1 = readRegister(portID, regMCR) | regMCR_DTR;
        writeRegister(portID, regMCR, reg1);
        break;
    case UART_DTR_OFF:
        reg1 = readRegister(portID, regMCR) & ~regMCR_DTR;
        writeRegister(portID, regMCR, reg1);
        break;
    case UART_RTS_ON:
        reg1 = readRegister(portID, regMCR) | regMCR_RTS;
        writeRegister(portID, regMCR, reg1);
        break;
    case UART_RTS_OFF:
        reg1 = readRegister(portID, regMCR) & ~regMCR_RTS;
        writeRegister(portID, regMCR, reg1);
        break;
    case UART_GET_SCRATCH_REGI:
        tmAssert(value, TMLIBDEV_ERR_NULL_PARAMETER);
        *(UInt8*)value = readRegister(portID, regSCR);
        break;
    case UART_SET_SCRATCH_REGI:
        tmAssert(value, TMLIBDEV_ERR_NULL_PARAMETER);
        writeRegister(portID, regSCR, *(UInt8*)value);
        break;
    case UART_SET_LOOP_BACK:
        tmAssert(value, TMLIBDEV_ERR_NULL_PARAMETER);
        reg1 = readRegister(portID, regMCR);
        if (*(Bool *) value)
            reg1 |= regMCR_LOOP;
        else
            reg1 &= ~regMCR_LOOP;
        writeRegister(portID, regMCR, reg1);
        break;
    default:
        return UART_ERR_UNSUPPORTED_CONFIG_COMMAND;
    }

    return err;
}

/************************************************************************************************/
extern Bool pc16552DGetEvent(unitSelect_t portID,
        tsaUartConfigEvent_t *event)
{
    UInt8                reg;
    UInt8                reg2;
    tsaUartConfigEvent_t e;

    if (iirStore == 0)
        reg = readRegister(portID, regIIR) & 0x0f;
    else
    {
        reg      = iirStore;
        iirStore = 0;
    }

    if (reg & regIIR_INT)
    {
        return False;
    }
    
    switch (reg)
    {
    case regIIR_LSR:
        e    = BOARD_UART_ERR_EVENT;
        reg2 = readRegister(portID, regLSR);
        if (reg2 & regLSR_OVERRUN)
            e |= BOARD_UART_RX_ERR_OVERRUN;
        if (reg2 & regLSR_PARITY)
            e |= BOARD_UART_RX_ERR_PARITY;
        if (reg2 & regLSR_FRAMING)
            e |= BOARD_UART_RX_ERR_FRAMING;
        if (reg2 & regLSR_BREAK)
            e |= BOARD_UART_RX_ERR_BREAK;
        break;
    case regIIR_RD:
    case regIIR_TIMEOUT:
        e = BOARD_UART_RX_DATA;
        break;
    case regIIR_TD:
        e = BOARD_UART_TX_COMPLETE;
        break;
    case regIIR_MSR:
        e = BOARD_UART_CONFIG_EVENT;
        reg2 = readRegister(portID, regMSR);
        if (reg2 & regMSR_DCTS)
        {
            if (reg2 & regMSR_CTS)
                e |= UART_CTS_ON;
            else
                e |= UART_CTS_OFF;
        }
        if (reg2 & regMSR_DDSR)
        {
            if (reg2 & regMSR_DSR)
                e |= UART_DSR_ON;
            else
                e |= UART_DSR_OFF;
        }
        if (reg & regMSR_TERI)
            e |= UART_RI_OFF;
        if (reg & regMSR_DDCD)
        {
            if (reg2 & regMSR_DCD)
                e |= UART_DCD_ON;
            else
                e |= UART_DCD_OFF;
        }
        if (reg & regMSR_RI)
            e |= UART_RI_ON;
        break;
    default:
        e = BOARD_UART_ERR_OTHER;
        break;
    }

    *event = e;

    return True;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DInitPort(unitSelect_t portID, pboardUartParam_t params)
{
    tmLibdevErr_t err;

    tmAssert(readRegister, -1);

    err = pc16552DSetBaudRate(portID, params->baudRate);
    if (err)
        return err;

    err = pc16552DSetSerialDataFormat(portID, params->numStopBits, params->numDataBits, params->parity);
    if (err)
        return err;

    err = pc16552DSetTxInt(portID, False);
    if (err)
        return err;

    err = pc16552DSetRxInt(portID, False);
    if (err)
        return err;

    err = pc16552DSetLineStatusInt(portID, False);
    if (err)
        return err;

    err = pc16552DSetModemStatusInt(portID, params->enableControlInt);
    if (err)
        return err;

    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DTermPort(unitSelect_t portID)
{
    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetTxInt(unitSelect_t portID, Bool enable)
{
    Int8 reg;
    
    reg = readRegister(portID, regIER);
    
    if (enable)
        reg |= regIER_TD;
    else
        reg &= ~regIER_TD;

    writeRegister(portID, regIER, reg);

    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetRxInt(unitSelect_t portID, Bool enable)
{
    Int8 reg;
    
    reg = readRegister(portID, regIER);
    
    if (enable)
        reg |= regIER_RD;
    else
        reg &= ~regIER_RD;

    writeRegister(portID, regIER, reg);

    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetLineStatusInt(unitSelect_t portID, Bool enable)
{
    Int8 reg;
    
    reg = readRegister(portID, regIER);
    
    if (enable)
        reg |= regIER_LSR;
    else
        reg &= ~regIER_LSR;

    writeRegister(portID, regIER, reg);

    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetModemStatusInt(unitSelect_t portID, Bool enable)
{
    Int8 reg;
    
    reg = readRegister(portID, regIER);
    
    if (enable)
        reg |= regIER_MSR;
    else
        reg &= ~regIER_MSR;

    writeRegister(portID, regIER, reg);

    return TMLIBDEV_OK;
}

/************************************************************************************************/
tmLibdevErr_t pc16552DSetSerialDataFormat (unitSelect_t portID,
        Int numStopBits, Int numDataBits, tsaUartParity_t parity)
{
    UInt8 reg;

    if (!(numStopBits == 1 || numStopBits == 2))
        return UART_ERR_INVALID_NUM_STOP_BITS;

    if (!(5 <= numDataBits && numDataBits <= 8))
        return UART_ERR_INVALID_NUM_DATA_BITS;

    if (!(parity == UART_PARITY_NONE || parity == UART_PARITY_EVEN ||
            parity == UART_PARITY_ODD || parity == UART_PARITY_MARK ||
            parity == UART_PARITY_SPACE))
        return UART_ERR_INVALID_PARITY;

    reg = readRegister (portID, regLCR);

    reg &= regLCR_DLAB; /*clear everything but DLAB*/

    reg |= numDataBits - 5 & regLCR_DATA;

    if (numStopBits == 2) reg |= regLCR_STOP;

    switch (parity)
    {
        case UART_PARITY_EVEN:
            reg |= regLCR_PARITY | regLCR_EVEN;
        break;

        case UART_PARITY_ODD:
            reg |= regLCR_PARITY;
        break;
        
        case UART_PARITY_MARK:
            reg |= regLCR_PARITY | regLCR_STICK;
        break;
        
        case UART_PARITY_SPACE:
            reg |= regLCR_PARITY | regLCR_STICK | regLCR_SPACE;
        break;
    }

    writeRegister(portID, regLCR, reg);

    return TMLIBDEV_OK;
}

/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetBaudRate(unitSelect_t portID, tsaUartBaud_t baudRate)
{
    UInt8 reg1;
    UInt8 reg2;
    UInt8 reg3;
    Int   i;

    tmAssert(baudRate & pc16552DSupportedBaudRates[crystalType], UART_ERR_INVALID_BAUDRATE);

    /* get index for baudrate table */
    switch(baudRate)
    {
    case UART_BAUD_9600:
        i = 0;
        break;
    case UART_BAUD_19200:
        i = 1;
        break;
    case UART_BAUD_38400:
        i = 2;
        break;
    case UART_BAUD_57600:
        i = 3;
        break;
    case UART_BAUD_115200:
        i = 4;
        break;
    default:
        return UART_ERR_INVALID_BAUDRATE;
    }
    /* Set divisor latch access bit, so that the divisor latch of the baud generator
       can be accessed. */
    reg1 = readRegister(portID, regLCR);
    writeRegister(portID, regLCR, reg1 | regLCR_DLAB);

    reg2 = baudDivisorTable[crystalType][i];
    reg3 = baudDivisorTable[crystalType][i] >> 8;

    writeRegister(portID, regDLL, reg2);
    writeRegister(portID, regDLM, reg3);
    
    /* reset divisor latch access bit */
    writeRegister(portID, regLCR, reg1 & ~regLCR_DLAB);

    return TMLIBDEV_OK;
}

⌨️ 快捷键说明

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