Exemplo n.º 1
0
char ButtonState(void)
{
  char          ButtonFace;
  ButtonFace = 0x00;
  if (BUTTON_IsPressed(BUTTON_S3)) ButtonFace = 0x01;
  if (BUTTON_IsPressed(BUTTON_S6)) ButtonFace = 0x02;
  if (BUTTON_IsPressed(BUTTON_S5)) ButtonFace = 0x04;
  if (BUTTON_IsPressed(BUTTON_S4)) ButtonFace = 0x08;
  return ButtonFace;
}
/*********************************************************************
* Function: void APP_DeviceCustomHIDTasks(void);
*
* Overview: Keeps the Custom HID demo running.
*
* PreCondition: The demo should have been initialized and started via
*   the APP_DeviceCustomHIDInitialize() and APP_DeviceCustomHIDStart() demos
*   respectively.
*
* Input: None
*
* Output: None
*
********************************************************************/
void APP_DeviceCustomHIDTasks()
{   
    //Check if we have received an OUT data packet from the host
    if(HIDRxHandleBusy(USBOutHandle) == false)
    {   
        //We just received a packet of data from the USB host.
        //Check the first uint8_t of the packet to see what command the host
        //application software wants us to fulfill.
        switch(ReceivedDataBuffer[0])				//Look at the data the host sent, to see what kind of application specific command it sent.
        {
            case COMMAND_TOGGLE_LED:  //Toggle LEDs command
                LED_Toggle(LED_USB_DEVICE_HID_CUSTOM);
                break;
            case COMMAND_GET_BUTTON_STATUS:  //Get push button state
                //Check to make sure the endpoint/buffer is free before we modify the contents
                if(!HIDTxHandleBusy(USBInHandle))
                {
                    ToSendDataBuffer[0] = 0x81;				//Echo back to the host PC the command we are fulfilling in the first uint8_t.  In this case, the Get Pushbutton State command.
                    if(BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_CUSTOM) == false)	//pushbutton not pressed, pull up resistor on circuit board is pulling the PORT pin high
                    {
                            ToSendDataBuffer[1] = 0x01;
                    }
                    else									//sw3 must be == 0, pushbutton is pressed and overpowering the pull up resistor
                    {
                            ToSendDataBuffer[1] = 0x00;
                    }
                    //Prepare the USB module to send the data packet to the host
                    USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ToSendDataBuffer[0],64);
                }
                break;

            case COMMAND_READ_POTENTIOMETER:	//Read POT command.  Uses ADC to measure an analog voltage on one of the ANxx I/O pins, and returns the result to the host
                {
                    uint16_t pot;

                    //Check to make sure the endpoint/buffer is free before we modify the contents
                    if(!HIDTxHandleBusy(USBInHandle))
                    {
                        //Use ADC to read the I/O pin voltage.  See the relevant HardwareProfile - xxxxx.h file for the I/O pin that it will measure.
                        //Some demo boards, like the PIC18F87J50 FS USB Plug-In Module board, do not have a potentiometer (when used stand alone).
                        //This function call will still measure the analog voltage on the I/O pin however.  To make the demo more interesting, it
                        //is suggested that an external adjustable analog voltage should be applied to this pin.

                        pot = ADC_Read10bit(ADC_CHANNEL_POTENTIOMETER);

                        ToSendDataBuffer[0] = 0x37;  	//Echo back to the host the command we are fulfilling in the first uint8_t.  In this case, the Read POT (analog voltage) command.
                        ToSendDataBuffer[1] = (uint8_t)pot; //LSB
                        ToSendDataBuffer[2] = pot >> 8;     //MSB


                        //Prepare the USB module to send the data packet to the host
                        USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ToSendDataBuffer[0],64);
                    }
                }
                break;
        }
        //Re-arm the OUT endpoint, so we can receive the next OUT data packet 
        //that the host may try to send us.
        USBOutHandle = HIDRxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ReceivedDataBuffer, 64);
    }
Exemplo n.º 3
0
/*********************************************************************
* Function: void SYSTEM_Initialize( SYSTEM_STATE state )
*
* Overview: Initializes the system.
*
* PreCondition: None
*
* Input:  SYSTEM_STATE - the state to initialize the system into
*
* Output: None
*
********************************************************************/
void SYSTEM_Initialize( SYSTEM_STATE state )
{
    switch(state)
    {
        case SYSTEM_STATE_USB_START:
            //Switch to alternate interrupt vector table for bootloader
            INTCON2bits.ALTIVT = 1;
            BUTTON_Enable(BUTTON_USB_DEVICE_HID_CUSTOM);

            if((BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_CUSTOM)==false) && ((RCON & 0x83) != 0))
            {
                //Switch to app standare IVT for non boot mode
                INTCON2bits.ALTIVT = 0;
                __asm__("goto 0x1800");
            }
            
            LED_Enable(LED_USB_DEVICE_STATE);
            LED_Enable(LED_USB_DEVICE_HID_CUSTOM);
            
            break;
            
        case SYSTEM_STATE_USB_SUSPEND:
            break;
            
        case SYSTEM_STATE_USB_RESUME:
            break;
    }
}
Exemplo n.º 4
0
/********************************************************************
 * Function:        void main(void)
 *******************************************************************/
MAIN_RETURN main(void)
{
    SYSTEM_Initialize();

    USBDeviceInit();
    USBDeviceAttach();

    while(1)
    {
        SYSTEM_Tasks();

        #if defined(USB_POLLING)
            USBDeviceTasks();
        #endif

        /* If the USB device isn't configured yet, we can't really do anything
         * else since we don't have a host to talk to.  So jump back to the
         * top of the while loop. */
        if( USBGetDeviceState() < CONFIGURED_STATE )
        {
            /* Jump back to the top of the while loop. */
            continue;
        }

        /* If we are currently suspended, then we need to see if we need to
         * issue a remote wakeup.  In either case, we shouldn't process any
         * keyboard commands since we aren't currently communicating to the host
         * thus just continue back to the start of the while loop. */
        if( USBIsDeviceSuspended() == true )
        {
            /* Jump back to the top of the while loop. */
            continue;
        }
        // implement nMCLR button
        if ( BUTTON_IsPressed(BUTTON_S1)) {
            LUNSoftDetach(0);       // mark the media as temporarily unavailable 
            ICSP_nMCLR = SLAVE_RESET;
            LED_Off(GREEN_LED);     // turn off RED LED to indicate ready for download
            LED_On (RED_LED);
            DIRECT_Initialize();    // reset the programming state machine
        }
        else { // simply act as a slave reset 
            LUNSoftAttach(0);                       // mark the media as available
            if ( !DIRECT_ProgrammingInProgress()) {  // do not release during prog.!
                ICSP_nMCLR = SLAVE_RUN;
                LED_On(GREEN_LED);   // turn off RED LED to indicate ready for download
                LED_Off(RED_LED);
            }
        }

        //Application specific tasks
        APP_DeviceMSDTasks();
        APP_DeviceCDCEmulatorTasks();

    }//end while
}//end main
/*********************************************************************
*
*       _cbButton
*
* Purpose: 
*  1. Calls the owner draw function if the WM_PAINT message has been send
*  2. Calls the original callback for further messages
*  3. After processing the messages the function evaluates the pressed-state
*     if the WM_TOUCH message has been send
*/
static void _cbButton(WM_MESSAGE *pMsg) {
  switch (pMsg->MsgId) {
    case WM_PAINT:
      _OnPaint(pMsg->hWin);
      break;
    default:
      _pcbCallback(pMsg); /* The original callback */
      break;
  }
  if (pMsg->MsgId == WM_TOUCH) {
    if (BUTTON_IsPressed(pMsg->hWin)) {
      if (!_Pressed) {
        _Pressed = 1;
      }
    } else {
      _Pressed = 0;
    }
  }
}
Exemplo n.º 6
0
/*********************************************************************
* Function: void SYSTEM_Initialize( SYSTEM_STATE state )
*
* Overview: Initializes the system.
*
* PreCondition: None
*
* Input:  SYSTEM_STATE - the state to initialize the system into
*
* Output: None
*
********************************************************************/
void SYSTEM_Initialize( SYSTEM_STATE state )
{
    switch(state)
    {
        case SYSTEM_STATE_USB_START:
            //Switch to alternate interrupt vector table for bootloader
            INTCON2bits.ALTIVT = 1;
            BUTTON_Enable(BUTTON_USB_DEVICE_HID_CUSTOM);

            if((BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_CUSTOM)==false) && ((RCON & 0x83) != 0))
            {
                //Switch to app standare IVT for non boot mode
                INTCON2bits.ALTIVT = 0;
                __asm__("goto 0x1800");
            }
            
            //On the PIC24FJ64GB004 Family of USB microcontrollers, the PLL will not power up and be enabled
            //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
            //This allows the device to power up at a lower initial operating frequency, which can be
            //advantageous when powered from a source which is not gauranteed to be adequate for 32MHz
            //operation.  On these devices, user firmware needs to manually set the CLKDIV<PLLEN> bit to
            //power up the PLL.
            {
                unsigned int pll_startup_counter = 600;
                CLKDIVbits.PLLEN = 1;
                while(pll_startup_counter--);
            }
        
            LED_Enable(LED_USB_DEVICE_STATE);
            LED_Enable(LED_USB_DEVICE_HID_CUSTOM);
            
            break;
            
        case SYSTEM_STATE_USB_SUSPEND:
            break;
            
        case SYSTEM_STATE_USB_RESUME:
            break;
    }
}
Exemplo n.º 7
0
int main(void)
{
    SYSTEM_Initialize(SYSTEM_STATE_USB_START);
    LED_Initialize();
    APP_KeyboardConfigure();

#ifdef WITH_HOS
    HosCheckDFU(BOOT_FLAGS_VALUE & BOOT_WITH_APP);
    if (!isUSBMode() || !isBusPowered()) {
        HosMainLoop();
    }
    for (uint16_t i = 0; i < HOS_STARTUP_DELAY; ++i) {
        if (HosSleep(HOS_TYPE_DEFAULT)) {
            break;
        }
        __delay_ms(4);
    }
#endif

    USBDeviceInit();
    USBDeviceAttach();

    for (;;)
    {
#ifdef WITH_HOS
        if (!isBusPowered() || !isUSBMode()) {
            Reset();
            Nop();
            Nop();
            // NOT REACHED HERE
        }
#endif

        SYSTEM_Tasks();

#if defined(USB_POLLING)
        /* Check bus status and service USB interrupts.  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. */
        USBDeviceTasks();
#endif

        APP_LEDUpdateUSBStatus();

        /* If the USB device isn't configured yet, we can't really do anything
         * else since we don't have a host to talk to.  So jump back to the
         * top of the while loop. */
        if (USBGetDeviceState() < CONFIGURED_STATE)
        {
            /* Jump back to the top of the while loop. */
            continue;
        }

        /* If we are currently suspended, then we need to see if we need to
         * issue a remote wakeup.  In either case, we shouldn't process any
         * keyboard commands since we aren't currently communicating to the host
         * thus just continue back to the start of the while loop. */
        if (USBIsDeviceSuspended())
        {
            //Check if we should assert a remote wakeup request to the USB host,
            //when the user presses the pushbutton.
            if (BUTTON_IsPressed())
            {
                USBCBSendResume();  //Does nothing unless we are in USB suspend with remote wakeup armed.
            }

            /* Jump back to the top of the while loop. */
            continue;
        }

        if (USBIsBusSuspended())
        {
            /* Jump back to the top of the while loop. */
            continue;
        }

        /* Run the keyboard tasks. */
        APP_KeyboardTasks();
    }//end while
}//end main
/*********************************************************************
* Function: void APP_HostMSDDataLoggerTasks(void);
*
* Overview: Keeps the demo running.
*
* PreCondition: The demo should have been initialized via
*   the APP_HostMSDDataLoggerInitialize()  
*
* Input: None
*
* Output: None
*
********************************************************************/
void APP_HostMSDDataLoggerTasks()
{
    if(FILEIO_MediaDetect(&gUSBDrive, &deviceAddress) == false)
    {
        //The device has been removed.  Now we should wait for a new
        //  device to be attached.
        demoState = WAITING_FOR_ATTACH;
    }
    
    switch( demoState)
    {
        case WAITING_FOR_ATTACH:
            break;

        case MOUNTING_DRIVE:
        {           
            // Attempt to mount the drive described by gUSBDrive as drive 'A'
            // The deviceAddress parameter describes the USB address of the device; it is initialized by the application in the 
            // USB_ApplicationEventHandler function when a new device is detected.
            if( FILEIO_DriveMount ('A', &gUSBDrive, &deviceAddress) == FILEIO_ERROR_NONE)
            {
                demoState = OPENING_FILE;
            }
            break;
        }

        case OPENING_FILE:
            // Opening a file with the FILEIO_OPEN_WRITE option allows us to write to the file.
            // Opening a file with the FILEIO_OPEN_CREATE file will create the file if it does not already exist.
            // Opening a file with the FILEIO_OPEN_TRUNCATE file will truncate it to a 0-length file if it already exists.
            if(FILEIO_Open(&myFile, "LOG.CSV", FILEIO_OPEN_WRITE | FILEIO_OPEN_CREATE | FILEIO_OPEN_TRUNCATE) == FILEIO_RESULT_SUCCESS)
            {
                //Opening the file failed.  Since we can't write to the
                //  device, abort the write attempt and wait for the device
                //  to be removed.
                demoState = WRITING_TO_FILE;

                blinkCount = 0;
                sampleRequested = false;
                TIMER_RequestTick(&APP_HostMSDDataLoggerTickHandler, 50);
                LED_On(LED_USB_HOST_MSD_DATA_LOGGER);
                ADC_ChannelEnable(ADC_USB_HOST_MSD_DATA_SOURCE);
                break;
            }
            break;

        case WRITING_TO_FILE:
            if(sampleRequested == true)
            {
                uint16_t  adcResult;
                int charCount;

                sampleRequested = false;
                
                adcResult = ADC_Read10bit(ADC_USB_HOST_MSD_DATA_SOURCE);

                charCount = sprintf(printBuffer, "%d\r\n", adcResult);
                
                //Write some data to the new file.
                FILEIO_Write(printBuffer, 1, charCount, &myFile);
            }

            if(BUTTON_IsPressed(BUTTON_USB_HOST_MSD_DATA_LOGGER) == true)
            {
                demoState = CLOSING_FILE;
            }
            break;

        case CLOSING_FILE:
            //Always make sure to close the file so that the data gets
            //  written to the drive.
            FILEIO_Close(&myFile);
            TIMER_CancelTick(&APP_HostMSDDataLoggerTickHandler);

            demoState = UNMOUNT_DRIVE;
            break;

        case UNMOUNT_DRIVE:
            // Unmount the drive since it is no longer in use.
            FILEIO_DriveUnmount ('A');

            //Now that we are done writing, we can do nothing until the
            //  drive is removed.
            demoState = WAITING_FOR_DETACH;
            break;

        case WAITING_FOR_DETACH:
            LED_Off(LED_USB_HOST_MSD_DATA_LOGGER);
            break;

        default:
            break;
    }
}
/*********************************************************************
* Function: void APP_DeviceCDCBasicDemoTasks(void);
*
* Overview: Keeps the demo running.
*
* PreCondition: The demo should have been initialized and started via
*   the APP_DeviceCDCBasicDemoInitialize() and APP_DeviceCDCBasicDemoStart() demos
*   respectively.
*
* Input: None
*
* Output: None
*
********************************************************************/
void APP_DeviceCDCBasicDemoTasks()
{
    /* If the user has pressed the button associated with this demo, then we
     * are going to send a "Button Pressed" message to the terminal.
     */
    if(BUTTON_IsPressed(BUTTON_DEVICE_CDC_BASIC_DEMO) == true)
    {
        /* Make sure that we only send the message once per button press and
         * not continuously as the button is held.
         */
        if(buttonPressed == false)
        {
            /* Make sure that the CDC driver is ready for a transmission.
             */
            if(mUSBUSARTIsTxTrfReady() == true)
            {
                putrsUSBUSART(buttonMessage);
                buttonPressed = true;
            }
        }
    }
    else
    {
        /* If the button is released, we can then allow a new message to be
         * sent the next time the button is pressed.
         */
        buttonPressed = false;
    }

    /* Check to see if there is a transmission in progress, if there isn't, then
     * we can see about performing an echo response to data received.
     */
    if( USBUSARTIsTxTrfReady() == true)
    {
      uint8_t numBytesRead;
      numBytesRead = getsUSBUSART(readBuffer, sizeof(readBuffer));

      if (numBytesRead > 0) {
        switch(readBuffer[0]) {
        case 0x10:
          {
            unsigned char size = readBuffer[1];
            debug_flag2 = !debug_flag2;
            PORTCbits.RC1 = debug_flag2;
            writeBuffer[0] = 0x90;
            writeBuffer[1] = 4;
            writeBuffer[2] = numBytesRead;
            writeBuffer[3] = readBuffer[1];
            writeBuffer[4] = readBuffer[2];
            writeBuffer[5] = readBuffer[3];
            writeBuffer[1] = 4+size;
            for (unsigned char i = 0; i<size; i++) {
              writeBuffer[i+6] = readBuffer[4 + i];
            }
            if (WaitToReadySerial())
              putUSBUSART(writeBuffer, writeBuffer[1]+2);
            WaitToReadySerial();
          }
          {
            unsigned char size = readBuffer[1];
            i2c_start(0x50, 0);
            // address in big-endian format
            i2c_send(readBuffer[3]); // address MSB
            i2c_send(readBuffer[2]); // address LSB
            for (unsigned char i = 0; i<size; i++) {
              i2c_send(readBuffer[4 + i]);
            }
            i2c_stop();
            __delay_ms(10);
          }
          break;
        case 0x11:
          {
            unsigned char size = readBuffer[1];
            unsigned char data;
            unsigned char i;
            i2c_start(0x50, 0);
            // address in big-endian format
            i2c_send(readBuffer[3]); // address MSB
            i2c_send(readBuffer[2]); // address LSB
            i2c_start(0x50, 1);
            for (i=0; i<size-1; i++) {
              writeBuffer[i+2] = i2c_receive(ACK);
            }
            writeBuffer[i+2] = i2c_receive(NOACK);
            i2c_stop();
            __delay_ms(10);
            writeBuffer[0] = 0x12;
            writeBuffer[1] = size;
            putUSBUSART(writeBuffer, writeBuffer[1]+2);
          }
          break;
        }
      }

      //if (debug_flag) {
      //  debug_flag = 0;
      //  writeBuffer[0] = 9;
      //  writeBuffer[1] = 1;
      //  writeBuffer[2] = debug_data;
      //  putUSBUSART(writeBuffer, writeBuffer[1]+2);
      //}
    }
    CDCTxService();
}
Exemplo n.º 10
0
/*********************************************************************
* Function: void SYSTEM_Initialize( SYSTEM_STATE state )
*
* Overview: Initializes the system.
*
* PreCondition: None
*
* Input:  SYSTEM_STATE - the state to initialize the system into
*
* Output: None
*
********************************************************************/
void SYSTEM_Initialize( SYSTEM_STATE state )
{
    switch(state)
    {
        case SYSTEM_STATE_USB_START:
            //Switch to alternate interrupt vector table for bootloader
            INTCON2bits.ALTIVT = 1;
            BUTTON_Enable(BUTTON_USB_DEVICE_HID_CUSTOM);

            if((BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_CUSTOM)==false) && ((RCON & 0x83) != 0))
            {
                //Switch to app standare IVT for non boot mode
                INTCON2bits.ALTIVT = 0;
                __asm__("goto 0x1800");
            }
            ANSELA = 0x0000;
            ANSELB = 0x0000;
            ANSELC = 0x0000;
            ANSELD = 0x0000;
            ANSELE = 0x0000;
            ANSELG = 0x0000;

            // Configure the device PLL to obtain 60 MIPS operation. The crystal
            // frequency is 8MHz. Divide 8MHz by 2, multiply by 60 and divide by
            // 2. This results in Fosc of 120MHz. The CPU clock frequency is
            // Fcy = Fosc/2 = 60MHz. Wait for the Primary PLL to lock and then
            // configure the auxilliary PLL to provide 48MHz needed for USB
            // Operation.

            PLLFBD = 58;                        /* M  = 60  */
            CLKDIVbits.PLLPOST = 0;             /* N1 = 2   */
            CLKDIVbits.PLLPRE = 0;              /* N2 = 2   */
            OSCTUN = 0;

            /*	Initiate Clock Switch to Primary
             *	Oscillator with PLL (NOSC= 0x3)*/
            __builtin_write_OSCCONH(0x03);
            __builtin_write_OSCCONL(0x01);

            while (OSCCONbits.COSC != 0x3);

            // Configuring the auxiliary PLL, since the primary
            // oscillator provides the source clock to the auxiliary
            // PLL, the auxiliary oscillator is disabled. Note that
            // the AUX PLL is enabled. The input 8MHz clock is divided
            // by 2, multiplied by 24 and then divided by 2. Wait till
            // the AUX PLL locks.

            ACLKCON3 = 0x24C1;
            ACLKDIV3 = 0x7;

            ACLKCON3bits.ENAPLL = 1;
            while(ACLKCON3bits.APLLCK != 1);
            
            LED_Enable(LED_USB_DEVICE_STATE);
            LED_Enable(LED_USB_DEVICE_HID_CUSTOM);
            
            break;
            
        case SYSTEM_STATE_USB_SUSPEND:
            break;
            
        case SYSTEM_STATE_USB_RESUME:
            break;
    }
}
Exemplo n.º 11
0
/*********************************************************************
* Function: void APP_DeviceCDCBasicDemoTasks(void);
*
* Overview: Keeps the demo running.
*
* PreCondition: The demo should have been initialized and started via
*   the APP_DeviceCDCBasicDemoInitialize() and APP_DeviceCDCBasicDemoStart() demos
*   respectively.
*
* Input: None
*
* Output: None
*
********************************************************************/
void APP_DeviceCDCBasicDemoTasks()
{
    uint8_t numBytesWrite = 0;
    uint8_t packet[MAX_PACKET_SIZE];
    uint8_t packetSize;
    packet_data_u data;

    /* Make sure that the CDC driver is ready for a transmission.
     */
    if (mUSBUSARTIsTxTrfReady() == true) {
        uint16_t value;
        uint32_t percent;
        button_state_s cur_state[3];

        memset(cur_state, 0x00, 3 * sizeof(button_state_s));

        bool button1IsPressed = BUTTON_IsPressed(BUTTON_S1);
        bool button2IsPressed = BUTTON_IsPressed(BUTTON_S2);
        bool button3IsPressed = BUTTON_IsPressed(BUTTON_S3);
    
        value = ADC_Read10bit(ADC_CHANNEL_1);
        percent = ((uint32_t)100 * value) / 0x03FF;
        cur_state[0].pos = 0;
        cur_state[0].state = button1IsPressed ? BUTTON_PRESSED : BUTTON_RELEASED;
        cur_state[0].state |= ((percent >= 95) ? BUTTON_UNMOUNTED : BUTTON_MOUNTED);
        cur_state[0].uid = percent;

        value = ADC_Read10bit(ADC_CHANNEL_2);
        percent = ((uint32_t)100 * value) / 0x03FF;
        cur_state[1].pos = 1;
        cur_state[1].state = button2IsPressed ? BUTTON_PRESSED : BUTTON_RELEASED;
        cur_state[1].state |= ((percent >= 95) ? BUTTON_UNMOUNTED : BUTTON_MOUNTED);
        cur_state[1].uid = percent;

        value = ADC_Read10bit(ADC_CHANNEL_3);
        percent = ((uint32_t)100 * value) / 0x03FF;
        cur_state[2].pos = 2;
        cur_state[2].state = button3IsPressed ? BUTTON_PRESSED : BUTTON_RELEASED;
        cur_state[2].state |= ((percent >= 95) ? BUTTON_UNMOUNTED : BUTTON_MOUNTED);
        cur_state[2].uid = percent;

        if ((buttons_state[0].state != cur_state[0].state) || (buttons_state[1].state != cur_state[1].state) || (buttons_state[2].state != cur_state[2].state)) {
            memset(&data, 0x00, sizeof(packet_data_u));
            memcpy(data.buttons_state, cur_state, 3 * sizeof(button_state_s));
            assemblyPacket(GET_BUTTONS_STATE, &data, packet, &packetSize);
            memcpy(writeBuffer, packet, packetSize);
            numBytesWrite = packetSize;

            if (numBytesWrite > 0) {
                putUSBUSART(writeBuffer, numBytesWrite);
            }
            
            memcpy(buttons_state, cur_state, 3 * sizeof(button_state_s));
        }
    }

    /* Check to see if there is a transmission in progress, if there isn't, then
     * we can see about performing an echo response to data received.
     */
    if( USBUSARTIsTxTrfReady() == true)
    {
        uint16_t i;
        uint16_t validDataLen;
        uint16_t numBytesRead;
        char deviceID[] = "Keys 011";
        char *e;
        packet_type_e type;
        uint8_t payload[MAX_DATA_SIZE];
        uint8_t payloadSize;

        // Collect incoming data in read buffer. Bear in mind, buffer have to had ability receive whole CDC packet.
        if ((readPos + CDC_DATA_OUT_EP_SIZE) >= sizeof(readBuffer)) {
            e = memchr(readBuffer, PREAMBLE, sizeof(readBuffer));
            // Wipe out trash before valid data
            if (e == 0) {
                memset(readBuffer, 0x00, sizeof(readBuffer));
                readPos = 0;
            } else {
                validDataLen = (uint16_t)(&readBuffer[sizeof(readBuffer)] - e);
                memmove(readBuffer, e, validDataLen);
                memset(&readBuffer[validDataLen], 0x00, sizeof(readBuffer) - validDataLen);
                readPos = 0;
            }
        }
        numBytesRead = getsUSBUSART(&readBuffer[readPos], CDC_DATA_OUT_EP_SIZE);
        if (numBytesRead > 0) {
            // Parse all collected incoming data
            do {
                e = memchr(readBuffer, PREAMBLE, sizeof(readBuffer));
                if (e == 0) {
                    break;
                }
                i = (uint16_t)(e - readBuffer);
                parsePacket(&readBuffer[i], sizeof(readBuffer) - i, &type, payload, &payloadSize);
                numBytesWrite = 0;
                if (type == GET_DEVICE_ID) {
                    memset(&data, 0x00, sizeof(packet_data_u));
                    memcpy(data.device_id, deviceID, 8);
                    assemblyPacket(GET_DEVICE_ID, &data, packet, &packetSize);
                    memcpy(writeBuffer, packet, packetSize);
                    numBytesWrite = packetSize;
                } else if (type == GET_STATUS) {
                    memset(&data, 0x00, sizeof(packet_data_u));
                    data.device_status.errors = ERROR_NONE;
                    data.device_status.rtc = 0;
                    assemblyPacket(GET_STATUS, &data, packet, &packetSize);
                    memcpy(writeBuffer, packet, packetSize);
                    numBytesWrite = packetSize;                    
                } else if (type == SET_LEDS_STATE) {
                    led_state_s *led = (led_state_s *)payload;
                    if (led->state == LED_TURN_ON) {
                        if (led->pos == 0)
                            LED_On(LED_D2);
                        if (led->pos == 1)
                            LED_On(LED_D3);
                        if (led->pos == 2)
                            LED_On(LED_D4);
                    } else {
                        if (led->pos == 0)
                            LED_Off(LED_D2);
                        if (led->pos == 1)
                            LED_Off(LED_D3);
                        if (led->pos == 2)
                            LED_Off(LED_D4);
                    }
                } else if (type == RESET_DEVICE) {
                    LED_Off(LED_D2);
                    LED_Off(LED_D3);
                    LED_Off(LED_D4);
                    memset(readBuffer, 0x00, sizeof(readBuffer));
                    readPos = 0;
                } else {
                    memcpy(writeBuffer, &readBuffer[i], 20);
                    numBytesWrite = 20;
                }
                // Clear packet's start marker - PREAMBLE
                memset(&readBuffer[i], 0x00, 1);
                // Send answer
                if (numBytesWrite > 0) {
                    putUSBUSART(writeBuffer, numBytesWrite);
                }
            } while (1);
        }
    }

    CDCTxService();
}
/*********************************************************************
* Function: void APP_DeviceAudioMIDITasks(void);
*
* Overview: Keeps the Custom HID demo running.
*
* PreCondition: The demo should have been initialized and started via
*   the APP_DeviceAudioMIDIInitialize() and APP_DeviceAudioMIDIStart() demos
*   respectively.
*
* Input: None
*
* Output: None
*
********************************************************************/
void APP_DeviceAudioMIDITasks()
{
    /* If the device is not configured yet, or the device is suspended, then
     * we don't need to run the demo since we can't send any data.
     */
    if( (USBGetDeviceState() < CONFIGURED_STATE) ||
        (USBIsDeviceSuspended() == true))
    {
        return;
    }

    if(!USBHandleBusy(USBRxHandle))
    {
        //We have received a MIDI packet from the host, process it and then
        //  prepare to receive the next packet

        //INSERT MIDI PROCESSING CODE HERE

        //Get ready for next packet (this will overwrite the old data)
        USBRxHandle = USBRxOnePacket(USB_DEVICE_AUDIO_MIDI_ENDPOINT,(uint8_t*)&ReceivedDataBuffer,64);
    }

    /* If the user button is pressed... */
    if(BUTTON_IsPressed(BUTTON_DEVICE_AUDIO_MIDI) == true)
    {
        /* and we haven't sent a transmission in the past 100ms... */
        if(msCounter == 0)
        {
            /* and we have sent the NOTE_OFF for the last note... */
            if(sentNoteOff == true)
            {
                /* and we aren't currently trying to transmit data... */
                if(!USBHandleBusy(USBTxHandle))
                {
                    //Then reset the 100ms counter
                    msCounter = 100;

                    midiData.Val = 0;   //must set all unused values to 0 so go ahead
                                        //  and set them all to 0

                    midiData.CableNumber = 0;
                    midiData.CodeIndexNumber = MIDI_CIN_NOTE_ON;
                    midiData.DATA_0 = 0x90;         //Note on
                    midiData.DATA_1 = pitch;         //pitch
                    midiData.DATA_2 = 0x7F;  //velocity

                    USBTxHandle = USBTxOnePacket(USB_DEVICE_AUDIO_MIDI_ENDPOINT,(uint8_t*)&midiData,4);

                    /* we now need to send the NOTE_OFF for this note. */
                    sentNoteOff = false;
                }
            }
        }
    }
    else
    {
        if(msCounter == 0)
        {
            if(sentNoteOff == false)
            {
                if(!USBHandleBusy(USBTxHandle))
                {
                    //Debounce counter for 100ms
                    msCounter = 100;

                    midiData.Val = 0;   //must set all unused values to 0 so go ahead
                                        //  and set them all to 0

                    midiData.CableNumber = 0;
                    midiData.CodeIndexNumber = MIDI_CIN_NOTE_ON;
                    midiData.DATA_0 = 0x90;     //Note off
                    midiData.DATA_1 = pitch++;     //pitch
                    midiData.DATA_2 = 0x00;        //velocity

                    if(pitch == 0x49)
                    {
                        pitch = 0x3C;
                    }

                    USBTxHandle = USBTxOnePacket(USB_DEVICE_AUDIO_MIDI_ENDPOINT,(uint8_t*)&midiData,4);
                    sentNoteOff = true;
                }
            }
        }
    }
}