📄 usbirqfunc.c
字号:
//-----------------------------------------------------------------------------
// File: UsbIrqFunc.c
// Contents: Process IRQ-control commands received from the USB host.
// Both internal IRQ (LV24xxx interrupt - script) and external interrupt
// (external RDS demodulator) are handled in thid file
//
// Copyright (c) 2004 ItoM Semiconductor. All rights reserved
//-----------------------------------------------------------------------------
#include <stdio.h>
#include "common.h"
#include "Lv24Ekit.h"
#ifdef USE_USB
#include "Usb3wCmd.h"
#endif //USB_USB
// ==============================================================================
#ifdef USE_IRQSCRIPT // The whole file can be discarded if interrupt is not used
// ==============================================================================
//////////////////////////////////////////////////////////////////////
// IRQ-script opcode
//////////////////////////////////////////////////////////////////////
#define ISO_IRQID 0x01 // Assign handler ID. Syntax: Opcode, byIrqId, byReserved
#define ISO_WRITE3W_D 0x02 // Write 3W direct. Syntax: Opcode, byAddress, byData (byData is immediate data)
#define ISO_WRITE3W_I 0x03 // Write 3W indirect. Syntax: Opcode, byAddress, byStorage
#define ISO_READ3W 0x04 // Read 3W. Syntax: Opcode, byAddress, byStorage
#define ISO_CHKMASK_L 0x05 // Check mask, true if low. Syntax: Opcode, byStorage, byMask
#define ISO_CHKMASK_H 0x06 // Check mask, true if set. Syntax: Opcode, byStorage, byMask
#define ISO_OR_MASK 0x07 // OR storage with mask. Syntax: Opcode, byStorage, byOrMask
#define ISO_AND_MASK 0x08 // AND storage with mask. Syntax: Opcode, byStorage, byAndMask
#define ISO_STORE_BUF 0x09 // Store register to buffer.Syntax: Opcode, byAddress, byBufId
#define ISO_READ3W_D 0x0A // Read 3W direct Syntax: Opcode, byAddress, byIndexInDirectBuffer
#define ISO_POLL_H 0x0B // Wait until bit(s) high Syntax: Opcode, byAddress, byBitMask
#define ISO_POLL_L 0x0C // Wait until bit(s) low Syntax: Opcode, byAddress, byBitMask
#define ISO_ENDSCRIPT 0xFF // End of script Syntax: Opcode, byReserved, byReserved
#define ISPARM_NA 0x00 // Not used parameter
// Special storage location in device interrupt buffer 0
#define ISWR_IRQOCC0 0 // Byte 0 of buffer 0 is meant for interrupt [0:7] occurred marks
#define ISWR_IRQOCC1 1 // Byte 1 of buffer 0 is meant for interrupt [8:15] occurred marks
// Script process status
#define SCRIPT_OK 0
#define SCRIPT_END 1
#define SCRIPT_CHK_FAIL 2
#define SCRIPT_ERROR 0xFF
// Subroutines
BYTE CopyRoundRobinBuf(PRNDBUF_ST pStRrBuf);
// Prototypes for USB-IRQ script handlers
BYTE ScNOP( BYTE byParm1, BYTE byParm2 );
BYTE ScIrqID( BYTE byParm1, BYTE byParm2 );
BYTE ScWrite3WD( BYTE byParm1, BYTE byParm2 );
BYTE ScWrite3WI( BYTE byParm1, BYTE byParm2 );
BYTE ScRead3W( BYTE byParm1, BYTE byParm2 );
BYTE ScChkMaskLow( BYTE byParm1, BYTE byParm2 );
BYTE ScChkMaskHigh( BYTE byParm1, BYTE byParm2 );
BYTE ScOrMask( BYTE byParm1, BYTE byParm2 );
BYTE ScAndMask( BYTE byParm1, BYTE byParm2 );
BYTE ScStoreBuf( BYTE byParm1, BYTE byParm2 );
BYTE ScRead3WD(BYTE byParm1, BYTE byParm2);
BYTE ScPollHi(BYTE byParm1, BYTE byParm2);
BYTE ScPollLo(BYTE byParm1, BYTE byParm2);
typedef BYTE (*SCRIPT_COMMAND_FUNC)(BYTE,BYTE); // Script op-code execution-function
static SCRIPT_COMMAND_FUNC ScriptCommandTable[] =
{
ScNOP, // Opcode 0
ScIrqID, // Opcode 1
ScWrite3WD, // Opcode 2
ScWrite3WI, // Opcode 3
ScRead3W, // Opcode 4
ScChkMaskLow, // Opcode 5
ScChkMaskHigh, // Opcode 6
ScOrMask, // Opcode 7
ScAndMask, // Opcode 8
ScStoreBuf, // Opcode 9
ScRead3WD, // opcode 10
ScPollHi, // opcode 11
ScPollLo, // opcode 12
};
#define SCRIPT_COMMAND_FUNC_MAX (sizeof(ScriptCommandTable)/(sizeof(ScriptCommandTable[0])-1))
BYTE UsbIrqControl()
{
// Interrupt comtrol from USB
// General input buffer format: <Command><Action><optional parameters><...>
BYTE byLen, byTmp;
WORD wLen;
byLen = 0; // Default length to be returned
switch (g_ReceiveBuf[1]) // Examine the action byte for handling the command
{
// ---- Interface IRQ handling ------
case RCA_INFIRQ_ENABLE: // Reset our administration and enable the external RDS-interrupt
g_stExtIrq.byW = 0; // Reset the write pointer
g_stExtIrq.byR = 0; // Reset the read pointer
g_stExtIrq.byF = 0; // Reset the filled count
g_byRdsBitCnt = 0; // Reset the received RDS bit counter
// fall through to enable the external interrupt
case RCA_INFIRQ_RESUME: // Just enable the external RDS-interrupt
byTmp = _I45CR;
byTmp &= 0xF0; // Don't touch INT5 setting, clear INT4 setting (disable INT4)
byTmp |= 0x09; // Don't touch INT5 setting, enable INT4 - rising edge trigger
_I45CR = byTmp;
break;
case RCA_INFIRQ_SUSPEND: // Just disable the external RDS-interrupt
case RCA_INFIRQ_DISABLE: // Disable the external RDS-interrupt
byTmp = _I45CR;
byTmp &= 0xF0; // Don't touch INT5 setting, clear INT4 setting (disable INT4)
_I45CR = byTmp;
break;
case RCA_INFIRQ_GETDATA: // Return our RDS-data
// Received format <RC_IRQ_CONTROL_CMD><GetData-action><BufId>
// Reply format <Cmd><ByteCnt=n><byte0><byte1><...><byte n>
// For interface interrupt - we don't care about the buffer ID, just send the only buffer back
byLen = CopyRoundRobinBuf(&g_stExtIrq);
break;
// ---- End Interface IRQ handling ------
// ---- Device IRQ handling ------
case RCA_DEVIRQ_ENABLE: // Enable device IRQ // No reply
// Reset data available flag of buffer 0
g_byaIrqBuf0[ISWR_IRQOCC0] = 0;
g_byaIrqBuf0[ISWR_IRQOCC1] = 0;
// Fall through
case RCA_DEVIRQ_RESUME: // Resume device IRQ // No reply
// Reset the administration for buffer 1 (Device RDS buffer)
g_stIrqBuf1.byW = 0; // The write pointer
g_stIrqBuf1.byR = 0; // The read pointer
g_stIrqBuf1.byF = 0; // The byte filled count
Enable3wIrq(TRUE);
g_ReplyBuf[1] = 0; // No error
break;
case RCA_DEVIRQ_DISABLE: // Disable device IRQ // No reply
case RCA_DEVIRQ_SUSPEND: // Suspend device IRQ // No reply
Enable3wIrq(FALSE);
g_ReplyBuf[1] = 0; // No error
break;
case RCA_DEVIRQ_GETDATA: // Get device IRQ data
// Received format <RC_IRQ_CONTROL_CMD><GetData-action><BufId>
// Reply format <Cmd><ByteCnt=n><byte0><byte1><...><byte n>
// Return the requested buffer (specified by buffer ID)
if (g_ReceiveBuf[2]==0) // Buffer 0 requested
{
if (g_byaIrqBuf0[ISWR_IRQOCC0] || g_byaIrqBuf0[ISWR_IRQOCC1] ) // Does interrupt occur?
{
// Copy the buffer 0 to reply packet
g_ReplyBuf[1] = MAXLEN_IRQBUF_0; // Number of IRQ data byte
for (byTmp=0; byTmp<MAXLEN_IRQBUF_0; byTmp++)
g_ReplyBuf[2+byTmp] = g_byaIrqBuf0[byTmp];
byLen = MAXLEN_IRQBUF_0 + 2; // Total byte of the USB-reply packet
// Clear data available flag
g_byaIrqBuf0[ISWR_IRQOCC0] = 0;
g_byaIrqBuf0[ISWR_IRQOCC1] = 0;
}
}
else if (g_ReceiveBuf[2]==1) // Buffer 1 requested
{
byLen = CopyRoundRobinBuf(&g_stIrqBuf1);
}
if (byLen==0) // Not suported buffer ID or no data
{
g_ReplyBuf[1]=0; // 0 byte filled
byLen = 2;
}
break;
case RCA_DEVIRQ_INSTALL: // Install interrupt handler script // See below
// We received the script in small packets in following format
// ReceiveBuf[0] = RC_IRQ_CONTROL_CMD - command
// ReceiveBuf[1] = RCA_DEVIRQ_INSTALL - sub command
// ReceiveBuf[2] = Low byte of the script's length
// ReceiveBuf[3] = High byte of the script's length
// ReceiveBuf[4] = low byte of current offset
// ReceiveBuf[5] = High byte of current offset
// ReceiveBuf[6] = Number of byte in this packet
// We reply in format:
// ReplyBuf[0] = RC_IRQ_CONTROL_CMD - command
// ReplyBuf[1] = RCA_DEVIRQ_INSTALL - sub command
// ReplyBuf[2] = Low byte of the script's length
// ReplyBuf[3] = High byte of the script's length
// ReplyBuf[4] = low byte of current offset
// ReplyBuf[5] = High byte of current offset
// ReplyBuf[6] = Number of byte received in this packet
// ReplyBuf[7] = Error code (0=no error)
{
WORD wCur;
// Prepare the reply buffer
for (byTmp=0; byTmp<7; byTmp++)
g_ReplyBuf[byTmp] = g_ReceiveBuf[byTmp];
g_ReplyBuf[7] = 0; // No error yet
// Determine length of the script
wLen = MAKEWORD(g_ReceiveBuf[2], g_ReceiveBuf[3]); // Script's length
if (wLen > MAX_IRQSCRIPT_LEN)
{
g_ReplyBuf[7] = 1; // Script length error
g_ReplyBuf[8] = LSB(MAX_IRQSCRIPT_LEN); // Return the max. size as extra info
g_ReplyBuf[9] = MSB(MAX_IRQSCRIPT_LEN);
byLen = 10; // Number of byte to be returned
}
else
{
// Determine current offset in the script
wCur = MAKEWORD(g_ReceiveBuf[4], g_ReceiveBuf[5]);
// Copy the script portion
for (byTmp=7; byTmp<g_ReceiveBuf[6]+7; byTmp++)
{
g_byaIrqScript[wCur] = g_ReceiveBuf[byTmp];
wCur++;
}
// Mark script is installed when we have enough bytes
if (wCur==wLen)
g_byLvIrqFlg |= IFL_USBIRQ_INSTALLED;
byLen = 8; // Number of byte to be returned
}
}
break;
case RCA_DEVIRQ_REMOVE: // Remove interrupt handler script // No reply
g_byLvIrqFlg &= (~IFL_USBIRQ_INSTALLED);
break;
//case RCA_DEVIRQ_SETCB: // Set callback // NA: for USB-uC
case RCA_DEVIRQ_SETBUF: // Set IRQ data buffer
// We receive the buffer info to USB-uC following format
// ReceiveBuf[0] = RC_IRQ_CONTROL_CMD - command
// ReceiveBuf[1] = RCA_DEVIRQ_SETBUF - sub command
// ReceiveBuf[2] = Buffer ID
// ReceiveBuf[3] = low byte of buffer size
// ReceiveBuf[4] = High byte of buffer size
// We reply in format:
// ReplyBuf[0] = RC_IRQ_CONTROL_CMD - command
// ReplyBuf[1] = RCA_DEVIRQ_SETBUF - sub command
// ReplyBuf[2] = Buffer ID
// ReplyBuf[3] = low byte of buffer size
// ReplyBuf[4] = High byte of buffer size
// ReplyBuf[5] = Error code (0=no error)
// Prepare the reply buffer
for (byTmp=0; byTmp<5; byTmp++)
g_ReplyBuf[byTmp] = g_ReceiveBuf[byTmp];
g_ReplyBuf[5] = 0; // No error yet
wLen = MAKEWORD(g_ReceiveBuf[3], g_ReceiveBuf[4]); // Requested buffer's length
// Check buffer ID, we only support buffer 0 and 1
if (g_ReceiveBuf[2] == 0) // Buffer 0 requested
{
if (wLen > MAXLEN_IRQBUF_0)
{
g_ReplyBuf[5] = 1; // Buffer length error
}
}
else if (g_ReceiveBuf[2] == 1) // Buffer 1 requested
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -