// sends all accumulated events. if a xmit fifo is empty then this call returns in about 14us. // it takes about 860us if we send 225 events. void sendEvents(){ // EA=0; //USB_Int_Disable(); // disable USB interrupt while writing buffer to FIFO LedBlueOn(); // toggle LED on each packet EIE1 &= ~0x02; Block_Write((BYTE*)AEBuffer, AECounter*4); EIE1 |= 0x02; AECounter=0; // reset counter and pointer for event buffering AEPtr=AEBuffer; LedBlueOff(); // toggle LED on each packet // EA=1; //USB_Int_Enable(); }
void LedTest(void) { while(1) { LedRedOn(); DelayNmS(200); LedRedOff(); DelayNmS(200); LedBlueOn(); DelayNmS(200); LedBlueOff(); DelayNmS(200); } }
void DisplayOK(void) { unsigned char i = 0; for(i=0;i<3;i++) { BellOn(); LedBlueOn(); DelayNmS(50); BellOff(); LedBlueOff(); DelayNmS(50); } }
void DisplayErr(void) { unsigned char i = 0; for(i=0;i<2;i++) { BellOn(); LedRedOn(); LedBlueOn(); DelayNmS(200); BellOff(); LedRedOff(); LedBlueOff(); DelayNmS(200); } }
void LedInit(void) { LedRedOff(); LedBlueOff(); }
//----------------------------------------------------------------------------- // Main Routine // after initialization, the program simply polls the !req input and when // !req goes low, !ack on P0.1 is lowered to acknowledge, // the address is captured in P1 (AE0-7) and P2 (AE8-15) and is copied to XRAM. // Then !ack is raised, we wait for !req to go high and start over. // When we get an interrupt from USB, we transmit the existing buffer of data. //----------------------------------------------------------------------------- void main(void) { PCA0MD &= ~0x40; // Disable Watchdog timer //void USB_Init (int VendorID, int ProductID, uchar *ManufacturerStr,uchar *ProductStr, uchar *SerialNumberStr, byte MaxPower, byte PwAttributes, uint bcdDevice) // note that ProductID is important that windows hardware installation wizard can find the USBXPress driver // this driver must be preinstalled before plugging in device // see the Preinstaller but note that path in .ini file may need to be changed for preinstaller to locate driver files // so that they can be copied to standard windows driver search folder for drivers. // this initVariables is for 60mA device, bus powered, serial number 1.00 USB_Init (0, 0xEA61, ManufacturerStr, ProductStr, SerialNumberStr,250,0x80,0x0100); CLKSEL |= 0x02; // system clock 24MHz (48MHz USB/2) RSTSRC |= 0x02; // power on reset Timer_Init(); // Init Timer and Capture for event timing. Init PCA peripheral before port init. Port_Init(); // Initialize crossbar and GPIO initVariables(); LedGreenOff(); LedBlueOff(); /* LedRedOn(); delay(); LedRedOff(); LedGreenOn(); delay(); LedGreenOff(); LedBlueOn(); delay(); LedBlueOff(); */ //flushEvents(); // flush some events in case the sender has been powered up //state=ST_WAITING; isActive=0; USB_Int_Enable(); // Enable USB_API Interrupts while (1){ // if(state==ST_ACTIVE){ if(isActive){ while(NOTREQ==1) { // wait for !req low if( TH1==0xFF){ // while polling req, check if we have wrapped timer1 since last transfer if(AECounter>0){ sendEvents(); // if so just send available events } } } LedGreenOn(); // got req NOTACK=0; // lower acknowledge //USB_Int_Disable(); // using these functions increases cycle time to >8us EA=0; // disable interrupts during snapshot of AE to avoid USB interrupt during snapshot //note according to C51 compiler specs, shorts are stored big-endian, MSB comes first *AEPtr++=P2; // AE8-15 *AEPtr++=P1; // AE07 *AEPtr++=PCA0CPH0; // captured PCA counter/timer MSB. This was captured by req low. *AEPtr++=PCA0CPL0; // timer LSB. AECounter++; // increment counter for events EA=1; // reenable interrupts // USB_Int_Enable(); // using these functions increases cycle time to >8us // if the retina is powered off, then its req will be low (no power). so this code will come here and // will have lowered ack and stored a bogus address. now it will wait for req to go high. // but req will be low from the retina and won't go high // because ack is low. therefore we can get stuck here if the retina is powered on after reset. while(NOTREQ==0){ // wait for req to go high if( TH1==0xFF) { // while polling req, check if we have wrapped timer1 since last transfer TH1=0; AECounter--; // throw away that event break; // break from possibly infinite loop. this will raise ack } } NOTACK=1; // raise acknowledge, completing handshake LedGreenOff(); // got req if(AECounter==AE_BUFFER_SIZE){ // when we have collected buffer, initiate transfer // during this 860us no handshaking is occurring sendEvents(); } // }else if(state==ST_WAITING){ }else{ // isActive is false, USB not open, just handshake // plain handshake cycle is about 1+/-0.2us while(NOTREQ==1) { // wait for !req low if( TH1==0xFF) { // while polling req, check if we have wrapped timer1 since last transfer TH1=0; NOTACK=0; NOTACK=1; // toggle ack an extra time in case we are stuck } } LedGreenOn(); // !req received NOTACK=0; // lower acknowledge while(NOTREQ==0){ // wait for req to go high if( TH1==0xFF) { // while polling req, check if we have wrapped timer1 since last transfer TH1=0; break; // break from possibly infinite loop } } NOTACK=1; // raise acknowledge, completing handshake LedGreenOff(); } } }