// // 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 "l1c8051.h" // Enumerate, locate and open device l1c8051::l1c8051( const char *type, unsigned serial ) { SI_STATUS rc; unsigned found = 0; // Find how many devices are attached DWORD NumDevices; rc = SI_GetNumDevices( &NumDevices ); if ( rc != SI_SUCCESS ) { errors.form( "l1c8051::l1c8051:Si_GetNumDevices(): rc = %d\n", rc ); return; } // Identify the correct device DWORD deviceIndex; unsigned serialNumber; char deviceString[256]; char deviceSerial[32]; for (deviceIndex=0; deviceIndex): rc = %d\n", rc ); return; } rc = SI_GetProductString( deviceIndex, deviceSerial, SI_RETURN_SERIAL_NUMBER ); if ( rc != SI_SUCCESS ) { errors.form( "Si_GetProductString(): rc = %d\n", rc ); return; } serialNumber = strtoul( deviceSerial, 0, 0 ); // trace.form( "SI_GetProductString(): [%d] [%s] rc = %d\n", deviceIndex, deviceString, rc ); if ( !strcmp( deviceString,type ) ) { if ( serialNumber == serial ) break; } } if ( deviceIndex == NumDevices ) { errors.form( "l1c8051::l1c8051: Device not found.\n" ); return; } // Open the device rc = SI_Open( deviceIndex, &deviceHandle ); if ( rc != SI_SUCCESS ) { errors.form( "l1c8051::l1c8051:Si_Open(): rc = %d\n", rc ); return; } // Set the read and write timeout to 5s rc = SI_SetTimeouts(5000,5000); if ( rc != SI_SUCCESS ) { errors.form( "l1c8051::l1c8051:Si_SetTimeouts(): rc = %d\n", rc ); return; } return; } int L1C8051Open( L1C8051ID *U, char *deviceType, unsigned idx ) { l1c8051 *u = new l1c8051( deviceType, idx ); *U = u; if ( !(*u) ) return -1; return 0; } // Close device l1c8051::~l1c8051() { SI_STATUS rc; rc = SI_Close( deviceHandle ); if ( rc != SI_SUCCESS ) { errors.form( "l1c8051::~l1c8051:Si_Close(): rc = %d\n", rc ); return; } return; } int L1C8051Close( L1C8051ID u ) { delete (l1c8051 *)u; return 0; } void l1c8051::showErrorTrace() { std::cerr << errors << std::endl; return; } void l1c8051::showInfoTrace() { std::cerr << trace << std::endl; return; } void L1C8051ShowErrorTrace( L1C8051ID u ) { l1c8051 *usb = (l1c8051 *)u; usb->showErrorTrace(); } // Read the block of data and send acknowledge to device void l1c8051::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( "l1c8051::receive: Si_Read(): rc = %d\n", rc ); return; } if ( len != msglen ) { errors.form( "l1c8051::receive: Si_Read(): Data under-run error. len = %d\n", len ); return; } return; } int L1C8051Receive( L1C8051ID u, devicePacket_t &buf, unsigned msglen ) { l1c8051 *usb = (l1c8051 *)u; usb->receive( buf, msglen ); if ( !(*usb) ) return -1; return 0; } // Read the status block sent from device void l1c8051::showLastStatus( devicePacket_t &lastStatus ) { trace.form( "showLastStatus(): cmd=%#x, len=%#x\n", lastStatus.cmd, lastStatus.length ); 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[0]: %#x\n", lastStatus.status.eventCount[0] ); trace.form( "Event counter[1]: %#x\n", lastStatus.status.eventCount[1] ); trace.form( "Buffer counter[0]: %#x\n", lastStatus.status.bufferCount[0] ); trace.form( "Buffer counter[1]: %#x\n", lastStatus.status.bufferCount[1] ); std::cout << trace << std::endl; return; } void L1C8051ShowLastStatus( L1C8051ID u, devicePacket_t &lastStatus ) { l1c8051 *usb = (l1c8051 *)u; usb->showLastStatus( lastStatus ); return; } void l1c8051::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.ui[i] ); if ( i%4 == 3 ) trace.form( "\n" ); } std::cout << trace << std::endl; return; } void L1C8051ShowLastData( L1C8051ID u, devicePacket_t &lastData ) { l1c8051 *usb = (l1c8051 *)u; usb->showLastData( lastData ); return; } void l1c8051::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( "l1c8051::dispatch:SI_Write() rc = %d\n", rc ); return; } if ( len != msglen ) { errors.form( "l1c8051::dispatch:SI_Write() write underrun\n" ); return; } return; } int L1C8051Dispatch( L1C8051ID u, devicePacket_t &msg, unsigned msglen ) { l1c8051 *usb = (l1c8051 *)u; usb->dispatch( msg, msglen ); if ( !(*usb) ) return -1; return 0; } int L1C8051DispatchConfiguration( L1C8051ID u, unsigned char id, unsigned short cfg ) { devicePacket_t msg; msg.cmd = deviceHeader_t::ConfigurationData; msg.length = 4; msg.config.Id = 0; msg.config.Data = cfg; l1c8051 *usb = (l1c8051 *)u; usb->dispatch( msg, 8 ); if ( !(*usb) ) return -1; return 0; } // Request trigger burst generation void l1c8051::dispatchTriggerBurstRequest( 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 L1C8051DispatchTriggerBurstRequest( L1C8051ID u, unsigned burstLength, unsigned period ) { l1c8051 *usb = (l1c8051 *)u; usb->dispatchTriggerBurstRequest( burstLength, period ); if ( !(*usb) ) return -1; return 0; } // Flush the Chimaera buffer unsigned l1c8051::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[0]; // 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[0]; } unsigned L1C8051FlushBuffer( L1C8051ID u, unsigned maxPacketRequest, bool show ) { l1c8051 *usb = (l1c8051 *)u; return usb->flushBuffer( maxPacketRequest, show ); }