📄 periph.c
字号:
#pragma NOIV // Do not generate interrupt vectors
//-----------------------------------------------------------------------------
// File: periph.c
// Contents: Hooks required to implement USB peripheral function.
//
// Copyright (c) 2001 Cypress Semiconductor All rights reserved
//-----------------------------------------------------------------------------
#include "ezusb.h"
#include "ezregs.h"
#include "Fx.h"
#include "intrins.h"
extern BOOL GotSUD; // Received setup data flag
extern BOOL Sleep;
extern BOOL Rwuen;
extern BOOL Selfpwr;
BYTE Configuration; // Current configuration
BYTE AlternateSetting; // Alternate settings
void TD_Poll( void );
// 0xFFFF - 0x9C40 = 0x63BF (don't forget it's an upcounter, rollover at 0xFFFF
#define T2AUTOH 0x63 // so, 10msec/250nsec = 40,000 tic's
#define T2AUTOL 0xBF // 40,000 tic's = 0x9C40 for auto-reload value
// TODO: check to see that this matrix maps properly to your connections...
// ...firmware is flexible, <smile>...
const BYTE code kpd_mat[ 4 ][ 4 ] =
{ // ...standard 4x4 keypad matrix...
{'A', '3', '2', '1'}, // alt: {'D', 'C', 'B', 'A'}, etc...
{'B', '6', '5', '4'}, // {'#', '9', '6', '3'},
{'C', '9', '8', '7'}, // {'0', '8', '5', '2'},
{'D', '#', '0', '*'} // {'*', '7', '4', '1'}
};
// Rev. D FX DK board, addr decode (movx reads only) via CPLD
xdata volatile const unsigned char LED0_ON _at_ 0x8000;
xdata volatile const unsigned char LED0_OFF _at_ 0x8100;
xdata volatile const unsigned char LED1_ON _at_ 0x9000;
xdata volatile const unsigned char LED1_OFF _at_ 0x9100;
xdata volatile const unsigned char LED2_ON _at_ 0xA000;
xdata volatile const unsigned char LED2_OFF _at_ 0xA100;
xdata volatile const unsigned char LED3_ON _at_ 0xB000;
xdata volatile const unsigned char LED3_OFF _at_ 0xB100;
// it may be worth noting that by default the Keil mon-51
// ...utility loads at 0xE000 and above
// use this global (periph.c) variable when (de)asserting debug LEDs...
BYTE ledX_rdvar = 0x00;
#define NOKEY 0xFF
#define DEQUEUE 0x00
#define ENQUEUE 0x01
#define BYTECNT 0x02
#define FLUSHDQ 0x03
#define AOKAY 0
#define ERROR 1
// ...only kpd_mat[][] char(s) are valid as data to enqueue/dequeue...
BYTE queue( BYTE qflg, BYTE qkey )
{ // ...this is a simple queue...
static BYTE kqueue[ 4 ]; // circular buffer
static BYTE qtail = 0x00; // enqueued keys here
static BYTE qhead = 0x00; // dequeued keys here
static BYTE qbc = 0x00; // number of keys in queue
switch( qflg )
{
case DEQUEUE:
{ // ...dequeue user entry
if( qbc )
{ // there are keys in the queue...notify user - "not full"...
ledX_rdvar = LED1_OFF;
qbc--;
if( qbc )
{ // notify user - "not empty"...
ledX_rdvar = LED0_ON;
}
else
{ // notify user - "empty"
ledX_rdvar = LED0_OFF;
}
qhead = ( qhead + 1 ) % sizeof( kqueue );
return( kqueue[ qhead ] );
}
else
{ // notify user - "empty"
ledX_rdvar = LED0_OFF;
return( NOKEY );
}
break;
}
case ENQUEUE:
{ // ...enqueue user entry
if( qbc < sizeof( kqueue ) )
{ // notify user - "not empty"...
ledX_rdvar = LED0_ON;
qbc++;
if( qbc == sizeof( kqueue ) )
{ // notify user - "full"...
ledX_rdvar = LED1_ON;
}
else
{ // notify user - "not full"...
ledX_rdvar = LED1_OFF;
}
qtail = ( qtail + 1 ) % sizeof( kqueue );
kqueue[ qtail ] = qkey;
return( AOKAY );
}
else
{ // notify user - "full"...
ledX_rdvar = LED1_ON;
return( ERROR );
}
break;
}
case BYTECNT:
{ // ...return current byte count
return( qbc );
}
case FLUSHDQ:
{ // ...flush queue
qbc = qtail = qhead = 0x00;
ledX_rdvar = LED1_OFF; // notify user, "not full"
ledX_rdvar = LED0_OFF; // notify user, "empty"
return( AOKAY );
}
default :
{
return( ERROR );
}
} // ...end "switch"
return( ERROR );
}
// 4x4 kpd lines tied to PORTD
// ...PD[7:4] are output col(s)
// ...PD[3:0] are input row(s) - need pull-ups
void getkey( void )
{ // this is a simple 4x4 keypad scan routine, stuffs entry into queue...
static BYTE lastkey = 0xFF;
static BYTE thiskey = 0xFF;
static BYTE cas = 0x7F; // col assert
static BOOL qd = 0;
BYTE icol = 0x00; // represents PD[7:4], outputs
BYTE zbit = 0x00;
BYTE zrow = 0x00; // represents PD[3:0], inputs
BYTE drow = 0x00;
if( TR2 )
{ // ...still processing software debounce
return; // ...continue to TD_Poll( );
}
thiskey = 0xFF;
OUTD = cas = 0x7F; // "prime-the-pump", assert col - PD7
zrow = drow = 0x00;
for( icol = 0; icol < 4; icol++ )
{
_nop_( ); // wait, 83nsec
_nop_( ); // wait, 167nsec
_nop_( ); // wait, 250nsec
_nop_( ); // wait, 333nsec
_nop_( ); // wait, 416nsec
_nop_( ); // wait, 499nsec
_nop_( ); // wait,
_nop_( ); // wait,
_nop_( ); // wait,
_nop_( ); // wait,
_nop_( ); // wait,
_nop_( ); // wait, 1usec
drow = ( PINSD & 0x0F );
if( drow != 0x0F )
{ // ...one of the rows detected lo
zbit = ( drow | 0xF0 ); // snap shot of row(s)
while( zbit & 1 )
{ // search through, find which row is lo
zbit >>= 1;
zrow++; // used in array lookup below
if( zrow > 3 )
{ // test for overflow
break; // ...out of while loop
}
}
// ...found match, do lookup
thiskey = kpd_mat[ zrow ][ icol ];
break; // ...out of for loop
}
else
{
}
// ...try next col...
cas = _cror_( cas, 1 );
OUTD = cas; // 0111 1111 - assert col PD7
// 1011 1111 - assert col PD6
// 1101 1111 - assert col PD5
// 1110 1111 - assert col PD4
}
OUTD = 0xF0;
if( thiskey != 0xFF )
{ // ...potential key pressed
ledX_rdvar = LED3_ON; // ...is "ON" while key is being held
if( thiskey == lastkey )
{ // ...debounce passed, valid entry
if( !qd )
{ // ...put key into queue
lastkey = 0xFF;
queue( ENQUEUE, thiskey );
qd = 1;
}
else
{ // ...
}
}
else
{ // ...new input detected first go 'round
lastkey = thiskey; // ...save entry
}
TR2 = 1; // ...start timer2(T2CON.2=1)
}
else
{ // ...
ledX_rdvar = LED3_OFF; // ...lastkey depressed
qd = 0;
}
}
//-----------------------------------------------------------------------------
// Task Dispatcher hooks
// The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------
void TD_Init( void )
{ // Called once at startup
CPUCS &= 0xFD; // don't drive CLKOUT (CLKOE=0)
IFCONFIG = 0x00; // ports mode
OED = 0xF0; // setup PD[7:4] as outputs, PD[3:0] as inputs
IN07VAL = 0x04; // enable endp 2 IN
OUT07VAL = 0x04; // enable endp 2 OUT
USBPAIR = 0x09; // enable 2x buffering on both endp's
BPADDR = ( WORD )TD_Poll; // set breakpoint to trigger on TD_Poll()
USBBAV |= 0x02; // BPEN=1, enable breakpoint feature
USBBAV &= 0xFB; // BPPULSE=0, disable breakpoint pulse mode
Rwuen = TRUE; // enable remote-wakeup
// using on-chip 16-bit timer2 with auto-reload feature at 10msec tic's...
// Timer2 runs only in 16-bit mode
// we'll want to use 16-bit auto-reload timer feature
CKCON &= 0xDF; // bit5 controls the base unit timer clock rate for Timer2
// bit5=0, Timer2 uses CLK24/12 (used in this example)
// bit5=1, Timer2 uses CLK24/4
RCAP2H = TH2 = T2AUTOH; // see top of this file for #define
RCAP2L = TL2 = T2AUTOL;
ET2 = 1; // ...don't forget to enable this interrupt
// turn debug LED[3:0] off...
ledX_rdvar = LED0_OFF;
ledX_rdvar = LED1_OFF;
ledX_rdvar = LED2_OFF;
ledX_rdvar = LED3_OFF;
}
void TD_Poll( void )
{ // Called repeatedly while the device is idle
BYTE entry = 0x00;
getkey( ); // ...scan kpd matix, if found then queue...
if( !( IN2CS & 0x02 ) )
{ // IN2BUSY=0 when buffer available...dequeue users inputs...
entry = queue( DEQUEUE, NOKEY );
if( entry != 0xFF )
{ // ...valid key closure
IN2BUF[ 0 ] = entry;
IN2BC = 1; // arm endp, 1 key at a time...
}
else
{ // ...
}
}
else
{
}
USBBAV |= 0x08; // turn off breakpoint LED
}
BOOL TD_Suspend(void) // Called before the device goes into suspend mode
{
return(TRUE);
}
BOOL TD_Resume(void) // Called after the device resumes
{
return(TRUE);
}
//-----------------------------------------------------------------------------
// Device Request hooks
// The following hooks are called by the end point 0 device request parser.
//-----------------------------------------------------------------------------
BOOL DR_GetDescriptor(void)
{
return(TRUE);
}
BOOL DR_SetConfiguration(void) // Called when a Set Configuration command is received
{
Configuration = SETUPDAT[2];
return(TRUE); // Handled by user code
}
BOOL DR_GetConfiguration(void) // Called when a Get Configuration command is received
{
IN0BUF[0] = Configuration;
EZUSB_SET_EP_BYTES(IN0BUF_ID,1);
return(TRUE); // Handled by user code
}
BOOL DR_SetInterface(void) // Called when a Set Interface command is received
{
AlternateSetting = SETUPDAT[2];
return(TRUE); // Handled by user code
}
BOOL DR_GetInterface(void) // Called when a Set Interface command is received
{
IN0BUF[0] = AlternateSetting;
EZUSB_SET_EP_BYTES(IN0BUF_ID,1);
return(TRUE); // Handled by user code
}
BOOL DR_GetStatus(void)
{
return(TRUE);
}
BOOL DR_ClearFeature(void)
{
return(TRUE);
}
BOOL DR_SetFeature(void)
{
return(TRUE);
}
#define VX_B0 0xB0 // ...flush the queue
#define VX_B1 0xB1 // ...return number of keys in queue
BOOL DR_VendorCmnd(void)
{
switch( SETUPDAT[ 1 ] )
{
case VX_B0:
{ // flush the queue
*IN0BUF = queue( FLUSHDQ, NOKEY );
IN0BC = 0x01; // arm endp, # bytes to xfr
EP0CS |= bmBIT1; // ack handshake phase of device request
break;
}
case VX_B1:
{ // return number of keys in queue
*IN0BUF = queue( BYTECNT, NOKEY );
IN0BC = 0x01; // arm endp, # bytes to xfr
EP0CS |= bmBIT1; // ack handshake phase of device request
break;
}
default:
{
break;
}
}
return( FALSE ); // no errors, cmd handled okay
}
//-----------------------------------------------------------------------------
// USB Interrupt Handlers
// The following functions are called by the USB interrupt jump table.
//-----------------------------------------------------------------------------
// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
GotSUD = TRUE; // Set flag
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUDAV; // Clear SUDAV IRQ
}
// Setup Token Interrupt Handler
void ISR_Sutok(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUTOK; // Clear SUTOK IRQ
}
void ISR_Sof(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmSOF; // Clear SOF IRQ
}
void ISR_Ures(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmURES; // Clear URES IRQ
}
void ISR_IBN(void) interrupt 0
{
}
void ISR_Susp(void) interrupt 0
{
Sleep = TRUE;
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUSP;
}
void ISR_Ep0in(void) interrupt 0
{
}
void ISR_Ep0out(void) interrupt 0
{
}
void ISR_Ep1in(void) interrupt 0
{
}
void ISR_Ep1out(void) interrupt 0
{
}
void ISR_Ep2in(void) interrupt 0
{
}
void ISR_Ep2out(void) interrupt 0
{
}
void ISR_Ep3in(void) interrupt 0
{
}
void ISR_Ep3out(void) interrupt 0
{
}
void ISR_Ep4in(void) interrupt 0
{
}
void ISR_Ep4out(void) interrupt 0
{
}
void ISR_Ep5in(void) interrupt 0
{
}
void ISR_Ep5out(void) interrupt 0
{
}
void ISR_Ep6in(void) interrupt 0
{
}
void ISR_Ep6out(void) interrupt 0
{
}
void ISR_Ep7in(void) interrupt 0
{
}
void ISR_Ep7out(void) interrupt 0
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -