// // PC host application to transmit and receive USB frames to the C8051 // device SPItoUSB interface. This application is based on the SiLabs // USBExpress library // #include #include #include #include #include #include #include "SiUSBXp.h" #include "chimaera.h" // Enumerate, locate and open device cbusb::cbusb( const char *type, unsigned index ) { SI_STATUS rc; unsigned found = 0; // Find how many devices are attached DWORD NumDevices; rc = SI_GetNumDevices( &NumDevices ); if ( rc != SI_SUCCESS ) { errors.form( "cbusb::cbusb:Si_GetNumDevices(): rc = %d\n", rc ); return; } // Identify the correct device DWORD deviceIndex; char deviceString[256]; for (deviceIndex=0; deviceIndexshowErrorTrace(); } // Read the block of data and send acknowledge to device void cbusb::receive( devicePacket_t &buf, unsigned msglen ) { SI_STATUS rc; DWORD len; rc = SI_Read( deviceHandle, (BYTE *)&buf, msglen, &len ); if ( rc == SI_RX_QUEUE_NOT_READY ) { // usleep(5000000); rc = SI_Read( deviceHandle, (BYTE *)&buf, msglen, &len ); } if ( rc != SI_SUCCESS ) { errors.form( "cbusb::receive: Si_Read(): rc = %d\n", rc ); return; } if ( len != msglen ) { errors.form( "cbusb::receive: Si_Read(): Data under-run error. len = %d\n", len ); return; } return; } int CBUSBReceive( CBUSBID u, devicePacket_t &buf, unsigned msglen ) { cbusb *usb = (cbusb *)u; usb->receive( buf, msglen ); if ( !(*usb) ) return -1; return 0; } // Read the status block sent from device void cbusb::showLastStatus( devicePacket_t &lastStatus ) { trace.form( "showLastStatus(): cmd=%#x, len=%#x\n", lastStatus.cmd, lastStatus.length ); trace.form( "PIO[2,1,0] = [%#x,%#x,%#x]\n", lastStatus.status.PIO[2],lastStatus.status.PIO[1],lastStatus.status.PIO[0] ); trace.form( "Sequence # = %d\n", lastStatus.status.seq ); trace.form( "Parity errors[0]: %#x\n", lastStatus.status.parityErrorCount[0] ); trace.form( "Parity errors[1]: %#x\n", lastStatus.status.parityErrorCount[1] ); trace.form( "Parity errors[2]: %#x\n", lastStatus.status.parityErrorCount[2] ); trace.form( "Parity errors[3]: %#x\n", lastStatus.status.parityErrorCount[3] ); trace.form( "Event counter: %#x\n", lastStatus.status.eventCount ); trace.form( "Buffer counter: %#x\n", lastStatus.status.bufferCount ); trace.form( "Rx error flags: %#x\n", lastStatus.status.rxerr ); trace.form( "Rx inhibit flags: %#x\n", lastStatus.status.rxinhibit ); trace.form( "Extra: %#x\n", lastStatus.status.extra ); trace.form( "ADC[0]: %#x\n", lastStatus.status.ADC[0] ); trace.form( "ADC[1]: %#x\n", lastStatus.status.ADC[1] ); std::cout << trace << std::endl; return; } void CBUSBShowLastStatus( CBUSBID u, devicePacket_t &lastStatus ) { cbusb *usb = (cbusb *)u; usb->showLastStatus( lastStatus ); return; } void cbusb::showLastData( devicePacket_t &lastData ) { for (unsigned i=0; i<16 ; i++ ) { if ( i%4 == 0 ) trace.form( "[%0#4x]", i ); trace.form( " %0#10x", lastData.data[i] ); if ( i%4 == 3 ) trace.form( "\n" ); } std::cout << trace << std::endl; return; } void CBUSBShowLastData( CBUSBID u, devicePacket_t &lastData ) { cbusb *usb = (cbusb *)u; usb->showLastData( lastData ); return; } void cbusb::dispatch( devicePacket_t &msg, unsigned msglen ) { SI_STATUS rc; DWORD len; msg.length = msglen - 4; rc = SI_Write( deviceHandle, &msg, msglen, &len ); if ( rc != SI_SUCCESS ) { errors.form( "cbusb::dispatch:SI_Write() rc = %d\n", rc ); return; } if ( len != msglen ) { errors.form( "cbusb::dispatch:SI_Write() write underrun\n" ); return; } return; } int CBUSBDispatch( CBUSBID u, devicePacket_t &msg, unsigned msglen ) { cbusb *usb = (cbusb *)u; usb->dispatch( msg, msglen ); if ( !(*usb) ) return -1; return 0; } int CBUSBDispatchConfiguration( CBUSBID u, unsigned mask, unsigned cfg ) { devicePacket_t msg; msg.cmd = deviceHeader_t::ConfigurationData; msg.length = 4; msg.config[0] = mask & 0xffff; msg.config[1] = cfg & 0xffff; cbusb *usb = (cbusb *)u; usb->dispatch( msg, 8 ); if ( !(*usb) ) return -1; return 0; } // Request write to IO Port void cbusb::dispatchPIOWriteRequest( unsigned PIO ) { devicePacket_t packet; // Send request packet.cmd = deviceHeader_t::PIOWriteRequest; packet.length = 4; packet.data[0] = PIO; dispatch( packet, 8 ); return; } int CBUSBDispatchPIOWriteRequest( CBUSBID u, unsigned PIO ) { cbusb *usb = (cbusb *)u; usb->dispatchPIOWriteRequest( PIO ); if ( !(*usb) ) return -1; return 0; } // Request clock burst generation void cbusb::dispatchClockBurstRequest( unsigned burstLength, unsigned period ) { devicePacket_t packet; unsigned pca0cp = (24*0x10000 - (period & 0xff)*burstLength)/24; // Send request packet.cmd = deviceHeader_t::GenerateClockBurst; packet.length = 4; packet.uc[0] = pca0cp & 0xff; packet.uc[1] = (pca0cp >> 8) & 0xff; packet.uc[2] = period & 0xff; dispatch( packet, 8 ); return; } int CBUSBDispatchClockBurstRequest( CBUSBID u, unsigned burstLength, unsigned period ) { cbusb *usb = (cbusb *)u; usb->dispatchClockBurstRequest( burstLength, period ); if ( !(*usb) ) return -1; return 0; } // Flush the Chimaera buffer unsigned cbusb::flushBuffer( unsigned maxPacketRequest, bool show ) { unsigned packetsRequested; devicePacket_t cmdPacket; devicePacket_t lastStatus; devicePacket_t lastData; // Request status to find how much (if any) data are buffered cmdPacket.cmd = deviceHeader_t::StatusRequest; dispatch( cmdPacket, 8 ); receive( lastStatus, 68 ); if ( lastStatus.status.bufferCount == 0 ) { return 0; } unsigned packets = (lastStatus.status.bufferCount >> 4) + 1; // Extract all the data from the buffer for ( unsigned packet=0; packet= maxPacketRequest ) { packetsRequested = maxPacketRequest; } else { packetsRequested = packetsRemaining; } cmdPacket.cmd = deviceHeader_t::PacketRequest; cmdPacket.uc[0] = packetsRequested; // Number of packets dispatch( cmdPacket, 8 ); for ( unsigned char nread=packetsRequested; nread; nread-- ) { receive( lastData, 68 ); if ( show ) showLastData( lastData ); } } return lastStatus.status.bufferCount; } unsigned CBUSBFlushBuffer( CBUSBID u, unsigned maxPacketRequest, bool show ) { cbusb *usb = (cbusb *)u; return usb->flushBuffer( maxPacketRequest, show ); }