📄 usb.c
字号:
TXEN3_PID_NO_TGL; /*enable TX, choose PID */
}
}
/**********************************************************************/
/* 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 */
}
else if(evnt & RESUME_A) /*resume event */
{
write_usb(ALTMSK,NORMAL_ALTMSK);/*adjust interrupts */
write_usb(NFSR,OPR_ST); /*go operational */
}
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 */
}
else /*spurious alt. event! */
{
}
}
/**********************************************************************/
/* This is the interrupt service routine for USB operations */
/**********************************************************************/
void usb_isr(void)
{
evnt = read_usb(MAEV); /*check the events */
USB_LED_ON; /*turn on intr. LED */
if (evnt & RX_EV)
{
evnt=read_usb(RXEV); /*check the RX events */
if (evnt&RXFIFO0) rx_0(); /*endpoint 0 */
else if (evnt&RXFIFO1) rx_1(); /*endpoint 2 */
else if (evnt&RXFIFO2) rx_2(); /*endpoint 4 */
else if (evnt&RXFIFO3) rx_3(); /*endpoint 6 */
else /*some other RX event */
{
}
}
else if (evnt & TX_EV)
{
evnt=read_usb(TXEV); /*check the TX events */
if (evnt&TXFIFO0) tx_0(); /*endpoint 0 */
else if (evnt&TXFIFO1) tx_1(); /*endpoint 1 */
else if (evnt&TXFIFO2) tx_2(); /*endpoint 3 */
else if (evnt&TXFIFO3) tx_3(); /*endpoint 5 */
else /*some other TX event */
{
}
}
else if (evnt & ALT) usb_alt(); /*alternate event? */
/*NAKs can come so fast and furious (especially with OHCI hosts)*/
/*that they MUST have a lower priority than the other events. If*/
/*they did not, the other events could get starved out. */
else if (evnt & NAK)
{
evnt=read_usb(NAKEV); /*check the NAK events */
if (evnt&NAK_O0) onak0(); /*endpoint 0 */
else if (evnt&NAK_O1) onak1(); /*endpoint 2 */
else if (evnt&NAK_O2) onak2(); /*endpoint 4 */
else if (evnt&NAK_I3) inak3(); /*endpoint 5 */
else /*some other NAK event */
{
}
}
else /*spurious event! */
{
}
/*the 9602 produces interrupt LEVELS, the COP looks for edges. */
/*So we have to fool the 9602 into producing new edges for us */
/*when we are ready to look for them. We do this by temporarily*/
/*disabling the interrupts, then re-enabling them. */
evnt=read_usb(MAMSK); /*save old mask contents */
write_usb(MAMSK,0); /*disable interrupts */
write_usb(MAMSK,evnt); /*re-enable interrupts */
USB_LED_OFF; /*turn off intr. LED */
}
/**********************************************************************/
/* This subroutine updates the given a/d report variable as necessary.*/
/**********************************************************************/
void update(byte chnl, byte near *val)
{
chnl = A2D_conv(chnl); /*convert the channel */
if (chnl<MINJOY) chnl=MINJOY; /*check and fix the limits*/
if (chnl>MAXJOY) chnl=MAXJOY;
chnl-=MINJOY; /*adjust for offset */
chnl=JOY_DATA[chnl]; /*linearize result */
if(chnl!=*val) /*if value is different */
{
*val=chnl; /*store the new value */
SETBIT(status,RPTCHNG); /*flag the value change */
}
}
/**********************************************************************/
/* This subroutine queues changes, if anyreport variable as necessary.*/
/**********************************************************************/
void queue_chngs(void)
{
/*This procedure uses the microwire port, which is also used by */
/*the interrupt routines. Since this procedure is called from */
/*the main loop, we must temporarily disable interrupts to en- */
/*sure that we don't step on ourselves. */
/*if there is new data to report and the xmitter is not loaded */
if((TSTBIT(status,RPTCHNG)) && (!TSTBIT(status,RPTBUSY)))
{
INTSOFF; /*dsable global interrupt */
queue_rpt(TXD3); /*queue a report */
TXEN3_PID_NO_TGL; /*enable TX, choose PID */
INTSON; /*enable global interrupt */
}
}
/**********************************************************************/
/* This is the handler for keeping track of the real time. This proc.*/
/* is called every 0.5 seconds. */
/**********************************************************************/
void trktim(void)
{
HEARTBEAT; /*heartbeat (1 Hz flash) */
SETBIT(status,RPTCHNG); /*do regular report */
if(suscntr>0) suscntr--; /*decriment until 0 */
}
/**********************************************************************/
/* This is the handler for the RS232 port. */
/**********************************************************************/
void rcveih(void)
{
rsnc=rcmd; /*slide buffer content up */
rcmd=rdta;
rdta=radh;
radh=radl;
radl=rcks;
GET_RX(rcks); /*rcks = rx data */
if (rsnc==SYNCBYT) /*if sync code is valid */
{
if (rcks==(unsigned char)(rsnc+rcmd+rdta+radh+radl))
do_cmd(); /*do the cmd */
}
}
/**********************************************************************/
/* This is the handler for the RS232 port. */
/**********************************************************************/
void xmitih(void)
{
byte i;
if(outq_idx>0)
{
PUT_TX(outq[0]); /*transmit top of queue */
for(i=0; i<outq_idx; i++) outq[i]=outq[i+1]; /*move queue*/
outq_idx--; /*decriment index */
}
if(outq_idx==0) TXINTOFF; /*turn off int if done */
}
/**********************************************************************/
/* This subroutine sends a character through the UART transmitter or */
/* The usb interface, depending on the mode. */
/**********************************************************************/
void xmit(char c)
{
/*USB mode: move character to endpoint 1 FIFO *******************/
if(TSTBIT(status,USB_CMD))
{
write_usb(TXD1,c); /*send data to the FIFO */
}
/*UART mode: move character to UART queue ***********************/
else
{
while (outq_idx>=OUTQLEN) /*wait for room in queue */
if (TX_EMPTY) xmitih(); /*or make it if we can */
outq[outq_idx++]=c; /*post character */
TXINTON; /*turn on interrupt */
if (TX_EMPTY) xmitih(); /*start xmission if ready */
}
}
/**********************************************************************/
/* This subroutine parses commands received through the cmd channel: */
/**********************************************************************/
void do_cmd(void)
{
byte *radr; /*pointer for memory ops */
#ifdef COP8
radr= (byte *) radl; /*setup pointer */
#else
radr= (byte *)(256*radh+radl); /*setup pointer */
#endif
switch (rcmd)
{
case 'b': /*look for EE bulk erase */
#ifdef EEPROM
eebulk(); /*bulk erase the EEPROM */
#endif
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;
case 'e': /*look for EE reg erase */
#ifdef EEPROM
eerase(radl); /*erase the EEPROM reg */
#endif
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 */
#ifdef EEPROM
eergrd(radl); /*load the EEPROM reg */
xmit(eebufl); /*send back low byte */
#else
xmit('l'); /*send back dummy code */
#endif
break;
case 'q': /*look for Query op */
xmit(VID); /*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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -