void ProcessIO(void) { if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return; /*if(USBGetDeviceState() == DETACHED_STATE) { if(I2CCount > 0) { ProcessCmd(OUTPacket); I2CCount = 0; } } else*/ if(!USBHandleBusy(USBGenericOutHandle)) { //if( OUTPacket[1] != MASTER_ADDRESS ) // I2CRelay(OUTPacket, USBGEN_EP_SIZE); //else ProcessCmd(OUTPacket); USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM, (BYTE*)&OUTPacket, USBGEN_EP_SIZE); } if(WQI != WQX && !USBHandleBusy(USBGenericInHandle)) { USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM, (BYTE*)&INPacket[WQX*USB_RECORD_SIZE], USB_RECORD_SIZE); WQX = (WQX+1) & 3; } } //end ProcessIO
static void processCy7c4xxFifo(void) { unsigned char c; static unsigned char *cy7c4xx_buf_ptr = InDataPacket; static unsigned char len = 0; if (cy7c4xxPull(&c) != 0) return; if (len) { *cy7c4xx_buf_ptr = c; ++cy7c4xx_buf_ptr; --len; if (len == 0) { #if DEBUG if (usbfifo_debug_operation.dump_fifo_out == 1) { unsigned char l = cy7c4xx_buf_ptr-InDataPacket, i; unsigned char b[12]; putrsUSART("FIFO IN: '"); for (i=0;i<l;++i) { if (i != 0) { while (BusyUSART()); putcUSART(' '); } sprintf(b, "%02x", InDataPacket[i]); putsUSART(b); } sprintf(b, "' len=%3d\r\n", l); putsUSART(b); } if (usbfifo_debug_operation.fifo_loopback == 1) { unsigned char l = cy7c4xx_buf_ptr-InDataPacket, i; /* length of incoming packet _must_ not exceed the length of outgoing */ fifo9403aPush(l, 1); for (i=0;i<l;++i) fifo9403aPush(InDataPacket[i], 1); } #endif /* FIXME: use real ping-pong */ while (USBHandleBusy(UsbInDataHandle)); // should not loop, anyway ... UsbInDataHandle = USBGenWrite(USBGEN_DATA_EP_NUM, (BYTE*)&InDataPacket, cy7c4xx_buf_ptr-InDataPacket); while (USBHandleBusy(UsbInDataHandle)); // have to wait here as full ping-pong is not implemented // and thus we don't want data from FIFO override the data being sent here cy7c4xx_buf_ptr = InDataPacket; } } else { len = c; } }
void SMP_sendData(void) { /** * Send sampled data over USB * * Waits for a buffer to be ready to send and then sends it */ SMP_LAST_TRANSMISSION = 0; // write the data buffer to the USB if(!mUSBGenTxIsBusy()) { // wait for the send buffer to be ready to send while(!(SMP_BUFFER_STATE[SMP_SEND_BUFFER_NUM] & SMP_BUF_RTS)); // send it USBGenWrite((BYTE*)(SMP_BUFFER+(SMP_SEND_BUFFER_NUM*1024)),1024); // unset RTS for the previous buffer SMP_BUFFER_STATE[(SMP_SEND_BUFFER_NUM+SMP_NUM_BUFFERS-1)%SMP_NUM_BUFFERS] &= ~SMP_BUF_RTS; } else { // ERROR } // move to the next buffer SMP_SEND_BUFFER_NUM = (SMP_SEND_BUFFER_NUM + 1) % SMP_NUM_BUFFERS; }
/******************************************************************** * モニタコマンド受信と実行. ******************************************************************** */ void ProcessIO(void) { // 返答パケットが空であること、かつ、 // 処理対象の受信データがある. if((ToPcRdy == 0) && (USBHandleBusy(USBGenericOutHandle)==0) ) { //受信データがあれば、受信データを受け取る. memcpy64((char*)&PacketFromPC,(char*)OUTPacket); //次の読み込みを発行する. USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket ,USBGEN_EP_SIZE); PacketToPC.raw[0]=Cmd0; // CMD ECHOBACK //コマンドに対応する処理を呼び出す. if(Cmd0==HIDASP_PEEK) {cmd_peek();} // メモリー読み出し. else if(Cmd0==HIDASP_POKE) {cmd_poke();} // メモリー書き込み. else if(Cmd0==HIDASP_JMP) {cmd_exec();} // 実行. else if(Cmd0==HIDASP_TEST) {cmd_echo();} // 接続テスト. else if(Cmd0==HIDASP_GET_STRING){cmd_get_string();} else if(Cmd0==HIDASP_USER_CMD) {cmd_user_cmd();} else if(Cmd0==HIDASP_SET_MODE) {cmd_set_mode();} } // 必要なら、返答パケットをバルク転送(EP1)でホストPCに返却する. if( ToPcRdy ) { if(!USBHandleBusy(USBGenericInHandle)) { memcpy64(INPacket,(char*)&PacketToPC); USBGenericInHandle=USBGenWrite(USBGEN_EP_NUM,(BYTE*)INPacket,USBGEN_EP_SIZE); ToPcRdy = 0; if(poll_mode!=0) { if( USBHandleBusy(USBGenericOutHandle) ) {//コマンドが来ない限り送り続ける. make_report(); } } } } }
static void processUsbCommands(void) { #if defined(USB_POLLING) // Check bus status and service USB interrupts. USBDeviceTasks(); // Interrupt or polling method. If using polling, must call // this function periodically. This function will take care // of processing and responding to SETUP transactions // (such as during the enumeration process when you first // plug in). USB hosts require that USB devices should accept // and process SETUP packets in a timely fashion. Therefore, // when using polling, this function should be called // regularly (such as once every 1.8ms or faster** [see // inline code comments in usb_device.c for explanation when // "or faster" applies]) In most cases, the USBDeviceTasks() // function does not take very long to execute (ex: <100 // instruction cycles) before it returns. #endif // Note: The user application should not begin attempting to read/write over the USB // until after the device has been fully enumerated. After the device is fully // enumerated, the USBDeviceState will be set to "CONFIGURED_STATE". if ((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return; // As the device completes the enumeration process, the UsbCbInitEP() function will // get called. In this function, we initialize the user application endpoints (in this // example code, the user application makes use of endpoint 1 IN and endpoint 1 OUT). // The USBGenRead() function call in the UsbCbInitEP() function initializes endpoint 1 OUT // and "arms" it so that it can receive a packet of data from the host. Once the endpoint // has been armed, the host can then send data to it (assuming some kind of application software // is running on the host, and the application software tries to send data to the USB device). // If the host sends a packet of data to the endpoint 1 OUT buffer, the hardware of the SIE will // automatically receive it and store the data at the memory location pointed to when we called // USBGenRead(). Additionally, the endpoint handle (in this case UsbOutCmdHandle) will indicate // that the endpoint is no longer busy. At this point, it is safe for this firmware to begin reading // from the endpoint buffer, and processing the data. In this example, we have implemented a few very // simple commands. For example, if the host sends a packet of data to the endpoint 1 OUT buffer, with the // first byte = 0x80, this is being used as a command to indicate that the firmware should "Toggle LED(s)". if (!USBHandleBusy(UsbOutCmdHandle)) { // Check if the endpoint has received any data from the host. #if DEBUG unsigned char l = USBHandleGetLength(UsbOutCmdHandle); if (usbfifo_debug_operation.dump_usb_out == 1) { unsigned char b[16]; unsigned char i; putrsUSART("USB OUT: '"); for (i=0;i<l;++i) { if (i != 0) { while (BusyUSART()); putcUSART(' '); } sprintf(b, "%02x", OutCmdPacket[i]); putsUSART(b); } sprintf(b, "' len=%3d\r\n", l); putsUSART(b); } if (usbfifo_debug_operation.usb_loopback == 1) { unsigned char i; // Now check to make sure no previous attempts to send data to the host are still pending. If any attemps are still // pending, we do not want to write to the endpoint 1 IN buffer again, until the previous transaction is complete. // Otherwise the unsent data waiting in the buffer will get overwritten and will result in unexpected behavior. while (USBHandleBusy(UsbInCmdHandle)); for (i=0;i<l;++i) InCmdPacket[i] = OutCmdPacket[i]; // The endpoint was not "busy", therefore it is safe to write to the buffer and arm the endpoint. // The USBGenWrite() function call "arms" the endpoint (and makes the handle indicate the endpoint is busy). // Once armed, the data will be automatically sent to the host (in hardware by the SIE) the next time the // host polls the endpoint. Once the data is successfully sent, the handle (in this case UsbInCmdHandle) // will indicate the the endpoint is no longer busy. UsbInCmdHandle = USBGenWrite(USBGEN_CMD_EP_NUM, (BYTE*)&InCmdPacket, l); } #endif switch (OutCmdPacket[0]) { #if DEBUG case USBFIFO_CMD_DUMP_USB_OUT: usbfifo_debug_operation.dump_usb_out ^= 1; break; case USBFIFO_CMD_DUMP_FIFO_OUT: usbfifo_debug_operation.dump_fifo_out ^= 1; break; case USBFIFO_CMD_FIFO_LOOPBACK: usbfifo_debug_operation.fifo_loopback ^= 1; break; case USBFIFO_CMD_USB_LOOPBACK: usbfifo_debug_operation.usb_loopback ^= 1; break; #endif default: { unsigned char b[8]; putrsUSART("Unexpected cmd="); sprintf(b, "0x%2X\r\n", OutCmdPacket[0]); putsUSART(b); } break; } // Re-arm the OUT endpoint for the next packet: // The USBGenRead() function call "arms" the endpoint (and makes it "busy"). If the endpoint is armed, the SIE will // automatically accept data from the host, if the host tries to send a packet of data to the endpoint. Once a data // packet addressed to this endpoint is received from the host, the endpoint will no longer be busy, and the application // can read the data which will be sitting in the buffer. UsbOutCmdHandle = USBGenRead(USBGEN_CMD_EP_NUM, (BYTE*)&OutCmdPacket, USBGEN_EP_SIZE); } if (!USBHandleBusy(UsbOutDataHandle)) { #if USBGEN_EP_SIZE > FIFO_9403A_MAX_MSG_LEN #error "Transfer of more than FIFO_9403A_MAX_MSG_LEN not implemented" #endif unsigned char l = USBHandleGetLength(UsbOutDataHandle); unsigned char i; #if DEBUG if (usbfifo_debug_operation.dump_usb_out == 1) { unsigned char b[16]; putrsUSART("USB OUT: '"); for (i=0;i<l;++i) { if (i != 0) { while (BusyUSART()); putcUSART(' '); } sprintf(b, "%02x", OutDataPacket[i]); } sprintf(b, "' len=%3d\r\n", l); putsUSART(b); } if (usbfifo_debug_operation.usb_loopback == 1) { while (USBHandleBusy(UsbInDataHandle)); // ensure that FIFO data left the device for (i=0;i<l;++i) InDataPacket[i] = OutDataPacket[i]; /* FIXME: use real ping-pong */ UsbInDataHandle = USBGenWrite(USBGEN_DATA_EP_NUM, (BYTE*)&InDataPacket, l); while (USBHandleBusy(UsbInDataHandle)); // have to wait here as full ping-pong is not implemented // and thus we don't want data from FIFO override the data being sent here } #endif fifo9403aPush(l, 1); for (i=0;i<l;++i) fifo9403aPush(OutDataPacket[i], 1); UsbOutDataHandle = USBGenRead(USBGEN_DATA_EP_NUM, (BYTE*)&OutDataPacket, USBGEN_EP_SIZE); } }
void UsbSendResp(byte resp, byte *data) { MCT_t *pMct; byte i; byte *pData; byte paramNum; ushort temp; ulong tempL; pMct = &string[OUTPacket[USB_PACKET_STR]].mct[OUTPacket[USB_PACKET_MCT]-1]; INPacket[USB_PACKET_STR] = OUTPacket[USB_PACKET_STR]; INPacket[USB_PACKET_MCT] = OUTPacket[USB_PACKET_MCT]; INPacket[USB_PACKET_PID] = OUTPacket[USB_PACKET_PID]; INPacket[USB_PACKET_CMD] = resp; switch (resp) { case USB_RESP_NULL: // 0x80 INPacket[USB_PACKET_LEN] = 7; break; case USB_RESP_BAD_MSG: // 0x81 INPacket[USB_PACKET_LEN] = 9; INPacket[USB_PACKET_DATA + 0] = data[0]; INPacket[USB_PACKET_DATA + 1] = data[1]; break; case USB_RESP_GET_VSTRING: INPacket[USB_PACKET_LEN] = 27; for (i = 0; i < 20; i++) { INPacket[USB_PACKET_DATA + i] = versString[i]; } break; case USB_RESP_GET_CHAN: // 0xB3 INPacket[USB_PACKET_LEN] = 39; for (i = 0; i < 16; i++) { temp = pMct->chan[i]; INPacket[5 + 2*i] = (byte)(temp >> 8); INPacket[6 + 2*i] = (byte)temp; } break; case USB_RESP_GET_MIRRORS: // 0xC2 INPacket[USB_PACKET_LEN] = 19; INPacket[5] = pMct->mirror[MIRROR1].tracking; INPacket[6] = pMct->mirror[MIRROR1].sensors; temp = pMct->mirror[MIRROR1].m[MOTOR_A].mdeg100; INPacket[7] = (byte)(temp >> 8); INPacket[8] = (byte)temp; temp = pMct->mirror[MIRROR1].m[MOTOR_B].mdeg100; INPacket[9] = (byte)(temp >> 8); INPacket[10] = (byte)temp; INPacket[11] = pMct->mirror[MIRROR2].tracking; INPacket[12] = pMct->mirror[MIRROR2].sensors; temp = pMct->mirror[MIRROR2].m[MOTOR_A].mdeg100; INPacket[13] = (byte)(temp >> 8); INPacket[14] = (byte)temp; temp = pMct->mirror[MIRROR2].m[MOTOR_B].mdeg100; INPacket[15] = (byte)(temp >> 8); INPacket[16] = (byte)temp; break; case USB_RESP_GET_STRING: INPacket[USB_PACKET_LEN] = 9; INPacket[5] = string[OUTPacket[USB_PACKET_STR]].maxAddr; INPacket[6] = string[OUTPacket[USB_PACKET_STR]].state; break; case USB_RESP_FIELD_STATE: INPacket[USB_PACKET_LEN] = 9; INPacket[USB_PACKET_DATA] = fieldState; break; case USB_RESP_GET_FCE: INPacket[USB_PACKET_LEN] = 28; INPacket[USB_PACKET_DATA] = fieldInState; INPacket[USB_PACKET_DATA+1] = FCE_inputs; INPacket[USB_PACKET_DATA+2] = FCE_outputs; for (i = 0; i < 7; i++) { INPacket[USB_PACKET_DATA+3+2*i] = (byte)(ads1115[i] >> 8); INPacket[USB_PACKET_DATA+4+2*i] = (byte)ads1115[i]; } INPacket[USB_PACKET_DATA+17] = (byte)(fieldDNI >> 8); INPacket[USB_PACKET_DATA+18] = (byte)fieldDNI; INPacket[USB_PACKET_DATA+19] = (byte)(fceRTD >> 8); INPacket[USB_PACKET_DATA+20] = (byte)fceRTD; break; case USB_RESP_GET_RTU: INPacket[USB_PACKET_LEN] = 44; for (i = 0; i < 10; i++) { INPacket[USB_PACKET_DATA+0+4*i] = (byte)(rtuAddr[i] >> 8); INPacket[USB_PACKET_DATA+1+4*i] = (byte)rtuAddr[i]; INPacket[USB_PACKET_DATA+2+4*i] = (byte)(rtuData[i] >> 8); INPacket[USB_PACKET_DATA+3+4*i] = (byte)rtuData[i]; } break; case USB_RESP_SEND_MCT485: INPacket[USB_PACKET_LEN] = 7; break; case USB_RESP_GET_MCT485: INPacket[USB_PACKET_STR] = usb485String; INPacket[USB_PACKET_MCT] = usb485RxBuffer[MCT485_ADDR]; INPacket[USB_PACKET_LEN] = 7 + usb485RxLen; for (i = 0; i < usb485RxLen; i++) { INPacket[USB_PACKET_DATA + i] = usb485RxBuffer[i]; } usb485RxLen = 0; break; case USB_RESP_RTC: // 0xE6 INPacket[USB_PACKET_LEN] = 19; INPacket[USB_PACKET_DATA+0] = rtcSec; INPacket[USB_PACKET_DATA+1] = rtcMin; INPacket[USB_PACKET_DATA+2] = rtcHour; INPacket[USB_PACKET_DATA+3] = rtcDate; INPacket[USB_PACKET_DATA+4] = rtcMonth; INPacket[USB_PACKET_DATA+5] = rtcYear; INPacket[USB_PACKET_DATA+6] = (byte)(sfcPcbTemp >> 8); INPacket[USB_PACKET_DATA+7] = (byte)sfcPcbTemp; INPacket[USB_PACKET_DATA+8] = (byte)(sfcThermistor >> 8); INPacket[USB_PACKET_DATA+9] = (byte)sfcThermistor; INPacket[USB_PACKET_DATA+10] = (byte)(sfcHumidity >> 8); INPacket[USB_PACKET_DATA+11] = (byte)sfcHumidity; break; case USB_RESP_LOG: // 0xE7 INPacket[USB_PACKET_LEN] = 7; do { i = DataLogReadNext(&INPacket[INPacket[USB_PACKET_LEN]-2]); INPacket[USB_PACKET_LEN] += i; } while (INPacket[USB_PACKET_LEN] <= 55); break; case USB_RESP_DESICCANT: // 0xE8 INPacket[USB_PACKET_LEN] = 9; INPacket[USB_PACKET_DATA+0] = desiccantState; INPacket[USB_PACKET_DATA+1] = FCE_outputs & (FCE_OUT_FAN + FCE_OUT_VALVE + FCE_OUT_HEAT); break; case USB_RESP_SFC_PARAM: // 0xE9 paramNum = OUTPacket[USB_PACKET_DATA]; INPacket[USB_PACKET_DATA] = paramNum; INPacket[USB_PACKET_LEN] = 47; i = 0; while (i < 40) { INPacket[USB_PACKET_DATA+i+1] = (byte)(param[paramNum] >> 24); INPacket[USB_PACKET_DATA+i+2] = (byte)(param[paramNum] >> 16); INPacket[USB_PACKET_DATA+i+3] = (byte)(param[paramNum] >> 8); INPacket[USB_PACKET_DATA+i+4] = (byte)(param[paramNum]); i += 4; paramNum++; } break; case USB_RESP_MEMORY: // 0xEA INPacket[USB_PACKET_DATA+0] = OUTPacket[USB_PACKET_DATA+0]; INPacket[USB_PACKET_DATA+1] = OUTPacket[USB_PACKET_DATA+1]; INPacket[USB_PACKET_DATA+2] = OUTPacket[USB_PACKET_DATA+2]; INPacket[USB_PACKET_DATA+3] = OUTPacket[USB_PACKET_DATA+3]; INPacket[USB_PACKET_DATA+4] = data[4]; INPacket[USB_PACKET_LEN] = 7+4+1+16; i = 0; tempL = ((ulong)OUTPacket[USB_PACKET_DATA+0]) << 24; tempL |= (((ulong)OUTPacket[USB_PACKET_DATA+1]) << 16); tempL |= (((ulong)OUTPacket[USB_PACKET_DATA+2]) << 8); tempL |= (ulong)OUTPacket[USB_PACKET_DATA+3]; pData = (byte *)tempL; while (i < 16) { INPacket[USB_PACKET_DATA+i+5] = *pData++; i++; } break; case USB_RESP_TEST: INPacket[USB_PACKET_LEN] = 7; break; default: break; } // switch() USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM, INPacket, INPacket[USB_PACKET_LEN]); } // UsbSendResp()
/****************************************************************************** * Function: void ServiceRequests(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: USB traffic can be generated * * Overview: This function takes in the commands from the PC from the * application and executes the commands requested * * Note: None *****************************************************************************/ void ServiceRequests(void) { BYTE index; //Check to see if data has arrived if(!USBHandleBusy(USBGenericOutHandle)) { //if the handle is no longer busy then the last //transmission is complete counter = 0; INPacket.CMD=OUTPacket.CMD; INPacket.len=OUTPacket.len; //process the command switch(OUTPacket.CMD) { case READ_VERSION: //dataPacket._byte[1] is len INPacket._byte[2] = MINOR_VERSION; INPacket._byte[3] = MAJOR_VERSION; counter=0x04; break; case ID_BOARD: counter = 0x01; if(OUTPacket.ID == 0) { mLED_3_Off();mLED_4_Off(); } else if(OUTPacket.ID == 1) { mLED_3_Off();mLED_4_On(); } else if(OUTPacket.ID == 2) { mLED_3_On();mLED_4_Off(); } else if(OUTPacket.ID == 3) { mLED_3_On();mLED_4_On(); } else counter = 0x00; break; case UPDATE_LED: #if defined(PIC18F87J50_PIM) || defined(PIC18F46J50_PIM) || defined(PIC18F47J53_PIM) blinkStatusValid = FALSE; #endif // LED1 & LED2 are used as USB event indicators. if(OUTPacket.led_num == 3) { if(OUTPacket.led_status) { mLED_3_On(); } else { mLED_3_Off(); } counter = 0x01; }//end if else if(OUTPacket.led_num == 4) { if(OUTPacket.led_status) { mLED_4_On(); } else { mLED_4_Off(); } counter = 0x01; }//end if else break; case SET_TEMP_REAL: temp_mode = TEMP_REAL_TIME; ResetTempLog(); counter = 0x01; break; case RD_TEMP: if(AcquireTemperature()) { INPacket._byte[1] = temperature.v[0]; INPacket._byte[2] = temperature.v[1]; counter=0x03; }//end if break; case SET_TEMP_LOGGING: temp_mode = TEMP_LOGGING; ResetTempLog(); counter=0x01; break; case RD_TEMP_LOGGING: counter = (valid_temp<<1)+2; // Update count in byte INPacket.len = (valid_temp<<1); for(index = valid_temp; index > 0; index--) { if(pTemp == 0) pTemp = 29; else pTemp--; INPacket._word[index] = temp_data[pTemp]; }//end for ResetTempLog(); // Once read, log will restart break; case RD_POT: { WORD_VAL w; mInitPOT(); w = ReadPOT(); INPacket._byte[1] = w.v[0]; INPacket._byte[2] = w.v[1]; counter=0x03; } break; case RESET: Reset(); break; default: break; }//end switch() if(counter != 0) { if(!USBHandleBusy(USBGenericInHandle)) { USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,counter); } }//end if //Re-arm the OUT endpoint for the next packet USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE); }//end if }//end ServiceRequests
/****************************************************************************** * Function: void ProcessIO(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This function is a place holder for other user routines. * It is a mixture of both USB and non-USB tasks. * * Note: None *****************************************************************************/ void ProcessIO(void) { //Blink the LEDs according to the USB device status, but only do so if the PC application isn't connected and controlling the LEDs. if(blinkStatusValid) { BlinkUSBStatus(); } //User Application USB tasks below. //Note: The user application should not begin attempting to read/write over the USB //until after the device has been fully enumerated. After the device is fully //enumerated, the USBDeviceState will be set to "CONFIGURED_STATE". if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return; //As the device completes the enumeration process, the USBCBInitEP() function will //get called. In this function, we initialize the user application endpoints (in this //example code, the user application makes use of endpoint 1 IN and endpoint 1 OUT). //The USBGenRead() function call in the USBCBInitEP() function initializes endpoint 1 OUT //and "arms" it so that it can receive a packet of data from the host. Once the endpoint //has been armed, the host can then send data to it (assuming some kind of application software //is running on the host, and the application software tries to send data to the USB device). //If the host sends a packet of data to the endpoint 1 OUT buffer, the hardware of the SIE will //automatically receive it and store the data at the memory location pointed to when we called //USBGenRead(). Additionally, the endpoint handle (in this case USBGenericOutHandle) will indicate //that the endpoint is no longer busy. At this point, it is safe for this firmware to begin reading //from the endpoint buffer, and processing the data. In this example, we have implemented a few very //simple commands. For example, if the host sends a packet of data to the endpoint 1 OUT buffer, with the //first byte = 0x80, this is being used as a command to indicate that the firmware should "Toggle LED(s)". if(!USBHandleBusy(USBGenericOutHandle)) //Check if the endpoint has received any data from the host. { switch(OUTPacket[0]) //Data arrived, check what kind of command might be in the packet of data. { case 0x80: //Toggle LED(s) command from PC application. blinkStatusValid = FALSE; //Disable the regular LED blink pattern indicating USB state, PC application is controlling the LEDs. if(mGetLED_1() == mGetLED_2()) { mLED_1_Toggle(); mLED_2_Toggle(); } else { mLED_1_On(); mLED_2_On(); } break; case 0x81: //Get push button state command from PC application. INPacket[0] = 0x81; //Echo back to the host PC the command we are fulfilling in the first byte. In this case, the Get Pushbutton State command. // if(sw2 == 1) //pushbutton not pressed, pull up resistor on circuit board is pulling the PORT pin high if (UserSW == 1) { INPacket[1] = 0x01; } else //sw2 must be == 0, pushbutton is pressed and overpowering the pull up resistor { INPacket[1] = 0x00; } //Now check to make sure no previous attempts to send data to the host are still pending. If any attemps are still //pending, we do not want to write to the endpoint 1 IN buffer again, until the previous transaction is complete. //Otherwise the unsent data waiting in the buffer will get overwritten and will result in unexpected behavior. if(!USBHandleBusy(USBGenericInHandle)) { //The endpoint was not "busy", therefore it is safe to write to the buffer and arm the endpoint. //The USBGenWrite() function call "arms" the endpoint (and makes the handle indicate the endpoint is busy). //Once armed, the data will be automatically sent to the host (in hardware by the SIE) the next time the //host polls the endpoint. Once the data is successfully sent, the handle (in this case USBGenericInHandle) //will indicate the the endpoint is no longer busy. USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,USBGEN_EP_SIZE); } break; } //Re-arm the OUT endpoint for the next packet: //The USBGenRead() function call "arms" the endpoint (and makes it "busy"). If the endpoint is armed, the SIE will //automatically accept data from the host, if the host tries to send a packet of data to the endpoint. Once a data //packet addressed to this endpoint is received from the host, the endpoint will no longer be busy, and the application //can read the data which will be sitting in the buffer. USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE); } }//end ProcessIO
void ProcessIO(void) { char oldPGDtris; char PIN; static byte counter=0; int nBytes; unsigned long address; // When the device is plugged in, the leds give the numbers 1, 2, 3, 4, 5. //After configured state, the leds are controlled by the next lines in this function if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) { BlinkUSBStatus(); return; } nBytes=USBGenRead((byte*)input_buffer,64); if(nBytes>0) { switch(input_buffer[0]) { case CMD_ERASE: setLeds(LEDS_ON | LEDS_WR); output_buffer[0]=bulk_erase(picfamily,pictype,input_buffer[1]); counter=1; setLeds(LEDS_ON); break; case CMD_READ_ID: setLeds(LEDS_ON | LEDS_RD); switch(picfamily) { case PIC24: case dsPIC30: read_code(picfamily,pictype,0xFF0000,(unsigned char*)output_buffer,2,3); break; case PIC18: case PIC18J: case PIC18K: read_code(picfamily,pictype,0x3FFFFE,(unsigned char*)output_buffer,2,3); //devid is at location 0x3ffffe for PIC18 devices break; case PIC16: set_vdd_vpp(picfamily, pictype, 0); read_code(picfamily,pictype,0x2006,(unsigned char*)output_buffer,2,3); //devid is at location 0x2006 for PIC16 devices break; } counter=2; setLeds(LEDS_ON); break; case CMD_WRITE_CODE: setLeds(LEDS_ON | LEDS_WR); address=((unsigned long)input_buffer[2])<<16| ((unsigned long)input_buffer[3])<<8| ((unsigned long)input_buffer[4]); output_buffer[0]=write_code(picfamily,pictype,address, (unsigned char*)(input_buffer+6),input_buffer[1],input_buffer[5]); counter=1; setLeds(LEDS_ON); break; case CMD_READ_CODE: setLeds(LEDS_ON | LEDS_RD); address=((unsigned long)input_buffer[2])<<16| ((unsigned long)input_buffer[3])<<8| ((unsigned long)input_buffer[4]); PIN=read_code(picfamily,pictype,address,(unsigned char*)output_buffer,input_buffer[1],input_buffer[5]); if(PIN==3)output_buffer[0]=0x3; counter=input_buffer[1]; setLeds(LEDS_ON); break; case CMD_WRITE_DATA: setLeds(LEDS_ON | LEDS_WR); address=((unsigned long)input_buffer[2])<<16| ((unsigned long)input_buffer[3])<<8| ((unsigned long)input_buffer[4]); output_buffer[0]=write_data(picfamily,pictype,address, (unsigned char*)(input_buffer+6),input_buffer[1],input_buffer[5]); counter=1; setLeds(LEDS_ON); break; case CMD_READ_DATA: setLeds(LEDS_ON | LEDS_RD); address=((unsigned long)input_buffer[2])<<16| ((unsigned long)input_buffer[3])<<8| ((unsigned long)input_buffer[4]); read_data(picfamily,pictype,address,(unsigned char*)output_buffer,input_buffer[1],input_buffer[5]); counter=input_buffer[1]; setLeds(LEDS_ON); break; case CMD_WRITE_CONFIG: setLeds(LEDS_ON | LEDS_WR); address=((unsigned long)input_buffer[2])<<16| ((unsigned long)input_buffer[3])<<8| ((unsigned long)input_buffer[4]); output_buffer[0]=write_config_bits(picfamily, pictype, address, (unsigned char*)(input_buffer+6),input_buffer[1],input_buffer[5]); counter=1; setLeds(LEDS_ON); break; case CMD_SET_PICTYPE: output_buffer[0]=set_pictype(input_buffer+1); //output_buffer[0]=1; //Ok counter=1; setLeds(LEDS_ON); break; case CMD_FIRMWARE_VERSION: strcpypgm2ram((char*)output_buffer,(const far rom char*)upp_version); counter=18; setLeds(LEDS_ON); break; case CMD_DEBUG: setLeds(LEDS_ON | LEDS_WR | LEDS_RD); switch(input_buffer[1]) { case 0: set_vdd_vpp(dsP30F, dsPIC30, 1); output_buffer[0]=1; counter=1; break; case 1: set_vdd_vpp(dsP30F, dsPIC30, 0); output_buffer[0]=1; counter=1; break; case 2: dspic_send_24_bits(((unsigned long)input_buffer[2])| ((unsigned long)input_buffer[3])<<8| ((unsigned long)input_buffer[4])<<16); output_buffer[0]=1; counter=1; break; case 3: nBytes = dspic_read_16_bits(1); output_buffer[0]=(unsigned char)nBytes; output_buffer[1]=(unsigned char)(nBytes>>8); counter=2; break; } break; case CMD_GET_PIN_STATUS: switch(input_buffer[1]) { case SUBCMD_PIN_PGC: if((!TRISPGC_LOW)&&(!PGC_LOW)) //3.3V levels { if(PGC) output_buffer[0] = PIN_STATE_3_3V; else output_buffer[0] = PIN_STATE_0V; } else //5V levels { if(PGC) output_buffer[0] = PIN_STATE_5V; else output_buffer[0] = PIN_STATE_0V; } counter=1; break; case SUBCMD_PIN_PGD: if(TRISPGD)//PGD is input { if(PGD_READ) output_buffer[0] = PIN_STATE_5V; else output_buffer[0] = PIN_STATE_0V; } else { if((!TRISPGD_LOW)&&(!PGD_LOW)) //3.3V levels { if(PGD) output_buffer[0] = PIN_STATE_3_3V; else output_buffer[0] = PIN_STATE_0V; } else //5V levels { if(PGD) output_buffer[0] = PIN_STATE_5V; else output_buffer[0] = PIN_STATE_0V; } } counter=1; break; case SUBCMD_PIN_VDD: if(VDD) output_buffer[0] = PIN_STATE_FLOAT; else output_buffer[0] = PIN_STATE_5V; counter = 1; break; case SUBCMD_PIN_VPP: counter=1; if(!VPP){output_buffer[0] = PIN_STATE_12V;break;} if(VPP_RST){output_buffer[0] = PIN_STATE_0V;break;} if(VPP_RUN){output_buffer[0] = PIN_STATE_5V;break;} output_buffer[0] = PIN_STATE_FLOAT; break; case SUBCMD_PIN_VPP_VOLTAGE: ReadAdc(output_buffer); counter=2; break; default: output_buffer[0]=3; counter=1; break; } break; case CMD_SET_PIN_STATUS: switch(input_buffer[1]) { case SUBCMD_PIN_PGC: switch(input_buffer[2]) { case PIN_STATE_0V: TRISPGC = 0; PGC = 0; TRISPGC_LOW = 1; PGC_LOW = 0; output_buffer[0]=1;//ok break; case PIN_STATE_3_3V: TRISPGC = 0; PGC = 1; TRISPGC_LOW = 0; PGC_LOW = 0; output_buffer[0]=1;//ok break; case PIN_STATE_5V: TRISPGC = 0; PGC = 1; TRISPGC_LOW = 1; PGC_LOW = 0; output_buffer[0]=1;//ok break; default: output_buffer[0]=3; break; } break; case SUBCMD_PIN_PGD: switch(input_buffer[2]) { case PIN_STATE_0V: TRISPGD = 0; PGD = 0; TRISPGD_LOW = 1; PGD_LOW = 0; output_buffer[0]=1;//ok break; case PIN_STATE_3_3V: TRISPGD = 0; PGD = 1; TRISPGD_LOW = 0; PGD_LOW = 0; output_buffer[0]=1;//ok break; case PIN_STATE_5V: TRISPGD = 0; PGD = 1; TRISPGD_LOW = 1; PGD_LOW = 0; output_buffer[0]=1;//ok break; case PIN_STATE_INPUT: TRISPGD_LOW = 1; TRISPGD = 1; output_buffer[0]=1;//ok break; default: output_buffer[0]=3; break; } break; case SUBCMD_PIN_VDD: switch(input_buffer[2]) { case PIN_STATE_5V: VDD = 0; output_buffer[0]=1; break; case PIN_STATE_FLOAT: VDD = 1; output_buffer[0]=1; break; default: output_buffer[0]=3; break; } break; case SUBCMD_PIN_VPP: switch(input_buffer[2]) { case PIN_STATE_0V: VPP = 1; VPP_RST = 1; VPP_RUN = 0; output_buffer[0]=1;//ok break; case PIN_STATE_5V: VPP = 1; VPP_RST = 0; VPP_RUN = 1; output_buffer[0]=1;//ok break; case PIN_STATE_12V: VPP = 0; VPP_RST = 0; VPP_RUN = 0; output_buffer[0]=1;//ok break; case PIN_STATE_FLOAT: VPP = 1; VPP_RST = 0; VPP_RUN = 0; output_buffer[0]=1;//ok break; default: output_buffer[0]=3; break; } break; default: output_buffer[0]=3; } counter=1; break; } } if(counter != 0) { if(!mUSBGenTxIsBusy()) USBGenWrite((byte*)&output_buffer,counter); counter=0; } }//end ProcessIO
/****************************************************************************** * Function: void ServiceRequests(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: USB traffic can be generated * * Overview: This function takes in the commands from the PC from the * application and executes the commands requested * * Note: None *****************************************************************************/ void ServiceRequests(void) { BYTE index; //Check to see if data has arrived if(!USBHandleBusy(USBGenericOutHandle)) { //if the handle is no longer busy then the last //transmission is complete counter = 0; INPacket.CMD=OUTPacket.CMD; INPacket.len=OUTPacket.len; //process the command switch(OUTPacket.CMD) { case READ_VERSION: //dataPacket._byte[1] is len INPacket._byte[2] = MINOR_VERSION; INPacket._byte[3] = MAJOR_VERSION; counter=0x04; break; case RD_SERIAL: { //***********Case to read the serial number of the pedalog device**********// INPacket._byte[1] = serial_str[0]; INPacket._byte[2] = serial_str[1]; INPacket._byte[3] = serial_str[2]; INPacket._byte[4] = serial_str[3]; counter=0x5; // This counter must be equal to the size of the data sent plus 1 } break; case RD_VOLTS: //***********Case to read the voltage when 0x40 sent via USB**********// // Voltage is a string XX.X INPacket._byte[1] = VoltStr[0]; INPacket._byte[2] = VoltStr[1]; INPacket._byte[3] = VoltStr[2]; INPacket._byte[4] = VoltStr[3]; counter=0x5; // This counter must be equal to the size of the data sent plus 1 break; case RD_AMPS: { //***********Case to read the current when 0x41 sent via USB**********// // Current is a string XX.XX INPacket._byte[1] = I_out_Str[0]; INPacket._byte[2] = I_out_Str[1]; INPacket._byte[3] = I_out_Str[2]; INPacket._byte[4] = I_out_Str[3]; INPacket._byte[5] = I_out_Str[4]; counter=0x6; // This counter must be equal to the size of the data sent plus 1 } break; case RD_POWER: { //***********Case to read the power when 0x42 sent via USB**********// // Power is a string XXX.X INPacket._byte[1] = P_O_Str[0]; INPacket._byte[2] = P_O_Str[1]; INPacket._byte[3] = P_O_Str[2]; INPacket._byte[4] = P_O_Str[3]; INPacket._byte[5] = P_O_Str[4]; counter=0x6; // This counter must be equal to the size of the data sent plus 1 } break; case RD_DATA: { //***********Case to read back all the data when 0x43 sent via USB**********// INPacket._byte[1] = VoltStr[0]; INPacket._byte[2] = VoltStr[1]; INPacket._byte[3] = VoltStr[2]; INPacket._byte[4] = VoltStr[3]; INPacket._byte[5] = I_out_Str[0]; INPacket._byte[6] = I_out_Str[1]; INPacket._byte[7] = I_out_Str[2]; INPacket._byte[8] = I_out_Str[3]; INPacket._byte[9] = I_out_Str[4]; INPacket._byte[10] = P_O_Str[0]; INPacket._byte[11] = P_O_Str[1]; INPacket._byte[12] = P_O_Str[2]; INPacket._byte[13] = P_O_Str[3]; INPacket._byte[14] = P_O_Str[4]; INPacket._byte[15] = E_O_Str_disp[0]; INPacket._byte[16] = E_O_Str_disp[1]; INPacket._byte[17] = E_O_Str_disp[2]; INPacket._byte[18] = E_O_Str_disp[3]; INPacket._byte[19] = E_O_Str_disp[4]; INPacket._byte[20] = E_O_Str_disp[5]; INPacket._byte[21] = E_O_Str_disp[6]; INPacket._byte[22] = P_Max_Str[0]; // MAX POWER INPacket._byte[23] = P_Max_Str[1]; INPacket._byte[24] = P_Max_Str[2]; INPacket._byte[25] = P_Max_Str[3]; INPacket._byte[26] = P_Max_Str[4]; INPacket._byte[27] = P_Ave_Str[0]; // AVERAGE POWER INPacket._byte[28] = P_Ave_Str[1]; INPacket._byte[29] = P_Ave_Str[2]; INPacket._byte[30] = P_Ave_Str[3]; INPacket._byte[31] = P_Ave_Str[4]; INPacket._byte[32] = total_run_time_s_str[0]; // TIME TAKEN INPacket._byte[33] = total_run_time_s_str[1]; INPacket._byte[34] = total_run_time_s_str[2]; INPacket._byte[35] = total_run_time_s_str[3]; INPacket._byte[36] = total_run_time_s_str[4]; INPacket._byte[37] = total_run_time_s_str[5]; INPacket._byte[38] = total_run_time_s_str[6]; INPacket._byte[39] = total_run_time_s_str[7]; INPacket._byte[40] = total_run_time_s_str[0]; // TIME TAKEN INPacket._byte[41] = total_run_time_s_str[1]; INPacket._byte[42] = total_run_time_s_str[2]; INPacket._byte[43] = total_run_time_s_str[3]; INPacket._byte[44] = total_run_time_s_str[4]; INPacket._byte[45] = total_run_time_s_str[5]; INPacket._byte[46] = total_run_time_s_str[6]; INPacket._byte[47] = total_run_time_s_str[7]; INPacket._byte[48] = serial_str[0]; INPacket._byte[49] = serial_str[1]; INPacket._byte[50] = serial_str[2]; INPacket._byte[51] = serial_str[3]; counter=52; // This counter must be equal to the size of the data sent plus 1 } break; case RESET: Reset(); break; default: Nop(); break; }//end switch() if(counter != 0) { if(!USBHandleBusy(USBGenericInHandle)) { USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,counter); } }//end if //Re-arm the OUT endpoint for the next packet USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE); }//end if }//end ServiceRequests
/****************************************************************************** * Function: void ProcessIO(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This function is a place holder for other user * routines. It is a mixture of both USB and * non-USB tasks. * * Note: None *****************************************************************************/ void ProcessIO(void) { //Blink the LEDs according to the USB device status, but only do so if the PC application isn't connected and controlling the LEDs. if(blinkStatusValid) { BlinkUSBStatus(); } // Check if the device is enumerated and is ready to accept commands. if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return; if(!USBHandleBusy(USBGenericOutHandle)) //Check if the endpoint has received any data from the host. { switch(OUTPacket[0]) //Data arrived, check what kind of command might be in the packet of data. { case 'A': if(!USBHandleBusy(USBGenericInHandle)) { if(OUTPacket[1] == '0') { ADCON0bits.ADON = 0; // Switch off ADC. ADCON0 &= 0xF0; // Select channel 0 ADCON0bits.ADON = 1; ADCON0bits.GO = 1; // Wait if conversion is happening while(ADCON0bits.DONE); INPacket[0] = ADRESL; INPacket[1] = ADRESH; } else if(OUTPacket[1] == '1') { ADCON0bits.ADON = 0; // Switch off ADC. ADCON0 &= 0xF0; // Select channel ADCON0bits.CHS0 = 1; ADCON0bits.ADON = 1; ADCON0bits.GO = 1; // Wait if conversion is happening while(ADCON0bits.DONE); INPacket[0] = ADRESL; INPacket[1] = ADRESH; } USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,USBGEN_EP_SIZE); } break; case 0x80: //Toggle LED(s) command from PC application. blinkStatusValid = FALSE; //Disable the regular LED blink pattern indicating USB state, PC application is controlling the LEDs. if(mGetLED_1() == mGetLED_2()) { mLED_1_Toggle(); mLED_2_Toggle(); } else { mLED_1_On(); mLED_2_On(); } break; case 0x81: //Get push button state command from PC application. if(!USBHandleBusy(USBGenericInHandle)) { //The endpoint was not "busy", therefore it is safe to write to the buffer and arm the endpoint. INPacket[0] = 0x81; //Echo back to the host PC the command we are fulfilling in the first byte. In this case, the Get Pushbutton State command. if(sw2 == 1) //pushbutton not pressed, pull up resistor on circuit board is pulling the PORT pin high { INPacket[1] = 0x01; } else //sw2 must be == 0, pushbutton is pressed and overpowering the pull up resistor { INPacket[1] = 0x00; } // Arm back the handle. USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,USBGEN_EP_SIZE); } break; } USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE); } }//end ProcessIO
void ServiceRequests( void ) { BYTE num_return_bytes; // Number of bytes to return in response to received command. BYTE cmd; // Store the command in the received packet. // Process packets received through the primary endpoint. if ( !USBHandleBusy( OutHandle[OutIndex] ) ) { num_return_bytes = 0; // Initially, assume nothing needs to be returned. // Got a packet, so start getting another packet while we process this one. OutPacket = &OutBuffer[OutIndex]; // Store pointer to just-received packet. OutPacketLength = USBHandleGetLength( OutHandle[OutIndex] ); // Store length of received packet. cmd = OutPacket->cmd; blink_counter = NUM_ACTIVITY_BLINKS; // Blink the LED whenever a USB transaction occurs. switch ( cmd ) // Process the contents of the packet based on the command byte. { case ID_BOARD_CMD: // Blink the LED in order to identify the board. blink_counter = 50; InPacket->cmd = cmd; num_return_bytes = 1; break; case INFO_CMD: // memcpy( ( void * )( (BYTE *)InPacket ), (void *)&sdBuf, sizeof( sdBuf ) ); InPacket->_dword[0] = numBlocks; InPacket->_word[2] = rdBlockSize; InPacket->_word[3] = wrBlockSize; InPacket->_word[4] = eraseSize; num_return_bytes = 16; break; // Return a packet with information about this USB interface device. InPacket->cmd = cmd; memcpypgm2ram( ( void * )( (BYTE *)InPacket + 1 ), (const rom void *)&device_info, sizeof( DEVICE_INFO ) ); // InPacket->device_info.checksum = calc_checksum( (CHAR8 *)InPacket, sizeof( DEVICE_INFO ) ); num_return_bytes = sizeof( DEVICE_INFO ) + 1; // Return information stored in packet. break; case READ_EEDATA_CMD: InPacket->cmd = OutPacket->cmd; for(buffer_cntr=0; buffer_cntr < OutPacket->len; buffer_cntr++) { InPacket->data[buffer_cntr] = ReadEeprom((BYTE)OutPacket->ADR.pAdr + buffer_cntr); } num_return_bytes = buffer_cntr + 5; break; case WRITE_EEDATA_CMD: InPacket->cmd = OutPacket->cmd; for(buffer_cntr=0; buffer_cntr < OutPacket->len; buffer_cntr++) { WriteEeprom((BYTE)OutPacket->ADR.pAdr + buffer_cntr, OutPacket->data[buffer_cntr]); } num_return_bytes = 1; break; case RESET_CMD: // When resetting, make sure to drop the device off the bus // for a period of time. Helps when the device is suspended. UCONbits.USBEN = 0; lcntr = 0xFFFF; for(lcntr = 0xFFFF; lcntr; lcntr--) ; Reset(); break; default: num_return_bytes = 0; break; } /* switch */ // This command packet has been handled, so get another. OutHandle[OutIndex] = USBGenRead( USBGEN_EP_NUM, (BYTE *)&OutBuffer[OutIndex], USBGEN_EP_SIZE ); OutIndex ^= 1; // Point to next ping-pong buffer. // Packets of data are returned to the PC here. // The counter indicates the number of data bytes in the outgoing packet. if ( num_return_bytes != 0U ) { InHandle[InIndex] = USBGenWrite( USBGEN_EP_NUM, (BYTE *)InPacket, num_return_bytes ); // Now send the packet. InIndex ^= 1; while ( USBHandleBusy( InHandle[InIndex] ) ) { ; // Wait until transmitter is not busy. } InPacket = &InBuffer[InIndex]; } } } /* ServiceRequests */
/** * Check for incoming data in the USB buffer. If found, process it and * fill the USB buffer with data to be returned to the USB host. */ void ServiceRequests(void) { uint32_t rate; if(USBGenRead((byte*)&dataPacket,sizeof(dataPacket))) { // Pointer to the data packet uint8_t* usbptr = dataPacket._byte; uint8_t* usbcmd = usbptr; uint8_t* usblen = usbptr + 1; usbptr += 2; // Points to beginning of payload // When writing data to the buffer, usbptr must always // point to the next free byte in the buffer. // Switch on the command byte of the USB packet we got from the PC switch(dataPacket.CMD) { case READ_VERSION: *usbptr++ = MINOR_VERSION; *usbptr++ = MAJOR_VERSION; break; case LOGIC_GET_SRATE: rate = getSampleRate(); *usbptr++ = (rate >> 24) & 0xFF; *usbptr++ = (rate >> 16) & 0xFF; *usbptr++ = (rate >> 8) & 0xFF; *usbptr++ = rate & 0xFF; // Returned is like [CMD, 0x04, MSB, {}, {}, LSB] break; case LOGIC_CONFIG: // Firstly configure the analyser options if(!logicConfig(*usbptr)) { *usbcmd = LOGIC_ERROR; *usbptr++ = ERROR_INVALID_CONFIG; break; } // Now the sample rate if(!setSampleRate((uint32_t*)(usbptr+1))) { *usbcmd = LOGIC_ERROR; *usbptr++ = ERROR_INVALID_SAMPLE_RATE; break; } // And finally the number of samples if(!setSampleNumber((uint32_t*)(usbptr+5))) { *usbcmd = LOGIC_ERROR; *usbptr++ = ERROR_INVALID_SAMPLE_NUMBER; break; } // Return 3 bytes, payload is '1' for success [CMD, 0x03, 0x01] *usbptr++ = 0x01; break; case LOGIC_ARM: // return [CMD, LEN, RESULT] logicStart(); *usbptr++ = 0x01; break; case LOGIC_POLL: // return [POLL, LEN, STATE] *usbptr++ = getLogicState(); if(getLogicState() == LOGIC_INPROGRESS) { *(uint32_t*)usbptr = writeptr; usbptr += 4; } break; case LOGIC_DATA: if(getLogicState() == LOGIC_END) { usbptr = fillUSBBuffer(usbptr); break; } else if(getLogicState() == LOGIC_END_DATA) { *usbcmd = LOGIC_ERROR; *usbptr++ = ERROR_END_OF_DATA; break; } else { *usbcmd = LOGIC_ERROR; *usbptr++ = ERROR_DATA_UNAVAILABLE; break; } // The following command breaks the the command/response // protocol defined for the Logic Analyser, in order that they be // back compatible with the provided example PC interface. // (They are missing length field). case BLINK_LED_COMMAND: // [0xEE, Onstate] LATDbits.LATD1 = *++usbcmd; break; case GET_ADC_COMMAND: // [0xED. 8-bit data] *usbptr++ = _calcPrescaler(1000UL); break; case LOGIC_RESET: logicReset(); *usbptr++ = 0x01; break; case PING: break; case RESET: Reset(); break; default: // We didn't understand the command the PC sent, so error *usbcmd = LOGIC_ERROR; *usbptr++ = ERROR_CMD_NOT_FOUND; break; } // Calculate the length of the data in the transmit buffer *usblen = usbptr - usbcmd; // If we've put data into the send buffer, then transmit if(*usblen != 0 && !mUSBGenTxIsBusy()) USBGenWrite((byte*)&dataPacket,*usblen); }