📄 usb_9602.c
字号:
write_usb(NFSR,OPR_ST); /*go operational */
write_usb(MCNTRL,VREG_ST+INTR_TYPE+NAT); /*set NODE ATTACH */
PoleCh[++PointCh]=read_usb(MAMSK);
PoleCh[++PointCh]=read_usb(MAEV);
IT1=1;
EX1=1; /* Enable Int 1 */
}
/**********************************************************************/
/* This subroutine parses commands received through the cmd channel: */
/**********************************************************************/
void do_cmd(void)
{
unsigned char *radr; /*pointer for memory ops */
radr= (unsigned char *)(256*radh+radl); /*setup pointer */
switch (rcmd)
{
case 'b': /*look for EE bulk erase */
xmit('b'); /*send back dummy code */
break;
case 'd': /*look for 'debug' toggle */
TGLBIT(status,DEBUG); /*flip the bit */
if(TSTBIT(status,DEBUG)) /*send back conf. code */
xmit(0xFF);
else
xmit(0x00);
break;
xmit('e'); /*send back dummy code */
break;
case 'g': /*look for 9602 get (read)*/
xmit(read_usb(radl)); /*read the spec. 9602 reg*/
break;
case 'p': /*look for 9602 prog (wr) */
write_usb(radl,rdta); /*write the spec. 9602 reg*/
xmit(rdta); /*send it back to confirm */
break;
case 'i': /*look for init USB cmd */
init_usb(); /*initialize the 9602 */
xmit('i'); /*send back dummy code */
break;
case 'l': /*look for EE reg load */
xmit('l'); /*send back dummy code */
break;
case 'q': /*look for Query op */
xmit('A'); /*send Vendor ID */
xmit(MAJREV); /*send Major Revision */
xmit(MINREV); /*send Minor Revision */
/*the (unsigned char) typecast is used here because the */
/*BYTECRAFT C compiler can't properly handle the (byte) */
/*variant. */
rdta=(unsigned char)&usb_buf; /*convert address to byte */
xmit(rdta); /*send usb buffer offset */
rdta=0;
xmit(rdta); /*send EE buffer offset */
xmit(brd_id); /*send ID */
break;
case 'c': /*look for LCD command */
xmit('c'); /*send back dummy code */
break;
case 'z': /*backward compatibility */
xmit('z'); /*send back dummy code */
break;
case 'j': /*look for joystick cmd */
xmit(0x00); /*and codes */
break;
case 's': /*look for EE reg store */
xmit('s'); /*send back dummy code */
break;
case 't': /*backward compatibility */
xmit(0); /*send back dummy code */
break;
case 'r': /*look for Rd code */
xmit(*radr); /*get data and send it */
break;
case 'w': /*look for Wr code */
*radr=rdta; /*write the data */
xmit(*radr); /*get data and send it */
break;
case 'x': /*look for Microwire exch.*/
xmit('x'); /*send back dummy code */
break;
default:
xmit('?'); /*we're confused... help!!*/
} /*end of switch */
}
/**********************************************************************/
/* This subroutine handles USB 'alternate' events. */
/**********************************************************************/
void usb_alt(void)
{
evnt = read_usb(ALTEV); /*check the events */
if(evnt & RESET_A) /*reset event */
{
write_usb(NFSR,RST_ST); /*enter reset state */
write_usb(FAR,AD_EN+0); /*set default address */
write_usb(EPC0, 0x00); /*enable EP0 only */
FLUSHTX0; /*flush TX0 and disable */
write_usb(RXC0,RX_EN); /*enable the receiver */
/*adjusting ints is nec. here in case we were in suspend */
write_usb(ALTMSK,NORMAL_ALTMSK);/*adjust interrupts */
write_usb(NFSR,OPR_ST); /*go operational */
//PoleCh[++PointCh]='R';
//PoleCh[++PointCh]='s';
//PoleCh[++PointCh]='t';
//PoleCh[++PointCh]='_';
//PoleCh[++PointCh]='A';
//PoleCh[++PointCh]=' ';
}
else if(evnt & RESUME_A) /*resume event */
{
write_usb(ALTMSK,NORMAL_ALTMSK);/*adjust interrupts */
write_usb(NFSR,OPR_ST); /*go operational */
//PoleCh[++PointCh]='R';
//PoleCh[++PointCh]='e';
//PoleCh[++PointCh]='s';
//PoleCh[++PointCh]='u';
//PoleCh[++PointCh]='_';
//PoleCh[++PointCh]='A';
}
else if((evnt & SD3)&&(suscntr==0)) /*suspend event */
{
write_usb(ALTMSK,SUSPND_ALTMSK);/*adj interrupts */
write_usb(NFSR,SUS_ST); /*enter suspend state */
deep_sleep(); /*reduce power cons. */
suscntr=SUSPND_TO; /*start suspend cntr */
//PoleCh[++PointCh]='S';
//PoleCh[++PointCh]='D';
//PoleCh[++PointCh]='3';
//PoleCh[++PointCh]=' ';
}
else /*spurious alt. event! */
{
//PoleCh[++PointCh]='e';
//PoleCh[++PointCh]='l';
//PoleCh[++PointCh]='s';
//PoleCh[++PointCh]='e';
//PoleCh[++PointCh]=' ';
}
}
/**********************************************************************/
/* This subroutine handles RX events for FIFO0 (endpoint 0) */
/**********************************************************************/
void rx_0(void)
{
rxstat=read_usb(RXS0); /*get receiver status */
/*is this a setup packet? ***************************************/
if(rxstat & SETUP_R)
{
/*read data payload into buffer then flush/disble the RX ****/
for(desc_idx=0; desc_idx<8; desc_idx++)
usb_buf[desc_idx] = read_usb(RXD0);
FLUSHRX0; /*make sure the RX is off */
FLUSHTX0; /*make sure the TX is off */
bitclr(EPC0,STALL); /*turn off stall */
switch (usb_buf[0]&0x60) /*decode request type */
{
case 0x00: /*standard request */
switch (usb_buf[1]) /*decode request code */
{
case CLEAR_FEATURE:
clrfeature();
break;
case GET_CONFIGURATION:
write_usb(TXD0,usb_cfg);/*load the config val */
break;
case GET_DESCRIPTOR:
getdescriptor();
break;
case GET_INTERFACE:
write_usb(TXD0,0); /*load the intf. val */
break;
case GET_STATUS:
getstatus();
break;
case SET_ADDRESS:
/*save the new address, but don't actually store*/
/*it into FAR until later (when status handshake*/
/*completes during tx_0). Note that the 9602 */
/*has a DEF bit in EPC0 designed for this purp- */
/*ose, but it only works if the default address */
/*is initially in effect. Therefore it can't */
/*be used for multiple SET_ADDRESS commands in */
/*sequence. This will work regardless of init- */
/*ial address. */
setaddr = (usb_buf[2] | AD_EN);
break;
case SET_CONFIGURATION:
setconfiguration();
break;
case SET_FEATURE:
setfeature();
break;
case SET_INTERFACE:
if(usb_buf[2]) /*if the requested intf!=0*/
bitset(EPC0,STALL); /*stall the endpoint */
break;
default: /*unsupported standard req*/
bitset(EPC0,STALL); /*stall the endpoint */
break;
}
break;
case 0x20: /*class request */
switch (usb_buf[1]) /*decode request code */
{
case GET_REPORT:
getreport();
break;
case SET_REPORT:
setreport();
break;
case GET_IDLE:
getidle();
break;
case SET_IDLE:
setidle();
break;
default: /*unsupported standard req*/
bitset(EPC0,STALL); /*stall the endpoint */
break;
}
break;
default: /*unsupported req type */
bitset(EPC0,STALL); /*stall the endpoint */
break;
}
/*the following is done for all setup packets. Note that if*/
/*no data was stuffed into the FIFO, the result of the fol- */
/*lowing will be a zero-length response. */
write_usb(TXC0,TX_TOGL+TX_EN); /*enable the TX (DATA1) */
CLRBIT(dtapid,TGL0PID); /*store NEXT PID state */
}
/*if not a setup packet, it must be an OUT packet ***************/
/* Note that there is no RX_ERR bit in RXS0, so we don't look */
/* for and handle them the way we do in the other RX event */
/* handlers. */
else
{
if (TSTBIT(status,MLTIPKT)) /*multi-pkt status stage? */
{
/*test for errors (zero length, correct PID) */
if ((rxstat& 0x5F)!=0x10) /*length error?? */
{ }
CLR_MLTIPKT; /*exit multi-packet mode */
FLUSHTX0; /*flush TX0 and disable */
}
write_usb(RXC0,RX_EN); /*re-enable the receiver */
}
/*we do this stuff for all rx_0 events **************************/
}
/**********************************************************************/
/* This subroutine handles RX events for FIFO1 (endpoint 2) */
/**********************************************************************/
void rx_1(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -