test

Dependencies:   BMI160 max32630hsp3 MemoryLCD USBDevice

Files at this revision

API Documentation at this revision

Comitter:
seyhmus.cacina
Date:
Mon Mar 18 10:21:53 2019 +0300
Child:
1:f875283d1530
Commit message:
ME11B Sample Code First Commit

Changed in this revision

Drivers/USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBAudio/USBAudio.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBAudio/USBAudio.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBAudio/USBAudio_Types.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBDescriptor.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBDevice.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBDevice.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBDevice_Types.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints_EFM32.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints_KL25Z.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints_LPC11U.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints_LPC17_LPC23.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints_Maxim.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints_RZ_A1H.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBEndpoints_STM32F4.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_EFM32.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_KL25Z.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_LPC11U.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_LPC17.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_LPC40.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_Maxim.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_RZ_A1H.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBHAL_STM32F4.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBDevice/USBRegs_STM32.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBHID.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBHID.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBHID_Types.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBKeyboard.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBMouse.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBMouse.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBMouseKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBHID/USBMouseKeyboard.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBMIDI/MIDIMessage.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBMIDI/USBMIDI.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBMIDI/USBMIDI.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBMSD/USBMSD.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBMSD/USBMSD.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBSerial/CircBuffer.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBSerial/USBCDC.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBSerial/USBCDC.h Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBSerial/USBSerial.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/USBDevice/USBSerial/USBSerial.h Show annotated file Show diff for this revision Revisions of this file
SHComm/SHComm.cpp Show annotated file Show diff for this revision Revisions of this file
SHComm/SHComm.h Show annotated file Show diff for this revision Revisions of this file
SHMAX8614X/HostAccelHelper.cpp Show annotated file Show diff for this revision Revisions of this file
SHMAX8614X/HostAccelHelper.h Show annotated file Show diff for this revision Revisions of this file
SHMAX8614X/SH_Max8614x_BareMetal.cpp Show annotated file Show diff for this revision Revisions of this file
SHMAX8614X/SH_Max8614x_BareMetal.h Show annotated file Show diff for this revision Revisions of this file
accelerometer/bmi160.cpp Show annotated file Show diff for this revision Revisions of this file
accelerometer/bmi160.h Show annotated file Show diff for this revision Revisions of this file
accelerometer/bmi160_i2c.cpp Show annotated file Show diff for this revision Revisions of this file
accelerometer/bmi160_spi.cpp Show annotated file Show diff for this revision Revisions of this file
bootloader/bootldrAPI.cpp Show annotated file Show diff for this revision Revisions of this file
bootloader/bootldrAPI.h Show annotated file Show diff for this revision Revisions of this file
cmdUI/cmdInterface.cpp Show annotated file Show diff for this revision Revisions of this file
cmdUI/cmdInterface.h Show annotated file Show diff for this revision Revisions of this file
demoDefinitions.h Show annotated file Show diff for this revision Revisions of this file
demoUI/demoUI.cpp Show annotated file Show diff for this revision Revisions of this file
demoUI/demoUI.h Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/BufferedDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/BufferedDisplay.h Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/GraphicsDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/GraphicsDisplay.h Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/LCDSettings.h Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/LS013B7DH03.cpp Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/LS013B7DH03.h Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/TextDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
demoUI/screen/TextDisplay.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
platform/MAX20303.cpp Show annotated file Show diff for this revision Revisions of this file
platform/MAX20303.h Show annotated file Show diff for this revision Revisions of this file
platform/max32630hsp.cpp Show annotated file Show diff for this revision Revisions of this file
platform/max32630hsp.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice.lib	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/MaximIntegrated/code/USBDevice/#dad310740b28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBAudio/USBAudio.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,618 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBAudio.h"
+#include "USBAudio_Types.h"
+
+
+
+USBAudio::USBAudio(uint32_t frequency_in, uint8_t channel_nb_in, uint32_t frequency_out, uint8_t channel_nb_out, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
+    mute = 0;
+    volCur = 0x0080;
+    volMin = 0x0000;
+    volMax = 0x0100;
+    volRes = 0x0004;
+    available = false;
+
+    FREQ_IN = frequency_in;
+    FREQ_OUT = frequency_out;
+
+    this->channel_nb_in = channel_nb_in;
+    this->channel_nb_out = channel_nb_out;
+
+    // stereo -> *2, mono -> *1
+    PACKET_SIZE_ISO_IN = (FREQ_IN / 500) * channel_nb_in;
+    PACKET_SIZE_ISO_OUT = (FREQ_OUT / 500) * channel_nb_out;
+
+    // STEREO -> left and right
+    channel_config_in = (channel_nb_in == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
+    channel_config_out = (channel_nb_out == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
+
+    SOF_handler = false;
+
+    buf_stream_out = NULL;
+    buf_stream_in = NULL;
+
+    interruptOUT = false;
+    writeIN = false;
+    interruptIN = false;
+    available = false;
+
+    volume = 0;
+
+    // connect the device
+    USBDevice::connect();
+}
+
+bool USBAudio::read(uint8_t * buf) {
+    buf_stream_in = buf;
+    SOF_handler = false;
+    while (!available || !SOF_handler);
+    available = false;
+    return true;
+}
+
+bool USBAudio::readNB(uint8_t * buf) {
+    buf_stream_in = buf;
+    SOF_handler = false;
+    while (!SOF_handler);
+    if (available) {
+        available = false;
+        buf_stream_in = NULL;
+        return true;
+    }
+    return false;
+}
+
+bool USBAudio::readWrite(uint8_t * buf_read, uint8_t * buf_write) {
+    buf_stream_in = buf_read;
+    SOF_handler = false;
+    writeIN = false;
+    if (interruptIN) {
+        USBDevice::writeNB(EP3IN, buf_write, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
+    } else {
+        buf_stream_out = buf_write;
+    }
+    while (!available);
+    if (interruptIN) {
+        while (!writeIN);
+    }
+    while (!SOF_handler);
+    return true;
+}
+
+
+bool USBAudio::write(uint8_t * buf) {
+    writeIN = false;
+    SOF_handler = false;
+    if (interruptIN) {
+        USBDevice::writeNB(EP3IN, buf, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
+    } else {
+        buf_stream_out = buf;
+    }
+    while (!SOF_handler);
+    if (interruptIN) {
+        while (!writeIN);
+    }
+    return true;
+}
+
+
+float USBAudio::getVolume() {
+    return (mute) ? 0.0 : volume;
+}
+
+
+bool USBAudio::EPISO_OUT_callback() {
+    uint32_t size = 0;
+    interruptOUT = true;
+    if (buf_stream_in != NULL) {
+        readEP(EP3OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN);
+        available = true;
+        buf_stream_in = NULL;
+    }
+    readStart(EP3OUT, PACKET_SIZE_ISO_IN);
+    return false;
+}
+
+
+bool USBAudio::EPISO_IN_callback() {
+    interruptIN = true;
+    writeIN = true;
+    return true;
+}
+
+
+
+// Called in ISR context on each start of frame
+void USBAudio::SOF(int frameNumber) {
+    uint32_t size = 0;
+
+    if (!interruptOUT) {
+        // read the isochronous endpoint
+        if (buf_stream_in != NULL) {
+            if (USBDevice::readEP_NB(EP3OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN)) {
+                if (size) {
+                    available = true;
+                    readStart(EP3OUT, PACKET_SIZE_ISO_IN);
+                    buf_stream_in = NULL;
+                }
+            }
+        }
+    }
+
+    if (!interruptIN) {
+        // write if needed
+        if (buf_stream_out != NULL) {
+            USBDevice::writeNB(EP3IN, (uint8_t *)buf_stream_out, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
+            buf_stream_out = NULL;
+        }
+    }
+
+    SOF_handler = true;
+}
+
+
+// Called in ISR context
+// Set configuration. Return false if the configuration is not supported.
+bool USBAudio::USBCallback_setConfiguration(uint8_t configuration) {
+    if (configuration != DEFAULT_CONFIGURATION) {
+        return false;
+    }
+
+    // Configure isochronous endpoint
+    realiseEndpoint(EP3OUT, PACKET_SIZE_ISO_IN, ISOCHRONOUS);
+    realiseEndpoint(EP3IN, PACKET_SIZE_ISO_OUT, ISOCHRONOUS);
+
+    // activate readings on this endpoint
+    readStart(EP3OUT, PACKET_SIZE_ISO_IN);
+    return true;
+}
+
+
+// Called in ISR context
+// Set alternate setting. Return false if the alternate setting is not supported
+bool USBAudio::USBCallback_setInterface(uint16_t interface, uint8_t alternate) {
+    if (interface == 0 && alternate == 0) {
+        return true;
+    }
+    if (interface == 1 && (alternate == 0 || alternate == 1)) {
+        return true;
+    }
+    if (interface == 2 && (alternate == 0 || alternate == 1)) {
+        return true;
+    }
+    return false;
+}
+
+
+
+// Called in ISR context
+// Called by USBDevice on Endpoint0 request
+// This is used to handle extensions to standard requests and class specific requests.
+// Return true if class handles this request
+bool USBAudio::USBCallback_request() {
+    bool success = false;
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+
+    // Process class-specific requests
+    if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
+
+        // Feature Unit: Interface = 0, ID = 2
+        if (transfer->setup.wIndex == 0x0200) {
+
+            // Master Channel
+            if ((transfer->setup.wValue & 0xff) == 0) {
+
+                switch (transfer->setup.wValue >> 8) {
+                    case MUTE_CONTROL:
+                        switch (transfer->setup.bRequest) {
+                            case REQUEST_GET_CUR:
+                                transfer->remaining = 1;
+                                transfer->ptr = &mute;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_CUR:
+                                transfer->remaining = 1;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            default:
+                                break;
+                        }
+                        break;
+                    case VOLUME_CONTROL:
+                        switch (transfer->setup.bRequest) {
+                            case REQUEST_GET_CUR:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volCur;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case REQUEST_GET_MIN:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volMin;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case REQUEST_GET_MAX:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volMax;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case REQUEST_GET_RES:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volRes;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_CUR:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            case REQUEST_SET_MIN:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            case REQUEST_SET_MAX:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            case REQUEST_SET_RES:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+    return success;
+}
+
+
+// Called in ISR context when a data OUT stage has been performed
+void USBAudio::USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {
+    if ((length == 1) || (length == 2)) {
+        uint16_t data = (length == 1) ? *buf : *((uint16_t *)buf);
+        CONTROL_TRANSFER * transfer = getTransferPtr();
+        switch (transfer->setup.wValue >> 8) {
+            case MUTE_CONTROL:
+                switch (transfer->setup.bRequest) {
+                    case REQUEST_SET_CUR:
+                        mute = data & 0xff;
+                        updateVol.call();
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            case VOLUME_CONTROL:
+                switch (transfer->setup.bRequest) {
+                    case REQUEST_SET_CUR:
+                        volCur = data;
+                        volume = (float)volCur/(float)volMax;
+                        updateVol.call();
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+
+
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (5 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (1 * CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1) \
+                               + (2 * INPUT_TERMINAL_DESCRIPTOR_LENGTH) \
+                               + (1 * FEATURE_UNIT_DESCRIPTOR_LENGTH) \
+                               + (2 * OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) \
+                               + (2 * STREAMING_INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (2 * FORMAT_TYPE_I_DESCRIPTOR_LENGTH) \
+                               + (2 * (ENDPOINT_DESCRIPTOR_LENGTH + 2)) \
+                               + (2 * STREAMING_ENDPOINT_DESCRIPTOR_LENGTH) )
+
+#define TOTAL_CONTROL_INTF_LENGTH    (CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1 + \
+                                      2*INPUT_TERMINAL_DESCRIPTOR_LENGTH     + \
+                                      FEATURE_UNIT_DESCRIPTOR_LENGTH    + \
+                                      2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
+
+uint8_t * USBAudio::configurationDesc() {
+    static uint8_t configDescriptor[] = {
+        // Configuration 1
+        CONFIGURATION_DESCRIPTOR_LENGTH,        // bLength
+        CONFIGURATION_DESCRIPTOR,               // bDescriptorType
+        LSB(TOTAL_DESCRIPTOR_LENGTH),           // wTotalLength (LSB)
+        MSB(TOTAL_DESCRIPTOR_LENGTH),           // wTotalLength (MSB)
+        0x03,                                   // bNumInterfaces
+        DEFAULT_CONFIGURATION,                  // bConfigurationValue
+        0x00,                                   // iConfiguration
+        0x80,                                   // bmAttributes
+        50,                                     // bMaxPower
+
+        // Interface 0, Alternate Setting 0, Audio Control
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x00,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOCONTROL,                  // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+
+        // Audio Control Interface
+        CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1,// bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_HEADER,                         // bDescriptorSubtype
+        LSB(0x0100),                            // bcdADC (LSB)
+        MSB(0x0100),                            // bcdADC (MSB)
+        LSB(TOTAL_CONTROL_INTF_LENGTH),         // wTotalLength
+        MSB(TOTAL_CONTROL_INTF_LENGTH),         // wTotalLength
+        0x02,                                   // bInCollection
+        0x01,                                   // baInterfaceNr
+        0x02,                                   // baInterfaceNr
+
+        // Audio Input Terminal (Speaker)
+        INPUT_TERMINAL_DESCRIPTOR_LENGTH,       // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_INPUT_TERMINAL,                 // bDescriptorSubtype
+        0x01,                                   // bTerminalID
+        LSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        MSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        0x00,                                   // bAssocTerminal
+        channel_nb_in,                          // bNrChannels
+        (uint8_t)(LSB(channel_config_in)),                 // wChannelConfig
+        (uint8_t)(MSB(channel_config_in)),                 // wChannelConfig
+        0x00,                                   // iChannelNames
+        0x00,                                   // iTerminal
+
+        // Audio Feature Unit (Speaker)
+        FEATURE_UNIT_DESCRIPTOR_LENGTH,         // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_FEATURE_UNIT,                   // bDescriptorSubtype
+        0x02,                                   // bUnitID
+        0x01,                                   // bSourceID
+        0x01,                                   // bControlSize
+        CONTROL_MUTE |
+        CONTROL_VOLUME,                         // bmaControls(0)
+        0x00,                                   // bmaControls(1)
+        0x00,                                   // iTerminal
+
+        // Audio Output Terminal (Speaker)
+        OUTPUT_TERMINAL_DESCRIPTOR_LENGTH,      // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_OUTPUT_TERMINAL,                // bDescriptorSubtype
+        0x03,                                   // bTerminalID
+        LSB(TERMINAL_SPEAKER),                  // wTerminalType
+        MSB(TERMINAL_SPEAKER),                  // wTerminalType
+        0x00,                                   // bAssocTerminal
+        0x02,                                   // bSourceID
+        0x00,                                   // iTerminal
+
+
+        // Audio Input Terminal (Microphone)
+        INPUT_TERMINAL_DESCRIPTOR_LENGTH,       // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_INPUT_TERMINAL,                 // bDescriptorSubtype
+        0x04,                                   // bTerminalID
+        LSB(TERMINAL_MICROPHONE),               // wTerminalType
+        MSB(TERMINAL_MICROPHONE),               // wTerminalType
+        0x00,                                   // bAssocTerminal
+        channel_nb_out,                         // bNrChannels
+        (uint8_t)(LSB(channel_config_out)),                // wChannelConfig
+        (uint8_t)(MSB(channel_config_out)),                // wChannelConfig
+        0x00,                                   // iChannelNames
+        0x00,                                   // iTerminal
+
+        // Audio Output Terminal (Microphone)
+        OUTPUT_TERMINAL_DESCRIPTOR_LENGTH,      // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_OUTPUT_TERMINAL,                // bDescriptorSubtype
+        0x05,                                   // bTerminalID
+        LSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        MSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        0x00,                                   // bAssocTerminal
+        0x04,                                   // bSourceID
+        0x00,                                   // iTerminal
+
+
+
+
+
+
+        // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x01,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Interface 1, Alternate Setting 1, Audio Streaming - Operational
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x01,                                   // bInterfaceNumber
+        0x01,                                   // bAlternateSetting
+        0x01,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Audio Streaming Interface
+        STREAMING_INTERFACE_DESCRIPTOR_LENGTH,  // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        STREAMING_GENERAL,                      // bDescriptorSubtype
+        0x01,                                   // bTerminalLink
+        0x00,                                   // bDelay
+        LSB(FORMAT_PCM),                        // wFormatTag
+        MSB(FORMAT_PCM),                        // wFormatTag
+
+        // Audio Type I Format
+        FORMAT_TYPE_I_DESCRIPTOR_LENGTH,        // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        STREAMING_FORMAT_TYPE,                  // bDescriptorSubtype
+        FORMAT_TYPE_I,                          // bFormatType
+        channel_nb_in,                          // bNrChannels
+        0x02,                                   // bSubFrameSize
+        16,                                     // bBitResolution
+        0x01,                                   // bSamFreqType
+        (uint8_t)(LSB(FREQ_IN)),                           // tSamFreq
+        (uint8_t)((FREQ_IN >> 8) & 0xff),                  // tSamFreq
+        (uint8_t)((FREQ_IN >> 16) & 0xff),                 // tSamFreq
+
+        // Endpoint - Standard Descriptor
+        ENDPOINT_DESCRIPTOR_LENGTH + 2,         // bLength
+        ENDPOINT_DESCRIPTOR,                    // bDescriptorType
+        PHY_TO_DESC(EPISO_OUT),                 // bEndpointAddress
+        E_ISOCHRONOUS,                          // bmAttributes
+        (uint8_t)(LSB(PACKET_SIZE_ISO_IN)),                   // wMaxPacketSize
+        (uint8_t)(MSB(PACKET_SIZE_ISO_IN)),                   // wMaxPacketSize
+        0x01,                                   // bInterval
+        0x00,                                   // bRefresh
+        0x00,                                   // bSynchAddress
+
+        // Endpoint - Audio Streaming
+        STREAMING_ENDPOINT_DESCRIPTOR_LENGTH,   // bLength
+        ENDPOINT_DESCRIPTOR_TYPE,               // bDescriptorType
+        ENDPOINT_GENERAL,                       // bDescriptor
+        0x00,                                   // bmAttributes
+        0x00,                                   // bLockDelayUnits
+        LSB(0x0000),                            // wLockDelay
+        MSB(0x0000),                            // wLockDelay
+
+
+
+
+
+
+
+        // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x02,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Interface 1, Alternate Setting 1, Audio Streaming - Operational
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x02,                                   // bInterfaceNumber
+        0x01,                                   // bAlternateSetting
+        0x01,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Audio Streaming Interface
+        STREAMING_INTERFACE_DESCRIPTOR_LENGTH,  // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        SUBCLASS_AUDIOCONTROL,                  // bDescriptorSubtype
+        0x05,                                   // bTerminalLink (output terminal microphone)
+        0x01,                                   // bDelay
+        0x01,                                   // wFormatTag
+        0x00,                                   // wFormatTag
+
+        // Audio Type I Format
+        FORMAT_TYPE_I_DESCRIPTOR_LENGTH,        // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        SUBCLASS_AUDIOSTREAMING,                // bDescriptorSubtype
+        FORMAT_TYPE_I,                          // bFormatType
+        channel_nb_out,                         // bNrChannels
+        0x02,                                   // bSubFrameSize
+        0x10,                                   // bBitResolution
+        0x01,                                   // bSamFreqType
+        (uint8_t)(LSB(FREQ_OUT)),                          // tSamFreq
+        (uint8_t)((FREQ_OUT >> 8) & 0xff),                 // tSamFreq
+        (uint8_t)((FREQ_OUT >> 16) & 0xff),                // tSamFreq
+
+        // Endpoint - Standard Descriptor
+        ENDPOINT_DESCRIPTOR_LENGTH + 2,         // bLength
+        ENDPOINT_DESCRIPTOR,                    // bDescriptorType
+        PHY_TO_DESC(EPISO_IN),                  // bEndpointAddress
+        E_ISOCHRONOUS,                          // bmAttributes
+        (uint8_t)(LSB(PACKET_SIZE_ISO_OUT)),                   // wMaxPacketSize
+        (uint8_t)(MSB(PACKET_SIZE_ISO_OUT)),                   // wMaxPacketSize
+        0x01,                                   // bInterval
+        0x00,                                   // bRefresh
+        0x00,                                   // bSynchAddress
+
+        // Endpoint - Audio Streaming
+        STREAMING_ENDPOINT_DESCRIPTOR_LENGTH,   // bLength
+        ENDPOINT_DESCRIPTOR_TYPE,               // bDescriptorType
+        ENDPOINT_GENERAL,                       // bDescriptor
+        0x00,                                   // bmAttributes
+        0x00,                                   // bLockDelayUnits
+        LSB(0x0000),                            // wLockDelay
+        MSB(0x0000),                            // wLockDelay
+
+        // Terminator
+        0                                       // bLength
+    };
+    return configDescriptor;
+}
+
+uint8_t * USBAudio::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x0c,                           //bLength
+        STRING_DESCRIPTOR,              //bDescriptorType 0x03
+        'A',0,'u',0,'d',0,'i',0,'o',0   //bString iInterface - Audio
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBAudio::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
+    };
+    return stringIproductDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBAudio/USBAudio.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,287 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBAudio_H
+#define USBAudio_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBDevice.h"
+
+
+/**
+* USBAudio example
+*
+* @code
+* #include "mbed.h"
+* #include "USBAudio.h"
+*
+* Serial pc(USBTX, USBRX);
+*
+* // frequency: 48 kHz
+* #define FREQ 48000
+*
+* // 1 channel: mono
+* #define NB_CHA 1
+*
+* // length of an audio packet: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1
+* #define AUDIO_LENGTH_PACKET 48 * 2 * 1
+*
+* // USBAudio
+* USBAudio audio(FREQ, NB_CHA);
+*
+* int main() {
+*    int16_t buf[AUDIO_LENGTH_PACKET/2];
+*
+*    while (1) {
+*        // read an audio packet
+*        audio.read((uint8_t *)buf);
+*
+*
+*        // print packet received
+*        pc.printf("recv: ");
+*        for(int i = 0; i < AUDIO_LENGTH_PACKET/2; i++) {
+*            pc.printf("%d ", buf[i]);
+*        }
+*        pc.printf("\r\n");
+*    }
+* }
+* @endcode
+*/
+class USBAudio: public USBDevice {
+public:
+
+    /**
+    * Constructor
+    *
+    * @param frequency_in frequency in Hz (default: 48000)
+    * @param channel_nb_in channel number (1 or 2) (default: 1)
+    * @param frequency_out frequency in Hz (default: 8000)
+    * @param channel_nb_out_in channel number (1 or 2) (default: 1)
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBAudio(uint32_t frequency_in = 48000, uint8_t channel_nb_in = 1, uint32_t frequency_out = 8000, uint8_t channel_nb_out = 1, uint16_t vendor_id = 0x7bb8, uint16_t product_id = 0x1111, uint16_t product_release = 0x0100);
+
+    /**
+    * Get current volume between 0.0 and 1.0
+    *
+    * @returns volume
+    */
+    float getVolume();
+
+    /**
+    * Read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Blocking
+    *
+    * @param buf pointer on a buffer which will be filled with an audio packet
+    *
+    * @returns true if successfull
+    */
+    bool read(uint8_t * buf);
+
+    /**
+    * Try to read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Non Blocking
+    *
+    * @param buf pointer on a buffer which will be filled if an audio packet is available
+    *
+    * @returns true if successfull
+    */
+    bool readNB(uint8_t * buf);
+
+    /**
+    * Write an audio packet. During a frame, only a single writing (you can't write and read an audio packet during the same frame)can be done using this method.
+    *
+    * @param buf pointer on the audio packet which will be sent
+    * @returns true if successful
+    */
+    bool write(uint8_t * buf);
+
+    /**
+    * Write and read an audio packet at the same time (on the same frame)
+    *
+    * @param buf_read pointer on a buffer which will be filled with an audio packet
+    * @param buf_write pointer on the audio packet which will be sent
+    * @returns true if successful
+    */
+    bool readWrite(uint8_t * buf_read, uint8_t * buf_write);
+
+
+    /** attach a handler to update the volume
+     *
+     * @param function Function to attach
+     *
+     */
+    void attach(void(*fptr)(void)) {
+        updateVol.attach(fptr);
+    }
+
+    /** Attach a nonstatic void/void member function to update the volume
+     *
+     * @param tptr Object pointer
+     * @param mptr Member function pointer
+     *
+     */
+    template<typename T>
+    void attach(T *tptr, void(T::*mptr)(void)) {
+        updateVol.attach(tptr, mptr);
+    }
+
+
+protected:
+
+    /*
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_setConfiguration(uint8_t configuration);
+
+    /*
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+    /*
+     * Called by USBDevice layer. Set interface/alternate of the device.
+     *
+     * @param interface Number of the interface to be configured
+     * @param alternate Number of the alternate to be configured
+     * @returns true if class handles this request
+     */
+    virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate);
+
+    /*
+    * Called by USBDevice on Endpoint0 request completion
+    * if the 'notify' flag has been set to true. Warning: Called in ISR context
+    *
+    * In this case it is used to indicate that a HID report has
+    * been received from the host on endpoint 0
+    *
+    * @param buf buffer received on endpoint 0
+    * @param length length of this buffer
+    */
+    virtual void USBCallback_requestCompleted(uint8_t * buf, uint32_t length);
+
+    /*
+    * Callback called on each Start of Frame event
+    */
+    virtual void SOF(int frameNumber);
+
+    /*
+    * Callback called when a packet is received
+    */
+    virtual bool EPISO_OUT_callback();
+
+    /*
+    * Callback called when a packet has been sent
+    */
+    virtual bool EPISO_IN_callback();
+
+private:
+
+    // stream available ?
+    volatile bool available;
+
+    // interrupt OUT has been received
+    volatile bool interruptOUT;
+
+    // interrupt IN has been received
+    volatile bool interruptIN;
+
+    // audio packet has been written
+    volatile bool writeIN;
+
+    // FREQ
+    uint32_t FREQ_OUT;
+    uint32_t FREQ_IN;
+
+    // size of the maximum packet for the isochronous endpoint
+    uint32_t PACKET_SIZE_ISO_IN;
+    uint32_t PACKET_SIZE_ISO_OUT;
+
+    // mono, stereo,...
+    uint8_t channel_nb_in;
+    uint8_t channel_nb_out;
+
+    // channel config: master, left, right
+    uint8_t channel_config_in;
+    uint8_t channel_config_out;
+
+    // mute state
+    uint8_t mute;
+
+    // Volume Current Value
+    uint16_t volCur;
+
+    // Volume Minimum Value
+    uint16_t volMin;
+
+    // Volume Maximum Value
+    uint16_t volMax;
+
+    // Volume Resolution
+    uint16_t volRes;
+
+    // Buffer containing one audio packet (to be read)
+    volatile uint8_t * buf_stream_in;
+
+    // Buffer containing one audio packet (to be written)
+    volatile uint8_t * buf_stream_out;
+
+    // callback to update volume
+    FunctionPointer updateVol;
+
+    // boolean showing that the SOF handler has been called. Useful for readNB.
+    volatile bool SOF_handler;
+
+    volatile float volume;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBAudio/USBAudio_Types.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,97 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBAUDIO_TYPES_H
+#define USBAUDIO_TYPES_H
+
+
+#define DEFAULT_CONFIGURATION (1)
+
+// Audio Request Codes
+#define REQUEST_SET_CUR     0x01
+#define REQUEST_GET_CUR     0x81
+#define REQUEST_SET_MIN     0x02
+#define REQUEST_GET_MIN     0x82
+#define REQUEST_SET_MAX     0x03
+#define REQUEST_GET_MAX     0x83
+#define REQUEST_SET_RES     0x04
+#define REQUEST_GET_RES     0x84
+
+#define MUTE_CONTROL        0x01
+#define VOLUME_CONTROL      0x02
+
+
+// Audio Descriptor Sizes
+#define CONTROL_INTERFACE_DESCRIPTOR_LENGTH       0x09
+#define STREAMING_INTERFACE_DESCRIPTOR_LENGTH     0x07
+#define INPUT_TERMINAL_DESCRIPTOR_LENGTH          0x0C
+#define OUTPUT_TERMINAL_DESCRIPTOR_LENGTH         0x09
+#define FEATURE_UNIT_DESCRIPTOR_LENGTH            0x09
+#define STREAMING_ENDPOINT_DESCRIPTOR_LENGTH      0x07
+
+// Audio Format Type Descriptor Sizes
+#define FORMAT_TYPE_I_DESCRIPTOR_LENGTH   0x0b
+
+#define AUDIO_CLASS                       0x01
+#define SUBCLASS_AUDIOCONTROL             0x01
+#define SUBCLASS_AUDIOSTREAMING           0x02
+
+// Audio Descriptor Types
+#define INTERFACE_DESCRIPTOR_TYPE         0x24
+#define ENDPOINT_DESCRIPTOR_TYPE          0x25
+
+// Audio Control Interface Descriptor Subtypes
+#define CONTROL_HEADER                    0x01
+#define CONTROL_INPUT_TERMINAL            0x02
+#define CONTROL_OUTPUT_TERMINAL           0x03
+#define CONTROL_FEATURE_UNIT              0x06
+
+// USB Terminal Types
+#define TERMINAL_USB_STREAMING            0x0101
+
+// Predefined Audio Channel Configuration Bits
+// Mono
+#define CHANNEL_M                         0x0000
+#define CHANNEL_L                         0x0001  /* Left Front */
+#define CHANNEL_R                         0x0002  /* Right Front */
+
+// Feature Unit Control Bits
+#define CONTROL_MUTE                      0x0001
+#define CONTROL_VOLUME                    0x0002
+
+// Input Terminal Types
+#define TERMINAL_MICROPHONE               0x0201
+
+// Output Terminal Types
+#define TERMINAL_SPEAKER                  0x0301
+#define TERMINAL_HEADPHONES               0x0302
+
+// Audio Streaming Interface Descriptor Subtypes
+#define STREAMING_GENERAL                 0x01
+#define STREAMING_FORMAT_TYPE             0x02
+
+// Audio Data Format Type I Codes
+#define FORMAT_PCM                        0x0001
+
+// Audio Format Types
+#define FORMAT_TYPE_I                     0x01
+
+// Audio Endpoint Descriptor Subtypes
+#define ENDPOINT_GENERAL                  0x01
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBDescriptor.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,74 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/* Standard descriptor types */
+#define DEVICE_DESCRIPTOR        (1)
+#define CONFIGURATION_DESCRIPTOR (2)
+#define STRING_DESCRIPTOR        (3)
+#define INTERFACE_DESCRIPTOR     (4)
+#define ENDPOINT_DESCRIPTOR      (5)
+#define QUALIFIER_DESCRIPTOR     (6)
+
+/* Standard descriptor lengths */
+#define DEVICE_DESCRIPTOR_LENGTH        (0x12)
+#define CONFIGURATION_DESCRIPTOR_LENGTH (0x09)
+#define INTERFACE_DESCRIPTOR_LENGTH     (0x09)
+#define ENDPOINT_DESCRIPTOR_LENGTH      (0x07)
+
+
+/*string offset*/
+#define STRING_OFFSET_LANGID            (0)
+#define STRING_OFFSET_IMANUFACTURER     (1)
+#define STRING_OFFSET_IPRODUCT          (2)
+#define STRING_OFFSET_ISERIAL           (3)
+#define STRING_OFFSET_ICONFIGURATION    (4)
+#define STRING_OFFSET_IINTERFACE        (5)
+
+/* USB Specification Release Number */
+#define USB_VERSION_2_0 (0x0200)
+
+/* Least/Most significant byte of short integer */
+#define LSB(n)  ((n)&0xff)
+#define MSB(n)  (((n)&0xff00)>>8)
+
+/* Convert physical endpoint number to descriptor endpoint number */
+#define PHY_TO_DESC(endpoint) (((endpoint)>>1) | (((endpoint) & 1) ? 0x80:0))
+
+/* bmAttributes in configuration descriptor */
+/* C_RESERVED must always be set */
+#define C_RESERVED      (1U<<7)
+#define C_SELF_POWERED  (1U<<6)
+#define C_REMOTE_WAKEUP (1U<<5)
+
+/* bMaxPower in configuration descriptor */
+#define C_POWER(mA)     ((mA)/2)
+
+/* bmAttributes in endpoint descriptor */
+#define E_CONTROL       (0x00)
+#define E_ISOCHRONOUS   (0x01)
+#define E_BULK          (0x02)
+#define E_INTERRUPT     (0x03)
+
+/* For isochronous endpoints only: */
+#define E_NO_SYNCHRONIZATION    (0x00)
+#define E_ASYNCHRONOUS          (0x04)
+#define E_ADAPTIVE              (0x08)
+#define E_SYNCHRONOUS           (0x0C)
+#define E_DATA                  (0x00)
+#define E_FEEDBACK              (0x10)
+#define E_IMPLICIT_FEEDBACK     (0x20)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBDevice.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,1005 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+
+#include "USBEndpoints.h"
+#include "USBDevice.h"
+#include "USBDescriptor.h"
+
+//#define DEBUG
+
+/* Device status */
+#define DEVICE_STATUS_SELF_POWERED  (1U<<0)
+#define DEVICE_STATUS_REMOTE_WAKEUP (1U<<1)
+
+/* Endpoint status */
+#define ENDPOINT_STATUS_HALT        (1U<<0)
+
+/* Standard feature selectors */
+#define DEVICE_REMOTE_WAKEUP        (1)
+#define ENDPOINT_HALT               (0)
+
+/* Macro to convert wIndex endpoint number to physical endpoint number */
+#define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + \
+    ((endpoint & 0x80) ? 1 : 0))
+
+
+bool USBDevice::requestGetDescriptor(void)
+{
+    bool success = false;
+#ifdef DEBUG
+    printf("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue));
+#endif
+    switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
+    {
+        case DEVICE_DESCRIPTOR:
+            if (deviceDesc() != NULL)
+            {
+                if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \
+                    && (deviceDesc()[1] == DEVICE_DESCRIPTOR))
+                {
+#ifdef DEBUG
+                    printf("device descr\r\n");
+#endif
+                    transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
+                    transfer.ptr = deviceDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                }
+            }
+            break;
+        case CONFIGURATION_DESCRIPTOR:
+            if (configurationDesc() != NULL)
+            {
+                if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \
+                    && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR))
+                {
+#ifdef DEBUG
+                    printf("conf descr request\r\n");
+#endif
+                    /* Get wTotalLength */
+                    transfer.remaining = configurationDesc()[2] \
+                        | (configurationDesc()[3] << 8);
+
+                    transfer.ptr = configurationDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                }
+            }
+            break;
+        case STRING_DESCRIPTOR:
+#ifdef DEBUG
+            printf("str descriptor\r\n");
+#endif
+            switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
+            {
+                            case STRING_OFFSET_LANGID:
+#ifdef DEBUG
+                                printf("1\r\n");
+#endif
+                                transfer.remaining = stringLangidDesc()[0];
+                                transfer.ptr = stringLangidDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case STRING_OFFSET_IMANUFACTURER:
+#ifdef DEBUG
+                                printf("2\r\n");
+#endif
+                                transfer.remaining =  stringImanufacturerDesc()[0];
+                                transfer.ptr = stringImanufacturerDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case STRING_OFFSET_IPRODUCT:
+#ifdef DEBUG
+                                printf("3\r\n");
+#endif
+                                transfer.remaining = stringIproductDesc()[0];
+                                transfer.ptr = stringIproductDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case STRING_OFFSET_ISERIAL:
+#ifdef DEBUG
+                                printf("4\r\n");
+#endif
+                                transfer.remaining = stringIserialDesc()[0];
+                                transfer.ptr = stringIserialDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case STRING_OFFSET_ICONFIGURATION:
+#ifdef DEBUG
+                                printf("5\r\n");
+#endif
+                                transfer.remaining = stringIConfigurationDesc()[0];
+                                transfer.ptr = stringIConfigurationDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case STRING_OFFSET_IINTERFACE:
+#ifdef DEBUG
+                                printf("6\r\n");
+#endif
+                                transfer.remaining = stringIinterfaceDesc()[0];
+                                transfer.ptr = stringIinterfaceDesc();
+                                transfer.direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+            }
+            break;
+        case INTERFACE_DESCRIPTOR:
+#ifdef DEBUG
+            printf("interface descr\r\n");
+#endif
+        case ENDPOINT_DESCRIPTOR:
+#ifdef DEBUG
+            printf("endpoint descr\r\n");
+#endif
+            /* TODO: Support is optional, not implemented here */
+            break;
+        default:
+#ifdef DEBUG
+            printf("ERROR\r\n");
+#endif
+            break;
+    }
+
+    return success;
+}
+
+void USBDevice::decodeSetupPacket(uint8_t *data, SETUP_PACKET *packet)
+{
+    /* Fill in the elements of a SETUP_PACKET structure from raw data */
+    packet->bmRequestType.dataTransferDirection = (data[0] & 0x80) >> 7;
+    packet->bmRequestType.Type = (data[0] & 0x60) >> 5;
+    packet->bmRequestType.Recipient = data[0] & 0x1f;
+    packet->bRequest = data[1];
+    packet->wValue = (data[2] | (uint16_t)data[3] << 8);
+    packet->wIndex = (data[4] | (uint16_t)data[5] << 8);
+    packet->wLength = (data[6] | (uint16_t)data[7] << 8);
+}
+
+
+bool USBDevice::controlOut(void)
+{
+    /* Control transfer data OUT stage */
+    uint8_t buffer[MAX_PACKET_SIZE_EP0];
+    uint32_t packetSize;
+
+    /* Check we should be transferring data OUT */
+    if (transfer.direction != HOST_TO_DEVICE)
+    {
+#if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
+        /*
+         * We seem to have a pending device-to-host transfer.  The host must have
+         * sent a new control request without waiting for us to finish processing
+         * the previous one.  This appears to happen when we're connected to certain 
+         * USB 3.0 host chip set. Do a zeor-length send to tell the host we're not
+         * ready for the new request - that'll make it resend - and then just
+         * pretend we were successful here so that the pending transfer can finish.
+         */
+         uint8_t buf[1] = { 0 };
+         EP0write(buf, 0);
+         
+         /* execute our pending ttransfer */
+         controlIn();
+         
+         /* indicate success */
+         return true;
+ #else
+         /* for other platforms, count on the HAL to handle this case */
+         return false;
+ #endif
+    }
+
+    /* Read from endpoint */
+    packetSize = EP0getReadResult(buffer);
+
+    /* Check if transfer size is valid */
+    if (packetSize > transfer.remaining)
+    {
+        /* Too big */
+        return false;
+    }
+
+    /* Update transfer */
+    transfer.ptr += packetSize;
+    transfer.remaining -= packetSize;
+
+    /* Check if transfer has completed */
+    if (transfer.remaining == 0)
+    {
+        /* Transfer completed */
+        if (transfer.notify)
+        {
+            /* Notify class layer. */
+            USBCallback_requestCompleted(buffer, packetSize);
+            transfer.notify = false;
+        }
+        /* Status stage */
+        EP0write(NULL, 0);
+    }
+    else
+    {
+        EP0read();
+    }
+
+    return true;
+}
+
+bool USBDevice::controlIn(void)
+{
+    /* Control transfer data IN stage */
+    uint32_t packetSize;
+
+    /* Check if transfer has completed (status stage transactions */
+    /* also have transfer.remaining == 0) */
+    if (transfer.remaining == 0)
+    {
+        if (transfer.zlp)
+        {
+            /* Send zero length packet */
+            EP0write(NULL, 0);
+            transfer.zlp = false;
+        }
+
+        /* Transfer completed */
+        if (transfer.notify)
+        {
+            /* Notify class layer. */
+            USBCallback_requestCompleted(NULL, 0);
+            transfer.notify = false;
+        }
+
+        EP0read();
+        EP0readStage();
+
+        /* Completed */
+        return true;
+    }
+
+    /* Check we should be transferring data IN */
+    if (transfer.direction != DEVICE_TO_HOST)
+    {
+        return false;
+    }
+
+    packetSize = transfer.remaining;
+
+    if (packetSize > MAX_PACKET_SIZE_EP0)
+    {
+        packetSize = MAX_PACKET_SIZE_EP0;
+    }
+
+    /* Write to endpoint */
+    EP0write(transfer.ptr, packetSize);
+
+    /* Update transfer */
+    transfer.ptr += packetSize;
+    transfer.remaining -= packetSize;
+
+    return true;
+}
+
+bool USBDevice::requestSetAddress(void)
+{
+    /* Set the device address */
+    setAddress(transfer.setup.wValue);
+
+    if (transfer.setup.wValue == 0)
+    {
+        device.state = DEFAULT;
+    }
+    else
+    {
+        device.state = ADDRESS;
+    }
+
+    return true;
+}
+
+bool USBDevice::requestSetConfiguration(void)
+{
+
+    device.configuration = transfer.setup.wValue;
+    /* Set the device configuration */
+    if (device.configuration == 0)
+    {
+        /* Not configured */
+        unconfigureDevice();
+        device.state = ADDRESS;
+    }
+    else
+    {
+        if (USBCallback_setConfiguration(device.configuration))
+        {
+            /* Valid configuration */
+            configureDevice();
+            device.state = CONFIGURED;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool USBDevice::requestGetConfiguration(void)
+{
+    /* Send the device configuration */
+    transfer.ptr = &device.configuration;
+    transfer.remaining = sizeof(device.configuration);
+    transfer.direction = DEVICE_TO_HOST;
+    return true;
+}
+
+bool USBDevice::requestGetInterface(void)
+{
+    /* Return the selected alternate setting for an interface */
+
+    if (device.state != CONFIGURED)
+    {
+        return false;
+    }
+
+    /* Send the alternate setting */
+    transfer.setup.wIndex = currentInterface;
+    transfer.ptr = &currentAlternate;
+    transfer.remaining = sizeof(currentAlternate);
+    transfer.direction = DEVICE_TO_HOST;
+    return true;
+}
+
+bool USBDevice::requestSetInterface(void)
+{
+    bool success = false;
+    if(USBCallback_setInterface(transfer.setup.wIndex, transfer.setup.wValue))
+    {
+        success = true;
+        currentInterface = transfer.setup.wIndex;
+        currentAlternate = transfer.setup.wValue;
+    }
+    return success;
+}
+
+bool USBDevice::requestSetFeature()
+{
+    bool success = false;
+
+    if (device.state != CONFIGURED)
+    {
+        /* Endpoint or interface must be zero */
+        if (transfer.setup.wIndex != 0)
+        {
+            return false;
+        }
+    }
+
+    switch (transfer.setup.bmRequestType.Recipient)
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Remote wakeup feature not supported */
+            break;
+        case ENDPOINT_RECIPIENT:
+            if (transfer.setup.wValue == ENDPOINT_HALT)
+            {
+                /* TODO: We should check that the endpoint number is valid */
+                stallEndpoint(
+                    WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
+                success = true;
+            }
+            break;
+        default:
+            break;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestClearFeature()
+{
+    bool success = false;
+
+    if (device.state != CONFIGURED)
+    {
+        /* Endpoint or interface must be zero */
+        if (transfer.setup.wIndex != 0)
+        {
+            return false;
+        }
+    }
+
+    switch (transfer.setup.bmRequestType.Recipient)
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Remote wakeup feature not supported */
+            break;
+        case ENDPOINT_RECIPIENT:
+            /* TODO: We should check that the endpoint number is valid */
+            if (transfer.setup.wValue == ENDPOINT_HALT)
+            {
+                unstallEndpoint( WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
+                success = true;
+            }
+            break;
+        default:
+            break;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestGetStatus(void)
+{
+    static uint16_t status;
+    bool success = false;
+
+    if (device.state != CONFIGURED)
+    {
+        /* Endpoint or interface must be zero */
+        if (transfer.setup.wIndex != 0)
+        {
+            return false;
+        }
+    }
+
+    switch (transfer.setup.bmRequestType.Recipient)
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Currently only supports self powered devices */
+            status = DEVICE_STATUS_SELF_POWERED;
+            success = true;
+            break;
+        case INTERFACE_RECIPIENT:
+            status = 0;
+            success = true;
+            break;
+        case ENDPOINT_RECIPIENT:
+            /* TODO: We should check that the endpoint number is valid */
+            if (getEndpointStallState(
+                WINDEX_TO_PHYSICAL(transfer.setup.wIndex)))
+            {
+                status = ENDPOINT_STATUS_HALT;
+            }
+            else
+            {
+                status = 0;
+            }
+            success = true;
+            break;
+        default:
+            break;
+    }
+
+    if (success)
+    {
+        /* Send the status */
+        transfer.ptr = (uint8_t *)&status; /* Assumes little endian */
+        transfer.remaining = sizeof(status);
+        transfer.direction = DEVICE_TO_HOST;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestSetup(void)
+{
+    bool success = false;
+
+    /* Process standard requests */
+    if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE))
+    {
+        switch (transfer.setup.bRequest)
+        {
+             case GET_STATUS:
+                 success = requestGetStatus();
+                 break;
+             case CLEAR_FEATURE:
+                 success = requestClearFeature();
+                 break;
+             case SET_FEATURE:
+                 success = requestSetFeature();
+                 break;
+             case SET_ADDRESS:
+                success = requestSetAddress();
+                 break;
+             case GET_DESCRIPTOR:
+                 success = requestGetDescriptor();
+                 break;
+             case SET_DESCRIPTOR:
+                 /* TODO: Support is optional, not implemented here */
+                 success = false;
+                 break;
+             case GET_CONFIGURATION:
+                 success = requestGetConfiguration();
+                 break;
+             case SET_CONFIGURATION:
+                 success = requestSetConfiguration();
+                 break;
+             case GET_INTERFACE:
+                 success = requestGetInterface();
+                 break;
+             case SET_INTERFACE:
+                 success = requestSetInterface();
+                 break;
+             default:
+                 break;
+        }
+    }
+
+    return success;
+}
+
+bool USBDevice::controlSetup(void)
+{
+    bool success = false;
+
+    /* Control transfer setup stage */
+    uint8_t buffer[MAX_PACKET_SIZE_EP0];
+
+    EP0setup(buffer);
+
+    /* Initialise control transfer state */
+    decodeSetupPacket(buffer, &transfer.setup);
+    transfer.ptr = NULL;
+    transfer.remaining = 0;
+    transfer.direction = 0;
+    transfer.zlp = false;
+    transfer.notify = false;
+
+#ifdef DEBUG
+    printf("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n",transfer.setup.bmRequestType.dataTransferDirection,
+                                                                                                                                   transfer.setup.bmRequestType.Type,
+                                                                                                                                   transfer.setup.bmRequestType.Recipient,
+                                                                                                                                   transfer.setup.bRequest,
+                                                                                                                                   transfer.setup.wValue,
+                                                                                                                                   transfer.setup.wIndex,
+                                                                                                                                   transfer.setup.wLength);
+#endif
+
+    /* Class / vendor specific */
+    success = USBCallback_request();
+
+    if (!success)
+    {
+        /* Standard requests */
+        if (!requestSetup())
+        {
+#ifdef DEBUG
+            printf("fail!!!!\r\n");
+#endif
+            return false;
+        }
+    }
+
+    /* Check transfer size and direction */
+    if (transfer.setup.wLength>0)
+    {
+        if (transfer.setup.bmRequestType.dataTransferDirection \
+            == DEVICE_TO_HOST)
+        {
+            /* IN data stage is required */
+            if (transfer.direction != DEVICE_TO_HOST)
+            {
+                return false;
+            }
+
+            /* Transfer must be less than or equal to the size */
+            /* requested by the host */
+            if (transfer.remaining > transfer.setup.wLength)
+            {
+                transfer.remaining = transfer.setup.wLength;
+            }
+        }
+        else
+        {
+
+            /* OUT data stage is required */
+            if (transfer.direction != HOST_TO_DEVICE)
+            {
+                return false;
+            }
+
+            /* Transfer must be equal to the size requested by the host */
+            if (transfer.remaining != transfer.setup.wLength)
+            {
+                return false;
+            }
+        }
+    }
+    else
+    {
+        /* No data stage; transfer size must be zero */
+        if (transfer.remaining != 0)
+        {
+            return false;
+        }
+    }
+
+    /* Data or status stage if applicable */
+    if (transfer.setup.wLength>0)
+    {
+        if (transfer.setup.bmRequestType.dataTransferDirection \
+            == DEVICE_TO_HOST)
+        {
+            /* Check if we'll need to send a zero length packet at */
+            /* the end of this transfer */
+            if (transfer.setup.wLength > transfer.remaining)
+            {
+                /* Device wishes to transfer less than host requested */
+                if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0)
+                {
+                    /* Transfer is a multiple of EP0 max packet size */
+                    transfer.zlp = true;
+                }
+            }
+
+            /* IN stage */
+            controlIn();
+        }
+        else
+        {
+            /* OUT stage */
+            EP0read();
+        }
+    }
+    else
+    {
+        /* Status stage */
+        EP0write(NULL, 0);
+    }
+
+    return true;
+}
+
+void USBDevice::busReset(void)
+{
+    device.state = DEFAULT;
+    device.configuration = 0;
+    device.suspended = false;
+
+    /* Call class / vendor specific busReset function */
+    USBCallback_busReset();
+}
+
+void USBDevice::EP0setupCallback(void)
+{
+    /* Endpoint 0 setup event */
+    if (!controlSetup())
+    {
+        /* Protocol stall */
+        EP0stall();
+    }
+
+    /* Return true if an OUT data stage is expected */
+}
+
+void USBDevice::EP0out(void)
+{
+    /* Endpoint 0 OUT data event */
+    if (!controlOut())
+    {
+        /* Protocol stall; this will stall both endpoints */
+        EP0stall();
+    }
+}
+
+void USBDevice::EP0in(void)
+{
+#ifdef DEBUG
+    printf("EP0IN\r\n");
+#endif
+    /* Endpoint 0 IN data event */
+    if (!controlIn())
+    {
+        /* Protocol stall; this will stall both endpoints */
+        EP0stall();
+    }
+}
+
+bool USBDevice::configured(void)
+{
+    /* Returns true if device is in the CONFIGURED state */
+    return (device.state == CONFIGURED);
+}
+
+void USBDevice::connect(bool blocking)
+{
+    /* Connect device */
+    USBHAL::connect();
+
+    if (blocking) {
+        /* Block if not configured */
+        while (!configured());
+    }
+}
+
+void USBDevice::disconnect(void)
+{
+    /* Disconnect device */
+    USBHAL::disconnect();
+    
+    /* Set initial device state */
+    device.state = POWERED;
+    device.configuration = 0;
+    device.suspended = false;
+}
+
+CONTROL_TRANSFER * USBDevice::getTransferPtr(void)
+{
+    return &transfer;
+}
+
+bool USBDevice::addEndpoint(uint8_t endpoint, uint32_t maxPacket)
+{
+    return realiseEndpoint(endpoint, maxPacket, 0);
+}
+
+bool USBDevice::addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket)
+{
+    /* For interrupt endpoints only */
+    return realiseEndpoint(endpoint, maxPacket, RATE_FEEDBACK_MODE);
+}
+
+uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
+{
+    /* Find a descriptor within the list of descriptors */
+    /* following a configuration descriptor. */
+    uint16_t wTotalLength;
+    uint8_t *ptr;
+
+    if (configurationDesc() == NULL)
+    {
+        return NULL;
+    }
+
+    /* Check this is a configuration descriptor */
+    if ((configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH) \
+            || (configurationDesc()[1] != CONFIGURATION_DESCRIPTOR))
+    {
+        return NULL;
+    }
+
+    wTotalLength = configurationDesc()[2] | (configurationDesc()[3] << 8);
+
+    /* Check there are some more descriptors to follow */
+    if (wTotalLength <= (CONFIGURATION_DESCRIPTOR_LENGTH+2))
+    /* +2 is for bLength and bDescriptorType of next descriptor */
+    {
+        return NULL;
+    }
+
+    /* Start at first descriptor after the configuration descriptor */
+    ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]);
+
+    do {
+        if (ptr[1] /* bDescriptorType */ == descriptorType)
+        {
+            /* Found */
+            return ptr;
+        }
+
+        /* Skip to next descriptor */
+        ptr += ptr[0]; /* bLength */
+    } while (ptr < (configurationDesc() + wTotalLength));
+
+    /* Reached end of the descriptors - not found */
+    return NULL;
+}
+
+
+void USBDevice::connectStateChanged(unsigned int connected)
+{
+}
+
+void USBDevice::suspendStateChanged(unsigned int suspended)
+{
+}
+
+
+USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release){
+    VENDOR_ID = vendor_id;
+    PRODUCT_ID = product_id;
+    PRODUCT_RELEASE = product_release;
+
+    /* Set initial device state */
+    device.state = POWERED;
+    device.configuration = 0;
+    device.suspended = false;
+};
+
+
+bool USBDevice::readStart(uint8_t endpoint, uint32_t maxSize)
+{
+    return endpointRead(endpoint, maxSize) == EP_PENDING;
+}
+
+
+bool USBDevice::write(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize)
+{
+    EP_STATUS result;
+
+    if (size > maxSize)
+    {
+        return false;
+    }
+
+
+    if(!configured()) {
+        return false;
+    }
+
+    /* Send report */
+    result = endpointWrite(endpoint, buffer, size);
+
+    if (result != EP_PENDING)
+    {
+        return false;
+    }
+
+    /* Wait for completion */
+    do {
+        result = endpointWriteResult(endpoint);
+    } while ((result == EP_PENDING) && configured());
+
+    return (result == EP_COMPLETED);
+}
+
+
+bool USBDevice::writeNB(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize)
+{
+    EP_STATUS result;
+
+    if (size > maxSize)
+    {
+        return false;
+    }
+
+    if(!configured()) {
+        return false;
+    }
+
+    /* Send report */
+    result = endpointWrite(endpoint, buffer, size);
+
+    if (result != EP_PENDING)
+    {
+        return false;
+    }
+
+    result = endpointWriteResult(endpoint);
+
+    return (result == EP_COMPLETED);
+}
+
+
+
+bool USBDevice::readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize)
+{
+    EP_STATUS result;
+
+    if(!configured()) {
+        return false;
+    }
+
+    /* Wait for completion */
+    do {
+        result = endpointReadResult(endpoint, buffer, size);
+    } while ((result == EP_PENDING) && configured());
+
+    return (result == EP_COMPLETED);
+}
+
+
+bool USBDevice::readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize)
+{
+    EP_STATUS result;
+
+    if(!configured()) {
+        return false;
+    }
+
+    result = endpointReadResult(endpoint, buffer, size);
+
+    return (result == EP_COMPLETED);
+}
+
+
+
+uint8_t * USBDevice::deviceDesc() {
+    static uint8_t deviceDescriptor[] = {
+        DEVICE_DESCRIPTOR_LENGTH,       /* bLength */
+        DEVICE_DESCRIPTOR,              /* bDescriptorType */
+        LSB(USB_VERSION_2_0),           /* bcdUSB (LSB) */
+        MSB(USB_VERSION_2_0),           /* bcdUSB (MSB) */
+        0x00,                           /* bDeviceClass */
+        0x00,                           /* bDeviceSubClass */
+        0x00,                           /* bDeviceprotocol */
+        MAX_PACKET_SIZE_EP0,            /* bMaxPacketSize0 */
+        (uint8_t)(LSB(VENDOR_ID)),                 /* idVendor (LSB) */
+        (uint8_t)(MSB(VENDOR_ID)),                 /* idVendor (MSB) */
+        (uint8_t)(LSB(PRODUCT_ID)),                /* idProduct (LSB) */
+        (uint8_t)(MSB(PRODUCT_ID)),                /* idProduct (MSB) */
+        (uint8_t)(LSB(PRODUCT_RELEASE)),           /* bcdDevice (LSB) */
+        (uint8_t)(MSB(PRODUCT_RELEASE)),           /* bcdDevice (MSB) */
+        STRING_OFFSET_IMANUFACTURER,    /* iManufacturer */
+        STRING_OFFSET_IPRODUCT,         /* iProduct */
+        STRING_OFFSET_ISERIAL,          /* iSerialNumber */
+        0x01                            /* bNumConfigurations */
+    };
+    return deviceDescriptor;
+}
+
+uint8_t * USBDevice::stringLangidDesc() {
+    static uint8_t stringLangidDescriptor[] = {
+        0x04,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        0x09,0x04,          /*bString Lang ID - 0x0409 - English*/
+    };
+    return stringLangidDescriptor;
+}
+
+uint8_t * USBDevice::stringImanufacturerDesc() {
+    static uint8_t stringImanufacturerDescriptor[] = {
+        0x12,                                            /*bLength*/
+        STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
+        'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/
+    };
+    return stringImanufacturerDescriptor;
+}
+
+uint8_t * USBDevice::stringIserialDesc() {
+    static uint8_t stringIserialDescriptor[] = {
+        0x16,                                                           /*bLength*/
+        STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
+        '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0,    /*bString iSerial - 0123456789*/
+    };
+    return stringIserialDescriptor;
+}
+
+uint8_t * USBDevice::stringIConfigurationDesc() {
+    static uint8_t stringIconfigurationDescriptor[] = {
+        0x06,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        '0',0,'1',0,        /*bString iConfiguration - 01*/
+    };
+    return stringIconfigurationDescriptor;
+}
+
+uint8_t * USBDevice::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x08,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        'U',0,'S',0,'B',0,  /*bString iInterface - USB*/
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBDevice::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       /*bLength*/
+        STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
+        'U',0,'S',0,'B',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 /*bString iProduct - USB DEVICE*/
+    };
+    return stringIproductDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBDevice.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,271 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBDEVICE_H
+#define USBDEVICE_H
+
+#include "mbed.h"
+#include "USBDevice_Types.h"
+#include "USBHAL.h"
+
+class USBDevice: public USBHAL
+{
+public:
+    USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release);
+
+    /*
+    * Check if the device is configured
+    *
+    * @returns true if configured, false otherwise
+    */
+    bool configured(void);
+
+    /*
+    * Connect a device
+    *
+    * @param blocking: block if not configured
+    */
+    void connect(bool blocking = true);
+
+    /*
+    * Disconnect a device
+    */
+    void disconnect(void);
+
+    /*
+    * Add an endpoint
+    *
+    * @param endpoint endpoint which will be added
+    * @param maxPacket Maximum size of a packet which can be sent for this endpoint
+    * @returns true if successful, false otherwise
+    */
+    bool addEndpoint(uint8_t endpoint, uint32_t maxPacket);
+
+    /*
+    * Start a reading on a certain endpoint.
+    * You can access the result of the reading by USBDevice_read
+    *
+    * @param endpoint endpoint which will be read
+    * @param maxSize the maximum length that can be read
+    * @return true if successful
+    */
+    bool readStart(uint8_t endpoint, uint32_t maxSize);
+
+    /*
+    * Read a certain endpoint. Before calling this function, USBUSBDevice_readStart
+    * must be called.
+    *
+    * Warning: blocking
+    *
+    * @param endpoint endpoint which will be read
+    * @param buffer buffer will be filled with the data received
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize);
+
+    /*
+    * Read a certain endpoint.
+    *
+    * Warning: non blocking
+    *
+    * @param endpoint endpoint which will be read
+    * @param buffer buffer will be filled with the data received (if data are available)
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize);
+
+    /*
+    * Write a certain endpoint.
+    *
+    * Warning: blocking
+    *
+    * @param endpoint endpoint to write
+    * @param buffer data contained in buffer will be write
+    * @param size the number of bytes to write
+    * @param maxSize the maximum length that can be written on this endpoint
+    */
+    bool write(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize);
+
+
+    /*
+    * Write a certain endpoint.
+    *
+    * Warning: non blocking
+    *
+    * @param endpoint endpoint to write
+    * @param buffer data contained in buffer will be write
+    * @param size the number of bytes to write
+    * @param maxSize the maximum length that can be written on this endpoint
+    */
+    bool writeNB(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize);
+
+
+    /*
+    * Called by USBDevice layer on bus reset. Warning: Called in ISR context
+    *
+    * May be used to reset state
+    */
+    virtual void USBCallback_busReset(void) {};
+
+    /*
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request() { return false; };
+
+    /*
+    * Called by USBDevice on Endpoint0 request completion
+    * if the 'notify' flag has been set to true. Warning: Called in ISR context
+    *
+    * In this case it is used to indicate that a HID report has
+    * been received from the host on endpoint 0
+    *
+    * @param buf buffer received on endpoint 0
+    * @param length length of this buffer
+    */
+    virtual void USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {};
+
+    /*
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    */
+    virtual bool USBCallback_setConfiguration(uint8_t configuration) { return false; };
+
+    /*
+     * Called by USBDevice layer. Set interface/alternate of the device.
+     *
+     * @param interface Number of the interface to be configured
+     * @param alternate Number of the alternate to be configured
+     * @returns true if class handles this request
+     */
+    virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate) { return false; };
+
+    /*
+    * Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the device descriptor
+    */
+    virtual uint8_t * deviceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc(){return NULL;};
+
+    /*
+    * Get string lang id descriptor
+    *
+    * @return pointer to the string lang id descriptor
+    */
+    virtual uint8_t * stringLangidDesc();
+
+    /*
+    * Get string manufacturer descriptor
+    *
+    * @returns pointer to the string manufacturer descriptor
+    */
+    virtual uint8_t * stringImanufacturerDesc();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+
+    /*
+    * Get string serial descriptor
+    *
+    * @returns pointer to the string serial descriptor
+    */
+    virtual uint8_t * stringIserialDesc();
+
+    /*
+    * Get string configuration descriptor
+    *
+    * @returns pointer to the string configuration descriptor
+    */
+    virtual uint8_t * stringIConfigurationDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+
+    /*
+    * Get the length of the report descriptor
+    *
+    * @returns length of the report descriptor
+    */
+    virtual uint16_t reportDescLength() { return 0; };
+
+
+
+protected:
+    virtual void busReset(void);
+    virtual void EP0setupCallback(void);
+    virtual void EP0out(void);
+    virtual void EP0in(void);
+    virtual void connectStateChanged(unsigned int connected);
+    virtual void suspendStateChanged(unsigned int suspended);
+    uint8_t * findDescriptor(uint8_t descriptorType);
+    CONTROL_TRANSFER * getTransferPtr(void);
+
+    uint16_t VENDOR_ID;
+    uint16_t PRODUCT_ID;
+    uint16_t PRODUCT_RELEASE;
+
+private:
+    bool addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket);
+    bool requestGetDescriptor(void);
+    bool controlOut(void);
+    bool controlIn(void);
+    bool requestSetAddress(void);
+    bool requestSetConfiguration(void);
+    bool requestSetFeature(void);
+    bool requestClearFeature(void);
+    bool requestGetStatus(void);
+    bool requestSetup(void);
+    bool controlSetup(void);
+    void decodeSetupPacket(uint8_t *data, SETUP_PACKET *packet);
+    bool requestGetConfiguration(void);
+    bool requestGetInterface(void);
+    bool requestSetInterface(void);
+
+    CONTROL_TRANSFER transfer;
+    USB_DEVICE device;
+
+    uint16_t currentInterface;
+    uint8_t currentAlternate;
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBDevice_Types.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,85 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBDEVICE_TYPES_H
+#define USBDEVICE_TYPES_H
+
+#include <stdint.h>
+
+/* Standard requests */
+#define GET_STATUS        (0)
+#define CLEAR_FEATURE     (1)
+#define SET_FEATURE       (3)
+#define SET_ADDRESS       (5)
+#define GET_DESCRIPTOR    (6)
+#define SET_DESCRIPTOR    (7)
+#define GET_CONFIGURATION (8)
+#define SET_CONFIGURATION (9)
+#define GET_INTERFACE     (10)
+#define SET_INTERFACE     (11)
+
+/* bmRequestType.dataTransferDirection */
+#define HOST_TO_DEVICE (0)
+#define DEVICE_TO_HOST (1)
+
+/* bmRequestType.Type*/
+#define STANDARD_TYPE  (0)
+#define CLASS_TYPE     (1)
+#define VENDOR_TYPE    (2)
+#define RESERVED_TYPE  (3)
+
+/* bmRequestType.Recipient */
+#define DEVICE_RECIPIENT    (0)
+#define INTERFACE_RECIPIENT (1)
+#define ENDPOINT_RECIPIENT  (2)
+#define OTHER_RECIPIENT     (3)
+
+/* Descriptors */
+#define DESCRIPTOR_TYPE(wValue)  (wValue >> 8)
+#define DESCRIPTOR_INDEX(wValue) (wValue & 0xff)
+
+typedef struct {
+    struct {
+        uint8_t dataTransferDirection;
+        uint8_t Type;
+        uint8_t Recipient;
+    } bmRequestType;
+    uint8_t  bRequest;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+} SETUP_PACKET;
+
+typedef struct {
+    SETUP_PACKET setup;
+    uint8_t *ptr;
+    uint32_t remaining;
+    uint8_t direction;
+    bool zlp;
+    bool notify;
+} CONTROL_TRANSFER;
+
+typedef enum {ATTACHED, POWERED, DEFAULT, ADDRESS, CONFIGURED} DEVICE_STATE;
+
+typedef struct {
+    volatile DEVICE_STATE state;
+    uint8_t configuration;
+    bool suspended;
+} USB_DEVICE;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,58 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBENDPOINTS_H
+#define USBENDPOINTS_H
+
+/* SETUP packet size */
+#define SETUP_PACKET_SIZE (8)
+
+/* Options flags for configuring endpoints */
+#define DEFAULT_OPTIONS     (0)
+#define SINGLE_BUFFERED     (1U << 0)
+#define ISOCHRONOUS         (1U << 1)
+#define RATE_FEEDBACK_MODE  (1U << 2) /* Interrupt endpoints only */
+
+/* Endpoint transfer status, for endpoints > 0 */
+typedef enum {
+    EP_COMPLETED,   /* Transfer completed */
+    EP_PENDING,     /* Transfer in progress */
+    EP_INVALID,     /* Invalid parameter */
+    EP_STALLED,     /* Endpoint stalled */
+} EP_STATUS;
+
+/* Include configuration for specific target */
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC2460) || defined(TARGET_LPC4088_DM)
+#include "USBEndpoints_LPC17_LPC23.h"
+#elif defined(TARGET_LPC11UXX) || defined(TARGET_LPC1347) || defined (TARGET_LPC11U6X) || defined (TARGET_LPC1549)
+#include "USBEndpoints_LPC11U.h"
+#elif defined(TARGET_KL25Z) | defined(TARGET_KL26Z) | defined(TARGET_KL27Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D50M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
+#include "USBEndpoints_KL25Z.h"
+#elif defined (TARGET_STM32F4)
+#include "USBEndpoints_STM32F4.h"
+#elif defined (TARGET_RZ_A1H) || defined (TARGET_VK_RZ_A1H)
+#include "USBEndpoints_RZ_A1H.h"
+#elif defined(TARGET_Maxim)
+#include "USBEndpoints_Maxim.h"
+#elif defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32HG_STK3400)
+#include "USBEndpoints_EFM32.h"
+#else
+#error "Unknown target type"
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints_EFM32.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,65 @@
+
+#ifndef TARGET_EFM32HG_STK3400
+# define NUMBER_OF_LOGICAL_ENDPOINTS   (6)
+#else
+# define NUMBER_OF_LOGICAL_ENDPOINTS   (3)
+#endif
+
+#define NUMBER_OF_PHYSICAL_ENDPOINTS  (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+#define NUMBER_OF_ENDPOINTS           (NUMBER_OF_PHYSICAL_ENDPOINTS + 2)  /* Includes EP0 */
+
+#define EP0OUT      (0)
+#define EP0IN       (1)
+#define EP1OUT      (2)
+#define EP1IN       (3)
+#define EP2OUT      (4)
+#define EP2IN       (5)
+#define EP3OUT      (6)
+#define EP3IN       (7)
+#ifndef TARGET_EFM32HG_STK3400
+# define EP4OUT     (8)
+# define EP4IN      (9)
+# define EP5OUT     (10)
+# define EP5IN      (11)
+# define EP6OUT     (12)
+# define EP6IN      (13)
+#endif
+
+#define USB_EP_TO_INDEX(ep) (ep)
+#define USB_EP_TO_ADDR(ep)  (((ep)>>1) | (((ep) & 1   ) ? 0x80 : 0x00))
+#define USB_ADDR_TO_EP(ep)  (((ep)<<1) | (((ep) & 0x80) ? 0x01 : 0x00))
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0   64
+#define MAX_PACKET_SIZE_EP1   64
+#define MAX_PACKET_SIZE_EP2   64
+#define MAX_PACKET_SIZE_EP3   64
+#ifndef TARGET_EFM32HG_STK3400
+# define MAX_PACKET_SIZE_EP4  64
+# define MAX_PACKET_SIZE_EP5  64
+# define MAX_PACKET_SIZE_EP6  64
+#endif
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoints */
+#define EPBULK_OUT            EP2OUT
+#define EPBULK_IN             EP2IN
+#define EPBULK_OUT_callback   EP2_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoints */
+#define EPINT_OUT             EP1OUT
+#define EPINT_IN              EP1IN
+#define EPINT_OUT_callback    EP1_OUT_callback
+#define EPINT_IN_callback     EP1_IN_callback
+/* Isochronous endpoints */
+#define EPISO_OUT             EP3OUT
+#define EPISO_IN              EP3IN
+#define EPISO_OUT_callback    EP3_OUT_callback
+#define EPISO_IN_callback     EP3_IN_callback
+
+#define MAX_PACKET_SIZE_EPBULK  64
+#define MAX_PACKET_SIZE_EPINT   64
+#define MAX_PACKET_SIZE_EPISO   1023
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints_KL25Z.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,99 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (16)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.   */
+/*      ----------------  */
+#define EP0OUT      (0)
+#define EP0IN       (1)
+#define EP1OUT      (2)
+#define EP1IN       (3)
+#define EP2OUT      (4)
+#define EP2IN       (5)
+#define EP3OUT      (6)
+#define EP3IN       (7)
+#define EP4OUT      (8)
+#define EP4IN       (9)
+#define EP5OUT      (10)
+#define EP5IN       (11)
+#define EP6OUT      (12)
+#define EP6IN       (13)
+#define EP7OUT      (14)
+#define EP7IN       (15)
+#define EP8OUT      (16)
+#define EP8IN       (17)
+#define EP9OUT      (18)
+#define EP9IN       (19)
+#define EP10OUT     (20)
+#define EP10IN      (21)
+#define EP11OUT     (22)
+#define EP11IN      (23)
+#define EP12OUT     (24)
+#define EP12IN      (25)
+#define EP13OUT     (26)
+#define EP13IN      (27)
+#define EP14OUT     (28)
+#define EP14IN      (29)
+#define EP15OUT     (30)
+#define EP15IN      (31)
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0  (64)
+#define MAX_PACKET_SIZE_EP1  (64)
+#define MAX_PACKET_SIZE_EP2  (64)
+#define MAX_PACKET_SIZE_EP3  (1023)
+#define MAX_PACKET_SIZE_EP4  (64)
+#define MAX_PACKET_SIZE_EP5  (64)
+#define MAX_PACKET_SIZE_EP6  (64)
+#define MAX_PACKET_SIZE_EP7  (64)
+#define MAX_PACKET_SIZE_EP8  (64)
+#define MAX_PACKET_SIZE_EP9  (64)
+#define MAX_PACKET_SIZE_EP10 (64)
+#define MAX_PACKET_SIZE_EP11 (64)
+#define MAX_PACKET_SIZE_EP12 (64)
+#define MAX_PACKET_SIZE_EP13 (64)
+#define MAX_PACKET_SIZE_EP14 (64)
+#define MAX_PACKET_SIZE_EP15 (64)
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoints */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+#define EPBULK_OUT_callback   EP2_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoints */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+#define EPINT_OUT_callback    EP1_OUT_callback
+#define EPINT_IN_callback     EP1_IN_callback
+/* Isochronous endpoints */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+#define EPISO_OUT_callback    EP3_OUT_callback
+#define EPISO_IN_callback     EP3_IN_callback
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints_LPC11U.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,71 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (5)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)       MaxPacket   DoubleBuffer  */
+/*      ----------------    ------------  ----------  ---           */
+#define EP0OUT      (0)  /* Control       64          No            */
+#define EP0IN       (1)  /* Control       64          No            */
+#define EP1OUT      (2)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP1IN       (3)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2OUT      (4)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2IN       (5)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3OUT      (6)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3IN       (7)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP4OUT      (8)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP4IN       (9)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0 (64)
+#define MAX_PACKET_SIZE_EP1 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP2 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP3 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP4 (64) /* Int/Bulk */
+
+#define MAX_PACKET_SIZE_EP1_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP2_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP3_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP4_ISO (1023) /* Isochronous */
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoint */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+#define EPBULK_OUT_callback   EP2_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoint */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+#define EPINT_OUT_callback    EP1_OUT_callback
+#define EPINT_IN_callback     EP1_IN_callback
+/* Isochronous endpoint */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+#define EPISO_OUT_callback    EP3_OUT_callback
+#define EPISO_IN_callback     EP3_IN_callback
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3_ISO)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints_LPC17_LPC23.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,99 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (16)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)       MaxPacket   DoubleBuffer  */
+/*      ----------------    ------------  ----------  ---           */
+#define EP0OUT      (0)  /* Control       64          No            */
+#define EP0IN       (1)  /* Control       64          No            */
+#define EP1OUT      (2)  /* Interrupt     64          No            */
+#define EP1IN       (3)  /* Interrupt     64          No            */
+#define EP2OUT      (4)  /* Bulk          64          Yes           */
+#define EP2IN       (5)  /* Bulk          64          Yes           */
+#define EP3OUT      (6)  /* Isochronous   1023        Yes           */
+#define EP3IN       (7)  /* Isochronous   1023        Yes           */
+#define EP4OUT      (8)  /* Interrupt     64          No            */
+#define EP4IN       (9)  /* Interrupt     64          No            */
+#define EP5OUT      (10) /* Bulk          64          Yes           */
+#define EP5IN       (11) /* Bulk          64          Yes           */
+#define EP6OUT      (12) /* Isochronous   1023        Yes           */
+#define EP6IN       (13) /* Isochronous   1023        Yes           */
+#define EP7OUT      (14) /* Interrupt     64          No            */
+#define EP7IN       (15) /* Interrupt     64          No            */
+#define EP8OUT      (16) /* Bulk          64          Yes           */
+#define EP8IN       (17) /* Bulk          64          Yes           */
+#define EP9OUT      (18) /* Isochronous   1023        Yes           */
+#define EP9IN       (19) /* Isochronous   1023        Yes           */
+#define EP10OUT     (20) /* Interrupt     64          No            */
+#define EP10IN      (21) /* Interrupt     64          No            */
+#define EP11OUT     (22) /* Bulk          64          Yes           */
+#define EP11IN      (23) /* Bulk          64          Yes           */
+#define EP12OUT     (24) /* Isochronous   1023        Yes           */
+#define EP12IN      (25) /* Isochronous   1023        Yes           */
+#define EP13OUT     (26) /* Interrupt     64          No            */
+#define EP13IN      (27) /* Interrupt     64          No            */
+#define EP14OUT     (28) /* Bulk          64          Yes           */
+#define EP14IN      (29) /* Bulk          64          Yes           */
+#define EP15OUT     (30) /* Bulk          64          Yes           */
+#define EP15IN      (31) /* Bulk          64          Yes           */
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0  (64)
+#define MAX_PACKET_SIZE_EP1  (64)
+#define MAX_PACKET_SIZE_EP2  (64)
+#define MAX_PACKET_SIZE_EP3  (1023)
+#define MAX_PACKET_SIZE_EP4  (64)
+#define MAX_PACKET_SIZE_EP5  (64)
+#define MAX_PACKET_SIZE_EP6  (1023)
+#define MAX_PACKET_SIZE_EP7  (64)
+#define MAX_PACKET_SIZE_EP8  (64)
+#define MAX_PACKET_SIZE_EP9  (1023)
+#define MAX_PACKET_SIZE_EP10 (64)
+#define MAX_PACKET_SIZE_EP11 (64)
+#define MAX_PACKET_SIZE_EP12 (1023)
+#define MAX_PACKET_SIZE_EP13 (64)
+#define MAX_PACKET_SIZE_EP14 (64)
+#define MAX_PACKET_SIZE_EP15 (64)
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoints */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+#define EPBULK_OUT_callback   EP2_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoints */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+#define EPINT_OUT_callback    EP1_OUT_callback
+#define EPINT_IN_callback     EP1_IN_callback
+/* Isochronous endpoints */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+#define EPISO_OUT_callback    EP3_OUT_callback
+#define EPISO_IN_callback     EP3_IN_callback
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints_Maxim.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS   (8)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS  (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+#define DIR_OUT       0x00
+#define DIR_IN        0x01
+#define EP_NUM(ep)    (ep >> 1)
+#define IN_EP(ep)     (ep & DIR_IN)
+#define OUT_EP(ep)    (!(ep & DIR_IN))
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.   */
+/*      ----------------  */
+#define EP0OUT      ((0 << 1) | DIR_OUT)
+#define EP0IN       ((0 << 1) | DIR_IN)
+#define EP1OUT      ((1 << 1) | DIR_OUT)
+#define EP1IN       ((1 << 1) | DIR_IN)
+#define EP2OUT      ((2 << 1) | DIR_OUT)
+#define EP2IN       ((2 << 1) | DIR_IN)
+#define EP3OUT      ((3 << 1) | DIR_OUT)
+#define EP3IN       ((3 << 1) | DIR_IN)
+#define EP4OUT      ((4 << 1) | DIR_OUT)
+#define EP4IN       ((4 << 1) | DIR_IN)
+#define EP5OUT      ((5 << 1) | DIR_OUT)
+#define EP5IN       ((5 << 1) | DIR_IN)
+#define EP6OUT      ((6 << 1) | DIR_OUT)
+#define EP6IN       ((6 << 1) | DIR_IN)
+#define EP7OUT      ((7 << 1) | DIR_OUT)
+#define EP7IN       ((7 << 1) | DIR_IN)
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0  (64)
+#define MAX_PACKET_SIZE_EP1  (64)
+#define MAX_PACKET_SIZE_EP2  (64)
+#define MAX_PACKET_SIZE_EP3  (64)
+#define MAX_PACKET_SIZE_EP4  (64)
+#define MAX_PACKET_SIZE_EP5  (64)
+#define MAX_PACKET_SIZE_EP6  (64)
+#define MAX_PACKET_SIZE_EP7  (64)
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoints */
+#define EPBULK_OUT  (EP1OUT)
+#define EPBULK_IN   (EP2IN)
+#define EPBULK_OUT_callback   EP1_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoints */
+#define EPINT_OUT   (EP3OUT)
+#define EPINT_IN    (EP4IN)
+#define EPINT_OUT_callback    EP3_OUT_callback
+#define EPINT_IN_callback     EP4_IN_callback
+/* Isochronous endpoints */
+/* NOT SUPPORTED - use invalid endpoint number to prevent built errors */
+#define EPISO_OUT   (EP0OUT)
+#define EPISO_IN    (EP0IN)
+
+#define MAX_PACKET_SIZE_EPBULK  (64)
+#define MAX_PACKET_SIZE_EPINT   (64)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints_RZ_A1H.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,85 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (16)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)   MaxSiz  DoubleBuf  pipe */
+/*      ----------------    --------- ------  ---------  ---- */
+#define EP0OUT      (0)  /* Control    256    No           0  */
+#define EP0IN       (1)  /* Control    256    No           0  */
+#define EP1OUT      (2)  /* Int         64    No           6  */
+#define EP1IN       (3)  /* Int         64    No           7  */
+#define EP2OUT      (4)  /* Bulk      2048    Yes          3  */
+#define EP2IN       (5)  /* Bulk      2048    Yes          4  */
+#define EP3OUT      (6)  /* Bulk/Iso  2048    Yes          1  */
+#define EP3IN       (7)  /* Bulk/Iso  2048    Yes          2  */
+/*following EP is not configured in sample program*/
+#define EP6IN       (8)  /* Bulk      2048    Yes          5  */
+#define EP8IN       (9)  /* Int        64     No           8  */
+#define EP9IN       (10) /* Bulk       512    Bulk         9  */
+#define EP10IN      (11) /* Int/Bulk  2048    Bulk        10  */
+#define EP11IN      (12) /* Bulk      2048    Yes         11  */
+#define EP12IN      (13) /* Bulk      2048    Yes         12  */
+#define EP13IN      (14) /* Bulk      2048    Yes         13  */
+#define EP14IN      (15) /* Bulk      2048    Yes         14  */
+#define EP15IN      (16) /* Bulk      2048    Yes         15  */
+
+/* Maximum Packet sizes */
+#define MAX_PACKET_SIZE_EP0   (64)      /*pipe0/pipe0: control      */
+#define MAX_PACKET_SIZE_EP1   (64)      /*pipe6/pipe7: interrupt    */
+#define MAX_PACKET_SIZE_EP2  (512)      /*pipe3/pipe4: bulk         */
+#define MAX_PACKET_SIZE_EP3  (512)      /*pipe1/pipe2: isochronous  */
+#define MAX_PACKET_SIZE_EP6   (64)      /*pipe5:    Note *1 */
+#define MAX_PACKET_SIZE_EP8   (64)      /*pipe7:    Note *1 */
+#define MAX_PACKET_SIZE_EP9  (512)      /*pipe8:    Note *1 */
+#define MAX_PACKET_SIZE_EP10 (512)      /*pipe9:    Note *1 */
+#define MAX_PACKET_SIZE_EP11 (512)      /*pipe10:   Note *1 */
+#define MAX_PACKET_SIZE_EP12 (512)      /*pipe11:   Note *1 */
+#define MAX_PACKET_SIZE_EP13 (512)      /*pipe12:   Note *1 */
+#define MAX_PACKET_SIZE_EP14 (512)      /*pipe13:   Note *1 */
+#define MAX_PACKET_SIZE_EP15 (512)      /*pipe14:   Note *1 */
+/* Note *1: This pipe is not configure in sample program */
+
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoints */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+#define EPBULK_OUT_callback   EP2_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoints */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+#define EPINT_OUT_callback    EP1_OUT_callback
+#define EPINT_IN_callback     EP1_IN_callback
+/* Isochronous endpoints */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+#define EPISO_OUT_callback    EP3_OUT_callback
+#define EPISO_IN_callback     EP3_IN_callback
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3)
+
+/*EOF*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBEndpoints_STM32F4.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,67 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (4)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)       MaxPacket   DoubleBuffer  */
+/*      ----------------    ------------  ----------  ---           */
+#define EP0OUT      (0)  /* Control       64          No            */
+#define EP0IN       (1)  /* Control       64          No            */
+#define EP1OUT      (2)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP1IN       (3)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2OUT      (4)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2IN       (5)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3OUT      (6)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3IN       (7)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0 (64)
+#define MAX_PACKET_SIZE_EP1 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP2 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP3 (64) /* Int/Bulk */
+
+#define MAX_PACKET_SIZE_EP1_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP2_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP3_ISO (1023) /* Isochronous */
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoint */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+#define EPBULK_OUT_callback   EP2_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoint */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+#define EPINT_OUT_callback    EP1_OUT_callback
+#define EPINT_IN_callback     EP1_IN_callback
+/* Isochronous endpoint */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+#define EPISO_OUT_callback    EP3_OUT_callback
+#define EPISO_IN_callback     EP3_IN_callback
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3_ISO)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,121 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBBUSINTERFACE_H
+#define USBBUSINTERFACE_H
+
+#include "mbed.h"
+#include "USBEndpoints.h"
+#include "toolchain.h"
+
+//#ifdef __GNUC__
+//#define __packed __attribute__ ((__packed__))
+//#endif
+
+class USBHAL {
+public:
+    /* Configuration */
+    USBHAL();
+    ~USBHAL();
+    void connect(void);
+    void disconnect(void);
+    void configureDevice(void);
+    void unconfigureDevice(void);
+    void setAddress(uint8_t address);
+    void remoteWakeup(void);
+
+    /* Endpoint 0 */
+    void EP0setup(uint8_t *buffer);
+    void EP0read(void);
+    void EP0readStage(void);
+    uint32_t EP0getReadResult(uint8_t *buffer);
+    void EP0write(uint8_t *buffer, uint32_t size);
+    void EP0getWriteResult(void);
+    void EP0stall(void);
+
+    /* Other endpoints */
+    EP_STATUS endpointRead(uint8_t endpoint, uint32_t maximumSize);
+    EP_STATUS endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead);
+    EP_STATUS endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size);
+    EP_STATUS endpointWriteResult(uint8_t endpoint);
+    void stallEndpoint(uint8_t endpoint);
+    void unstallEndpoint(uint8_t endpoint);
+    bool realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options);
+    bool getEndpointStallState(unsigned char endpoint);
+    uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer);
+
+protected:
+    virtual void busReset(void){};
+    virtual void EP0setupCallback(void){};
+    virtual void EP0out(void){};
+    virtual void EP0in(void){};
+    virtual void connectStateChanged(unsigned int connected){};
+    virtual void suspendStateChanged(unsigned int suspended){};
+    virtual void SOF(int frameNumber){};
+
+    virtual bool EP1_OUT_callback(){return false;};
+    virtual bool EP1_IN_callback(){return false;};
+    virtual bool EP2_OUT_callback(){return false;};
+    virtual bool EP2_IN_callback(){return false;};
+    virtual bool EP3_OUT_callback(){return false;};
+    virtual bool EP3_IN_callback(){return false;};
+#if !defined(TARGET_STM32F4)
+    virtual bool EP4_OUT_callback(){return false;};
+    virtual bool EP4_IN_callback(){return false;};
+#if !(defined(TARGET_LPC11UXX) || defined(TARGET_LPC11U6X) || defined(TARGET_LPC1347) || defined(TARGET_LPC1549))
+    virtual bool EP5_OUT_callback(){return false;};
+    virtual bool EP5_IN_callback(){return false;};
+    virtual bool EP6_OUT_callback(){return false;};
+    virtual bool EP6_IN_callback(){return false;};
+    virtual bool EP7_OUT_callback(){return false;};
+    virtual bool EP7_IN_callback(){return false;};
+    virtual bool EP8_OUT_callback(){return false;};
+    virtual bool EP8_IN_callback(){return false;};
+    virtual bool EP9_OUT_callback(){return false;};
+    virtual bool EP9_IN_callback(){return false;};
+    virtual bool EP10_OUT_callback(){return false;};
+    virtual bool EP10_IN_callback(){return false;};
+    virtual bool EP11_OUT_callback(){return false;};
+    virtual bool EP11_IN_callback(){return false;};
+    virtual bool EP12_OUT_callback(){return false;};
+    virtual bool EP12_IN_callback(){return false;};
+    virtual bool EP13_OUT_callback(){return false;};
+    virtual bool EP13_IN_callback(){return false;};
+    virtual bool EP14_OUT_callback(){return false;};
+    virtual bool EP14_IN_callback(){return false;};
+    virtual bool EP15_OUT_callback(){return false;};
+    virtual bool EP15_IN_callback(){return false;};
+#endif
+#endif
+
+private:
+    void usbisr(void);
+    static void _usbisr(void);
+    static USBHAL * instance;
+
+#if defined(TARGET_LPC11UXX) || defined(TARGET_LPC11U6X) || defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
+        bool (USBHAL::*epCallback[10 - 2])(void);
+#elif defined(TARGET_STM32F4)
+        bool (USBHAL::*epCallback[8 - 2])(void);
+#else
+        bool (USBHAL::*epCallback[32 - 2])(void);
+#endif
+
+
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_EFM32.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,775 @@
+/* Copyright 2015 Silicon Labs, http://www.silabs.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined TARGET_EFM32GG_STK3700 || \
+    defined TARGET_EFM32LG_STK3600 || \
+    defined TARGET_EFM32WG_STK3800 || \
+    defined TARGET_EFM32HG_STK3400
+
+#include "USBHAL.h"
+#include "em_usb.h"
+#include "em_usbtypes.h"
+#include "em_usbhal.h"
+#include "em_usbd.h"
+
+#include "sleepmodes.h"
+
+enum USBISRCommand {
+    CMD_HANDLED = 0,
+    CMD_EP0SETUP,
+    CMD_EP0IN,
+    CMD_EP0OUT,
+    CMD_EP_XFER_COMPLETED,
+    CMD_SOF,
+    CMD_BUSRESET,
+    CMD_SUSPEND_STATE_CHANGED,
+    CMD_ENUM_END_MARKER
+};
+
+enum IEPStatus {
+    NOT_CONFIGURED = 0,
+    IDLE = 1,
+    READ_PENDING = 2,
+    WRITE_PENDING = 3,
+    READ_COMPLETE = 4,
+    WRITE_COMPLETE = 5,
+    FAILED_INVALID = 6,
+    FAILED_STALLED = 7
+};
+
+typedef struct {
+    IEPStatus status;
+    uint32_t byte_count;
+    uint32_t max_packet;
+    USB_XferCompleteCb_TypeDef intern_cb;
+    uint8_t *data_buf;
+} ep_state_t;
+
+USBHAL * USBHAL::instance;
+static uint8_t ep0setupdata[8];
+static ep_state_t ep_state[NUMBER_OF_ENDPOINTS];
+#ifdef USB_USE_DYNAMIC_MEMORY
+static uint8_t ep0in_data_buf[MAX_PACKET_SIZE_EP0] __attribute__ ((aligned (4)));
+static uint8_t ep0out_data_buf[MAX_PACKET_SIZE_EP0]; // FIXME: does this need to be this big?
+#else
+static uint8_t ep_data_buf[NUMBER_OF_ENDPOINTS][64] __attribute__ ((aligned (4)));
+#endif
+
+static void run_cmd(USBISRCommand cmd, uint32_t param);
+static void (*isrptr)() = NULL;
+static USBISRCommand usb_isrcmd = CMD_HANDLED;
+static uint32_t usb_isrcmd_param = 0;
+
+extern "C" void usbhal_allow_em2(bool allow_em2);
+
+#ifdef DEBUG_USB_API
+#define TRACE(fmt,...)            printf("USB:   %s: " fmt "\n", __func__, __VA_ARGS__);
+#define TRACE_FUNC_IN             printf("USB: > %s\n",__func__);
+#define TRACE_FUNC_IN_P(fmt, ...) printf("USB: > %s: " fmt "\n", __func__, __VA_ARGS__);
+#else
+#define TRACE(fmt,...)
+#define TRACE_FUNC_IN
+#define TRACE_FUNC_IN_P(fmt, ...)
+#endif
+
+static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize);
+
+static int usbhal_xfer_complete_cb(uint8_t epaddr, USB_Status_TypeDef status,
+                                   uint32_t xferred, uint32_t remaining);
+static void usbhal_free_buffers(void);
+
+/* Internal EP transfer complete callbacks */
+#define EPCB(n) static int usbhal_xfer_complete_cb_##n(USB_Status_TypeDef status,              \
+                                                       uint32_t xferred, uint32_t remaining) { \
+        return usbhal_xfer_complete_cb(n, status, xferred, remaining);                         \
+}
+/*   ------^   */
+EPCB(EP0OUT)
+EPCB(EP0IN)
+EPCB(EP1OUT)
+EPCB(EP1IN)
+EPCB(EP2OUT)
+EPCB(EP2IN)
+EPCB(EP3OUT)
+EPCB(EP3IN)
+#ifndef TARGET_EFM32HG_STK3400
+EPCB(EP4OUT)
+EPCB(EP4IN)
+EPCB(EP5OUT)
+EPCB(EP5IN)
+EPCB(EP6OUT)
+EPCB(EP6IN)
+#endif
+
+static inline bool is_aligned(const void *pointer, size_t byte_count)
+{
+    return ((uintptr_t)pointer % byte_count == 0);
+}
+
+USBHAL::USBHAL(void)
+{
+    TRACE_FUNC_IN;
+
+    isrptr = &USBHAL::_usbisr;
+
+    if (instance) {
+        TRACE("Assert self failed! instance=%p", instance);
+        abort();
+    }
+    instance = this;
+
+    // When USB is active, we can't go below EM1. This block may
+    // be dynamically removed/reinstated to allow deeper sleep.
+    usbhal_allow_em2(false);
+
+    // When in suspend / Vbus off we can go to EM2, but never below
+    // that as long as USB is being used. Despite the name the call here
+    // blocks entering modes _below_ EM2, but allows EM2.
+    blockSleepMode(EM2);
+
+    epCallback[EP0OUT] = NULL;
+    epCallback[EP0IN ] = NULL;
+    epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback;
+    epCallback[EP1IN ] = &USBHAL::EP1_IN_callback;
+    epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback;
+    epCallback[EP2IN ] = &USBHAL::EP2_IN_callback;
+    epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback;
+    epCallback[EP3IN ] = &USBHAL::EP3_IN_callback;
+#ifndef TARGET_EFM32HG_STK3400
+    epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback;
+    epCallback[EP4IN ] = &USBHAL::EP4_IN_callback;
+    epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback;
+    epCallback[EP5IN ] = &USBHAL::EP5_IN_callback;
+    epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback;
+    epCallback[EP6IN ] = &USBHAL::EP6_IN_callback;
+#endif
+
+    memset(ep_state, 0, sizeof(ep_state));
+
+    ep_state[EP0OUT].intern_cb = usbhal_xfer_complete_cb_EP0OUT;
+    ep_state[EP0IN ].intern_cb = usbhal_xfer_complete_cb_EP0IN;
+    ep_state[EP1OUT].intern_cb = usbhal_xfer_complete_cb_EP1OUT;
+    ep_state[EP1IN ].intern_cb = usbhal_xfer_complete_cb_EP1IN;
+    ep_state[EP2OUT].intern_cb = usbhal_xfer_complete_cb_EP2OUT;
+    ep_state[EP2IN ].intern_cb = usbhal_xfer_complete_cb_EP2IN;
+    ep_state[EP3OUT].intern_cb = usbhal_xfer_complete_cb_EP3OUT;
+    ep_state[EP3IN ].intern_cb = usbhal_xfer_complete_cb_EP3IN;
+#ifndef TARGET_EFM32HG_STK3400
+    ep_state[EP4OUT].intern_cb = usbhal_xfer_complete_cb_EP4OUT;
+    ep_state[EP4IN ].intern_cb = usbhal_xfer_complete_cb_EP4IN;
+    ep_state[EP5OUT].intern_cb = usbhal_xfer_complete_cb_EP5OUT;
+    ep_state[EP5IN ].intern_cb = usbhal_xfer_complete_cb_EP5IN;
+    ep_state[EP6OUT].intern_cb = usbhal_xfer_complete_cb_EP6OUT;
+    ep_state[EP6IN ].intern_cb = usbhal_xfer_complete_cb_EP6IN;
+#endif
+
+#ifdef USB_USE_DYNAMIC_MEMORY
+    ep_state[EP0OUT].data_buf = ep0out_data_buf;
+    ep_state[EP0IN].data_buf = ep0in_data_buf;
+#else
+    for (int i=0 ; i<NUMBER_OF_ENDPOINTS ; i++) {
+        ep_state[i].data_buf = ep_data_buf[i];
+    }
+#endif
+}
+
+USBHAL::~USBHAL(void)
+{
+    TRACE_FUNC_IN;
+    USBD_AbortAllTransfers();
+    USBD_Disconnect();
+    usbhal_free_buffers();
+
+    usbhal_allow_em2(true);
+    unblockSleepMode(EM2);
+}
+
+extern "C" void usbhal_allow_em2(bool allow_em2)
+{
+    if (allow_em2) {
+        // unblockSleepMode is safe to call even if we would unblock
+        // an already unblocked mode, so no checks here.
+        unblockSleepMode(EM1);
+    } else {
+        blockSleepMode(EM1);
+    }
+}
+
+static void usbhal_reset_cb(void)
+{
+    TRACE_FUNC_IN;
+    run_cmd(CMD_BUSRESET, 0);
+}
+
+#ifdef DEBUG_USB_API
+static const char *usbstate[] = { "NONE", "ATTACHED", "POWERED", "DEFAULT",
+                                  "ADDRESSED", "CONFIGURED", "SUSPENDED", "???" };
+#endif
+
+static void usbhal_state_change_cb(USBD_State_TypeDef oldState,
+                                   USBD_State_TypeDef newState)
+{
+    TRACE("state changed %s -> %s", usbstate[oldState], usbstate[newState]);
+
+    if (oldState == USBD_STATE_SUSPENDED) {
+        run_cmd(CMD_SUSPEND_STATE_CHANGED, 0);
+    }
+
+    if (newState == USBD_STATE_SUSPENDED) {
+        run_cmd(CMD_SUSPEND_STATE_CHANGED, 1);
+    }
+
+    // Should call connectStateChanged from here as well but there is
+    // no documentation on when to actually do so. (And the implementation
+    // in USBDevice.cpp is a stub)
+
+    // HACK! Since connectStateChanged is not used, indicate the loss
+    // off connection by reporting a bus reset. This causes USBDevice
+    // to realise that at least it's not in CONFIGURED anymore, and
+    // stop trying to read/write in a busyloop.
+    if (newState == USBD_STATE_NONE) {
+        run_cmd(CMD_BUSRESET, 0);
+    }
+}
+
+static int usbhal_setupcmd_cb(const USB_Setup_TypeDef *setup)
+{
+    TRACE_FUNC_IN;
+    if (!setup) {
+        EFM_ASSERT(false);
+        return USB_STATUS_REQ_ERR;
+    }
+
+    memcpy(ep0setupdata, setup, 8);
+    run_cmd(CMD_EP0SETUP, 0);
+
+    return USB_STATUS_OK;
+}
+
+static void usbhal_sof_cb(uint16_t frameNum)
+{
+    run_cmd(CMD_SOF, frameNum);
+}
+
+static void usbhal_free_buffers(void)
+{
+#ifdef USB_USE_DYNAMIC_MEMORY
+    TRACE_FUNC_IN;
+
+    for (int i=EP1OUT ; i<NUMBER_OF_ENDPOINTS ; i++ ) {
+        if (ep_state[i].data_buf) {
+            free(ep_state[i].data_buf);
+            ep_state[i].data_buf = NULL;
+        }
+    }
+#endif
+}
+
+void USBHAL::connect(void)
+{
+    TRACE_FUNC_IN;
+
+    // Init datastructures must be static - driver will use these even after the init function exits!
+
+    static const uint8_t buffer_multiplier[] = { 1 }; // Mult 1 for control EP
+    static const USBD_Callbacks_TypeDef usbd_callbacks = {
+        .usbReset = usbhal_reset_cb,
+        .usbStateChange = usbhal_state_change_cb,
+        .setupCmd = usbhal_setupcmd_cb,
+        .isSelfPowered = NULL,
+        .sofInt = usbhal_sof_cb
+    };
+
+    USBD_Init_TypeDef initdata = {
+        .deviceDescriptor = NULL,
+        .configDescriptor = NULL,
+        .stringDescriptors = NULL,
+        .numberOfStrings = 0,
+        .bufferingMultiplier = buffer_multiplier,
+        .callbacks = &usbd_callbacks,
+        .reserved = 0
+    };
+
+    int ret = USBD_Init(&initdata);
+
+    TRACE("init = %d, devicedesc = %lx, configdesc = %lx", ret,
+          (uint32_t) initdata.deviceDescriptor,
+          (uint32_t) initdata.configDescriptor);
+
+    EFM_ASSERT(ret == USB_STATUS_OK);
+}
+
+void USBHAL::disconnect(void)
+{
+    TRACE_FUNC_IN;
+    USBD_Disconnect();
+}
+
+void USBHAL::configureDevice(void)
+{
+    TRACE_FUNC_IN;
+    USBD_SetUsbState(USBD_STATE_CONFIGURED);
+}
+
+void USBHAL::unconfigureDevice(void)
+{
+    TRACE_FUNC_IN;
+    USBD_SetUsbState(USBD_STATE_DEFAULT);
+    usbhal_free_buffers();
+}
+
+void USBHAL::setAddress(uint8_t address)
+{
+    TRACE_FUNC_IN_P("addr 0x%x", (unsigned)address);
+    USBD_SetAddress(address);
+}
+
+void USBHAL::remoteWakeup(void)
+{
+    TRACE_FUNC_IN;
+    USBD_RemoteWakeup();
+}
+
+void USBHAL::EP0setup(uint8_t *buffer)
+{
+    TRACE_FUNC_IN;
+    EFM_ASSERT(buffer);
+    if (buffer) {
+        memcpy(buffer, ep0setupdata, 8);
+    }
+}
+
+void USBHAL::EP0read(void)
+{
+    TRACE_FUNC_IN;
+    (void)internEndpointRead(0, MAX_PACKET_SIZE_EP0);
+}
+
+void USBHAL::EP0readStage(void)
+{
+    TRACE_FUNC_IN;
+    // Not needed
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
+{
+    TRACE_FUNC_IN;
+    EFM_ASSERT(buffer);
+
+    uint32_t read = 0;
+    endpointReadResult(0, buffer, &read);
+    return read;
+}
+
+static int usbhal_xfer_complete_cb(uint8_t ep, USB_Status_TypeDef status,
+                                   uint32_t xferred, uint32_t remaining)
+{
+    TRACE_FUNC_IN_P("ep 0x%x, status %u, xferred %lu, rem %lu",
+                    ep, status, xferred, remaining);
+
+    if (ep >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return USB_STATUS_REQ_ERR;
+    }
+
+    switch (ep) {
+        case EP0OUT:
+            if (ep_state[EP0OUT].status == READ_PENDING) {
+                ep_state[EP0OUT].status = READ_COMPLETE;
+                ep_state[EP0OUT].byte_count = xferred;
+                // drop zlp
+                if (xferred == 0) {
+                    break;
+                }
+            }
+            run_cmd(CMD_EP0OUT, 0);
+            break;
+
+        case EP0IN:
+            run_cmd(CMD_EP0IN, 0);
+            break;
+
+        default:
+            bool write = ep & 1;
+
+            if (status == USB_STATUS_OK) {
+                if (!write && ep_state[ep].status == READ_PENDING) {
+                    ep_state[ep].status = READ_COMPLETE;
+                    ep_state[ep].byte_count = xferred;
+                } else if (write && ep_state[ep].status == WRITE_PENDING) {
+                    ep_state[ep].status = WRITE_COMPLETE;
+                } else {
+                    ep_state[ep].status = FAILED_INVALID;
+                }
+            } else {
+                ep_state[ep].status = FAILED_INVALID;
+            }
+
+            if (ep_state[ep].status != FAILED_INVALID) {
+                run_cmd(CMD_EP_XFER_COMPLETED, ep);
+            }
+            break;
+    }
+
+    return USB_STATUS_OK;
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
+{
+    //TRACE_FUNC_IN_P("buffer %lx, size %lu", (uint32_t) buffer, size);
+
+    int ret;
+    USB_XferCompleteCb_TypeDef cb = ep_state[EP0IN].intern_cb;
+
+    EFM_ASSERT((buffer != NULL) || (size == 0));
+    EFM_ASSERT(size <= MAX_PACKET_SIZE_EP0);
+
+    if (!buffer || size == 0) {
+        // No callback after writing EP0 ZLP
+        cb = NULL;
+    }
+
+    if (buffer && !is_aligned(buffer,4)) {
+        // Copy unaligned data to write-buffer before USBD_Write
+        memcpy(ep_state[EP0IN].data_buf, buffer, size);
+        ret = USBD_Write(0, ep_state[EP0IN].data_buf, size, cb);
+    } else {
+        ret = USBD_Write(0, buffer, size, cb);
+    }
+
+    if (ret != USB_STATUS_OK) {
+        TRACE("FAILED - ret %d", ret);
+    }
+}
+
+void USBHAL::EP0stall(void)
+{
+    TRACE_FUNC_IN;
+    USBD_StallEp0();
+}
+
+static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize)
+{
+    //TRACE_FUNC_IN_P("endpoint 0x%x, size %ld, cb %d", (unsigned)ep, maxSize, useCallback);
+
+    if (ep >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return EP_INVALID;
+    }
+
+    ep_state[ep].status = READ_PENDING;
+
+    int ret = USBD_Read(USB_EP_TO_ADDR(ep), ep_state[ep].data_buf, maxSize,
+                        ep_state[ep].intern_cb);
+
+    if (ret == USB_STATUS_OK) {
+        return EP_PENDING;
+    } else {
+        TRACE("FAILED - ret %d", ret);
+
+        if (ret == USB_STATUS_EP_STALLED) {
+            return EP_STALLED;
+        } else {
+            return EP_INVALID;
+        }
+    }
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
+{
+    return internEndpointRead(endpoint, maximumSize);
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead)
+{
+    TRACE_FUNC_IN;
+
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return EP_INVALID;
+    }
+
+    EFM_ASSERT(data);
+    EFM_ASSERT(bytesRead);
+    if (!data || !bytesRead) {
+        return EP_INVALID;
+    }
+
+    switch (ep_state[endpoint].status) {
+        case READ_PENDING:
+            return EP_PENDING;
+
+        case READ_COMPLETE:
+            memcpy(data, ep_state[endpoint].data_buf, ep_state[endpoint].byte_count);
+            *bytesRead = ep_state[endpoint].byte_count;
+            ep_state[endpoint].status = IDLE;
+            return EP_COMPLETED;
+
+        case FAILED_STALLED:
+            ep_state[endpoint].status = IDLE;
+            return EP_STALLED;
+
+        default:
+            ep_state[endpoint].status = IDLE;
+            return EP_INVALID;
+    }
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
+{
+    TRACE_FUNC_IN_P("endpoint 0x%x, data 0x%lx, size %lu", (unsigned )endpoint, (uint32_t)data, size);
+
+    EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
+    EFM_ASSERT(endpoint > EP0IN);
+    EFM_ASSERT(size <= ep_state[endpoint].max_packet);
+    EFM_ASSERT(data);
+
+    uint8_t ep = USB_EP_TO_INDEX(endpoint);
+
+    if (endpoint >= NUMBER_OF_ENDPOINTS || endpoint <= EP0IN) {
+        return EP_INVALID;
+    }
+
+    if (size > ep_state[endpoint].max_packet) {
+        return EP_INVALID;
+    }
+
+    if (!data) {
+        return EP_INVALID;
+    }
+
+    memcpy(ep_state[ep].data_buf, data, size);
+
+    ep_state[ep].status = WRITE_PENDING;
+    int ret = USBD_Write(USB_EP_TO_ADDR(endpoint), ep_state[ep].data_buf, size, ep_state[ep].intern_cb);
+
+    if (ret == USB_STATUS_EP_STALLED) {
+        ep_state[ep].status = IDLE;
+        return EP_STALLED;
+    } else if (ret != USB_STATUS_OK) {
+        ep_state[ep].status = IDLE;
+        return EP_INVALID;
+    }
+
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
+{
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return EP_INVALID;
+    }
+
+    switch (ep_state[endpoint].status) {
+        case WRITE_PENDING:
+            return EP_PENDING;
+
+        case WRITE_COMPLETE:
+            ep_state[endpoint].status = IDLE;
+            return EP_COMPLETED;
+
+        case FAILED_STALLED:
+            ep_state[endpoint].status = IDLE;
+            return EP_STALLED;
+
+        default:
+            ep_state[endpoint].status = IDLE;
+            return EP_INVALID;
+    }
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint)
+{
+    TRACE_FUNC_IN;
+
+    EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
+    EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
+
+    USBD_StallEp(USB_EP_TO_ADDR(endpoint));
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint)
+{
+    TRACE_FUNC_IN;
+
+    EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
+    EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
+
+    USBD_UnStallEp(USB_EP_TO_ADDR(endpoint));
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
+{
+    TRACE_FUNC_IN_P("endpoint %d, packetsize %ld, options 0x%lx", endpoint,
+                    maxPacket, options);
+
+    int mult = 1; // RX/TX buffer size multiplier
+    int type = USB_EPTYPE_INTR;
+
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return false;
+    }
+
+    if (endpoint == EP0IN || endpoint == EP0OUT) {
+        EFM_ASSERT(false);
+        return false;
+    }
+
+    ep_state[endpoint].max_packet = 0;
+
+    if (endpoint == EPISO_OUT || endpoint ==  EPISO_IN) {
+        if (maxPacket > MAX_PACKET_SIZE_EPISO) {
+            EFM_ASSERT(false);
+            return false;
+        }
+    } else if ((maxPacket > MAX_PACKET_SIZE_EPBULK) || (maxPacket > MAX_PACKET_SIZE_EPINT)) {
+        EFM_ASSERT(false);
+        return false;
+    }
+
+    // USBDevice performs a read right after creating the endpoints,
+    // before calling configureDevice. The read will fail since
+    // at that point the device state is still ADDRESSED. Workaround
+    // is to force configured state here.
+    //
+    // This relies on USBDevice to not call realiseEndpoint unless
+    // it is transitioning to the CONFIGURED state.
+    USBD_SetUsbState(USBD_STATE_CONFIGURED);
+
+    // Why doesn't this function have a type param? This is silly...
+    switch (endpoint) {
+        case EPBULK_OUT:
+        case EPBULK_IN:
+            type = USB_EPTYPE_BULK;
+            mult = 2;
+            break;
+        case EPINT_OUT:
+        case EPINT_IN:
+            type = USB_EPTYPE_INTR;
+            mult = 1;
+            break;
+        case EPISO_OUT:
+        case EPISO_IN:
+            type = USB_EPTYPE_ISOC;
+            mult = 2; // ?
+            break;
+    }
+
+    // Some options force the endpoint to a specific type
+    if( options & ISOCHRONOUS ) {
+        type = USB_EPTYPE_ISOC;
+        mult = 2; // ?
+    } else if ( options & RATE_FEEDBACK_MODE ) {
+        // No support for whatever rate feedback is, but for interrupt only
+        type = USB_EPTYPE_INTR;
+        mult = 1;
+    }
+
+#ifdef USB_USE_DYNAMIC_MEMORY
+    if (ep_state[endpoint].data_buf) {
+        free(ep_state[endpoint].data_buf);
+    }
+
+    ep_state[endpoint].data_buf = (uint8_t *)malloc(maxPacket);
+
+    if (!ep_state[endpoint].data_buf) {
+        EFM_ASSERT(false);
+        return false;
+    }
+#endif
+
+    int ret = USBD_AddEndpoint(USB_EP_TO_ADDR(endpoint), type, maxPacket, mult);
+
+    if (ret == USB_STATUS_OK) {
+        ep_state[endpoint].status = IDLE;
+        ep_state[endpoint].max_packet = maxPacket;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool USBHAL::getEndpointStallState(unsigned char endpoint)
+{
+    TRACE_FUNC_IN;
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return false;
+    }
+    return USBD_EpIsStalled(USB_EP_TO_ADDR(endpoint));
+}
+
+static void run_cmd(USBISRCommand cmd, uint32_t param)
+{
+    if (usb_isrcmd != CMD_HANDLED || cmd >= CMD_ENUM_END_MARKER) {
+        EFM_ASSERT(false);
+        abort();
+    }
+
+    usb_isrcmd = cmd;
+    usb_isrcmd_param = param;
+    isrptr();
+}
+
+void USBHAL::_usbisr(void)
+{
+    EFM_ASSERT(instance);
+    instance->usbisr();
+}
+
+void USBHAL::usbisr(void)
+{
+    //TRACE_FUNC_IN;
+
+    // This "ISR" is used just to route callbacks from SiL USB driver
+    // callback context (which can not call protected/private USBHAL
+    // methods), to the actual USBHAL.
+
+    EFM_ASSERT(usb_isrcmd != CMD_HANDLED);
+    switch (usb_isrcmd) {
+        case CMD_EP0SETUP:
+            this->EP0setupCallback();
+            break;
+        case CMD_EP0IN:
+            this->EP0in();
+            break;
+        case CMD_EP0OUT:
+            this->EP0out();
+            break;
+        case CMD_BUSRESET:
+            this->busReset();
+            break;
+        case CMD_EP_XFER_COMPLETED:
+            if (epCallback[usb_isrcmd_param] && instance) {
+                (instance->*(epCallback[usb_isrcmd_param]))();
+            }
+            break;
+        case CMD_SOF:
+            this->SOF(usb_isrcmd_param);
+            break;
+        case CMD_SUSPEND_STATE_CHANGED:
+            this->suspendStateChanged(usb_isrcmd_param);
+            break;
+        default:
+            EFM_ASSERT(false);
+            break;
+    }
+    usb_isrcmd = CMD_HANDLED;
+}
+#endif
+
+// End of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_KL25Z.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,552 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D50M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
+
+#include "USBHAL.h"
+
+USBHAL * USBHAL::instance;
+
+static volatile int epComplete = 0;
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1<<(endpoint))
+
+// Convert physical to logical
+#define PHY_TO_LOG(endpoint)    ((endpoint)>>1)
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+#define BD_OWN_MASK        (1<<7)
+#define BD_DATA01_MASK     (1<<6)
+#define BD_KEEP_MASK       (1<<5)
+#define BD_NINC_MASK       (1<<4)
+#define BD_DTS_MASK        (1<<3)
+#define BD_STALL_MASK      (1<<2)
+
+#define TX    1
+#define RX    0
+#define ODD   0
+#define EVEN  1
+// this macro waits a physical endpoint number
+#define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 *  odd)))
+
+#define SETUP_TOKEN    0x0D
+#define IN_TOKEN       0x09
+#define OUT_TOKEN      0x01
+#define TOK_PID(idx)   ((bdt[idx].info >> 2) & 0x0F)
+
+// for each endpt: 8 bytes
+typedef struct BDT {
+    uint8_t   info;       // BD[0:7]
+    uint8_t   dummy;      // RSVD: BD[8:15]
+    uint16_t  byte_count; // BD[16:32]
+    uint32_t  address;    // Addr
+} BDT;
+
+
+// there are:
+//    * 16 bidirectionnal endpt -> 32 physical endpt
+//    * as there are ODD and EVEN buffer -> 32*2 bdt
+__attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
+uint8_t * endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2];
+uint8_t * endpoint_buffer_iso[2*2];
+
+static uint8_t set_addr = 0;
+static uint8_t addr = 0;
+
+static uint32_t Data1  = 0x55555555;
+
+static uint32_t frameNumber() {
+    return((USB0->FRMNUML | (USB0->FRMNUMH << 8)) & 0x07FF);
+}
+
+uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
+    return 0;
+}
+
+USBHAL::USBHAL(void) {
+    // Disable IRQ
+    NVIC_DisableIRQ(USB0_IRQn);
+
+#if defined(TARGET_K64F)
+    MPU->CESR=0;
+#endif
+    // fill in callback array
+    epCallback[0] = &USBHAL::EP1_OUT_callback;
+    epCallback[1] = &USBHAL::EP1_IN_callback;
+    epCallback[2] = &USBHAL::EP2_OUT_callback;
+    epCallback[3] = &USBHAL::EP2_IN_callback;
+    epCallback[4] = &USBHAL::EP3_OUT_callback;
+    epCallback[5] = &USBHAL::EP3_IN_callback;
+    epCallback[6] = &USBHAL::EP4_OUT_callback;
+    epCallback[7] = &USBHAL::EP4_IN_callback;
+    epCallback[8] = &USBHAL::EP5_OUT_callback;
+    epCallback[9] = &USBHAL::EP5_IN_callback;
+    epCallback[10] = &USBHAL::EP6_OUT_callback;
+    epCallback[11] = &USBHAL::EP6_IN_callback;
+    epCallback[12] = &USBHAL::EP7_OUT_callback;
+    epCallback[13] = &USBHAL::EP7_IN_callback;
+    epCallback[14] = &USBHAL::EP8_OUT_callback;
+    epCallback[15] = &USBHAL::EP8_IN_callback;
+    epCallback[16] = &USBHAL::EP9_OUT_callback;
+    epCallback[17] = &USBHAL::EP9_IN_callback;
+    epCallback[18] = &USBHAL::EP10_OUT_callback;
+    epCallback[19] = &USBHAL::EP10_IN_callback;
+    epCallback[20] = &USBHAL::EP11_OUT_callback;
+    epCallback[21] = &USBHAL::EP11_IN_callback;
+    epCallback[22] = &USBHAL::EP12_OUT_callback;
+    epCallback[23] = &USBHAL::EP12_IN_callback;
+    epCallback[24] = &USBHAL::EP13_OUT_callback;
+    epCallback[25] = &USBHAL::EP13_IN_callback;
+    epCallback[26] = &USBHAL::EP14_OUT_callback;
+    epCallback[27] = &USBHAL::EP14_IN_callback;
+    epCallback[28] = &USBHAL::EP15_OUT_callback;
+    epCallback[29] = &USBHAL::EP15_IN_callback;
+
+#if defined(TARGET_KL43Z)
+    // enable USBFS clock
+    SIM->SCGC4 |= SIM_SCGC4_USBFS_MASK;
+
+    // enable the IRC48M clock
+    USB0->CLK_RECOVER_IRC_EN |= USB_CLK_RECOVER_IRC_EN_IRC_EN_MASK;
+
+    // enable the USB clock recovery tuning
+    USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
+
+    // choose usb src clock
+    SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK;
+#else
+    // choose usb src as PLL
+    SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;
+    SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | (1 << SIM_SOPT2_PLLFLLSEL_SHIFT));
+
+    // enable OTG clock
+    SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
+#endif
+
+    // Attach IRQ
+    instance = this;
+    NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr);
+    NVIC_EnableIRQ(USB0_IRQn);
+
+    // USB Module Configuration
+    // Reset USB Module
+    USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
+    while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
+
+    // Set BDT Base Register
+    USB0->BDTPAGE1 = (uint8_t)((uint32_t)bdt>>8);
+    USB0->BDTPAGE2 = (uint8_t)((uint32_t)bdt>>16);
+    USB0->BDTPAGE3 = (uint8_t)((uint32_t)bdt>>24);
+
+    // Clear interrupt flag
+    USB0->ISTAT = 0xff;
+
+    // USB Interrupt Enablers
+    USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK |
+                   USB_INTEN_SOFTOKEN_MASK |
+                   USB_INTEN_ERROREN_MASK  |
+                   USB_INTEN_USBRSTEN_MASK;
+
+    // Disable weak pull downs
+    USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK);
+
+    USB0->USBTRC0 |= 0x40;
+}
+
+USBHAL::~USBHAL(void) { }
+
+void USBHAL::connect(void) {
+    // enable USB
+    USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
+    // Pull up enable
+    USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK;
+}
+
+void USBHAL::disconnect(void) {
+    // disable USB
+    USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
+    // Pull up disable
+    USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
+
+    //Free buffers if required:
+    for (int i = 0; i<(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2; i++) {
+        free(endpoint_buffer[i]);
+        endpoint_buffer[i] = NULL;
+    }
+    free(endpoint_buffer_iso[2]);
+    endpoint_buffer_iso[2] = NULL;
+    free(endpoint_buffer_iso[0]);
+    endpoint_buffer_iso[0] = NULL;
+}
+
+void USBHAL::configureDevice(void) {
+    // not needed
+}
+
+void USBHAL::unconfigureDevice(void) {
+    // not needed
+}
+
+void USBHAL::setAddress(uint8_t address) {
+    // we don't set the address now otherwise the usb controller does not ack
+    // we set a flag instead
+    // see usbisr when an IN token is received
+    set_addr = 1;
+    addr = address;
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
+    uint32_t handshake_flag = 0;
+    uint8_t * buf;
+
+    if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
+        return false;
+    }
+
+    uint32_t log_endpoint = PHY_TO_LOG(endpoint);
+
+    if ((flags & ISOCHRONOUS) == 0) {
+        handshake_flag = USB_ENDPT_EPHSHK_MASK;
+        if (IN_EP(endpoint)) {
+            if (endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] == NULL)
+                endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] = (uint8_t *) malloc (64);
+            buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)][0];
+        } else {
+            if (endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] == NULL)
+                endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] = (uint8_t *) malloc (64);
+            buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)][0];
+        }
+    } else {
+        if (IN_EP(endpoint)) {
+            if (endpoint_buffer_iso[2] == NULL)
+                endpoint_buffer_iso[2] = (uint8_t *) malloc (1023);
+            buf = &endpoint_buffer_iso[2][0];
+        } else {
+            if (endpoint_buffer_iso[0] == NULL)
+                endpoint_buffer_iso[0] = (uint8_t *) malloc (1023);
+            buf = &endpoint_buffer_iso[0][0];
+        }
+    }
+
+    // IN endpt -> device to host (TX)
+    if (IN_EP(endpoint)) {
+        USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag |        // ep handshaking (not if iso endpoint)
+                                              USB_ENDPT_EPTXEN_MASK;  // en TX (IN) tran
+        bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf;
+        bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0;
+    }
+    // OUT endpt -> host to device (RX)
+    else {
+        USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag |        // ep handshaking (not if iso endpoint)
+                                              USB_ENDPT_EPRXEN_MASK;  // en RX (OUT) tran.
+        bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket;
+        bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address    = (uint32_t) buf;
+        bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info       = BD_OWN_MASK | BD_DTS_MASK;
+        bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info       = 0;
+    }
+
+    Data1 |= (1 << endpoint);
+
+    return true;
+}
+
+// read setup packet
+void USBHAL::EP0setup(uint8_t *buffer) {
+    uint32_t sz;
+    endpointReadResult(EP0OUT, buffer, &sz);
+}
+
+void USBHAL::EP0readStage(void) {
+    Data1 &= ~1UL;  // set DATA0
+    bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
+}
+
+void USBHAL::EP0read(void) {
+    uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0);
+    bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
+    uint32_t sz;
+    endpointReadResult(EP0OUT, buffer, &sz);
+    return sz;
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
+    endpointWrite(EP0IN, buffer, size);
+}
+
+void USBHAL::EP0getWriteResult(void) {
+}
+
+void USBHAL::EP0stall(void) {
+    stallEndpoint(EP0OUT);
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
+    endpoint = PHY_TO_LOG(endpoint);
+    uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
+    bdt[idx].byte_count = maximumSize;
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
+    uint32_t n, sz, idx, setup = 0;
+    uint8_t not_iso;
+    uint8_t * ep_buf;
+
+    uint32_t log_endpoint = PHY_TO_LOG(endpoint);
+
+    if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
+        return EP_INVALID;
+    }
+
+    // if read on a IN endpoint -> error
+    if (IN_EP(endpoint)) {
+        return EP_INVALID;
+    }
+
+    idx = EP_BDT_IDX(log_endpoint, RX, 0);
+    sz  = bdt[idx].byte_count;
+    not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK;
+
+    //for isochronous endpoint, we don't wait an interrupt
+    if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) {
+        return EP_PENDING;
+    }
+
+    if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) {
+        setup = 1;
+    }
+
+    // non iso endpoint
+    if (not_iso) {
+        ep_buf = endpoint_buffer[idx];
+    } else {
+        ep_buf = endpoint_buffer_iso[0];
+    }
+
+    for (n = 0; n < sz; n++) {
+        buffer[n] = ep_buf[n];
+    }
+
+    if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) {
+        if (setup && (buffer[6] == 0))  // if no setup data stage,
+            Data1 &= ~1UL;              // set DATA0
+        else
+            Data1 ^= (1 << endpoint);
+    }
+
+    if (((Data1 >> endpoint) & 1)) {
+        bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
+    }
+    else {
+        bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
+    }
+
+    USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
+    *bytesRead = sz;
+
+    epComplete &= ~EP(endpoint);
+    return EP_COMPLETED;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
+    uint32_t idx, n;
+    uint8_t * ep_buf;
+
+    if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
+        return EP_INVALID;
+    }
+
+    // if write on a OUT endpoint -> error
+    if (OUT_EP(endpoint)) {
+        return EP_INVALID;
+    }
+
+    idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0);
+    bdt[idx].byte_count = size;
+
+
+    // non iso endpoint
+    if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) {
+        ep_buf = endpoint_buffer[idx];
+    } else {
+        ep_buf = endpoint_buffer_iso[2];
+    }
+
+    for (n = 0; n < size; n++) {
+        ep_buf[n] = data[n];
+    }
+
+    if ((Data1 >> endpoint) & 1) {
+        bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
+    } else {
+        bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
+    }
+
+    Data1 ^= (1 << endpoint);
+
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
+    if (epComplete & EP(endpoint)) {
+        epComplete &= ~EP(endpoint);
+        return EP_COMPLETED;
+    }
+
+    return EP_PENDING;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint) {
+    USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK;
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint) {
+    USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
+}
+
+bool USBHAL::getEndpointStallState(uint8_t endpoint) {
+    uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK);
+    return (stall) ? true : false;
+}
+
+void USBHAL::remoteWakeup(void) {
+    // [TODO]
+}
+
+
+void USBHAL::_usbisr(void) {
+    instance->usbisr();
+}
+
+
+void USBHAL::usbisr(void) {
+    uint8_t i;
+    uint8_t istat = USB0->ISTAT;
+
+    // reset interrupt
+    if (istat & USB_ISTAT_USBRST_MASK) {
+        // disable all endpt
+        for(i = 0; i < 16; i++) {
+            USB0->ENDPOINT[i].ENDPT = 0x00;
+        }
+
+        // enable control endpoint
+        realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
+        realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
+
+        Data1 = 0x55555555;
+        USB0->CTL |=  USB_CTL_ODDRST_MASK;
+
+        USB0->ISTAT   =  0xFF;  // clear all interrupt status flags
+        USB0->ERRSTAT =  0xFF;  // clear all error flags
+        USB0->ERREN   =  0xFF;  // enable error interrupt sources
+        USB0->ADDR    =  0x00;  // set default address
+
+        return;
+    }
+
+    // resume interrupt
+    if (istat & USB_ISTAT_RESUME_MASK) {
+        USB0->ISTAT = USB_ISTAT_RESUME_MASK;
+    }
+
+    // SOF interrupt
+    if (istat & USB_ISTAT_SOFTOK_MASK) {
+        USB0->ISTAT = USB_ISTAT_SOFTOK_MASK;
+        // SOF event, read frame number
+        SOF(frameNumber());
+    }
+
+    // stall interrupt
+    if (istat & 1<<7) {
+        if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
+            USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
+        USB0->ISTAT |= USB_ISTAT_STALL_MASK;
+    }
+
+    // token interrupt
+    if (istat & 1<<3) {
+        uint32_t num  = (USB0->STAT >> 4) & 0x0F;
+        uint32_t dir  = (USB0->STAT >> 3) & 0x01;
+        uint32_t ev_odd = (USB0->STAT >> 2) & 0x01;
+        int endpoint = (num << 1) | dir;
+
+        // setup packet
+        if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
+            Data1 &= ~0x02;
+            bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK;
+            bdt[EP_BDT_IDX(0, TX, ODD)].info  &= ~BD_OWN_MASK;
+
+            // EP0 SETUP event (SETUP data received)
+            EP0setupCallback();
+
+        } else {
+            // OUT packet
+            if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) {
+                if (num == 0)
+                    EP0out();
+                else {
+                    epComplete |= EP(endpoint);
+                    if ((instance->*(epCallback[endpoint - 2]))()) {
+                        epComplete &= ~EP(endpoint);
+                    }
+                }
+            }
+
+            // IN packet
+            if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) {
+                if (num == 0) {
+                    EP0in();
+                    if (set_addr == 1) {
+                        USB0->ADDR = addr & 0x7F;
+                        set_addr = 0;
+                    }
+                }
+                else {
+                    epComplete |= EP(endpoint);
+                    if ((instance->*(epCallback[endpoint - 2]))()) {
+                        epComplete &= ~EP(endpoint);
+                    }
+                }
+            }
+        }
+
+        USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
+    }
+
+    // sleep interrupt
+    if (istat & 1<<4) {
+        USB0->ISTAT |= USB_ISTAT_SLEEP_MASK;
+    }
+
+    // error interrupt
+    if (istat & USB_ISTAT_ERROR_MASK) {
+        USB0->ERRSTAT = 0xFF;
+        USB0->ISTAT |= USB_ISTAT_ERROR_MASK;
+    }
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_LPC11U.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,738 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(TARGET_LPC11UXX) || defined(TARGET_LPC11U6X) || defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
+
+#if defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
+#define USB_IRQ USB_IRQ_IRQn
+#else
+#define USB_IRQ USB_IRQn
+#endif
+
+#include "USBHAL.h"
+
+USBHAL * USBHAL::instance;
+#if defined(TARGET_LPC1549)
+static uint8_t usbmem[2048] __attribute__((aligned(2048)));
+#endif
+
+// Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
+#define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1UL<<endpoint)
+
+// Convert physical to logical
+#define PHY_TO_LOG(endpoint)    ((endpoint)>>1)
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+// USB RAM
+#if defined(TARGET_LPC1549)
+#define USB_RAM_START ((uint32_t)usbmem)
+#define USB_RAM_SIZE  sizeof(usbmem)
+#else
+#define USB_RAM_START (0x20004000)
+#define USB_RAM_SIZE  (0x00000800)
+#endif
+
+// SYSAHBCLKCTRL
+#if defined(TARGET_LPC1549)
+#define CLK_USB     (1UL<<23)
+#else
+#define CLK_USB     (1UL<<14)
+#define CLK_USBRAM  (1UL<<27)
+#endif
+
+// USB Information register
+#define FRAME_NR(a)     ((a) & 0x7ff)   // Frame number
+
+// USB Device Command/Status register
+#define DEV_ADDR_MASK   (0x7f)          // Device address
+#define DEV_ADDR(a)     ((a) & DEV_ADDR_MASK)
+#define DEV_EN          (1UL<<7)        // Device enable
+#define SETUP           (1UL<<8)        // SETUP token received
+#define PLL_ON          (1UL<<9)        // PLL enabled in suspend
+#define DCON            (1UL<<16)       // Device status - connect
+#define DSUS            (1UL<<17)       // Device status - suspend
+#define DCON_C          (1UL<<24)       // Connect change
+#define DSUS_C          (1UL<<25)       // Suspend change
+#define DRES_C          (1UL<<26)       // Reset change
+#define VBUSDEBOUNCED   (1UL<<28)       // Vbus detected
+
+// Endpoint Command/Status list
+#define CMDSTS_A                 (1UL<<31)          // Active
+#define CMDSTS_D                 (1UL<<30)          // Disable
+#define CMDSTS_S                 (1UL<<29)          // Stall
+#define CMDSTS_TR                (1UL<<28)          // Toggle Reset
+#define CMDSTS_RF                (1UL<<27)          // Rate Feedback mode
+#define CMDSTS_TV                (1UL<<27)          // Toggle Value
+#define CMDSTS_T                 (1UL<<26)          // Endpoint Type
+#define CMDSTS_NBYTES(n)         (((n)&0x3ff)<<16)  // Number of bytes
+#define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff)  // Buffer start address
+
+#define BYTES_REMAINING(s)       (((s)>>16)&0x3ff)  // Bytes remaining after transfer
+
+// USB Non-endpoint interrupt sources
+#define FRAME_INT   (1UL<<30)
+#define DEV_INT     (1UL<<31)
+
+static volatile int epComplete = 0;
+
+// One entry for a double-buffered logical endpoint in the endpoint
+// command/status list. Endpoint 0 is single buffered, out[1] is used
+// for the SETUP packet and in[1] is not used
+typedef struct {
+    uint32_t out[2];
+    uint32_t in[2];
+} PACKED EP_COMMAND_STATUS;
+
+typedef struct {
+    uint8_t out[MAX_PACKET_SIZE_EP0];
+    uint8_t in[MAX_PACKET_SIZE_EP0];
+    uint8_t setup[SETUP_PACKET_SIZE];
+} PACKED CONTROL_TRANSFER;
+
+typedef struct {
+    uint32_t    maxPacket;
+    uint32_t    buffer[2];
+    uint32_t    options;
+} PACKED EP_STATE;
+
+static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
+
+// Pointer to the endpoint command/status list
+static EP_COMMAND_STATUS *ep = NULL;
+
+// Pointer to endpoint 0 data (IN/OUT and SETUP)
+static CONTROL_TRANSFER *ct = NULL;
+
+// Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
+// initiating a remote wakeup event.
+static volatile uint32_t devCmdStat;
+
+// Pointers used to allocate USB RAM
+static uint32_t usbRamPtr = USB_RAM_START;
+static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
+
+#define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
+
+void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size);
+void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
+    if (size > 0) {
+        do {
+            *dst++ = *src++;
+        } while (--size > 0);
+    }
+}
+
+
+USBHAL::USBHAL(void) {
+    NVIC_DisableIRQ(USB_IRQ);
+
+    // fill in callback array
+    epCallback[0] = &USBHAL::EP1_OUT_callback;
+    epCallback[1] = &USBHAL::EP1_IN_callback;
+    epCallback[2] = &USBHAL::EP2_OUT_callback;
+    epCallback[3] = &USBHAL::EP2_IN_callback;
+    epCallback[4] = &USBHAL::EP3_OUT_callback;
+    epCallback[5] = &USBHAL::EP3_IN_callback;
+    epCallback[6] = &USBHAL::EP4_OUT_callback;
+    epCallback[7] = &USBHAL::EP4_IN_callback;
+
+#if defined(TARGET_LPC1549)
+    /* Set USB PLL input to system oscillator */
+    LPC_SYSCON->USBPLLCLKSEL = 0x01;
+
+    /* Setup USB PLL  (FCLKIN = 12MHz) * 4 = 48MHz
+       MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2)
+       FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz
+       FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */
+    LPC_SYSCON->USBPLLCTRL = (0x3 | (1UL << 6));
+
+    /* Powerup USB PLL */
+    LPC_SYSCON->PDRUNCFG &= ~(CLK_USB);
+
+    /* Wait for PLL to lock */
+    while(!(LPC_SYSCON->USBPLLSTAT & 0x01));
+
+    /* enable USB main clock */
+    LPC_SYSCON->USBCLKSEL = 0x02;
+    LPC_SYSCON->USBCLKDIV = 1;
+
+    /* Enable AHB clock to the USB block. */
+    LPC_SYSCON->SYSAHBCLKCTRL1 |= CLK_USB;
+
+    /* power UP USB Phy */
+    LPC_SYSCON->PDRUNCFG &= ~(1UL << 9);
+
+    /* Reset USB block */
+    LPC_SYSCON->PRESETCTRL1 |= (CLK_USB);
+    LPC_SYSCON->PRESETCTRL1 &= ~(CLK_USB);
+
+#else
+    #if defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501)
+    // USB_VBUS input with pull-down
+    LPC_IOCON->PIO0_3 = 0x00000009;
+    #endif
+
+    // nUSB_CONNECT output
+    LPC_IOCON->PIO0_6 = 0x00000001;
+
+    // Enable clocks (USB registers, USB RAM)
+    LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
+
+    // Ensure device disconnected (DCON not set)
+    LPC_USB->DEVCMDSTAT = 0;
+#endif
+    // to ensure that the USB host sees the device as
+    // disconnected if the target CPU is reset.
+    wait(0.3);
+
+    // Reserve space in USB RAM for endpoint command/status list
+    // Must be 256 byte aligned
+    usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
+    ep = (EP_COMMAND_STATUS *)usbRamPtr;
+    usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
+    LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
+
+    // Reserve space in USB RAM for Endpoint 0
+    // Must be 64 byte aligned
+    usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
+    ct = (CONTROL_TRANSFER *)usbRamPtr;
+    usbRamPtr += sizeof(CONTROL_TRANSFER);
+    LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
+
+    // Setup command/status list for EP0
+    ep[0].out[0] = 0;
+    ep[0].in[0] =  0;
+    ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
+
+    // Route all interrupts to IRQ, some can be routed to
+    // USB_FIQ if you wish.
+    LPC_USB->INTROUTING = 0;
+
+    // Set device address 0, enable USB device, no remote wakeup
+    devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+
+    // Enable interrupts for device events and EP0
+    LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT) | FRAME_INT;
+    instance = this;
+
+    //attach IRQ handler and enable interrupts
+    NVIC_SetVector(USB_IRQ, (uint32_t)&_usbisr);
+}
+
+USBHAL::~USBHAL(void) {
+    // Ensure device disconnected (DCON not set)
+    LPC_USB->DEVCMDSTAT = 0;
+    // Disable USB interrupts
+    NVIC_DisableIRQ(USB_IRQ);
+}
+
+void USBHAL::connect(void) {
+    NVIC_EnableIRQ(USB_IRQ);
+    devCmdStat |= DCON;
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+void USBHAL::disconnect(void) {
+    NVIC_DisableIRQ(USB_IRQ);
+    devCmdStat &= ~DCON;
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+void USBHAL::configureDevice(void) {
+    // Not required
+}
+
+void USBHAL::unconfigureDevice(void) {
+    // Not required
+}
+
+void USBHAL::EP0setup(uint8_t *buffer) {
+    // Copy setup packet data
+    USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
+}
+
+void USBHAL::EP0read(void) {
+    // Start an endpoint 0 read
+
+    // The USB ISR will call USBDevice_EP0out() when a packet has been read,
+    // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
+    // read the data.
+
+    ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
+                   | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
+    // Complete an endpoint 0 read
+    uint32_t bytesRead;
+
+    // Find how many bytes were read
+    bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
+
+    // Copy data
+    USBMemCopy(buffer, ct->out, bytesRead);
+    return bytesRead;
+}
+
+
+void USBHAL::EP0readStage(void) {
+    // Not required
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
+    // Start and endpoint 0 write
+
+    // The USB ISR will call USBDevice_EP0in() when the data has
+    // been written, the USBDevice layer then calls
+    // USBBusInterface_EP0getWriteResult() to complete the transaction.
+
+    // Copy data
+    USBMemCopy(ct->in, buffer, size);
+
+    // Start transfer
+    ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
+                  | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
+}
+
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
+    uint8_t bf = 0;
+    uint32_t flags = 0;
+
+    //check which buffer must be filled
+    if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+        // Double buffered
+        if (LPC_USB->EPINUSE & EP(endpoint)) {
+            bf = 1;
+        } else {
+            bf = 0;
+        }
+    }
+
+    // if isochronous endpoint, T = 1
+    if(endpointState[endpoint].options & ISOCHRONOUS)
+    {
+        flags |= CMDSTS_T;
+    }
+
+    //Active the endpoint for reading
+    ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
+                                       | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags;
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
+
+    uint8_t bf = 0;
+
+    if (!(epComplete & EP(endpoint)))
+        return EP_PENDING;
+    else {
+        epComplete &= ~EP(endpoint);
+
+        //check which buffer has been filled
+        if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+            // Double buffered (here we read the previous buffer which was used)
+            if (LPC_USB->EPINUSE & EP(endpoint)) {
+                bf = 0;
+            } else {
+                bf = 1;
+            }
+        }
+
+        // Find how many bytes were read
+        *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf]));
+
+        // Copy data
+        USBMemCopy(data, ct->out, *bytesRead);
+        return EP_COMPLETED;
+    }
+}
+
+void USBHAL::EP0getWriteResult(void) {
+    // Not required
+}
+
+void USBHAL::EP0stall(void) {
+    ep[0].in[0] = CMDSTS_S;
+    ep[0].out[0] = CMDSTS_S;
+}
+
+void USBHAL::setAddress(uint8_t address) {
+    devCmdStat &= ~DEV_ADDR_MASK;
+    devCmdStat |= DEV_ADDR(address);
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
+    uint32_t flags = 0;
+    uint32_t bf;
+
+    // Validate parameters
+    if (data == NULL) {
+        return EP_INVALID;
+    }
+
+    if (endpoint > LAST_PHYSICAL_ENDPOINT) {
+        return EP_INVALID;
+    }
+
+    if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
+        return EP_INVALID;
+    }
+
+    if (size > endpointState[endpoint].maxPacket) {
+        return EP_INVALID;
+    }
+
+    if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+        // Double buffered
+        if (LPC_USB->EPINUSE & EP(endpoint)) {
+            bf = 1;
+        } else {
+            bf = 0;
+        }
+    } else {
+        // Single buffered
+        bf = 0;
+    }
+
+    // Check if already active
+    if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
+        return EP_INVALID;
+    }
+
+    // Check if stalled
+    if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
+        return EP_STALLED;
+    }
+
+    // Copy data to USB RAM
+    USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
+
+    // Add options
+    if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
+        flags |= CMDSTS_RF;
+    }
+
+    if (endpointState[endpoint].options & ISOCHRONOUS) {
+        flags |= CMDSTS_T;
+    }
+
+    // Add transfer
+    ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
+                                      endpointState[endpoint].buffer[bf]) \
+                                      | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
+
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
+    uint32_t bf;
+
+    // Validate parameters
+    if (endpoint > LAST_PHYSICAL_ENDPOINT) {
+        return EP_INVALID;
+    }
+
+    if (OUT_EP(endpoint)) {
+        return EP_INVALID;
+    }
+
+    if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+        // Double buffered     // TODO: FIX THIS
+        if (LPC_USB->EPINUSE & EP(endpoint)) {
+            bf = 1;
+        } else {
+            bf = 0;
+        }
+    } else {
+        // Single buffered
+        bf = 0;
+    }
+
+    // Check if endpoint still active
+    if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
+        return EP_PENDING;
+    }
+
+    // Check if stalled
+    if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
+        return EP_STALLED;
+    }
+
+    return EP_COMPLETED;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint) {
+
+    // FIX: should this clear active bit?
+    if (IN_EP(endpoint)) {
+        ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
+        ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
+    } else {
+        ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
+        ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
+    }
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint) {
+    if (LPC_USB->EPBUFCFG & EP(endpoint)) {
+        // Double buffered
+        if (IN_EP(endpoint)) {
+            ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
+            ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
+
+            if (LPC_USB->EPINUSE & EP(endpoint)) {
+                ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
+            } else {
+                ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
+            }
+        } else {
+            ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
+            ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
+
+            if (LPC_USB->EPINUSE & EP(endpoint)) {
+                ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
+            } else {
+                ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
+            }
+        }
+    } else {
+        // Single buffered
+        if (IN_EP(endpoint)) {
+            ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR;     // S = 0, TR = 1, TV = 0
+        } else {
+            ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR;    // S = 0, TR = 1, TV = 0
+        }
+    }
+}
+
+bool USBHAL::getEndpointStallState(unsigned char endpoint) {
+    if (IN_EP(endpoint)) {
+        if (LPC_USB->EPINUSE & EP(endpoint)) {
+            if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
+                return true;
+            }
+        } else {
+            if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
+                return true;
+            }
+        }
+    } else {
+        if (LPC_USB->EPINUSE & EP(endpoint)) {
+            if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
+                return true;
+            }
+        } else {
+            if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
+    uint32_t tmpEpRamPtr;
+
+    if (endpoint > LAST_PHYSICAL_ENDPOINT) {
+        return false;
+    }
+
+    // Not applicable to the control endpoints
+    if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
+        return false;
+    }
+
+    // Allocate buffers in USB RAM
+    tmpEpRamPtr = epRamPtr;
+
+    // Must be 64 byte aligned
+    tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
+
+    if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
+        // Out of memory
+        return false;
+    }
+
+    // Allocate first buffer
+    endpointState[endpoint].buffer[0] = tmpEpRamPtr;
+    tmpEpRamPtr += maxPacket;
+
+    if (!(options & SINGLE_BUFFERED)) {
+        // Must be 64 byte aligned
+        tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
+
+        if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
+            // Out of memory
+            return false;
+        }
+
+        // Allocate second buffer
+        endpointState[endpoint].buffer[1] = tmpEpRamPtr;
+        tmpEpRamPtr += maxPacket;
+    }
+
+    // Commit to this USB RAM allocation
+    epRamPtr = tmpEpRamPtr;
+
+    // Remaining endpoint state values
+    endpointState[endpoint].maxPacket = maxPacket;
+    endpointState[endpoint].options = options;
+
+    // Enable double buffering if required
+    if (options & SINGLE_BUFFERED) {
+        LPC_USB->EPBUFCFG &= ~EP(endpoint);
+    } else {
+        // Double buffered
+        LPC_USB->EPBUFCFG |= EP(endpoint);
+    }
+
+    // Enable interrupt
+    LPC_USB->INTEN |= EP(endpoint);
+
+    // Enable endpoint
+    unstallEndpoint(endpoint);
+    return true;
+}
+
+void USBHAL::remoteWakeup(void) {
+    // Clearing DSUS bit initiates a remote wakeup if the
+    // device is currently enabled and suspended - otherwise
+    // it has no effect.
+    LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
+}
+
+
+static void disableEndpoints(void) {
+    uint32_t logEp;
+
+    // Ref. Table 158 "When a bus reset is received, software
+    // must set the disable bit of all endpoints to 1".
+
+    for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
+        ep[logEp].out[0] = CMDSTS_D;
+        ep[logEp].out[1] = CMDSTS_D;
+        ep[logEp].in[0] =  CMDSTS_D;
+        ep[logEp].in[1] =  CMDSTS_D;
+    }
+
+    // Start of USB RAM for endpoints > 0
+    epRamPtr = usbRamPtr;
+}
+
+
+
+void USBHAL::_usbisr(void) {
+    instance->usbisr();
+}
+
+void USBHAL::usbisr(void) {
+    // Start of frame
+    if (LPC_USB->INTSTAT & FRAME_INT) {
+        // Clear SOF interrupt
+        LPC_USB->INTSTAT = FRAME_INT;
+
+        // SOF event, read frame number
+        SOF(FRAME_NR(LPC_USB->INFO));
+    }
+
+    // Device state
+    if (LPC_USB->INTSTAT & DEV_INT) {
+        LPC_USB->INTSTAT = DEV_INT;
+
+        if (LPC_USB->DEVCMDSTAT & DSUS_C) {
+            // Suspend status changed
+            LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
+            if (LPC_USB->DEVCMDSTAT & DSUS) {
+                suspendStateChanged(1);
+            } else {
+                suspendStateChanged(0);
+            }
+        }
+
+        if (LPC_USB->DEVCMDSTAT & DRES_C) {
+            // Bus reset
+            LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
+
+            // Disable endpoints > 0
+            disableEndpoints();
+
+            // Bus reset event
+            busReset();
+        }
+    }
+
+    // Endpoint 0
+    if (LPC_USB->INTSTAT & EP(EP0OUT)) {
+        // Clear EP0OUT/SETUP interrupt
+        LPC_USB->INTSTAT = EP(EP0OUT);
+
+        // Check if SETUP
+        if (LPC_USB->DEVCMDSTAT & SETUP) {
+            // Clear Active and Stall bits for EP0
+            // Documentation does not make it clear if we must use the
+            // EPSKIP register to achieve this, Fig. 16 and NXP reference
+            // code suggests we can just clear the Active bits - check with
+            // NXP to be sure.
+            ep[0].in[0] = 0;
+            ep[0].out[0] = 0;
+
+            // Clear EP0IN interrupt
+            LPC_USB->INTSTAT = EP(EP0IN);
+
+            // Clear SETUP (and INTONNAK_CI/O) in device status register
+            LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
+
+            // EP0 SETUP event (SETUP data received)
+            EP0setupCallback();
+        } else {
+            // EP0OUT ACK event (OUT data received)
+            EP0out();
+        }
+    }
+
+    if (LPC_USB->INTSTAT & EP(EP0IN)) {
+        // Clear EP0IN interrupt
+        LPC_USB->INTSTAT = EP(EP0IN);
+
+        // EP0IN ACK event (IN data sent)
+        EP0in();
+    }
+
+    for (uint8_t num = 2; num < 5*2; num++) {
+        if (LPC_USB->INTSTAT & EP(num)) {
+            LPC_USB->INTSTAT = EP(num);
+            epComplete |= EP(num);
+            if ((instance->*(epCallback[num - 2]))()) {
+                epComplete &= ~EP(num);
+            }
+        }
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_LPC17.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,623 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC2460)
+
+#include "USBHAL.h"
+
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1UL<<endpoint)
+
+// Power Control for Peripherals register
+#define PCUSB      (1UL<<31)
+
+// USB Clock Control register
+#define DEV_CLK_EN (1UL<<1)
+#define AHB_CLK_EN (1UL<<4)
+
+// USB Clock Status register
+#define DEV_CLK_ON (1UL<<1)
+#define AHB_CLK_ON (1UL<<4)
+
+// USB Device Interupt registers
+#define FRAME      (1UL<<0)
+#define EP_FAST    (1UL<<1)
+#define EP_SLOW    (1UL<<2)
+#define DEV_STAT   (1UL<<3)
+#define CCEMPTY    (1UL<<4)
+#define CDFULL     (1UL<<5)
+#define RxENDPKT   (1UL<<6)
+#define TxENDPKT   (1UL<<7)
+#define EP_RLZED   (1UL<<8)
+#define ERR_INT    (1UL<<9)
+
+// USB Control register
+#define RD_EN (1<<0)
+#define WR_EN (1<<1)
+#define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
+
+// USB Receive Packet Length register
+#define DV      (1UL<<10)
+#define PKT_RDY (1UL<<11)
+#define PKT_LNGTH_MASK (0x3ff)
+
+// Serial Interface Engine (SIE)
+#define SIE_WRITE   (0x01)
+#define SIE_READ    (0x02)
+#define SIE_COMMAND (0x05)
+#define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
+
+// SIE Command codes
+#define SIE_CMD_SET_ADDRESS        (0xD0)
+#define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
+#define SIE_CMD_SET_MODE           (0xF3)
+#define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
+#define SIE_CMD_READ_TEST_REGISTER (0xFD)
+#define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_ERROR_CODE     (0xFF)
+#define SIE_CMD_READ_ERROR_STATUS  (0xFB)
+
+#define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
+#define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
+#define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
+
+#define SIE_CMD_CLEAR_BUFFER    (0xF2)
+#define SIE_CMD_VALIDATE_BUFFER (0xFA)
+
+// SIE Device Status register
+#define SIE_DS_CON    (1<<0)
+#define SIE_DS_CON_CH (1<<1)
+#define SIE_DS_SUS    (1<<2)
+#define SIE_DS_SUS_CH (1<<3)
+#define SIE_DS_RST    (1<<4)
+
+// SIE Device Set Address register
+#define SIE_DSA_DEV_EN  (1<<7)
+
+// SIE Configue Device register
+#define SIE_CONF_DEVICE (1<<0)
+
+// Select Endpoint register
+#define SIE_SE_FE       (1<<0)
+#define SIE_SE_ST       (1<<1)
+#define SIE_SE_STP      (1<<2)
+#define SIE_SE_PO       (1<<3)
+#define SIE_SE_EPN      (1<<4)
+#define SIE_SE_B_1_FULL (1<<5)
+#define SIE_SE_B_2_FULL (1<<6)
+
+// Set Endpoint Status command
+#define SIE_SES_ST      (1<<0)
+#define SIE_SES_DA      (1<<5)
+#define SIE_SES_RF_MO   (1<<6)
+#define SIE_SES_CND_ST  (1<<7)
+
+
+USBHAL * USBHAL::instance;
+
+static volatile int epComplete;
+static uint32_t endpointStallState;
+
+static void SIECommand(uint32_t command) {
+    // The command phase of a SIE transaction
+    LPC_USB->USBDevIntClr = CCEMPTY;
+    LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
+    while (!(LPC_USB->USBDevIntSt & CCEMPTY));
+}
+
+static void SIEWriteData(uint8_t data) {
+    // The data write phase of a SIE transaction
+    LPC_USB->USBDevIntClr = CCEMPTY;
+    LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
+    while (!(LPC_USB->USBDevIntSt & CCEMPTY));
+}
+
+static uint8_t SIEReadData(uint32_t command) {
+    // The data read phase of a SIE transaction
+    LPC_USB->USBDevIntClr = CDFULL;
+    LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
+    while (!(LPC_USB->USBDevIntSt & CDFULL));
+    return (uint8_t)LPC_USB->USBCmdData;
+}
+
+static void SIEsetDeviceStatus(uint8_t status) {
+    // Write SIE device status register
+    SIECommand(SIE_CMD_SET_DEVICE_STATUS);
+    SIEWriteData(status);
+}
+
+static uint8_t SIEgetDeviceStatus(void) {
+    // Read SIE device status register
+    SIECommand(SIE_CMD_GET_DEVICE_STATUS);
+    return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
+}
+
+void SIEsetAddress(uint8_t address) {
+    // Write SIE device address register
+    SIECommand(SIE_CMD_SET_ADDRESS);
+    SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
+}
+
+static uint8_t SIEselectEndpoint(uint8_t endpoint) {
+    // SIE select endpoint command
+    SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
+    return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
+}
+
+static uint8_t SIEclearBuffer(void) {
+    // SIE clear buffer command
+    SIECommand(SIE_CMD_CLEAR_BUFFER);
+    return SIEReadData(SIE_CMD_CLEAR_BUFFER);
+}
+
+static void SIEvalidateBuffer(void) {
+    // SIE validate buffer command
+    SIECommand(SIE_CMD_VALIDATE_BUFFER);
+}
+
+static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) {
+    // SIE set endpoint status command
+    SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
+    SIEWriteData(status);
+}
+
+static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
+static uint16_t SIEgetFrameNumber(void) {
+    // Read current frame number
+    uint16_t lowByte;
+    uint16_t highByte;
+
+    SIECommand(SIE_CMD_READ_FRAME_NUMBER);
+    lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
+    highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
+
+    return (highByte << 8) | lowByte;
+}
+
+static void SIEconfigureDevice(void) {
+    // SIE Configure device command
+    SIECommand(SIE_CMD_CONFIGURE_DEVICE);
+    SIEWriteData(SIE_CONF_DEVICE);
+}
+
+static void SIEunconfigureDevice(void) {
+    // SIE Configure device command
+    SIECommand(SIE_CMD_CONFIGURE_DEVICE);
+    SIEWriteData(0);
+}
+
+static void SIEconnect(void) {
+    // Connect USB device
+    uint8_t status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus(status | SIE_DS_CON);
+}
+
+
+static void SIEdisconnect(void) {
+    // Disconnect USB device
+    uint8_t status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus(status & ~SIE_DS_CON);
+}
+
+
+static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) {
+    // Implemented using using EP_INT_CLR.
+    LPC_USB->USBEpIntClr = EP(endpoint);
+    while (!(LPC_USB->USBDevIntSt & CDFULL));
+    return (uint8_t)LPC_USB->USBCmdData;
+}
+
+
+static void enableEndpointEvent(uint8_t endpoint) {
+    // Enable an endpoint interrupt
+    LPC_USB->USBEpIntEn |= EP(endpoint);
+}
+
+static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
+static void disableEndpointEvent(uint8_t endpoint) {
+    // Disable an endpoint interrupt
+    LPC_USB->USBEpIntEn &= ~EP(endpoint);
+}
+
+static volatile uint32_t __attribute__((used)) dummyRead;
+uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
+    // Read from an OUT endpoint
+    uint32_t size;
+    uint32_t i;
+    uint32_t data = 0;
+    uint8_t offset;
+
+    LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
+    while (!(LPC_USB->USBRxPLen & PKT_RDY));
+
+    size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
+
+    offset = 0;
+
+    if (size > 0) {
+        for (i=0; i<size; i++) {
+            if (offset==0) {
+                // Fetch up to four bytes of data as a word
+                data = LPC_USB->USBRxData;
+            }
+
+            // extract a byte
+            *buffer = (data>>offset) & 0xff;
+            buffer++;
+
+            // move on to the next byte
+            offset = (offset + 8) % 32;
+        }
+    } else {
+        dummyRead = LPC_USB->USBRxData;
+    }
+
+    LPC_USB->USBCtrl = 0;
+
+    if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
+        SIEselectEndpoint(endpoint);
+        SIEclearBuffer();
+    }
+
+    return size;
+}
+
+static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) {
+    // Write to an IN endpoint
+    uint32_t temp, data;
+    uint8_t offset;
+
+    LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
+
+    LPC_USB->USBTxPLen = size;
+    offset = 0;
+    data = 0;
+
+    if (size>0) {
+        do {
+            // Fetch next data byte into a word-sized temporary variable
+            temp = *buffer++;
+
+            // Add to current data word
+            temp = temp << offset;
+            data = data | temp;
+
+            // move on to the next byte
+            offset = (offset + 8) % 32;
+            size--;
+
+            if ((offset==0) || (size==0)) {
+                // Write the word to the endpoint
+                LPC_USB->USBTxData = data;
+                data = 0;
+            }
+        } while (size>0);
+    } else {
+        LPC_USB->USBTxData = 0;
+    }
+
+    // Clear WR_EN to cover zero length packet case
+    LPC_USB->USBCtrl=0;
+
+    SIEselectEndpoint(endpoint);
+    SIEvalidateBuffer();
+}
+
+USBHAL::USBHAL(void) {
+    // Disable IRQ
+    NVIC_DisableIRQ(USB_IRQn);
+
+    // fill in callback array
+    epCallback[0] = &USBHAL::EP1_OUT_callback;
+    epCallback[1] = &USBHAL::EP1_IN_callback;
+    epCallback[2] = &USBHAL::EP2_OUT_callback;
+    epCallback[3] = &USBHAL::EP2_IN_callback;
+    epCallback[4] = &USBHAL::EP3_OUT_callback;
+    epCallback[5] = &USBHAL::EP3_IN_callback;
+    epCallback[6] = &USBHAL::EP4_OUT_callback;
+    epCallback[7] = &USBHAL::EP4_IN_callback;
+    epCallback[8] = &USBHAL::EP5_OUT_callback;
+    epCallback[9] = &USBHAL::EP5_IN_callback;
+    epCallback[10] = &USBHAL::EP6_OUT_callback;
+    epCallback[11] = &USBHAL::EP6_IN_callback;
+    epCallback[12] = &USBHAL::EP7_OUT_callback;
+    epCallback[13] = &USBHAL::EP7_IN_callback;
+    epCallback[14] = &USBHAL::EP8_OUT_callback;
+    epCallback[15] = &USBHAL::EP8_IN_callback;
+    epCallback[16] = &USBHAL::EP9_OUT_callback;
+    epCallback[17] = &USBHAL::EP9_IN_callback;
+    epCallback[18] = &USBHAL::EP10_OUT_callback;
+    epCallback[19] = &USBHAL::EP10_IN_callback;
+    epCallback[20] = &USBHAL::EP11_OUT_callback;
+    epCallback[21] = &USBHAL::EP11_IN_callback;
+    epCallback[22] = &USBHAL::EP12_OUT_callback;
+    epCallback[23] = &USBHAL::EP12_IN_callback;
+    epCallback[24] = &USBHAL::EP13_OUT_callback;
+    epCallback[25] = &USBHAL::EP13_IN_callback;
+    epCallback[26] = &USBHAL::EP14_OUT_callback;
+    epCallback[27] = &USBHAL::EP14_IN_callback;
+    epCallback[28] = &USBHAL::EP15_OUT_callback;
+    epCallback[29] = &USBHAL::EP15_IN_callback;
+
+    // Enable power to USB device controller
+    LPC_SC->PCONP |= PCUSB;
+
+    // Enable USB clocks
+    LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
+    while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
+
+    // Configure pins P0.29 and P0.30 to be USB D+ and USB D-
+    LPC_PINCON->PINSEL1 &= 0xc3ffffff;
+    LPC_PINCON->PINSEL1 |= 0x14000000;
+
+    // Disconnect USB device
+    SIEdisconnect();
+
+    // Configure pin P2.9 to be Connect
+    LPC_PINCON->PINSEL4 &= 0xfffcffff;
+    LPC_PINCON->PINSEL4 |= 0x00040000;
+
+    // Connect must be low for at least 2.5uS
+    wait(0.3);
+
+    // Set the maximum packet size for the control endpoints
+    realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
+    realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
+
+    // Attach IRQ
+    instance = this;
+    NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
+
+    // Enable interrupts for device events and EP0
+    LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT | FRAME;
+    enableEndpointEvent(EP0IN);
+    enableEndpointEvent(EP0OUT);
+}
+
+USBHAL::~USBHAL(void) {
+    // Ensure device disconnected
+    SIEdisconnect();
+    // Disable USB interrupts
+    NVIC_DisableIRQ(USB_IRQn);
+}
+
+void USBHAL::connect(void) {
+    NVIC_EnableIRQ(USB_IRQn);
+    // Connect USB device
+    SIEconnect();
+}
+
+void USBHAL::disconnect(void) {
+    NVIC_DisableIRQ(USB_IRQn);
+    // Disconnect USB device
+    SIEdisconnect();
+}
+
+void USBHAL::configureDevice(void) {
+    SIEconfigureDevice();
+}
+
+void USBHAL::unconfigureDevice(void) {
+    SIEunconfigureDevice();
+}
+
+void USBHAL::setAddress(uint8_t address) {
+    SIEsetAddress(address);
+}
+
+void USBHAL::EP0setup(uint8_t *buffer) {
+    endpointReadcore(EP0OUT, buffer);
+}
+
+void USBHAL::EP0read(void) {
+    // Not required
+}
+
+void USBHAL::EP0readStage(void) {
+    // Not required
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
+    return endpointReadcore(EP0OUT, buffer);
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
+    endpointWritecore(EP0IN, buffer, size);
+}
+
+void USBHAL::EP0getWriteResult(void) {
+    // Not required
+}
+
+void USBHAL::EP0stall(void) {
+    // This will stall both control endpoints
+    stallEndpoint(EP0OUT);
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
+
+    //for isochronous endpoint, we don't wait an interrupt
+    if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
+        if (!(epComplete & EP(endpoint)))
+            return EP_PENDING;
+    }
+
+    *bytesRead = endpointReadcore(endpoint, buffer);
+    epComplete &= ~EP(endpoint);
+    return EP_COMPLETED;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
+    if (getEndpointStallState(endpoint)) {
+        return EP_STALLED;
+    }
+
+    epComplete &= ~EP(endpoint);
+
+    endpointWritecore(endpoint, data, size);
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
+    if (epComplete & EP(endpoint)) {
+        epComplete &= ~EP(endpoint);
+        return EP_COMPLETED;
+    }
+
+    return EP_PENDING;
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
+    // Realise an endpoint
+    LPC_USB->USBDevIntClr = EP_RLZED;
+    LPC_USB->USBReEp |= EP(endpoint);
+    LPC_USB->USBEpInd = endpoint;
+    LPC_USB->USBMaxPSize = maxPacket;
+
+    while (!(LPC_USB->USBDevIntSt & EP_RLZED));
+    LPC_USB->USBDevIntClr = EP_RLZED;
+
+    // Clear stall state
+    endpointStallState &= ~EP(endpoint);
+
+    enableEndpointEvent(endpoint);
+    return true;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint) {
+    // Stall an endpoint
+    if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) {
+        // Conditionally stall both control endpoints
+        SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
+    } else {
+        SIEsetEndpointStatus(endpoint, SIE_SES_ST);
+
+        // Update stall state
+        endpointStallState |= EP(endpoint);
+    }
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint) {
+    // Unstall an endpoint. The endpoint will also be reinitialised
+    SIEsetEndpointStatus(endpoint, 0);
+
+    // Update stall state
+    endpointStallState &= ~EP(endpoint);
+}
+
+bool USBHAL::getEndpointStallState(uint8_t endpoint) {
+    // Returns true if endpoint stalled
+    return endpointStallState & EP(endpoint);
+}
+
+void USBHAL::remoteWakeup(void) {
+    // Remote wakeup
+    uint8_t status;
+
+    // Enable USB clocks
+    LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
+    while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
+
+    status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus(status & ~SIE_DS_SUS);
+}
+
+void USBHAL::_usbisr(void) {
+    instance->usbisr();
+}
+
+
+void USBHAL::usbisr(void) {
+    uint8_t devStat;
+
+    if (LPC_USB->USBDevIntSt & FRAME) {
+        // Start of frame event
+        SOF(SIEgetFrameNumber());
+        // Clear interrupt status flag
+        LPC_USB->USBDevIntClr = FRAME;
+    }
+
+    if (LPC_USB->USBDevIntSt & DEV_STAT) {
+        // Device Status interrupt
+        // Must clear the interrupt status flag before reading the device status from the SIE
+        LPC_USB->USBDevIntClr = DEV_STAT;
+
+        // Read device status from SIE
+        devStat = SIEgetDeviceStatus();
+        //printf("devStat: %d\r\n", devStat);
+
+        if (devStat & SIE_DS_SUS_CH) {
+            // Suspend status changed
+            if((devStat & SIE_DS_SUS) != 0) {
+                suspendStateChanged(0);
+            }
+        }
+
+        if (devStat & SIE_DS_RST) {
+            // Bus reset
+            if((devStat & SIE_DS_SUS) == 0) {
+                suspendStateChanged(1);
+            }
+            busReset();
+        }
+    }
+
+    if (LPC_USB->USBDevIntSt & EP_SLOW) {
+        // (Slow) Endpoint Interrupt
+
+        // Process each endpoint interrupt
+        if (LPC_USB->USBEpIntSt & EP(EP0OUT)) {
+            if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
+                // this is a setup packet
+                EP0setupCallback();
+            } else {
+                EP0out();
+            }
+            LPC_USB->USBDevIntClr = EP_SLOW;
+        }
+
+        if (LPC_USB->USBEpIntSt & EP(EP0IN)) {
+            selectEndpointClearInterrupt(EP0IN);
+            LPC_USB->USBDevIntClr = EP_SLOW;
+            EP0in();
+        }
+
+        for (uint8_t num = 2; num < 16*2; num++) {
+            if (LPC_USB->USBEpIntSt & EP(num)) {
+                selectEndpointClearInterrupt(num);
+                epComplete |= EP(num);
+                LPC_USB->USBDevIntClr = EP_SLOW;
+                if ((instance->*(epCallback[num - 2]))()) {
+                    epComplete &= ~EP(num);
+                }
+            }
+        }
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_LPC40.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,628 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
+
+#include "USBHAL.h"
+
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1UL<<endpoint)
+
+// Power Control for Peripherals register
+#define PCUSB      (1UL<<31)
+
+// USB Clock Control register
+#define DEV_CLK_EN  (1UL<<1)
+#define PORT_CLK_EN (1UL<<3)
+#define AHB_CLK_EN  (1UL<<4)
+
+// USB Clock Status register
+#define DEV_CLK_ON (1UL<<1)
+#define AHB_CLK_ON (1UL<<4)
+
+// USB Device Interupt registers
+#define FRAME      (1UL<<0)
+#define EP_FAST    (1UL<<1)
+#define EP_SLOW    (1UL<<2)
+#define DEV_STAT   (1UL<<3)
+#define CCEMPTY    (1UL<<4)
+#define CDFULL     (1UL<<5)
+#define RxENDPKT   (1UL<<6)
+#define TxENDPKT   (1UL<<7)
+#define EP_RLZED   (1UL<<8)
+#define ERR_INT    (1UL<<9)
+
+// USB Control register
+#define RD_EN (1<<0)
+#define WR_EN (1<<1)
+#define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
+
+// USB Receive Packet Length register
+#define DV      (1UL<<10)
+#define PKT_RDY (1UL<<11)
+#define PKT_LNGTH_MASK (0x3ff)
+
+// Serial Interface Engine (SIE)
+#define SIE_WRITE   (0x01)
+#define SIE_READ    (0x02)
+#define SIE_COMMAND (0x05)
+#define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
+
+// SIE Command codes
+#define SIE_CMD_SET_ADDRESS        (0xD0)
+#define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
+#define SIE_CMD_SET_MODE           (0xF3)
+#define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
+#define SIE_CMD_READ_TEST_REGISTER (0xFD)
+#define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_ERROR_CODE     (0xFF)
+#define SIE_CMD_READ_ERROR_STATUS  (0xFB)
+
+#define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
+#define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
+#define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
+
+#define SIE_CMD_CLEAR_BUFFER    (0xF2)
+#define SIE_CMD_VALIDATE_BUFFER (0xFA)
+
+// SIE Device Status register
+#define SIE_DS_CON    (1<<0)
+#define SIE_DS_CON_CH (1<<1)
+#define SIE_DS_SUS    (1<<2)
+#define SIE_DS_SUS_CH (1<<3)
+#define SIE_DS_RST    (1<<4)
+
+// SIE Device Set Address register
+#define SIE_DSA_DEV_EN  (1<<7)
+
+// SIE Configue Device register
+#define SIE_CONF_DEVICE (1<<0)
+
+// Select Endpoint register
+#define SIE_SE_FE       (1<<0)
+#define SIE_SE_ST       (1<<1)
+#define SIE_SE_STP      (1<<2)
+#define SIE_SE_PO       (1<<3)
+#define SIE_SE_EPN      (1<<4)
+#define SIE_SE_B_1_FULL (1<<5)
+#define SIE_SE_B_2_FULL (1<<6)
+
+// Set Endpoint Status command
+#define SIE_SES_ST      (1<<0)
+#define SIE_SES_DA      (1<<5)
+#define SIE_SES_RF_MO   (1<<6)
+#define SIE_SES_CND_ST  (1<<7)
+
+
+USBHAL * USBHAL::instance;
+
+static volatile int epComplete;
+static uint32_t endpointStallState;
+
+static void SIECommand(uint32_t command) {
+    // The command phase of a SIE transaction
+    LPC_USB->DevIntClr = CCEMPTY;
+    LPC_USB->CmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
+    while (!(LPC_USB->DevIntSt & CCEMPTY));
+}
+
+static void SIEWriteData(uint8_t data) {
+    // The data write phase of a SIE transaction
+    LPC_USB->DevIntClr = CCEMPTY;
+    LPC_USB->CmdCode = SIE_CMD_CODE(SIE_WRITE, data);
+    while (!(LPC_USB->DevIntSt & CCEMPTY));
+}
+
+static uint8_t SIEReadData(uint32_t command) {
+    // The data read phase of a SIE transaction
+    LPC_USB->DevIntClr = CDFULL;
+    LPC_USB->CmdCode = SIE_CMD_CODE(SIE_READ, command);
+    while (!(LPC_USB->DevIntSt & CDFULL));
+    return (uint8_t)LPC_USB->CmdData;
+}
+
+static void SIEsetDeviceStatus(uint8_t status) {
+    // Write SIE device status register
+    SIECommand(SIE_CMD_SET_DEVICE_STATUS);
+    SIEWriteData(status);
+}
+
+static uint8_t SIEgetDeviceStatus(void) {
+    // Read SIE device status register
+    SIECommand(SIE_CMD_GET_DEVICE_STATUS);
+    return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
+}
+
+void SIEsetAddress(uint8_t address) {
+    // Write SIE device address register
+    SIECommand(SIE_CMD_SET_ADDRESS);
+    SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
+}
+
+static uint8_t SIEselectEndpoint(uint8_t endpoint) {
+    // SIE select endpoint command
+    SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
+    return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
+}
+
+static uint8_t SIEclearBuffer(void) {
+    // SIE clear buffer command
+    SIECommand(SIE_CMD_CLEAR_BUFFER);
+    return SIEReadData(SIE_CMD_CLEAR_BUFFER);
+}
+
+static void SIEvalidateBuffer(void) {
+    // SIE validate buffer command
+    SIECommand(SIE_CMD_VALIDATE_BUFFER);
+}
+
+static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) {
+    // SIE set endpoint status command
+    SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
+    SIEWriteData(status);
+}
+
+static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
+static uint16_t SIEgetFrameNumber(void) {
+    // Read current frame number
+    uint16_t lowByte;
+    uint16_t highByte;
+
+    SIECommand(SIE_CMD_READ_FRAME_NUMBER);
+    lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
+    highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
+
+    return (highByte << 8) | lowByte;
+}
+
+static void SIEconfigureDevice(void) {
+    // SIE Configure device command
+    SIECommand(SIE_CMD_CONFIGURE_DEVICE);
+    SIEWriteData(SIE_CONF_DEVICE);
+}
+
+static void SIEunconfigureDevice(void) {
+    // SIE Configure device command
+    SIECommand(SIE_CMD_CONFIGURE_DEVICE);
+    SIEWriteData(0);
+}
+
+static void SIEconnect(void) {
+    // Connect USB device
+    uint8_t status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus(status | SIE_DS_CON);
+}
+
+
+static void SIEdisconnect(void) {
+    // Disconnect USB device
+    uint8_t status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus(status & ~SIE_DS_CON);
+}
+
+
+static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) {
+    // Implemented using using EP_INT_CLR.
+    LPC_USB->EpIntClr = EP(endpoint);
+    while (!(LPC_USB->DevIntSt & CDFULL));
+    return (uint8_t)LPC_USB->CmdData;
+}
+
+
+static void enableEndpointEvent(uint8_t endpoint) {
+    // Enable an endpoint interrupt
+    LPC_USB->EpIntEn |= EP(endpoint);
+}
+
+static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
+static void disableEndpointEvent(uint8_t endpoint) {
+    // Disable an endpoint interrupt
+    LPC_USB->EpIntEn &= ~EP(endpoint);
+}
+
+static volatile uint32_t __attribute__((used)) dummyRead;
+uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
+    // Read from an OUT endpoint
+    uint32_t size;
+    uint32_t i;
+    uint32_t data = 0;
+    uint8_t offset;
+
+    LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | RD_EN;
+    while (!(LPC_USB->RxPLen & PKT_RDY));
+
+    size = LPC_USB->RxPLen & PKT_LNGTH_MASK;
+
+    offset = 0;
+
+    if (size > 0) {
+        for (i=0; i<size; i++) {
+            if (offset==0) {
+                // Fetch up to four bytes of data as a word
+                data = LPC_USB->RxData;
+            }
+
+            // extract a byte
+            *buffer = (data>>offset) & 0xff;
+            buffer++;
+
+            // move on to the next byte
+            offset = (offset + 8) % 32;
+        }
+    } else {
+        dummyRead = LPC_USB->RxData;
+    }
+
+    LPC_USB->Ctrl = 0;
+
+    if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
+        SIEselectEndpoint(endpoint);
+        SIEclearBuffer();
+    }
+
+    return size;
+}
+
+static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) {
+    // Write to an IN endpoint
+    uint32_t temp, data;
+    uint8_t offset;
+
+    LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | WR_EN;
+
+    LPC_USB->TxPLen = size;
+    offset = 0;
+    data = 0;
+
+    if (size>0) {
+        do {
+            // Fetch next data byte into a word-sized temporary variable
+            temp = *buffer++;
+
+            // Add to current data word
+            temp = temp << offset;
+            data = data | temp;
+
+            // move on to the next byte
+            offset = (offset + 8) % 32;
+            size--;
+
+            if ((offset==0) || (size==0)) {
+                // Write the word to the endpoint
+                LPC_USB->TxData = data;
+                data = 0;
+            }
+        } while (size>0);
+    } else {
+        LPC_USB->TxData = 0;
+    }
+
+    // Clear WR_EN to cover zero length packet case
+    LPC_USB->Ctrl=0;
+
+    SIEselectEndpoint(endpoint);
+    SIEvalidateBuffer();
+}
+
+USBHAL::USBHAL(void) {
+    // Disable IRQ
+    NVIC_DisableIRQ(USB_IRQn);
+
+    // fill in callback array
+    epCallback[0] = &USBHAL::EP1_OUT_callback;
+    epCallback[1] = &USBHAL::EP1_IN_callback;
+    epCallback[2] = &USBHAL::EP2_OUT_callback;
+    epCallback[3] = &USBHAL::EP2_IN_callback;
+    epCallback[4] = &USBHAL::EP3_OUT_callback;
+    epCallback[5] = &USBHAL::EP3_IN_callback;
+    epCallback[6] = &USBHAL::EP4_OUT_callback;
+    epCallback[7] = &USBHAL::EP4_IN_callback;
+    epCallback[8] = &USBHAL::EP5_OUT_callback;
+    epCallback[9] = &USBHAL::EP5_IN_callback;
+    epCallback[10] = &USBHAL::EP6_OUT_callback;
+    epCallback[11] = &USBHAL::EP6_IN_callback;
+    epCallback[12] = &USBHAL::EP7_OUT_callback;
+    epCallback[13] = &USBHAL::EP7_IN_callback;
+    epCallback[14] = &USBHAL::EP8_OUT_callback;
+    epCallback[15] = &USBHAL::EP8_IN_callback;
+    epCallback[16] = &USBHAL::EP9_OUT_callback;
+    epCallback[17] = &USBHAL::EP9_IN_callback;
+    epCallback[18] = &USBHAL::EP10_OUT_callback;
+    epCallback[19] = &USBHAL::EP10_IN_callback;
+    epCallback[20] = &USBHAL::EP11_OUT_callback;
+    epCallback[21] = &USBHAL::EP11_IN_callback;
+    epCallback[22] = &USBHAL::EP12_OUT_callback;
+    epCallback[23] = &USBHAL::EP12_IN_callback;
+    epCallback[24] = &USBHAL::EP13_OUT_callback;
+    epCallback[25] = &USBHAL::EP13_IN_callback;
+    epCallback[26] = &USBHAL::EP14_OUT_callback;
+    epCallback[27] = &USBHAL::EP14_IN_callback;
+    epCallback[28] = &USBHAL::EP15_OUT_callback;
+    epCallback[29] = &USBHAL::EP15_IN_callback;
+
+    // Enable power to USB device controller
+    LPC_SC->PCONP |= PCUSB;
+
+    // Enable USB clocks
+    LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN;
+    while ((LPC_USB->USBClkSt & (DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN)) != (DEV_CLK_ON | AHB_CLK_ON | PORT_CLK_EN));
+
+    // Select port USB2
+    LPC_USB->StCtrl |= 3;
+
+
+    // Configure pin P0.31 to be USB2
+    LPC_IOCON->P0_31 &= ~0x07;
+    LPC_IOCON->P0_31 |= 0x01;
+
+    // Disconnect USB device
+    SIEdisconnect();
+
+    // Configure pin P0.14 to be Connect
+    LPC_IOCON->P0_14 &= ~0x07;
+    LPC_IOCON->P0_14 |= 0x03;
+
+    // Connect must be low for at least 2.5uS
+    wait(0.3);
+
+    // Set the maximum packet size for the control endpoints
+    realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
+    realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
+
+    // Attach IRQ
+    instance = this;
+    NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
+
+    // Enable interrupts for device events and EP0
+    LPC_USB->DevIntEn = EP_SLOW | DEV_STAT | FRAME;
+    enableEndpointEvent(EP0IN);
+    enableEndpointEvent(EP0OUT);
+}
+
+USBHAL::~USBHAL(void) {
+    // Ensure device disconnected
+    SIEdisconnect();
+    // Disable USB interrupts
+    NVIC_DisableIRQ(USB_IRQn);
+}
+
+void USBHAL::connect(void) {
+    NVIC_EnableIRQ(USB_IRQn);
+    // Connect USB device
+    SIEconnect();
+}
+
+void USBHAL::disconnect(void) {
+    NVIC_DisableIRQ(USB_IRQn);
+    // Disconnect USB device
+    SIEdisconnect();
+}
+
+void USBHAL::configureDevice(void) {
+    SIEconfigureDevice();
+}
+
+void USBHAL::unconfigureDevice(void) {
+    SIEunconfigureDevice();
+}
+
+void USBHAL::setAddress(uint8_t address) {
+    SIEsetAddress(address);
+}
+
+void USBHAL::EP0setup(uint8_t *buffer) {
+    endpointReadcore(EP0OUT, buffer);
+}
+
+void USBHAL::EP0read(void) {
+    // Not required
+}
+
+void USBHAL::EP0readStage(void) {
+    // Not required
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
+    return endpointReadcore(EP0OUT, buffer);
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
+    endpointWritecore(EP0IN, buffer, size);
+}
+
+void USBHAL::EP0getWriteResult(void) {
+    // Not required
+}
+
+void USBHAL::EP0stall(void) {
+    // This will stall both control endpoints
+    stallEndpoint(EP0OUT);
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
+
+    //for isochronous endpoint, we don't wait an interrupt
+    if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
+        if (!(epComplete & EP(endpoint)))
+            return EP_PENDING;
+    }
+
+    *bytesRead = endpointReadcore(endpoint, buffer);
+    epComplete &= ~EP(endpoint);
+    return EP_COMPLETED;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
+    if (getEndpointStallState(endpoint)) {
+        return EP_STALLED;
+    }
+
+    epComplete &= ~EP(endpoint);
+
+    endpointWritecore(endpoint, data, size);
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
+    if (epComplete & EP(endpoint)) {
+        epComplete &= ~EP(endpoint);
+        return EP_COMPLETED;
+    }
+
+    return EP_PENDING;
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
+    // Realise an endpoint
+    LPC_USB->DevIntClr = EP_RLZED;
+    LPC_USB->ReEp |= EP(endpoint);
+    LPC_USB->EpInd = endpoint;
+    LPC_USB->MaxPSize = maxPacket;
+
+    while (!(LPC_USB->DevIntSt & EP_RLZED));
+    LPC_USB->DevIntClr = EP_RLZED;
+
+    // Clear stall state
+    endpointStallState &= ~EP(endpoint);
+
+    enableEndpointEvent(endpoint);
+    return true;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint) {
+    // Stall an endpoint
+    if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) {
+        // Conditionally stall both control endpoints
+        SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
+    } else {
+        SIEsetEndpointStatus(endpoint, SIE_SES_ST);
+
+        // Update stall state
+        endpointStallState |= EP(endpoint);
+    }
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint) {
+    // Unstall an endpoint. The endpoint will also be reinitialised
+    SIEsetEndpointStatus(endpoint, 0);
+
+    // Update stall state
+    endpointStallState &= ~EP(endpoint);
+}
+
+bool USBHAL::getEndpointStallState(uint8_t endpoint) {
+    // Returns true if endpoint stalled
+    return endpointStallState & EP(endpoint);
+}
+
+void USBHAL::remoteWakeup(void) {
+    // Remote wakeup
+    uint8_t status;
+
+    // Enable USB clocks
+    LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
+    while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
+
+    status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus(status & ~SIE_DS_SUS);
+}
+
+void USBHAL::_usbisr(void) {
+    instance->usbisr();
+}
+
+
+void USBHAL::usbisr(void) {
+    uint8_t devStat;
+
+    if (LPC_USB->DevIntSt & FRAME) {
+        // Start of frame event
+        SOF(SIEgetFrameNumber());
+        // Clear interrupt status flag
+        LPC_USB->DevIntClr = FRAME;
+    }
+
+    if (LPC_USB->DevIntSt & DEV_STAT) {
+        // Device Status interrupt
+        // Must clear the interrupt status flag before reading the device status from the SIE
+        LPC_USB->DevIntClr = DEV_STAT;
+
+        // Read device status from SIE
+        devStat = SIEgetDeviceStatus();
+        //printf("devStat: %d\r\n", devStat);
+
+        if (devStat & SIE_DS_SUS_CH) {
+            // Suspend status changed
+            if((devStat & SIE_DS_SUS) != 0) {
+                suspendStateChanged(0);
+            }
+        }
+
+        if (devStat & SIE_DS_RST) {
+            // Bus reset
+            if((devStat & SIE_DS_SUS) == 0) {
+                suspendStateChanged(1);
+            }
+            busReset();
+        }
+    }
+
+    if (LPC_USB->DevIntSt & EP_SLOW) {
+        // (Slow) Endpoint Interrupt
+
+        // Process each endpoint interrupt
+        if (LPC_USB->EpIntSt & EP(EP0OUT)) {
+            if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
+                // this is a setup packet
+                EP0setupCallback();
+            } else {
+                EP0out();
+            }
+            LPC_USB->DevIntClr = EP_SLOW;
+        }
+
+        if (LPC_USB->EpIntSt & EP(EP0IN)) {
+            selectEndpointClearInterrupt(EP0IN);
+            LPC_USB->DevIntClr = EP_SLOW;
+            EP0in();
+        }
+
+        for (uint8_t num = 2; num < 16*2; num++) {
+            if (LPC_USB->EpIntSt & EP(num)) {
+                selectEndpointClearInterrupt(num);
+                epComplete |= EP(num);
+                LPC_USB->DevIntClr = EP_SLOW;
+                if ((instance->*(epCallback[num - 2]))()) {
+                    epComplete &= ~EP(num);
+                }
+            }
+        }
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_Maxim.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#if defined(TARGET_Maxim)
+
+#include "USBHAL.h"
+#include "usb_regs.h"
+#include "clkman_regs.h"
+
+#if defined(TARGET_MAX32625) || defined(TARGET_MAX32630)
+#include "pwrman_regs.h"
+#endif
+
+#define CONNECT_INTS    (MXC_F_USB_DEV_INTEN_BRST | MXC_F_USB_DEV_INTEN_SETUP | MXC_F_USB_DEV_INTEN_EP_IN | MXC_F_USB_DEV_INTEN_EP_OUT | MXC_F_USB_DEV_INTEN_DMA_ERR)
+
+USBHAL *USBHAL::instance;
+
+typedef struct {
+    volatile uint32_t buf0_desc;
+    volatile uint32_t buf0_address;
+    volatile uint32_t buf1_desc;
+    volatile uint32_t buf1_address;
+} ep_buffer_t;
+
+typedef struct {
+    ep_buffer_t out_buffer;
+    ep_buffer_t in_buffer;
+} ep0_buffer_t;
+
+typedef struct {
+    ep0_buffer_t ep0;
+    ep_buffer_t ep[MXC_USB_NUM_EP - 1];
+} ep_buffer_descriptor_t;
+
+// Static storage for endpoint buffer descriptor table. Must be 512 byte aligned for DMA.
+#ifdef __IAR_SYSTEMS_ICC__
+#pragma data_alignment = 512
+#else
+__attribute__ ((aligned (512))) 
+#endif
+ep_buffer_descriptor_t ep_buffer_descriptor;
+
+// static storage for temporary data buffers. Must be 32 byte aligned.
+#ifdef __IAR_SYSTEMS_ICC__
+#pragma data_alignment = 4
+#else
+__attribute__ ((aligned (4))) 
+#endif
+static uint8_t aligned_buffer[NUMBER_OF_LOGICAL_ENDPOINTS][MXC_USB_MAX_PACKET];
+
+// control packet state
+static enum {
+    CTRL_NONE = 0,
+    CTRL_SETUP,
+    CTRL_OUT,
+    CTRL_IN,
+} control_state;
+
+USBHAL::USBHAL(void)
+{
+    NVIC_DisableIRQ(USB_IRQn);
+
+#if defined(TARGET_MAX32600)
+    // The PLL must be enabled for USB
+    MBED_ASSERT(MXC_CLKMAN->clk_config & MXC_F_CLKMAN_CLK_CONFIG_PLL_ENABLE);
+
+    // Enable the USB clock
+    MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_USB_GATE_N;
+#elif defined(TARGET_MAX32620)
+    // Enable the USB clock
+    MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_USB_CLOCK_ENABLE;
+#elif defined(TARGET_MAX32625) || defined(TARGET_MAX32630)
+    MXC_PWRMAN->pwr_rst_ctrl |= MXC_F_PWRMAN_PWR_RST_CTRL_USB_POWERED;
+    MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_USB_CLOCK_ENABLE;
+#endif
+
+    // reset the device
+    MXC_USB->cn = 0;
+    MXC_USB->cn = MXC_F_USB_CN_USB_EN;
+    MXC_USB->dev_inten = 0;
+    MXC_USB->dev_cn = 0;
+    MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST;
+    MXC_USB->dev_cn = 0;
+
+    // fill in callback arrays
+    epCallback[EP0OUT] = NULL;
+    epCallback[EP0IN]  = NULL;
+    epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback;
+    epCallback[EP1IN ] = &USBHAL::EP1_IN_callback;
+    epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback;
+    epCallback[EP2IN ] = &USBHAL::EP2_IN_callback;
+    epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback;
+    epCallback[EP3IN ] = &USBHAL::EP3_IN_callback;
+    epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback;
+    epCallback[EP4IN ] = &USBHAL::EP4_IN_callback;
+    epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback;
+    epCallback[EP5IN ] = &USBHAL::EP5_IN_callback;
+    epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback;
+    epCallback[EP6IN ] = &USBHAL::EP6_IN_callback;
+    epCallback[EP7OUT] = &USBHAL::EP7_OUT_callback;
+    epCallback[EP7IN ] = &USBHAL::EP7_IN_callback;
+
+    // clear driver state
+    control_state = CTRL_NONE;
+
+    // set the descriptor location
+    MXC_USB->ep_base = (uint32_t)&ep_buffer_descriptor;
+
+    // enable VBUS interrupts
+    MXC_USB->dev_inten = MXC_F_USB_DEV_INTEN_NO_VBUS | MXC_F_USB_DEV_INTEN_VBUS;
+
+    // attach IRQ handler and enable interrupts
+    instance = this;
+    NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
+    NVIC_EnableIRQ(USB_IRQn);
+}
+
+USBHAL::~USBHAL(void)
+{
+    MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST;
+    MXC_USB->dev_cn = 0;
+    MXC_USB->cn = 0;
+}
+
+void USBHAL::connect(void)
+{
+    // enable interrupts
+    MXC_USB->dev_inten |= CONNECT_INTS;
+
+    // allow interrupts on ep0
+    MXC_USB->ep[0] |= MXC_F_USB_EP_INT_EN;
+
+    // pullup enable
+    MXC_USB->dev_cn |= (MXC_F_USB_DEV_CN_CONNECT | MXC_F_USB_DEV_CN_FIFO_MODE);
+}
+
+void USBHAL::disconnect(void)
+{
+    // disable interrupts
+    MXC_USB->dev_inten &= ~CONNECT_INTS;
+
+    // disable pullup
+    MXC_USB->dev_cn &= ~MXC_F_USB_DEV_CN_CONNECT;
+}
+
+void USBHAL::configureDevice(void)
+{
+    // do nothing
+}
+
+void USBHAL::unconfigureDevice(void)
+{
+    // reset endpoints
+    for (int i = 0; i < MXC_USB_NUM_EP; i++) {
+        // Disable endpoint and clear the data toggle
+        MXC_USB->ep[i] &= ~MXC_F_USB_EP_DIR;
+        MXC_USB->ep[i] |= MXC_F_USB_EP_DT;
+    }
+}
+
+void USBHAL::setAddress(uint8_t address)
+{
+    // do nothing
+}
+
+void USBHAL::remoteWakeup(void)
+{
+    // do nothing
+}
+
+static ep_buffer_t *get_desc(uint8_t endpoint)
+{
+    uint8_t epnum = EP_NUM(endpoint);
+    ep_buffer_t *desc;
+
+    if (epnum == 0) {
+        if (IN_EP(endpoint)) {
+            desc = &ep_buffer_descriptor.ep0.in_buffer;
+        } else {
+            desc = &ep_buffer_descriptor.ep0.out_buffer;
+        }
+    } else {
+        desc = &ep_buffer_descriptor.ep[epnum - 1];
+    }
+
+    return desc;
+}
+
+void USBHAL::EP0setup(uint8_t *buffer)
+{
+    // Setup packet is fixed at 8 bytes
+    // Setup registers cannot be read in byte mode
+    uint32_t *ptr32 = (uint32_t*)buffer;
+    ptr32[0] = (uint32_t)MXC_USB->setup0;
+    ptr32[1] = (uint32_t)MXC_USB->setup1;
+}
+
+void USBHAL::EP0read(void)
+{
+    if (control_state == CTRL_IN) {
+        // This is the status stage. ACK.
+        MXC_USB->ep[0] |= MXC_F_USB_EP_ST_ACK;
+        control_state = CTRL_NONE;
+        return;
+    }
+
+    control_state = CTRL_OUT;
+
+    endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
+}
+
+void USBHAL::EP0readStage(void)
+{
+    // do nothing
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
+{
+    uint32_t size;
+
+    if (MXC_USB->out_owner & 1) {
+        return 0;
+    }
+
+    // get the packet length and contents
+    ep_buffer_t *desc = get_desc(EP0OUT);
+    size = desc->buf0_desc;
+    memcpy(buffer, aligned_buffer[0], size);
+
+    return size;
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
+{
+    if ((size == 0) && (control_state != CTRL_IN)) {
+        // This is a status stage ACK. Handle in hardware.
+        MXC_USB->ep[0] |= MXC_F_USB_EP_ST_ACK;
+        control_state = CTRL_NONE;
+        return;
+    }
+
+    control_state = CTRL_IN;
+
+    endpointWrite(EP0IN, buffer, size);
+}
+
+void USBHAL::EP0stall(void)
+{
+    stallEndpoint(0);
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
+{
+    uint8_t epnum = EP_NUM(endpoint);
+
+    if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || IN_EP(endpoint)) {
+        return EP_INVALID;
+    }
+
+    if (maximumSize > MXC_USB_MAX_PACKET) {
+        return EP_INVALID;
+    }
+    
+    uint32_t mask = (1 << epnum);
+    if (MXC_USB->out_owner & mask) {
+        return EP_INVALID;
+    }
+
+    ep_buffer_t *desc = get_desc(endpoint);
+    desc->buf0_desc = maximumSize;
+    desc->buf0_address = (uint32_t)aligned_buffer[epnum];
+
+    MXC_USB->out_owner = mask;
+
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead)
+{
+    if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || IN_EP(endpoint)) {
+        return EP_INVALID;
+    }
+
+    uint32_t mask = (1 << EP_NUM(endpoint));
+    if (MXC_USB->out_owner & mask) {
+        return EP_PENDING;
+    }
+
+    // get the packet length and contents
+    ep_buffer_t *desc = get_desc(endpoint);
+    *bytesRead = desc->buf0_desc;
+    memcpy(data, aligned_buffer[EP_NUM(endpoint)], *bytesRead);
+
+    return EP_COMPLETED;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
+{
+    uint8_t epnum = EP_NUM(endpoint);
+
+    if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || OUT_EP(endpoint)) {
+        return EP_INVALID;
+    }
+
+    if (size > MXC_USB_MAX_PACKET) {
+        return EP_INVALID;
+    }
+
+    uint32_t mask = (1 << epnum);
+    if (MXC_USB->in_owner & mask) {
+        return EP_INVALID;
+    }
+
+    memcpy(aligned_buffer[epnum], data, size);
+
+    ep_buffer_t *desc = get_desc(endpoint);
+    desc->buf0_desc = size;
+    desc->buf0_address = (uint32_t)aligned_buffer[epnum];
+
+    // start the DMA
+    MXC_USB->in_owner = mask;
+
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
+{
+    uint32_t mask = (1 << EP_NUM(endpoint));
+    if (MXC_USB->in_owner & mask) {
+        return EP_PENDING;
+    }
+
+    return EP_COMPLETED;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint)
+{
+    uint8_t epnum = EP_NUM(endpoint);
+
+    if (epnum == 0) {
+        MXC_USB->ep[epnum] |= MXC_F_USB_EP_ST_STALL;
+    }
+
+    MXC_USB->ep[epnum] |= MXC_F_USB_EP_STALL;
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint)
+{
+    MXC_USB->ep[EP_NUM(endpoint)] &= ~MXC_F_USB_EP_STALL;
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
+{
+    uint8_t epnum = EP_NUM(endpoint);
+    uint32_t ep_ctrl;
+
+    if (epnum >= NUMBER_OF_PHYSICAL_ENDPOINTS) {
+        return false;
+    }
+
+    if (IN_EP(endpoint)) {
+        ep_ctrl = (MXC_V_USB_EP_DIR_IN << MXC_F_USB_EP_DIR_POS);
+    } else {
+        ep_ctrl = (MXC_S_USB_EP_DIR_OUT << MXC_F_USB_EP_DIR_POS);
+    }
+
+    ep_ctrl |= (MXC_F_USB_EP_DT | MXC_F_USB_EP_INT_EN);
+
+    MXC_USB->ep[epnum] = ep_ctrl;
+
+    return true;
+}
+
+bool USBHAL::getEndpointStallState(unsigned char endpoint)
+{
+    return !!(MXC_USB->ep[endpoint] & MXC_F_USB_EP_STALL);
+}
+
+void USBHAL::_usbisr(void)
+{
+    instance->usbisr();
+}
+
+void USBHAL::usbisr(void)
+{
+    // get and clear irqs
+    uint32_t irq_flags = MXC_USB->dev_intfl;
+    MXC_USB->dev_intfl = irq_flags;
+
+    // process only enabled interrupts
+    irq_flags &= MXC_USB->dev_inten;
+
+    // suspend 
+    if (irq_flags & MXC_F_USB_DEV_INTFL_SUSP) {
+        suspendStateChanged(1);
+    }
+
+    // bus reset
+    if (irq_flags & MXC_F_USB_DEV_INTFL_BRST) {
+
+        // reset endpoints
+        for (int i = 0; i < MXC_USB_NUM_EP; i++) {
+            // Disable endpoint and clear the data toggle
+            MXC_USB->ep[i] &= ~MXC_F_USB_EP_DIR;
+            MXC_USB->ep[i] |= MXC_F_USB_EP_DT;
+        }
+
+        // clear driver state
+        control_state = CTRL_NONE;
+
+        busReset();
+
+        // no need to process events after reset
+        return;
+    }
+
+    // Setup packet
+    if (irq_flags & MXC_F_USB_DEV_INTFL_SETUP) {
+        control_state = CTRL_SETUP;
+        EP0setupCallback();
+    }
+
+    // IN packets
+    if (irq_flags & MXC_F_USB_DEV_INTFL_EP_IN) {
+        // get and clear IN irqs
+        uint32_t in_irqs = MXC_USB->in_int;
+        MXC_USB->in_int = in_irqs;
+
+        if (in_irqs & 1) {
+            EP0in();
+        }
+
+        for (uint8_t epnum = 1; epnum < NUMBER_OF_LOGICAL_ENDPOINTS; epnum++) {
+            uint32_t irq_mask = (1 << epnum);
+            if (in_irqs & irq_mask) {
+                uint8_t endpoint = (epnum << 1) | DIR_IN;
+                (instance->*(epCallback[endpoint]))();
+            }
+        }
+    }
+
+    // OUT packets
+    if (irq_flags & MXC_F_USB_DEV_INTFL_EP_OUT) {
+        // get and clear OUT irqs
+        uint32_t out_irqs = MXC_USB->out_int;
+        MXC_USB->out_int = out_irqs;
+
+        if (out_irqs & 1) {
+            EP0out();
+        }
+
+        for (uint8_t epnum = 1; epnum < NUMBER_OF_LOGICAL_ENDPOINTS; epnum++) {
+            uint32_t irq_mask = (1 << epnum);
+            if (out_irqs & irq_mask) {
+                uint8_t endpoint = (epnum << 1) | DIR_OUT;
+                (instance->*(epCallback[endpoint]))();
+            }
+        }
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_RZ_A1H.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,1497 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or
+* sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following
+* conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(TARGET_RZ_A1H) || defined(TARGET_VK_RZ_A1H)
+
+/*
+  This class can use the pipe1, pipe3 and pipe6 only. You should
+  re-program this class if you wanted to use other pipe.
+ */
+
+/*************************************************************************/
+extern "C"
+{
+#include "r_typedefs.h"
+#include "iodefine.h"
+}
+#include "USBHAL.h"
+#include "devdrv_usb_function_api.h"
+#include "usb_iobitmask.h"
+#include "rza_io_regrw.h"
+#include "USBDevice_Types.h"
+#include "usb_function_setting.h"
+
+
+/*************************************************************************/
+/* constants */
+const struct PIPECFGREC {
+    uint16_t    endpoint;
+    uint16_t    pipesel;
+    uint16_t    pipecfg;
+    uint16_t    pipebuf;
+    uint16_t    pipemaxp;
+    uint16_t    pipeperi;
+} def_pipecfg[] = {
+    /*EP0OUT and EP0IN are configured by USB IP*/
+    {
+        EP1OUT, /*EP1: Host -> Func, INT*/
+        6 | USB_FUNCTION_D0FIFO_USE,
+        USB_FUNCTION_INTERRUPT |
+        USB_FUNCTION_BFREOFF   |
+        USB_FUNCTION_DBLBOFF   |
+        USB_FUNCTION_CNTMDON   |
+        USB_FUNCTION_SHTNAKOFF |
+        USB_FUNCTION_DIR_P_OUT |
+        USB_FUNCTION_EP1,
+        ( ( (  64) / 64 - 1 ) << 10 ) | 0x04u,
+        MAX_PACKET_SIZE_EP1,
+        DEVDRV_USBF_OFF |
+        ( 3 << USB_PIPEPERI_IITV_SHIFT ),
+    },
+    {
+        EP1IN,  /*EP1: Host <- Func, INT*/
+        7 | USB_FUNCTION_D1FIFO_USE,
+        USB_FUNCTION_INTERRUPT |
+        USB_FUNCTION_BFREOFF   |
+        USB_FUNCTION_DBLBOFF   |
+        USB_FUNCTION_CNTMDOFF  |
+        USB_FUNCTION_SHTNAKOFF |
+        USB_FUNCTION_DIR_P_IN  |
+        USB_FUNCTION_EP1,
+        ( ( (  64) / 64 - 1 ) << 10 ) | 0x05u,
+        MAX_PACKET_SIZE_EP1,
+        DEVDRV_USBF_OFF |
+        ( 3 << USB_PIPEPERI_IITV_SHIFT ),
+    },
+    {
+        EP2OUT, /*EP2: Host -> Func, BULK*/
+        3 | USB_FUNCTION_D0FIFO_USE,
+        USB_FUNCTION_BULK      |
+        USB_FUNCTION_BFREOFF   |
+        USB_FUNCTION_DBLBON    |
+        USB_FUNCTION_CNTMDON   |
+        USB_FUNCTION_SHTNAKON  |
+        USB_FUNCTION_DIR_P_OUT |
+        USB_FUNCTION_EP2,
+        ( ( (2048) / 64 - 1 ) << 10 ) | 0x30u,
+        MAX_PACKET_SIZE_EP2,
+        DEVDRV_USBF_OFF |
+        ( 0 << USB_PIPEPERI_IITV_SHIFT ),
+    },
+    {
+        EP2IN,  /*EP2: Host <- Func, BULK*/
+        4 | USB_FUNCTION_D1FIFO_USE,
+        USB_FUNCTION_BULK      |
+        USB_FUNCTION_BFREOFF   |
+        USB_FUNCTION_DBLBOFF   |
+        USB_FUNCTION_CNTMDON   |
+        USB_FUNCTION_SHTNAKOFF |
+        USB_FUNCTION_DIR_P_IN  |
+        USB_FUNCTION_EP2,
+        ( ( (2048) / 64 - 1 ) << 10 ) | 0x50u,
+        MAX_PACKET_SIZE_EP2,
+        DEVDRV_USBF_OFF |
+        ( 0 << USB_PIPEPERI_IITV_SHIFT ),
+    },
+    {
+        EP3OUT, /*EP3: Host -> Func, ISO*/
+        1 | USB_FUNCTION_D0FIFO_USE,
+        USB_FUNCTION_ISO       |
+        USB_FUNCTION_BFREOFF   |
+        USB_FUNCTION_DBLBON    |
+        USB_FUNCTION_CNTMDOFF  |
+        USB_FUNCTION_SHTNAKON  |
+        USB_FUNCTION_DIR_P_OUT |
+        USB_FUNCTION_EP3,
+        ( ( ( 512) / 64 - 1 ) << 10 ) | 0x10u,
+        MAX_PACKET_SIZE_EP3,
+        DEVDRV_USBF_OFF |
+        ( 0 << USB_PIPEPERI_IITV_SHIFT ),
+    },
+    {
+        EP3IN,  /*EP3: Host <- Func, ISO*/
+        2 | USB_FUNCTION_D1FIFO_USE,
+        USB_FUNCTION_ISO       |
+        USB_FUNCTION_BFREOFF   |
+        USB_FUNCTION_DBLBON    |
+        USB_FUNCTION_CNTMDOFF  |
+        USB_FUNCTION_SHTNAKOFF |
+        USB_FUNCTION_DIR_P_IN  |
+        USB_FUNCTION_EP3,
+        ( ( ( 512) / 64 - 1 ) << 10 ) | 0x20u,
+        MAX_PACKET_SIZE_EP3,
+        DEVDRV_USBF_OFF |
+        ( 0 << USB_PIPEPERI_IITV_SHIFT ),
+    },
+    { /*terminator*/
+        0, 0, 0, 0, 0,
+    },
+};
+
+
+/*************************************************************************/
+/* workareas */
+USBHAL * USBHAL::instance;
+
+static IRQn_Type    int_id;         /* interrupt ID          */
+static uint16_t     int_level;      /* initerrupt level      */
+static uint16_t     clock_mode;     /* input clock selector  */
+static uint16_t     mode;           /* USB speed (HIGH/FULL) */
+
+//static DigitalOut *usbx_en;
+
+static uint16_t     EP0_read_status;
+static uint16_t     EPx_read_status;
+
+static uint16_t setup_buffer[MAX_PACKET_SIZE_EP0 / 2];
+
+/* 0: not used / other: a pipe number to use recv_buffer*/
+static uint8_t  recv_buffer[MAX_PACKET_SIZE_EPBULK];
+volatile static uint16_t    recv_error;
+
+
+/*************************************************************************/
+/* prototypes for C */
+extern "C" {
+    void usbx_function_BRDYInterruptPIPE0 (uint16_t status, uint16_t intenb,
+        USBHAL *object, void (USBHAL::*EP0func)(void));
+
+    void usbx_function_BRDYInterrupt (uint16_t status, uint16_t intenb,
+        USBHAL *object, bool (USBHAL::*epCallback[])(void));
+
+    void usbx_function_NRDYInterruptPIPE0(uint16_t status, uint16_t intenb,
+        USBHAL *object, void (USBHAL::*EP0func)(void));
+
+    void usbx_function_NRDYInterrupt (uint16_t status, uint16_t intenb,
+        USBHAL *object, bool (USBHAL::*epCallback[])(void));
+
+    void usbx_function_BEMPInterruptPIPE0(uint16_t status, uint16_t intenb,
+        USBHAL *object, void (USBHAL::*EP0func)(void));
+
+    void usbx_function_BEMPInterrupt (uint16_t status, uint16_t intenb,
+        USBHAL *object, bool (USBHAL::*epCallback[])(void));
+}
+
+
+/*************************************************************************/
+/* macros */
+
+/******************************************************************************
+ * Function Name: usbx_function_BRDYInterruptPIPE0
+ * Description  : Executes BRDY interrupt for pipe0.
+ * Arguments    : uint16_t status       ; BRDYSTS Register Value
+ *              : uint16_t intenb       ; BRDYENB Register Value
+ * Return Value : none
+ *****************************************************************************/
+extern "C" {
+    void usbx_function_BRDYInterruptPIPE0 (
+        uint16_t status,
+        uint16_t intenb,
+        USBHAL *object,
+        void (USBHAL::*EP0func)(void)
+    )
+    {
+        volatile uint16_t dumy_sts;
+        uint16_t read_status;
+
+        USB20X.BRDYSTS =
+            (uint16_t)~g_usbx_function_bit_set[USB_FUNCTION_PIPE0];
+        RZA_IO_RegWrite_16(
+            &USB20X.CFIFOSEL, USB_FUNCTION_PIPE0,
+            USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE);
+
+        g_usbx_function_PipeDataSize[USB_FUNCTION_PIPE0] =
+            g_usbx_function_data_count[USB_FUNCTION_PIPE0];
+
+        read_status = usbx_function_read_buffer_c(USB_FUNCTION_PIPE0);
+
+        g_usbx_function_PipeDataSize[USB_FUNCTION_PIPE0] -=
+            g_usbx_function_data_count[USB_FUNCTION_PIPE0];
+
+        switch (read_status) {
+            case USB_FUNCTION_READING:      /* Continue of data read */
+            case USB_FUNCTION_READEND:      /* End of data read */
+                /* PID = BUF */
+                usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);
+
+                /*callback*/
+                (object->*EP0func)();
+                break;
+
+            case USB_FUNCTION_READSHRT:     /* End of data read */
+                usbx_function_disable_brdy_int(USB_FUNCTION_PIPE0);
+                /* PID = BUF */
+                usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);
+
+                /*callback*/
+                (object->*EP0func)();
+                break;
+
+            case USB_FUNCTION_READOVER:     /* FIFO access error */
+                /* Buffer Clear */
+                USB20X.CFIFOCTR = USB_FUNCTION_BITBCLR;
+                usbx_function_disable_brdy_int(USB_FUNCTION_PIPE0);
+                /* Req Error */
+                usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);
+
+                /*callback*/
+                (object->*EP0func)();
+                break;
+
+            case DEVDRV_USBF_FIFOERROR:     /* FIFO access error */
+            default:
+                usbx_function_disable_brdy_int(USB_FUNCTION_PIPE0);
+                /* Req Error */
+                usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);
+                break;
+        }
+        /* Three dummy reads for clearing interrupt requests */
+        dumy_sts = USB20X.BRDYSTS;
+    }
+}
+
+
+/******************************************************************************
+ * Function Name: usbx_function_BRDYInterrupt
+ * Description  : Executes BRDY interrupt uxclude pipe0.
+ * Arguments    : uint16_t status       ; BRDYSTS Register Value
+ *              : uint16_t intenb       ; BRDYENB Register Value
+ * Return Value : none
+ *****************************************************************************/
+extern "C" {
+    void usbx_function_BRDYInterrupt(
+        uint16_t status,
+        uint16_t intenb,
+        USBHAL *object,
+        bool (USBHAL::*epCallback[])(void)
+    )
+    {
+        volatile uint16_t dumy_sts;
+
+        /**************************************************************
+         * Function Name: usbx_function_brdy_int
+         * Description  : Executes BRDY interrupt(USB_FUNCTION_PIPE1-9).
+         *              : According to the pipe that interrupt is generated in,
+         *              : reads/writes buffer allocated in the pipe.
+         *              : This function is executed in the BRDY
+         *              : interrupt handler.  This function
+         *              : clears BRDY interrupt status and BEMP
+         *              : interrupt status.
+         * Arguments    : uint16_t Status    ; BRDYSTS Register Value
+         *              : uint16_t Int_enbl  ; BRDYENB Register Value
+         * Return Value : none
+         *************************************************************/
+        /* copied from usbx_function_intrn.c */
+        uint32_t int_sense = 0;
+        uint16_t pipe;
+        uint16_t pipebit;
+        uint16_t ep;
+
+        for (pipe = USB_FUNCTION_PIPE1; pipe <= USB_FUNCTION_MAX_PIPE_NO; pipe++) {
+            pipebit = g_usbx_function_bit_set[pipe];
+
+            if ((status & pipebit) && (intenb & pipebit)) {
+                USB20X.BRDYSTS = (uint16_t)~pipebit;
+                USB20X.BEMPSTS = (uint16_t)~pipebit;
+
+                switch (g_usbx_function_PipeTbl[pipe] & USB_FUNCTION_FIFO_USE) {
+                    case USB_FUNCTION_D0FIFO_DMA:
+                        if (g_usbx_function_DmaStatus[USB_FUNCTION_D0FIFO] != USB_FUNCTION_DMA_READY) {
+                            /*now, DMA is not supported*/
+                            usbx_function_dma_interrupt_d0fifo(int_sense);
+                        }
+
+                        if (RZA_IO_RegRead_16(
+                                &g_usbx_function_pipecfg[pipe], USB_PIPECFG_BFRE_SHIFT, USB_PIPECFG_BFRE) == 0) {
+                            /*now, DMA is not supported*/
+                            usbx_function_read_dma(pipe);
+                            usbx_function_disable_brdy_int(pipe);
+                        } else {
+                            USB20X.D0FIFOCTR = USB_FUNCTION_BITBCLR;
+                            g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE;
+                        }
+                        break;
+
+                    case USB_FUNCTION_D1FIFO_DMA:
+                        if (g_usbx_function_DmaStatus[USB_FUNCTION_D1FIFO] != USB_FUNCTION_DMA_READY) {
+                            /*now, DMA is not supported*/
+                            usbx_function_dma_interrupt_d1fifo(int_sense);
+                        }
+
+                        if (RZA_IO_RegRead_16(
+                                &g_usbx_function_pipecfg[pipe], USB_PIPECFG_BFRE_SHIFT, USB_PIPECFG_BFRE) == 0) {
+                            /*now, DMA is not supported*/
+                            usbx_function_read_dma(pipe);
+                            usbx_function_disable_brdy_int(pipe);
+                        } else {
+                            USB20X.D1FIFOCTR = USB_FUNCTION_BITBCLR;
+                            g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE;
+                        }
+                        break;
+
+                    default:
+                        ep = (g_usbx_function_pipecfg[pipe] & USB_PIPECFG_EPNUM) >> USB_PIPECFG_EPNUM_SHIFT;
+                        ep <<= 1;
+                        if (RZA_IO_RegRead_16(
+                                &g_usbx_function_pipecfg[pipe], USB_PIPECFG_DIR_SHIFT, USB_PIPECFG_DIR) == 0) {
+                            /* read */
+                            EPx_read_status = DEVDRV_USBF_PIPE_WAIT;
+                            (object->*(epCallback[ep - 2])) ();
+                            EPx_read_status = DEVDRV_USBF_PIPE_DONE;
+                        } else {
+                            /* write */
+                            EPx_read_status = DEVDRV_USBF_PIPE_WAIT;
+                            (object->*(epCallback[ep - 2 + 1])) ();
+                            EPx_read_status = DEVDRV_USBF_PIPE_DONE;
+                            usbx_function_write_buffer(pipe);
+                        }
+                }
+            }
+        }
+        /* Three dummy reads for clearing interrupt requests */
+        dumy_sts = USB20X.BRDYSTS;
+    }
+}
+
+
+/******************************************************************************
+ * Function Name: usbx_function_NRDYInterruptPIPE0
+ * Description  : Executes NRDY interrupt for pipe0.
+ * Arguments    : uint16_t status       ; NRDYSTS Register Value
+ *              : uint16_t intenb       ; NRDYENB Register Value
+ * Return Value : none
+ *****************************************************************************/
+extern "C" {
+    void usbx_function_NRDYInterruptPIPE0(
+        uint16_t status,
+        uint16_t intenb,
+        USBHAL *object,
+        void (USBHAL::*EP0func)(void)
+    )
+    {
+        volatile uint16_t dumy_sts;
+
+        USB20X.NRDYSTS =
+            (uint16_t)~g_usbx_function_bit_set[USB_FUNCTION_PIPE0];
+
+        /* Three dummy reads for clearing interrupt requests */
+        dumy_sts = USB20X.NRDYSTS;
+    }
+}
+
+
+/******************************************************************************
+ * Function Name: usbx_function_NRDYInterrupt
+ * Description  : Executes NRDY interrupt exclude pipe0.
+ * Arguments    : uint16_t status       ; NRDYSTS Register Value
+ *              : uint16_t intenb       ; NRDYENB Register Value
+ * Return Value : none
+ *****************************************************************************/
+extern "C" {
+    void usbx_function_NRDYInterrupt(
+        uint16_t status,
+        uint16_t intenb,
+        USBHAL *object,
+        bool (USBHAL::*epCallback[])(void)
+    )
+    {
+        volatile uint16_t dumy_sts;
+
+        /**************************************************************
+         * Function Name: usbx_function_nrdy_int
+         * Description  : Executes NRDY interrupt(USB_FUNCTION_PIPE1-9).
+         *              : Checks NRDY interrupt cause by PID. When the cause if STALL,
+         *              : regards the pipe state as STALL and ends the processing.
+         *              : Then the cause is not STALL, increments the error count to
+         *              : communicate again. When the error count is 3, determines
+         *              : the pipe state as DEVDRV_USBF_PIPE_NORES and ends the processing.
+         *              : This function is executed in the NRDY interrupt handler.
+         *              : This function clears NRDY interrupt status.
+         * Arguments    : uint16_t status       ; NRDYSTS Register Value
+         *              : uint16_t int_enb      ; NRDYENB Register Value
+         * Return Value : none
+         *************************************************************/
+        /* copied from usbx_function_intrn.c */
+#if 0
+        uint16_t usefifo;
+#endif
+        uint16_t pid;
+        uint16_t pipe;
+        uint16_t bitcheck;
+#if 0
+        uint16_t mbw;
+        uint32_t size;
+#endif
+        uint16_t ep;
+
+        bitcheck = (uint16_t)(status & intenb);
+
+        USB20X.NRDYSTS = (uint16_t)~status;
+
+
+        if (RZA_IO_RegRead_16(&USB20X.SYSCFG0, USB_SYSCFG_DCFM_SHIFT, USB_SYSCFG_DCFM) == 1) {
+            /* USB HOST */
+            /* not support */
+
+        } else {
+            /* USB Function */
+            for (pipe = USB_FUNCTION_PIPE1; pipe <= USB_FUNCTION_MAX_PIPE_NO; pipe++) {
+                if ((bitcheck&g_usbx_function_bit_set[pipe]) != g_usbx_function_bit_set[pipe]) {
+                    continue;
+                }
+
+                if (g_usbx_function_pipe_status[pipe] != DEVDRV_USBF_PIPE_WAIT) {
+                    continue;
+                }
+
+#if 0
+                usbx_function_set_pid_nak(pipe);
+
+                size = (uint32_t)g_usbx_function_data_count[pipe];
+                mbw = usbx_function_get_mbw(
+                    size, (uint32_t)g_usbx_function_data_pointer[pipe]);
+
+                usefifo = (uint16_t)(g_usbx_function_PipeTbl[pipe] & USB_FUNCTION_FIFO_USE);
+                switch (usefifo) {
+
+                    case USB_FUNCTION_D0FIFO_USE:
+                        usbx_function_set_curpipe(
+                            pipe, USB_FUNCTION_D0USE, DEVDRV_USBF_NO, mbw);
+                        USB20X.D0FIFOCTR = USB_FUNCTION_BITBCLR;
+                        break;
+
+                    case USB_FUNCTION_D1FIFO_USE:
+                        usbx_function_set_curpipe(
+                            pipe, USB_FUNCTION_D1USE, DEVDRV_USBF_NO, mbw);
+                        USB20X.D1FIFOCTR = USB_FUNCTION_BITBCLR;
+                        break;
+
+                    default:
+                        usbx_function_set_curpipe(
+                            pipe, USB_FUNCTION_CUSE, USB_FUNCTION_CFIFO_READ, mbw);
+                        USB20X.CFIFOCTR = USB_FUNCTION_BITBCLR;
+                        break;
+                }
+
+                usbx_function_aclrm(pipe);
+
+                usbx_function_enable_nrdy_int(pipe);
+                usbx_function_enable_brdy_int(pipe);
+
+                usbx_function_set_pid_buf(pipe);
+#endif
+
+                pid = usbx_function_get_pid(pipe);
+                if ((pid == DEVDRV_USBF_PID_STALL) || (pid == DEVDRV_USBF_PID_STALL2)) {
+                    g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_STALL;
+                } else {
+                    usbx_function_set_pid_buf(pipe);
+                }
+
+                ep = (g_usbx_function_pipecfg[pipe] & USB_PIPECFG_EPNUM) >> USB_PIPECFG_EPNUM_SHIFT;
+                ep <<= 1;
+                if (RZA_IO_RegRead_16(
+                        &g_usbx_function_pipecfg[pipe], USB_PIPECFG_DIR_SHIFT, USB_PIPECFG_DIR) == 0) {
+                    /* read */
+                    __NOP();
+                } else {
+                    /* write */
+                    __NOP();
+                }
+            }
+        }
+
+        /* Three dummy reads for clearing interrupt requests */
+        dumy_sts = USB20X.NRDYSTS;
+    }
+}
+
+/******************************************************************************
+ * Function Name: usbx_function_BEMPInterruptPIPE0
+ * Description  : Executes BEMP interrupt for pipe0.
+ * Arguments    : uint16_t status       ; BEMPSTS Register Value
+ *              : uint16_t intenb       ; BEMPENB Register Value
+ * Return Value : none
+ *****************************************************************************/
+extern "C" {
+    void usbx_function_BEMPInterruptPIPE0(
+        uint16_t status,
+        uint16_t intenb,
+        USBHAL *object,
+        void (USBHAL::*EP0func)(void)
+    )
+    {
+        volatile uint16_t dumy_sts;
+
+        USB20X.BEMPSTS =
+            (uint16_t)~g_usbx_function_bit_set[USB_FUNCTION_PIPE0];
+        RZA_IO_RegWrite_16(
+            &USB20X.CFIFOSEL, USB_FUNCTION_PIPE0,
+            USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE);
+
+        /*usbx_function_write_buffer_c(USB_FUNCTION_PIPE0);*/
+        (object->*EP0func)();
+
+        /* Three dummy reads for clearing interrupt requests */
+        dumy_sts = USB20X.BEMPSTS;
+    }
+}
+
+
+/******************************************************************************
+ * Function Name: usbx_function_BEMPInterrupt
+ * Description  : Executes BEMP interrupt exclude pipe0.
+ * Arguments    : uint16_t status       ; BEMPSTS Register Value
+ *              : uint16_t intenb       ; BEMPENB Register Value
+ * Return Value : none
+ *****************************************************************************/
+extern "C" {
+    void usbx_function_BEMPInterrupt(
+        uint16_t status,
+        uint16_t intenb,
+        USBHAL *object,
+        bool (USBHAL::*epCallback[])(void)
+    )
+    {
+        volatile uint16_t dumy_sts;
+
+        /**************************************************************
+         * Function Name: usbx_function_bemp_int
+         * Description  : Executes BEMP interrupt(USB_FUNCTION_PIPE1-9).
+         * Arguments    : uint16_t status       ; BEMPSTS Register Value
+         *              : uint16_t intenb      ; BEMPENB Register Value
+         * Return Value : none
+         *************************************************************/
+        /* copied from usbx_function_intrn.c */
+        uint16_t pid;
+        uint16_t pipe;
+        uint16_t bitcheck;
+        uint16_t inbuf;
+        uint16_t ep;
+
+        bitcheck = (uint16_t)(status & intenb);
+
+        USB20X.BEMPSTS = (uint16_t)~status;
+
+        for (pipe = USB_FUNCTION_PIPE1; pipe <= USB_FUNCTION_MAX_PIPE_NO; pipe++) {
+            if ((bitcheck&g_usbx_function_bit_set[pipe]) != g_usbx_function_bit_set[pipe]) {
+                continue;
+            }
+
+            pid = usbx_function_get_pid(pipe);
+
+            if ((pid == DEVDRV_USBF_PID_STALL) ||
+                (pid == DEVDRV_USBF_PID_STALL2)) {
+                g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_STALL;
+
+            } else {
+                inbuf = usbx_function_get_inbuf(pipe);
+
+                if (inbuf == 0) {
+                    usbx_function_disable_bemp_int(pipe);
+                    usbx_function_set_pid_nak(pipe);
+                    g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE;
+
+                    switch (g_usbx_function_PipeTbl[pipe] & USB_FUNCTION_FIFO_USE) {
+                        case USB_FUNCTION_D0FIFO_DMA:
+                            /*now, DMA is not supported*/
+                            break;
+
+                        case USB_FUNCTION_D1FIFO_DMA:
+                            /*now, DMA is not supported*/
+                            break;
+
+                        default:
+                            ep = (g_usbx_function_pipecfg[pipe] & USB_PIPECFG_EPNUM) >> USB_PIPECFG_EPNUM_SHIFT;
+                            ep <<= 1;
+                            if (RZA_IO_RegRead_16(
+                                    &g_usbx_function_pipecfg[pipe], USB_PIPECFG_DIR_SHIFT, USB_PIPECFG_DIR) == 0) {
+                                /* read */
+                                __NOP();
+                            } else {
+                                /* write */
+                                EPx_read_status = DEVDRV_USBF_PIPE_WAIT;
+                                (object->*(epCallback[ep - 2 + 1])) ();
+                                EPx_read_status = DEVDRV_USBF_PIPE_DONE;
+                            }
+                    }
+                }
+            }
+        }
+
+        /* Three dummy reads for clearing interrupt requests */
+        dumy_sts = USB20X.BEMPSTS;
+    }
+}
+
+/******************************************************************************
+ * Function Name: EP2PIPE
+ * Description  : Converts from endpoint to pipe
+ * Arguments    : number of endpoint
+ * Return Value : number of pipe
+ *****************************************************************************/
+/*EP2PIPE converter is for pipe1, pipe3 and pipe6 only.*/
+#define EP2PIPE(endpoint)   ((uint32_t)usbx_function_EpToPipe(endpoint))
+
+
+/******************************************************************************
+ * Function Name: usbx_function_save_request
+ * Description  : Retains the USB request information in variables.
+ * Arguments    : none
+ * Return Value : none
+ *****************************************************************************/
+#define  usbx_function_save_request()                       \
+    {                                                       \
+        uint16_t *bufO = &setup_buffer[0];                  \
+                                                            \
+        USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITVALID;  \
+        /*data[0] <= bmRequest, data[1] <= bmRequestType */ \
+        *bufO++ = USB20X.USBREQ;                            \
+        /*data[2] data[3] <= wValue*/                       \
+        *bufO++ = USB20X.USBVAL;                            \
+        /*data[4] data[5] <= wIndex*/                       \
+        *bufO++ = USB20X.USBINDX;                           \
+        /*data[6] data[6] <= wIndex*/                       \
+        *bufO++ = USB20X.USBLENG;                           \
+    }
+
+
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+
+/*************************************************************************/
+/* constructor */
+USBHAL::USBHAL(void)
+{
+    /* ---- P4_1 : P4_1 (USB0_EN for GR-PEACH) ---- */
+    //usbx_en = new DigitalOut(P4_1, 1);
+
+    /* some constants */
+    int_id          = USBIX_IRQn;
+    int_level       = ( 2 << 3 );
+    clock_mode      = USBFCLOCK_X1_48MHZ;
+#if (USB_FUNCTION_HISPEED == 0)
+    mode            = USB_FUNCTION_FULL_SPEED;
+#else
+    mode            = USB_FUNCTION_HIGH_SPEED;
+#endif
+    EP0_read_status = DEVDRV_USBF_WRITEEND;
+    EPx_read_status = DEVDRV_USBF_PIPE_DONE;
+
+    /* Disables interrupt for usb */
+    GIC_DisableIRQ(int_id);
+
+    /* Setup the end point */
+    epCallback[ 0] = &USBHAL::EP1_OUT_callback;
+    epCallback[ 1] = &USBHAL::EP1_IN_callback;
+    epCallback[ 2] = &USBHAL::EP2_OUT_callback;
+    epCallback[ 3] = &USBHAL::EP2_IN_callback;
+    epCallback[ 4] = &USBHAL::EP3_OUT_callback;
+    epCallback[ 5] = &USBHAL::EP3_IN_callback;
+    epCallback[ 6] = &USBHAL::EP4_OUT_callback;
+    epCallback[ 7] = &USBHAL::EP4_IN_callback;
+    epCallback[ 8] = &USBHAL::EP5_OUT_callback;
+    epCallback[ 9] = &USBHAL::EP5_IN_callback;
+    epCallback[10] = &USBHAL::EP6_OUT_callback;
+    epCallback[11] = &USBHAL::EP6_IN_callback;
+    epCallback[12] = &USBHAL::EP7_OUT_callback;
+    epCallback[13] = &USBHAL::EP7_IN_callback;
+    epCallback[14] = &USBHAL::EP8_OUT_callback;
+    epCallback[15] = &USBHAL::EP8_IN_callback;
+    epCallback[16] = &USBHAL::EP9_OUT_callback;
+    epCallback[17] = &USBHAL::EP9_IN_callback;
+    epCallback[18] = &USBHAL::EP10_OUT_callback;
+    epCallback[19] = &USBHAL::EP10_IN_callback;
+    epCallback[20] = &USBHAL::EP11_OUT_callback;
+    epCallback[21] = &USBHAL::EP11_IN_callback;
+    epCallback[22] = &USBHAL::EP12_OUT_callback;
+    epCallback[23] = &USBHAL::EP12_IN_callback;
+    epCallback[24] = &USBHAL::EP13_OUT_callback;
+    epCallback[25] = &USBHAL::EP13_IN_callback;
+    epCallback[26] = &USBHAL::EP14_OUT_callback;
+    epCallback[27] = &USBHAL::EP14_IN_callback;
+    epCallback[28] = &USBHAL::EP15_OUT_callback;
+    epCallback[29] = &USBHAL::EP15_IN_callback;
+
+    /* registers me */
+    instance = this;
+
+    /* Clear pipe table */
+    usbx_function_clear_pipe_tbl();
+
+/******************************************************************************
+ * Function Name: usbx_api_function_init
+ * Description  : Initializes the USB module in the USB function mode.
+ *****************************************************************************/
+    /* The clock of USB0 modules is permitted */
+#if (USB_FUNCTION_CH == 0)
+    CPG.STBCR7 &= ~(CPG_STBCR7_MSTP71);
+#else
+    CPG.STBCR7 &= ~(CPG_STBCR7_MSTP71 | CPG_STBCR7_MSTP70);
+#endif
+    volatile uint8_t    dummy8;
+    dummy8 = CPG.STBCR7;
+
+    {
+/******************************************************************************
+ * Function Name: usbx_function_setting_interrupt
+ * Description  : Sets the USB module interrupt level.
+ *****************************************************************************/
+#if 0   /*DMA is not supported*/
+        IRQn_Type d0fifo_dmaintid;
+        IRQn_Type d1fifo_dmaintid;
+#endif
+
+        InterruptHandlerRegister(int_id, &_usbisr);
+        GIC_SetPriority(int_id, int_level);
+        GIC_EnableIRQ(int_id);
+
+#if 0   /*DMA is not supported*/
+        d0fifo_dmaintid = Userdef_USB_usbx_function_d0fifo_dmaintid();
+        if (d0fifo_dmaintid != 0xFFFF) {
+            InterruptHandlerRegister(d0fifo_dmaintid, usbx_function_dma_interrupt_d0fifo);
+            GIC_SetPriority(d0fifo_dmaintid, int_level);
+            GIC_EnableIRQ(d0fifo_dmaintid);
+        }
+#endif
+
+#if 0   /*DMA is not supported*/
+        d1fifo_dmaintid = Userdef_USB_usbx_function_d1fifo_dmaintid();
+        if (d1fifo_dmaintid != 0xFFFF) {
+            InterruptHandlerRegister(d1fifo_dmaintid, usbx_function_dma_interrupt_d1fifo);
+            GIC_SetPriority(d1fifo_dmaintid, int_level);
+            GIC_EnableIRQ(d1fifo_dmaintid);
+        }
+#endif
+/*****************************************************************************/
+    }
+
+    /* reset USB module with setting tranciever and HSE=1 */
+    usbx_function_reset_module(clock_mode);
+
+    /* clear variables */
+    usbx_function_init_status();
+
+    /* select USB Function and Interrupt Enable */
+    /* Detect USB Device to attach or detach    */
+    usbx_function_InitModule(mode);
+
+    {
+        uint16_t buf;
+        buf  = USB20X.INTENB0;
+        buf |= USB_INTENB0_SOFE;
+        USB20X.INTENB0 = buf;
+    }
+}
+
+/*************************************************************************/
+USBHAL::~USBHAL(void)
+{
+    /* Disables interrupt for usb */
+    GIC_DisableIRQ( int_id );
+    /* Unregisters interrupt function and priority */
+    InterruptHandlerRegister( int_id, (uint32_t)NULL );
+
+    //usbx_en  = NULL;
+    instance = NULL;
+}
+
+/*************************************************************************/
+void USBHAL::connect(void)
+{
+    /* Activates USB0_EN */
+    //(*usbx_en) = 0;
+}
+
+
+/*************************************************************************/
+void USBHAL::disconnect(void)
+{
+    /* Deactivates USB0_EN */
+    //(*usbx_en) = 1;
+}
+
+
+/*************************************************************************/
+void USBHAL::configureDevice(void)
+{
+    /*The pipes set up in USBHAL::realiseEndpoint*/
+    /*usbx_function_clear_alt();*/      /* Alternate setting clear */
+    /*usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);*/
+}
+
+
+/*************************************************************************/
+void USBHAL::unconfigureDevice(void)
+{
+    /* The Interface would be managed by USBDevice */
+    /*usbx_function_clear_alt();*/      /* Alternate setting clear */
+    /*usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);*/
+}
+
+
+/*************************************************************************/
+void USBHAL::setAddress(uint8_t address)
+{
+    if (address <= 127) {
+        usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);      /* OK */
+    } else {
+        usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);    /* Not Spec */
+    }
+}
+
+
+/*************************************************************************/
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags)
+{
+    const struct PIPECFGREC *cfg;
+    uint16_t pipe;
+    uint16_t buf;
+
+    if ( (EP0OUT == endpoint) || (EP0IN  == endpoint) ) {
+        return true;
+    }
+
+    for (cfg = &def_pipecfg[0]; cfg->pipesel != 0; cfg++) {
+        if (cfg->endpoint == endpoint) {
+            break;
+        }
+    }
+    if (cfg->pipesel == 0) {
+        return false;
+    }
+
+    pipe = ((cfg->pipesel & USB_PIPESEL_PIPESEL) >> USB_PIPESEL_PIPESEL_SHIFT);
+
+    g_usbx_function_PipeTbl[ pipe ] = (uint16_t)(endpoint | ((cfg->pipesel & USB_FUNCTION_FIFO_USE) << 0));
+
+    /* There are maintenance routine of SHTNAK and BFRE bits
+     * in original sample program. This sample is not
+     * programmed. Do maintenance the "def_pipecfg" array if
+     * you want it. */
+
+    /* Interrupt Disable */
+    buf  = USB20X.BRDYENB;
+    buf &= (uint16_t)~g_usbx_function_bit_set[pipe];
+    USB20X.BRDYENB = buf;
+    buf  = USB20X.NRDYENB;
+    buf &= (uint16_t)~g_usbx_function_bit_set[pipe];
+    USB20X.NRDYENB = buf;
+    buf  = USB20X.BEMPENB;
+    buf &= (uint16_t)~g_usbx_function_bit_set[pipe];
+    USB20X.BEMPENB = buf;
+
+    usbx_function_set_pid_nak(pipe);
+
+    /* CurrentPIPE Clear */
+    if (RZA_IO_RegRead_16(&USB20X.CFIFOSEL, USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE) == pipe) {
+        RZA_IO_RegWrite_16(&USB20X.CFIFOSEL, 0, USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE);
+    }
+
+    if (RZA_IO_RegRead_16(&USB20X.D0FIFOSEL, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE) == pipe) {
+        RZA_IO_RegWrite_16(&USB20X.D0FIFOSEL, 0, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE);
+    }
+
+    if (RZA_IO_RegRead_16(&USB20X.D1FIFOSEL, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE) == pipe) {
+        RZA_IO_RegWrite_16(&USB20X.D1FIFOSEL, 0, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE);
+    }
+
+    /* PIPE Configuration */
+    USB20X.PIPESEL  = pipe;
+    USB20X.PIPECFG  = cfg->pipecfg;
+    USB20X.PIPEBUF  = cfg->pipebuf;
+    USB20X.PIPEMAXP = cfg->pipemaxp;
+    USB20X.PIPEPERI = cfg->pipeperi;
+
+    g_usbx_function_pipecfg[pipe]  = cfg->pipecfg;
+    g_usbx_function_pipebuf[pipe]  = cfg->pipebuf;
+    g_usbx_function_pipemaxp[pipe] = cfg->pipemaxp;
+    g_usbx_function_pipeperi[pipe] = cfg->pipeperi;
+
+    /* Buffer Clear */
+    usbx_function_set_sqclr(pipe);
+    usbx_function_aclrm(pipe);
+
+    /* init Global */
+    g_usbx_function_pipe_status[pipe]  = DEVDRV_USBF_PIPE_IDLE;
+    g_usbx_function_PipeDataSize[pipe] = 0;
+
+    return true;
+}
+
+
+/*************************************************************************/
+// read setup packet
+void USBHAL::EP0setup(uint8_t *buffer)
+{
+    memcpy(buffer, setup_buffer, MAX_PACKET_SIZE_EP0);
+}
+
+
+/*************************************************************************/
+void USBHAL::EP0readStage(void)
+{
+    // No implements
+}
+
+
+/*************************************************************************/
+void USBHAL::EP0read(void)
+{
+    uint8_t *buffer;
+    uint32_t size;
+
+    /* remain of last writing */
+    while (EP0_read_status != DEVDRV_USBF_WRITEEND) {
+        static uint8_t bbb[2] = { 255, 255 };
+        EP0write(&bbb[0], 0);
+    }
+
+    buffer = (uint8_t*)(&setup_buffer[4]);
+    size   = (MAX_PACKET_SIZE_EP0 / 2) - 8;
+    usbx_api_function_CtrlWriteStart(size, buffer);
+}
+
+
+/*************************************************************************/
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
+{
+    memcpy(buffer, (uint8_t*)(&setup_buffer[4]), g_usbx_function_PipeDataSize[USB_FUNCTION_PIPE0]);
+
+    return g_usbx_function_PipeDataSize[USB_FUNCTION_PIPE0];
+}
+
+
+/*************************************************************************/
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
+{
+    /* zero byte writing */
+    if ( (size == 0) && (EP0_read_status == DEVDRV_USBF_WRITEEND) ) {
+        return;
+    }
+
+    if (EP0_read_status == DEVDRV_USBF_WRITEEND) {
+        /*1st block*/
+        EP0_read_status = usbx_api_function_CtrlReadStart(size, buffer);
+    } else {
+        /* waits the last transmission */
+        /*other blocks*/
+        g_usbx_function_data_count[ USB_FUNCTION_PIPE0 ]    = size;
+        g_usbx_function_data_pointer [ USB_FUNCTION_PIPE0 ] = buffer;
+        EP0_read_status = usbx_function_write_buffer_c(USB_FUNCTION_PIPE0);
+    }
+    /*max size may be deblocking outside*/
+    if (size == MAX_PACKET_SIZE_EP0) {
+        EP0_read_status = DEVDRV_USBF_WRITING;
+    }
+}
+
+
+/*************************************************************************/
+#if 0   // No implements
+void USBHAL::EP0getWriteResult(void)
+{
+}
+#endif
+
+/*************************************************************************/
+void USBHAL::EP0stall(void)
+{
+    stallEndpoint( 0 );
+}
+
+
+/*************************************************************************/
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t max_size)
+{
+    uint32_t    pipe = EP2PIPE(endpoint);
+    uint32_t    pipe_size;
+    uint16_t    pipe_status;
+    EP_STATUS status = EP_COMPLETED;
+
+    pipe_status = usbx_api_function_check_pipe_status(pipe, &pipe_size);
+
+    switch (pipe_status) {
+        case DEVDRV_USBF_PIPE_IDLE:
+        case DEVDRV_USBF_PIPE_WAIT:
+            usbx_api_function_set_pid_nak(pipe);
+            usbx_api_function_clear_pipe_status(pipe);
+
+            usbx_api_function_start_receive_transfer(pipe, max_size, recv_buffer);
+            break;
+
+        default:
+            status = EP_PENDING;
+            break;
+    }
+
+    return status;
+}
+
+
+/*************************************************************************/
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *buffer, uint32_t *bytes_read )
+{
+    uint32_t pipe = EP2PIPE(endpoint);
+    uint16_t pipe_status;
+    uint16_t err;
+    EP_STATUS status = EP_PENDING;
+
+
+    if (EPx_read_status != DEVDRV_USBF_PIPE_WAIT) {
+        return status;
+    }
+
+    pipe_status = usbx_api_function_check_pipe_status(pipe, bytes_read);
+    switch (pipe_status) {
+        case DEVDRV_USBF_PIPE_IDLE:
+            return EP_COMPLETED;
+
+        case DEVDRV_USBF_PIPE_DONE:
+            return EP_COMPLETED;
+
+        case DEVDRV_USBF_PIPE_WAIT:
+            break;
+
+        default:
+            return status;
+    }
+
+    /* sets the output buffer and size */
+    g_usbx_function_data_pointer[pipe] = buffer;
+
+    /* receives data from pipe */
+    err = usbx_function_read_buffer(pipe);
+    recv_error = err;
+    switch (err) {
+        case USB_FUNCTION_READEND:
+        case USB_FUNCTION_READSHRT:
+        case USB_FUNCTION_READOVER:
+            *bytes_read = g_usbx_function_PipeDataSize[pipe];
+            break;
+
+        case USB_FUNCTION_READING:
+        case DEVDRV_USBF_FIFOERROR:
+            break;
+    }
+
+    pipe_status = usbx_api_function_check_pipe_status(pipe, bytes_read);
+    switch (pipe_status) {
+        case DEVDRV_USBF_PIPE_DONE:
+            status = EP_COMPLETED;
+            break;
+
+        case DEVDRV_USBF_PIPE_IDLE:
+        case DEVDRV_USBF_PIPE_NORES:
+        case DEVDRV_USBF_PIPE_STALL:
+        case DEVDRV_USBF_FIFOERROR:
+        default:
+            break;
+    }
+
+    return status;
+}
+
+
+/*************************************************************************/
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
+{
+    uint32_t pipe = EP2PIPE(endpoint);
+    uint32_t pipe_size;
+    uint16_t pipe_status;
+    uint16_t err;
+    uint16_t count;
+    EP_STATUS status = EP_PENDING;
+
+    pipe_status = usbx_api_function_check_pipe_status(pipe, &pipe_size);
+
+    /* waits the last transmission */
+    count = 30000;
+    while ((pipe_status == DEVDRV_USBF_PIPE_WAIT) || (pipe_status == DEVDRV_USBF_PIPE_DONE)) {
+        pipe_status = usbx_api_function_check_pipe_status(pipe, &pipe_size);
+        if( --count == 0 ) {
+            pipe_status = DEVDRV_USBF_PIPE_STALL;
+            break;
+        }
+    }
+
+    switch (pipe_status) {
+        case DEVDRV_USBF_PIPE_IDLE:
+            err = usbx_api_function_start_send_transfer(pipe, size, data);
+
+            switch (err) {
+                    /* finish to write */
+                case DEVDRV_USBF_WRITEEND:
+                    /* finish to write, but data is short */
+                case DEVDRV_USBF_WRITESHRT:
+                    /* continue to write */
+                case DEVDRV_USBF_WRITING:
+                    /* use DMA */
+                case DEVDRV_USBF_WRITEDMA:
+                    /* error */
+                case DEVDRV_USBF_FIFOERROR:
+                    status = EP_PENDING;
+                    break;
+            }
+            break;
+
+        case DEVDRV_USBF_PIPE_WAIT:
+        case DEVDRV_USBF_PIPE_DONE:
+            status = EP_PENDING;
+            break;
+
+        case DEVDRV_USBF_PIPE_NORES:
+        case DEVDRV_USBF_PIPE_STALL:
+        default:
+            status = EP_STALLED;
+            break;
+    }
+
+    return status;
+}
+
+
+/*************************************************************************/
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
+{
+    uint32_t    pipe = EP2PIPE(endpoint);
+    uint32_t    pipe_size;
+    uint16_t    pipe_status;
+    EP_STATUS status = EP_PENDING;
+
+    pipe_status = usbx_api_function_check_pipe_status(pipe, &pipe_size);
+
+    switch (pipe_status) {
+        case DEVDRV_USBF_PIPE_IDLE:
+            status = EP_COMPLETED;
+            break;
+
+        case DEVDRV_USBF_PIPE_WAIT:
+            status = EP_PENDING;
+            break;
+
+        case DEVDRV_USBF_PIPE_DONE:
+            usbx_function_stop_transfer(pipe);
+            status = EP_COMPLETED;
+            break;
+
+        case DEVDRV_USBF_PIPE_NORES:
+            status = EP_STALLED;
+            break;
+
+        case DEVDRV_USBF_PIPE_STALL:
+            status = EP_STALLED;
+            break;
+
+        default:
+            status = EP_PENDING;
+    }
+
+    return status;
+}
+
+
+/*************************************************************************/
+void USBHAL::stallEndpoint(uint8_t endpoint)
+{
+    uint32_t pipe = EP2PIPE(endpoint);
+
+    usbx_function_clear_pid_stall(pipe);
+}
+
+
+/*************************************************************************/
+void USBHAL::unstallEndpoint(uint8_t endpoint)
+{
+    uint32_t pipe = EP2PIPE(endpoint);
+
+    usbx_function_set_pid_stall( pipe );
+}
+
+
+/*************************************************************************/
+bool USBHAL::getEndpointStallState(uint8_t endpoint)
+{
+    // No implemens
+    return false;
+}
+
+
+/*************************************************************************/
+#if 0   // No implements
+void USBHAL::remoteWakeup(void)
+{
+}
+#endif
+
+/*************************************************************************/
+void USBHAL::_usbisr(void)
+{
+    instance->usbisr();
+}
+
+
+/*************************************************************************/
+void USBHAL::usbisr(void)
+{
+    uint16_t            int_sts0;
+    uint16_t            int_sts1;
+    uint16_t            int_sts2;
+    uint16_t            int_sts3;
+    uint16_t            int_enb0;
+    uint16_t            int_enb2;
+    uint16_t            int_enb3;
+    uint16_t            int_enb4;
+    volatile uint16_t   dumy_sts;
+
+
+    int_sts0 = USB20X.INTSTS0;
+
+    if (!(int_sts0 & (
+                USB_FUNCTION_BITVBINT |
+                USB_FUNCTION_BITRESM  |
+                USB_FUNCTION_BITSOFR  |
+                USB_FUNCTION_BITDVST  |
+                USB_FUNCTION_BITCTRT  |
+                USB_FUNCTION_BITBEMP  |
+                USB_FUNCTION_BITNRDY  |
+                USB_FUNCTION_BITBRDY ))) {
+        return;
+    }
+
+    int_sts1 = USB20X.BRDYSTS;
+    int_sts2 = USB20X.NRDYSTS;
+    int_sts3 = USB20X.BEMPSTS;
+    int_enb0 = USB20X.INTENB0;
+    int_enb2 = USB20X.BRDYENB;
+    int_enb3 = USB20X.NRDYENB;
+    int_enb4 = USB20X.BEMPENB;
+
+    if ((int_sts0 & USB_FUNCTION_BITRESM) &&
+            (int_enb0 & USB_FUNCTION_BITRSME)) {
+        USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITRESM;
+        RZA_IO_RegWrite_16(&USB20X.INTENB0, 0, USB_INTENB0_RSME_SHIFT, USB_INTENB0_RSME);
+        /*usbx_function_USB_FUNCTION_Resume();*/
+        suspendStateChanged(1);
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITVBINT) &&
+        (int_enb0 & USB_FUNCTION_BITVBSE)) {
+        USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITVBINT;
+
+        if (usbx_function_CheckVBUStaus() == DEVDRV_USBF_ON) {
+            usbx_function_USB_FUNCTION_Attach();
+        } else {
+            usbx_function_USB_FUNCTION_Detach();
+        }
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITSOFR) &&
+        (int_enb0 & USB_FUNCTION_BITSOFE)) {
+        USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITSOFR;
+        SOF((USB20X.FRMNUM & USB_FRMNUM_FRNM) >> USB_FRMNUM_FRNM_SHIFT);
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITDVST) &&
+        (int_enb0 & USB_FUNCTION_BITDVSE)) {
+        USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITDVST;
+        switch (int_sts0 & USB_FUNCTION_BITDVSQ) {
+            case USB_FUNCTION_DS_POWR:
+                break;
+
+            case USB_FUNCTION_DS_DFLT:
+                /*****************************************************************************
+                 * Function Name: usbx_function_USB_FUNCTION_BusReset
+                 * Description  : This function is executed when the USB device is transitioned
+                 *              : to POWERD_STATE. Sets the device descriptor according to the
+                 *              : connection speed determined by the USB reset hand shake.
+                 * Arguments    : none
+                 * Return Value : none
+                 *****************************************************************************/
+                usbx_function_init_status();            /* memory clear */
+
+#if 0
+                /* You would program those steps in USBCallback_busReset
+                 * if the system need the comment out steps.
+                 */
+
+                if (usbx_function_is_hispeed() == USB_FUNCTION_HIGH_SPEED) {
+                    /* Device Descriptor reset */
+                    usbx_function_ResetDescriptor(USB_FUNCTION_HIGH_SPEED);
+                } else {
+                    /* Device Descriptor reset */
+                    usbx_function_ResetDescriptor(USB_FUNCTION_FULL_SPEED);
+                }
+#endif
+                /* Default Control PIPE reset */
+                /*****************************************************************************
+                 * Function Name: usbx_function_ResetDCP
+                 * Description  : Initializes the default control pipe(DCP).
+                 * Outline      : Reset default control pipe
+                 * Arguments    : none
+                 * Return Value : none
+                 *****************************************************************************/
+                USB20X.DCPCFG  = 0;
+                USB20X.DCPMAXP = 64;    /*TODO: This value is copied from sample*/
+
+                USB20X.CFIFOSEL  = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE);
+                USB20X.D0FIFOSEL = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE);
+                USB20X.D1FIFOSEL = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE);
+
+                busReset();
+                break;
+
+            case USB_FUNCTION_DS_ADDS:
+                break;
+
+            case USB_FUNCTION_DS_CNFG:
+                break;
+
+            case USB_FUNCTION_DS_SPD_POWR:
+            case USB_FUNCTION_DS_SPD_DFLT:
+            case USB_FUNCTION_DS_SPD_ADDR:
+            case USB_FUNCTION_DS_SPD_CNFG:
+                suspendStateChanged(0);
+                /*usbx_function_USB_FUNCTION_Suspend();*/
+                break;
+
+            default:
+                break;
+        }
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITBEMP) &&
+        (int_enb0 & USB_FUNCTION_BITBEMP) &&
+        ((int_sts3 & int_enb4) & g_usbx_function_bit_set[USB_FUNCTION_PIPE0])) {
+        /* ==== BEMP PIPE0 ==== */
+        usbx_function_BEMPInterruptPIPE0(int_sts3, int_enb4, this, &USBHAL::EP0in);
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITBRDY) &&
+        (int_enb0 & USB_FUNCTION_BITBRDY) &&
+        ((int_sts1 & int_enb2) & g_usbx_function_bit_set[USB_FUNCTION_PIPE0])) {
+        /* ==== BRDY PIPE0 ==== */
+        usbx_function_BRDYInterruptPIPE0(int_sts1, int_enb2, this, &USBHAL::EP0out);
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITNRDY) &&
+        (int_enb0 & USB_FUNCTION_BITNRDY) &&
+        ((int_sts2 & int_enb3) & g_usbx_function_bit_set[USB_FUNCTION_PIPE0])) {
+        /* ==== NRDY PIPE0 ==== */
+        usbx_function_NRDYInterruptPIPE0(int_sts2, int_enb3, this, NULL);
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITCTRT) && (int_enb0 & USB_FUNCTION_BITCTRE)) {
+        int_sts0 = USB20X.INTSTS0;
+        USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITCTRT;
+
+        if (((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_RDDS) ||
+                ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRDS) ||
+                ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRND)) {
+
+            /* remake EP0 into buffer */
+            usbx_function_save_request();
+            if ((USB20X.INTSTS0 & USB_FUNCTION_BITVALID) && (
+                        ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_RDDS) ||
+                        ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRDS) ||
+                        ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRND))) {
+                /* New SETUP token received */
+                /* Three dummy reads for cleearing interrupt requests */
+                dumy_sts = USB20X.INTSTS0;
+                dumy_sts = USB20X.INTSTS0;
+                dumy_sts = USB20X.INTSTS0;
+                return;
+            }
+        }
+
+        switch (int_sts0 & USB_FUNCTION_BITCTSQ) {
+            case USB_FUNCTION_CS_IDST:
+                if (g_usbx_function_TestModeFlag == DEVDRV_USBF_YES) {
+                    /* ==== Test Mode ==== */
+                    usbx_function_USB_FUNCTION_TestMode();
+                }
+                /* Needs not procedure in this state */
+                break;
+
+            case USB_FUNCTION_CS_RDDS:
+                /* Reads a setup packet */
+                EP0setupCallback();
+                break;
+
+            case USB_FUNCTION_CS_WRDS:
+                /* Original code was the SetDescriptor was called */
+                EP0setupCallback();
+                break;
+
+            case USB_FUNCTION_CS_WRND:
+                EP0setupCallback();
+
+                /*The EP0setupCallback should finish in successful */
+                usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);
+
+                RZA_IO_RegWrite_16(&USB20X.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL);
+                break;
+
+            case USB_FUNCTION_CS_RDSS:
+                RZA_IO_RegWrite_16(&USB20X.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL);
+                break;
+
+            case USB_FUNCTION_CS_WRSS:
+                RZA_IO_RegWrite_16(&USB20X.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL);
+                break;
+
+            case USB_FUNCTION_CS_SQER:
+                usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);
+                break;
+
+            default:
+                usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);
+                break;
+        }
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITBEMP) &&
+        (int_enb0 & USB_FUNCTION_BITBEMP) &&
+        (int_sts3 & int_enb4) ) {
+        /* ==== BEMP PIPEx ==== */
+        usbx_function_BEMPInterrupt(int_sts3, int_enb4, this, epCallback);
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITBRDY) &&
+        (int_enb0 & USB_FUNCTION_BITBRDY) &&
+        (int_sts1 & int_enb2) ) {
+        /* ==== BRDY PIPEx ==== */
+        usbx_function_BRDYInterrupt(int_sts1, int_enb2, this, epCallback);
+    } else if (
+        (int_sts0 & USB_FUNCTION_BITNRDY) &&
+        (int_enb0 & USB_FUNCTION_BITNRDY) &&
+        (int_sts2 & int_enb3)) {
+        /* ==== NRDY PIPEx ==== */
+        usbx_function_NRDYInterrupt(int_sts2, int_enb3, this, epCallback);
+    } else {
+        /* Do Nothing */
+    }
+
+    /* Three dummy reads for cleearing interrupt requests */
+    dumy_sts = USB20X.INTSTS0;
+    dumy_sts = USB20X.INTSTS1;
+}
+
+/*************************************************************************/
+#endif
+/*************************************************************************/
+/*EOF*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBHAL_STM32F4.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,416 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(TARGET_STM32F4)
+
+#include "USBHAL.h"
+#include "USBRegs_STM32.h"
+#include "pinmap.h"
+
+USBHAL * USBHAL::instance;
+
+static volatile int epComplete = 0;
+
+static uint32_t bufferEnd = 0;
+static const uint32_t rxFifoSize = 512;
+static uint32_t rxFifoCount = 0;
+
+static uint32_t setupBuffer[MAX_PACKET_SIZE_EP0 >> 2];
+
+uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
+    return 0;
+}
+
+USBHAL::USBHAL(void) {
+    NVIC_DisableIRQ(OTG_FS_IRQn);
+    epCallback[0] = &USBHAL::EP1_OUT_callback;
+    epCallback[1] = &USBHAL::EP1_IN_callback;
+    epCallback[2] = &USBHAL::EP2_OUT_callback;
+    epCallback[3] = &USBHAL::EP2_IN_callback;
+    epCallback[4] = &USBHAL::EP3_OUT_callback;
+    epCallback[5] = &USBHAL::EP3_IN_callback;
+
+    // Enable power and clocking
+    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
+
+#if defined(TARGET_STM32F407VG) || defined(TARGET_STM32F401RE) || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F429ZI)
+    pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS));
+    pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLDOWN, GPIO_AF10_OTG_FS));
+    pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS));
+    pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS));
+    pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS));
+#else
+    pin_function(PA_8, STM_PIN_DATA(2, 10));
+    pin_function(PA_9, STM_PIN_DATA(0, 0));
+    pin_function(PA_10, STM_PIN_DATA(2, 10));
+    pin_function(PA_11, STM_PIN_DATA(2, 10));
+    pin_function(PA_12, STM_PIN_DATA(2, 10));
+
+    // Set ID pin to open drain with pull-up resistor
+    pin_mode(PA_10, OpenDrain);
+    GPIOA->PUPDR &= ~(0x3 << 20);
+    GPIOA->PUPDR |= 1 << 20;
+
+    // Set VBUS pin to open drain
+    pin_mode(PA_9, OpenDrain);
+#endif
+
+    RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
+
+    // Enable interrupts
+    OTG_FS->GREGS.GAHBCFG |= (1 << 0);
+
+    // Turnaround time to maximum value - too small causes packet loss
+    OTG_FS->GREGS.GUSBCFG |= (0xF << 10);
+
+    // Unmask global interrupts
+    OTG_FS->GREGS.GINTMSK |= (1 << 3) | // SOF
+                             (1 << 4) | // RX FIFO not empty
+                             (1 << 12); // USB reset
+
+    OTG_FS->DREGS.DCFG |= (0x3 << 0) | // Full speed
+                          (1 << 2); // Non-zero-length status OUT handshake
+
+    OTG_FS->GREGS.GCCFG |= (1 << 19) | // Enable VBUS sensing
+                           (1 << 16); // Power Up
+
+    instance = this;
+    NVIC_SetVector(OTG_FS_IRQn, (uint32_t)&_usbisr);
+    NVIC_SetPriority(OTG_FS_IRQn, 1);
+}
+
+USBHAL::~USBHAL(void) {
+}
+
+void USBHAL::connect(void) {
+    NVIC_EnableIRQ(OTG_FS_IRQn);
+}
+
+void USBHAL::disconnect(void) {
+    NVIC_DisableIRQ(OTG_FS_IRQn);
+}
+
+void USBHAL::configureDevice(void) {
+    // Not needed
+}
+
+void USBHAL::unconfigureDevice(void) {
+    // Not needed
+}
+
+void USBHAL::setAddress(uint8_t address) {
+    OTG_FS->DREGS.DCFG |= (address << 4);
+    EP0write(0, 0);
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket,
+                             uint32_t flags) {
+    uint32_t epIndex = endpoint >> 1;
+
+    uint32_t type;
+    switch (endpoint) {
+        case EP0IN:
+        case EP0OUT:
+            type = 0;
+            break;
+        case EPISO_IN:
+        case EPISO_OUT:
+            type = 1;
+        case EPBULK_IN:
+        case EPBULK_OUT:
+            type = 2;
+            break;
+        case EPINT_IN:
+        case EPINT_OUT:
+            type = 3;
+            break;
+    }
+
+    // Generic in or out EP controls
+    uint32_t control = (maxPacket << 0) | // Packet size
+                       (1 << 15) | // Active endpoint
+                       (type << 18); // Endpoint type
+
+    if (endpoint & 0x1) { // In Endpoint
+        // Set up the Tx FIFO
+        if (endpoint == EP0IN) {
+            OTG_FS->GREGS.DIEPTXF0_HNPTXFSIZ = ((maxPacket >> 2) << 16) |
+                                               (bufferEnd << 0);
+        }
+        else {
+            OTG_FS->GREGS.DIEPTXF[epIndex - 1] = ((maxPacket >> 2) << 16) |
+                                                 (bufferEnd << 0);
+        }
+        bufferEnd += maxPacket >> 2;
+
+        // Set the In EP specific control settings
+        if (endpoint != EP0IN) {
+            control |= (1 << 28); // SD0PID
+        }
+
+        control |= (epIndex << 22) | // TxFIFO index
+                   (1 << 27); // SNAK
+        OTG_FS->INEP_REGS[epIndex].DIEPCTL = control;
+
+        // Unmask the interrupt
+        OTG_FS->DREGS.DAINTMSK |= (1 << epIndex);
+    }
+    else { // Out endpoint
+        // Set the out EP specific control settings
+        control |= (1 << 26); // CNAK
+        OTG_FS->OUTEP_REGS[epIndex].DOEPCTL = control;
+
+        // Unmask the interrupt
+        OTG_FS->DREGS.DAINTMSK |= (1 << (epIndex + 16));
+    }
+    return true;
+}
+
+// read setup packet
+void USBHAL::EP0setup(uint8_t *buffer) {
+    memcpy(buffer, setupBuffer, MAX_PACKET_SIZE_EP0);
+}
+
+void USBHAL::EP0readStage(void) {
+}
+
+void USBHAL::EP0read(void) {
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
+    uint32_t* buffer32 = (uint32_t *) buffer;
+    uint32_t length = rxFifoCount;
+    for (uint32_t i = 0; i < length; i += 4) {
+        buffer32[i >> 2] = OTG_FS->FIFO[0][0];
+    }
+
+    rxFifoCount = 0;
+    return length;
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
+    endpointWrite(0, buffer, size);
+}
+
+void USBHAL::EP0getWriteResult(void) {
+}
+
+void USBHAL::EP0stall(void) {
+    // If we stall the out endpoint here then we have problems transferring
+    // and setup requests after the (stalled) get device qualifier requests.
+    // TODO: Find out if this is correct behavior, or whether we are doing
+    // something else wrong
+    stallEndpoint(EP0IN);
+//    stallEndpoint(EP0OUT);
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
+    uint32_t epIndex = endpoint >> 1;
+    uint32_t size = (1 << 19) | // 1 packet
+                    (maximumSize << 0); // Packet size
+//    if (endpoint == EP0OUT) {
+        size |= (1 << 29); // 1 setup packet
+//    }
+    OTG_FS->OUTEP_REGS[epIndex].DOEPTSIZ = size;
+    OTG_FS->OUTEP_REGS[epIndex].DOEPCTL |= (1 << 31) | // Enable endpoint
+                                           (1 << 26); // Clear NAK
+
+    epComplete &= ~(1 << endpoint);
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
+    if (!(epComplete & (1 << endpoint))) {
+        return EP_PENDING;
+    }
+
+    uint32_t* buffer32 = (uint32_t *) buffer;
+    uint32_t length = rxFifoCount;
+    for (uint32_t i = 0; i < length; i += 4) {
+        buffer32[i >> 2] = OTG_FS->FIFO[endpoint >> 1][0];
+    }
+    rxFifoCount = 0;
+    *bytesRead = length;
+    return EP_COMPLETED;
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
+    uint32_t epIndex = endpoint >> 1;
+    OTG_FS->INEP_REGS[epIndex].DIEPTSIZ = (1 << 19) | // 1 packet
+                                          (size << 0); // Size of packet
+    OTG_FS->INEP_REGS[epIndex].DIEPCTL |= (1 << 31) | // Enable endpoint
+                                          (1 << 26); // CNAK
+    OTG_FS->DREGS.DIEPEMPMSK = (1 << epIndex);
+
+    while ((OTG_FS->INEP_REGS[epIndex].DTXFSTS & 0XFFFF) < ((size + 3) >> 2));
+
+    for (uint32_t i=0; i<(size + 3) >> 2; i++, data+=4) {
+        OTG_FS->FIFO[epIndex][0] = *(uint32_t *)data;
+    }
+
+    epComplete &= ~(1 << endpoint);
+
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
+    if (epComplete & (1 << endpoint)) {
+        epComplete &= ~(1 << endpoint);
+        return EP_COMPLETED;
+    }
+
+    return EP_PENDING;
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint) {
+    if (endpoint & 0x1) { // In EP
+        OTG_FS->INEP_REGS[endpoint >> 1].DIEPCTL |= (1 << 30) | // Disable
+                                                    (1 << 21); // Stall
+    }
+    else {  // Out EP
+        OTG_FS->DREGS.DCTL |= (1 << 9); // Set global out NAK
+        OTG_FS->OUTEP_REGS[endpoint >> 1].DOEPCTL |= (1 << 30) | // Disable
+                                                     (1 << 21); // Stall
+    }
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint) {
+
+}
+
+bool USBHAL::getEndpointStallState(uint8_t endpoint) {
+    return false;
+}
+
+void USBHAL::remoteWakeup(void) {
+}
+
+
+void USBHAL::_usbisr(void) {
+    instance->usbisr();
+}
+
+
+void USBHAL::usbisr(void) {
+    if (OTG_FS->GREGS.GINTSTS & (1 << 11)) { // USB Suspend
+        suspendStateChanged(1);
+    };
+
+    if (OTG_FS->GREGS.GINTSTS & (1 << 12)) { // USB Reset
+        suspendStateChanged(0);
+
+        // Set SNAK bits
+        OTG_FS->OUTEP_REGS[0].DOEPCTL |= (1 << 27);
+        OTG_FS->OUTEP_REGS[1].DOEPCTL |= (1 << 27);
+        OTG_FS->OUTEP_REGS[2].DOEPCTL |= (1 << 27);
+        OTG_FS->OUTEP_REGS[3].DOEPCTL |= (1 << 27);
+
+        OTG_FS->DREGS.DIEPMSK = (1 << 0);
+
+        bufferEnd = 0;
+
+        // Set the receive FIFO size
+        OTG_FS->GREGS.GRXFSIZ = rxFifoSize >> 2;
+        bufferEnd += rxFifoSize >> 2;
+
+        // Create the endpoints, and wait for setup packets on out EP0
+        realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
+        realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
+        endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
+
+        OTG_FS->GREGS.GINTSTS = (1 << 12);
+    }
+
+    if (OTG_FS->GREGS.GINTSTS & (1 << 4)) { // RX FIFO not empty
+        uint32_t status = OTG_FS->GREGS.GRXSTSP;
+
+        uint32_t endpoint = (status & 0xF) << 1;
+        uint32_t length = (status >> 4) & 0x7FF;
+        uint32_t type = (status >> 17) & 0xF;
+
+        rxFifoCount = length;
+
+        if (type == 0x6) {
+            // Setup packet
+            for (uint32_t i=0; i<length; i+=4) {
+                setupBuffer[i >> 2] = OTG_FS->FIFO[0][i >> 2];
+            }
+            rxFifoCount = 0;
+        }
+
+        if (type == 0x4) {
+            // Setup complete
+            EP0setupCallback();
+            endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
+        }
+
+        if (type == 0x2) {
+            // Out packet
+            if (endpoint == EP0OUT) {
+                EP0out();
+            }
+            else {
+                epComplete |= (1 << endpoint);
+                if ((instance->*(epCallback[endpoint - 2]))()) {
+                    epComplete &= (1 << endpoint);
+                }
+            }
+        }
+
+        for (uint32_t i=0; i<rxFifoCount; i+=4) {
+            (void) OTG_FS->FIFO[0][0];
+        }
+        OTG_FS->GREGS.GINTSTS = (1 << 4);
+    }
+
+    if (OTG_FS->GREGS.GINTSTS & (1 << 18)) { // In endpoint interrupt
+        // Loop through the in endpoints
+        for (uint32_t i=0; i<4; i++) {
+            if (OTG_FS->DREGS.DAINT & (1 << i)) { // Interrupt is on endpoint
+
+                if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 7)) {// Tx FIFO empty
+                    // If the Tx FIFO is empty on EP0 we need to send a further
+                    // packet, so call EP0in()
+                    if (i == 0) {
+                        EP0in();
+                    }
+                    // Clear the interrupt
+                    OTG_FS->INEP_REGS[i].DIEPINT = (1 << 7);
+                    // Stop firing Tx empty interrupts
+                    // Will get turned on again if another write is called
+                    OTG_FS->DREGS.DIEPEMPMSK &= ~(1 << i);
+                }
+
+                // If the transfer is complete
+                if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 0)) { // Tx Complete
+                    epComplete |= (1 << (1 + (i << 1)));
+                    OTG_FS->INEP_REGS[i].DIEPINT = (1 << 0);
+                }
+            }
+        }
+        OTG_FS->GREGS.GINTSTS = (1 << 18);
+    }
+
+    if (OTG_FS->GREGS.GINTSTS & (1 << 3)) { // Start of frame
+        SOF((OTG_FS->GREGS.GRXSTSR >> 17) & 0xF);
+        OTG_FS->GREGS.GINTSTS = (1 << 3);
+    }
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBDevice/USBRegs_STM32.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,149 @@
+/**
+  ******************************************************************************
+  * @file    usb_regs.h
+  * @author  MCD Application Team
+  * @version V2.1.0
+  * @date    19-March-2012
+  * @brief   hardware registers
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+#ifndef __USB_OTG_REGS_H__
+#define __USB_OTG_REGS_H__
+
+typedef struct //000h
+{
+  __IO uint32_t GOTGCTL;      /* USB_OTG Control and Status Register    000h*/
+  __IO uint32_t GOTGINT;      /* USB_OTG Interrupt Register             004h*/
+  __IO uint32_t GAHBCFG;      /* Core AHB Configuration Register    008h*/
+  __IO uint32_t GUSBCFG;      /* Core USB Configuration Register    00Ch*/
+  __IO uint32_t GRSTCTL;      /* Core Reset Register                010h*/
+  __IO uint32_t GINTSTS;      /* Core Interrupt Register            014h*/
+  __IO uint32_t GINTMSK;      /* Core Interrupt Mask Register       018h*/
+  __IO uint32_t GRXSTSR;      /* Receive Sts Q Read Register        01Ch*/
+  __IO uint32_t GRXSTSP;      /* Receive Sts Q Read & POP Register  020h*/
+  __IO uint32_t GRXFSIZ;      /* Receive FIFO Size Register         024h*/
+  __IO uint32_t DIEPTXF0_HNPTXFSIZ;   /* EP0 / Non Periodic Tx FIFO Size Register 028h*/
+  __IO uint32_t HNPTXSTS;     /* Non Periodic Tx FIFO/Queue Sts reg 02Ch*/
+  uint32_t Reserved30[2];     /* Reserved                           030h*/
+  __IO uint32_t GCCFG;        /* General Purpose IO Register        038h*/
+  __IO uint32_t CID;          /* User ID Register                   03Ch*/
+  uint32_t  Reserved40[48];   /* Reserved                      040h-0FFh*/
+  __IO uint32_t HPTXFSIZ; /* Host Periodic Tx FIFO Size Reg     100h*/
+  __IO uint32_t DIEPTXF[3];/* dev Periodic Transmit FIFO */
+}
+USB_OTG_GREGS;
+
+typedef struct // 800h
+{
+  __IO uint32_t DCFG;         /* dev Configuration Register   800h*/
+  __IO uint32_t DCTL;         /* dev Control Register         804h*/
+  __IO uint32_t DSTS;         /* dev Status Register (RO)     808h*/
+  uint32_t Reserved0C;           /* Reserved                     80Ch*/
+  __IO uint32_t DIEPMSK;   /* dev IN Endpoint Mask         810h*/
+  __IO uint32_t DOEPMSK;  /* dev OUT Endpoint Mask        814h*/
+  __IO uint32_t DAINT;     /* dev All Endpoints Itr Reg    818h*/
+  __IO uint32_t DAINTMSK; /* dev All Endpoints Itr Mask   81Ch*/
+  uint32_t  Reserved20;          /* Reserved                     820h*/
+  uint32_t Reserved9;       /* Reserved                     824h*/
+  __IO uint32_t DVBUSDIS;    /* dev VBUS discharge Register  828h*/
+  __IO uint32_t DVBUSPULSE;  /* dev VBUS Pulse Register      82Ch*/
+  __IO uint32_t DTHRCTL;     /* dev thr                      830h*/
+  __IO uint32_t DIEPEMPMSK; /* dev empty msk             834h*/
+}
+USB_OTG_DREGS;
+
+typedef struct
+{
+  __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/
+  uint32_t Reserved04;             /* Reserved                       900h + (ep_num * 20h) + 04h*/
+  __IO uint32_t DIEPINT; /* dev IN Endpoint Itr Reg     900h + (ep_num * 20h) + 08h*/
+  uint32_t Reserved0C;             /* Reserved                       900h + (ep_num * 20h) + 0Ch*/
+  __IO uint32_t DIEPTSIZ; /* IN Endpoint Txfer Size   900h + (ep_num * 20h) + 10h*/
+  uint32_t Reserved14;
+  __IO uint32_t DTXFSTS;/*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/
+  uint32_t Reserved1C;             /* Reserved  900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/
+}
+USB_OTG_INEPREGS;
+
+typedef struct
+{
+  __IO uint32_t DOEPCTL;       /* dev OUT Endpoint Control Reg  B00h + (ep_num * 20h) + 00h*/
+  uint32_t Reserved04;         /* Reserved                      B00h + (ep_num * 20h) + 04h*/
+  __IO uint32_t DOEPINT;       /* dev OUT Endpoint Itr Reg      B00h + (ep_num * 20h) + 08h*/
+  uint32_t Reserved0C;         /* Reserved                      B00h + (ep_num * 20h) + 0Ch*/
+  __IO uint32_t DOEPTSIZ;      /* dev OUT Endpoint Txfer Size   B00h + (ep_num * 20h) + 10h*/
+  uint32_t Reserved14[3];
+}
+USB_OTG_OUTEPREGS;
+
+typedef struct
+{
+  __IO uint32_t HCFG;             /* Host Configuration Register    400h*/
+  __IO uint32_t HFIR;      /* Host Frame Interval Register   404h*/
+  __IO uint32_t HFNUM;         /* Host Frame Nbr/Frame Remaining 408h*/
+  uint32_t Reserved40C;                   /* Reserved                       40Ch*/
+  __IO uint32_t HPTXSTS;   /* Host Periodic Tx FIFO/ Queue Status 410h*/
+  __IO uint32_t HAINT;   /* Host All Channels Interrupt Register 414h*/
+  __IO uint32_t HAINTMSK;   /* Host All Channels Interrupt Mask 418h*/
+}
+USB_OTG_HREGS;
+
+typedef struct
+{
+  __IO uint32_t HCCHAR;
+  __IO uint32_t HCSPLT;
+  __IO uint32_t HCINT;
+  __IO uint32_t HCINTMSK;
+  __IO uint32_t HCTSIZ;
+  uint32_t Reserved[3];
+}
+USB_OTG_HC_REGS;
+
+typedef struct
+{
+    USB_OTG_GREGS         GREGS;
+    uint32_t RESERVED0[188];
+    USB_OTG_HREGS         HREGS;
+    uint32_t RESERVED1[9];
+    __IO uint32_t         HPRT;
+    uint32_t RESERVED2[47];
+    USB_OTG_HC_REGS       HC_REGS[8];
+    uint32_t RESERVED3[128];
+    USB_OTG_DREGS         DREGS;
+    uint32_t RESERVED4[50];
+    USB_OTG_INEPREGS      INEP_REGS[4];
+    uint32_t RESERVED5[96];
+    USB_OTG_OUTEPREGS     OUTEP_REGS[4];
+    uint32_t RESERVED6[160];
+    __IO uint32_t         PCGCCTL;
+    uint32_t RESERVED7[127];
+    __IO uint32_t         FIFO[4][1024];
+}
+USB_OTG_CORE_REGS;
+
+
+#define OTG_FS_BASE (AHB2PERIPH_BASE + 0x0000)
+#define OTG_FS ((USB_OTG_CORE_REGS *) OTG_FS_BASE)
+
+#endif //__USB_OTG_REGS_H__
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBHID.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,276 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBHAL.h"
+#include "USBHID.h"
+
+
+USBHID::USBHID(uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect): USBDevice(vendor_id, product_id, product_release)
+{
+    output_length = output_report_length;
+    input_length = input_report_length;
+    if(connect) {
+        USBDevice::connect();
+    }
+}
+
+
+bool USBHID::send(HID_REPORT *report)
+{
+    return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
+}
+
+bool USBHID::sendNB(HID_REPORT *report)
+{
+    return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
+}
+
+
+bool USBHID::read(HID_REPORT *report)
+{
+    uint32_t bytesRead = 0;
+    bool result;
+    result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
+    if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
+        return false;
+    report->length = bytesRead;
+    return result;
+}
+
+
+bool USBHID::readNB(HID_REPORT *report)
+{
+    uint32_t bytesRead = 0;
+    bool result;
+    result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
+    // if readEP_NB did not succeed, does not issue a readStart
+    if (!result)
+        return false;
+    report->length = bytesRead;
+    if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
+        return false;
+    return result;
+}
+
+
+uint16_t USBHID::reportDescLength() {
+    reportDesc();
+    return reportLength;
+}
+
+
+
+//
+//  Route callbacks from lower layers to class(es)
+//
+
+
+// Called in ISR context
+// Called by USBDevice on Endpoint0 request
+// This is used to handle extensions to standard requests
+// and class specific requests
+// Return true if class handles this request
+bool USBHID::USBCallback_request() {
+    bool success = false;
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+    uint8_t *hidDescriptor;
+
+    // Process additional standard requests
+
+    if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
+    {
+        switch (transfer->setup.bRequest)
+        {
+            case GET_DESCRIPTOR:
+                switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
+                {
+                    case REPORT_DESCRIPTOR:
+                        if ((reportDesc() != NULL) \
+                            && (reportDescLength() != 0))
+                        {
+                            transfer->remaining = reportDescLength();
+                            transfer->ptr = reportDesc();
+                            transfer->direction = DEVICE_TO_HOST;
+                            success = true;
+                        }
+                        break;
+                    case HID_DESCRIPTOR:
+                            // Find the HID descriptor, after the configuration descriptor
+                            hidDescriptor = findDescriptor(HID_DESCRIPTOR);
+                            if (hidDescriptor != NULL)
+                            {
+                                transfer->remaining = HID_DESCRIPTOR_LENGTH;
+                                transfer->ptr = hidDescriptor;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                            }
+                            break;
+
+                    default:
+                        break;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    // Process class-specific requests
+
+    if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
+    {
+        switch (transfer->setup.bRequest)
+        {
+             case SET_REPORT:
+                // First byte will be used for report ID
+                outputReport.data[0] = transfer->setup.wValue & 0xff;
+                outputReport.length = transfer->setup.wLength + 1;
+
+                transfer->remaining = sizeof(outputReport.data) - 1;
+                transfer->ptr = &outputReport.data[1];
+                transfer->direction = HOST_TO_DEVICE;
+                transfer->notify = true;
+                success = true;
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+
+#define DEFAULT_CONFIGURATION (1)
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported
+bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
+    if (configuration != DEFAULT_CONFIGURATION) {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
+    addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
+
+    // We activate the endpoint to be able to recceive data
+    readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
+    return true;
+}
+
+
+uint8_t * USBHID::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x08,               //bLength
+        STRING_DESCRIPTOR,  //bDescriptorType 0x03
+        'H',0,'I',0,'D',0,  //bString iInterface - HID
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBHID::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
+    };
+    return stringIproductDescriptor;
+}
+
+
+
+uint8_t * USBHID::reportDesc() {
+    static uint8_t reportDescriptor[] = {
+        0x06, LSB(0xFFAB), MSB(0xFFAB),
+        0x0A, LSB(0x0200), MSB(0x0200),
+        0xA1, 0x01,         // Collection 0x01
+        0x75, 0x08,         // report size = 8 bits
+        0x15, 0x00,         // logical minimum = 0
+        0x26, 0xFF, 0x00,   // logical maximum = 255
+        0x95, input_length, // report count
+        0x09, 0x01,         // usage
+        0x81, 0x02,         // Input (array)
+        0x95, output_length,// report count
+        0x09, 0x02,         // usage
+        0x91, 0x02,         // Output (array)
+        0xC0                // end collection
+
+    };
+    reportLength = sizeof(reportDescriptor);
+    return reportDescriptor;
+}
+
+#define DEFAULT_CONFIGURATION (1)
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (1 * HID_DESCRIPTOR_LENGTH) \
+                               + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+uint8_t * USBHID::configurationDesc() {
+    static uint8_t configurationDescriptor[] = {
+        CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+        CONFIGURATION_DESCRIPTOR,       // bDescriptorType
+        LSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (LSB)
+        MSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (MSB)
+        0x01,                           // bNumInterfaces
+        DEFAULT_CONFIGURATION,          // bConfigurationValue
+        0x00,                           // iConfiguration
+        C_RESERVED | C_SELF_POWERED,    // bmAttributes
+        C_POWER(0),                     // bMaxPower
+
+        INTERFACE_DESCRIPTOR_LENGTH,    // bLength
+        INTERFACE_DESCRIPTOR,           // bDescriptorType
+        0x00,                           // bInterfaceNumber
+        0x00,                           // bAlternateSetting
+        0x02,                           // bNumEndpoints
+        HID_CLASS,                      // bInterfaceClass
+        HID_SUBCLASS_NONE,              // bInterfaceSubClass
+        HID_PROTOCOL_NONE,              // bInterfaceProtocol
+        0x00,                           // iInterface
+
+        HID_DESCRIPTOR_LENGTH,          // bLength
+        HID_DESCRIPTOR,                 // bDescriptorType
+        LSB(HID_VERSION_1_11),          // bcdHID (LSB)
+        MSB(HID_VERSION_1_11),          // bcdHID (MSB)
+        0x00,                           // bCountryCode
+        0x01,                           // bNumDescriptors
+        REPORT_DESCRIPTOR,              // bDescriptorType
+        (uint8_t)(LSB(this->reportDescLength())),  // wDescriptorLength (LSB)
+        (uint8_t)(MSB(this->reportDescLength())),  // wDescriptorLength (MSB)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_OUT),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+    };
+    return configurationDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBHID.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,172 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USB_HID_H
+#define USB_HID_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBHID_Types.h"
+#include "USBDevice.h"
+
+
+/**
+ * USBHID example
+ * @code
+ * #include "mbed.h"
+ * #include "USBHID.h"
+ *
+ * USBHID hid;
+ * HID_REPORT recv;
+ * BusOut leds(LED1,LED2,LED3,LED4);
+ *
+ * int main(void) {
+ *    while (1) {
+ *        hid.read(&recv);
+ *        leds = recv.data[0];
+ *    }
+ * }
+ * @endcode
+ */
+
+class USBHID: public USBDevice {
+public:
+
+    /**
+    * Constructor
+    *
+    * @param output_report_length Maximum length of a sent report (up to 64 bytes) (default: 64 bytes)
+    * @param input_report_length Maximum length of a received report (up to 64 bytes) (default: 64 bytes)
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    * @param connect Connect the device
+    */
+    USBHID(uint8_t output_report_length = 64, uint8_t input_report_length = 64, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0006, uint16_t product_release = 0x0001, bool connect = true);
+
+
+    /**
+    * Send a Report. warning: blocking
+    *
+    * @param report Report which will be sent (a report is defined by all data and the length)
+    * @returns true if successful
+    */
+    bool send(HID_REPORT *report);
+
+
+    /**
+    * Send a Report. warning: non blocking
+    *
+    * @param report Report which will be sent (a report is defined by all data and the length)
+    * @returns true if successful
+    */
+    bool sendNB(HID_REPORT *report);
+
+    /**
+    * Read a report: blocking
+    *
+    * @param report pointer to the report to fill
+    * @returns true if successful
+    */
+    bool read(HID_REPORT * report);
+
+    /**
+    * Read a report: non blocking
+    *
+    * @param report pointer to the report to fill
+    * @returns true if successful
+    */
+    bool readNB(HID_REPORT * report);
+
+protected:
+    uint16_t reportLength;
+
+    /*
+    * Get the Report descriptor
+    *
+    * @returns pointer to the report descriptor
+    */
+    virtual uint8_t * reportDesc();
+
+    /*
+    * Get the length of the report descriptor
+    *
+    * @returns the length of the report descriptor
+    */
+    virtual uint16_t reportDescLength();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+
+    /*
+    * HID Report received by SET_REPORT request. Warning: Called in ISR context
+    * First byte of data will be the report ID
+    *
+    * @param report Data and length received
+    */
+    virtual void HID_callbackSetReport(HID_REPORT *report){};
+
+
+    /*
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request();
+
+
+    /*
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_setConfiguration(uint8_t configuration);
+
+private:
+    HID_REPORT outputReport;
+    uint8_t output_length;
+    uint8_t input_length;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBHID_Types.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,91 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBCLASS_HID_TYPES
+#define USBCLASS_HID_TYPES
+
+#include <stdint.h>
+
+/* */
+#define HID_VERSION_1_11    (0x0111)
+
+/* HID Class */
+#define HID_CLASS           (3)
+#define HID_SUBCLASS_NONE   (0)
+#define HID_PROTOCOL_NONE   (0)
+
+/* Descriptors */
+#define HID_DESCRIPTOR          (33)
+#define HID_DESCRIPTOR_LENGTH   (0x09)
+#define REPORT_DESCRIPTOR       (34)
+
+/* Class requests */
+#define GET_REPORT (0x1)
+#define GET_IDLE   (0x2)
+#define SET_REPORT (0x9)
+#define SET_IDLE   (0xa)
+
+/* HID Class Report Descriptor */
+/* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes */
+/* of data as per HID Class standard */
+
+/* Main items */
+#define INPUT(size)             (0x80 | size)
+#define OUTPUT(size)            (0x90 | size)
+#define FEATURE(size)           (0xb0 | size)
+#define COLLECTION(size)        (0xa0 | size)
+#define END_COLLECTION(size)    (0xc0 | size)
+
+/* Global items */
+#define USAGE_PAGE(size)        (0x04 | size)
+#define LOGICAL_MINIMUM(size)   (0x14 | size)
+#define LOGICAL_MAXIMUM(size)   (0x24 | size)
+#define PHYSICAL_MINIMUM(size)  (0x34 | size)
+#define PHYSICAL_MAXIMUM(size)  (0x44 | size)
+#define UNIT_EXPONENT(size)     (0x54 | size)
+#define UNIT(size)              (0x64 | size)
+#define REPORT_SIZE(size)       (0x74 | size)
+#define REPORT_ID(size)         (0x84 | size)
+#define REPORT_COUNT(size)      (0x94 | size)
+#define PUSH(size)              (0xa4 | size)
+#define POP(size)               (0xb4 | size)
+
+/* Local items */
+#define USAGE(size)                 (0x08 | size)
+#define USAGE_MINIMUM(size)         (0x18 | size)
+#define USAGE_MAXIMUM(size)         (0x28 | size)
+#define DESIGNATOR_INDEX(size)      (0x38 | size)
+#define DESIGNATOR_MINIMUM(size)    (0x48 | size)
+#define DESIGNATOR_MAXIMUM(size)    (0x58 | size)
+#define STRING_INDEX(size)          (0x78 | size)
+#define STRING_MINIMUM(size)        (0x88 | size)
+#define STRING_MAXIMUM(size)        (0x98 | size)
+#define DELIMITER(size)             (0xa8 | size)
+
+/* HID Report */
+/* Where report IDs are used the first byte of 'data' will be the */
+/* report ID and 'length' will include this report ID byte. */
+
+#define MAX_HID_REPORT_SIZE (64)
+
+typedef struct {
+    uint32_t length;
+    uint8_t data[MAX_HID_REPORT_SIZE];
+} HID_REPORT;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBKeyboard.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,553 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+
+#include "USBKeyboard.h"
+
+#define REPORT_ID_KEYBOARD 1
+#define REPORT_ID_VOLUME   3
+
+
+typedef struct {
+    unsigned char usage;
+    unsigned char modifier;
+} KEYMAP;
+
+#ifdef US_KEYBOARD
+/* US keyboard (as HID standard) */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x34, KEY_SHIFT},      /* " */
+    {0x20, KEY_SHIFT},      /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x1f, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x31, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x31, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x35, KEY_SHIFT},      /* ~ */
+    {0,0},              /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+
+#else
+/* UK keyboard */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x1f, KEY_SHIFT},      /* " */
+    {0x32, 0},          /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x34, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x64, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x64, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x32, KEY_SHIFT},      /* ~ */
+    {0,0},             /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+#endif
+
+uint8_t * USBKeyboard::reportDesc() {
+    static uint8_t reportDescriptor[] = {
+        USAGE_PAGE(1), 0x01,                    // Generic Desktop
+        USAGE(1), 0x06,                         // Keyboard
+        COLLECTION(1), 0x01,                    // Application
+        REPORT_ID(1),       REPORT_ID_KEYBOARD,
+
+        USAGE_PAGE(1), 0x07,                    // Key Codes
+        USAGE_MINIMUM(1), 0xE0,
+        USAGE_MAXIMUM(1), 0xE7,
+        LOGICAL_MINIMUM(1), 0x00,
+        LOGICAL_MAXIMUM(1), 0x01,
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x08,
+        INPUT(1), 0x02,                         // Data, Variable, Absolute
+        REPORT_COUNT(1), 0x01,
+        REPORT_SIZE(1), 0x08,
+        INPUT(1), 0x01,                         // Constant
+
+
+        REPORT_COUNT(1), 0x05,
+        REPORT_SIZE(1), 0x01,
+        USAGE_PAGE(1), 0x08,                    // LEDs
+        USAGE_MINIMUM(1), 0x01,
+        USAGE_MAXIMUM(1), 0x05,
+        OUTPUT(1), 0x02,                        // Data, Variable, Absolute
+        REPORT_COUNT(1), 0x01,
+        REPORT_SIZE(1), 0x03,
+        OUTPUT(1), 0x01,                        // Constant
+
+
+        REPORT_COUNT(1), 0x06,
+        REPORT_SIZE(1), 0x08,
+        LOGICAL_MINIMUM(1), 0x00,
+        LOGICAL_MAXIMUM(1), 0x65,
+        USAGE_PAGE(1), 0x07,                    // Key Codes
+        USAGE_MINIMUM(1), 0x00,
+        USAGE_MAXIMUM(1), 0x65,
+        INPUT(1), 0x00,                         // Data, Array
+        END_COLLECTION(0),
+
+        // Media Control
+        USAGE_PAGE(1), 0x0C,
+        USAGE(1), 0x01,
+        COLLECTION(1), 0x01,
+        REPORT_ID(1), REPORT_ID_VOLUME,
+        USAGE_PAGE(1), 0x0C,
+        LOGICAL_MINIMUM(1), 0x00,
+        LOGICAL_MAXIMUM(1), 0x01,
+        REPORT_SIZE(1), 0x01,
+        REPORT_COUNT(1), 0x07,
+        USAGE(1), 0xB5,             // Next Track
+        USAGE(1), 0xB6,             // Previous Track
+        USAGE(1), 0xB7,             // Stop
+        USAGE(1), 0xCD,             // Play / Pause
+        USAGE(1), 0xE2,             // Mute
+        USAGE(1), 0xE9,             // Volume Up
+        USAGE(1), 0xEA,             // Volume Down
+        INPUT(1), 0x02,             // Input (Data, Variable, Absolute)
+        REPORT_COUNT(1), 0x01,
+        INPUT(1), 0x01,
+        END_COLLECTION(0),
+    };
+    reportLength = sizeof(reportDescriptor);
+    return reportDescriptor;
+}
+
+
+bool USBKeyboard::EPINT_OUT_callback() {
+    uint32_t bytesRead = 0;
+    uint8_t led[65];
+    USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE);
+
+    // we take led[1] because led[0] is the report ID
+    lock_status = led[1] & 0x07;
+
+    // We activate the endpoint to be able to recceive data
+    if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
+        return false;
+    return true;
+}
+
+uint8_t USBKeyboard::lockStatus() {
+    return lock_status;
+}
+
+int USBKeyboard::_putc(int c) {
+    return keyCode(c, keymap[c].modifier);
+}
+
+bool USBKeyboard::keyCode(uint8_t key, uint8_t modifier) {
+    // Send a simulated keyboard keypress. Returns true if successful.
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_KEYBOARD;
+    report.data[1] = modifier;
+    report.data[2] = 0;
+    report.data[3] = keymap[key].usage;
+    report.data[4] = 0;
+    report.data[5] = 0;
+    report.data[6] = 0;
+    report.data[7] = 0;
+    report.data[8] = 0;
+
+    report.length = 9;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    report.data[1] = 0;
+    report.data[3] = 0;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    return true;
+
+}
+
+
+bool USBKeyboard::mediaControl(MEDIA_KEY key) {
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = (1 << key) & 0x7f;
+
+    report.length = 2;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = 0;
+
+    report.length = 2;
+
+    return send(&report);
+}
+
+
+#define DEFAULT_CONFIGURATION (1)
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (1 * HID_DESCRIPTOR_LENGTH) \
+                               + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+uint8_t * USBKeyboard::configurationDesc() {
+    static uint8_t configurationDescriptor[] = {
+        CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+        CONFIGURATION_DESCRIPTOR,       // bDescriptorType
+        LSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (LSB)
+        MSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (MSB)
+        0x01,                           // bNumInterfaces
+        DEFAULT_CONFIGURATION,          // bConfigurationValue
+        0x00,                           // iConfiguration
+        C_RESERVED | C_SELF_POWERED,    // bmAttributes
+        C_POWER(0),                     // bMaxPowerHello World from Mbed
+
+        INTERFACE_DESCRIPTOR_LENGTH,    // bLength
+        INTERFACE_DESCRIPTOR,           // bDescriptorType
+        0x00,                           // bInterfaceNumber
+        0x00,                           // bAlternateSetting
+        0x02,                           // bNumEndpoints
+        HID_CLASS,                      // bInterfaceClass
+        1,                              // bInterfaceSubClass
+        1,                              // bInterfaceProtocol (keyboard)
+        0x00,                           // iInterface
+
+        HID_DESCRIPTOR_LENGTH,          // bLength
+        HID_DESCRIPTOR,                 // bDescriptorType
+        LSB(HID_VERSION_1_11),          // bcdHID (LSB)
+        MSB(HID_VERSION_1_11),          // bcdHID (MSB)
+        0x00,                           // bCountryCode
+        0x01,                           // bNumDescriptors
+        REPORT_DESCRIPTOR,              // bDescriptorType
+        (uint8_t)(LSB(reportDescLength())),  // wDescriptorLength (LSB)
+        (uint8_t)(MSB(reportDescLength())),  // wDescriptorLength (MSB)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_OUT),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+    };
+    return configurationDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBKeyboard.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,183 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBKEYBOARD_H
+#define USBKEYBOARD_H
+
+#include "USBHID.h"
+#include "Stream.h"
+
+/* Modifiers */
+enum MODIFIER_KEY {
+    KEY_CTRL = 1,
+    KEY_SHIFT = 2,
+    KEY_ALT = 4,
+};
+
+
+enum MEDIA_KEY {
+    KEY_NEXT_TRACK,     /*!< next Track Button */
+    KEY_PREVIOUS_TRACK, /*!< Previous track Button */
+    KEY_STOP,           /*!< Stop Button */
+    KEY_PLAY_PAUSE,     /*!< Play/Pause Button */
+    KEY_MUTE,           /*!< Mute Button */
+    KEY_VOLUME_UP,      /*!< Volume Up Button */
+    KEY_VOLUME_DOWN,    /*!< Volume Down Button */
+};
+
+enum FUNCTION_KEY {
+    KEY_F1 = 128,   /* F1 key */
+    KEY_F2,         /* F2 key */
+    KEY_F3,         /* F3 key */
+    KEY_F4,         /* F4 key */
+    KEY_F5,         /* F5 key */
+    KEY_F6,         /* F6 key */
+    KEY_F7,         /* F7 key */
+    KEY_F8,         /* F8 key */
+    KEY_F9,         /* F9 key */
+    KEY_F10,        /* F10 key */
+    KEY_F11,        /* F11 key */
+    KEY_F12,        /* F12 key */
+
+    KEY_PRINT_SCREEN,   /* Print Screen key */
+    KEY_SCROLL_LOCK,    /* Scroll lock */
+    KEY_CAPS_LOCK,      /* caps lock */
+    KEY_NUM_LOCK,       /* num lock */
+    KEY_INSERT,         /* Insert key */
+    KEY_HOME,           /* Home key */
+    KEY_PAGE_UP,        /* Page Up key */
+    KEY_PAGE_DOWN,      /* Page Down key */
+
+    RIGHT_ARROW,        /* Right arrow */
+    LEFT_ARROW,         /* Left arrow */
+    DOWN_ARROW,         /* Down arrow */
+    UP_ARROW,           /* Up arrow */
+};
+
+/**
+ * USBKeyboard example
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBKeyboard.h"
+ *
+ * USBKeyboard key;
+ *
+ * int main(void)
+ * {
+ *   while (1)
+ *   {
+ *       key.printf("Hello World\r\n");
+ *       wait(1);
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class USBKeyboard: public USBHID, public Stream {
+public:
+
+    /**
+    *   Constructor
+    *
+    *
+    * @param leds Leds bus: first: NUM_LOCK, second: CAPS_LOCK, third: SCROLL_LOCK
+    * @param vendor_id Your vendor_id (default: 0x1235)
+    * @param product_id Your product_id (default: 0x0050)
+    * @param product_release Your preoduct_release (default: 0x0001)
+    *
+    */
+    USBKeyboard(uint16_t vendor_id = 0x1235, uint16_t product_id = 0x0050, uint16_t product_release = 0x0001):
+            USBHID(0, 0, vendor_id, product_id, product_release, false) {
+        lock_status = 0;
+        connect();
+    };
+
+    /**
+    * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key
+    *
+    * @code
+    * //To send CTRL + s (save)
+    *  keyboard.keyCode('s', KEY_CTRL);
+    * @endcode
+    *
+    * @param modifier bit 0: KEY_CTRL, bit 1: KEY_SHIFT, bit 2: KEY_ALT (default: 0)
+    * @param key character to send
+    * @returns true if there is no error, false otherwise
+    */
+    bool keyCode(uint8_t key, uint8_t modifier = 0);
+
+    /**
+    * Send a character
+    *
+    * @param c character to be sent
+    * @returns true if there is no error, false otherwise
+    */
+    virtual int _putc(int c);
+
+    /**
+    * Control media keys
+    *
+    * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN)
+    * @returns true if there is no error, false otherwise
+    */
+    bool mediaControl(MEDIA_KEY key);
+
+    /*
+    * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the report descriptor
+    */
+    virtual uint8_t * reportDesc();
+
+    /*
+    * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
+    *
+    * @returns if handle by subclass, return true
+    */
+    virtual bool EPINT_OUT_callback();
+
+    /**
+    * Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important:
+    *   - First bit: NUM_LOCK
+    *   - Second bit: CAPS_LOCK
+    *   - Third bit: SCROLL_LOCK
+    *
+    * @returns status of lock keys
+    */
+    uint8_t lockStatus();
+
+protected:
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+private:
+    //dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
+    virtual int _getc() {
+        return -1;
+    };
+
+    uint8_t lock_status;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBMouse.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,245 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMouse.h"
+
+bool USBMouse::update(int16_t x, int16_t y, uint8_t button, int8_t z) {
+    switch (mouse_type) {
+        case REL_MOUSE:
+            while (x > 127) {
+                if (!mouseSend(127, 0, button, z)) return false;
+                x = x - 127;
+            }
+            while (x < -128) {
+                if (!mouseSend(-128, 0, button, z)) return false;
+                x = x + 128;
+            }
+            while (y > 127) {
+                if (!mouseSend(0, 127, button, z)) return false;
+                y = y - 127;
+            }
+            while (y < -128) {
+                if (!mouseSend(0, -128, button, z)) return false;
+                y = y + 128;
+            }
+            return mouseSend(x, y, button, z);
+        case ABS_MOUSE:
+            HID_REPORT report;
+
+            report.data[0] = x & 0xff;
+            report.data[1] = (x >> 8) & 0xff;
+            report.data[2] = y & 0xff;
+            report.data[3] = (y >> 8) & 0xff;
+            report.data[4] = -z;
+            report.data[5] = button & 0x07;
+
+            report.length = 6;
+
+            return send(&report);
+        default:
+            return false;
+    }
+}
+
+bool USBMouse::mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z) {
+    HID_REPORT report;
+    report.data[0] = buttons & 0x07;
+    report.data[1] = x;
+    report.data[2] = y;
+    report.data[3] = -z; // >0 to scroll down, <0 to scroll up
+
+    report.length = 4;
+
+    return send(&report);
+}
+
+bool USBMouse::move(int16_t x, int16_t y) {
+    return update(x, y, button, 0);
+}
+
+bool USBMouse::scroll(int8_t z) {
+    return update(0, 0, button, z);
+}
+
+
+bool USBMouse::doubleClick() {
+    if (!click(MOUSE_LEFT))
+        return false;
+    wait(0.1);
+    return click(MOUSE_LEFT);
+}
+
+bool USBMouse::click(uint8_t button) {
+    if (!update(0, 0, button, 0))
+        return false;
+    wait(0.01);
+    return update(0, 0, 0, 0);
+}
+
+bool USBMouse::press(uint8_t button_) {
+    button = button_ & 0x07;
+    return update(0, 0, button, 0);
+}
+
+bool USBMouse::release(uint8_t button_) {
+    button = (button & (~button_)) & 0x07;
+    return update(0, 0, button, 0);
+}
+
+
+uint8_t * USBMouse::reportDesc() {
+
+    if (mouse_type == REL_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+            USAGE_PAGE(1),      0x01,       // Genric Desktop
+            USAGE(1),           0x02,       // Mouse
+            COLLECTION(1),      0x01,       // Application
+            USAGE(1),           0x01,       // Pointer
+            COLLECTION(1),      0x00,       // Physical
+
+            REPORT_COUNT(1),    0x03,
+            REPORT_SIZE(1),     0x01,
+            USAGE_PAGE(1),      0x09,       // Buttons
+            USAGE_MINIMUM(1),       0x1,
+            USAGE_MAXIMUM(1),       0x3,
+            LOGICAL_MINIMUM(1),     0x00,
+            LOGICAL_MAXIMUM(1),     0x01,
+            INPUT(1),           0x02,
+            REPORT_COUNT(1),    0x01,
+            REPORT_SIZE(1),     0x05,
+            INPUT(1),           0x01,
+
+            REPORT_COUNT(1),    0x03,
+            REPORT_SIZE(1),     0x08,
+            USAGE_PAGE(1),      0x01,
+            USAGE(1),           0x30,       // X
+            USAGE(1),           0x31,       // Y
+            USAGE(1),           0x38,       // scroll
+            LOGICAL_MINIMUM(1),     0x81,
+            LOGICAL_MAXIMUM(1),     0x7f,
+            INPUT(1),           0x06,       // Relative data
+
+            END_COLLECTION(0),
+            END_COLLECTION(0),
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    } else if (mouse_type == ABS_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+
+            USAGE_PAGE(1), 0x01,           // Generic Desktop
+            USAGE(1), 0x02,                // Mouse
+            COLLECTION(1), 0x01,           // Application
+            USAGE(1), 0x01,                // Pointer
+            COLLECTION(1), 0x00,           // Physical
+
+            USAGE_PAGE(1), 0x01,            // Generic Desktop
+            USAGE(1), 0x30,                 // X
+            USAGE(1), 0x31,                 // Y
+            LOGICAL_MINIMUM(1), 0x00,       // 0
+            LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767
+            REPORT_SIZE(1), 0x10,
+            REPORT_COUNT(1), 0x02,
+            INPUT(1), 0x02,                 // Data, Variable, Absolute
+
+            USAGE_PAGE(1), 0x01,            // Generic Desktop
+            USAGE(1), 0x38,                 // scroll
+            LOGICAL_MINIMUM(1), 0x81,       // -127
+            LOGICAL_MAXIMUM(1), 0x7f,       // 127
+            REPORT_SIZE(1), 0x08,
+            REPORT_COUNT(1), 0x01,
+            INPUT(1), 0x06,                 // Data, Variable, Relative
+
+            USAGE_PAGE(1), 0x09,            // Buttons
+            USAGE_MINIMUM(1), 0x01,
+            USAGE_MAXIMUM(1), 0x03,
+            LOGICAL_MINIMUM(1), 0x00,       // 0
+            LOGICAL_MAXIMUM(1), 0x01,       // 1
+            REPORT_COUNT(1), 0x03,
+            REPORT_SIZE(1), 0x01,
+            INPUT(1), 0x02,                 // Data, Variable, Absolute
+            REPORT_COUNT(1), 0x01,
+            REPORT_SIZE(1), 0x05,
+            INPUT(1), 0x01,                 // Constant
+
+            END_COLLECTION(0),
+            END_COLLECTION(0)
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    }
+    return NULL;
+}
+
+#define DEFAULT_CONFIGURATION (1)
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (1 * HID_DESCRIPTOR_LENGTH) \
+                               + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+uint8_t * USBMouse::configurationDesc() {
+    static uint8_t configurationDescriptor[] = {
+        CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+        CONFIGURATION_DESCRIPTOR,       // bDescriptorType
+        LSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (LSB)
+        MSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (MSB)
+        0x01,                           // bNumInterfaces
+        DEFAULT_CONFIGURATION,          // bConfigurationValue
+        0x00,                           // iConfiguration
+        C_RESERVED | C_SELF_POWERED,    // bmAttributes
+        C_POWER(0),                     // bMaxPowerHello World from Mbed
+
+        INTERFACE_DESCRIPTOR_LENGTH,    // bLength
+        INTERFACE_DESCRIPTOR,           // bDescriptorType
+        0x00,                           // bInterfaceNumber
+        0x00,                           // bAlternateSetting
+        0x02,                           // bNumEndpoints
+        HID_CLASS,                      // bInterfaceClass
+        1,                              // bInterfaceSubClass
+        2,                              // bInterfaceProtocol (mouse)
+        0x00,                           // iInterface
+
+        HID_DESCRIPTOR_LENGTH,          // bLength
+        HID_DESCRIPTOR,                 // bDescriptorType
+        LSB(HID_VERSION_1_11),          // bcdHID (LSB)
+        MSB(HID_VERSION_1_11),          // bcdHID (MSB)
+        0x00,                           // bCountryCode
+        0x01,                           // bNumDescriptors
+        REPORT_DESCRIPTOR,              // bDescriptorType
+        (uint8_t)(LSB(reportDescLength())),        // wDescriptorLength (LSB)
+        (uint8_t)(MSB(reportDescLength())),        // wDescriptorLength (MSB)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        1,                              // bInterval (milliseconds)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_OUT),         // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        1,                              // bInterval (milliseconds)
+    };
+    return configurationDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBMouse.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,209 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBMOUSE_H
+#define USBMOUSE_H
+
+#include "USBHID.h"
+
+#define REPORT_ID_MOUSE   2
+
+/* Common usage */
+
+enum MOUSE_BUTTON
+{
+    MOUSE_LEFT = 1,
+    MOUSE_RIGHT = 2,
+    MOUSE_MIDDLE = 4,
+};
+
+/* X and Y limits */
+/* These values do not directly map to screen pixels */
+/* Zero may be interpreted as meaning 'no movement' */
+#define X_MIN_ABS    (1)        /*!< Minimum value on x-axis */
+#define Y_MIN_ABS    (1)        /*!< Minimum value on y-axis */
+#define X_MAX_ABS    (0x7fff)   /*!< Maximum value on x-axis */
+#define Y_MAX_ABS    (0x7fff)   /*!< Maximum value on y-axis */
+
+#define X_MIN_REL    (-127)     /*!< The maximum value that we can move to the left on the x-axis */
+#define Y_MIN_REL    (-127)     /*!< The maximum value that we can move up on the y-axis */
+#define X_MAX_REL    (127)      /*!< The maximum value that we can move to the right on the x-axis */
+#define Y_MAX_REL    (127)      /*!< The maximum value that we can move down on the y-axis */
+
+enum MOUSE_TYPE
+{
+    ABS_MOUSE,
+    REL_MOUSE,
+};
+
+/**
+ *
+ * USBMouse example
+ * @code
+ * #include "mbed.h"
+ * #include "USBMouse.h"
+ *
+ * USBMouse mouse;
+ *
+ * int main(void)
+ * {
+ *   while (1)
+ *   {
+ *      mouse.move(20, 0);
+ *      wait(0.5);
+ *   }
+ * }
+ *
+ * @endcode
+ *
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "USBMouse.h"
+ * #include <math.h>
+ *
+ * USBMouse mouse(ABS_MOUSE);
+ *
+ * int main(void)
+ * {
+ *   uint16_t x_center = (X_MAX_ABS - X_MIN_ABS)/2;
+ *   uint16_t y_center = (Y_MAX_ABS - Y_MIN_ABS)/2;
+ *   uint16_t x_screen = 0;
+ *   uint16_t y_screen = 0;
+ *
+ *   uint32_t x_origin = x_center;
+ *   uint32_t y_origin = y_center;
+ *   uint32_t radius = 5000;
+ *   uint32_t angle = 0;
+ *
+ *   while (1)
+ *   {
+ *       x_screen = x_origin + cos((double)angle*3.14/180.0)*radius;
+ *       y_screen = y_origin + sin((double)angle*3.14/180.0)*radius;
+ *
+ *       mouse.move(x_screen, y_screen);
+ *       angle += 3;
+ *       wait(0.01);
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class USBMouse: public USBHID
+{
+    public:
+
+        /**
+        *   Constructor
+        *
+        * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE)
+        * @param vendor_id Your vendor_id (default: 0x1234)
+        * @param product_id Your product_id (default: 0x0001)
+        * @param product_release Your preoduct_release (default: 0x0001)
+        *
+        */
+        USBMouse(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0001, uint16_t product_release = 0x0001):
+            USBHID(0, 0, vendor_id, product_id, product_release, false)
+            {
+                button = 0;
+                this->mouse_type = mouse_type;
+                connect();
+            };
+
+        /**
+        * Write a state of the mouse
+        *
+        * @param x x-axis position
+        * @param y y-axis position
+        * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE)
+        * @param z wheel state (>0 to scroll down, <0 to scroll up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z);
+
+
+        /**
+        * Move the cursor to (x, y)
+        *
+        * @param x-axis position
+        * @param y-axis position
+        * @returns true if there is no error, false otherwise
+        */
+        bool move(int16_t x, int16_t y);
+
+        /**
+        * Press one or several buttons
+        *
+        * @param button button state (ex: press(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool press(uint8_t button);
+
+        /**
+        * Release one or several buttons
+        *
+        * @param button button state (ex: release(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool release(uint8_t button);
+
+        /**
+        * Double click (MOUSE_LEFT)
+        *
+        * @returns true if there is no error, false otherwise
+        */
+        bool doubleClick();
+
+        /**
+        * Click
+        *
+        * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool click(uint8_t button);
+
+        /**
+        * Scrolling
+        *
+        * @param z value of the wheel (>0 to go down, <0 to go up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool scroll(int8_t z);
+
+        /*
+        * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+        *
+        * @returns pointer to the report descriptor
+        */
+        virtual uint8_t * reportDesc();
+
+    protected:
+        /*
+        * Get configuration descriptor
+        *
+        * @returns pointer to the configuration descriptor
+        */
+        virtual uint8_t * configurationDesc();
+
+    private:
+        MOUSE_TYPE mouse_type;
+        uint8_t button;
+        bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBMouseKeyboard.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,706 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMouseKeyboard.h"
+
+typedef struct {
+    unsigned char usage;
+    unsigned char modifier;
+} KEYMAP;
+
+#ifdef US_KEYBOARD
+/* US keyboard (as HID standard) */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x34, KEY_SHIFT},      /* " */
+    {0x20, KEY_SHIFT},      /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x1f, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x31, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x31, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x35, KEY_SHIFT},      /* ~ */
+    {0,0},              /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+
+#else
+/* UK keyboard */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] = {
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x1f, KEY_SHIFT},      /* " */
+    {0x32, 0},          /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x34, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x64, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x64, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x32, KEY_SHIFT},      /* ~ */
+    {0,0},             /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+#endif
+
+
+uint8_t * USBMouseKeyboard::reportDesc() {
+    if (mouse_type == REL_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+                // Keyboard
+                USAGE_PAGE(1),      0x01,
+                USAGE(1),           0x06,
+                COLLECTION(1),      0x01,
+                REPORT_ID(1),       REPORT_ID_KEYBOARD,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0xE0,
+                USAGE_MAXIMUM(1),       0xE7,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(1),     0x01,
+                REPORT_SIZE(1),     0x01,
+                REPORT_COUNT(1),    0x08,
+                INPUT(1),           0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x08,
+                INPUT(1),           0x01,
+                REPORT_COUNT(1),    0x05,
+                REPORT_SIZE(1),     0x01,
+                USAGE_PAGE(1),      0x08,
+                USAGE_MINIMUM(1),       0x01,
+                USAGE_MAXIMUM(1),       0x05,
+                OUTPUT(1),          0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x03,
+                OUTPUT(1),          0x01,
+                REPORT_COUNT(1),    0x06,
+                REPORT_SIZE(1),     0x08,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(2),     0xff, 0x00,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0x00,
+                USAGE_MAXIMUM(2),       0xff, 0x00,
+                INPUT(1),           0x00,
+                END_COLLECTION(0),
+
+                // Mouse
+                USAGE_PAGE(1),      0x01,           // Generic Desktop
+                USAGE(1),           0x02,           // Mouse
+                COLLECTION(1),      0x01,           // Application
+                USAGE(1),           0x01,           // Pointer
+                COLLECTION(1),      0x00,           // Physical
+                REPORT_ID(1),       REPORT_ID_MOUSE,
+                REPORT_COUNT(1),    0x03,
+                REPORT_SIZE(1),     0x01,
+                USAGE_PAGE(1),      0x09,           // Buttons
+                USAGE_MINIMUM(1),       0x1,
+                USAGE_MAXIMUM(1),       0x3,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(1),     0x01,
+                INPUT(1),           0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x05,
+                INPUT(1),           0x01,
+                REPORT_COUNT(1),    0x03,
+                REPORT_SIZE(1),     0x08,
+                USAGE_PAGE(1),      0x01,
+                USAGE(1),           0x30,           // X
+                USAGE(1),           0x31,           // Y
+                USAGE(1),           0x38,           // scroll
+                LOGICAL_MINIMUM(1),     0x81,
+                LOGICAL_MAXIMUM(1),     0x7f,
+                INPUT(1),           0x06,
+                END_COLLECTION(0),
+                END_COLLECTION(0),
+
+
+                // Media Control
+                USAGE_PAGE(1), 0x0C,
+                USAGE(1), 0x01,
+                COLLECTION(1), 0x01,
+                REPORT_ID(1), REPORT_ID_VOLUME,
+                USAGE_PAGE(1), 0x0C,
+                LOGICAL_MINIMUM(1), 0x00,
+                LOGICAL_MAXIMUM(1), 0x01,
+                REPORT_SIZE(1), 0x01,
+                REPORT_COUNT(1), 0x07,
+                USAGE(1), 0xB5,             // Next Track
+                USAGE(1), 0xB6,             // Previous Track
+                USAGE(1), 0xB7,             // Stop
+                USAGE(1), 0xCD,             // Play / Pause
+                USAGE(1), 0xE2,             // Mute
+                USAGE(1), 0xE9,             // Volume Up
+                USAGE(1), 0xEA,             // Volume Down
+                INPUT(1), 0x02,             // Input (Data, Variable, Absolute)
+                REPORT_COUNT(1), 0x01,
+                INPUT(1), 0x01,
+                END_COLLECTION(0),
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    } else if (mouse_type == ABS_MOUSE) {
+        static uint8_t reportDescriptor[] = {
+
+                // Keyboard
+                USAGE_PAGE(1),      0x01,
+                USAGE(1),           0x06,
+                COLLECTION(1),      0x01,
+                REPORT_ID(1),       REPORT_ID_KEYBOARD,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0xE0,
+                USAGE_MAXIMUM(1),       0xE7,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(1),     0x01,
+                REPORT_SIZE(1),     0x01,
+                REPORT_COUNT(1),    0x08,
+                INPUT(1),           0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x08,
+                INPUT(1),           0x01,
+                REPORT_COUNT(1),    0x05,
+                REPORT_SIZE(1),     0x01,
+                USAGE_PAGE(1),      0x08,
+                USAGE_MINIMUM(1),       0x01,
+                USAGE_MAXIMUM(1),       0x05,
+                OUTPUT(1),          0x02,
+                REPORT_COUNT(1),    0x01,
+                REPORT_SIZE(1),     0x03,
+                OUTPUT(1),          0x01,
+                REPORT_COUNT(1),    0x06,
+                REPORT_SIZE(1),     0x08,
+                LOGICAL_MINIMUM(1),     0x00,
+                LOGICAL_MAXIMUM(2),     0xff, 0x00,
+                USAGE_PAGE(1),      0x07,
+                USAGE_MINIMUM(1),       0x00,
+                USAGE_MAXIMUM(2),       0xff, 0x00,
+                INPUT(1),           0x00,
+                END_COLLECTION(0),
+
+                // Mouse
+                USAGE_PAGE(1), 0x01,               // Generic Desktop
+                USAGE(1), 0x02,                    // Mouse
+                COLLECTION(1), 0x01,               // Application
+                USAGE(1), 0x01,                    // Pointer
+                COLLECTION(1), 0x00,               // Physical
+                REPORT_ID(1),       REPORT_ID_MOUSE,
+
+                USAGE_PAGE(1), 0x01,                // Generic Desktop
+                USAGE(1), 0x30,                     // X
+                USAGE(1), 0x31,                     // Y
+                LOGICAL_MINIMUM(1), 0x00,           // 0
+                LOGICAL_MAXIMUM(2), 0xff, 0x7f,     // 32767
+                REPORT_SIZE(1), 0x10,
+                REPORT_COUNT(1), 0x02,
+                INPUT(1), 0x02,                     // Data, Variable, Absolute
+
+                USAGE_PAGE(1), 0x01,                // Generic Desktop
+                USAGE(1), 0x38,                     // scroll
+                LOGICAL_MINIMUM(1), 0x81,           // -127
+                LOGICAL_MAXIMUM(1), 0x7f,           // 127
+                REPORT_SIZE(1), 0x08,
+                REPORT_COUNT(1), 0x01,
+                INPUT(1), 0x06,                     // Data, Variable, Relative
+
+                USAGE_PAGE(1), 0x09,                // Buttons
+                USAGE_MINIMUM(1), 0x01,
+                USAGE_MAXIMUM(1), 0x03,
+                LOGICAL_MINIMUM(1), 0x00,           // 0
+                LOGICAL_MAXIMUM(1), 0x01,           // 1
+                REPORT_COUNT(1), 0x03,
+                REPORT_SIZE(1), 0x01,
+                INPUT(1), 0x02,                     // Data, Variable, Absolute
+                REPORT_COUNT(1), 0x01,
+                REPORT_SIZE(1), 0x05,
+                INPUT(1), 0x01,                     // Constant
+
+                END_COLLECTION(0),
+                END_COLLECTION(0),
+
+                // Media Control
+                USAGE_PAGE(1), 0x0C,
+                USAGE(1), 0x01,
+                COLLECTION(1), 0x01,
+                REPORT_ID(1), REPORT_ID_VOLUME,
+                USAGE_PAGE(1), 0x0C,
+                LOGICAL_MINIMUM(1), 0x00,
+                LOGICAL_MAXIMUM(1), 0x01,
+                REPORT_SIZE(1), 0x01,
+                REPORT_COUNT(1), 0x07,
+                USAGE(1), 0xB5,             // Next Track
+                USAGE(1), 0xB6,             // Previous Track
+                USAGE(1), 0xB7,             // Stop
+                USAGE(1), 0xCD,             // Play / Pause
+                USAGE(1), 0xE2,             // Mute
+                USAGE(1), 0xE9,             // Volume Up
+                USAGE(1), 0xEA,             // Volume Down
+                INPUT(1), 0x02,             // Input (Data, Variable, Absolute)
+                REPORT_COUNT(1), 0x01,
+                INPUT(1), 0x01,
+                END_COLLECTION(0),
+        };
+        reportLength = sizeof(reportDescriptor);
+        return reportDescriptor;
+    }
+
+    return NULL;
+}
+
+bool USBMouseKeyboard::EPINT_OUT_callback() {
+    uint32_t bytesRead = 0;
+    uint8_t led[65];
+    USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE);
+
+    // we take led[1] because led[0] is the report ID
+    lock_status = led[1] & 0x07;
+
+    // We activate the endpoint to be able to recceive data
+    if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
+        return false;
+    return true;
+}
+
+uint8_t USBMouseKeyboard::lockStatus() {
+    return lock_status;
+}
+
+bool USBMouseKeyboard::update(int16_t x, int16_t y, uint8_t button, int8_t z) {
+    switch (mouse_type) {
+    case REL_MOUSE:
+        while (x > 127) {
+            if (!mouseSend(127, 0, button, z)) return false;
+            x = x - 127;
+        }
+        while (x < -128) {
+            if (!mouseSend(-128, 0, button, z)) return false;
+            x = x + 128;
+        }
+        while (y > 127) {
+            if (!mouseSend(0, 127, button, z)) return false;
+            y = y - 127;
+        }
+        while (y < -128) {
+            if (!mouseSend(0, -128, button, z)) return false;
+            y = y + 128;
+        }
+        return mouseSend(x, y, button, z);
+    case ABS_MOUSE:
+        HID_REPORT report;
+
+        report.data[0] = REPORT_ID_MOUSE;
+        report.data[1] = x & 0xff;
+        report.data[2] = (x >> 8) & 0xff;
+        report.data[3] = y & 0xff;
+        report.data[4] = (y >> 8) & 0xff;
+        report.data[5] = -z;
+        report.data[6] = button & 0x07;
+
+        report.length = 7;
+
+        return send(&report);
+    default:
+        return false;
+    }
+}
+
+bool USBMouseKeyboard::mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z) {
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_MOUSE;
+    report.data[1] = buttons & 0x07;
+    report.data[2] = x;
+    report.data[3] = y;
+    report.data[4] = -z; // >0 to scroll down, <0 to scroll up
+
+    report.length = 5;
+
+    return send(&report);
+}
+
+bool USBMouseKeyboard::move(int16_t x, int16_t y) {
+    return update(x, y, button, 0);
+}
+
+bool USBMouseKeyboard::scroll(int8_t z) {
+    return update(0, 0, button, z);
+}
+
+bool USBMouseKeyboard::doubleClick() {
+    if (!click(MOUSE_LEFT))
+        return false;
+    wait(0.1);
+    return click(MOUSE_LEFT);
+}
+
+bool USBMouseKeyboard::click(uint8_t button) {
+    if (!update(0, 0, button, 0))
+        return false;
+    wait(0.01);
+    return update(0, 0, 0, 0);
+}
+
+bool USBMouseKeyboard::press(uint8_t button_) {
+    button = button_ & 0x07;
+    return update(0, 0, button, 0);
+}
+
+bool USBMouseKeyboard::release(uint8_t button_) {
+    button = (button & (~button_)) & 0x07;
+    return update(0, 0, button, 0);
+}
+
+int USBMouseKeyboard::_putc(int c) {
+    return keyCode(c, keymap[c].modifier);
+}
+
+bool USBMouseKeyboard::keyCode(uint8_t key, uint8_t modifier) {
+    // Send a simulated keyboard keypress. Returns true if successful.
+
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_KEYBOARD;
+    report.data[1] = modifier;
+    report.data[2] = 0;
+    report.data[3] = keymap[key].usage;
+    report.data[4] = 0;
+    report.data[5] = 0;
+    report.data[6] = 0;
+    report.data[7] = 0;
+    report.data[8] = 0;
+
+    report.length = 9;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    report.data[1] = 0;
+    report.data[3] = 0;
+
+    if (!send(&report)) {
+        return false;
+    }
+
+    return true;
+
+}
+
+
+bool USBMouseKeyboard::mediaControl(MEDIA_KEY key) {
+    HID_REPORT report;
+
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = (1 << key) & 0x7f;
+
+    report.length = 2;
+
+    send(&report);
+
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = 0;
+
+    report.length = 2;
+
+    return send(&report);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBHID/USBMouseKeyboard.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,220 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBMOUSEKEYBOARD_H
+#define USBMOUSEKEYBOARD_H
+
+#define REPORT_ID_KEYBOARD 1
+#define REPORT_ID_MOUSE 2
+#define REPORT_ID_VOLUME 3
+
+#include "USBMouse.h"
+#include "USBKeyboard.h"
+#include "Stream.h"
+#include "USBHID.h"
+
+/**
+ * USBMouseKeyboard example
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBMouseKeyboard.h"
+ *
+ * USBMouseKeyboard key_mouse;
+ *
+ * int main(void)
+ * {
+ *   while(1)
+ *   {
+ *       key_mouse.move(20, 0);
+ *       key_mouse.printf("Hello From MBED\r\n");
+ *       wait(1);
+ *   }
+ * }
+ * @endcode
+ *
+ *
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBMouseKeyboard.h"
+ *
+ * USBMouseKeyboard key_mouse(ABS_MOUSE);
+ *
+ * int main(void)
+ * {
+ *   while(1)
+ *   {
+ *       key_mouse.move(X_MAX_ABS/2, Y_MAX_ABS/2);
+ *       key_mouse.printf("Hello from MBED\r\n");
+ *       wait(1);
+ *   }
+ * }
+ * @endcode
+ */
+class USBMouseKeyboard: public USBHID, public Stream
+{
+    public:
+
+        /**
+        *   Constructor
+        *
+        * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE)
+        * @param leds Leds bus: first: NUM_LOCK, second: CAPS_LOCK, third: SCROLL_LOCK
+        * @param vendor_id Your vendor_id (default: 0x1234)
+        * @param product_id Your product_id (default: 0x0001)
+        * @param product_release Your preoduct_release (default: 0x0001)
+        *
+        */
+        USBMouseKeyboard(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x0021, uint16_t product_id = 0x0011, uint16_t product_release = 0x0001):
+            USBHID(0, 0, vendor_id, product_id, product_release, false)
+            {
+                lock_status = 0;
+                button = 0;
+                this->mouse_type = mouse_type;
+                connect();
+            };
+
+        /**
+        * Write a state of the mouse
+        *
+        * @param x x-axis position
+        * @param y y-axis position
+        * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE)
+        * @param z wheel state (>0 to scroll down, <0 to scroll up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z);
+
+
+        /**
+        * Move the cursor to (x, y)
+        *
+        * @param x x-axis position
+        * @param y y-axis position
+        * @returns true if there is no error, false otherwise
+        */
+        bool move(int16_t x, int16_t y);
+
+        /**
+        * Press one or several buttons
+        *
+        * @param button button state (ex: press(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool press(uint8_t button);
+
+        /**
+        * Release one or several buttons
+        *
+        * @param button button state (ex: release(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool release(uint8_t button);
+
+        /**
+        * Double click (MOUSE_LEFT)
+        *
+        * @returns true if there is no error, false otherwise
+        */
+        bool doubleClick();
+
+        /**
+        * Click
+        *
+        * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
+        * @returns true if there is no error, false otherwise
+        */
+        bool click(uint8_t button);
+
+        /**
+        * Scrolling
+        *
+        * @param z value of the wheel (>0 to go down, <0 to go up)
+        * @returns true if there is no error, false otherwise
+        */
+        bool scroll(int8_t z);
+
+        /**
+        * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key
+        *
+        * @code
+        * //To send CTRL + s (save)
+        *  keyboard.keyCode('s', KEY_CTRL);
+        * @endcode
+        *
+        * @param modifier bit 0: KEY_CTRL, bit 1: KEY_SHIFT, bit 2: KEY_ALT (default: 0)
+        * @param key character to send
+        * @returns true if there is no error, false otherwise
+        */
+        bool keyCode(uint8_t key, uint8_t modifier = 0);
+
+        /**
+        * Send a character
+        *
+        * @param c character to be sent
+        * @returns true if there is no error, false otherwise
+        */
+        virtual int _putc(int c);
+
+        /**
+        * Control media keys
+        *
+        * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN)
+        * @returns true if there is no error, false otherwise
+        */
+        bool mediaControl(MEDIA_KEY key);
+
+        /**
+        * Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important:
+        *   - First bit: NUM_LOCK
+        *   - Second bit: CAPS_LOCK
+        *   - Third bit: SCROLL_LOCK
+        *
+        * @returns status of lock keys
+        */
+        uint8_t lockStatus();
+
+        /*
+        * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+        *
+        * @returns pointer to the report descriptor
+        */
+        virtual uint8_t * reportDesc();
+
+        /*
+        * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
+        *
+        * @returns if handle by subclass, return true
+        */
+        virtual bool EPINT_OUT_callback();
+
+
+    private:
+        bool mouseWrite(int8_t x, int8_t y, uint8_t buttons, int8_t z);
+        MOUSE_TYPE mouse_type;
+        uint8_t button;
+        bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z);
+
+        uint8_t lock_status;
+
+        //dummy otherwise it doesn't compile (we must define all methods of an abstract class)
+        virtual int _getc() { return -1;}
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBMIDI/MIDIMessage.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,276 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MIDIMESSAGE_H
+#define MIDIMESSAGE_H
+
+#include "mbed.h"
+
+#define MAX_MIDI_MESSAGE_SIZE 256 // Max message size. SysEx can be up to 65536 but 256 should be fine for most usage
+
+// MIDI Message Format
+//
+// [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
+//
+// MIDI Data Messages (Channel Specific)
+//
+// Message               msg n          m
+// ---------------------------------------------
+// Note Off              0x8 Key        Velocity
+// Note On               0x9 Key        Velocity
+// Polyphonic Aftertouch 0xA Key        Pressure
+// Control Change        0xB Controller Value
+// Program Change        0xC Program    -
+// Channel Aftertouch    0xD Pressure   -
+// Pitch Wheel           0xE LSB        MSB
+
+#define CABLE_NUM (0<<4)
+
+/** A MIDI message container */
+class MIDIMessage {
+public:
+    MIDIMessage() : length(4) {}
+
+    MIDIMessage(uint8_t *buf) : length(4) {
+        for (int i = 0; i < 4; i++)
+            data[i] = buf[i];
+    }
+
+    // New constructor, buf is a true MIDI message (not USBMidi message) and buf_len true message length.
+    MIDIMessage(uint8_t *buf, int buf_len) {
+        length=buf_len+1;
+        // first byte keeped for retro-compatibility
+        data[0]=0;
+
+        for (int i = 0; i < buf_len; i++)
+            data[i+1] = buf[i];
+    }
+
+    // create messages
+
+    /** Create a NoteOff message
+     * @param key Key ID
+     * @param velocity Key velocity (0-127, default = 127)
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage NoteOff(int key, int velocity = 127, int channel = 0) {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x08;
+        msg.data[1] = 0x80 | (channel & 0x0F);
+        msg.data[2] = key & 0x7F;
+        msg.data[3] = velocity & 0x7F;
+        return msg;
+    }
+
+    /** Create a NoteOn message
+     * @param key Key ID
+     * @param velocity Key velocity (0-127, default = 127)
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage NoteOn(int key, int velocity = 127, int channel = 0) {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x09;
+        msg.data[1] = 0x90 | (channel & 0x0F);
+        msg.data[2] = key & 0x7F;
+        msg.data[3] = velocity & 0x7F;
+        return msg;
+    }
+
+    /** Create a PolyPhonic Aftertouch message
+     * @param key Key ID
+     * @param pressure Aftertouch pressure (0-127)
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0A;
+        msg.data[1] = 0xA0 | (channel & 0x0F);
+        msg.data[2] = key & 0x7F;
+        msg.data[3] = pressure & 0x7F;
+        return msg;
+    }
+
+    /** Create a Control Change message
+     * @param control Controller ID
+     * @param value Controller value (0-127)
+     * @param channel Controller channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage ControlChange(int control, int value, int channel = 0) {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0B;
+        msg.data[1] = 0xB0 | (channel & 0x0F);
+        msg.data[2] = control & 0x7F;
+        msg.data[3] = value & 0x7F;
+        return msg;
+    }
+
+    /** Create a Program Change message
+     * @param program Program ID
+     * @param channel Channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage ProgramChange(int program, int channel = 0) {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0C;
+        msg.data[1] = 0xC0 | (channel & 0x0F);
+        msg.data[2] = program & 0x7F;
+        msg.data[3] = 0x00;
+        return msg;
+    }
+
+    /** Create a Channel Aftertouch message
+     * @param pressure Pressure
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0D;
+        msg.data[1] = 0xD0 | (channel & 0x0F);
+        msg.data[2] = pressure & 0x7F;
+        msg.data[3] = 0x00;
+        return msg;
+    }
+
+    /** Create a Pitch Wheel message
+     * @param pitch Pitch (-8192 - 8191, default = 0)
+     * @param channel Channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) {
+        MIDIMessage msg;
+        int p = pitch + 8192;    // 0 - 16383, 8192 is center
+        msg.data[0] = CABLE_NUM | 0x0E;
+        msg.data[1] = 0xE0 | (channel & 0x0F);
+        msg.data[2] = p & 0x7F;
+        msg.data[3] = (p >> 7) & 0x7F;
+        return msg;
+    }
+
+    /** Create an All Notes Off message
+     * @param channel Channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage AllNotesOff(int channel = 0) {
+        return ControlChange(123, 0, channel);
+    }
+
+     /** Create a SysEx message
+     * @param data SysEx data (including 0xF0 .. 0xF7)
+     * @param len SysEx data length
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage SysEx(uint8_t *data, int len) {
+        MIDIMessage msg=MIDIMessage(data,len);
+        return msg;
+    }
+
+    // decode messages
+
+    /** MIDI Message Types */
+    enum MIDIMessageType {
+        ErrorType,
+        NoteOffType,
+        NoteOnType,
+        PolyphonicAftertouchType,
+        ControlChangeType,
+        ProgramChangeType,
+        ChannelAftertouchType,
+        PitchWheelType,
+        AllNotesOffType,
+        SysExType
+    };
+
+    /** Read the message type
+     * @returns MIDIMessageType
+     */
+    MIDIMessageType type() {
+        switch((data[1] >> 4) & 0xF) {
+            case 0x8: return NoteOffType;
+            case 0x9: return NoteOnType;
+            case 0xA: return PolyphonicAftertouchType;
+            case 0xB:
+                if(controller() < 120) { // standard controllers
+                    return ControlChangeType;
+                } else if(controller() == 123) {
+                    return AllNotesOffType;
+                } else {
+                    return ErrorType; // unsupported atm
+                }
+            case 0xC: return ProgramChangeType;
+            case 0xD: return ChannelAftertouchType;
+            case 0xE: return PitchWheelType;
+            case 0xF: return SysExType;
+            default: return ErrorType;
+        }
+    }
+
+    /** Read the channel number */
+    int channel() {
+        return (data[1] & 0x0F);
+    }
+
+    /** Read the key ID */
+    int key() {
+        return (data[2] & 0x7F);
+    }
+
+    /** Read the velocity */
+    int velocity() {
+        return (data[3] & 0x7F);
+    }
+
+    /** Read the controller value */
+    int value() {
+        return (data[3] & 0x7F);
+    }
+
+    /** Read the aftertouch pressure */
+    int pressure() {
+        if(type() == PolyphonicAftertouchType) {
+            return (data[3] & 0x7F);
+        } else {
+            return (data[2] & 0x7F);
+        }
+    }
+
+    /** Read the controller number */
+    int controller() {
+        return (data[2] & 0x7F);
+    }
+
+    /** Read the program number */
+    int program() {
+        return (data[2] & 0x7F);
+    }
+
+    /** Read the pitch value */
+    int pitch() {
+        int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F);
+        return p - 8192; // 0 - 16383, 8192 is center
+    }
+
+    uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
+    uint8_t length;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBMIDI/USBMIDI.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,207 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMIDI.h"
+
+
+USBMIDI::USBMIDI(uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
+ : USBDevice(vendor_id, product_id, product_release), cur_data(0), data_end(true)
+{
+    midi_evt = NULL;
+    USBDevice::connect();
+}
+
+// write plain MIDIMessage that will be converted to USBMidi event packet
+void USBMIDI::write(MIDIMessage m) {
+    // first byte keeped for retro-compatibility
+    for(int p=1; p < m.length; p+=3) {
+        uint8_t buf[4];
+        // Midi message to USBMidi event packet
+        buf[0]=m.data[1] >> 4;
+        // SysEx
+        if(buf[0] == 0xF) {
+            if((m.length - p) > 3) {
+                // SysEx start or continue
+                buf[0]=0x4;
+            } else {
+                switch(m.length - p) {
+                    case 1:
+                        // SysEx end with one byte
+                        buf[0]=0x5;
+                        break;
+                    case 2:
+                        // SysEx end with two bytes
+                        buf[0]=0x6;
+                        break;
+                    case 3:
+                        // SysEx end with three bytes
+                        buf[0]=0x7;
+                        break;
+                }
+            }
+        }
+        buf[1]=m.data[p];
+
+        if(p+1 < m.length)
+            buf[2]=m.data[p+1];
+        else
+            buf[2]=0;
+
+        if(p+2 < m.length)
+            buf[3]=m.data[p+2];
+        else
+            buf[3]=0;
+
+        USBDevice::write(EPBULK_IN, buf, 4, MAX_PACKET_SIZE_EPBULK);
+    }
+}
+
+
+void USBMIDI::attach(void (*fptr)(MIDIMessage)) {
+    midi_evt = fptr;
+}
+
+bool USBMIDI::EPBULK_OUT_callback() {
+    uint8_t buf[64];
+    uint32_t len;
+    readEP(EPBULK_OUT, buf, &len, 64);
+
+    if (midi_evt != NULL) {
+        for (uint32_t i=0; i<len; i+=4) {   
+            uint8_t data_read;
+            data_end=true;
+            switch(buf[i]) {
+            case 0x2:
+                // Two-bytes System Common Message - undefined in USBMidi 1.0
+                data_read=2;
+                break;
+            case 0x4:
+                // SysEx start or continue
+                data_end=false;
+                data_read=3;
+                break;
+            case 0x5:
+                 // Single-byte System Common Message or SysEx end with one byte
+                data_read=1;
+                break;
+            case 0x6:
+                // SysEx end with two bytes
+                data_read=2;
+                break;
+            case 0xC:
+                // Program change
+                data_read=2;
+                break;
+            case 0xD:
+                // Channel pressure
+                data_read=2;
+                break;      
+            case 0xF:
+                // Single byte
+                data_read=1;
+                break;    
+            default:
+                // Others three-bytes messages
+                data_read=3;
+                break;      
+            } 
+        
+            for(uint8_t j=1;j<data_read+1;j++) {
+                data[cur_data]=buf[i+j];
+                cur_data++;
+            }
+        
+            if(data_end) {
+                 midi_evt(MIDIMessage(data,cur_data));
+                 cur_data=0;            
+            }
+       }
+    }
+
+    // We reactivate the endpoint to receive next characters
+    readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+    return true;
+}
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBMIDI::USBCallback_setConfiguration(uint8_t configuration) {
+    if (configuration != DEFAULT_CONFIGURATION) {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
+    addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+
+    // We activate the endpoint to be able to receive data
+    readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+    return true;
+}
+
+
+uint8_t * USBMIDI::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x0c,                           //bLength
+        STRING_DESCRIPTOR,              //bDescriptorType 0x03
+        'A',0,'u',0,'d',0,'i',0,'o',0   //bString iInterface - Audio
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBMIDI::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
+    };
+    return stringIproductDescriptor;
+}
+
+
+uint8_t * USBMIDI::configurationDesc() {
+    static uint8_t configDescriptor[] = {
+        // configuration descriptor
+        0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50,
+
+        // The Audio Interface Collection
+        0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, // Standard AC Interface Descriptor
+        0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, // Class-specific AC Interface Descriptor
+        0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, // MIDIStreaming Interface Descriptors
+        0x07, 0x24, 0x01, 0x00, 0x01, 0x41, 0x00,             // Class-Specific MS Interface Header Descriptor
+
+        // MIDI IN JACKS
+        0x06, 0x24, 0x02, 0x01, 0x01, 0x00,
+        0x06, 0x24, 0x02, 0x02, 0x02, 0x00,
+
+        // MIDI OUT JACKS
+        0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00,
+        0x09, 0x24, 0x03, 0x02, 0x06, 0x01, 0x01, 0x01, 0x00,
+
+        // OUT endpoint descriptor
+        0x09, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
+        0x05, 0x25, 0x01, 0x01, 0x01,
+
+        // IN endpoint descriptor
+        0x09, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
+        0x05, 0x25, 0x01, 0x01, 0x03,
+    };
+    return configDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBMIDI/USBMIDI.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,112 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBMIDI_H
+#define USBMIDI_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBDevice.h"
+#include "MIDIMessage.h"
+
+#define DEFAULT_CONFIGURATION (1)
+
+/**
+* USBMIDI example
+*
+* @code
+* #include "mbed.h"
+* #include "USBMIDI.h"
+*
+* USBMIDI midi;
+*
+* int main() {
+*    while (1) {
+*        for(int i=48; i<83; i++) {     // send some messages!
+*            midi.write(MIDIMessage::NoteOn(i));
+*            wait(0.25);
+*            midi.write(MIDIMessage::NoteOff(i));
+*            wait(0.5);
+*        }
+*    }
+* }
+* @endcode
+*/
+class USBMIDI: public USBDevice {
+public:
+
+    /**
+    * Constructor
+    *
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBMIDI(uint16_t vendor_id = 0x0700, uint16_t product_id = 0x0101, uint16_t product_release = 0x0001);
+
+    /**
+     * Send a MIDIMessage
+     *
+     * @param m The MIDIMessage to send
+     */
+    void write(MIDIMessage m);
+
+    /**
+     * Attach a callback for when a MIDIEvent is received
+     *
+     * @param fptr function pointer
+     */
+    void attach(void (*fptr)(MIDIMessage));
+
+
+protected:
+    virtual bool EPBULK_OUT_callback();
+    virtual bool USBCallback_setConfiguration(uint8_t configuration);
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+private:
+    uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
+    uint8_t cur_data;
+    bool data_end;
+    
+    void (*midi_evt)(MIDIMessage);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBMSD/USBMSD.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,655 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMSD.h"
+
+#define DISK_OK         0x00
+#define NO_INIT         0x01
+#define NO_DISK         0x02
+#define WRITE_PROTECT   0x04
+
+#define CBW_Signature   0x43425355
+#define CSW_Signature   0x53425355
+
+// SCSI Commands
+#define TEST_UNIT_READY            0x00
+#define REQUEST_SENSE              0x03
+#define FORMAT_UNIT                0x04
+#define INQUIRY                    0x12
+#define MODE_SELECT6               0x15
+#define MODE_SENSE6                0x1A
+#define START_STOP_UNIT            0x1B
+#define MEDIA_REMOVAL              0x1E
+#define READ_FORMAT_CAPACITIES     0x23
+#define READ_CAPACITY              0x25
+#define READ10                     0x28
+#define WRITE10                    0x2A
+#define VERIFY10                   0x2F
+#define READ12                     0xA8
+#define WRITE12                    0xAA
+#define MODE_SELECT10              0x55
+#define MODE_SENSE10               0x5A
+
+// MSC class specific requests
+#define MSC_REQUEST_RESET          0xFF
+#define MSC_REQUEST_GET_MAX_LUN    0xFE
+
+#define DEFAULT_CONFIGURATION (1)
+
+// max packet size
+#define MAX_PACKET  MAX_PACKET_SIZE_EPBULK
+
+// CSW Status
+enum Status {
+    CSW_PASSED,
+    CSW_FAILED,
+    CSW_ERROR,
+};
+
+
+USBMSD::USBMSD(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
+    stage = READ_CBW;
+    memset((void *)&cbw, 0, sizeof(CBW));
+    memset((void *)&csw, 0, sizeof(CSW));
+    page = NULL;
+}
+
+USBMSD::~USBMSD() {
+    disconnect();
+}
+
+
+// Called in ISR context to process a class specific request
+bool USBMSD::USBCallback_request(void) {
+
+    bool success = false;
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+    static uint8_t maxLUN[1] = {0};
+
+    if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
+        switch (transfer->setup.bRequest) {
+            case MSC_REQUEST_RESET:
+                reset();
+                success = true;
+                break;
+            case MSC_REQUEST_GET_MAX_LUN:
+                transfer->remaining = 1;
+                transfer->ptr = maxLUN;
+                transfer->direction = DEVICE_TO_HOST;
+                success = true;
+                break;
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+
+bool USBMSD::connect(bool blocking) {
+    //disk initialization
+    if (disk_status() & NO_INIT) {
+        if (disk_initialize()) {
+            return false;
+        }
+    }
+
+    // get number of blocks
+    BlockCount = disk_sectors();
+
+    // get memory size
+    MemorySize = disk_size();
+
+    if (BlockCount > 0) {
+        BlockSize = MemorySize / BlockCount;
+        if (BlockSize != 0) {
+            free(page);
+            page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t));
+            if (page == NULL)
+                return false;
+        }
+    } else {
+        return false;
+    }
+
+    //connect the device
+    USBDevice::connect(blocking);
+    return true;
+}
+
+void USBMSD::disconnect() {
+    USBDevice::disconnect();
+    //De-allocate MSD page size:
+    free(page);
+    page = NULL;
+}
+
+void USBMSD::reset() {
+    stage = READ_CBW;
+}
+
+
+// Called in ISR context called when a data is received
+bool USBMSD::EPBULK_OUT_callback() {
+    uint32_t size = 0;
+    uint8_t buf[MAX_PACKET_SIZE_EPBULK];
+    readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK);
+    switch (stage) {
+            // the device has to decode the CBW received
+        case READ_CBW:
+            CBWDecode(buf, size);
+            break;
+
+            // the device has to receive data from the host
+        case PROCESS_CBW:
+            switch (cbw.CB[0]) {
+                case WRITE10:
+                case WRITE12:
+                    memoryWrite(buf, size);
+                    break;
+                case VERIFY10:
+                    memoryVerify(buf, size);
+                    break;
+            }
+            break;
+
+            // an error has occured: stall endpoint and send CSW
+        default:
+            stallEndpoint(EPBULK_OUT);
+            csw.Status = CSW_ERROR;
+            sendCSW();
+            break;
+    }
+
+    //reactivate readings on the OUT bulk endpoint
+    readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+    return true;
+}
+
+// Called in ISR context when a data has been transferred
+bool USBMSD::EPBULK_IN_callback() {
+    switch (stage) {
+
+            // the device has to send data to the host
+        case PROCESS_CBW:
+            switch (cbw.CB[0]) {
+                case READ10:
+                case READ12:
+                    memoryRead();
+                    break;
+            }
+            break;
+
+            //the device has to send a CSW
+        case SEND_CSW:
+            sendCSW();
+            break;
+
+        // the host has received the CSW -> we wait a CBW
+        case WAIT_CSW:
+            stage = READ_CBW;
+            break;
+
+        // an error has occured
+        default:
+            stallEndpoint(EPBULK_IN);
+            sendCSW();
+            break;
+    }
+    return true;
+}
+
+
+void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) {
+
+    if ((addr + size) > MemorySize) {
+        size = MemorySize - addr;
+        stage = ERROR;
+        stallEndpoint(EPBULK_OUT);
+    }
+
+    // we fill an array in RAM of 1 block before writing it in memory
+    for (int i = 0; i < size; i++)
+        page[addr%BlockSize + i] = buf[i];
+
+    // if the array is filled, write it in memory
+    if (!((addr + size)%BlockSize)) {
+        if (!(disk_status() & WRITE_PROTECT)) {
+            disk_write(page, addr/BlockSize, 1);
+        }
+    }
+
+    addr += size;
+    length -= size;
+    csw.DataResidue -= size;
+
+    if ((!length) || (stage != PROCESS_CBW)) {
+        csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED;
+        sendCSW();
+    }
+}
+
+void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) {
+    uint32_t n;
+
+    if ((addr + size) > MemorySize) {
+        size = MemorySize - addr;
+        stage = ERROR;
+        stallEndpoint(EPBULK_OUT);
+    }
+
+    // beginning of a new block -> load a whole block in RAM
+    if (!(addr%BlockSize))
+        disk_read(page, addr/BlockSize, 1);
+
+    // info are in RAM -> no need to re-read memory
+    for (n = 0; n < size; n++) {
+        if (page[addr%BlockSize + n] != buf[n]) {
+            memOK = false;
+            break;
+        }
+    }
+
+    addr += size;
+    length -= size;
+    csw.DataResidue -= size;
+
+    if ( !length || (stage != PROCESS_CBW)) {
+        csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED;
+        sendCSW();
+    }
+}
+
+
+bool USBMSD::inquiryRequest (void) {
+    uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01,
+                          36 - 4, 0x80, 0x00, 0x00,
+                          'M', 'B', 'E', 'D', '.', 'O', 'R', 'G',
+                          'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ',
+                          '1', '.', '0', ' ',
+                        };
+    if (!write(inquiry, sizeof(inquiry))) {
+        return false;
+    }
+    return true;
+}
+
+
+bool USBMSD::readFormatCapacity() {
+    uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08,
+                           (uint8_t)((BlockCount >> 24) & 0xff),
+                           (uint8_t)((BlockCount >> 16) & 0xff),
+                           (uint8_t)((BlockCount >> 8) & 0xff),
+                           (uint8_t)((BlockCount >> 0) & 0xff),
+
+                           0x02,
+                           (uint8_t)((BlockSize >> 16) & 0xff),
+                           (uint8_t)((BlockSize >> 8) & 0xff),
+                           (uint8_t)((BlockSize >> 0) & 0xff),
+                         };
+    if (!write(capacity, sizeof(capacity))) {
+        return false;
+    }
+    return true;
+}
+
+
+bool USBMSD::readCapacity (void) {
+    uint8_t capacity[] = {
+        (uint8_t)(((BlockCount - 1) >> 24) & 0xff),
+        (uint8_t)(((BlockCount - 1) >> 16) & 0xff),
+        (uint8_t)(((BlockCount - 1) >> 8) & 0xff),
+        (uint8_t)(((BlockCount - 1) >> 0) & 0xff),
+
+        (uint8_t)((BlockSize >> 24) & 0xff),
+        (uint8_t)((BlockSize >> 16) & 0xff),
+        (uint8_t)((BlockSize >> 8) & 0xff),
+        (uint8_t)((BlockSize >> 0) & 0xff),
+    };
+    if (!write(capacity, sizeof(capacity))) {
+        return false;
+    }
+    return true;
+}
+
+bool USBMSD::write (uint8_t * buf, uint16_t size) {
+
+    if (size >= cbw.DataLength) {
+        size = cbw.DataLength;
+    }
+    stage = SEND_CSW;
+
+    if (!writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) {
+        return false;
+    }
+
+    csw.DataResidue -= size;
+    csw.Status = CSW_PASSED;
+    return true;
+}
+
+
+bool USBMSD::modeSense6 (void) {
+    uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 };
+    if (!write(sense6, sizeof(sense6))) {
+        return false;
+    }
+    return true;
+}
+
+void USBMSD::sendCSW() {
+    csw.Signature = CSW_Signature;
+    writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK);
+    stage = WAIT_CSW;
+}
+
+bool USBMSD::requestSense (void) {
+    uint8_t request_sense[] = {
+        0x70,
+        0x00,
+        0x05,   // Sense Key: illegal request
+        0x00,
+        0x00,
+        0x00,
+        0x00,
+        0x0A,
+        0x00,
+        0x00,
+        0x00,
+        0x00,
+        0x30,
+        0x01,
+        0x00,
+        0x00,
+        0x00,
+        0x00,
+    };
+
+    if (!write(request_sense, sizeof(request_sense))) {
+        return false;
+    }
+
+    return true;
+}
+
+void USBMSD::fail() {
+    csw.Status = CSW_FAILED;
+    sendCSW();
+}
+
+
+void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) {
+    if (size == sizeof(cbw)) {
+        memcpy((uint8_t *)&cbw, buf, size);
+        if (cbw.Signature == CBW_Signature) {
+            csw.Tag = cbw.Tag;
+            csw.DataResidue = cbw.DataLength;
+            if ((cbw.CBLength <  1) || (cbw.CBLength > 16) ) {
+                fail();
+            } else {
+                switch (cbw.CB[0]) {
+                    case TEST_UNIT_READY:
+                        testUnitReady();
+                        break;
+                    case REQUEST_SENSE:
+                        requestSense();
+                        break;
+                    case INQUIRY:
+                        inquiryRequest();
+                        break;
+                    case MODE_SENSE6:
+                        modeSense6();
+                        break;
+                    case READ_FORMAT_CAPACITIES:
+                        readFormatCapacity();
+                        break;
+                    case READ_CAPACITY:
+                        readCapacity();
+                        break;
+                    case READ10:
+                    case READ12:
+                        if (infoTransfer()) {
+                            if ((cbw.Flags & 0x80)) {
+                                stage = PROCESS_CBW;
+                                memoryRead();
+                            } else {
+                                stallEndpoint(EPBULK_OUT);
+                                csw.Status = CSW_ERROR;
+                                sendCSW();
+                            }
+                        }
+                        break;
+                    case WRITE10:
+                    case WRITE12:
+                        if (infoTransfer()) {
+                            if (!(cbw.Flags & 0x80)) {
+                                stage = PROCESS_CBW;
+                            } else {
+                                stallEndpoint(EPBULK_IN);
+                                csw.Status = CSW_ERROR;
+                                sendCSW();
+                            }
+                        }
+                        break;
+                    case VERIFY10:
+                        if (!(cbw.CB[1] & 0x02)) {
+                            csw.Status = CSW_PASSED;
+                            sendCSW();
+                            break;
+                        }
+                        if (infoTransfer()) {
+                            if (!(cbw.Flags & 0x80)) {
+                                stage = PROCESS_CBW;
+                                memOK = true;
+                            } else {
+                                stallEndpoint(EPBULK_IN);
+                                csw.Status = CSW_ERROR;
+                                sendCSW();
+                            }
+                        }
+                        break;
+                    case MEDIA_REMOVAL:
+                        csw.Status = CSW_PASSED;
+                        sendCSW();
+                        break;
+                    default:
+                        fail();
+                        break;
+                }
+            }
+        }
+    }
+}
+
+void USBMSD::testUnitReady (void) {
+
+    if (cbw.DataLength != 0) {
+        if ((cbw.Flags & 0x80) != 0) {
+            stallEndpoint(EPBULK_IN);
+        } else {
+            stallEndpoint(EPBULK_OUT);
+        }
+    }
+
+    csw.Status = CSW_PASSED;
+    sendCSW();
+}
+
+
+void USBMSD::memoryRead (void) {
+    uint32_t n;
+
+    n = (length > MAX_PACKET) ? MAX_PACKET : length;
+
+    if ((addr + n) > MemorySize) {
+        n = MemorySize - addr;
+        stage = ERROR;
+    }
+
+    // we read an entire block
+    if (!(addr%BlockSize))
+        disk_read(page, addr/BlockSize, 1);
+
+    // write data which are in RAM
+    writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK);
+
+    addr += n;
+    length -= n;
+
+    csw.DataResidue -= n;
+
+    if ( !length || (stage != PROCESS_CBW)) {
+        csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
+        stage = (stage == PROCESS_CBW) ? SEND_CSW : stage;
+    }
+}
+
+
+bool USBMSD::infoTransfer (void) {
+    uint32_t n;
+
+    // Logical Block Address of First Block
+    n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] <<  8) | (cbw.CB[5] <<  0);
+
+    addr = n * BlockSize;
+
+    // Number of Blocks to transfer
+    switch (cbw.CB[0]) {
+        case READ10:
+        case WRITE10:
+        case VERIFY10:
+            n = (cbw.CB[7] <<  8) | (cbw.CB[8] <<  0);
+            break;
+
+        case READ12:
+        case WRITE12:
+            n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] <<  8) | (cbw.CB[9] <<  0);
+            break;
+    }
+
+    length = n * BlockSize;
+
+    if (!cbw.DataLength) {              // host requests no data
+        csw.Status = CSW_FAILED;
+        sendCSW();
+        return false;
+    }
+
+    if (cbw.DataLength != length) {
+        if ((cbw.Flags & 0x80) != 0) {
+            stallEndpoint(EPBULK_IN);
+        } else {
+            stallEndpoint(EPBULK_OUT);
+        }
+
+        csw.Status = CSW_FAILED;
+        sendCSW();
+        return false;
+    }
+
+    return true;
+}
+
+
+
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) {
+    if (configuration != DEFAULT_CONFIGURATION) {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
+    addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+
+    //activate readings
+    readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+    return true;
+}
+
+
+uint8_t * USBMSD::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x08,                           //bLength
+        STRING_DESCRIPTOR,              //bDescriptorType 0x03
+        'M',0,'S',0,'D',0               //bString iInterface - MSD
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBMSD::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x12,                                           //bLength
+        STRING_DESCRIPTOR,                              //bDescriptorType 0x03
+        'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio
+    };
+    return stringIproductDescriptor;
+}
+
+
+uint8_t * USBMSD::configurationDesc() {
+    static uint8_t configDescriptor[] = {
+
+        // Configuration 1
+        9,      // bLength
+        2,      // bDescriptorType
+        LSB(9 + 9 + 7 + 7), // wTotalLength
+        MSB(9 + 9 + 7 + 7),
+        0x01,   // bNumInterfaces
+        0x01,   // bConfigurationValue: 0x01 is used to select this configuration
+        0x00,   // iConfiguration: no string to describe this configuration
+        0xC0,   // bmAttributes
+        100,    // bMaxPower, device power consumption is 100 mA
+
+        // Interface 0, Alternate Setting 0, MSC Class
+        9,      // bLength
+        4,      // bDescriptorType
+        0x00,   // bInterfaceNumber
+        0x00,   // bAlternateSetting
+        0x02,   // bNumEndpoints
+        0x08,   // bInterfaceClass
+        0x06,   // bInterfaceSubClass
+        0x50,   // bInterfaceProtocol
+        0x04,   // iInterface
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                          // bLength
+        5,                          // bDescriptorType
+        PHY_TO_DESC(EPBULK_IN),     // bEndpointAddress
+        0x02,                       // bmAttributes (0x02=bulk)
+        LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
+        0,                          // bInterval
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                          // bLength
+        5,                          // bDescriptorType
+        PHY_TO_DESC(EPBULK_OUT),    // bEndpointAddress
+        0x02,                       // bmAttributes (0x02=bulk)
+        LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
+        0                           // bInterval
+    };
+    return configDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBMSD/USBMSD.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,251 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef USBMSD_H
+#define USBMSD_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBDevice.h"
+
+/**
+ * USBMSD class: generic class in order to use all kinds of blocks storage chip
+ *
+ * Introduction
+ *
+ * The USBMSD implements the MSD protocol. It permits to access a memory chip (flash, sdcard,...)
+ * from a computer over USB. But this class doesn't work standalone, you need to subclass this class
+ * and define virtual functions which are called in USBMSD.
+ *
+ * How to use this class with your chip ?
+ *
+ * You have to inherit and define some pure virtual functions (mandatory step):
+ *   - virtual int disk_read(char * data, int block): function to read a block
+ *   - virtual int disk_write(const char * data, int block): function to write a block
+ *   - virtual int disk_initialize(): function to initialize the memory
+ *   - virtual int disk_sectors(): return the number of blocks
+ *   - virtual int disk_size(): return the memory size
+ *   - virtual int disk_status(): return the status of the storage chip (0: OK, 1: not initialized, 2: no medium in the drive, 4: write protection)
+ *
+ * All functions names are compatible with the fat filesystem library. So you can imagine using your own class with
+ * USBMSD and the fat filesystem library in the same program. Just be careful because there are two different parts which
+ * will access the sd card. You can do a master/slave system using the disk_status method.
+ *
+ * Once these functions defined, you can call connect() (at the end of the constructor of your class for instance)
+ * of USBMSD to connect your mass storage device. connect() will first call disk_status() to test the status of the disk.
+ * If disk_status() returns 1 (disk not initialized), then disk_initialize() is called. After this step, connect() will collect information
+ * such as the number of blocks and the memory size.
+ */
+class USBMSD: public USBDevice {
+public:
+
+    /**
+    * Constructor
+    *
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBMSD(uint16_t vendor_id = 0x0703, uint16_t product_id = 0x0104, uint16_t product_release = 0x0001);
+
+    /**
+    * Connect the USB MSD device. Establish disk initialization before really connect the device.
+    *
+    * @param blocking if not configured
+    * @returns true if successful
+    */
+    bool connect(bool blocking = true);
+
+    /**
+    * Disconnect the USB MSD device.
+    */
+    void disconnect();
+
+    /**
+    * Destructor
+    */
+    ~USBMSD();
+
+protected:
+
+    /*
+    * read one or more blocks on a storage chip
+    *
+    * @param data pointer where will be stored read data
+    * @param block starting block number
+    * @param count number of blocks to read
+    * @returns 0 if successful
+    */
+    virtual int disk_read(uint8_t* data, uint64_t block, uint8_t count) = 0;
+
+    /*
+    * write one or more blocks on a storage chip
+    *
+    * @param data data to write
+    * @param block starting block number
+    * @param count number of blocks to write
+    * @returns 0 if successful
+    */
+    virtual int disk_write(const uint8_t* data, uint64_t block, uint8_t count) = 0;
+
+    /*
+    * Disk initilization
+    */
+    virtual int disk_initialize() = 0;
+
+    /*
+    * Return the number of blocks
+    *
+    * @returns number of blocks
+    */
+    virtual uint64_t disk_sectors() = 0;
+
+    /*
+    * Return memory size
+    *
+    * @returns memory size
+    */
+    virtual uint64_t disk_size() = 0;
+
+
+    /*
+    * To check the status of the storage chip
+    *
+    * @returns status: 0: OK, 1: disk not initialized, 2: no medium in the drive, 4: write protected
+    */
+    virtual int disk_status() = 0;
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+    /*
+    * Callback called when a packet is received
+    */
+    virtual bool EPBULK_OUT_callback();
+
+    /*
+    * Callback called when a packet has been sent
+    */
+    virtual bool EPBULK_IN_callback();
+
+    /*
+    * Set configuration of device. Add endpoints
+    */
+    virtual bool USBCallback_setConfiguration(uint8_t configuration);
+
+    /*
+    * Callback called to process class specific requests
+    */
+    virtual bool USBCallback_request();
+
+
+private:
+
+    // MSC Bulk-only Stage
+    enum Stage {
+        READ_CBW,     // wait a CBW
+        ERROR,        // error
+        PROCESS_CBW,  // process a CBW request
+        SEND_CSW,     // send a CSW
+        WAIT_CSW,     // wait that a CSW has been effectively sent
+    };
+
+    // Bulk-only CBW
+    typedef struct {
+        uint32_t Signature;
+        uint32_t Tag;
+        uint32_t DataLength;
+        uint8_t  Flags;
+        uint8_t  LUN;
+        uint8_t  CBLength;
+        uint8_t  CB[16];
+    } PACKED CBW;
+
+    // Bulk-only CSW
+    typedef struct {
+        uint32_t Signature;
+        uint32_t Tag;
+        uint32_t DataResidue;
+        uint8_t  Status;
+    } PACKED CSW;
+
+    //state of the bulk-only state machine
+    Stage stage;
+
+    // current CBW
+    CBW cbw;
+
+    // CSW which will be sent
+    CSW csw;
+
+    // addr where will be read or written data
+    uint32_t addr;
+
+    // length of a reading or writing
+    uint32_t length;
+
+    // memory OK (after a memoryVerify)
+    bool memOK;
+
+    // cache in RAM before writing in memory. Useful also to read a block.
+    uint8_t * page;
+
+    int BlockSize;
+    uint64_t MemorySize;
+    uint64_t BlockCount;
+
+    void CBWDecode(uint8_t * buf, uint16_t size);
+    void sendCSW (void);
+    bool inquiryRequest (void);
+    bool write (uint8_t * buf, uint16_t size);
+    bool readFormatCapacity();
+    bool readCapacity (void);
+    bool infoTransfer (void);
+    void memoryRead (void);
+    bool modeSense6 (void);
+    void testUnitReady (void);
+    bool requestSense (void);
+    void memoryVerify (uint8_t * buf, uint16_t size);
+    void memoryWrite (uint8_t * buf, uint16_t size);
+    void reset();
+    void fail();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBSerial/CircBuffer.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef CIRCBUFFER_H
+#define CIRCBUFFER_H
+
+template <class T, int Size>
+class CircBuffer {
+public:
+    CircBuffer():write(0), read(0){}
+    bool isFull() {
+        return ((write + 1) % size == read);
+    };
+
+    bool isEmpty() {
+        return (read == write);
+    };
+
+    void queue(T k) {
+        if (isFull()) {
+            read++;
+            read %= size;
+        }
+        buf[write++] = k;
+        write %= size;
+    }
+
+    uint16_t available() {
+        return (write >= read) ? write - read : size - read + write;
+    };
+
+    bool dequeue(T * c) {
+        bool empty = isEmpty();
+        if (!empty) {
+            *c = buf[read++];
+            read %= size;
+        }
+        return(!empty);
+    };
+
+private:
+    volatile uint16_t write;
+    volatile uint16_t read;
+    static const int size = Size+1;  //a modern optimizer should be able to remove this so it uses no ram.
+    T buf[Size+1];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBSerial/USBCDC.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,286 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBCDC.h"
+
+static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08};
+
+#define DEFAULT_CONFIGURATION (1)
+
+#define CDC_SET_LINE_CODING        0x20
+#define CDC_GET_LINE_CODING        0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+
+// Control Line State bits
+#define CLS_DTR   (1 << 0)
+#define CLS_RTS   (1 << 1)
+
+#define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK
+
+USBCDC::USBCDC(uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking): USBDevice(vendor_id, product_id, product_release) {
+    terminal_connected = false;
+    USBDevice::connect(connect_blocking);
+}
+
+bool USBCDC::USBCallback_request(void) {
+    /* Called in ISR context */
+
+    bool success = false;
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+
+    /* Process class-specific requests */
+
+    if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
+        switch (transfer->setup.bRequest) {
+            case CDC_GET_LINE_CODING:
+                transfer->remaining = 7;
+                transfer->ptr = cdc_line_coding;
+                transfer->direction = DEVICE_TO_HOST;
+                success = true;
+                break;
+            case CDC_SET_LINE_CODING:
+                transfer->remaining = 7;
+                transfer->notify = true;
+                success = true;
+                break;
+            case CDC_SET_CONTROL_LINE_STATE:
+                if (transfer->setup.wValue & CLS_DTR) {
+                    terminal_connected = true;
+                } else {
+                    terminal_connected = false;
+                }
+                success = true;
+                break;
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+void USBCDC::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) {
+    // Request of setting line coding has 7 bytes
+    if (length != 7) {
+        return;
+    }
+
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+
+    /* Process class-specific requests */
+    if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
+        if (transfer->setup.bRequest == CDC_SET_LINE_CODING) {
+            if (memcmp(cdc_line_coding, buf, 7)) {
+                memcpy(cdc_line_coding, buf, 7);
+
+                int baud = buf[0] + (buf[1] << 8)
+                         + (buf[2] << 16) + (buf[3] << 24);
+                int stop = buf[4];
+                int bits = buf[6];
+                int parity = buf[5];
+
+                lineCodingChanged(baud, bits, parity, stop);
+            }
+        }
+    }
+}
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBCDC::USBCallback_setConfiguration(uint8_t configuration) {
+    if (configuration != DEFAULT_CONFIGURATION) {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
+    addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
+    addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+
+    // We activate the endpoint to be able to recceive data
+    readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+    return true;
+}
+
+bool USBCDC::send(uint8_t * buffer, uint32_t size) {
+    return USBDevice::write(EPBULK_IN, buffer, size, MAX_CDC_REPORT_SIZE);
+}
+
+bool USBCDC::readEP(uint8_t * buffer, uint32_t * size) {
+    if (!USBDevice::readEP(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
+        return false;
+    if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE))
+        return false;
+    return true;
+}
+
+bool USBCDC::readEP_NB(uint8_t * buffer, uint32_t * size) {
+    if (!USBDevice::readEP_NB(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
+        return false;
+    if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE))
+        return false;
+    return true;
+}
+
+
+uint8_t * USBCDC::deviceDesc() {
+    static uint8_t deviceDescriptor[] = {
+        18,                   // bLength
+        1,                    // bDescriptorType
+        0x10, 0x01,           // bcdUSB
+        2,                    // bDeviceClass
+        0,                    // bDeviceSubClass
+        0,                    // bDeviceProtocol
+        MAX_PACKET_SIZE_EP0,  // bMaxPacketSize0
+        (uint8_t)(LSB(VENDOR_ID)), (uint8_t)(MSB(VENDOR_ID)),  // idVendor
+        (uint8_t)(LSB(PRODUCT_ID)), (uint8_t)(MSB(PRODUCT_ID)),// idProduct
+        0x00, 0x01,           // bcdDevice
+        1,                    // iManufacturer
+        2,                    // iProduct
+        3,                    // iSerialNumber
+        1                     // bNumConfigurations
+    };
+    return deviceDescriptor;
+}
+
+uint8_t * USBCDC::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x08,
+        STRING_DESCRIPTOR,
+        'C',0,'D',0,'C',0,
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBCDC::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,
+        STRING_DESCRIPTOR,
+        'C',0,'D',0,'C',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0
+    };
+    return stringIproductDescriptor;
+}
+
+
+#define CONFIG1_DESC_SIZE (9+8+9+5+5+4+5+7+9+7+7)
+
+uint8_t * USBCDC::configurationDesc() {
+    static uint8_t configDescriptor[] = {
+        // configuration descriptor
+        9,                      // bLength
+        2,                      // bDescriptorType
+        LSB(CONFIG1_DESC_SIZE), // wTotalLength
+        MSB(CONFIG1_DESC_SIZE),
+        2,                      // bNumInterfaces
+        1,                      // bConfigurationValue
+        0,                      // iConfiguration
+        0x80,                   // bmAttributes
+        50,                     // bMaxPower
+
+        // IAD to associate the two CDC interfaces
+        0x08,                   // bLength
+        0x0b,                   // bDescriptorType
+        0x00,                   // bFirstInterface
+        0x02,                   // bInterfaceCount
+        0x02,                   // bFunctionClass
+        0x02,                   // bFunctionSubClass
+        0,                      // bFunctionProtocol
+        0,                      // iFunction
+
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                      // bLength
+        4,                      // bDescriptorType
+        0,                      // bInterfaceNumber
+        0,                      // bAlternateSetting
+        1,                      // bNumEndpoints
+        0x02,                   // bInterfaceClass
+        0x02,                   // bInterfaceSubClass
+        0x01,                   // bInterfaceProtocol
+        0,                      // iInterface
+
+        // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x00,                   // bDescriptorSubtype
+        0x10, 0x01,             // bcdCDC
+
+        // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x01,                   // bDescriptorSubtype
+        0x03,                   // bmCapabilities
+        1,                      // bDataInterface
+
+        // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
+        4,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x02,                   // bDescriptorSubtype
+        0x06,                   // bmCapabilities
+
+        // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x06,                   // bDescriptorSubtype
+        0,                      // bMasterInterface
+        1,                      // bSlaveInterface0
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes (0x03=intr)
+        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
+        16,                             // bInterval
+
+
+
+
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                          // bLength
+        4,                          // bDescriptorType
+        1,                          // bInterfaceNumber
+        0,                          // bAlternateSetting
+        2,                          // bNumEndpoints
+        0x0A,                       // bInterfaceClass
+        0x00,                       // bInterfaceSubClass
+        0x00,                       // bInterfaceProtocol
+        0,                          // iInterface
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        ENDPOINT_DESCRIPTOR_LENGTH, // bLength
+        ENDPOINT_DESCRIPTOR,        // bDescriptorType
+        PHY_TO_DESC(EPBULK_IN),     // bEndpointAddress
+        E_BULK,                     // bmAttributes (0x02=bulk)
+        LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
+        0,                          // bInterval
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        ENDPOINT_DESCRIPTOR_LENGTH, // bLength
+        ENDPOINT_DESCRIPTOR,        // bDescriptorType
+        PHY_TO_DESC(EPBULK_OUT),    // bEndpointAddress
+        E_BULK,                     // bmAttributes (0x02=bulk)
+        LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
+        MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
+        0                           // bInterval
+    };
+    return configDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBSerial/USBCDC.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,124 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBCDC_H
+#define USBCDC_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBDevice.h"
+
+class USBCDC: public USBDevice {
+public:
+
+    /*
+    * Constructor
+    *
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    * @param connect_blocking define if the connection must be blocked if USB not plugged in
+    */
+    USBCDC(uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking);
+	
+	volatile bool terminal_connected;
+
+protected:
+
+    /*
+    * Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the device descriptor
+    */
+    virtual uint8_t * deviceDesc();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+    /*
+    * Send a buffer
+    *
+    * @param endpoint endpoint which will be sent the buffer
+    * @param buffer buffer to be sent
+    * @param size length of the buffer
+    * @returns true if successful
+    */
+    bool send(uint8_t * buffer, uint32_t size);
+
+    /*
+    * Read a buffer from a certain endpoint. Warning: blocking
+    *
+    * @param endpoint endpoint to read
+    * @param buffer buffer where will be stored bytes
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP(uint8_t * buffer, uint32_t * size);
+
+    /*
+    * Read a buffer from a certain endpoint. Warning: non blocking
+    *
+    * @param endpoint endpoint to read
+    * @param buffer buffer where will be stored bytes
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP_NB(uint8_t * buffer, uint32_t * size);
+
+    /*
+    * Called by USBCallback_requestCompleted when CDC line coding is changed
+    * Warning: Called in ISR
+    *
+    * @param baud The baud rate
+    * @param bits The number of bits in a word (5-8)
+    * @param parity The parity
+    * @param stop The number of stop bits (1 or 2)
+    */
+    virtual void lineCodingChanged(int baud, int bits, int parity, int stop) {};
+
+protected:
+    virtual bool USBCallback_request();
+    virtual void USBCallback_requestCompleted(uint8_t *buf, uint32_t length);
+    virtual bool USBCallback_setConfiguration(uint8_t configuration);
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBSerial/USBSerial.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,67 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBSerial.h"
+
+int USBSerial::_putc(int c) {
+    if (!terminal_connected)
+        return 0;
+    send((uint8_t *)&c, 1);
+    return 1;
+}
+
+int USBSerial::_getc() {
+    uint8_t c = 0;
+    while (buf.isEmpty());
+    buf.dequeue(&c);
+    return c;
+}
+
+
+bool USBSerial::writeBlock(uint8_t * buf, uint16_t size) {
+    if(size > MAX_PACKET_SIZE_EPBULK) {
+        return false;
+    }
+    if(!send(buf, size)) {
+        return false;
+    }
+    return true;
+}
+
+
+
+bool USBSerial::EPBULK_OUT_callback() {
+    uint8_t c[65];
+    uint32_t size = 0;
+
+    //we read the packet received and put it on the circular buffer
+    readEP(c, &size);
+    for (uint32_t i = 0; i < size; i++) {
+        buf.queue(c[i]);
+    }
+
+    //call a potential handler
+    rx.call();
+
+    return true;
+}
+
+uint8_t USBSerial::available() {
+    return buf.available();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/USBDevice/USBSerial/USBSerial.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,161 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBSERIAL_H
+#define USBSERIAL_H
+
+#include "USBCDC.h"
+#include "Stream.h"
+#include "CircBuffer.h"
+
+
+/**
+* USBSerial example
+*
+* @code
+* #include "mbed.h"
+* #include "USBSerial.h"
+*
+* //Virtual serial port over USB
+* USBSerial serial;
+*
+* int main(void) {
+*
+*    while(1)
+*    {
+*        serial.printf("I am a virtual serial port\n");
+*        wait(1);
+*    }
+* }
+* @endcode
+*/
+class USBSerial: public USBCDC, public Stream {
+public:
+
+    /**
+    *   Constructor
+    *
+    * @param vendor_id Your vendor_id (default: 0x1f00)
+    * @param product_id Your product_id (default: 0x2012)
+    * @param product_release Your preoduct_release (default: 0x0001)
+    * @param connect_blocking define if the connection must be blocked if USB not plugged in
+    *
+    */
+    USBSerial(uint16_t vendor_id = 0x1f00, uint16_t product_id = 0x2012, uint16_t product_release = 0x0001, bool connect_blocking = true): USBCDC(vendor_id, product_id, product_release, connect_blocking){
+        settingsChangedCallback = 0;
+    };
+
+
+    /**
+    * Send a character. You can use puts, printf.
+    *
+    * @param c character to be sent
+    * @returns true if there is no error, false otherwise
+    */
+    virtual int _putc(int c);
+
+    /**
+    * Read a character: blocking
+    *
+    * @returns character read
+    */
+    virtual int _getc();
+
+    /**
+    * Check the number of bytes available.
+    *
+    * @returns the number of bytes available
+    */
+    uint8_t available();
+
+    /** Determine if there is a character available to read
+     *
+     *  @returns
+     *    1 if there is a character available to read,
+     *    0 otherwise
+     */
+    int readable() { return available() ? 1 : 0; }
+
+    /** Determine if there is space available to write a character
+     *
+     *  @returns
+     *    1 if there is space to write a character,
+     *    0 otherwise
+     */
+    int writeable() { return 1; } // always return 1, for write operation is blocking
+
+    /**
+    * Write a block of data.
+    *
+    * For more efficiency, a block of size 64 (maximum size of a bulk endpoint) has to be written.
+    *
+    * @param buf pointer on data which will be written
+    * @param size size of the buffer. The maximum size of a block is limited by the size of the endpoint (64 bytes)
+    *
+    * @returns true if successfull
+    */
+    bool writeBlock(uint8_t * buf, uint16_t size);
+
+    /**
+     *  Attach a member function to call when a packet is received.
+     *
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void attach(T* tptr, void (T::*mptr)(void)) {
+        if((mptr != NULL) && (tptr != NULL)) {
+            rx.attach(tptr, mptr);
+        }
+    }
+
+    /**
+     * Attach a callback called when a packet is received
+     *
+     * @param fptr function pointer
+     */
+    void attach(void (*fptr)(void)) {
+        if(fptr != NULL) {
+            rx.attach(fptr);
+        }
+    }
+
+    /**
+     * Attach a callback to call when serial's settings are changed.
+     *
+     * @param fptr function pointer
+     */
+    void attach(void (*fptr)(int baud, int bits, int parity, int stop)) {
+        settingsChangedCallback = fptr;
+    }
+
+protected:
+    virtual bool EPBULK_OUT_callback();
+    virtual void lineCodingChanged(int baud, int bits, int parity, int stop){
+        if (settingsChangedCallback) {
+            settingsChangedCallback(baud, bits, parity, stop);
+        }
+    }
+
+private:
+    FunctionPointer rx;
+    CircBuffer<uint8_t,128> buf;
+    void (*settingsChangedCallback)(int baud, int bits, int parity, int stop);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SHComm/SHComm.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,1411 @@
+/*
+ * SHcomm.cpp
+ *
+ *  Created on: Nov 16, 2018
+ *      Author: Yagmur.Gok
+ */
+
+/*
+#ifdef __cplusplus
+extern "C" {
+#endif
+*/
+
+#include <events/mbed_events.h>
+#include <mbed.h>
+#include "mbed.h"
+
+#include "SHComm.h"
+
+
+#define SS_I2C_8BIT_SLAVE_ADDR      0xAA
+#define SENSORHUB_I2C_ADRESS        SS_I2C_8BIT_SLAVE_ADDR
+
+#define ENABLED   ((int)(1))
+#define DISABLED  ((int)(0))
+
+#define SS_DUMP_REG_SLEEP_MS        (100)
+#define SS_ENABLE_SENSOR_SLEEP_MS   (20)
+#define SS_DEFAULT_CMD_SLEEP_MS     (2)
+#define SS_WAIT_BETWEEN_TRIES_MS    (2)
+#define SS_CMD_WAIT_PULLTRANS_MS    (5)
+#define SS_FEEDFIFO_CMD_SLEEP_MS	(30)
+
+
+#define SS_DEFAULT_RETRIES       ((int) (4))
+#define SS_ZERO_DELAY               0
+#define SS_ZERO_BYTES               0
+
+
+/*define sample size of algorithm and raw sensor data in bytes*/
+#define SH_ALGO_WHRM_SAMPLE_DATABYTES  4
+#define SH_ALGO_SP02_SAMPLE_DATABYTES  4
+
+
+/*define command sequences given in Maxim ME32664 user manual*/
+#define SH_GET_HUB_STATUS_CMDSEQ               {0x00,0x00}
+#define SH_SET_OPERATING_MODE_CMDSEQ(opMode)   {0x01,0x00,opMode}
+       #define SH_SET_OPERATING_MODE_BOOTLOADER_CMDSEQ      {0x02,0x00,0x08}
+       #define SH_SET_OPERATING_MODE_APPLICATION_CMDSEQ     {0x02,0x00,0x00}
+       #define SH_SET_OPERATING_MODE_RESET_CMDSEQ           {0x02,0x00,0x02}
+#define SH_GET_OPERATING_MODE_CMDSEQ           {0x02,0x00}
+
+#define SH_SET_OUTPUT_MODE_CMDSEQ( outMode)    {0x10,0x00, outMode}
+	   #define SH_SET_OUTMODE_NODATA_CMDSEQ                 {0x10,0x00,0x00}
+       #define SH_SET_OUTMODE_SENSORDATA_CMDSEQ             {0x10,0x00,0x01}
+       #define SH_SET_OUTMODE_ALGODATA_CMDSEQ               {0x10,0x00,0x02}
+       #define SH_SET_OUTMODE_PAUSE_CMDSEQ                  {0x10,0x00,0x04}
+       #define SH_SET_OUTMODE_SENSAMPLECNT_CMDSEQ           {0x10,0x00,0x05}
+	   #define SH_SET_OUTMODE_ALGOSAMPLECNT_CMDSEQ          {0x10,0x00,0x06}
+       #define SH_SET_OUTMODE_ALGOSENSAMPLECNT_CMDSEQ       {0x10,0x00,0x07}
+
+#define SH_GET_OUTPUT_MODE_CMDSEQ             {0x11,0x00}
+
+#define SH_DFIFO_SET_INT_THRESHOLD_CMDSEQ( ucThreshold )    {0x10,0x01,ucThreshold}
+#define SH_DFIFO_GET_INT_THRESHOLD_CMDSEQ                   {0x11,0x01}
+
+#define SH_DFIFO_GET_NSAMPLES_CMDSEQ          {0x12,0x00}
+#define SH_DFIFO_PULL_SAMPLE_CMDSEQ           {0x12,0x01}
+#define SH_GET_EXTINPUT_FIFOSZ_CMDSEQ         {0x13,0x01}
+#define SH_GET_SAMPLEBYTECNT_INPUTFIFO_CMDSEQ {0x13,0x04}
+#define SH_FEED_TO_INPUTFIFO_CMDSEQ           {0x14,0x00}
+
+#define SH_WRITE_SENSORREG_CMDSEQ( sensorIdx , regAddr )    { 0x40, sensorIdx , regAddr}
+#define SH_READ_SENSORREG_CMDSEQ( sensorIdx , regAddr )     { 0x41, sensorIdx , regAddr}
+#define SH_READ_AFE_ATTRIBUTES_CMDSEQ(sensorIdx)            { 0x42, sensorIdx}
+#define SH_READ_ALLREGISTERS_CMDSEQ(sensorIdx)              { 0x43, sensorIdx}
+
+#define SH_ENABLE_SENSOR_CMDSEQ(sensorIdx , extMode)    {0x44, sensorIdx, 0x01 , extMode }
+#define SH_DISABLE_SENSOR_CMDSEQ(sensorIdx)   {0x44, sensorIdx, 0x00}
+
+
+#define SH_AGC_SET_ADCRANGE_CMDSEQ( uiPercentage)           {0x50, 0x00, 0x00 , uiPercentage}
+#define SH_AGC_SET_STEPSZ_CMDSEQ( uiPercentage)             {0x50, 0x00, 0x01 , uiPercentage}
+#define SH_AGC_SET_SENSITIVITY_CMDSEQ( uiPercentage)        {0x50, 0x00, 0x02 , uiPercentage}
+#define SH_AGC_SET_NSAMPLESAVRAGING_CMDSEQ( ucNsamples)     {0x50, 0x00, 0x03 , uiNsamples}
+#define SH_WHRM_SET_SAMPRATE_CMDSEQ( ucNsamples)            {0x50, 0x02, 0x03 , uiNsamples}
+
+
+#define SH_ENABLE_ALGO_CMDSEQ( algoIdx)      { 0x52, algoIdx , 0x01}
+#define SH_DISABLE_ALGO_CMDSEQ( algoIdx)     { 0x52, algoIdx , 0x00}
+
+#define SH_SET_ALGO_CONFIGURATION_CMDSEQ( algoIdx, cgfIdx)  { 0x50 , algoIdx, cgfIdx }
+#define SH_GET_ALGO_CONFIGURATION_CMDSEQ( algoIdx, cgfIdx)  { 0x51 , algoIdx, cgfIdx }
+
+#define SH_COMM_CHECK_CMDSEQ                 {0xFF, 0x00}
+
+
+
+//phase2 additions
+#define SH_CHECKIF_BOOTLDRMODE_CMDSEQ   { 0x02, 0x00 }
+#define SH_SELFTEST_CMDSEQ(idx)         { 0x70, (uint8_t)idx }
+#define SH_EXIT_BOOTLDRMODE_CMDSEQ      { 0x01, 0x00 }
+#define SH_GETLOGSIZE_CMDSEQ            { 0x90, 0x01 }
+#define SH_READHUBLOGS_CMDSEQ           { 0x90, 0x00 }
+
+#define SH_GET_BOOTLDRPAGESIZE_CMDSEQ   { 0x81, 0x01 }
+#define SH_SET_BOOTLDRPAGECOUNT_CMDSEQ  { 0x80, 0x02 }
+
+#define BOOTLOADER_MAX_PAGE_SIZE 8192
+
+/* BOOTLOADER HOST */
+#define EBL_CMD_TRIGGER_MODE	0
+#define EBL_GPIO_TRIGGER_MODE	1
+
+
+
+/*
+ *   define the "platform specific" hardware interface which SSinterface requires:
+ *   1. master i2c port
+ *   2. interrupt attachable I/O pin (mfio)
+ *   3. I/O pin for reset
+ *   Note: Definitions below are for MAX32630FTR Pagasus board . Modify for your platform.
+ **/
+
+I2C *m_i2cBus;                /*i2c  bus sensor hub is connected to*/
+
+PinName ss_mfio(P5_4);             /* platform specific mfio event pin */
+PinName ss_reset(P5_6);            /* platform specific sensor hub reset pin */
+DigitalInOut mfio_pin(ss_mfio);    /* mfio pin mode be I/O */
+DigitalInOut reset_pin(ss_reset);  /* reset pin mode be I/O */
+InterruptIn irq_pin(ss_mfio);      /* define mfio pin interrupt attachable*/
+
+
+/*
+ * SSI API funcions
+ * NOTE: Generic functions for any platform.
+ *       exceptions: below needs needs modification according to platform and HAL drivers
+ *       1. Hard reset function
+ *       2. Enable/disable mfio event interrput
+ *       3. mfio pin interrupt routine
+ *
+ * **/
+
+/*global buffer for sensor i2c commands+data*/
+uint8_t sh_write_buf[512];
+static volatile bool m_irq_received_ = false;
+static volatile bool mfio_int_happened = false;
+
+/* sensor hub states */
+static bool sc_en     = false;
+static int data_type  = 0;
+static int is_sensor_enabled[SS_MAX_SUPPORTED_SENSOR_NUM] = {0};
+static int is_algo_enabled[SS_MAX_SUPPORTED_ALGO_NUM]     = {0};
+static int enabled_algo_mode[SS_MAX_SUPPORTED_ALGO_NUM]   = {0};
+static int sensor_sample_sz[SS_MAX_SUPPORTED_SENSOR_NUM]  = {0};
+static int algo_sample_sz[SS_MAX_SUPPORTED_ALGO_NUM]      = {0};
+
+/* Mode to control sesnor hub resets. ie via GPIO based hard reset or Command based soft reset*/
+static uint8_t ebl_mode = EBL_GPIO_TRIGGER_MODE;
+
+/* desc  :
+ *         Func to init master i2c hardware comm interface with sennor hub
+ *                 init mfio interrupt pin and attach irq to pin
+ *                 init reset pin
+ * params:
+ *         N/A
+ */
+
+
+void sh_irq_handler();
+void sh_init_hwcomm_interface(){
+	static I2C ssI2C(P3_4, P3_5);     /*set up sensor hub i2c communication at 400 kHz*/
+	ssI2C.frequency(400000);
+	m_i2cBus = &ssI2C;
+
+	reset_pin.input();
+	reset_pin.mode(PullUp);
+	mfio_pin.input();                /*set mfio as input for getting mfio event reporting when sesnor hub is on  application mode */
+	mfio_pin.mode(PullUp);
+
+	irq_pin.fall(sh_irq_handler);    /*attach falling edge interrupt to mfio pin for mfio event reporting */
+
+    return;
+}
+
+/* mfio pin event reporting related interrupt functions*/
+/*
+ * data ready event reporting isr from sensor hub
+ *
+ * params:
+ *         N/A
+ * */
+void sh_irq_handler()
+{
+	m_irq_received_ = true;
+}
+void sh_clear_mfio_event_flag(void){
+	m_irq_received_ = false;
+}
+
+bool sh_has_mfio_event(void){
+	return m_irq_received_;
+}
+
+/*  desc:
+ *       func to enable event reporting from sensor hub
+ *
+ *  params:
+ *       N/A
+ * */
+void sh_enable_irq_mfioevent(void)
+{
+	irq_pin.enable_irq();
+}
+
+/*  desc:
+ *       func to disable event reporting from sensor hub
+ *
+ *  params:
+ *       N/A
+ * */
+void sh_disable_irq_mfioevent(void)
+{
+	irq_pin.disable_irq();
+}
+
+/* desc:
+ *     reset event reporting process from sensor hub, on host side
+ *
+ *  params:
+ *       N/A
+ **/
+bool sh_reset_mfio_irq(){
+	bool ret = mfio_int_happened;
+	mfio_int_happened = false;
+	sh_disable_irq_mfioevent();
+	irq_pin.fall(sh_irq_handler);
+	sh_enable_irq_mfioevent();
+	return ret;
+}
+
+
+/*
+ * desc:
+ *    function to reset sensor hub and put to application mode after reset  interface and get data format.
+ *
+ * params:
+ *
+ *    __I wakeupMode : 0x00 : application mode
+ *                     0x08 : bootloader mode
+ * */
+int sh_hard_reset(int wakeupMode){
+
+   int status;
+   sh_disable_irq_mfioevent();
+   reset_pin.output();
+   mfio_pin.output();
+
+   reset_pin.write(0);
+   wait_ms(SS_RESET_TIME);
+
+   if( (wakeupMode & 0xFF) == 0 ) {
+
+	   mfio_pin.write(1);
+	   reset_pin.write(1);
+	   wait_ms(SS_STARTUP_TO_MAIN_APP_TIME);
+
+   }else {
+
+	    mfio_pin.write(0);
+		reset_pin.write(1);
+		wait_ms(SS_STARTUP_TO_BTLDR_TIME);
+   }
+	mfio_pin.input();
+	mfio_pin.mode(PullUp);
+	reset_pin.input();
+	sh_enable_irq_mfioevent();
+
+
+}
+
+
+int sh_set_ebl_mode(const uint8_t mode)
+{
+	int status;
+	if (mode == EBL_CMD_TRIGGER_MODE || mode == EBL_GPIO_TRIGGER_MODE) {
+		ebl_mode = mode;
+		status =  SS_SUCCESS;
+	} else
+		status = SS_ERR_INPUT_VALUE;
+
+	return status;
+}
+
+const int sh_get_ebl_mode(void)
+{
+   return ebl_mode;
+}
+
+int sh_reset_to_bootloader(void){
+
+	int status;
+	uint8_t hubMode;
+
+     if(ebl_mode == EBL_GPIO_TRIGGER_MODE)
+    	 sh_hard_reset(0x08);
+     if(ebl_mode == EBL_CMD_TRIGGER_MODE)
+    	 status = sh_set_sensorhub_operating_mode(0x08);
+
+     status = sh_get_sensorhub_operating_mode(&hubMode);
+     if( status != 0x00 /*SS_SUCCESS*/ || hubMode != 0x08 ){
+    	 status = -1;
+     }
+
+     return status;
+
+}
+
+static bool in_bootldr;
+
+
+int in_bootldr_mode()
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_MODE, SS_CMDIDX_MODE };
+	uint8_t rxbuf[2] = { 0 };
+
+	int status = sh_read_cmd(&cmd_bytes[0], sizeof(cmd_bytes),
+			0, 0,
+			&rxbuf[0], sizeof(rxbuf), SS_DEFAULT_CMD_SLEEP_MS);
+	if (status != SS_SUCCESS)
+		return -1;
+
+	return (rxbuf[1] & SS_MASK_MODE_BOOTLDR);
+}
+
+int exit_from_bootloader(void)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
+	uint8_t data[] = { 0x00 };
+
+	int status = sh_write_cmd_with_data( &cmd_bytes[0], sizeof(cmd_bytes),
+										 &data[0], 1 /*sizeof(data)*/,
+										 10*SS_DEFAULT_CMD_SLEEP_MS);
+
+	in_bootldr = (status == SS_SUCCESS) ? true : false;
+
+	return status;
+}
+
+static int stay_in_bootloader()
+{
+	uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
+	uint8_t data[] = { SS_MASK_MODE_BOOTLDR };
+
+	int status = sh_write_cmd_with_data(
+			&cmd_bytes[0], sizeof(cmd_bytes),
+			&data[0], sizeof(data), SS_DEFAULT_CMD_SLEEP_MS);
+
+	in_bootldr = (status == SS_SUCCESS) ? true : false;
+	return status;
+}
+
+
+static void cfg_mfio(PinDirection dir)
+{
+	if (dir == PIN_INPUT) {
+		mfio_pin.input();
+		mfio_pin.mode(PullUp);
+	} else {
+		sh_enable_irq_mfioevent();
+		mfio_pin.output();
+	}
+}
+
+int sh_debug_reset_to_bootloader(void)
+{
+
+	int status = -1;
+
+	sh_disable_irq_mfioevent();
+	if (ebl_mode == EBL_GPIO_TRIGGER_MODE) {
+
+		reset_pin.output();
+		cfg_mfio(PIN_OUTPUT);
+		reset_pin.write(0);
+		wait_ms(SS_RESET_TIME);
+		mfio_pin.write(0);
+		reset_pin.write(1);
+		wait_ms(SS_STARTUP_TO_BTLDR_TIME);
+		cfg_mfio(PIN_INPUT);
+		reset_pin.input();
+		sh_enable_irq_mfioevent();
+		stay_in_bootloader();
+		if (in_bootldr_mode() < 0)
+			status = SS_ERR_UNKNOWN;
+		else
+			status = SS_SUCCESS;
+
+	}else{
+		stay_in_bootloader();
+		sh_enable_irq_mfioevent();
+		status = SS_SUCCESS;
+
+	}
+
+    return status;
+}
+
+
+int sh_reset_to_main_app(void)
+{
+	int status = -1;
+	sh_disable_irq_mfioevent();
+	if (ebl_mode == EBL_GPIO_TRIGGER_MODE) {
+
+		reset_pin.output();
+		cfg_mfio(PIN_OUTPUT);
+		mfio_pin.write(0);
+		wait_ms(SS_RESET_TIME - 5);
+		reset_pin.write(0);
+		wait_ms(SS_RESET_TIME - 5);
+		mfio_pin.write(1);
+		wait_ms(SS_RESET_TIME - 5);
+		reset_pin.write(1);
+		//wait_ms(50);
+		//mfio_pin.write(0);
+		wait_ms(2*SS_STARTUP_TO_MAIN_APP_TIME);
+		cfg_mfio(PIN_INPUT);
+		reset_pin.input();
+
+    	sh_enable_irq_mfioevent();
+		// Verify we exited bootloader mode
+		if (in_bootldr_mode() == 0)
+			status = SS_SUCCESS;
+		else
+			status = SS_ERR_UNKNOWN;
+	}else{
+		status = exit_from_bootloader();
+		sh_enable_irq_mfioevent();
+	}
+
+	return status;
+
+}
+
+/*
+ * desc:
+ *    function to init sensor comm interface and get data format.
+ *
+ * */
+void sh_init_hubinterface(void){
+
+	sh_init_hwcomm_interface();
+	//sh_get_data_type(&data_type, &sc_en);
+    return;
+}
+
+
+/*
+ *
+ *   SENSOR HUB COMMUNICATION INTERFACE ( Defined in MAX32664 User Guide ) API FUNCTIONS
+ *
+ *
+ * */
+
+
+//PHASE2 ADDITIONS:
+
+int sh_self_test(int idx, uint8_t *result, int sleep_ms){
+
+	uint8_t cmd_bytes[] = { SS_FAM_R_SELFTEST, (uint8_t)idx }; // = SH_SELFTEST_CMDSEQ;
+    uint8_t rxbuf[2];
+    result[0] = 0xFF;
+
+    int status = sh_read_cmd(&cmd_bytes[0],sizeof(cmd_bytes) ,
+                             0, 0,
+						     &rxbuf[0], sizeof(rxbuf),
+						     sleep_ms  );
+
+	if (status != SS_SUCCESS)
+		return SS_ERR_TRY_AGAIN;
+
+    result[0] = rxbuf[1];
+	return status;
+}
+
+const char* sh_get_hub_fw_version(void)
+{
+    uint8_t cmd_bytes[2];
+    uint8_t rxbuf[4];
+
+    static char fw_version[32] = "SENSORHUB";
+
+	int bootldr = sh_checkif_bootldr_mode();
+
+	if (bootldr > 0) {
+		cmd_bytes[0] = SS_FAM_R_BOOTLOADER;
+		cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION;
+	} else if (bootldr == 0) {
+		cmd_bytes[0] = SS_FAM_R_IDENTITY;
+		cmd_bytes[1] = SS_CMDIDX_FWVERSION;
+	} else {
+
+		return &fw_version[0];
+	}
+
+    int status = sh_read_cmd( &cmd_bytes[0], sizeof(cmd_bytes),
+             	 	 	 	  0, 0,
+							  &rxbuf[0], sizeof(rxbuf),
+							  SS_DEFAULT_CMD_SLEEP_MS );
+
+    if (status == SS_SUCCESS) {
+        snprintf(fw_version, sizeof(fw_version),
+            "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]);
+	}
+
+    return &fw_version[0];
+}
+
+
+const char* sh_get_hub_algo_version(void)
+{
+    uint8_t cmd_bytes[3];
+    uint8_t rxbuf[4];
+
+    static char algo_version[64] = "SENSORHUBALGORITHMS";
+
+	int bootldr = sh_checkif_bootldr_mode();
+
+	if (bootldr > 0) {
+		cmd_bytes[0] = SS_FAM_R_BOOTLOADER;
+		cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION;
+		cmd_bytes[2] = 0;
+	} else if (bootldr == 0) {
+		cmd_bytes[0] = SS_FAM_R_IDENTITY;
+		cmd_bytes[1] = SS_CMDIDX_ALGOVER;
+		cmd_bytes[2] = SS_CMDIDX_AVAILSENSORS;
+	} else {
+
+		return &algo_version[0];
+	}
+
+    int status = sh_read_cmd( &cmd_bytes[0], sizeof(cmd_bytes),
+                              0, 0,
+                              &rxbuf[0], sizeof(rxbuf),
+						      SS_DEFAULT_CMD_SLEEP_MS   );
+
+    if (status == SS_SUCCESS) {
+        snprintf(algo_version, sizeof(algo_version),
+            "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]);
+
+    }
+
+    return &algo_version[0];
+}
+
+int sh_send_raw(uint8_t *rawdata, int rawdata_sz)
+{
+	return sh_write_cmd(&rawdata[0], rawdata_sz, 5 * SS_ENABLE_SENSOR_SLEEP_MS);
+}
+
+int sh_get_log_len(int *log_len)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_LOG, SS_CMDIDX_R_LOG_LEN }; // = SH_GETLOGSIZE_CMDSEQ;
+	uint8_t rxbuf[2] = {0};
+    int logLen = 0;
+
+	int status = sh_read_cmd(&cmd_bytes[0], sizeof(cmd_bytes),
+								   0, 0,
+								   &rxbuf[0], sizeof(rxbuf),
+								   SS_DEFAULT_CMD_SLEEP_MS   );
+
+	if (status == SS_SUCCESS) {
+		logLen = (rxbuf[1] << 8) | rxbuf[0];
+	}
+	*log_len = logLen;
+
+	return status;
+}
+
+int sh_read_ss_log(int num_bytes, uint8_t *log_buf, int log_buf_sz)
+{
+	int bytes_to_read = num_bytes + 1; //+1 for status byte
+	//mxm_assert_msg((bytes_to_read <= log_buf_sz), "log_buf too small");
+
+	uint8_t cmd_bytes[] = { SS_FAM_R_LOG, SS_CMDIDX_R_LOG_DATA }; // = SH_READHUBLOGS_CMDSEQ;
+
+	int status = sh_read_cmd(&cmd_bytes[0], sizeof(cmd_bytes),
+						     0, 0,
+							 log_buf, bytes_to_read,
+							 SS_CMD_WAIT_PULLTRANS_MS  );
+
+	return status;
+}
+
+// END OF PHASE2 ADDITIONS
+
+
+
+
+int sh_write_cmd( uint8_t *tx_buf,
+		          int tx_len,
+				  int sleep_ms)
+{
+	int retries = SS_DEFAULT_RETRIES;
+	int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
+	while (ret != 0 && retries-- > 0) {
+
+		wait_ms(1);
+    	ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
+	}
+    if (ret != 0)
+       return SS_ERR_UNAVAILABLE;
+
+
+    wait_ms(sleep_ms);
+
+    char status_byte;
+    ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1);
+	bool try_again = (status_byte == SS_ERR_TRY_AGAIN);
+	while ((ret != 0 || try_again)
+			&& retries-- > 0) {
+	 	wait_ms(sleep_ms);
+    	ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1);
+		try_again = (status_byte == SS_ERR_TRY_AGAIN);
+	}
+
+    if (ret != 0 || try_again)
+        return SS_ERR_UNAVAILABLE;
+
+	return (int) (SS_STATUS)status_byte;
+}
+
+
+int sh_write_cmd_with_data(uint8_t *cmd_bytes,
+		                   int cmd_bytes_len,
+                           uint8_t *data,
+						   int data_len,
+                           int cmd_delay_ms)
+{
+    memcpy(sh_write_buf, cmd_bytes, cmd_bytes_len);
+    memcpy(sh_write_buf + cmd_bytes_len, data, data_len);
+    int status = sh_write_cmd(sh_write_buf,cmd_bytes_len + data_len, cmd_delay_ms);
+    return status;
+}
+
+
+int sh_read_cmd( uint8_t *cmd_bytes,
+		         int cmd_bytes_len,
+	             uint8_t *data,
+				 int data_len,
+	             uint8_t *rxbuf,
+				 int rxbuf_sz,
+                 int sleep_ms )
+{
+
+	int retries = SS_DEFAULT_RETRIES;
+
+    int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
+    if (data_len != 0)
+        ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
+
+
+	while (ret != 0 && retries-- > 0) {
+		wait_ms(1);
+    	ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
+	    if (data_len != 0)
+	        ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
+
+	}
+    if (ret != 0)
+    	return SS_ERR_UNAVAILABLE;
+
+
+    wait_ms(sleep_ms);
+
+    ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz);
+	bool try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN);
+	while ((ret != 0 || try_again) && retries-- > 0) {
+		wait_ms(sleep_ms);
+    	ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz);
+		try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN);
+	}
+    if (ret != 0 || try_again)
+        return SS_ERR_UNAVAILABLE;
+
+    return (int) ((SS_STATUS)rxbuf[0]);
+}
+
+
+
+int sh_get_sensorhub_status(uint8_t *hubStatus){
+
+	uint8_t ByteSeq[] = SH_GET_HUB_STATUS_CMDSEQ;
+	uint8_t rxbuf[2] = { 0 };
+
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+			                    0, 0,
+			                    &rxbuf[0], sizeof(rxbuf),
+								SS_DEFAULT_CMD_SLEEP_MS);
+
+	*hubStatus = rxbuf[1];
+	return status;
+}
+
+
+int sh_get_sensorhub_operating_mode(uint8_t *hubMode){
+
+	uint8_t ByteSeq[] = SH_GET_OPERATING_MODE_CMDSEQ;
+	uint8_t rxbuf[2] = { 0 };
+
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+			                    0, 0,
+			                    &rxbuf[0], sizeof(rxbuf),
+								SS_DEFAULT_CMD_SLEEP_MS);
+
+	*hubMode = rxbuf[1];
+	return status;
+}
+
+
+int sh_set_sensorhub_operating_mode(uint8_t hubMode){
+
+	uint8_t ByteSeq[] = SH_SET_OPERATING_MODE_CMDSEQ(hubMode);
+	int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_DEFAULT_CMD_SLEEP_MS);
+    return status;
+
+}
+
+
+//int sh_set_data_type( uint8_t outMode)
+int sh_set_data_type(int data_type_, bool sc_en_)
+{
+
+#if 0
+	uint8_t dataTypeSc = (uint8_t)((sc_en ? SS_MASK_OUTPUTMODE_SC_EN : 0) | ((data_type << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE));
+	uint8_t ByteSeq[] = SH_SET_OUTPUT_MODE_CMDSEQ( dataTypeSc);
+	int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_DEFAULT_CMD_SLEEP_MS);
+    if( status == 0x00){
+    	data_type = data_type_;
+        sc_en = sc_en_;
+    }
+#endif
+
+	uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
+	uint8_t data_bytes[] = { (uint8_t)((sc_en_ ? SS_MASK_OUTPUTMODE_SC_EN : 0) |
+							((data_type_ << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE)) };
+
+	int status = sh_write_cmd_with_data(&cmd_bytes[0], sizeof(cmd_bytes),
+								&data_bytes[0], sizeof(data_bytes),
+								SS_DEFAULT_CMD_SLEEP_MS);
+	data_type = data_type_;
+	sc_en = sc_en_;
+
+	return status;
+}
+
+
+int sh_get_data_type(int *data_type_, bool *sc_en_){
+
+	uint8_t ByteSeq[] = SH_GET_OUTPUT_MODE_CMDSEQ;
+	uint8_t rxbuf[2] = {0};
+	int status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq),
+							  0, 0,
+							  &rxbuf[0], sizeof(rxbuf),
+							  SS_DEFAULT_CMD_SLEEP_MS);
+	if (status == 0x00 /*SS_SUCCESS*/) {
+		*data_type_ =
+			(rxbuf[1] & SS_MASK_OUTPUTMODE_DATATYPE) >> SS_SHIFT_OUTPUTMODE_DATATYPE;
+		*sc_en_ =
+			(bool)((rxbuf[1] & SS_MASK_OUTPUTMODE_SC_EN) >> SS_SHIFT_OUTPUTMODE_SC_EN);
+
+	}
+
+	return status;
+
+}
+
+
+int sh_set_fifo_thresh( int threshold ){
+
+#if 0
+	uint8_t ucThresh = (uint8_t) (threshold & 0xFF);
+	uint8_t ByteSeq[] = SH_DFIFO_SET_INT_THRESHOLD_CMDSEQ(ucThresh );
+	int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_DEFAULT_CMD_SLEEP_MS);
+	return status;
+#endif
+
+	uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_FIFOAFULL };
+	uint8_t data_bytes[] = { (uint8_t)threshold };
+
+	int status = sh_write_cmd_with_data(&cmd_bytes[0], sizeof(cmd_bytes),
+								&data_bytes[0], sizeof(data_bytes),
+								SS_DEFAULT_CMD_SLEEP_MS
+	                            );
+	return status;
+
+}
+
+
+int sh_get_fifo_thresh(int *thresh){
+
+	uint8_t ByteSeq[] = SH_DFIFO_GET_INT_THRESHOLD_CMDSEQ;
+	uint8_t rxbuf[2] = {0};
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+							 0, 0,
+							 &rxbuf[0], sizeof(rxbuf),
+							 SS_DEFAULT_CMD_SLEEP_MS);
+
+	*thresh = (int) rxbuf[1];
+
+	return status;
+
+}
+
+
+int sh_ss_comm_check(void){
+
+
+	uint8_t ByteSeq[] = SH_COMM_CHECK_CMDSEQ;
+	uint8_t rxbuf[2];
+
+	int status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq),
+							  0, 0,
+							  &rxbuf[0], sizeof(rxbuf),
+							  SS_DEFAULT_CMD_SLEEP_MS );
+
+	int tries = 4;
+	while (status == SS_ERR_TRY_AGAIN && tries--) {
+		wait_ms(1000);
+		status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq),
+									  0, 0,
+									  &rxbuf[0], sizeof(rxbuf),
+									  SS_DEFAULT_CMD_SLEEP_MS );
+
+	}
+
+	return status;
+}
+
+
+int sh_num_avail_samples(int *numSamples) {
+
+	 uint8_t ByteSeq[] = SH_DFIFO_GET_NSAMPLES_CMDSEQ;
+	 uint8_t rxbuf[2] = {0};
+
+	 int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+							  0, 0,
+							  &rxbuf[0], sizeof(rxbuf),
+							  1);
+
+	 *numSamples = (int) rxbuf[1];
+
+	 return status;
+}
+
+
+int sh_read_fifo_data( int numSamples,
+		               int sampleSize,
+		               uint8_t* databuf,
+					   int databufSz) {
+
+	int bytes_to_read = numSamples * sampleSize + 1; //+1 for status byte
+
+	uint8_t ByteSeq[] = SH_DFIFO_PULL_SAMPLE_CMDSEQ;
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+							 0, 0,
+							 databuf, bytes_to_read,
+							 10);
+
+	return status;
+}
+
+
+/*
+ * desc:
+ *        func to read sample size for SmartSensor input FIFO for extrenal accel data
+ *
+ * params:
+ *		  __O sampSize:  size of data sample struct in bytes
+ * returns:
+ *        1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_read_input_fifo_samplesz( int *sampSize){
+
+	/* NOT IMPLEMENTED IN SS INTERFACE */
+
+}
+
+/*
+ * desc:
+ *        func to write data  samples to  SmartSensor input FIFO for extrenal accel data
+ *
+ * params:
+          ...
+ * returns:
+ *        1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_write_input_fifo( void *arg){
+
+	/* NOT IMPLEMENTED IN SS INTERFACE */
+
+}
+
+
+int sh_set_reg(int idx, uint8_t addr, uint32_t val, int regSz){
+
+	uint8_t ByteSeq[] = SH_WRITE_SENSORREG_CMDSEQ( ((uint8_t)idx) , addr );
+	uint8_t data_bytes[4];
+	for (int i = 0; i < regSz; i++) {
+		data_bytes[i] = (val >> (8 * (regSz - 1)) & 0xFF);
+	}
+	int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq),
+							             &data_bytes[0], (uint8_t) regSz,
+										 SS_DEFAULT_CMD_SLEEP_MS);
+
+    return status;
+}
+
+
+int sh_get_reg(int idx, uint8_t addr, uint32_t *val){
+
+
+	uint32_t i32tmp;
+	uint8_t ByteSeq[] = SH_READ_AFE_ATTRIBUTES_CMDSEQ(((uint8_t) idx));
+	uint8_t rxbuf[3] = {0};
+
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+								0, 0,
+							 &rxbuf[0], sizeof(rxbuf),
+							 SS_DEFAULT_CMD_SLEEP_MS);
+
+
+    if(status == 0x00 /* SS_SUCCESS */) {
+
+    	int reg_width = rxbuf[1];
+    	uint8_t ByteSeq2[] = SH_READ_SENSORREG_CMDSEQ( ((uint8_t)idx) , addr );
+    	uint8_t rxbuf2[5] = {0};
+    	status = sh_read_cmd(&ByteSeq2[0], sizeof(ByteSeq2),
+    						0, 0,
+    						&rxbuf2[0], reg_width + 1,
+							SS_DEFAULT_CMD_SLEEP_MS);
+
+    	if (status == 0x00  /* SS_SUCCESS */) {
+    		i32tmp = 0;
+    		for (int i = 0; i < reg_width; i++) {
+    			i32tmp = (i32tmp << 8) | rxbuf2[i + 1];
+    		}
+            *val = i32tmp;
+    	}
+     }
+
+    return status;
+
+}
+
+
+int sh_sensor_enable( int idx , int sensorSampleSz , uint8_t ext_mode ){
+
+	uint8_t ByteSeq[] = SH_ENABLE_SENSOR_CMDSEQ( ((uint8_t) idx) ,  ((uint8_t) ext_mode));
+	int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), 5 * SS_ENABLE_SENSOR_SLEEP_MS);
+	if(status == 0x00){
+
+		is_sensor_enabled[idx] = ENABLED;
+		sensor_sample_sz[idx] = sensorSampleSz;
+	}
+    return status;
+
+}
+
+
+int sh_sensor_disable( int idx ){
+
+	uint8_t ByteSeq[] = SH_DISABLE_SENSOR_CMDSEQ( ((uint8_t) idx));
+	int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_ENABLE_SENSOR_SLEEP_MS);
+	if(status == 0x00){
+
+		is_sensor_enabled[idx] = DISABLED;
+	}
+	return status;
+
+}
+
+
+int sh_get_input_fifo_size(int *fifo_size)
+{
+
+	uint8_t ByteSeq[] = SH_GET_EXTINPUT_FIFOSZ_CMDSEQ;
+	uint8_t rxbuf[3]; /* status + fifo size */
+
+
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+							  0, 0,
+							  rxbuf, sizeof(rxbuf), 2*SS_DEFAULT_CMD_SLEEP_MS);
+
+	*fifo_size = rxbuf[1] << 8 | rxbuf[2];
+	return status;
+}
+
+
+int sh_feed_to_input_fifo(uint8_t *tx_buf, int tx_buf_sz, int *nb_written)
+{
+	int status;
+
+	uint8_t ByteSeq[] = SH_FEED_TO_INPUTFIFO_CMDSEQ;
+	uint8_t rxbuf[3];
+
+	tx_buf[0] = 0x14;
+	tx_buf[1] = 0x00;
+
+	status= sh_read_cmd(tx_buf, tx_buf_sz,
+			          0, 0,
+			          rxbuf, sizeof(rxbuf), SS_FEEDFIFO_CMD_SLEEP_MS);
+
+	*nb_written = rxbuf[1] * 256 + rxbuf[2];
+	return status;
+}
+
+
+int sh_get_num_bytes_in_input_fifo(int *fifo_size)
+{
+
+    uint8_t ByteSeq[] = SH_GET_SAMPLEBYTECNT_INPUTFIFO_CMDSEQ;
+	uint8_t rxbuf[3]; /* status + fifo size */
+
+
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+							 0, 0,
+							 rxbuf, sizeof(rxbuf),
+							 2*SS_DEFAULT_CMD_SLEEP_MS);
+
+	*fifo_size = rxbuf[1] << 8 | rxbuf[2];
+	return status;
+}
+
+
+/*
+ * ALGARITIM RELATED FUNCTIONS :)
+ *
+ *
+ *
+ *
+ *
+ * */
+
+
+int sh_enable_algo(int idx , int algoSampleSz){
+
+	uint8_t ByteSeq[] = SH_ENABLE_ALGO_CMDSEQ( ((uint8_t) idx) );
+	int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), 25 * SS_ENABLE_SENSOR_SLEEP_MS);
+	if(status == 0x00){
+
+		is_algo_enabled[idx] = ENABLED;
+		algo_sample_sz[idx]  = algoSampleSz;
+	}
+    return status;
+
+}
+
+
+int sh_enable_algo_withmode(int idx, int mode, int algoSampleSz)
+{
+
+	uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, (uint8_t)mode };
+
+	int status = sh_write_cmd_with_data(&cmd_bytes[0], sizeof(cmd_bytes), 0, 0, 25 * SS_ENABLE_SENSOR_SLEEP_MS);
+
+	if (status == SS_SUCCESS) {
+		is_algo_enabled[idx]   = ENABLED;
+		algo_sample_sz[idx]    = algoSampleSz;
+		enabled_algo_mode[idx] = mode;
+	}
+
+	return status;
+}
+
+
+
+int sh_disable_algo(int idx){
+
+	uint8_t ByteSeq[] = SH_DISABLE_ALGO_CMDSEQ( ((uint8_t) idx) );
+	int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_ENABLE_SENSOR_SLEEP_MS );
+	if(status == 0x00){
+
+		is_algo_enabled[idx] = DISABLED;
+	}
+    return status;
+
+}
+
+
+int sh_set_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz){
+
+	uint8_t ByteSeq[] = SH_SET_ALGO_CONFIGURATION_CMDSEQ( ((uint8_t) algo_idx) ,  ((uint8_t) cfg_idx)  );
+	int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq),
+			                             cfg, cfg_sz,
+										 SS_DEFAULT_CMD_SLEEP_MS);
+
+	return status;
+
+}
+
+
+int sh_get_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz){
+
+	uint8_t ByteSeq[] = SH_GET_ALGO_CONFIGURATION_CMDSEQ( ((uint8_t) algo_idx) ,  ((uint8_t) cfg_idx)  );
+	int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq),
+						     0, 0,
+							 cfg, cfg_sz,
+							 SS_DEFAULT_CMD_SLEEP_MS);
+	return status;
+
+}
+
+
+/*
+ * desc:
+ *      func to get active cumulative sample size of sensor hub in order to
+ *           calculate number of bytes to be read from sensor hub report data buffer
+ *
+ * params:
+ *      __I data_type : active data type of sensor hub -> no data              :0 (SS_DATATYPE_PAUSE)
+ *                                                        raw sensor data only :1 (SS_DATATYPE_RAW)
+ *                                                        algo data only       :2 (SS_DATATYPE_ALGO)
+ *                                                        algo+raw data        :3 (SS_DATATYPE_BOTH)
+ *      __O sample_size : calculated active cumulative sample size
+
+ * returns:
+ *        N/A
+ *
+ **/
+static void fifo_sample_size(int data_type_, int *sample_size)
+{
+
+    int tmpSz = 0;
+	//*sample_size = 0;
+
+	if (data_type_ == SS_DATATYPE_RAW || data_type_ == SS_DATATYPE_BOTH) {
+		for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
+			if (is_sensor_enabled[i]) {
+				tmpSz += sensor_sample_sz[i];
+				//*sample_size += sensor_data_reqs[i]->data_size;
+			}
+		}
+	}
+
+	if (data_type_ == SS_DATATYPE_ALGO || data_type_ == SS_DATATYPE_BOTH) {
+		for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) {
+			if (is_algo_enabled[i]) {
+				tmpSz += algo_sample_sz[i];
+				//*sample_size += algo_data_reqs[i]->data_size;
+			}
+		}
+	}
+
+	*sample_size = tmpSz;
+}
+
+
+int sh_ss_execute_once( uint8_t *databuf , int databufLen , int *nSamplesRead){
+
+	if(m_irq_received_ == false) {
+		  *nSamplesRead = 0;
+		  return -1;
+	}
+
+	uint8_t sample_count;
+
+    sh_disable_irq_mfioevent();
+    sh_clear_mfio_event_flag();
+
+	uint8_t hubStatus = 0;
+	int status = sh_get_sensorhub_status(&hubStatus);
+	if(status != 0x00 /*SS_SUCCESS*/){
+    	*nSamplesRead = 0;
+    	sh_enable_irq_mfioevent();
+        return status;
+    }
+
+    if (hubStatus & SS_MASK_STATUS_DATA_RDY) {
+
+    	 int num_samples = 1;
+    	 status = sh_num_avail_samples(&num_samples);
+      	 if (status != 0x00 /*SS_SUCCESS*/){
+    		 *nSamplesRead = 0;
+    		 sh_enable_irq_mfioevent();
+    		 return status;
+         }
+
+
+    	 int sample_size;
+    	 fifo_sample_size(data_type, &sample_size);
+    	 /*DEBUG *///
+
+
+    	 int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
+         if ( bytes_to_read > databufLen) {
+ 			//Reduce number of samples to read to fit in buffer
+ 			num_samples = (databufLen - 1) / sample_size;
+ 		 }
+
+
+        wait_ms(5);
+        status = sh_read_fifo_data(num_samples, sample_size, &databuf[0], databufLen);
+        if(status != 0x00 /*SS_SUCCESS*/){
+        	*nSamplesRead = 0;
+        	sh_enable_irq_mfioevent();
+        	return status;
+        }
+        *nSamplesRead = num_samples;
+    }
+
+    sh_enable_irq_mfioevent();
+    return status;
+}
+
+
+
+/*
+ * BOOTLOADER RELATED FUNCTIONS
+ *
+ *
+ * */
+
+static const int aes_nonce_sz = 11;
+static const int aes_auth_sz  = 16;
+static int bl_comm_delay_factor = 1;
+
+
+
+int sh_set_bootloader_delayfactor(const int factor ) {
+
+	int status = -1;
+	if( factor >= 1  && factor < 51){
+	    bl_comm_delay_factor = factor;
+	    status = 0x00;
+	}
+
+	return status;
+
+}
+
+const int sh_get_bootloader_delayfactor(void){
+
+     return bl_comm_delay_factor;
+}
+
+int sh_exit_from_bootloader(void)
+{
+
+	return sh_reset_to_main_app(); //sh_set_sensorhub_operating_mode(0x00);
+}
+
+int sh_put_in_bootloader(void)
+{
+	return sh_set_sensorhub_operating_mode( 0x08);
+}
+
+int sh_checkif_bootldr_mode(void)
+{
+	uint8_t hubMode;
+	int status = sh_get_sensorhub_operating_mode(&hubMode);
+	return (status != SS_SUCCESS)? -1:(hubMode & SS_MASK_MODE_BOOTLDR);
+}
+
+int sh_get_bootloader_pagesz(int *pagesz){
+
+	//uint8_t ByteSeq[]= SH_GET_BOOTLDRPAGESIZE_CMDSEQ;
+	uint8_t ByteSeq[]= { SS_FAM_R_BOOTLOADER, SS_CMDIDX_PAGESIZE };
+    uint8_t rxbuf[3];
+    int sz = 0;
+
+    int status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq),
+                          0, 0,
+                          &rxbuf[0], sizeof(rxbuf),
+						  SS_DEFAULT_CMD_SLEEP_MS);
+    if (status == 0x00) {
+           //rxbuf holds page size in big-endian format
+            sz = (256*(int)rxbuf[1]) + rxbuf[2];
+            if(sz > BOOTLOADER_MAX_PAGE_SIZE ) {
+                   sz = -2;
+            }
+    }
+
+    *pagesz = sz;
+
+    return status;
+
+}
+
+int sh_set_bootloader_numberofpages(const int pageCount){
+
+	//uint8_t ByteSeq[] = SH_SET_BOOTLDRPAGECOUNT_CMDSEQ;
+    uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETNUMPAGES };
+    //num pages = 256*MSB + LSB
+    uint8_t data_bytes[] = { (uint8_t)((pageCount >> 8) & 0xFF), (uint8_t)(pageCount & 0xFF) };
+
+    int status = sh_write_cmd_with_data(&ByteSeq[0], sizeof(ByteSeq),
+								        &data_bytes[0], sizeof(data_bytes),
+										bl_comm_delay_factor * SS_DEFAULT_CMD_SLEEP_MS );
+
+    return status;
+
+}
+
+int sh_set_bootloader_iv(uint8_t iv_bytes[aes_nonce_sz]){
+
+	 uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETIV };
+	 int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq),
+			                              &iv_bytes[0], aes_nonce_sz /*sizeof(iv_bytes)*/,
+										  bl_comm_delay_factor * SS_DEFAULT_CMD_SLEEP_MS
+										  );
+
+     return status;
+
+}
+
+
+int sh_set_bootloader_auth(uint8_t auth_bytes[aes_auth_sz]){
+
+	 uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETAUTH };
+	 int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq),
+			                              &auth_bytes[0], aes_auth_sz /*sizeof(auth_bytes)*/,
+										  bl_comm_delay_factor * SS_DEFAULT_CMD_SLEEP_MS
+										  );
+
+     return status;
+
+}
+
+
+int sh_set_bootloader_erase(void){
+
+    uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_ERASE };
+
+    int status = sh_write_cmd_with_data(&ByteSeq[0], sizeof(ByteSeq),
+                                        0, 0,
+										bl_comm_delay_factor * SS_BOOTLOADER_ERASE_DELAY);
+
+    return status;
+
+}
+
+
+int sh_bootloader_flashpage(uint8_t *flashDataPreceedByCmdBytes , const int page_size){
+
+	static const int flash_cmdbytes_len   = 2;
+	static const int check_bytes_len      = 16;
+	static const int page_write_time_ms   = 200;
+
+    //static const uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SENDPAGE };
+    int status = -1;
+
+    if( (*flashDataPreceedByCmdBytes == SS_FAM_W_BOOTLOADER) &&  ( *(flashDataPreceedByCmdBytes+1) == SS_CMDIDX_SENDPAGE ) ) {
+
+		/* We do not use sh_write_cmd_with_data function because internal buffers of the function
+		   is limited to 512 bytes which does not support if flashing page size is bigger */
+		status = sh_write_cmd(flashDataPreceedByCmdBytes, page_size + check_bytes_len + flash_cmdbytes_len, bl_comm_delay_factor * page_write_time_ms);
+
+    }
+	return status;
+
+}
+
+
+int sh_get_ss_fw_version(uint8_t *fwDesciptor  , uint8_t *descSize)
+{
+
+	int status = -1;
+	uint8_t cmd_bytes[2];
+    uint8_t rxbuf[4];
+
+	int bootldr = in_bootldr_mode();
+
+	if (bootldr > 0) {
+		cmd_bytes[0] = SS_FAM_R_BOOTLOADER;
+		cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION;
+	} else if (bootldr == 0) {
+		cmd_bytes[0] = SS_FAM_R_IDENTITY;
+		cmd_bytes[1] = SS_CMDIDX_FWVERSION;
+	} else {
+		return -1;
+	}
+
+    status = sh_read_cmd( &cmd_bytes[0], sizeof(cmd_bytes),
+             	 	 	 	 	 	0, 0,
+								    &rxbuf[0], sizeof(rxbuf) ,
+									SS_DEFAULT_CMD_SLEEP_MS );
+
+    if (status == 0x00 /*SS_SUCCESS*/) {
+    	*fwDesciptor       = rxbuf[1];
+    	*(fwDesciptor + 1) = rxbuf[2];
+    	*(fwDesciptor + 2) = rxbuf[3];
+    	*descSize = 3;
+    }else{
+    	*descSize = 0;
+    }
+
+    return status;
+
+}
+
+
+/*
+#ifdef __cplusplus
+}
+#endif
+*/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SHComm/SHComm.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,863 @@
+/*
+ * SHComm.h
+ *
+ *  Created on: Nov 16, 2018
+ *      Author: Yagmur.Gok
+ */
+
+#ifndef SOURCE_SHCOMM_H_
+#define SOURCE_SHCOMM_H_
+
+/*
+#ifdef __cplusplus
+extern "C" {
+#endif
+*/
+
+// Sensor/Algo indicies
+#define SH_SENSORIDX_MAX8614X	0x00
+#define SH_SENSORIDX_MAX30205	0x01
+#define SH_SENSORIDX_MAX30001	0x02
+#define SH_SENSORIDX_MAX30101	0x03
+#define SH_SENSORIDX_ACCEL	    0x04
+#define SH_NUM_CURRENT_SENSORS	5
+
+#define SH_ALGOIDX_AGC	        0x00
+#define SH_ALGOIDX_AEC			0x01
+#define SH_ALGOIDX_WHRM			0x02
+#define SH_ALGOIDX_ECG			0x03
+#define SH_ALGOIDX_BPT			0x04
+#define SH_ALGOIDX_WSPO2        0x05
+#define SH_NUM_CURRENT_ALGOS	6
+
+#define PADDING_BYTE            (0xEE)
+#define DATA_BYTE               (0xED)
+
+
+#define SS_I2C_8BIT_SLAVE_ADDR 0xAA
+#define SS_DEFAULT_CMD_SLEEP_MS 2
+#define SS_DUMP_REG_SLEEP_MS 100
+#define SS_ENABLE_SENSOR_SLEEP_MS 20
+#define SS_BOOTLOADER_ERASE_DELAY	1000
+
+#define SH_INPUT_DATA_DIRECT_SENSOR	0x00
+#define SH_INPUT_DATA_FROM_HOST		0x01
+
+#define SS_FAM_R_STATUS		0x00
+	#define SS_CMDIDX_STATUS	0x00
+		#define SS_SHIFT_STATUS_ERR				0
+		#define SS_MASK_STATUS_ERR				(0x07 << SS_SHIFT_STATUS_ERR)
+		#define SS_SHIFT_STATUS_DATA_RDY		3
+		#define SS_MASK_STATUS_DATA_RDY			(1 << SS_SHIFT_STATUS_DATA_RDY)
+		#define SS_SHIFT_STATUS_FIFO_OUT_OVR	4
+		#define SS_MASK_STATUS_FIFO_OUT_OVR		(1 << SS_SHIFT_STATUS_FIFO_OUT_OVR)
+		#define SS_SHIFT_STATUS_FIFO_IN_OVR		5
+		#define SS_MASK_STATUS_FIFO_IN_OVR		(1 << SS_SHIFT_STATUS_FIFO_IN_OVR)
+
+		#define SS_SHIFT_STATUS_LOG_OVR			6
+		#define SS_MASK_STATUS_LOG_OVR			(1 << SS_SHIFT_STATUS_LOG_OVR)
+
+		#define SS_SHIFT_STATUS_LOG_RDY			7
+		#define SS_MASK_STATUS_LOG_RDY			(1 << SS_SHIFT_STATUS_LOG_RDY)
+
+
+
+#define SS_FAM_W_MODE	0x01
+#define SS_FAM_R_MODE	0x02
+	#define SS_CMDIDX_MODE	0x00
+		#define SS_SHIFT_MODE_SHDN		0
+		#define SS_MASK_MODE_SHDN		(1 << SS_SHIFT_MODE_SHDN)
+		#define SS_SHIFT_MODE_RESET		1
+		#define SS_MASK_MODE_RESET		(1 << SS_SHIFT_MODE_RESET)
+		#define SS_SHIFT_MODE_FIFORESET	2
+		#define SS_MASK_MODE_FIFORESET	(1 << SS_SHIFT_MODE_FIFORESET)
+		#define SS_SHIFT_MODE_BOOTLDR	3
+		#define SS_MASK_MODE_BOOTLDR	(1 << SS_SHIFT_MODE_BOOTLDR)
+
+/*MYG*/
+#define SH_MODE_REQUEST_RET_BYTES        (2)
+#define SH_MODE_REQUEST_DELAY            (2)
+#define SH_STATUS_REQUEST_RET_BYTES      (2)
+#define SH_STATUS_REQUEST_DELAY          (2)
+
+
+
+#define SS_I2C_READ		0x03
+
+#define SS_FAM_W_COMMCHAN	0x10
+#define SS_FAM_R_COMMCHAN	0x11
+	#define SS_CMDIDX_OUTPUTMODE	0x00
+		#define SS_SHIFT_OUTPUTMODE_DATATYPE	0
+		#define SS_MASK_OUTPUTMODE_DATATYPE		(0x03 << SS_SHIFT_OUTPUTMODE_DATATYPE)
+			#define SS_DATATYPE_PAUSE				0
+			#define SS_DATATYPE_RAW					1
+			#define SS_DATATYPE_ALGO				2
+			#define SS_DATATYPE_BOTH				3
+		#define SS_SHIFT_OUTPUTMODE_SC_EN		2
+		#define SS_MASK_OUTPUTMODE_SC_EN		(1 << SS_SHIFT_OUTPUTMODE_SC_EN)
+	#define SS_CMDIDX_FIFOAFULL		0x01
+
+#define SS_FAM_R_OUTPUTFIFO	0x12
+	#define SS_CMDIDX_OUT_NUMSAMPLES	0x00
+	#define SS_CMDIDX_READFIFO		    0x01
+
+#define SS_FAM_R_INPUTFIFO						0x13
+	#define SS_CMDIDX_SAMPLE_SIZE				0x00
+	#define SS_CMDIDX_INPUT_FIFO_SIZE			0x01
+	#define SS_CMDIDX_SENSOR_FIFO_SIZE			0x02
+	#define SS_CMDIDX_NUM_SAMPLES_SENSOR_FIFO	0x03
+	#define SS_CMDIDX_NUM_SAMPLES_INPUT_FIFO	0x04
+
+#define SS_FAM_W_INPUTFIFO	0x14
+	#define SS_CMDIDN_WRITEFIFO		0x00
+	#define SS_CMDIDX_WRITE_FIFO    0x00
+
+#define SS_FAM_W_WRITEREG		0x40
+#define SS_FAM_R_READREG		0x41
+#define SS_FAM_R_REGATTRIBS		0x42
+#define SS_FAM_R_DUMPREG		0x43
+
+#define SS_FAM_W_SENSORMODE	0x44
+#define SS_FAM_R_SENSORMODE	0x45
+
+//TODO: Fill in known configuration parameters
+#define SS_FAM_W_ALGOCONFIG	0x50
+#define SS_FAM_R_ALGOCONFIG	0x51
+	#define SS_CFGIDX_AGC_TARGET		0x00
+	#define SS_CFGIDX_AGC_CORR_COEFF	0x01
+	#define SS_CFGIDX_AGC_SENSITIVITY	0x02
+	#define SS_CFGIDX_AGC_SMP_AVG		0x03
+
+	#define SS_CFGIDX_WHRM_SR			0x00
+	#define SS_CFGIDX_WHRM_MAX_HEIGHT	0x01
+	#define SS_CFGIDX_WHRM_MAX_WEIGHT	0x02
+	#define SS_CFGIDX_WHRM_MAX_AGE		0x03
+	#define SS_CFGIDX_WHRM_MIN_HEIGHT	0x04
+	#define SS_CFGIDX_WHRM_MIN_WEIGHT	0x05
+	#define SS_CFGIDX_WHRM_MIN_AGE		0x06
+	#define SS_CFGIDX_WHRM_DEF_HEIGHT	0x07
+	#define SS_CFGIDX_WHRM_DEF_WEIGHT	0x08
+	#define SS_CFGIDX_WHRM_DEF_AGE		0x09
+	#define SS_CFGIDX_WHRM_INIT_HR		0x0A
+	// additional for WHRM_AEC_SCD
+	#define SS_CFGIDX_WHRM_AEC_ENABLE						0x0B
+	#define SS_CFGIDX_WHRM_SCD_ENABLE						0x0C
+	#define SS_CFGIDX_WHRM_ADJ_TARGET_PD_CURRENT_PERIOD		0x0D
+	#define SS_CFGIDX_WHRM_SCD_DEBOUNCE_WINDOW				0x0E
+	#define SS_CFGIDX_WHRM_MOTION_MAG_THRESHOLD				0x0F
+	#define SS_CFGIDX_WHRM_MIN_PD_CURRENT			    	0x10
+	#define SS_CFGIDX_WHRM_PD_CONFIG				    	0x11
+
+    	// config for WSPO2
+	#define SS_CFGIDX_WSPO2_CAL								0x00
+	#define SS_CFGIDX_WSPO2_SR								0x01
+	#define SS_CFGIDX_WSPO2_ALGO_MODE						0x02
+	#define SS_CFGIDX_WSPO2_AGC_MODE						0x03
+	#define SS_CFGIDX_WSPO2_MOTION_DET						0x04
+	#define SS_CFGIDX_WSPO2_MOTION_PERIOD					0x05
+	#define SS_CFGIDX_WSPO2_MOTION_THRESHOLD 				0x06
+	#define SS_CFGIDX_WSPO2_AGC_TIMEOUT						0x07
+	#define SS_CFGIDX_WSPO2_TIMEOUT							0x08
+	#define SS_CFGIDX_WSPO2_PD_CONFIG						0x09
+
+	#define SS_CFGIDX_BP_USE_MED		0x00
+	#define SS_CFGIDX_BP_SYS_BP_CAL		0x01
+	#define SS_CFGIDX_BP_DIA_BP_CAL		0x02
+	#define SS_CFGIDX_BP_CAL_DATA		0x03
+	#define SS_CFGIDX_BP_EST_DATE		0x04
+	#define SS_CFGIDX_BP_EST_NONREST	0x05
+
+#define SS_FAM_W_ALGOMODE	0x52
+#define SS_FAM_R_ALGOMODE	0x53
+
+#define SS_FAM_W_EXTERNSENSORMODE	0x60
+#define SS_FAM_R_EXTERNSENSORMODE	0x61
+
+#define SS_FAM_R_SELFTEST    0x70
+
+#define SS_FAM_W_BOOTLOADER	0x80
+	#define SS_CMDIDX_SETIV			0x00
+	#define SS_CMDIDX_SETAUTH		0x01
+	#define SS_CMDIDX_SETNUMPAGES	0x02
+	#define SS_CMDIDX_ERASE			0x03
+	#define SS_CMDIDX_SENDPAGE		0x04
+	#define SS_CMDIDX_ERASE_PAGE	0x05
+#define SS_FAM_R_BOOTLOADER	0x81
+	#define SS_CMDIDX_BOOTFWVERSION	0x00
+	#define SS_CMDIDX_PAGESIZE		0x01
+
+#define SS_FAM_W_BOOTLOADER_CFG	0x82
+#define SS_FAM_R_BOOTLOADER_CFG	0x83
+	#define SS_CMDIDX_BL_SAVE		0x00
+	#define SS_CMDIDX_BL_ENTRY		0x01
+		#define SS_BL_CFG_ENTER_BL_MODE		0x00
+		#define SS_BL_CFG_EBL_PIN			0x01
+		#define SS_BL_CFG_EBL_POL			0x02
+	#define SS_CMDIDX_BL_EXIT		0x02
+		#define SS_BL_CFG_EXIT_BL_MODE		0x00
+		#define SS_BL_CFG_TIMEOUT			0x01
+
+/* Enable logging/debugging */
+#define SS_FAM_R_LOG				0x90
+	#define SS_CMDIDX_R_LOG_DATA	0x00
+	#define SS_CMDIDX_R_LOG_LEN		0x01
+
+	#define SS_CMDIDX_R_LOG_LEVEL	0x02
+		#define SS_LOG_DISABLE		0x00
+		#define SS_LOG_CRITICAL		0x01
+		#define SS_LOG_ERROR		0x02
+		#define SS_LOG_INFO			0x04
+		#define SS_LOG_DEBUG		0x08
+
+#define SS_FAM_W_LOG_CFG			0x91
+	#define SS_CMDIDX_LOG_GET_LEVEL	0x00
+	#define SS_CMDIDX_LOG_SET_LEVEL	0x01
+
+#define SS_FAM_R_IDENTITY			0xFF
+	#define SS_CMDIDX_PLATTYPE		0x00
+	#define SS_CMDIDX_PARTID		0x01
+	#define SS_CMDIDX_REVID			0x02
+	#define SS_CMDIDX_FWVERSION		0x03
+	#define SS_CMDIDX_AVAILSENSORS	0x04
+	#define SS_CMDIDX_DRIVERVER		0x05
+	#define SS_CMDIDX_AVAILALGOS	0x06
+	#define SS_CMDIDX_ALGOVER		0x07
+
+
+/* Newly added ones; checko for collosion or repeats with the ones above */
+#define SS_RESET_TIME	10
+#define SS_STARTUP_TO_BTLDR_TIME	20
+#define SS_STARTUP_TO_MAIN_APP_TIME	1000
+
+#define SS_MAX_SUPPORTED_SENSOR_NUM	0xFE
+#define SS_MAX_SUPPORTED_ALGO_NUM	0xFE
+
+#define SS_APPPLICATION_MODE   0x00
+#define SS_BOOTLOADER_MODE     0x08
+
+typedef enum {
+	SS_SUCCESS             =0x00,
+	SS_ERR_COMMAND         =0x01,
+	SS_ERR_UNAVAILABLE     =0x02,
+	SS_ERR_DATA_FORMAT     =0x03,
+	SS_ERR_INPUT_VALUE     =0x04,
+	SS_ERR_BTLDR_GENERAL   =0x80,
+	SS_ERR_BTLDR_CHECKSUM  =0x81,
+	SS_ERR_TRY_AGAIN       =0xFE,
+	SS_ERR_UNKNOWN         =0xFF,
+
+} SS_STATUS;
+
+
+
+/* ***************************************************************************************** *
+ *																							 *
+ *   SENSOR HUB COMMUNICATION INTERFACE ( Defined in MAX32664 User Guide ) API FUNCTIONS     *
+ *																							 *
+ *																							 *
+ * ***************************************************************************************** */
+
+
+/**
+* @brief	Func to write to sensor hub via sending generic command byte sequences
+*
+* @param[in]	tx_buf   - command byte sequence
+* @param[in]	tx_len   - command byte sequence length in bytes
+* @param[in]	sleep_ms - time to wait for sensor hub to report statuss
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_write_cmd( uint8_t *tx_buf,
+		          int tx_len,
+				  int sleep_ms );
+
+
+/**
+* @brief	Func to write to sensor hub via sending generic command byte sequences and data bytes
+*
+* @param[in]	cmd_bytes      - command byte sequence
+* @param[in]	cmd_bytes_len  - command byte sequence length in bytes
+* @param[in]    data           - data byte array to be sent following cmd bytes
+* @param[in]    data_len       - data array size in bytes
+* @param[in]    cmd_delay_ms   - time to wait for sensor hub to report status
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_write_cmd_with_data(uint8_t *cmd_bytes,
+		                   int cmd_bytes_len,
+                           uint8_t *data,
+						   int data_len,
+                           int cmd_delay_ms);
+
+
+/**
+* @brief	Func to read from sensor hub via sending generic command byte sequences
+*
+* @param[in]	cmd_bytes      - command byte sequence
+* @param[in]	cmd_bytes_len  - command byte sequence length in bytes
+* @param[in]    data           - data byte array to be sent following cmd bytes
+* @param[in]    data_len       - data array size in bytes
+* @param[out]   rxbuf          - byte buffer to store incoming data (including status byte)
+* @param[in]    rxbuf_sz       - incoming data buffer size in bytes ( to prevent overflow)
+* @param[in]    cmd_delay_ms   - time to wait for sensor hub to report status
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_read_cmd( uint8_t *cmd_bytes,
+		         int cmd_bytes_len,
+	             uint8_t *data,
+				 int data_len,
+	             uint8_t *rxbuf,
+				 int rxbuf_sz,
+                 int sleep_ms );
+
+
+/**
+* @brief	func to read sensor hub status
+* @param[out]	hubStatus   - pointer to output byte sesnor hub status will be written
+* @details	 ensor hub status byte:   [2:0] ->  0 : no Err ,              1: comm failure with sensor
+ *                                    [3]   ->  0 : FIFO below threshold; 1: FIFO filled to threshold or above.
+ *                                    [4]   ->  0 : No FIFO overflow;     1: Sensor Hub Output FIFO overflowed, data lost.
+ *                                    [5]   ->  0 : No FIFO overflow;     1: Sensor Hub Input FIFO overflowed, data lost.
+ *                                    [6]   ->  0 : Sensor Hub ready;     1: Sensor Hub is busy processing.
+ *                                    [6]   ->  reserved.
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_get_sensorhub_status(uint8_t *hubStatus);
+
+
+/**
+* @brief	func to read sensor operating mode
+*
+* @param[in]	hubMode   - pointer to output byte mode will be written
+* @details      0x00: application operating mode
+*               0x08: bootloader operating mode
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_get_sensorhub_operating_mode(uint8_t *hubMode);
+
+
+/**
+* @brief	func to set sensor hub operating mode
+*
+* @param[out]	hubMode   - pointer to output byte mode will be written
+* @details      0x00: application operating mode
+*               0x02: soft reset
+*               0x08: bootloader operating mode
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_set_sensorhub_operating_mode(uint8_t hubMode);
+
+
+/**
+* @brief	func to set sensorhub data output mode
+*
+* @param[in]	data_type : 1 byte output format
+* @details      outpur format 0x00 : no data
+ *                            0x01 : sensor data  SS_DATATYPE_RAW
+ *                            0x02 : algo data    SS_DATATYPE_ALGO
+ *                            0x03 : algo+sensor  SS_DATATYPE_BOTH
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_set_data_type(int data_type, bool sc_en);
+
+
+/**
+* @brief	func to get sensorhub data output mode
+*
+* @param[out]	data_type   - pointer to  byte, output format will be written to.
+*
+* @param[out]    sc_en     -  pointer to  boolean, sample count enable/disable status format will be written to.
+*                            If true, SmartSensor is prepending data with 1 byte sample count.
+*
+* @details      output format 0x00 : only algorithm data
+ *                            0x01 : only raw sensor data
+ *                            0x02 : algo + raw sensor data
+ *                            0x03 : no data
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_get_data_type(int *data_type, bool *sc_en);
+
+
+/**
+ * @brief	func to set the number of samples for the SmartSensor to collect
+ *			before issuing an mfio event reporting interrupt
+ *
+ * @param[in]	thresh - Number of samples (1-255) to collect before interrupt
+ *
+ * @return 1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_set_fifo_thresh( int threshold );
+
+
+/**
+ * @brief	func to get the number of samples the SmartSensor will collect
+ *			before issuing an mfio event reporting interrupt
+ *
+ * @param[out]	thresh - Number of samples (1-255) collected before interrupt
+ *
+ * @return 1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_get_fifo_thresh(int *thresh);
+
+
+/**
+ * @brief	func to check that the SmartSensor is connected
+ *
+ * @return 1 byte connection status 0x00: on connection
+ */
+int sh_ss_comm_check(void);
+
+
+/**
+* @brief	func to get the number of available samples in SmartSensor output FIFO
+*
+* @param[out]	numSamples -  number of data struct samples (1-255)
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_num_avail_samples(int *numSamples);
+
+
+/**
+* @brief	func to pull samples from SmartSensor output FIFO
+*
+* @param[in]	numSamples  - number of data struct samples to be pulled
+* @param[in]    sampleSize  - size of cumulative data sample struct (based on enabled sesnors+algorithms) in bytes
+* @param[out]   databuf     - buffer samples be written
+* @param[in]    databufSize - size of provided buffer size samples to be written
+*
+* @return 1 byte status: 0x00 (SS_SUCCESS) on success
+*/
+int sh_read_fifo_data( int numSamples, int sampleSize, uint8_t* databuf, int databufSz);
+
+
+/**
+ * @brief	func to set register of a device onboard SmartSensor
+ *
+ * @param[in] idx   - Index of device to read
+ * @param[in] addr  - Register address
+ * @param[in] val   - Register value
+ * @param[in] regSz - Size of sensor device register in bytes
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_set_reg(int idx, uint8_t addr, uint32_t val, int regSz);
+
+
+/**
+ * @brief	func to read register from a device onboard SmartSensor
+ *
+ * @param[in]  idx - Index of device to read
+ * @param[in]  addr - Register address
+ * @param[out] val - Register value
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_get_reg(int idx, uint8_t addr, uint32_t *val);
+
+
+// depricated: int sh_sensor_enable( int idx , int sensorSampleSz);
+/**
+ * @brief	func to enable a sensor device onboard SmartSensor
+ *
+ * @param[in] idx             - index of sensor device( i.e max8614x) to enable
+ * @param[in] sensorSampleSz  - sample size of sensor device( i.e max8614x) to enable
+ * @param[in] ext_mode        - enable extermal data input to Sensot Hub, ie accelerometer data for WHRM+WSPo2
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_sensor_enable( int idx , int sensorSampleSz , uint8_t ext_mode );
+
+
+/**
+ * @brief	func to disable a device on the SmartSensor
+ *
+ * @param[in] idx - Index of device
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_sensor_disable( int idx );
+
+
+/**
+ * @brief	func to get the total number of samples the input FIFO can hold
+ *
+ * @param[in] fifo_size - intger input FIFO capacity will be written to.
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_get_input_fifo_size(int *fifo_size);
+
+
+/**
+ * @brief	func to send ass external sensor data (accelerometer) to sensor hub's input FIFO
+ *
+ * @param[in]  tx_buf     - host sample data to be send to sensor hub input FIFO
+ * @param[in]  tx_buf_sz  - number of bytes of tx_buf
+ * @param[out] nb_written - number of samples succesfully written to sensor hub's input FIFO
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_feed_to_input_fifo(uint8_t *tx_buf, int tx_buf_sz, int *nb_written);
+
+
+/**
+ * @brief	func to get the total number of bytes in the sensor hub's input FIFO
+ *
+ * @param[in]  fifo_size - total number of sample bytes available in input FIFO
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_get_num_bytes_in_input_fifo(int *fifo_size);
+
+
+/**
+ * @brief	func to enable an algorithm on  SmartSensor
+ *
+ * @param[in] idx            - index of algorithm to enable
+ * @param[in] sensorSampleSz - sample size of algorithm to enable
+ *
+ * @details   idx -    0x00 : AGC
+ *                     0x01 : AEC
+ *                     0x02 : WHRM/Maximfast
+ *                     0x03 : ECG
+ *                     0x04 : BPT
+ *                     0x05 : SPo2
+ *                     0x06 : HRM/Maximfast finger
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_enable_algo(int idx , int algoSampleSz);
+
+/* @sh_enable_algo + mode of the algorithm:
+ *
+ *
+ *
+ * */
+int sh_enable_algo_withmode(int idx, int mode, int algoSampleSz);
+
+/**
+ * @brief	func to disable an algorithm on the SmartSensor
+ *
+ * @param[in] idx - index of algorithm to disable
+ *
+ * @return	1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_disable_algo(int idx);
+
+
+/**
+ * @brief	func to set the value of an algorithm configuration parameter
+ *
+ * @param[in] algo_idx   - index of algorithm
+ * @param[in] cfg_idx    - index of configuration parameter
+ * @param[in] cfg Array  - byte array of configuration
+ * @param[in] cfg_sz     - size of cfg array
+ *
+ * @return 1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_set_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz);
+
+
+/**
+ * @brief	func to get the value of an algorithm configuration parameter
+ *
+ * @param[in] algo_idx  - index of algorithm
+ * @param[in] cfg_idx   - index of configuration parameter
+ * @param[out] cfg      - array of configuration bytes to be filled in
+ * @param[in] cfg_sz    - number of configuration parameter bytes to be read
+ *
+ * @return 1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_get_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz);
+
+/**
+ * @brief   func to pull sensor, algo data sample bytes from sensor hub. outpur buffer, Content of the buffer depends on
+ *          enabled sensors, algorithms and their sample sizes.
+ *
+ * @param[out] databuf      - byte buffer to hold pulled samples
+ * @param[in]  databufLen   - size of provided databuf in bytes
+ * @param[out] nSamplesRea  - number of pulled samples in databuf
+ *
+ * @return N/A
+ */
+//void sh_ss_execute_once( uint8_t *databuf , int databufLen , int *nSamplesRead);
+int sh_ss_execute_once( uint8_t *databuf , int databufLen , int *nSamplesRead);
+
+
+
+
+
+
+/* ***************************************************************************************** *
+ *																							 *
+ *			PHASE2 ADDITIONS                     									         *
+ *                                                    										 *
+ * ***************************************************************************************** */
+
+
+/**
+ * @brief		run the self test commands
+ * param[in]	idx - the id of the sensor for the self test
+ * param[in]	result - self-test response
+ * param[in]	sleep_ms - duration of wait for read command
+ *
+ * @return		1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+SS_STATUS self_test(int idx, uint8_t *result, int sleep_ms = SS_DEFAULT_CMD_SLEEP_MS);
+int sh_self_test(int idx, uint8_t *result, int sleep_ms);
+
+
+/**
+ * @brief		transition from bootloder mode to application mode
+ *
+ * @return		1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_exit_from_bootloader(void);
+
+
+/**
+ * @brief		transition from application mode to bootloader mode
+ *
+ * @return		1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_put_in_bootloader(void);
+
+/**
+ * @brief	Check if SmartSensor is in bootloader mode
+ *
+ * @return	1 byte mode info : 1 if in bootloader mode, 0 if in main app, -1 if comm error
+ */
+int sh_checkif_bootldr_mode(void);
+
+/**
+* @brief	Get a string representing the SmartSensor firmware version
+* @details	If in bootloader mode, returns bootloader version
+*
+* @return   Pointer to firmware version string
+*/
+const char* sh_get_hub_fw_version(void);
+
+/**
+* @brief	Get a string representing the SmartSensor algo version
+* @details	If in bootloader mode, returns bootloader version
+*
+* @return   Pointer to algo version string
+*/
+const char* sh_get_hub_algo_version(void);
+
+
+/**
+ * @brief		send raw string to I2C
+ * @param[in]	rawdata - Raw data string, after slave address
+ * @param[out]	rawdata_sz - Raw data size
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int  sh_send_raw(uint8_t *rawdata, int rawdata_sz);
+
+/**
+ * @brief		get length of hub debug log data available
+ * @param[out]	log_len - length of hub log data available
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_get_log_len(int *log_len);
+
+
+/**
+ * @brief		read hub debug log data available
+ * @details	    first call sh_get_log_len() to get available log data in bytes then
+ *              call this function with parameter num_bytes with a value smaller then available log data in bytes
+ *
+ * @param[in]	num_bytes  - number of log data bytes to be read
+ * @param[in]	log_buf_sz - byte size of buffer log data will be dumped to
+ * @param[out]	log_buf    - byte buffer log data will be dumped to
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ */
+int sh_read_ss_log(int num_bytes, uint8_t *log_buf, int log_buf_sz);
+
+
+
+/**
+ * @brief		read sensor hub firmaware version
+ *
+ * @param[out]	fwDesciptor - byte array fw version will be written to
+ * @param[out]	fwDescSz    - array size of firmware descriptor in bytes
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_get_ss_fw_version(uint8_t *fwDesciptor  , uint8_t *fwDescSz);
+
+
+
+
+/* ***************************************************************************************** *
+ *																							 *
+ *			BOOTLOADER ADDITIONS                     									         *
+ *                                                    										 *
+ * ***************************************************************************************** */
+
+/**
+ * @brief		read sensor hub bootloader page size
+ *
+ * @param[out]	pagesz - page size in terms of bytes
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_get_bootloader_pagesz(int *pagesz);
+
+/**
+ * @brief		sends bootloader number of MSBL app pages to be send/flashed
+ *
+ * @param[in]	pageCount - page size in terms of bytes
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_set_bootloader_numberofpages(const int pageCount);
+
+/**
+ * @brief		sends bootloader iv vector dor decryption
+ *
+ * @param[in]	ivbytes - 22 character long iv byte vector
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_set_bootloader_iv(uint8_t iv_bytes[]);
+
+/**
+ * @brief		sends bootloader authentication data
+ *
+ * @param[in]	ivbytes - 36 character long authentication  data
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_set_bootloader_auth(uint8_t auth_bytes[]);
+
+/**
+ * @brief		erases ME11 Sensor hub app flash memory
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_set_bootloader_erase(void);
+
+/**
+ * @brief		sends MSBL page to sensor hub to be written to flash
+ *
+ * @param[in]   flashDataPreceedByCmdBytes - page bytes of page_size + 2 cmd bytes for flashing
+ * @param[in]   page_size                  - size of MSBL file app page
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_bootloader_flashpage(uint8_t *flashDataPreceedByCmdBytes , const int page_size);
+
+/**
+ * @brief		sends delay factor multipler to sensor hub for seting wait duration s between bootloade commands
+ *
+ * @param[in]   factor - delay factor multipler 1 to 4 practical
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_set_bootloader_delayfactor(const int factor );
+
+/**
+ * @brief		gets delay factor multipler to sensor hub for seting wait duration s between bootloade commands
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+
+const int sh_get_bootloader_delayfactor(void);
+
+/**
+ * @brief		sets sensor hub reset mode to commnad based reset or GPIO based reset. GPIO based is default and preferred.
+ *
+ * @param[in]   mode - mode flag 0: CMD 1: GPIO
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_set_ebl_mode(const uint8_t mode);
+
+/**
+ * @brief		gets sensor hub reset mode to commnad based reset or GPIO based reset. GPIO based is default and preferred.
+ *
+ * @return      1 byte ebl mode, 0: CMD , 1: GPIO
+ *
+ **/
+const int sh_get_ebl_mode(void);
+
+/**
+ * @brief		resets sensor hub mode to booloader mode
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_reset_to_bootloader(void);
+
+/**
+ * @brief		resets sensor hub mode to application mode
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+int sh_reset_to_main_app(void);
+
+/**
+ * @brief		command based exit from bootloader mode.
+ *
+ * @return      1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success
+ *
+ **/
+
+int exit_from_bootloader(void);
+
+/*FOR DEBUG DEPRICATED*/
+int sh_debug_reset_to_bootloader(void);
+
+
+/* *************************************************************************************** *
+ * DEMO SPECIFIC DECLERATIONS, NOT RELATED TO SENSOR HUB INTERFACE API.                    *
+ *                                                                                         *
+ *                                                                                         *                                                                                         *
+ * *****************************************************************************************/
+
+void sh_init_hwcomm_interface();
+bool sh_has_mfio_event(void);
+void sh_enable_irq_mfioevent(void);
+void sh_disable_irq_mfioevent(void);
+void sh_clear_mfio_event_flag(void);
+int sh_hard_reset(int wakeupMode);
+
+extern uint8_t sh_write_buf[];
+
+/*
+#ifdef __cplusplus
+}
+#endif
+*/
+
+
+
+#endif /* _SENSOR_HUB_H */
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SHMAX8614X/HostAccelHelper.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "HostAccelHelper.h"
+#include "mbed.h"
+#include "bmi160.h"
+#include "CircularBuffer.h"
+
+#define BUF_SIZE (32)
+
+I2C I2CM2(P5_7, P6_0); /* SDA, SCL */
+InterruptIn bmi160_int_pin(P3_6);
+BMI160_I2C bmi160_dev(&I2CM2, BMI160_I2C::I2C_ADRS_SDO_LO, &bmi160_int_pin);
+CircularBuffer<accel_data_t, BUF_SIZE> glbl_BMI160_QUEUE;
+
+
+static BMI160_I2C *pbmi160;
+
+
+
+
+void CSTMR_SH_HostAccelerometerInitialize() {
+	pbmi160 = &bmi160_dev;
+	pbmi160->reset();
+	glbl_BMI160_QUEUE.reset();
+	wait_ms(20);
+}
+
+
+void CSTMR_SH_HostAccelerometerSetDefaults() {
+	pbmi160->BMI160_DefaultInitalize();
+}
+
+int CSTMR_SH_HostAccelerometerSetSampleRate(int sampleRate) {
+	return pbmi160->setSampleRate(sampleRate);
+}
+
+int CSTMR_SH_HostAccelerometerEnableDataReadyInterrupt() {
+	return pbmi160->enable_data_ready_interrupt();
+}
+
+int CSTMR_SH_HostAccelerometerGet_sensor_xyz(accel_data_t *accel_data) {
+	int ret = 0;
+	BMI160::SensorData stacc_data = {0};
+
+	if(pbmi160 == NULL)
+		return -1;
+
+	if (pbmi160) {
+		ret = pbmi160->getSensorXYZ(stacc_data, BMI160::SENS_2G);
+		if (ret < 0)
+			return ret;
+	}
+
+	accel_data->x = stacc_data.xAxis.scaled;
+	accel_data->y = stacc_data.yAxis.scaled;
+	accel_data->z = stacc_data.zAxis.scaled;
+	accel_data->x_raw = stacc_data.xAxis.raw;
+	accel_data->y_raw = stacc_data.yAxis.raw;
+	accel_data->z_raw = stacc_data.zAxis.raw;
+
+	return ret;
+}
+
+
+int CSTMR_SH_HostAccelerometerEnqueueData(accel_data_t *accel_data) {
+	int ret = 0;
+	if(glbl_BMI160_QUEUE.full())
+		ret = -1;
+	else {
+		glbl_BMI160_QUEUE.push(*accel_data);
+	}
+	return ret;
+}
+
+int CSTMR_SH_HostAccelerometerGetDataCount() {
+	return glbl_BMI160_QUEUE.size();
+}
+
+int CSTMR_SH_HostAccelerometerDequeuData(accel_data_t *accel_data) {
+	int ret = 0;
+
+	if(glbl_BMI160_QUEUE.empty()) {
+		ret = -1;
+	} else {
+		glbl_BMI160_QUEUE.pop(*accel_data);
+	}
+	return ret;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SHMAX8614X/HostAccelHelper.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#ifndef _HOST_ACCEL_HELPER_H_
+#define _HOST_ACCEL_HELPER_H_
+
+#include <stdint.h>
+
+/* Struct defining the sample of accelerometer
+ * Note: as alogorithms expect data as mg or g ; calculations needs to be done over raws accel sensordata and convert to mg or g
+ *       acceld data is feed to sensor hub in mg or g format for all 3 axis,s data. Float definitions below are for mg and g
+ *       calculations and can be modified to work with fixed point data type.
+ *
+ * */
+typedef struct _accel_data_t {
+	float x;
+	float y;
+	float z;
+	int16_t x_raw;
+	int16_t y_raw;
+	int16_t z_raw;
+} accel_data_t;
+
+/**
+ * @brief	Initialize the accelerometer on the host device
+ */
+void CSTMR_SH_HostAccelerometerInitialize();
+
+/**
+ * @brief	Set default parameters for the accelerometer
+ */
+void CSTMR_SH_HostAccelerometerSetDefaults();
+
+/**
+ * @brief	Set the sampling rate of the accelerometer
+ *
+ *
+ * @return	0 on SUCCESS
+ */
+int CSTMR_SH_HostAccelerometerSetSampleRate(int sampleRate);
+
+/**
+ * @brief	Enable data ready interrupt of the accelerometer
+ *
+ *
+ * @return	0 on SUCCESS
+ */
+int CSTMR_SH_HostAccelerometerEnableDataReadyInterrupt();
+
+/**
+ * @brief	Gets a sample from the accelerometer if the sample is ready
+ *
+ *
+ * @return	0 on SUCCESS
+ */
+int CSTMR_SH_HostAccelerometerGet_sensor_xyz(accel_data_t *accel_data);
+
+/**
+ * @brief	Add the given sample to the accelerometer queue
+ *
+ *
+ * @return	0 on SUCCESS
+ */
+int CSTMR_SH_HostAccelerometerEnqueueData(accel_data_t *accel_data);
+
+/**
+ * @brief	Get the sample count in the accelerometer queue
+ *
+ *
+ * @return	0 on SUCCESS
+ */
+int CSTMR_SH_HostAccelerometerGetDataCount();
+
+/**
+ * @brief	Get a sample from the accelerometer queue
+ *
+ *
+ * @return	0 on SUCCESS
+ */
+int CSTMR_SH_HostAccelerometerDequeuData(accel_data_t *accel_data);
+
+
+
+
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SHMAX8614X/SH_Max8614x_BareMetal.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,887 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "SH_Max8614x_BareMetal.h"
+#include "SHComm.h"
+#include "HostAccelHelper.h"
+#include <string.h> //for memset
+#include <stdint.h>
+
+#include "demoDefinitions.h"
+
+/* Do not warn sign/unsigned miss alignment*/
+//#pragma warning (disable : 4018 )
+
+uint16_t HrmResult       = 0;
+uint8_t  HrmConfidence   = 0;
+
+//#define SERIALOUT printf
+#define DEBUG_INFO
+
+#if defined(DEBUG_INFO)
+	#define __DBGMESSAGE( str , val ) {printf(str, val);}
+#else
+	#define __DBGMESSAGE( str , val )
+#endif
+
+
+// Defines
+#define SSMAX8614X_REG_SIZE  		1
+#define SSMAX8614X_MODE1_DATASIZE  18				//Taken from API doc
+#define SSWHRM_MODE1_DATASIZE 		6				//Taken from API doc
+#define SSACCEL_MODE1_DATASIZE  	6				//Taken from API doc
+#define SSAGC_MODE1_DATASIZE  		0				//Taken from API doc
+#define SSBPT_MODE1_2_DATASIZE  	4				//Taken from API doc /* TODO */
+
+#define MIN_MACRO(a,b) ((a)<(b)?(a):(b))
+
+// sensor configuration
+//#define ENABLE_SENSOR_HUB_ACCEL
+#define USE_HOST_ACCEL
+// end of senor and algorithm configuration
+#define MAX_NUM_WR_ACC_SAMPLES			 5
+#define BMI160_SAMPLE_RATE				25
+// end of defines
+
+//function pointer use to perform arithmetic operation
+typedef void (*rx_data_callback)(uint8_t *);
+typedef struct {
+	int data_size;
+	rx_data_callback rx_data_parser;
+} ss_data_req;
+
+typedef struct {
+	int16_t x;
+	int16_t y;
+	int16_t z;
+} accel_mode1_data;
+
+typedef struct {
+	uint32_t led1;
+	uint32_t led2;
+	uint32_t led3;
+	uint32_t led4;
+	uint32_t led5;
+	uint32_t led6;
+} max8614x_mode1_data;
+
+typedef struct {
+	uint16_t hr;
+	uint8_t hr_conf;
+	uint16_t RESERVED;
+	uint8_t status;
+} whrm_mode1_data;
+
+
+typedef struct Max86140_SH_Status_Tracker {
+	uint8_t sensor_data_from_host;
+	uint8_t data_type_enabled;					// what type of data is enabled
+	uint8_t sample_count_enabled;				// does me11 provide sample count
+	uint32_t sample_count;
+	uint8_t data_buf_storage[512];				// store data read from SH
+	ss_data_req algo_callbacks[SH_NUM_CURRENT_ALGOS];
+	ss_data_req sensor_callbacks[SH_NUM_CURRENT_SENSORS];
+	uint8_t sensor_enabled_mode[SH_NUM_CURRENT_SENSORS];
+	uint8_t algo_enabled_mode[SH_NUM_CURRENT_ALGOS];
+	int input_fifo_size;
+} Max86140_SH_Status_Tracker_t;
+
+// Max8614x Default Callbacks
+void max8614x_data_rx(uint8_t* data_ptr)
+{
+	max8614x_mode1_data sample;
+	sample.led1 = (data_ptr[0] << 16) | (data_ptr[1] << 8) | data_ptr[2];
+	sample.led2 = (data_ptr[3] << 16) | (data_ptr[4] << 8) | data_ptr[5];
+	sample.led3 = (data_ptr[6] << 16) | (data_ptr[7] << 8) | data_ptr[8];
+	sample.led4 = (data_ptr[9] << 16) | (data_ptr[10] << 8) | data_ptr[11];
+	sample.led5 = (data_ptr[12] << 16) | (data_ptr[13] << 8) | data_ptr[14];
+	sample.led6 = (data_ptr[15] << 16) | (data_ptr[16] << 8) | data_ptr[17];
+
+	//SERIALOUT("led1=%.6X led2=%.6X led3=%.6X led4=%.6X led5=%.6X led6=%.6X\r\n",
+	//		sample.led1, sample.led2, sample.led3, sample.led4, sample.led5, sample.led6);
+
+	//enqueue(&max8614x_queue, &sample);
+}
+void whrm_data_rx(uint8_t* data_ptr) {
+	//See API doc for data format
+	whrm_mode1_data sample;
+	sample.hr = (data_ptr[0] << 8) | data_ptr[1];
+	sample.hr_conf = data_ptr[2];
+	sample.RESERVED = (data_ptr[3] << 8) | data_ptr[4];
+	sample.status = data_ptr[5];
+	HrmResult  = sample.hr / 10;
+	HrmConfidence = sample.hr_conf;
+	SERIALOUT("hr_c=%d\r\n", HrmResult);
+#if defined(DEBUG_INFO)
+	SERIALOUT("hr=%.1f conf=%d status=%d\r\n", (float)sample.hr / 10.0, sample.hr_conf, sample.status);
+#endif
+	//enqueue(&whrm_queue, &sample);
+}
+
+void accel_data_rx(uint8_t* data_ptr) {
+	//See API doc for data format
+	accel_mode1_data sample;
+	sample.x = (data_ptr[0] << 8) | data_ptr[1];
+	sample.y = (data_ptr[2] << 8) | data_ptr[3];
+	sample.z = (data_ptr[4] << 8) | data_ptr[5];
+#if defined(DEBUG_INFO)
+	//SERIALOUT("x:%d, y:%d, z:%d\r\n", sample.x, sample.y, sample.z);
+#endif
+}
+
+void agc_data_rx(uint8_t* data_ptr) {
+	//NOP: AGC does not collect data
+}
+// end of Max8614x Default Callbacks
+
+
+static Max86140_SH_Status_Tracker * get_config_struct() {
+
+    /* assigns a static adress to configuration struct*/
+	static Max86140_SH_Status_Tracker glbl_max8614x_status_track;
+	return &glbl_max8614x_status_track;
+}
+
+void initialize_config_struct() {
+	Max86140_SH_Status_Tracker *p_glbl_max8614x_status_track = get_config_struct();
+	/*
+	 * Desc: Configuration init flow, Perform this action at init stage of data acquisition. Raw sesnsor data buffer pointer is input to each
+	 *       enabled sensor/algorithm,s funtion that is responsible to extract numeric data from data byte stream from sensor hub.
+	 *
+	 *       - Append Sensor Raw Data structure with raw sensor data sample size and pointer to function of sensor that is reposible to parse
+	 *         data byte stream from sesnor hub and extract sensor numeric data.
+	 *       - Append accompanying sensors to main state of sensor. ie Accelerometer from Host with sensor data sample size and pointer to function of
+	 *         sensor that is reposible to parse data byte stream from sesnor hub and extract sensor numeric data.
+	 *       - Append algorithms to be enabled  with algorithm data sample size and pointer to function of
+	 *         algorithm that is reposible to parse data byte stream from sensor hub and extract sensor numeric data.
+	 *
+	 * */
+
+	//set all the values to 0
+	memset(p_glbl_max8614x_status_track, 0, sizeof(*p_glbl_max8614x_status_track));
+	// max8614x
+	p_glbl_max8614x_status_track->sensor_callbacks[SH_SENSORIDX_MAX8614X].data_size = SSMAX8614X_MODE1_DATASIZE;
+	p_glbl_max8614x_status_track->sensor_callbacks[SH_SENSORIDX_MAX8614X].rx_data_parser = &max8614x_data_rx;
+	// accelerometer
+	p_glbl_max8614x_status_track->sensor_callbacks[SH_SENSORIDX_ACCEL].data_size = SSACCEL_MODE1_DATASIZE;
+	p_glbl_max8614x_status_track->sensor_callbacks[SH_SENSORIDX_ACCEL].rx_data_parser = &accel_data_rx;
+	// whrm NOTE: do not register aec and scd as they do not have data reporter callbacks and defined within WHRM suite. Look at 8614c command table for aec/scd on/off !!!!
+	p_glbl_max8614x_status_track->algo_callbacks[SH_ALGOIDX_WHRM].data_size = SSWHRM_MODE1_DATASIZE;
+	p_glbl_max8614x_status_track->algo_callbacks[SH_ALGOIDX_WHRM].rx_data_parser = &whrm_data_rx;
+
+}
+
+
+void SH_Max8614x_get_reg(uint8_t addr, uint32_t *val) {
+	int status = sh_get_reg(SH_SENSORIDX_MAX8614X, addr, val);
+
+	if (status == 0) {
+		__DBGMESSAGE("\r\n reg_val=%02X err=0 \r\n", ((uint8_t)*val))
+	} else {
+		__DBGMESSAGE("\r\n err=%d\r\n", -1)
+	}
+
+	return;
+}
+
+int CSTMR_SH_FeedAccDataIntoSH(Max86140_SH_Status_Tracker_t *p_max8614x_status_track) {
+	static accel_data_t peek_buf[MAX_NUM_WR_ACC_SAMPLES];
+	static uint8_t tx_buf[MAX_NUM_WR_ACC_SAMPLES * sizeof(accel_mode1_data) + 2]; // 2 bytes for the command
+	if(!p_max8614x_status_track->sensor_data_from_host) {
+		return -1;
+	} else {
+		accel_data_t accel_data = {0};
+		accel_mode1_data acc_sample;
+		int num_tx, num_samples, num_bytes = 0, num_wr_bytes = 0;
+		int num_written_samples, nb_expected;
+		int ret = 0;
+
+		// get accelerometer data
+		ret = CSTMR_SH_HostAccelerometerGet_sensor_xyz(&accel_data);
+		if (ret < 0)
+			return ret;
+
+		if(CSTMR_SH_HostAccelerometerEnqueueData(&accel_data) != 0) {
+			__DBGMESSAGE("Thrown an accel sample\n", NULL)
+		}
+
+		if(CSTMR_SH_HostAccelerometerGetDataCount() < MAX_NUM_WR_ACC_SAMPLES) {
+			return -1;
+		}
+
+		ret = sh_get_num_bytes_in_input_fifo(&num_bytes);
+		if (ret != 0) {
+			__DBGMESSAGE("Unable to read num bytes in input fifo\r\n", NULL)
+			return -1;
+		}
+		num_tx = p_max8614x_status_track->input_fifo_size - num_bytes;
+		if (num_tx <= 0) {
+			__DBGMESSAGE("num_tx can't be negative\r\n",NULL)
+			return -1;
+		}
+		num_samples = num_tx / sizeof(accel_mode1_data);
+		num_samples = MIN_MACRO(num_samples, MAX_NUM_WR_ACC_SAMPLES);
+		num_tx = num_samples * sizeof(accel_mode1_data);
+		if (num_samples == 0) {
+			__DBGMESSAGE("Input FIFO is Full\r\n",NULL)
+			return -1;
+		}
+
+		for(int i = 0; i < num_samples; ++i) {
+			ret |= CSTMR_SH_HostAccelerometerDequeuData(&peek_buf[i]);
+		}
+		if (ret != 0) {
+			__DBGMESSAGE("CSTMR_SH_HostAccelerometerDequeuData failed\r\n",NULL)
+			return -1;
+		}
+
+
+		for (int i = 2, j = 0; j < num_samples; i+= sizeof(accel_mode1_data), j++) {
+			accel_data = peek_buf[j];
+			acc_sample.x = (int16_t)(accel_data.x*1000);
+			acc_sample.y = (int16_t)(accel_data.y*1000);
+			acc_sample.z = (int16_t)(accel_data.z*1000);
+			tx_buf[i] = acc_sample.x;
+			tx_buf[i + 1] = acc_sample.x >> 8;
+			tx_buf[i + 2] = acc_sample.y;
+			tx_buf[i + 3] = acc_sample.y >> 8;
+			tx_buf[i + 4] = acc_sample.z;
+			tx_buf[i + 5] = acc_sample.z >> 8;
+
+		}
+
+		ret = sh_feed_to_input_fifo(tx_buf, num_tx + 2, &num_wr_bytes);
+		if(ret != 0) {
+			__DBGMESSAGE("sh_feed_to_input_fifo\r\n",NULL)
+			return -1;
+		}
+		num_written_samples = num_wr_bytes / sizeof(accel_mode1_data);
+		if(num_written_samples != num_samples) {
+			__DBGMESSAGE("num_written_samples failed\r\n",NULL)
+			return -1;
+		}
+	}
+	return 0;
+}
+
+
+void SH_Max8614x_set_reg(uint8_t addr, uint32_t val) {
+	int status;
+	status = sh_set_reg(SH_SENSORIDX_MAX8614X, addr, val, SSMAX8614X_REG_SIZE);
+	__DBGMESSAGE("\r\n err=%d\r\n", status);
+}
+
+
+
+int SH_Max8614x_data_report_execute(void) {
+
+	int num_samples, databufLen;
+	uint8_t *databuf;
+
+
+	Max86140_SH_Status_Tracker_t *p_glbl_max8614x_status_track = get_config_struct();
+
+	// prepare the buffer to store the results
+	databuf = p_glbl_max8614x_status_track->data_buf_storage;
+	databufLen = sizeof(p_glbl_max8614x_status_track->data_buf_storage);
+
+	// poll SH
+	sh_ss_execute_once(databuf, databufLen, &num_samples);
+	//__DBGMESSAGE( "nsamplesFIFO: %d \r\n" , num_samples)
+
+	if(num_samples > 0 && num_samples <255) {
+		//Skip status byte
+		uint8_t *data_ptr = &databuf[1];
+
+		int i = 0;
+		for (i = 0; i < num_samples; i++) {
+			int sh_data_type = p_glbl_max8614x_status_track->data_type_enabled;
+			if (p_glbl_max8614x_status_track->sample_count_enabled) {
+				p_glbl_max8614x_status_track->sample_count = *data_ptr++;
+			}
+			//Chop up data and send to modules with enabled sensors
+			if (sh_data_type == SS_DATATYPE_RAW || sh_data_type == SS_DATATYPE_BOTH) {
+				for (int i = 0; i < SH_NUM_CURRENT_SENSORS; i++) {
+					if (p_glbl_max8614x_status_track->sensor_enabled_mode[i]) {
+						p_glbl_max8614x_status_track->sensor_callbacks[i].rx_data_parser(data_ptr);
+						data_ptr += p_glbl_max8614x_status_track->sensor_callbacks[i].data_size;
+					}
+				}
+			}
+			if (sh_data_type == SS_DATATYPE_ALGO || sh_data_type == SS_DATATYPE_BOTH) {
+				for (int i = 0; i < SH_NUM_CURRENT_ALGOS; i++) {
+					if (p_glbl_max8614x_status_track->algo_enabled_mode[i]) {
+						p_glbl_max8614x_status_track->algo_callbacks[i].rx_data_parser(data_ptr);
+						data_ptr += p_glbl_max8614x_status_track->algo_callbacks[i].data_size;
+					}
+				}
+			}
+		}
+        /* JUST*/
+		CSTMR_SH_FeedAccDataIntoSH(p_glbl_max8614x_status_track);
+	}
+	// feed accelerometer into me11
+	//////////////////CSTMR_SH_FeedAccDataIntoSH(p_glbl_max8614x_status_track);
+
+
+	return num_samples;
+}
+
+int SH_Max8614x_algo_init(enum enAlgoMode paramAlgoMode) {
+
+	/*
+	 *
+	 * */
+	int status;
+	Max86140_SH_Status_Tracker_t *p_glbl_max8614x_status_track = get_config_struct();
+	if(p_glbl_max8614x_status_track->algo_enabled_mode[SH_ALGOIDX_WHRM]) {
+		    __DBGMESSAGE("\r\n Algo already enabled\r\n",NULL)
+		return -1;
+	}
+
+	if(paramAlgoMode == kAlgoModeHeartRate) {
+		status = sh_enable_algo(SH_ALGOIDX_WHRM, SSWHRM_MODE1_DATASIZE);
+		if (status != SS_SUCCESS) {
+			__DBGMESSAGE("\r\n err=%d\r\n", COMM_GENERAL_ERROR)
+			__DBGMESSAGE("FAILED at line %d, enable whrm\n", __LINE__)
+			return status;
+		}
+		p_glbl_max8614x_status_track->algo_enabled_mode[SH_ALGOIDX_WHRM] = 0x01;
+	}
+}
+
+
+
+int SH_Max8614x_default_init(enum enAlgoMode paramAlgoMode) {
+	/*
+	 *  Desc: Initialization flow to get algorithm estimation results:
+	 *        1. initialize algorithm config struct
+	 *        2. enable data type to both raw sensor and algorithm data
+	 *        3. get input fifo size to learn fifo capacity
+	 *        4. set fifo threshold for mfio event frequency
+	 *        5. enable sensor to acquire ppg data
+	 *        6. enable accompanying accel sensor
+	 *        7. enable algorithm
+	 *        8. Sensor Hub now starts to write raw sensor/algorithm data to its data report FIFO which
+	 *           reports mfio event when data size determined by fifo threshold is written to report fifo
+	 *           data can be read by SH_Max8614x_data_report_execute function.
+	 *
+	 * */
+
+	int status;
+
+	// first initialize the global config struct
+	initialize_config_struct();
+	Max86140_SH_Status_Tracker_t *p_glbl_max8614x_status_track = get_config_struct();
+
+	// get input fifo size
+	status = sh_get_input_fifo_size(&p_glbl_max8614x_status_track->input_fifo_size);
+	if (status != SS_SUCCESS) {
+		__DBGMESSAGE("\r\n err=%d\r\n", COMM_GENERAL_ERROR)
+		__DBGMESSAGE("FAILED at line %d\n", __LINE__)
+		return COMM_GENERAL_ERROR;;
+	}
+
+	// enable both data stype
+	p_glbl_max8614x_status_track->data_type_enabled = SS_DATATYPE_BOTH;
+	p_glbl_max8614x_status_track->sample_count_enabled = false;
+	status = sh_set_data_type(p_glbl_max8614x_status_track->data_type_enabled,
+							  p_glbl_max8614x_status_track->sample_count_enabled);
+	if (status != 0) {
+		__DBGMESSAGE("\r\n err=%d\r\n", COMM_GENERAL_ERROR)
+		__DBGMESSAGE("FAILED at line %d\n", __LINE__)
+		return COMM_GENERAL_ERROR;
+	}
+
+	status = sh_set_fifo_thresh(5);
+	if (status != 0) {
+		__DBGMESSAGE("\r\n err=%d\r\n", COMM_GENERAL_ERROR)
+		__DBGMESSAGE("FAILED at line %d\n", __LINE__)
+		return COMM_GENERAL_ERROR;
+	}
+
+
+
+	status = sh_sensor_enable(SH_SENSORIDX_MAX8614X, SSMAX8614X_MODE1_DATASIZE, SH_INPUT_DATA_DIRECT_SENSOR);
+	if (status != 0) {
+		__DBGMESSAGE("\r\n err=%d\r\n",  COMM_GENERAL_ERROR)
+		__DBGMESSAGE("FAILED at line %d\n", __LINE__)
+		return COMM_GENERAL_ERROR;
+	}
+	p_glbl_max8614x_status_track->sensor_enabled_mode[SH_SENSORIDX_MAX8614X] = 0x01;
+
+#ifdef ENABLE_SENSOR_HUB_ACCEL
+	status = sh_sensor_enable(SH_SENSORIDX_ACCEL, SSACCEL_MODE1_DATASIZE, SH_INPUT_DATA_DIRECT_SENSOR);
+	if (status != SS_SUCCESS) {
+		__DBGMESSAGE("\r\n err=%d\r\n", COMM_GENERAL_ERROR)
+		__DBGMESSAGE("FAILED at line %d\n", __LINE__)
+	}
+	p_glbl_max8614x_status_track->sensor_data_from_host = false;
+	p_glbl_max8614x_status_track->sensor_enabled_mode[SH_SENSORIDX_ACCEL] = 0x01;
+#elif defined(USE_HOST_ACCEL)
+	CSTMR_SH_HostAccelerometerInitialize();
+	CSTMR_SH_HostAccelerometerSetDefaults();
+	status = CSTMR_SH_HostAccelerometerSetSampleRate(BMI160_SAMPLE_RATE);
+	if (status != 0) {
+		__DBGMESSAGE("Unable to set BMI160's sample rate\n",NULL)
+		__DBGMESSAGE("\r\n err=%d\r\n", COMM_GENERAL_ERROR)
+		__DBGMESSAGE("FAILED at line %d\n", __LINE__)
+		return status;
+	}
+
+	status = CSTMR_SH_HostAccelerometerEnableDataReadyInterrupt();
+	if(status != 0){
+		__DBGMESSAGE("Unable to enable BMI160 Interrupt, ret: %d\n", status)
+		return status;
+	}
+
+	status = sh_sensor_enable(SH_SENSORIDX_ACCEL, SSACCEL_MODE1_DATASIZE, SH_INPUT_DATA_FROM_HOST);
+	if (status != 0) {
+		__DBGMESSAGE("\r\n err=%d\r\n", COMM_GENERAL_ERROR)
+		__DBGMESSAGE("FAILED at line %d\n", __LINE__)
+		return status;
+	}
+	p_glbl_max8614x_status_track->sensor_data_from_host = true;
+	p_glbl_max8614x_status_track->sensor_enabled_mode[SH_SENSORIDX_ACCEL] = 0x01;
+#endif
+	status = SH_Max8614x_algo_init(paramAlgoMode);
+	if(status != 0) {
+		__DBGMESSAGE("AlgoInitFailed\r\n",NULL)
+	}
+
+	    __DBGMESSAGE("\r\n err=%d\r\n",  status)
+	return status;
+}
+
+void SH_Max8614x_stop() {
+
+	sh_disable_irq_mfioevent();
+	Max86140_SH_Status_Tracker_t *p_glbl_max8614x_status_track = get_config_struct();
+
+	for(int i = 0; i < SH_NUM_CURRENT_SENSORS; ++i) {
+		if(p_glbl_max8614x_status_track->sensor_enabled_mode[i]) {
+			p_glbl_max8614x_status_track->sensor_enabled_mode[i] = 0;
+			sh_sensor_disable(i);
+		}
+
+	}
+
+	for(int i = 0; i < SH_NUM_CURRENT_ALGOS; ++i) {
+		if(p_glbl_max8614x_status_track->algo_enabled_mode[i]) {
+			p_glbl_max8614x_status_track->algo_enabled_mode[i] = 0;
+			sh_disable_algo(i);
+		}
+	}
+
+	if(p_glbl_max8614x_status_track->sensor_data_from_host) {
+		CSTMR_SH_HostAccelerometerInitialize();
+		p_glbl_max8614x_status_track->sensor_data_from_host = 0;
+	}
+
+	sh_clear_mfio_event_flag();
+	sh_enable_irq_mfioevent();
+}
+
+
+
+
+
+
+/* **********************************************************************************************
+ * 																							   	*
+ *   					   COMMAND INTERFACE RELATED METHODS								 	*
+ *																								*
+ * **********************************************************************************************/
+
+
+
+//MYG: CHECK FOR STDIN WITH SSCANF < WHY THEY NEEDED PARSE_CMD?????   PAY ATTENTION: HEX AND/OR DECIMAL PARAMETER ENRTY!!!
+
+
+static int SH_Max8614x_set_singleparamcfg_(const char *cfg , const int algo_idx, const int cfg_idx , const int paramsz){
+	int status = -1;
+	uint32_t val;
+	if(paramsz == 1 || paramsz == 2) {
+    	if( sscanf(cfg, "%*s %*s %*s %10x", &val) == 1 ){
+    		uint8_t Temp[2] = { (uint8_t)((val >> 8) & 0xFF),  (uint8_t) (val & 0xFF) };
+    		status = sh_set_algo_cfg(algo_idx, cfg_idx , &Temp[2-paramsz], paramsz);
+    	}
+	}
+    return status;  // if command error return -1 if operational error return >0 error
+}
+
+
+static int SH_Max8614x_get_singleparamcfg_( const int algo_idx, const int cfg_idx ,const int paramsz, int *val){
+	// CMD: get_cfg spo2 samplerate
+
+	int tmp;
+	int status = -1;
+	uint8_t rxBuff[3]; // first byte is status 1/2 bytes cfgparam asked for.
+	if(paramsz == 1 || paramsz == 2) {
+	    status = sh_get_algo_cfg(algo_idx, cfg_idx, &rxBuff[0], paramsz+1);
+		if( status == 0){
+			tmp = (int)((rxBuff[1]<<(8*(paramsz-1))) + rxBuff[2]*(paramsz-1));  // MYG: CHECK IF TRUE!
+		}else
+			tmp = -1;
+	}else
+		tmp = -1;
+
+	*val = tmp;
+	return status;
+}
+
+
+
+
+
+int SH_Max8614x_set_ppgreg(const char *addr_value_args){
+
+	//CMD: set_reg ppgsensor 0xAA 0xAA
+	int addr,val,status;
+	if( sscanf(addr_value_args,"%*s %*s %4x %10x", &addr , &addr ) == 2 ){
+        status = sh_set_reg(SH_SENSORIDX_MAX8614X, (uint8_t) addr, (uint32_t) val, SSMAX8614X_REG_SIZE);
+        if(status == 0)
+        	SERIALOUT("OK \r\n");
+	}else
+		    SERIALOUT("ERR \r\n");
+
+    return status;
+}
+
+int SH_Max8614x_get_ppgreg(const char *addr_arg){
+
+	//CMD: get_reg ppgsensor 0xAA
+	int addr;
+	int status = -1;
+	uint32_t val;
+
+	if( sscanf(addr_arg,"%*s %*s %4x", &addr) == 1 ){
+		int status = sh_get_reg(SH_SENSORIDX_MAX8614X, (uint8_t) addr, &val);
+        if(status == 0)
+        	SERIALOUT("reg_val=%02X \r\n",val);
+	}else
+		    SERIALOUT("ERR \r\n");
+
+    return status;
+}
+
+int SH_Max8614x_self_test_ppg(const char *null_arg){
+
+	// MYG: mfio interaction needed!
+    return -1;
+}
+
+int SH_Max8614x_self_test_acc(const char *null_arg){
+	// MYG: mfio interaction needed!
+	return -1;
+}
+
+//************************************WHRM METHODS***********************************************/
+
+int SH_Max8614x_get_whrm_dataformat(const char *null_arg){
+
+	 SERIALOUT("\r\n  format={smpleCnt,16},"
+		"{grnCnt,20},{grn2Cnt,20},{accelX,14,3},{accelY,14,3},"
+		"{accelZ,14,3},{hr,12},{hrconf,8},{spo2,11,1},{activity,8} err=0\r\n" );
+      return 0;
+}
+
+int SH_Max8614x_measure_whrm(const char *null_arg){
+
+	 int status;
+	 SH_Max8614x_stop();
+	 status = SH_Max8614x_default_init(kAlgoModeHeartRate);
+	 if(status == 0)
+		 SERIALOUT("whrm started \r\n");
+	 else
+		 SERIALOUT("ERR");
+
+     return status;
+}
+
+int SH_Max8614x_set_whrm_aecusage(const char *onoff_arg){
+
+	int status = SH_Max8614x_set_singleparamcfg_( onoff_arg , SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_AEC_ENABLE , 1 );
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	if( status == -1)
+    		SERIALOUT("CMDERR \r\n");
+    	else
+    		SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+
+int SH_Max8614x_get_whrm_aecusage(const char *null_arg){
+
+	int val;
+	int status =  SH_Max8614x_get_singleparamcfg_( SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_AEC_ENABLE, 1 , &val);
+    if(val != -1)
+    	SERIALOUT("whrm_aec_usage= %d", val);
+    else
+    	SERIALOUT("ERR \r\n");
+
+    return status;
+
+}
+
+int SH_Max8614x_set_whrm_scdusage(const char *onoff_arg){
+
+	int status = SH_Max8614x_set_singleparamcfg_( onoff_arg , SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_SCD_ENABLE, 1 );
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	if( status == -1)
+    		SERIALOUT("CMDERR \r\n");
+    	else
+    		SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+
+
+int SH_Max8614x_get_whrm_scdusage(const char *null_arg){
+
+	int val;
+	int status =  SH_Max8614x_get_singleparamcfg_( SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_SCD_ENABLE, 1 , &val);
+    if(val != -1)
+    	SERIALOUT("whrm_scd_usage= %d", val);
+    else
+    	SERIALOUT("ERR \r\n");
+
+    return status;
+
+}
+
+int SH_Max8614x_set_whrm_scdadjperiod(const char *period_arg){
+
+	int status = SH_Max8614x_set_singleparamcfg_(period_arg , SH_ALGOIDX_WHRM , SS_CFGIDX_WHRM_ADJ_TARGET_PD_CURRENT_PERIOD , 2);
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	if( status == -1)
+    		SERIALOUT("CMDERR \r\n");
+    	else
+    		SERIALOUT("ERR \r\n");
+    }
+    return status;
+}
+
+int SH_Max8614x_get_whrm_scdadjperiod(const char *null_arg){
+
+	int val;
+	int status =  SH_Max8614x_get_singleparamcfg_( SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_ADJ_TARGET_PD_CURRENT_PERIOD, 2, &val);
+    if(val != -1)
+    	SERIALOUT("whrm_scd_adjperiod= 0x%x", val);
+    else
+    	SERIALOUT("ERR \r\n");
+
+    return status;
+
+}
+
+int SH_Max8614x_set_whrm_scddebouncewin(const char *dwindow_arg){
+
+	int status = SH_Max8614x_set_singleparamcfg_(dwindow_arg , SH_ALGOIDX_WHRM , SS_CFGIDX_WHRM_SCD_DEBOUNCE_WINDOW , 2);
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	if( status == -1)
+    		SERIALOUT("CMDERR \r\n");
+    	else
+    		SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+int SH_Max8614x_get_whrm_scddebouncewin(const char *null_arg){
+
+	int val;
+	int status =  SH_Max8614x_get_singleparamcfg_( SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_SCD_DEBOUNCE_WINDOW , 2, &val);
+    if(val != -1)
+    	SERIALOUT("whrm_scd_debouncewin= 0x%x", val);
+    else
+    	SERIALOUT("ERR \r\n");
+
+    return status;
+
+}
+
+int SH_Max8614x_set_whrm_motionthresh(const char *motion_arg){
+
+	int status = SH_Max8614x_set_singleparamcfg_(motion_arg , SH_ALGOIDX_WHRM , SS_CFGIDX_WHRM_MOTION_MAG_THRESHOLD , 2);
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	if( status == -1)
+    		SERIALOUT("CMDERR \r\n");
+    	else
+    		SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+
+int SH_Max8614x_get_whrm_motionthresh(const char *null_arg){
+
+	int val;
+	int status =  SH_Max8614x_get_singleparamcfg_( SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_MOTION_MAG_THRESHOLD , 2, &val);
+    if(val != -1)
+    	SERIALOUT("whrm_motion_threshold= 0x%x", val);
+    else
+    	SERIALOUT("ERR \r\n");
+
+    return status;
+
+}
+
+int SH_Max8614x_set_whrm_minpdiodecurr(const char *curr_arg){
+
+	int status = SH_Max8614x_set_singleparamcfg_(curr_arg, SH_ALGOIDX_WHRM , SS_CFGIDX_WHRM_MIN_PD_CURRENT , 2);
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	if( status == -1)
+    		SERIALOUT("CMDERR \r\n");
+    	else
+    		SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+
+int SH_Max8614x_get_whrm_minpdiodecurr(const char *null_arg){
+
+	int val;
+	int status =  SH_Max8614x_get_singleparamcfg_( SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_MIN_PD_CURRENT , 2, &val);
+    if(val != -1)
+    	SERIALOUT("whrm_currentrange= %d", val);  // MYG: CHECKIF EXPRESSION IS TRUE!
+    else
+    	SERIALOUT("ERR \r\n");
+
+    return status;
+
+}
+
+int SH_Max8614x_set_whrm_pdiodeconfig(const char *cfg_arg){
+
+	int status = SH_Max8614x_set_singleparamcfg_( cfg_arg , SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_PD_CONFIG , 1 );
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	if( status == -1)
+    		SERIALOUT("CMDERR \r\n");
+    	else
+    		SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+
+int SH_Max8614x_get_whrm_pdiodeconfig(const char *null_arg){
+
+	int val;
+	int status =  SH_Max8614x_get_singleparamcfg_( SH_ALGOIDX_WHRM, SS_CFGIDX_WHRM_PD_CONFIG, 1 , &val);
+    if(val != -1)
+    	SERIALOUT("whrm_pdiode_config= %d", val);
+    else
+    	SERIALOUT("ERR \r\n");
+
+    return status;
+
+}
+
+int SH_Max8614x_stop_acquisition(const char *null_arg){
+	      SH_Max8614x_stop();
+}
+
+
+
+/*FOR THIS DEMO PURPOSE*/
+int Max8614x_Set_WSPO2Mode(int mode){
+
+	uint8_t Temp[1] = { (uint8_t)(mode) };
+	int status = sh_set_algo_cfg(SH_ALGOIDX_WSPO2, SS_CFGIDX_WSPO2_ALGO_MODE , &Temp[0], 1);
+    return status;
+
+}
+
+
+#if defined(RAW_DATA_ONLY)
+
+int SH_Max8614x_disable_whrm (const char *onoff_arg){
+
+	int status = sh_disable_algo(SH_ALGOIDX_WHRM);
+    if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+
+int SH_Max8614x_enable_pureraw(const char *onoff_arg){
+
+	int status;
+
+	status = sh_disable_algo(SH_ALGOIDX_WHRM);
+	wait_ms(500);
+	status = sh_set_data_type(SS_DATATYPE_RAW ,	false);
+	status = sh_set_fifo_thresh(5);
+	status = sh_sensor_enable(SH_SENSORIDX_MAX8614X, SSMAX8614X_MODE1_DATASIZE, SH_INPUT_DATA_DIRECT_SENSOR);
+
+	if( status == 0)
+    	SERIALOUT("OK \r\n");
+    else {
+    	SERIALOUT("ERR \r\n");
+    }
+    return status;
+
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SHMAX8614X/SH_Max8614x_BareMetal.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,401 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef SH_Max8614x_BareMetal_H_
+#define SH_Max8614x_BareMetal_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include "demoDefinitions.h"
+
+
+#define COMM_SUCCESS        0
+#define COMM_GENERAL_ERROR  -1
+#define COMM_INVALID_PARAM  -254
+#define COMM_NOT_RECOGNIZED -255
+
+enum enAlgoMode{
+	kAlgoModeHeartRate = 0,
+	reinitHeartRate    = 1,
+};
+
+/**
+ * @brief	Get the value of register at addr
+ *
+ * @param[in]	addr - adress of the register
+ * @param[out]	val - value at the register
+
+ */
+void SH_Max8614x_get_reg(uint8_t addr, uint32_t *val);
+
+/**
+* @brief	Write a value to the register at address addr
+*
+* @param[in]	addr - adress of the register to write
+* @param[in]	val - value of the register to write
+*/
+void SH_Max8614x_set_reg(uint8_t addr, uint32_t val);
+
+/**
+* @brief	Initialize Max86140 with default configuration
+*
+* @param[in] paramAlgoMode - the mode of the algorithm to initialize
+*
+* @return 0 on SUCCESS
+*/
+int SH_Max8614x_default_init(enum enAlgoMode paramAlgoMode);
+
+/**
+* @brief	Check the data stored in the Sensor Hub. Reads and prints
+* 			the data if available
+*
+*/
+int SH_Max8614x_data_report_execute(void);
+
+/**
+* @brief	Stops the active sensors and algorithms
+*
+*/
+void SH_Max8614x_stop(void);
+
+
+extern uint16_t HrmResult;
+extern uint8_t  HrmConfidence;
+
+
+/* define to see debug messages*/
+//#define DEBUG_INFO
+
+/**
+* @brief	gets the data format of reported whrm algo result sample , in form of struct fields with number of bits they are represented.
+*
+* @param[in] null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return 0
+*/
+int SH_Max8614x_get_whrm_dataformat(const char *null_arg);
+
+
+/**
+* @brief	sets the register value of ppg sensor (8614x is connected to ME11 SENSOR HUB for this demo but can be used for all sensors physically
+*           connected to ME11 SENSOR HUB).
+*
+* @param[in] addr_value_args : byte string including command followed by register address in hex and register value in hex
+*                              "set_reg ppgsensor 0xAB 0xCD" or "set_reg ppgsensor AB CD"
+*
+* @return 0x00 on success and prints on command console
+*/
+int SH_Max8614x_set_ppgreg(const char *addr_value_args);
+
+/**
+* @brief	gets the register value of ppg sensor (8614x is connected to ME11 SENSOR HUB for this demo but can be used for all sensors physically
+*           connected to ME11 SENSOR HUB).
+*
+* @param[in] addr_arg: byte string including command followed by register address in hex
+*                      "set_reg ppgsensor 0xAB" or "set_reg ppgsensor AB"
+*
+* @return 0x00 on success and prints register value on command console
+*/
+int SH_Max8614x_get_ppgreg(const char *addr_arg);
+
+/**
+* @brief	  initalizes and starts whrm measurement from ME11 SENSOR HUB.
+*             It default initilizes datatype(to BOTH) input fifo lenght(to 5 , this is FIFO used by accel data from host)
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+** @return 0x00 on success and prints status on command console
+*/
+int SH_Max8614x_measure_whrm(const char *null_arg);
+
+
+/**
+* @brief	  starts self test of ppg sensor
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+** @return 0x00 on success and prints status on command console
+*/
+int SH_Max8614x_self_test_ppg(const char *null_arg);
+
+/**
+* @brief	  starts self test of accelerometer sensor physically connected to ME11 SENSOR HUB
+*             NOTE:Not supported within this demo as Customer is assumed to feed accel data from HOST.
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+** @return 0x00 on success and prints status on command console
+*/
+int SH_Max8614x_self_test_acc(const char *null_arg);
+
+/**
+* @brief	  sets the aec algo usage of SPO2 algorithm
+*
+* @param[in]  onoff_arg : byte string including command followed by mode value in HEX uo to 1 hexadecimal digits.
+*                         "set_cfg whrm aecenable 0/1"  0:off 1: On
+*
+*@return  status info, 0x00 on success
+*
+**/
+int SH_Max8614x_set_whrm_aecusage(const char *onoff_arg);
+
+/**
+* @brief	  gets the aec algo usage of SPO2 algorithm
+*             prints aec algo usage usage on/off value commnad console. 0 : Off 1: On
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_Max8614x_get_whrm_aecusage(const char *null_arg);
+
+/**
+* @brief	  sets the skin contact detection usage of SPO2 algorithm
+*
+* @param[in]  onoff_arg : byte string including command followed by mode value in HEX uo to 1 hexadecimal digits.
+*                         "set_cfg whrm aecenable 0/1"  0:off 1: On
+*
+*@return  status info, 0x00 on success
+*
+**/
+int SH_Max8614x_set_whrm_scdusage(const char *onoff_arg);
+
+/**
+* @brief	  gets the skin contact detection usage  of SPO2 algorithm
+*             prints skin contact detection usage on/off value commnad console. 0 : Off 1: On
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_Max8614x_get_whrm_scdusage(const char *null_arg);
+
+/**
+* @brief	  sets the adjustment period parameter for skin contact detection for SPO2 algorithm.
+*
+* @param[in]  period_arg : byte string including command followed by period value in HEX up to 4 hexadecimal digits.
+*                          "set_cfg whrm scdadjperiod 0xABCD"
+*
+* @return status info, 0x00 on success.
+**/
+int SH_Max8614x_set_whrm_scdadjperiod(const char *period_arg);
+
+/**
+* @brief	  Gets the adjustment period parameter for skin contact detection for SPO2 algorithm.
+*             prints SPo2 period value on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+*
+**/
+int SH_Max8614x_get_whrm_scdadjperiod(const char *null_arg);
+
+/**
+* @brief	  sets the  debounce window parameter for skin contact detection for SPO2 algorithm.
+*
+* @param[in]  dwindow_arg : byte string including command followed by debounce window value in HEX up to 4 hexadecimal digits.
+*                          "set_cfg whrm scddebouncewin 0xABCD"
+*
+* @return status info, 0x00 on success.
+**/
+int SH_Max8614x_set_whrm_scddebouncewin(const char *dwindow_arg);
+
+/**
+* @brief	  gets the  debounce window parameter for skin contact detection for SPO2 algorithm.
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_Max8614x_get_whrm_scddebouncewin(const char *null_arg);
+
+
+/**
+* @brief	  sets the motion threshold parameter for WHRM algorithm.
+*
+* @param[in]  timeout_arg : byte string including command followed by motion threshold value in HEX up to 4 hexadecimal digits.
+*                           "set_cfg whrm motionthreshold 0xABCD"
+*
+* @return status info, 0x00 on success.
+*
+**/
+int SH_Max8614x_set_whrm_motionthresh(const char *motion_arg);
+
+/**
+* @brief	  Gets the motion threshold for WHRM algorithm. prints WHRM algorith motion threshold value on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+*
+**/
+int SH_Max8614x_get_whrm_motionthresh(const char *null_arg);
+
+/**
+* @brief	  sets the minimum photodiode current parameter for WHRM algorithm.
+*
+* @param[in]  curr_arg : byte string including command followed by diode current value in HEX up to 4 hexadecimal digits.
+*                           "set_cfg whrm motionthreshold 0xABCD"
+*
+* @return status info, 0x00 on success.
+*
+**/
+int SH_Max8614x_set_whrm_minpdiodecurr(const char *curr_arg);
+
+/**
+* @brief	  Gets the minimum photodiode current parameter for WHRM algorithm. prints WHRM algorithm photodiode current parameter value on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+*
+**/
+int SH_Max8614x_get_whrm_minpdiodecurr(const char *null_arg);
+
+/**
+* @brief	  sets the sensor photodiode configuration for WHRM algorithm.
+*
+* @param[in]  pdcfg_arg : byte string including command followed by photodiode configuration value in HEX up to 1 hexadecimal digits.
+                          "set_cfg whrm pdconfig 0xA" or "set_cfg whrm pdconfig A"
+*
+* @return status info, 0x00 on success.
+**/
+int SH_Max8614x_set_whrm_pdiodeconfig(const char *cfg_arg);
+
+/**
+* @brief	  Gets the sensor photodiode configuration for WHRM algorithm. prints WHRM algorithm photodiode configuration  on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+*
+**/
+int SH_Max8614x_get_whrm_pdiodeconfig(const char *null_arg);
+
+/**
+* @brief	  Sends raw byte stream to ME11 SENSOR HUB. For debug purposes mainly.
+*
+* @param[in]  raw_data : byte stream to be send
+*
+* @return status info, 0x00 on success.
+*
+**/
+//int SH_Max8614x_send_raw(const char *raw_data);
+
+
+
+/**
+* @brief	  Stops sensor+algorithm data acquisition and operation for all algorithms of ME11 sensor HUB .
+*             Mainly for use in this demo code!!
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+*
+**/
+int SH_Max8614x_stop_acquisition(const char *null_arg);
+
+
+#if defined(RAW_DATA_ONLY)
+	int SH_Max8614x_disable_whrm(const char *onoff_arg);
+	int SH_Max8614x_enable_pureraw(const char *onoff_arg);
+    #define NUMCMDS8614X (24)
+#else
+	#define NUMCMDS8614X (22)
+#endif
+
+/*Number of commands accosicated with 8614x sesnor command table*/
+
+#define CONSOLE_STR_BUF_SZ  ((int)1024);
+
+
+typedef int (*cmdExecFunc)( const char*); // typedef void (*cmdExecFunc)( const void*);
+
+typedef struct {
+	char const* cmdStr;
+	cmdExecFunc execute;
+	char const *help;
+}cmd_interface_t;
+
+
+static int command_help(const char *str);
+
+
+const cmd_interface_t CMDTABLE8614x[] = {
+
+		{  "get_format whrmdata"     		, SH_Max8614x_get_whrm_dataformat		,  "returns whrm algo sample format in terms of bit fileds"												},
+		{  "enable_measurement whrm" 		, SH_Max8614x_measure_whrm 				,  "start whrm measurement with default settings"  														},
+		{  "get_reg ppgsensor"       		, SH_Max8614x_get_ppgreg 				,  "get register value of 8614x sensor, usage:  get_reg ppgsensor rAddr(1byte)" 						},
+		{  "set_reg ppgsensor"       		, SH_Max8614x_set_ppgreg 				,  "set register value of 8614x sensor, usage :  set_reg ppgsensor rAddr(1byte) rval(1byte)" 			},
+		{  "self_test ppgsensor"     		, SH_Max8614x_self_test_ppg 			,  "starts self test of onboard ppg sensor" 															},
+		{  "self_test accel"         		, SH_Max8614x_self_test_acc 			,  "starts self test of onboard accel sensor" 															},
+		{  "set_cfg whrm aecenable"         , SH_Max8614x_set_whrm_aecusage       	,  "on/off whrm aec algo,  usage: set_cfg whrm aec X , X: 0 off 1 on" 									},
+		{  "get_cfg whrm aecenable"         , SH_Max8614x_get_whrm_aecusage       	,  "check if aec algo for whrm is on/off" 																},
+        {  "set_cfg whrm scdenable"         , SH_Max8614x_set_whrm_scdusage      	,  "on/off whrm skin contact detection,  usage: set_cfg whrm scd X , X: 0 off 1 on" 					},
+		{  "get_cfg whrm scdenable"         , SH_Max8614x_get_whrm_scdusage       	,  "check if whrm skin contact detection is on/off" 													},
+        {  "set_cfg whrm scdadjperiod"      , SH_Max8614x_set_whrm_scdadjperiod     ,  "sets photo diode adj peroiod for whrm scd algo, usage:  set_cfg whrm scdadjperiod period(numeric)" 	},
+		{  "get_cfg whrm scdadjperiod"      , SH_Max8614x_get_whrm_scdadjperiod     ,  "gets photo diode adj peroiod for whrm scd algo" 													},
+		{  "set_cfg whrm scddebouncewin"    , SH_Max8614x_set_whrm_scddebouncewin   ,  "sets debounce window for whrm scd algo, usage:  set_cfg whrm scddebouncewin window(numeric)" 		},
+		{  "get_cfg whrm scddebouncewin"    , SH_Max8614x_get_whrm_scddebouncewin   ,  "gets debounce window for whrm scd algo" 															},
+		{  "set_cfg whrm motionthreshold"   , SH_Max8614x_set_whrm_motionthresh 	,  "sets motion threshold for whrm, usage:  set_cfg whrm motionthreshold threshold(numeric)" 			},
+		{  "get_cfg whrm motionthreshold"  	, SH_Max8614x_get_whrm_motionthresh 	,  "gets motion threshold for whrm" 																	},
+		{  "set_cfg whrm minpdcurrent"      , SH_Max8614x_set_whrm_minpdiodecurr 	,  "sets photodiode current range for whrm, usage:  set_cfg whrm minpdcurrent current(numeric)" 		},
+		{  "get_cfg whrm minpdcurrent"  	, SH_Max8614x_get_whrm_minpdiodecurr 	,  "gets photodiode current rangefor whrm" 																},
+        {  "set_cfg whrm pdconfig"          , SH_Max8614x_set_whrm_pdiodeconfig 	,  "sets photdiode config for whrm, usage:  set_cfg whrmaecscd pdconfig configstring" 					},
+		{  "get_cfg whrm pdconfig"          , SH_Max8614x_get_whrm_pdiodeconfig 	,  "gets photdiode config for whrm" 																	},
+		{  "stop"                           , SH_Max8614x_stop_acquisition          ,  "stops raw&algorithm data acquisition within 8614x instance of hub"                            		},
+		{  "help"                           , command_help          		        ,  "commnand info" 																						},
+#if defined(RAW_DATA_ONLY)
+		{  "disable_whrm"                  , SH_Max8614x_disable_whrm               ,  "disable algorithms" 																				},
+		{  "enable_raw_only"               , SH_Max8614x_enable_pureraw             ,  "enable just raw ppg data" 																				},
+#endif
+		//		{  "send_raw"                       , SH_Max8614x_send_raw 					,  "sends raw data to sensor hub, usage: send_raw datastring" 									},
+};
+
+
+static int command_help(const char *str){
+	int cmdIdx = 0;
+
+	SERIALOUT("AVAILABLE COMMANDS: \r\n\r\n");
+	while( cmdIdx != NUMCMDS8614X){
+		SERIALOUT(" %s : \r\n  %s \r\n\r\n", CMDTABLE8614x[cmdIdx].cmdStr , CMDTABLE8614x[cmdIdx].help );
+        cmdIdx++;
+	};
+
+}
+
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/accelerometer/bmi160.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,724 @@
+/**********************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+
+#include "bmi160.h"
+
+
+const struct BMI160::AccConfig BMI160::DEFAULT_ACC_CONFIG = {SENS_2G,
+                                                             ACC_US_OFF,
+                                                             ACC_BWP_2,
+                                                             ACC_ODR_8};
+
+const struct BMI160::GyroConfig BMI160::DEFAULT_GYRO_CONFIG = {DPS_2000,
+                                                               GYRO_BWP_2,
+                                                               GYRO_ODR_8};
+
+
+//*****************************************************************************
+int32_t BMI160::setSensorPowerMode(Sensors sensor, PowerModes pwrMode)
+{
+    int32_t rtnVal = -1;
+
+    switch(sensor)
+    {
+        case MAG:
+            rtnVal = writeRegister(CMD, (MAG_SET_PMU_MODE | pwrMode));
+        break;
+
+        case GYRO:
+            rtnVal = writeRegister(CMD, (GYR_SET_PMU_MODE | pwrMode));
+        break;
+
+        case ACC:
+            rtnVal = writeRegister(CMD, (ACC_SET_PMU_MODE | pwrMode));
+        break;
+
+        default:
+            rtnVal = -1;
+        break;
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::setSensorConfig(const AccConfig &config)
+{
+    uint8_t data[2];
+
+    data[0] = ((config.us << ACC_US_POS) | (config.bwp << ACC_BWP_POS) |
+               (config.odr << ACC_ODR_POS));
+    data[1] = config.range;
+
+    return writeBlock(ACC_CONF, ACC_RANGE, data);
+}
+
+
+//*****************************************************************************
+int32_t BMI160::setSensorConfig(const GyroConfig &config)
+{
+    uint8_t data[2];
+
+    data[0] = ((config.bwp << GYRO_BWP_POS) | (config.odr << GYRO_ODR_POS));
+    data[1] = config.range;
+
+    return writeBlock(GYR_CONF, GYR_RANGE, data);
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorConfig(AccConfig &config)
+{
+    uint8_t data[2];
+    int32_t rtnVal = readBlock(ACC_CONF, ACC_RANGE, data);
+
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        config.range = static_cast<BMI160::AccRange>(
+        (data[1] & ACC_RANGE_MASK));
+        config.us = static_cast<BMI160::AccUnderSampling>(
+        ((data[0] & ACC_US_MASK) >> ACC_US_POS));
+        config.bwp = static_cast<BMI160::AccBandWidthParam>(
+        ((data[0] & ACC_BWP_MASK) >> ACC_BWP_POS));
+        config.odr = static_cast<BMI160::AccOutputDataRate>(
+        ((data[0] & ACC_ODR_MASK) >> ACC_ODR_POS));
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorConfig(GyroConfig &config)
+{
+    uint8_t data[2];
+    int32_t rtnVal = readBlock(GYR_CONF, GYR_RANGE, data);
+
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        config.range = static_cast<BMI160::GyroRange>(
+        (data[1] & GYRO_RANGE_MASK));
+        config.bwp = static_cast<BMI160::GyroBandWidthParam>(
+        ((data[0] & GYRO_BWP_MASK) >> GYRO_BWP_POS));
+        config.odr = static_cast<BMI160::GyroOutputDataRate>(
+        ((data[0] & GYRO_ODR_MASK) >> GYRO_ODR_POS));
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorAxis(SensorAxis axis, AxisData &data, AccRange range)
+{
+    uint8_t localData[2];
+    int32_t rtnVal;
+
+    switch(axis)
+    {
+        case X_AXIS:
+            rtnVal = readBlock(DATA_14, DATA_15, localData);
+        break;
+
+        case Y_AXIS:
+            rtnVal = readBlock(DATA_16, DATA_17, localData);
+        break;
+
+        case Z_AXIS:
+            rtnVal = readBlock(DATA_18, DATA_19, localData);
+        break;
+
+        default:
+            rtnVal = -1;
+        break;
+    }
+
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        data.raw = ((localData[1] << 8) | localData[0]);
+        switch(range)
+        {
+            case SENS_2G:
+                data.scaled = (data.raw/SENS_2G_LSB_PER_G);
+            break;
+
+            case SENS_4G:
+                data.scaled = (data.raw/SENS_4G_LSB_PER_G);
+            break;
+
+            case SENS_8G:
+                data.scaled = (data.raw/SENS_8G_LSB_PER_G);
+            break;
+
+            case SENS_16G:
+                data.scaled = (data.raw/SENS_16G_LSB_PER_G);
+            break;
+        }
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorAxis(SensorAxis axis, AxisData &data, GyroRange range)
+{
+    uint8_t localData[2];
+    int32_t rtnVal;
+
+    switch(axis)
+    {
+        case X_AXIS:
+            rtnVal = readBlock(DATA_8, DATA_9, localData);
+        break;
+
+        case Y_AXIS:
+            rtnVal = readBlock(DATA_10, DATA_11, localData);
+        break;
+
+        case Z_AXIS:
+            rtnVal = readBlock(DATA_12, DATA_13, localData);
+        break;
+
+        default:
+            rtnVal = -1;
+        break;
+    }
+
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        data.raw = ((localData[1] << 8) | localData[0]);
+        switch(range)
+        {
+            case DPS_2000:
+                data.scaled = (data.raw/SENS_2000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_1000:
+                data.scaled = (data.raw/SENS_1000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_500:
+                data.scaled = (data.raw/SENS_500_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_250:
+                data.scaled = (data.raw/SENS_250_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_125:
+                data.scaled = (data.raw/SENS_125_DPS_LSB_PER_DPS);
+            break;
+        }
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorXYZ(SensorData &data, AccRange range)
+{
+    uint8_t localData[6];
+    int32_t rtnVal = readBlock(DATA_14, DATA_19, localData);
+
+	if (m_use_irq == true && bmi160_irq_asserted == false)
+		return -1;
+
+	bmi160_irq_asserted = false;
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        data.xAxis.raw = ((localData[1] << 8) | localData[0]);
+        data.yAxis.raw = ((localData[3] << 8) | localData[2]);
+        data.zAxis.raw = ((localData[5] << 8) | localData[4]);
+
+        switch(range)
+        {
+            case SENS_2G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_2G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_2G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_2G_LSB_PER_G);
+            break;
+
+            case SENS_4G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_4G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_4G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_4G_LSB_PER_G);
+            break;
+
+            case SENS_8G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_8G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_8G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_8G_LSB_PER_G);
+            break;
+
+            case SENS_16G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_16G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_16G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_16G_LSB_PER_G);
+            break;
+        }
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorXYZ(SensorData &data, GyroRange range)
+{
+    uint8_t localData[6];
+    int32_t rtnVal = readBlock(DATA_8, DATA_13, localData);
+
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        data.xAxis.raw = ((localData[1] << 8) | localData[0]);
+        data.yAxis.raw = ((localData[3] << 8) | localData[2]);
+        data.zAxis.raw = ((localData[5] << 8) | localData[4]);
+
+        switch(range)
+        {
+            case DPS_2000:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_1000:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_500:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_250:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_125:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+            break;
+        }
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorXYZandSensorTime(SensorData &data,
+                                          SensorTime &sensorTime,
+                                          AccRange range)
+{
+    uint8_t localData[9];
+    int32_t rtnVal = readBlock(DATA_14, SENSORTIME_2, localData);
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        data.xAxis.raw = ((localData[1] << 8) | localData[0]);
+        data.yAxis.raw = ((localData[3] << 8) | localData[2]);
+        data.zAxis.raw = ((localData[5] << 8) | localData[4]);
+
+        switch(range)
+        {
+            case SENS_2G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_2G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_2G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_2G_LSB_PER_G);
+            break;
+
+            case SENS_4G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_4G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_4G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_4G_LSB_PER_G);
+            break;
+
+            case SENS_8G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_8G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_8G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_8G_LSB_PER_G);
+            break;
+
+            case SENS_16G:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_16G_LSB_PER_G);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_16G_LSB_PER_G);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_16G_LSB_PER_G);
+            break;
+        }
+
+        sensorTime.raw = ((localData[8] << 16) | (localData[7] << 8) |
+                           localData[6]);
+        sensorTime.seconds = (sensorTime.raw * SENSOR_TIME_LSB);
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorXYZandSensorTime(SensorData &data,
+                                          SensorTime &sensorTime,
+                                          GyroRange range)
+{
+    uint8_t localData[16];
+    int32_t rtnVal = readBlock(DATA_8, SENSORTIME_2, localData);
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        data.xAxis.raw = ((localData[1] << 8) | localData[0]);
+        data.yAxis.raw = ((localData[3] << 8) | localData[2]);
+        data.zAxis.raw = ((localData[5] << 8) | localData[4]);
+
+        switch(range)
+        {
+            case DPS_2000:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_1000:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_500:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_250:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_125:
+                data.xAxis.scaled = (data.xAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+                data.yAxis.scaled = (data.yAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+                data.zAxis.scaled = (data.zAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+            break;
+        }
+
+        sensorTime.raw = ((localData[14] << 16) | (localData[13] << 8) |
+                           localData[12]);
+        sensorTime.seconds = (sensorTime.raw * SENSOR_TIME_LSB);
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getGyroAccXYZandSensorTime(SensorData &accData,
+                                           SensorData &gyroData,
+                                           SensorTime &sensorTime,
+                                           AccRange accRange,
+                                           GyroRange gyroRange)
+{
+    uint8_t localData[16];
+    int32_t rtnVal = readBlock(DATA_8, SENSORTIME_2, localData);
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        gyroData.xAxis.raw = ((localData[1] << 8) | localData[0]);
+        gyroData.yAxis.raw = ((localData[3] << 8) | localData[2]);
+        gyroData.zAxis.raw = ((localData[5] << 8) | localData[4]);
+
+        accData.xAxis.raw = ((localData[7] << 8) | localData[6]);
+        accData.yAxis.raw = ((localData[9] << 8) | localData[8]);
+        accData.zAxis.raw = ((localData[11] << 8) | localData[10]);
+
+        switch(gyroRange)
+        {
+            case DPS_2000:
+                gyroData.xAxis.scaled = (gyroData.xAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+                gyroData.yAxis.scaled = (gyroData.yAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+                gyroData.zAxis.scaled = (gyroData.zAxis.raw/SENS_2000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_1000:
+                gyroData.xAxis.scaled = (gyroData.xAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+                gyroData.yAxis.scaled = (gyroData.yAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+                gyroData.zAxis.scaled = (gyroData.zAxis.raw/SENS_1000_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_500:
+                gyroData.xAxis.scaled = (gyroData.xAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+                gyroData.yAxis.scaled = (gyroData.yAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+                gyroData.zAxis.scaled = (gyroData.zAxis.raw/SENS_500_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_250:
+                gyroData.xAxis.scaled = (gyroData.xAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+                gyroData.yAxis.scaled = (gyroData.yAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+                gyroData.zAxis.scaled = (gyroData.zAxis.raw/SENS_250_DPS_LSB_PER_DPS);
+            break;
+
+            case DPS_125:
+                gyroData.xAxis.scaled = (gyroData.xAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+                gyroData.yAxis.scaled = (gyroData.yAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+                gyroData.zAxis.scaled = (gyroData.zAxis.raw/SENS_125_DPS_LSB_PER_DPS);
+            break;
+        }
+
+        switch(accRange)
+        {
+            case SENS_2G:
+                accData.xAxis.scaled = (accData.xAxis.raw/SENS_2G_LSB_PER_G);
+                accData.yAxis.scaled = (accData.yAxis.raw/SENS_2G_LSB_PER_G);
+                accData.zAxis.scaled = (accData.zAxis.raw/SENS_2G_LSB_PER_G);
+            break;
+
+            case SENS_4G:
+                accData.xAxis.scaled = (accData.xAxis.raw/SENS_4G_LSB_PER_G);
+                accData.yAxis.scaled = (accData.yAxis.raw/SENS_4G_LSB_PER_G);
+                accData.zAxis.scaled = (accData.zAxis.raw/SENS_4G_LSB_PER_G);
+            break;
+
+            case SENS_8G:
+                accData.xAxis.scaled = (accData.xAxis.raw/SENS_8G_LSB_PER_G);
+                accData.yAxis.scaled = (accData.yAxis.raw/SENS_8G_LSB_PER_G);
+                accData.zAxis.scaled = (accData.zAxis.raw/SENS_8G_LSB_PER_G);
+            break;
+
+            case SENS_16G:
+                accData.xAxis.scaled = (accData.xAxis.raw/SENS_16G_LSB_PER_G);
+                accData.yAxis.scaled = (accData.yAxis.raw/SENS_16G_LSB_PER_G);
+                accData.zAxis.scaled = (accData.zAxis.raw/SENS_16G_LSB_PER_G);
+            break;
+        }
+
+        sensorTime.raw = ((localData[14] << 16) | (localData[13] << 8) |
+                           localData[12]);
+        sensorTime.seconds = (sensorTime.raw * SENSOR_TIME_LSB);
+    }
+
+    return rtnVal;
+}
+
+int32_t BMI160::setSampleRate(int sample_rate)
+{
+	int sr_reg_val = -1;
+	int i;
+	const uint16_t odr_table[][2] = {
+	    {25, GYRO_ODR_6}, ///<25Hz
+        {50, GYRO_ODR_7}, ///<50Hz
+        {100, GYRO_ODR_8}, ///<100Hz
+        {200, GYRO_ODR_9}, ///<200Hz
+        {400, GYRO_ODR_10}, ///<400Hz
+        {800, GYRO_ODR_11}, ///<800Hz
+        {1600, GYRO_ODR_12}, ///<1600Hz
+        {3200, GYRO_ODR_13}, ///<3200Hz
+	};
+
+	int num_sr = sizeof(odr_table)/sizeof(odr_table[0]);
+	for (i = 0; i < num_sr; i++) {
+		if (sample_rate == odr_table[i][0]) {
+			sr_reg_val = odr_table[i][1];
+			break;
+		}
+	}
+
+	if (sr_reg_val == -1)
+		return -2;
+
+	AccConfig accConfigRead;
+	if (getSensorConfig(accConfigRead) == BMI160::RTN_NO_ERROR) {
+	accConfigRead.odr = (AccOutputDataRate)sr_reg_val;
+		return setSensorConfig(accConfigRead) == BMI160::RTN_NO_ERROR ? 0 : -1;
+	} else
+		return -1;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getSensorTime(SensorTime &sensorTime)
+{
+    uint8_t localData[3];
+    int32_t rtnVal = readBlock(SENSORTIME_0, SENSORTIME_2, localData);
+
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        sensorTime.raw = ((localData[2] << 16) | (localData[1] << 8) |
+                           localData[0]);
+        sensorTime.seconds = (sensorTime.raw * SENSOR_TIME_LSB);
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160::getTemperature(float *temp)
+{
+    uint8_t data[2];
+    uint16_t rawTemp;
+
+    int32_t rtnVal = readBlock(TEMPERATURE_0, TEMPERATURE_1, data);
+    if(rtnVal == RTN_NO_ERROR)
+    {
+        rawTemp = ((data[1] << 8) | data[0]);
+        if(rawTemp & 0x8000)
+        {
+            *temp = (23.0F - ((0x10000 - rawTemp)/512.0F));
+        }
+        else
+        {
+            *temp = ((rawTemp/512.0F) + 23.0F);
+        }
+    }
+
+    return rtnVal;
+}
+
+//***********************************************************************************
+int32_t BMI160::BMI160_DefaultInitalize(){
+
+		//soft reset the accelerometer
+		writeRegister(CMD ,SOFT_RESET);
+		wait(0.1);
+
+	    //Power up sensors in normal mode
+	    if(setSensorPowerMode(BMI160::GYRO, BMI160::SUSPEND) != BMI160::RTN_NO_ERROR){
+	        //printf("Failed to set gyroscope power mode\n");
+	    }
+
+	    wait(0.1);
+
+	    if(setSensorPowerMode(BMI160::ACC, BMI160::NORMAL) != BMI160::RTN_NO_ERROR){
+	        //printf("Failed to set accelerometer power mode\n");
+	    }
+	    wait(0.1);
+
+	    BMI160::AccConfig accConfig;
+	    BMI160::AccConfig accConfigRead;
+	    accConfig.range = BMI160::SENS_2G;
+	    accConfig.us = BMI160::ACC_US_OFF;
+	    accConfig.bwp = BMI160::ACC_BWP_2;
+	    accConfig.odr = BMI160::ACC_ODR_6;
+	    if(setSensorConfig(accConfig) == BMI160::RTN_NO_ERROR)
+	    {
+	        if(getSensorConfig(accConfigRead) == BMI160::RTN_NO_ERROR)
+	        {
+	            if((accConfig.range != accConfigRead.range) ||
+	                    (accConfig.us != accConfigRead.us) ||
+	                    (accConfig.bwp != accConfigRead.bwp) ||
+	                    (accConfig.odr != accConfigRead.odr))
+	            {
+	               /* printf("ACC read data desn't equal set data\n\n");
+	                printf("ACC Set Range = %d\n", accConfig.range);
+	                printf("ACC Set UnderSampling = %d\n", accConfig.us);
+	                printf("ACC Set BandWidthParam = %d\n", accConfig.bwp);
+	                printf("ACC Set OutputDataRate = %d\n\n", accConfig.odr);
+	                printf("ACC Read Range = %d\n", accConfigRead.range);
+	                printf("ACC Read UnderSampling = %d\n", accConfigRead.us);
+	                printf("ACC Read BandWidthParam = %d\n", accConfigRead.bwp);
+	                printf("ACC Read OutputDataRate = %d\n\n", accConfigRead.odr);*/
+	            }
+
+	        }
+	        else
+	        {
+	             //printf("Failed to read back accelerometer configuration\n");
+	        }
+	    }
+	    else
+	    {
+	        //printf("Failed to set accelerometer configuration\n");
+	    }
+	    return 0;
+}
+
+//***********************************************************************************
+int32_t BMI160::enable_data_ready_interrupt() {
+	uint8_t data = 0;
+	uint8_t temp = 0;
+	int32_t result;
+
+	result = readRegister(INT_EN_1, &data);
+	temp = data & ~0x10;
+	data = temp | ((1 << 4) & 0x10);
+	/* Writing data to INT ENABLE 1 Address */
+	result |= writeRegister(INT_EN_1, data);
+
+	// configure in_out ctrl
+	//bmi160_get_regs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev);
+	result |= readRegister(INT_OUT_CTRL, &data);
+	data = 0x09;
+	result |= writeRegister(INT_OUT_CTRL,data);
+
+	//config int latch
+	//bmi160_get_regs(BMI160_INT_LATCH_ADDR, &data, 1, dev);
+	result |= readRegister(INT_LATCH, &data);
+	data = 0x0F;
+	result |= writeRegister(INT_LATCH, data);
+
+	//bmi160_get_regs(BMI160_INT_MAP_1_ADDR, &data, 1, dev);
+	result |= readRegister(INT_MAP_1, &data);
+	data = 0x80;
+	result |= writeRegister(INT_MAP_1, data);
+
+	if(result != 0){
+		//printf("BMI160::%s failed.\r\n", __func__);
+		return -1;
+	}
+
+	m_bmi160_irq->disable_irq();
+	m_bmi160_irq->mode(PullUp);
+	m_bmi160_irq->fall(this, &BMI160::irq_handler);
+	m_bmi160_irq->enable_irq();
+	return 0;
+}
+
+void BMI160::irq_handler() {
+	bmi160_irq_asserted = true;
+}
+
+int32_t BMI160::reset() {
+	if (m_use_irq)
+		m_bmi160_irq->disable_irq();
+	bmi160_irq_asserted = false;
+	writeRegister(CMD, SOFT_RESET);
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/accelerometer/bmi160.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,846 @@
+/**********************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+
+#ifndef BMI160_H
+#define BMI160_H
+
+#include "mbed.h"
+
+/**
+@brief The BMI160 is a small, low power, low noise 16-bit inertial measurement
+unit designed for use in mobile applications like augmented reality or indoor
+navigation which require highly accurate, real-time sensor data.
+
+In full operation mode, with both the accelerometer and gyroscope enabled, the
+current consumption is typically 950 μA, enabling always-on applications in
+battery driven devices. It is available in a compact 14-pin 2.5 x 3.0 x 0.8 mm³
+LGA package."
+
+This class is an abstract base class and can not be instaniated, use BMI160_I2C
+or BMI160_SPI.
+*/
+class BMI160
+{
+public:
+
+    ///Return value on success.
+    static const uint8_t RTN_NO_ERROR = 0;
+
+    ///Sensor types
+    enum Sensors
+    {
+        MAG = 0, ///<Optional external sensor
+        GYRO,    ///<Angular rate sensor
+        ACC      ///<g sensor
+    };
+
+    ///Sensor Axis
+    enum SensorAxis
+    {
+        X_AXIS = 0,
+        Y_AXIS,
+        Z_AXIS
+    };
+
+    ///Structure for axis data
+    struct AxisData
+    {
+        int16_t raw;  ///<Axis raw data
+        float scaled; ///<Axis scaled data
+    };
+
+    ///Structure for sensor time data
+    struct SensorTime
+    {
+        uint32_t raw;  ///<raw SensorTime
+        float seconds; ///<SensorTime as seconds
+    };
+
+    ///Period of internal counter
+    static const float SENSOR_TIME_LSB = 39e-6;
+
+    ///Structure for holding sensor data
+    struct SensorData
+    {
+        AxisData xAxis; ///<Sensor X axis data
+        AxisData yAxis; ///<Sensor Y axis data
+        AxisData zAxis; ///<Sensor Z axis data
+    };
+
+
+    ///BMI160 registers
+    enum Registers
+    {
+        CHIP_ID = 0x00,  ///<Chip Identification.
+        ERR_REG = 0x02,  ///<Reports sensor error flags.  Flags reset when read.
+        PMU_STATUS,      ///<Reports current power mode for sensors.
+        DATA_0,          ///<MAG_X axis bits7:0
+        DATA_1,          ///<MAG_X axis bits15:8
+        DATA_2,          ///<MAG_Y axis bits7:0
+        DATA_3,          ///<MAG_Y axis bits15:8
+        DATA_4,          ///<MAG_Z axis bits7:0
+        DATA_5,          ///<MAG_Z axis bits15:8
+        DATA_6,          ///<RHALL bits7:0
+        DATA_7,          ///<RHALL bits15:8
+        DATA_8,          ///<GYR_X axis bits7:0
+        DATA_9,          ///<GYR_X axis bits15:8
+        DATA_10,         ///<GYR_Y axis bits7:0
+        DATA_11,         ///<GYR_Y axis bits15:8
+        DATA_12,         ///<GYR_Z axis bits7:0
+        DATA_13,         ///<GYR_Z axis bits15:8
+        DATA_14,         ///<ACC_X axis bits7:0
+        DATA_15,         ///<ACC_X axis bits15:8
+        DATA_16,         ///<ACC_Y axis bits7:0
+        DATA_17,         ///<ACC_Y axis bits15:8
+        DATA_18,         ///<ACC_Z axis bits7:0
+        DATA_19,         ///<ACC_Z axis bits15:8
+        SENSORTIME_0,    ///<24bit counter synchronized with data, bits7:0
+        SENSORTIME_1,    ///<24bit counter synchronized with data, bits15:8
+        SENSORTIME_2,    ///<24bit counter synchronized with data, bits23:16
+        STATUS,          ///<Reports sensors status flags
+        INT_STATUS_0,    ///<Contains interrupt status flags
+        INT_STATUS_1,    ///<Contains interrupt status flags
+        INT_STATUS_2,    ///<Contains interrupt status flags
+        INT_STATUS_3,    ///<Contains interrupt status flags
+        TEMPERATURE_0,   ///<Contains temperature of sensor, bits7:0
+        TEMPERATURE_1,   ///<Contains temperature of sensor, bits15:8
+        FIFO_LENGTH_0,   ///<Current fill level of FIFO, bits7:0
+        FIFO_LENGTH_1,   ///<Current fill level of FIFO, bits10:8
+        FIFO_DATA,       ///<FIFO data read out register, burst read
+        ACC_CONF = 0x40, ///<Set ODR, bandwidth, and read mode of accelerometer
+        ACC_RANGE,       ///<Sets accelerometer g-range
+        GYR_CONF,        ///<Set ODR, bandwidth, and read mode of gyroscope
+        GYR_RANGE,       ///<Sets gyroscope angular rate measurement range
+        MAG_CONF,        ///<Sets ODR of magnetometer interface
+        FIFO_DOWNS,      ///<Sets down sampling ratios of accel and gyro data
+                         ///<for FIFO
+        FIFO_CONFIG_0,   ///<Sets FIFO Watermark
+        FIFO_CONFIG_1,   ///<Sets which sensor data is available in FIFO,
+                         ///<Header/Headerless mode, Ext Int tagging, Sensortime
+        MAG_IF_0 = 0x4B, ///<Magnetometer 7-bit I2C address, bits7:1
+        MAG_IF_1,        ///<Magnetometer interface configuration
+        MAG_IF_2,        ///<Magnetometer address to read
+        MAG_IF_3,        ///<Magnetometer address to write
+        MAG_IF_4,        ///<Magnetometer data to write
+        INT_EN_0,        ///<Interrupt enable bits
+        INT_EN_1,        ///<Interrupt enable bits
+        INT_EN_2,        ///<Interrupt enable bits
+        INT_OUT_CTRL,    ///<Contains the behavioral configuration of INT pins
+        INT_LATCH,       ///<Contains the interrupt rest bit and the interrupt
+                         ///<mode selection
+        INT_MAP_0,       ///<Controls which interrupt signals are mapped to the
+                         ///<INT1 and INT2 pins
+        INT_MAP_1,       ///<Controls which interrupt signals are mapped to the
+                         ///<INT1 and INT2 pins
+        INT_MAP_2,       ///<Controls which interrupt signals are mapped to the
+                         ///<INT1 and INT2 pins
+        INT_DATA_0,      ///<Contains the data source definition for the two
+                         ///<interrupt groups
+        INT_DATA_1,      ///<Contains the data source definition for the two
+                         ///<interrupt groups
+        INT_LOWHIGH_0,   ///<Contains the configuration for the low g interrupt
+        INT_LOWHIGH_1,   ///<Contains the configuration for the low g interrupt
+        INT_LOWHIGH_2,   ///<Contains the configuration for the low g interrupt
+        INT_LOWHIGH_3,   ///<Contains the configuration for the low g interrupt
+        INT_LOWHIGH_4,   ///<Contains the configuration for the low g interrupt
+        INT_MOTION_0,    ///<Contains the configuration for the any motion and
+                         ///<no motion interrupts
+        INT_MOTION_1,    ///<Contains the configuration for the any motion and
+                         ///<no motion interrupts
+        INT_MOTION_2,    ///<Contains the configuration for the any motion and
+                         ///<no motion interrupts
+        INT_MOTION_3,    ///<Contains the configuration for the any motion and
+                         ///<no motion interrupts
+        INT_TAP_0,       ///<Contains the configuration for the tap interrupts
+        INT_TAP_1,       ///<Contains the configuration for the tap interrupts
+        INT_ORIENT_0,    ///<Contains the configuration for the oeientation
+                         ///<interrupt
+        INT_ORIENT_1,    ///<Contains the configuration for the oeientation
+                         ///<interrupt
+        INT_FLAT_0,      ///<Contains the configuration for the flat interrupt
+        INT_FLAT_1,      ///<Contains the configuration for the flat interrupt
+        FOC_CONF,        ///<Contains configuration for the fast offset
+                         ///<compensation for the accelerometer and gyroscope
+        CONF,            ///<Configuration of sensor, nvm_prog_en bit
+        IF_CONF,         ///<Contains settings for the digital interface
+        PMU_TRIGGER,     ///<Sets trigger conditions to change gyro power modes
+        SELF_TEST,       ///<Self test configuration
+        NV_CONF = 0x70,  ///<Contains settings for the digital interface
+        OFFSET_0,        ///<Contains offset comp values for acc_off_x7:0
+        OFFSET_1,        ///<Contains offset comp values for acc_off_y7:0
+        OFFSET_2,        ///<Contains offset comp values for acc_off_z7:0
+        OFFSET_3,        ///<Contains offset comp values for gyr_off_x7:0
+        OFFSET_4,        ///<Contains offset comp values for gyr_off_y7:0
+        OFFSET_5,        ///<Contains offset comp values for gyr_off_z7:0
+        OFFSET_6,        ///<gyr/acc offset enable bit and gyr_off_(zyx) bits9:8
+        STEP_CNT_0,      ///<Step counter bits 15:8
+        STEP_CNT_1,      ///<Step counter bits 7:0
+        STEP_CONF_0,     ///<Contains configuration of the step detector
+        STEP_CONF_1,     ///<Contains configuration of the step detector
+        CMD = 0x7E       ///<Command register triggers operations like
+                         ///<softreset, NVM programming, etc.
+    };
+
+
+    ///@name ERR_REG(0x02)
+    ///Error register data
+    ///@{
+
+    static const uint8_t FATAL_ERR_MASK = 0x01;
+    static const uint8_t FATAL_ERR_POS = 0x00;
+    static const uint8_t ERR_CODE_MASK = 0x1E;
+    static const uint8_t ERR_CODE_POS = 0x01;
+    static const uint8_t I2C_FAIL_ERR_MASK = 0x20;
+    static const uint8_t I2C_FAIL_ERR_POS = 0x05;
+    static const uint8_t DROP_CMD_ERR_MASK = 0x40;
+    static const uint8_t DROP_CMD_ERR_POS = 0x06;
+    static const uint8_t MAG_DRDY_ERR_MASK = 0x80;
+    static const uint8_t MAG_DRDY_ERR_POS = 0x08;
+
+    ///Enumerated error codes
+    enum ErrorCodes
+    {
+        NO_ERROR = 0,        ///<No Error
+        ERROR_1,             ///<Listed as error
+        ERROR_2,             ///<Listed as error
+        LPM_INT_PFD,         ///<Low-power mode and interrupt uses pre-filtered
+                             ///<data
+        ODR_MISMATCH = 0x06, ///<ODRs of enabled sensors in headerless mode do
+                             ///<not match
+        PFD_USED_LPM         ///<Pre-filtered data are used in low power mode
+    };
+    ///@}
+
+
+    ///@name ACC_CONF(0x40) and ACC_RANGE(0x41)
+    ///Data for configuring accelerometer
+    ///@{
+
+    static const uint8_t ACC_ODR_MASK = 0x0F;
+    static const uint8_t ACC_ODR_POS = 0x00;
+    static const uint8_t ACC_BWP_MASK = 0x70;
+    static const uint8_t ACC_BWP_POS = 0x04;
+    static const uint8_t ACC_US_MASK = 0x80;
+    static const uint8_t ACC_US_POS = 0x07;
+    static const uint8_t ACC_RANGE_MASK = 0x0F;
+    static const uint8_t ACC_RANGE_POS = 0x00;
+
+    ///Accelerometer output data rates
+    enum AccOutputDataRate
+    {
+        ACC_ODR_1 = 1,  ///< 25/32Hz
+        ACC_ODR_2,      ///< 25/16Hz
+        ACC_ODR_3,      ///< 25/8Hz
+        ACC_ODR_4,      ///< 25/4Hz
+        ACC_ODR_5,      ///< 25/2Hz
+        ACC_ODR_6,      ///< 25Hz
+        ACC_ODR_7,      ///< 50Hz
+        ACC_ODR_8,      ///< 100Hz
+        ACC_ODR_9,      ///< 200Hz
+        ACC_ODR_10,     ///< 400Hz
+        ACC_ODR_11,     ///< 800Hz
+        ACC_ODR_12      ///< 1600Hz
+    };
+
+    ///Accelerometer bandwidth parameters
+    enum AccBandWidthParam
+    {
+        ACC_BWP_0 = 0, ///< Average 1 cycle;  when acc_us = 0 OSR4
+        ACC_BWP_1,     ///< Average 2 cycles; when acc_us = 0 OSR2
+        ACC_BWP_2,     ///< Average 4 cycles; when acc_us = 0 normal mode
+        ACC_BWP_3,     ///< Average 8 cycles
+        ACC_BWP_4,     ///< Average 16 cycles
+        ACC_BWP_5,     ///< Average 32 cycles
+        ACC_BWP_6,     ///< Average 64 cycles
+        ACC_BWP_7      ///< Average 128 cycles
+    };
+
+    ///Accelerometer undersampling
+    enum AccUnderSampling
+    {
+        ACC_US_OFF = 0,
+        ACC_US_ON
+    };
+
+    ///Accelerometer ranges
+    enum AccRange
+    {
+        SENS_2G = 0x03,  ///<Accelerometer range +-2G
+        SENS_4G = 0x05,  ///<Accelerometer range +-4G
+        SENS_8G = 0x08,  ///<Accelerometer range +-8G
+        SENS_16G = 0x0C ///<Accelerometer range +-16G
+    };
+
+    static const float SENS_2G_LSB_PER_G = 16384.0F;
+    static const float SENS_4G_LSB_PER_G = 8192.0F;
+    static const float SENS_8G_LSB_PER_G = 4096.0F;
+    static const float SENS_16G_LSB_PER_G = 2048.0F;
+
+    ///Accelerometer configuration data structure
+    struct AccConfig
+    {
+        AccRange range;        ///<Accelerometer range
+        AccUnderSampling us;   ///<Accelerometr undersampling mode
+        AccBandWidthParam bwp; ///<Accelerometer bandwidth param
+        AccOutputDataRate odr; ///<Accelerometr output data rate
+    };
+
+    ///Accelerometer default configuration
+    static const AccConfig DEFAULT_ACC_CONFIG;
+    ///@}
+
+
+    ///@name GYR_CONF(0x42) and GYR_RANGE(0x43)
+    ///Data for configuring gyroscope
+    ///@{
+
+    static const uint8_t GYRO_ODR_MASK = 0x0F;
+    static const uint8_t GYRO_ODR_POS = 0x00;
+    static const uint8_t GYRO_BWP_MASK = 0x30;
+    static const uint8_t GYRO_BWP_POS = 0x04;
+    static const uint8_t GYRO_RANGE_MASK = 0x07;
+    static const uint8_t GYRO_RANGE_POS = 0x00;
+
+    ///Gyroscope output data rates
+    enum GyroOutputDataRate
+    {
+        GYRO_ODR_6 = 0x06,  ///<25Hz
+        GYRO_ODR_7 = 0x07,  ///<50Hz
+        GYRO_ODR_8 = 0x08,  ///<100Hz
+        GYRO_ODR_9 = 0x09,  ///<200Hz
+        GYRO_ODR_10 = 0x0A, ///<400Hz
+        GYRO_ODR_11 = 0x0B, ///<800Hz
+        GYRO_ODR_12 = 0x0C, ///<1600Hz
+        GYRO_ODR_13 = 0x0D  ///<3200Hz
+    };
+
+    ///Gyroscope bandwidth paramaters
+    enum GyroBandWidthParam
+    {
+        GYRO_BWP_0 = 0, ///<OSR4 Over Sampling Rate of 4
+        GYRO_BWP_1,     ///<OSR2 Over Sampling Rate of 2
+        GYRO_BWP_2      ///<Normal Mode, Equidistant Sampling
+    };
+
+    ///Gyroscope ranges
+    enum GyroRange
+    {
+        DPS_2000 = 0, ///<+-2000dps, 16.4LSB/dps
+        DPS_1000,     ///<+-1000dps, 32.8LSB/dps
+        DPS_500,      ///<+-500dps, 65.6LSB/dps
+        DPS_250,      ///<+-250dps, 131.2LSB/dps
+        DPS_125       ///<+-125dps, 262.4LSB/dps,
+    };
+
+    static const float SENS_2000_DPS_LSB_PER_DPS = 16.4F;
+    static const float SENS_1000_DPS_LSB_PER_DPS = 32.8F;
+    static const float SENS_500_DPS_LSB_PER_DPS = 65.6F;
+    static const float SENS_250_DPS_LSB_PER_DPS = 131.2F;
+    static const float SENS_125_DPS_LSB_PER_DPS = 262.4F;
+
+    ///Gyroscope configuration data structure
+    struct GyroConfig
+    {
+        GyroRange range;        ///<Gyroscope range
+        GyroBandWidthParam bwp; ///<Gyroscope bandwidth param
+        GyroOutputDataRate odr; ///<Gyroscope output data rate
+    };
+
+    ///Gyroscope default configuration
+    static const GyroConfig DEFAULT_GYRO_CONFIG;
+    ///@}
+
+
+    ///Enumerated power modes
+    enum PowerModes
+    {
+        SUSPEND = 0,  ///<Acc and Gyro, No sampling, No FIFO data readout
+        NORMAL,       ///<Acc and Gyro, Full chip operation
+        LOW_POWER,    ///<Acc duty-cycling between suspend and normal
+        FAST_START_UP ///<Gyro start up delay time to normal mode <= 10 ms
+    };
+
+
+    ///Enumerated commands used with CMD register
+    enum Commands
+    {
+        START_FOC = 0x03,        ///<Starts Fast Offset Calibrartion
+        ACC_SET_PMU_MODE = 0x10, ///<Sets acc power mode
+        GYR_SET_PMU_MODE = 0x14, ///<Sets gyro power mode
+        MAG_SET_PMU_MODE = 0x18, ///<Sets mag power mode
+        PROG_NVM = 0xA0,         ///<Writes NVM backed registers into NVM
+        FIFO_FLUSH = 0xB0,       ///<Clears FIFO
+        INT_RESET,               ///<Clears interrupt engine, INT_STATUS, and
+                                 ///<the interrupt pin
+        STEP_CNT_CLR,            ///<Triggers reset of the step counter
+        SOFT_RESET = 0xB6        ///<Triggers a reset including a reboot.
+    };
+
+
+    ///@brief BMI160 Destructor.\n
+    ///
+    ///On Entry:
+    ///@param[in] none
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns none
+    virtual ~BMI160(){ }
+
+
+    ///@brief Reads a single register.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - pointer to memory for storing read data
+    ///
+    ///On Exit:
+    ///@param[out] data - holds contents of read register on success
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t readRegister(Registers reg, uint8_t *data) = 0;
+
+
+    ///@brief Writes a single register.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - data to write to register
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t writeRegister(Registers reg, const uint8_t data) = 0;
+
+
+    ///@brief Reads a block of registers.\n
+    ///@detail User must ensure that all registers between 'startReg' and
+    ///'stopReg' exist and are readable.  Function reads up to, including,
+    ///'stopReg'.\n
+    ///
+    ///On Entry:
+    ///@param[in] startReg - register to start reading from
+    ///@param[in] stopReg - register to stop reading from
+    ///@param[in] data - pointer to memory for storing read data
+    ///
+    ///On Exit:
+    ///@param[out] data - holds contents of read registers on success
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t readBlock(Registers startReg, Registers stopReg,
+    uint8_t *data) = 0;
+
+
+    ///@brief Writes a block of registers.\n
+    ///@detail User must ensure that all registers between 'startReg' and
+    ///'stopReg' exist and are writeable.  Function writes up to, including,
+    ///'stopReg'.\n
+    ///
+    ///On Entry:
+    ///@param[in] startReg - register to start writing at
+    ///@param[in] stopReg - register to stop writing at
+    ///@param[in] data - pointer to data to write to registers
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t writeBlock(Registers startReg, Registers stopReg,
+    const uint8_t *data) = 0;
+
+
+    ///@brief Sets sensors power mode through CMD register.\n
+    ///@details Observe command execution times given in datasheet.\n
+    ///
+    ///On Entry:
+    ///@param[in] sensor - Sensor which power mode we are setting
+    ///@param[in] pwrMode - Desired powermode of the sensor
+    ///
+    ///On Exit:
+    ///@param[out]
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t setSensorPowerMode(Sensors sensor, PowerModes pwrMode);
+
+
+    ///@brief Configure sensor.\n
+    ///
+    ///On Entry:
+    ///@param[in] config - sSensor configuration data structure
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t setSensorConfig(const AccConfig &config);
+    int32_t setSensorConfig(const GyroConfig &config);
+
+
+    ///@brief Get sensor configuration.\n
+    ///
+    ///On Entry:
+    ///@param[in] config - Sensor configuration data structure
+    ///
+    ///On Exit:
+    ///@param[out] config - on success, holds sensor's current
+    ///configuration
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t getSensorConfig(AccConfig &config);
+    int32_t getSensorConfig(GyroConfig &config);
+
+
+    ///@brief Get sensor axis.\n
+    ///
+    ///On Entry:
+    ///@param[in] axis - Sensor axis
+    ///@param[in] data - AxisData structure
+    ///@param[in] range - Sensor range
+    ///
+    ///On Exit:
+    ///@param[out] data - Structure holds raw and scaled axis data
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t getSensorAxis(SensorAxis axis, AxisData &data, AccRange range);
+    int32_t getSensorAxis(SensorAxis axis, AxisData &data, GyroRange range);
+
+
+    ///@brief Get sensor xyz axis.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - SensorData structure
+    ///@param[in] range - Sensor range
+    ///
+    ///On Exit:
+    ///@param[out] data - Structure holds raw and scaled data for all three axis
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t getSensorXYZ(SensorData &data, AccRange range);
+    int32_t getSensorXYZ(SensorData &data, GyroRange range);
+
+
+    ///@brief Get sensor xyz axis and sensor time.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - SensorData structure
+    ///@param[in] sensorTime - SensorTime structure for data
+    ///@param[in] range - Sensor range
+    ///
+    ///On Exit:
+    ///@param[out] data - Structure holds raw and scaled data for all three axis
+    ///@param[out] sensorTime - Holds sensor time on success
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t getSensorXYZandSensorTime(SensorData &data, SensorTime &sensorTime,
+                                      AccRange range);
+    int32_t getSensorXYZandSensorTime(SensorData &data, SensorTime &sensorTime,
+                                      GyroRange range);
+
+
+    ///@brief Get Gyroscope/Accelerometer data and sensor time.\n
+    ///
+    ///On Entry:
+    ///@param[in] accData -  Sensor data structure for accelerometer
+    ///@param[in] gyroData - Sensor data structure for gyroscope
+    ///@param[in] sensorTime - SensorTime data structure
+    ///@param[in] accRange - Accelerometer range
+    ///@param[in] gyroRange - Gyroscope range
+    ///
+    ///On Exit:
+    ///@param[out] accData -  Synchronized accelerometer data
+    ///@param[out] gyroData - Synchronized gyroscope data
+    ///@param[out] sensorTime - Synchronized sensor time
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t getGyroAccXYZandSensorTime(SensorData &accData,
+                                       SensorData &gyroData,
+                                       SensorTime &sensorTime,
+                                       AccRange accRange, GyroRange gyroRange);
+
+
+    ///@brief Get sensor time.\n
+    ///
+    ///On Entry:
+    ///@param[in] sensorTime - SensorTime structure for data
+    ///
+    ///On Exit:
+    ///@param[out] sensorTime - Holds sensor time on success
+    ///
+    ///@returns returns 0 on success, non 0 on failure
+    int32_t getSensorTime(SensorTime &sensorTime);
+
+
+    ///@brief Get die temperature.\n
+    ///
+    ///On Entry:
+    ///@param[in] temp - pointer to float for temperature
+    ///
+    ///On Exit:
+    ///@param[out] temp - on success, holds the die temperature
+    ///
+    ///@returns 0 on success, non 0 on failure
+    int32_t getTemperature(float *temp);
+
+    // Initialize BMI160 with default parameters:
+    // set GYRO: Suspended, Acc Normal Mode, ODR:25 Hz
+    int32_t BMI160_DefaultInitalize();
+
+    //
+    //
+    int32_t enable_data_ready_interrupt();
+
+	//
+	// Set sample rate
+	// This function can be alled after BMI160_DefaultInitalize
+	int32_t setSampleRate(int sample_rate);
+
+	/// @brief Soft reset
+	///
+	int32_t reset();
+
+private:
+	bool m_use_irq;
+	bool bmi160_irq_asserted;
+	InterruptIn *m_bmi160_irq;
+	void irq_handler();
+
+protected:
+	BMI160(InterruptIn *int_pin): m_bmi160_irq(int_pin), m_use_irq(true) {
+		bmi160_irq_asserted = false;
+	}
+
+	BMI160(): m_use_irq(false) { }
+};
+
+
+/**
+@brief BMI160_I2C - supports BMI160 object with I2C interface
+*/
+class BMI160_I2C: public BMI160
+{
+public:
+
+    ///BMI160 default I2C address.
+    static const uint8_t I2C_ADRS_SDO_LO = 0x68;
+    ///BMI160 optional I2C address.
+    static const uint8_t I2C_ADRS_SDO_HI = 0x69;
+
+
+    ///@brief BMI160_I2C Constructor.\n
+    ///
+    ///On Entry:
+    ///@param[in] i2cBus - reference to I2C bus for this device
+    ///@param[in] i2cAdrs - 7-bit I2C address
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns none
+    BMI160_I2C(I2C *i2cBus, uint8_t i2cAdrs);
+
+    ///@brief BMI160_I2C Constructor.\n
+    ///
+    ///On Entry:
+    ///@param[in] i2cBus - reference to I2C bus for this device
+    ///@param[in] i2cAdrs - 7-bit I2C address
+    ///@param[in] int_pin - Interrupt pin
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns none
+	BMI160_I2C(I2C *i2cBus, uint8_t i2cAdrs, InterruptIn *int_pin);
+
+    ///@brief Reads a single register.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - pointer to memory for storing read data
+    ///
+    ///On Exit:
+    ///@param[out] data - holds contents of read register on success
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t readRegister(Registers reg, uint8_t *data);
+
+
+    ///@brief Writes a single register.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - data to write to register
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t writeRegister(Registers reg, const uint8_t data);
+
+
+    ///@brief Reads a block of registers.\n
+    ///@detail User must ensure that all registers between 'startReg' and
+    ///'stopReg' exist and are readable.  Function reads up to, including,
+    ///'stopReg'.\n
+    ///
+    ///On Entry:
+    ///@param[in] startReg - register to start reading from
+    ///@param[in] stopReg - register to stop reading from
+    ///@param[in] data - pointer to memory for storing read data
+    ///
+    ///On Exit:
+    ///@param[out] data - holds contents of read registers on success
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t readBlock(Registers startReg, Registers stopReg,
+    uint8_t *data);
+
+
+    ///@brief Writes a block of registers.\n
+    ///@detail User must ensure that all registers between 'startReg' and
+    ///'stopReg' exist and are writeable.  Function writes up to, including,
+    ///'stopReg'.\n
+    ///
+    ///On Entry:
+    ///@param[in] startReg - register to start writing at
+    ///@param[in] stopReg - register to stop writing at
+    ///@param[in] data - pointer to data to write to registers
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t writeBlock(Registers startReg, Registers stopReg,
+    const uint8_t *data);
+
+private:
+    I2C *m_i2cBus;
+    uint8_t m_Wadrs, m_Radrs;
+};
+
+
+/**
+@brief BMI160_SPI - supports BMI160 object with SPI interface
+*/
+class BMI160_SPI: public BMI160
+{
+public:
+
+    ///@brief BMI160_SPI Constructor.\n
+    ///
+    ///On Entry:
+    ///@param[in] spiBus - reference to SPI bus for this device
+    ///@param[in] cs - reference to DigitalOut used for chip select
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns none
+    BMI160_SPI(SPI *spiBus, DigitalOut &cs);
+
+
+    ///@brief Reads a single register.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - pointer to memory for storing read data
+    ///
+    ///On Exit:
+    ///@param[out] data - holds contents of read register on success
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t readRegister(Registers reg, uint8_t *data);
+
+
+    ///@brief Writes a single register.\n
+    ///
+    ///On Entry:
+    ///@param[in] data - data to write to register
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t writeRegister(Registers reg, const uint8_t data);
+
+
+    ///@brief Reads a block of registers.\n
+    ///@detail User must ensure that all registers between 'startReg' and
+    ///'stopReg' exist and are readable.  Function reads up to, including,
+    ///'stopReg'.\n
+    ///
+    ///On Entry:
+    ///@param[in] startReg - register to start reading from
+    ///@param[in] stopReg - register to stop reading from
+    ///@param[in] data - pointer to memory for storing read data
+    ///
+    ///On Exit:
+    ///@param[out] data - holds contents of read registers on success
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t readBlock(Registers startReg, Registers stopReg,
+    uint8_t *data);
+
+
+    ///@brief Writes a block of registers.\n
+    ///@detail User must ensure that all registers between 'startReg' and
+    ///'stopReg' exist and are writeable.  Function writes up to, including,
+    ///'stopReg'.\n
+    ///
+    ///On Entry:
+    ///@param[in] startReg - register to start writing at
+    ///@param[in] stopReg - register to stop writing at
+    ///@param[in] data - pointer to data to write to registers
+    ///
+    ///On Exit:
+    ///@param[out] none
+    ///
+    ///@returns 0 on success, non 0 on failure
+    virtual int32_t writeBlock(Registers startReg, Registers stopReg,
+    const uint8_t *data);
+
+private:
+
+    SPI *m_spiBus;
+    DigitalOut m_cs;
+};
+
+#endif /* BMI160_H */
+
+
+///@brief fx documentation template.\n
+///
+///On Entry:
+///@param[in] none
+///
+///On Exit:
+///@param[out] none
+///
+///@returns none
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/accelerometer/bmi160_i2c.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,104 @@
+/**********************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+
+#include "bmi160.h"
+
+
+//*****************************************************************************
+BMI160_I2C::BMI160_I2C(I2C *i2cBus, uint8_t i2cAdrs)
+:m_i2cBus(i2cBus), m_Wadrs(i2cAdrs << 1), m_Radrs((i2cAdrs << 1) | 1)
+{
+
+}
+
+BMI160_I2C::BMI160_I2C(I2C *i2cBus, uint8_t i2cAdrs, InterruptIn *int_pin)
+:m_i2cBus(i2cBus), m_Wadrs(i2cAdrs << 1), m_Radrs((i2cAdrs << 1) | 1), BMI160(int_pin)
+{
+
+}
+
+//*****************************************************************************
+int32_t BMI160_I2C::readRegister(Registers reg, uint8_t *data)
+{
+    int32_t rtnVal = -1;
+    char packet[] = {static_cast<char>(reg)};
+
+    if(m_i2cBus->write(m_Wadrs, packet, 1) == 0)
+    {
+        rtnVal = m_i2cBus->read(m_Radrs, reinterpret_cast<char *>(data), 1);
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160_I2C::writeRegister(Registers reg, const uint8_t data)
+{
+    char packet[] = {static_cast<char>(reg), static_cast<char>(data)};
+
+    return m_i2cBus->write(m_Wadrs, packet, sizeof(packet));
+}
+
+
+//*****************************************************************************
+int32_t BMI160_I2C::readBlock(Registers startReg, Registers stopReg,
+uint8_t *data)
+{
+    int32_t rtnVal = -1;
+    int32_t numBytes = ((stopReg - startReg) + 1);
+    char packet[] = {static_cast<char>(startReg)};
+
+    if(m_i2cBus->write(m_Wadrs, packet, 1) == 0)
+    {
+        rtnVal = m_i2cBus->read(m_Radrs, reinterpret_cast<char *>(data), numBytes);
+    }
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160_I2C::writeBlock(Registers startReg, Registers stopReg,
+const uint8_t *data)
+{
+    int32_t numBytes = ((stopReg - startReg) + 1);
+    char packet[numBytes + 1];
+
+    packet[0] = static_cast<char>(startReg);
+
+    memcpy(packet + 1, data, numBytes);
+
+    return m_i2cBus->write(m_Wadrs, packet, sizeof(packet));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/accelerometer/bmi160_spi.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,81 @@
+/**********************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+
+#include "bmi160.h"
+
+
+//*****************************************************************************
+BMI160_SPI::BMI160_SPI(SPI *spiBus, DigitalOut &cs)
+:m_spiBus(spiBus), m_cs(cs)
+{
+
+}
+
+
+//*****************************************************************************
+int32_t BMI160_SPI::readRegister(Registers reg, uint8_t *data)
+{
+    int32_t rtnVal = -1;
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160_SPI::writeRegister(Registers reg, const uint8_t data)
+{
+    int32_t rtnVal = -1;
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160_SPI::readBlock(Registers startReg, Registers stopReg,
+uint8_t *data)
+{
+    int32_t rtnVal = -1;
+
+    return rtnVal;
+}
+
+
+//*****************************************************************************
+int32_t BMI160_SPI::writeBlock(Registers startReg, Registers stopReg,
+const uint8_t *data)
+{
+    int32_t rtnVal = -1;
+
+    return rtnVal;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootloader/bootldrAPI.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,651 @@
+/*
+ * bootldrInterface.cpp
+ *
+ *  Created on: Feb 7, 2019
+ *      Author: Yagmur.Gok
+ */
+
+#include <mbed.h>  /*for type definitions*/
+#include "bootldrAPI.h"
+#include "SHComm.h"
+#include "demoDefinitions.h"
+
+//extern Serial daplink;
+
+//#define SERIALOUT printf
+//#define SERIALIN  printf
+
+#define COMM_SUCCESS        0
+#define COMM_GENERAL_ERROR  -1
+#define COMM_INVALID_PARAM  -254
+#define COMM_NOT_RECOGNIZED -255
+
+#define BL_FLASH_ERR_GENERAL  	-1
+#define BL_FLASH_ERR_CHECKSUM 	-2
+#define BL_FLASH_ERR_AUTH      	-3
+#define BL_SET_NUM_PAGES_FAIL	-4
+#define BL_FLASS_ERASE_FAIL		-5
+#define BL_SET_IV_FAIL			-6
+#define BL_FLASHING_FAIL		-7
+#define BL_RAM_ALLOC_FAIL		-8
+
+#define AES_NONCE_SIZE 11
+#define AES_AUTH_SIZE  16
+#define BOOTLOADER_MAX_PAGE_SIZE (8192)
+#define CHECKBYTES_SIZE (16)
+#define FLASHCMDBYTES (2)
+
+#define SS_BOOTLOADER_ERASE_DELAY	700
+#define AES_NONCE_SIZE				11
+#define AES_AUTH_SIZE				16
+#define MAX_PAGE_SIZE				8192
+#define CHECKBYTES_SIZE				16
+
+#define PAGE_WRITE_DELAY_MS			170
+#define MAX_PAGE_NUMBER				31
+#define PAGE_ERASE_CMD_SLEEP_MS		50
+#define BL_CFG_SAVE_CMD_SLEEP_MS	50
+
+static int parse_iv(const char* cmd, uint8_t* iv_bytes);
+static int parse_auth(const char* cmd, uint8_t *auth_bytes);
+static int is_hub_ready_for_flash(void);
+static void clear_state_info(void);
+
+
+typedef struct {
+	int num_allocated_pages; /* Allocated page size */
+	int num_pages;
+	int num_received_pages;
+	int page_size;
+	uint8_t auth[AES_AUTH_SIZE];
+	uint8_t nonce[AES_NONCE_SIZE];
+	uint8_t pages[MAX_PAGE_NUMBER * (MAX_PAGE_SIZE + CHECKBYTES_SIZE)]; //TODO: Use dynamic allocation
+} app_image_t;
+
+
+static app_image_t *app_image = NULL;
+
+static struct {
+
+	uint32_t num_pages;
+	uint32_t page_size;
+	uint32_t hub_mode_bootloader;
+	uint32_t is_iv_set;
+	uint32_t is_auth_done;
+	uint32_t is_flash_erased;
+	uint32_t flag_image_on_ram;
+	uint32_t bootcmds_delay_factor;
+	uint32_t ebl_mode;
+
+}bootldrState = { 0 , 0 , 0 ,0 , 0 , 0 , 0 , 1 ,1};
+
+
+
+int BOOTLDR_get_host_bootloader_state(const char *null_arg){
+
+	SERIALOUT(" \r\n BOOT STATE INFO: \r\n num_pages= %d \r\n page_size= %d \r\n is_iv_set= %d \r\n is_auth_done= %d \r\n is_flash_erased= %d \r\n flag_image_on_ram= %d \r\n bootcmds_delay_factor= %d \r\n ebl_mode= %d \r\n",
+			                             bootldrState.num_pages,
+										 bootldrState.page_size,
+										 bootldrState.is_iv_set,
+										 bootldrState.is_auth_done,
+										 bootldrState.is_flash_erased,
+										 bootldrState.flag_image_on_ram,
+										 bootldrState.bootcmds_delay_factor,
+										 bootldrState.ebl_mode );
+
+
+}
+
+int SH_BOOTLDR_enter_blmode(const char *null_arg){
+
+	int status = 0x00;
+
+	//status = sh_put_in_bootloader();
+	//status = sh_set_ebl_mode((uint8_t)1); /* 1: GPIO rest 0: CMD reset*/
+
+    if( status == 0x00) {
+
+	    //////////status = sh_reset_to_bootloader(); - CHECKIF PROBLEM STILL PRESENT!!
+    	status = sh_debug_reset_to_bootloader();
+	    //status = sh_set_sensorhub_operating_mode((uint8_t)0x08);
+		if (status == 0x00) {
+		   SERIALOUT("\r\n%s err=%d\r\n", "bootldr", COMM_SUCCESS);
+		   bootldrState.hub_mode_bootloader  = 1;
+		}
+		else
+		   SERIALOUT("\r\n%s err=%d\r\n", "bootldr", COMM_GENERAL_ERROR);
+    }
+
+	return status;
+
+}
+
+
+int SH_BOOTLDR_exit_blmode(const char *null_arg){
+
+	int status;
+	status = sh_reset_to_main_app() ; //sh_exit_from_bootloader();
+	if (status == 0x00)
+		printf("\r\n exited from bootloader mode \r\n");
+
+	if (status == 0x00) {
+	   SERIALOUT("\r\n%s err=%d\r\n", "exit", COMM_SUCCESS);
+       bootldrState.hub_mode_bootloader  = 0;
+	}
+    else
+       SERIALOUT("\r\n%s err=%d\r\n", "exit", COMM_GENERAL_ERROR);
+
+	return status;
+
+}
+
+int SH_BOOTLOADER_image_on_ram( const char *arg ){
+
+      int status = COMM_SUCCESS;
+	  int tmp;
+      sscanf(arg, "%*s %d", &tmp );
+      bootldrState.flag_image_on_ram = (tmp > 0)? 1:0 ;
+
+      if(tmp == 1){
+
+    	  app_image = (app_image_t*) malloc(sizeof(*app_image));
+    	  if(app_image != NULL){
+
+    		  app_image->num_allocated_pages = MAX_PAGE_NUMBER;
+    		  app_image->num_pages = 0;
+    		  app_image->num_received_pages = 0;
+    		  app_image->page_size = MAX_PAGE_SIZE;
+    		  //app_image->nonce = {0};
+    		  //app_image->auth  = {0};
+    		  //app_image->pages = {0};
+
+     	  }else {
+    		  SERIALOUT("Memory allocation fail for ram image \r\n");
+    		  status = BL_RAM_ALLOC_FAIL;
+    	  }
+
+      }
+
+      SERIALOUT("\r\n%s err=%d\r\n", "image_on_ram", COMM_SUCCESS);
+
+}
+
+int SH_BOOTLDR_get_pagesz(const char *null_arg){
+
+	int status;
+	int pageSize;
+
+	if (bootldrState.flag_image_on_ram) {
+		SERIALOUT("\r\n%s value=%d err=%d\r\n", "page_size", MAX_PAGE_SIZE, COMM_SUCCESS);
+		app_image->page_size   = MAX_PAGE_SIZE;
+		bootldrState.page_size = MAX_PAGE_SIZE;
+		SERIALOUT("\r\n%s err=%d\r\n", "image_on_ram", 1);
+
+	}else {
+
+		status = sh_get_bootloader_pagesz(&pageSize);
+		if (status == 0x00 ){
+			  if( pageSize == -2){
+				  SERIALOUT("\r\n Page size over maximum allowable \r\n");
+				  status = -1;
+			  }else {
+				  SERIALOUT("\r\n%s value=%d err=%d\r\n", "page_size", pageSize, status);
+				  bootldrState.page_size = pageSize;
+			  }
+		}else
+			SERIALOUT("\r\n%s err=%d\r\n", "page_size", status);
+
+	}
+    return status;
+
+}
+
+int SH_BOOTLDR_set_pagecount(const char *arg){
+
+	int status = -1;
+	int pageCount;
+
+    if(sscanf(arg, "%*s %d", &pageCount)){
+
+        if(bootldrState.flag_image_on_ram){
+        	app_image->num_pages =  (pageCount <= MAX_PAGE_NUMBER)?  pageCount:0;
+        	app_image->num_allocated_pages = MAX_PAGE_NUMBER;
+        	bootldrState.num_pages = app_image->num_pages;
+
+        }else {
+
+			status = sh_set_bootloader_numberofpages(pageCount);
+			if (status == 0x00){
+				bootldrState.num_pages = pageCount;
+			}else
+				bootldrState.num_pages = 0;
+        }
+    }
+    SERIALOUT("\r\n%s err=%d\r\n", "num_pages", status);
+	return status;
+
+}
+
+int SH_BOOTLDR_set_iv(const char *arg) {
+
+    uint8_t iv_bytes[AES_NONCE_SIZE];
+    int status =  parse_iv(arg, &iv_bytes[0]);
+    if( status == 0x00){
+
+     	if(bootldrState.flag_image_on_ram){
+    		int i=0;
+    		for(i = 0 ; i != AES_NONCE_SIZE ; i++)
+    			app_image->nonce[i] = iv_bytes[i];
+    		bootldrState.is_iv_set = 1;
+
+    	}else {
+
+			status = sh_set_bootloader_iv(iv_bytes);
+			if( status == 0x00 ) {
+				bootldrState.is_iv_set = 1;
+			}
+			else {
+				bootldrState.is_iv_set = 0;
+				status = COMM_GENERAL_ERROR;
+			}
+		}
+	}
+    SERIALOUT("\r\n%s err=%d\r\n", "set_iv", status);
+
+    return status;
+
+}
+
+
+int SH_BOOTLDR_set_authentication(const char *arg){
+
+	uint8_t auth_bytes[AES_AUTH_SIZE];
+	int status = parse_auth(arg, &auth_bytes[0]);
+    if( status == 0x00){
+
+    	if(bootldrState.flag_image_on_ram){
+    		int i=0;
+    		for(i = 0 ; i != AES_AUTH_SIZE ; i++)
+    			app_image->auth[i] = auth_bytes[i];
+    		bootldrState.is_auth_done = 1;
+
+    	}else {
+
+			status = sh_set_bootloader_auth(auth_bytes);
+			if( status == 0x00 ){
+				bootldrState.is_auth_done = 1;
+			}
+			else
+				status = COMM_GENERAL_ERROR;
+    	}
+
+    }
+    SERIALOUT("\r\n%s err=%d\r\n", "set_auth", status);
+
+    return status;
+
+}
+
+int SH_BOOTLDR_eraseflash(const char *null_arg){
+
+	int status;
+	if(bootldrState.flag_image_on_ram){
+		SERIALOUT("\r\n%s err=%d\r\n", "erase", COMM_SUCCESS);
+		status == 0x00 /*SS_SUCCESS*/;
+
+	}else {
+
+		status = sh_set_bootloader_erase();
+		if(status == 0x00 /*SS_SUCCESS*/) {
+			bootldrState.is_flash_erased = 1;
+		}else{
+			status = COMM_GENERAL_ERROR;
+		}
+		SERIALOUT("\r\n%s err=%d\r\n", "erase", status);
+
+	}
+    return status;
+
+}
+
+
+int SH_BOOTLDR_receive_image_to_ram(void){
+
+
+	int status;
+	int totalBytes = 0;
+	int currentPage = 1;
+
+	if( app_image != NULL && app_image->num_allocated_pages > 0) {
+
+		uint8_t *page = &app_image->pages[0];
+		uint32_t offset = 0;
+		while (currentPage <= app_image->num_pages) {
+
+			while (totalBytes < (MAX_PAGE_SIZE + CHECKBYTES_SIZE)) {
+				page[totalBytes++] = SERIALIN(); // daplink.getc();  ; /////////////////////////////////////////////////////m_USB->_getc();
+			}
+
+			currentPage++;
+			SERIALOUT("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS);
+
+			offset += MAX_PAGE_SIZE + CHECKBYTES_SIZE;
+			page = &app_image->pages[offset];
+			totalBytes = 0;
+		}
+
+		app_image->num_received_pages = currentPage;
+
+		status =  COMM_SUCCESS;
+
+	}else
+	    status =  COMM_GENERAL_ERROR;
+
+	return status;
+
+}
+
+int SH_BOOTLDR_flash_pages(void){
+
+
+    int totalBytes = 0;
+    int currentPage = 1;
+	char charbuf_flash[256];
+	int data_len_flash = 0;
+	int status;
+
+    static uint8_t tx_buf[ BOOTLOADER_MAX_PAGE_SIZE + CHECKBYTES_SIZE + FLASHCMDBYTES] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SENDPAGE };
+    uint8_t *data_buffer = &tx_buf[2];
+
+    if(!is_hub_ready_for_flash()){
+    	printf("missing condition for flashing:  no page size , no page number, iv notset , no outhentication , flash noterased or mode is not bootloader!\r\n");
+    	clear_state_info();
+    	return -1;
+    }
+    printf(" \r\n NOW WE ARE FLASHING THE PAGES..........\r\n");
+    printf(" \r\n page_size:  %d \r\n", bootldrState.page_size);
+    printf(" \r\n num_pages:  %d \r\n", bootldrState.num_pages);
+
+    while (currentPage <= bootldrState.num_pages) {
+
+        while (totalBytes < (bootldrState.page_size + CHECKBYTES_SIZE)) {
+            data_buffer[totalBytes++] = SERIALIN(); //daplink.getc(); //m_USB->_getc();  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MYG
+            //Here we should be able to take the data over BLE
+        }
+        printf(" \r\n NOW WE GOT A  PAGE..........\r\n");
+        //status = sh_bootloader_flashpage(&tx_buf[0] , bootldrState.page_size);
+
+        status = sh_write_cmd(tx_buf, bootldrState.page_size + CHECKBYTES_SIZE + 2, 2000);
+
+        if (status == 0x00)
+        		printf(" \r\n NOW WE PUSHED A  PAGE..........\r\n");
+/*
+        if (status == 0x00){
+        	currentPage++;
+        	SERIALOUT("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS);
+        }else{
+
+        	if (status == SS_ERR_BTLDR_CHECKSUM)
+        		SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_CHECKSUM);
+        	else
+        		SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_GENERAL);
+
+        }
+ */
+
+        if (status == SS_ERR_BTLDR_CHECKSUM) {
+
+            data_len_flash = snprintf(charbuf_flash, sizeof(charbuf_flash), "\r\npageFlashDone err=%d\r\n", FLASH_ERR_CHECKSUM);
+            SERIALOUT(charbuf_flash);
+        } else if (status != SS_SUCCESS) {
+
+            data_len_flash = snprintf(charbuf_flash, sizeof(charbuf_flash), "\r\npageFlashDone err=%d\r\n", FLASH_ERR_GENERAL);
+            SERIALOUT(charbuf_flash);
+        } else {
+            currentPage++;
+
+            data_len_flash = snprintf(charbuf_flash, sizeof(charbuf_flash), "\r\npageFlashDone err=%d\r\n", COMM_SUCCESS);
+            SERIALOUT(charbuf_flash);
+        }
+        totalBytes = 0;
+
+    }
+    //SERIALOUT(" all pages are flashed \r\n");
+    clear_state_info();
+
+    return status;
+
+}
+
+
+int SH_BOOTLDR_flash(const char *null_arg){
+
+	int status;
+	if(bootldrState.flag_image_on_ram)
+		status = SH_BOOTLDR_receive_image_to_ram();
+	else
+		status = SH_BOOTLDR_flash_pages();
+
+	SERIALOUT("\r\n%s err=%d\r\n", "flash", status);
+
+	return status;
+}
+
+
+int SH_BOOTLDR_flash_appimage_from_ram(const char *null_arg){
+
+
+	int currentPage = 1;
+	uint32_t offset = 0;
+	int ret;
+
+	if(app_image == NULL)
+	    return -1;
+
+	/* Put device to bootloader mode */
+	int status = SH_BOOTLDR_enter_blmode(NULL);
+	if( status != 0x00)
+         return -1;
+
+	wait_ms(10);
+
+	status = sh_set_bootloader_numberofpages(app_image->num_pages);
+	SERIALOUT("*** set_num_page... ret: %d\n", ret);
+	if (status != 0x00) {
+		return BL_SET_NUM_PAGES_FAIL;
+	}
+
+	status = sh_set_bootloader_iv(app_image->nonce);
+	SERIALOUT("*** set_iv... ret: %d\n", ret);
+	if (status != 0) {
+		return BL_SET_IV_FAIL;
+	}
+
+	status = sh_set_bootloader_auth(app_image->auth);
+	SERIALOUT("*** set_auth... ret: %d\n", ret);
+	if (status != 0) {
+		return BL_FLASH_ERR_AUTH;
+	}
+
+	status = sh_set_bootloader_erase() ;
+	SERIALOUT("*** erase app memory... ret: %d\n", ret);
+	if (status != 0) {
+		return BL_FLASS_ERASE_FAIL;
+	}
+
+	static uint8_t tx_buf[MAX_PAGE_SIZE + CHECKBYTES_SIZE + 2];
+
+	tx_buf[0] = SS_FAM_W_BOOTLOADER;
+	tx_buf[1] = SS_CMDIDX_SENDPAGE;
+
+	while (currentPage <= app_image->num_pages) {
+
+		memcpy(&tx_buf[2], &app_image->pages[offset], MAX_PAGE_SIZE + CHECKBYTES_SIZE);
+
+		status = sh_write_cmd(tx_buf, MAX_PAGE_SIZE + CHECKBYTES_SIZE + 2, bootldrState.bootcmds_delay_factor * PAGE_WRITE_DELAY_MS);
+
+		if (status == SS_ERR_BTLDR_CHECKSUM) {
+
+			SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_CHECKSUM);
+			break;
+		} else if (status != SS_SUCCESS) {
+
+			SERIALOUT("\r\npageFlashDone err=%d\r\n", BL_FLASH_ERR_GENERAL);
+			break;
+		} else {
+
+			SERIALOUT("\r\npageFlashDone err=%d\r\n", COMM_SUCCESS);
+		}
+
+		offset += MAX_PAGE_SIZE + CHECKBYTES_SIZE;
+		currentPage++;
+	}
+
+	return COMM_SUCCESS;
+
+}
+
+int SH_BOOTLDR_set_host_ebl_mode(const char *arg) {
+
+    int status;
+    int tmp;
+    sscanf(arg, "%*s %*s %*s %d", &tmp);
+    status = sh_set_ebl_mode(tmp);
+    if( status == 0x00) {
+    	bootldrState.ebl_mode = tmp;
+    }else
+    	status = COMM_INVALID_PARAM;
+
+    SERIALOUT("\r\n%s err=%d\r\n", "set_cfg host ebl",status);
+
+    return status;
+
+}
+
+int SH_BOOTLDR_get_host_ebl_mode(const char *null_arg){
+
+      int value;
+      value = sh_get_ebl_mode();
+      SERIALOUT("\r\n%s value=%s\r\n", "get_cfg host ebl", (value==1)? "GPIO_RST_MODE":"CMD_RST_MODE");
+      return 0x00;
+}
+
+int SH_BOOTLDR_set_host_bootcmds_delay_factor( const char *arg) {
+
+     int status;
+	 int tmp;
+     sscanf(arg, "%*s %*s %*s %d", &tmp);
+     status =  sh_set_bootloader_delayfactor( tmp);
+     if( status == 0x00) {
+    	 bootldrState.bootcmds_delay_factor = tmp;
+     }else
+    	 status = COMM_INVALID_PARAM;
+
+     SERIALOUT("\r\n%s err=%d\r\n", "set_cfg host cdf",status);
+
+     return status;
+
+}
+
+int SH_BOOTLDR_get_host_bootcmds_delay_factor( const char *null_arg){
+
+	int value;
+	value =  sh_get_bootloader_delayfactor();
+	SERIALOUT("\r\n%s value=%d \r\n", "get_cfg host cdf", value);
+	return 0x00;
+
+}
+
+static int is_hub_ready_for_flash(void){
+
+	int status = 0;
+	if( bootldrState.hub_mode_bootloader == 1 &&
+		 bootldrState.is_auth_done == 1	&&
+		  bootldrState.is_iv_set == 1 &&
+		   bootldrState.is_flash_erased == 1 &&
+		    bootldrState.num_pages > 0 &&
+			 bootldrState.page_size > 0 )
+		    	status =  1;
+
+    return status;
+}
+
+static void clear_state_info(void) {
+
+	bootldrState.is_auth_done    = 0;
+	bootldrState.is_iv_set       = 0;
+	bootldrState.is_flash_erased = 0;
+	bootldrState.num_pages       = 0;
+	bootldrState.page_size       = 0;
+	bootldrState.hub_mode_bootloader;
+
+	return;
+}
+
+static int parse_iv(const char* cmd, uint8_t* iv_bytes) {
+
+	int status = 0x00;
+	char cmdStr[] = "set_iv ";
+	int length = strlen(cmd);
+	int expected_length = strlen(cmdStr) + 2*AES_NONCE_SIZE;
+
+	if (length != expected_length) {
+		SERIALOUT("Couldn't parse IV, incorrect number of characters (len:%d, expected:%d)\n",
+               length, expected_length);
+		status = COMM_INVALID_PARAM;
+	}else{
+
+		const char* ivPtr = cmd + strlen(cmdStr);
+		int num_found;
+		int byteVal;
+		for (int ividx = 0; ividx < AES_NONCE_SIZE; ividx++) {
+			num_found = sscanf(ivPtr, "%2X", &byteVal);
+
+			if (num_found != 1 || byteVal > 0xFF) {
+				status = COMM_INVALID_PARAM;
+				//break; //
+				return status;
+			}
+			iv_bytes[ividx] = (uint8_t)byteVal;
+		   ivPtr += 2;
+		}
+	}
+    return status;
+
+}
+
+
+static int parse_auth(const char* cmd, uint8_t *auth_bytes){
+
+	int status = 0x00;
+	char cmdStr[] = "set_auth ";
+    int length = strlen(cmd);
+    int expected_length = strlen(cmdStr) + 2*AES_AUTH_SIZE;
+
+    if (length != expected_length) {
+    	status = -1;
+    }else{
+
+		const char* macPtr = cmd + strlen(cmdStr);
+
+		int num_found;
+		int byteVal;
+		for (int aidx = 0; aidx < AES_AUTH_SIZE; aidx++) {
+			num_found = sscanf(macPtr, "%2X", &byteVal);
+
+			if (num_found != 1 || byteVal > 0xFF) {
+				status = COMM_INVALID_PARAM;;
+				//break; //
+				return status;
+			}
+
+			auth_bytes[aidx] = (uint8_t)byteVal;
+			macPtr += 2;
+		}
+
+    }
+    return status;
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootloader/bootldrAPI.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,200 @@
+/*
+ * bootldrInterface.h
+ *
+ *  Created on: Feb 7, 2019
+ *      Author: Yagmur.Gok
+ */
+
+#ifndef SOURCE_CMDUI_BOOTLDRINTERFACE_H_
+#define SOURCE_CMDUI_BOOTLDRINTERFACE_H_
+
+typedef int (*cmdExecFunc)( const char*); // typedef void (*cmdExecFunc)( const void*);
+
+typedef struct {
+	char const* cmdStr;
+	cmdExecFunc execute;
+	char const *help;
+}cmd_interface_tb;
+
+#define FLASH_ERR_GENERAL   -1
+#define FLASH_ERR_CHECKSUM  -2
+#define FLASH_ERR_AUTH      -3
+
+/**
+* @brief	  sets the SENSOR HUB to Bootloader Mode for Firmware update. Prints status info on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_enter_blmode(const char *null_arg);
+
+/**
+* @brief	  exits the SENSOR HUB from Bootloader Mode to Application Mode. Prints status info on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_exit_blmode(const char *null_arg);
+
+/**
+* @brief	  gets the page size of bootloader within SENSOR HUB. Prints status info and page size value on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_get_pagesz(const char *null_arg);
+
+/**
+* @brief	  sets the totatl page count for MSBL file to be uploaded to SENSOR HUB. Prints status info on command console
+*
+* @param[in]  arg : byte string including command followed by page size value extracted from header of MSBL file in DECIMAL format!
+*                   "num_pages 24"
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_set_pagecount(const char *arg);
+
+/**
+* @brief	  sets the IV vector of  MSBL file to be uploaded to SENSOR HUB. Prints status info on command console
+*             IV vector is 22 bytes of data extracted from header of MSBL file.
+*
+* @param[in]  arg : byte string including command followed by 22 byte IV value in HEXADECIMAL format! do no preceed IV bytes wirh 0x !!!!
+                    "set_iv 1234567891234567891234"
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_set_iv(const char *arg);
+
+/**
+* @brief	  sets the Authentication vector of  MSBL file to be uploaded to SENSOR HUB. Prints status info on command console
+*             Authentication vector is 36 bytes of data extracted from header of MSBL file.
+*
+* @param[in]  arg : byte string including command followed by 22 byte IV value in HEXADECIMAL format! do no preceed IV bytes wirh 0x !!!!
+                    "set_auth 12345678912345678912345678912345"
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_set_authentication(const char *arg);
+
+/**
+* @brief	  erases application code of SENSOR HUB. Prints status info on command console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_eraseflash(const char *null_arg);
+
+/**
+* @brief	  puts the SENSOR HUB to the state of waiting for MSBL application code pages from serial command interface.
+*             Prints status info on command console upon flashing of every page.
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_flash(const char *null_arg);
+
+/**
+* @brief	  sets the SENSOR HUB to the bootloader state where application image pages are first stored into HOST ram and will be flashed
+*             at once. Prints status info on command console.
+*
+* @param[in]  arg : byte string including command followed by 1 byte omage on ram flag in DECIMAL format
+*                   "image_on_ram 0/1"  0: for classic mode where pages are downloaded form PC over serial command console and
+*                    flashed to SENSOR HUB 1 by 1. 1: for image on ram mode.
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLOADER_image_on_ram( const char *arg );
+
+/**
+* @brief	  flashes pages in HOST Ram to Sensor Hub.
+*             USE ONLY IN IMAGE_ON_RAM MODE !!!!
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_flash_appimage_from_ram(const char *null_arg);
+
+/**
+* @brief	  set the delay factor multipler for Bootloader wait durations in commands and between flashing of pages
+*
+* @param[in]  arg : byte string including command followed by delay factor in DECIMAL format
+*                   "set_cfg host cdf 1" to "set_cfg host cdf 4" practical range. 1 is default.
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_set_host_bootcmds_delay_factor( const char *arg);
+
+/**
+* @brief	  get the delay factor multipler for Bootloader wait durations in commands and between flashing of pages.
+*             Prints delay factor multipler value on command console.
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_get_host_bootcmds_delay_factor( const char *null_arg);
+
+/**
+* @brief	  sets the resetting method of SENSOR HUB between command based and GPIO based resets. Default is GPIO based reset.ie 1.
+*
+* @param[in]  arg : byte string including command followed by ebl mode in DECIMAL format
+*                   "set_cfg host ebl 1/0" . 0 for command based reset; 1 for GPIO based reset which is default and preferred option.
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_set_host_ebl_mode(const char *arg);
+
+/**
+* @brief	  gets the resetting method of SENSOR HUB between command based and GPIO based resets.
+*             Prints delay factor multipler value on command console.
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int SH_BOOTLDR_get_host_ebl_mode(const char *null_arg);
+
+/**
+* @brief	  gets the struct keeping state information about bootloading steps required at HOST side.
+*             Prints struct data fields and state flags; ie. is_iv_set? page_size acquired from hub etc.
+*             If all steps are not done, flashing operation do not take place and informs user on command
+*             console
+*
+* @param[in]  null_arg : NULL string, just to match the form of command table function pointer type
+*
+* @return status info, 0x00 on success.
+**/
+int BOOTLDR_get_host_bootloader_state(const char *null_arg);
+
+
+#define NUMCMDSBOOTLDRAPI (15)
+
+const cmd_interface_tb CMDTABLEBOOTLDR[] = {
+
+		{  "bootldr"     	  , SH_BOOTLDR_enter_blmode	      			  , "resets and puts sensor hub to bootloader mode "	   			 												},
+		{  "exit"             , SH_BOOTLDR_exit_blmode        			  , "exits sensor hub from bootloader mode to app mode" 			  							  					},
+		{  "page_size"        , SH_BOOTLDR_get_pagesz         			  , "returns sensor hub bootloader page size for app data pages"   							      					},
+		{  "num_pages"        , SH_BOOTLDR_set_pagecount      			  , "sets sensor hub bootloader app image pages, uasge: num_pages PAGES" 				    						},
+		{  "set_iv"           , SH_BOOTLDR_set_iv             			  , "sets sensor hub bootloader initial vector bytes, usage: set_iv XXXXXXXXXXX (11 hex chrs)"      				},
+		{  "set_auth"         , SH_BOOTLDR_set_authentication 			  , "sets sensor hub bootloader authentication bytes, usage: set_iv XXXXXXXXXXXXXXXX (16 hex chrs)" 				},
+		{  "erase"            , SH_BOOTLDR_eraseflash         			  , "erases sesn hub application flash memory" 							        				  					},
+		{  "image_on_ram"     , SH_BOOTLOADER_image_on_ram    			  , "selects pagBypage download-flash / block download-flash options"           									},
+		{  "flash"            , SH_BOOTLDR_flash              	    	  ,  "flash image to hub/dowload pages from PC based on image_on_ram selection" 									},
+		{  "image_flash"      , SH_BOOTLDR_flash_appimage_from_ram        , "flashes app image in ram to sensor hub, call after flash cmd in image_on_ram mode"								},
+		{  "set_cfg host cdf" , SH_BOOTLDR_set_host_bootcmds_delay_factor , "sets delay factor for bootoader cmd waits default 1, usage: set_cfg host cdf FACTOR"       					},
+		{  "set_cfg host ebl" , SH_BOOTLDR_set_host_ebl_mode              , "sets GPIO/CMD reset for reset hub to bootoader mode. default GPIO, usage: set_cfg host ebl 1/0,  1 for GPIO"  	},
+		{  "get_cfg host cdf" , SH_BOOTLDR_get_host_bootcmds_delay_factor , "sets delay factor for bootoader cmd waits default 1, usage: set_cfg host cdf FACTOR"       					},
+		{  "get_cfg host ebl" , SH_BOOTLDR_get_host_ebl_mode              , "sets GPIO/CMD reset for reset hub to bootoader mode. default GPIO, usage: set_cfg host ebl 1/0,  1 for GPIO"  	},
+		{  "get_host_boot_state_info" , BOOTLDR_get_host_bootloader_state , "gets boot state keeping struct of host"  	                                                                    },
+
+
+};
+
+#endif /* SOURCE_CMDUI_BOOTLDRINTERFACE_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmdUI/cmdInterface.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,277 @@
+/*
+ * cmdInterface.cpp
+ *
+ *  Created on: Jan 30, 2019
+ *      Author: Yagmur.Gok
+ */
+
+#include <mbed.h>
+#include "cmdInterface.h"
+#include "SH_Max8614x_BareMetal.h"
+#include "bootldrAPI.h"
+#include "SHComm.h"
+#include "demoDefinitions.h"
+
+static uint8_t hostOperatingMode = HOSTMODEAPPLICATION;
+static uint8_t hostCommEchoMode  = HOSTCOMMMODE_ECHO_OFF;
+
+/* @brief    function to get the current operating mode of HOST: "APPMODE" or "BOOTLOADERMODE"
+ *           associated with command:  "get_host_opmode".
+ *
+ * @param[in]   arg : NULL string, just to match the form of command table function pointer type
+ *
+ * */
+static int get_host_operating_mode(const char* arg){
+
+	int status = 0x00;
+	SERIALOUT("\r\n%s host_operating_mode=%s\r\n", "get_host_mode", (hostOperatingMode ==HOSTMODEAPPLICATION)? "APPMODE":"BOOTLOADERMODE" );
+    return status;
+}
+
+/* @brief    function to set the current operating mode of HOST: "APPMODE" or "BOOTLOADERMODE"
+ *           associated with command:  "set_host_opmode".
+ *
+ * @param[in]   arg: whole command string with argument included:  "set_host_opmode X", X: 1 or 0
+ *                                                                                      0 : APPMODE
+ *                                                                                      1 : BOOTLOADERMODE
+ *
+ * */
+static int set_host_operating_mode(const char* arg){
+
+    int status = -1;
+	uint32_t val;
+	if(  sscanf(arg, "%*s %x", &val) == 1 ){
+		hostOperatingMode = ( val > 0 )? HOSTMODEBOOTLOADER:HOSTMODEAPPLICATION;
+
+		status = 0x00;
+	}
+	SERIALOUT("\r\n%s err=%d\r\n", "set_host_opmode", status);
+    return status;
+
+}
+
+
+/* @brief    function to get the current firmware version of Sensor Hub".
+ *
+ * @param[in]   arg : NULL string, just to match the form of command table function pointer type
+ *
+ * */
+static int get_hub_firmware_version(const char* arg){
+
+    int idx;
+	int status = -1;
+    static const int MAXFWDESCSIZE = 5;
+	uint8_t descArray[MAXFWDESCSIZE];
+    uint8_t descSz;
+
+    status = sh_get_ss_fw_version( &descArray[0] , &descSz);
+    if(status == 0x00 && descSz > 0 &&  descSz < MAXFWDESCSIZE){
+    	 SERIALOUT("\r\n Firmware Version of Sensor Hub is = ");
+         for(idx = 0 ; idx != descSz ; idx++)
+        	 SERIALOUT("%d.", descArray[idx]);
+         SERIALOUT("\r\n");
+    }
+
+
+}
+
+static int set_host_comm_echomode(const char* arg){
+
+	int status = -1;
+	uint32_t val;
+	if(  sscanf(arg, "%*s %x", &val) == 1 ){
+		hostCommEchoMode = ( val > 0 )? HOSTCOMMMODE_ECHO_ON:HOSTCOMMMODE_ECHO_OFF;
+
+		status = 0x00;
+	}
+	SERIALOUT("\r\n%s err=%d\r\n", "set_host_comm_echomode", status);
+    return status;
+
+}
+
+/*
+static int get_hub_operating_mode(const char* arg){
+
+	uint8_t hubMode;
+	int status = sh_get_sensorhub_operating_mode(&hubMode);
+	if( status == 0x00)
+		SERIALOUT("\r\n hub_operating_mode=%s\r\n", (hubMode == 0x00)? "APPMODE":"BOOTLOADERMODE" );
+	else
+		SERIALOUT("\r\n%s err=%d\r\n", "get_sensorhub_opmode", status);
+
+    return status;
+}*/
+
+//__attribute__((__always_inline__))
+uint8_t get_internal_operating_mode(void) {
+
+	return hostOperatingMode;
+}
+
+
+/* HOST MCU related mode functions inoredr to keep application&bootloader side modular:
+ *
+ *  1. in app mode Host accepts commnands related to algo/ppg applications ( command table in SH_Max8614x_BareMetal.h)
+ *     and does not check/relpy to bootloder related commnads
+ *
+ *  2. in bootloader mode Host accepts commands related to bootloader ( command table in bootldrAPI.h) only.
+ *
+ * */
+cmd_interface_t setCommEchoModeCMD  = {"set_host_echomode"   , set_host_comm_echomode , "enables/disables echoing of command console commands"};
+cmd_interface_t setHostModeCMD      = {"set_host_opmode"     , set_host_operating_mode , "sets mode of host to app or bootloader"};
+cmd_interface_t getHostModeCMD      = {"get_host_opmode"     , get_host_operating_mode , "gets mode of host app or bootloader"};
+cmd_interface_t getHubFwVersionCMD  = {"get_hub_fwversion"   , get_hub_firmware_version , "gets mode of host app or bootloader"};
+//cmd_interface_t getHubModeCMD     =  {"get_sensorhub_opmode", get_hub_operating_mode , "gets mode of host app or bootloader"};
+
+/* @brief    Compares two string to check whether they match.
+ *
+ * @param[in]   str1, str2 : strings to compare
+ *
+ * */
+
+static bool starts_with(const char* str1, const char* str2)
+{
+	while (*str1 && *str2) {
+		if (*str1 != *str2)
+			return false;
+		str1++;
+		str2++;
+	}
+
+	if (*str2)
+		return false;
+
+	return true;
+}
+
+
+
+/**
+* @brief    Command parser and executer for user input commands
+* @details  Gets the command string from command builder, compares with the commands of defined command tables of 8614x and bootloader
+*           if found calls the function associated with the command, passsing the whole command string with arguments to the called
+*           function
+*
+* @param[in]    cmd_str Input commnad from user.
+*/
+
+int parse_execute_command( const char *cmd_str)
+{
+
+	int found = 0;
+    int tableIdx;
+
+    if( starts_with(&cmd_str[0], setCommEchoModeCMD.cmdStr)) {
+    	int status = setCommEchoModeCMD.execute(cmd_str);
+        if( status != 0x00){
+        	SERIALOUT("\r\n%s err=%d\r\n", "set_host_mode", COMM_INVALID_PARAM);
+        	hostCommEchoMode  = HOSTCOMMMODE_ECHO_OFF;
+        }
+        found = 1;
+    }
+
+    if( starts_with(&cmd_str[0], setHostModeCMD.cmdStr)) {
+    	int status = setHostModeCMD.execute(cmd_str);
+        if( status != 0x00){
+        	SERIALOUT("\r\n%s err=%d\r\n", "set_host_mode", COMM_INVALID_PARAM);
+        	hostOperatingMode = HOSTMODEAPPLICATION;
+        }
+        found = 1;
+    }
+
+    if( starts_with(&cmd_str[0], getHostModeCMD.cmdStr)) {
+    	int  status = getHostModeCMD.execute(cmd_str);
+    	found = 1;
+    }
+
+    if( starts_with(&cmd_str[0], getHubFwVersionCMD.cmdStr)) {
+    	int  status = getHubFwVersionCMD.execute(cmd_str);
+    	found = 1;
+    }
+
+ /*   if( starts_with(&cmd_str[0], getHubModeCMD.cmdStr)) {
+    	int  status = getHubModeCMD.execute(cmd_str);
+    	found = 1;
+    }*/
+
+    if( hostOperatingMode == HOSTMODEAPPLICATION) {
+
+		tableIdx = NUMCMDS8614X;
+		do{
+			tableIdx -= 1;
+			if (starts_with(&cmd_str[0], CMDTABLE8614x[tableIdx].cmdStr)){
+
+				CMDTABLE8614x[tableIdx].execute(cmd_str);
+				/*MYG DEBUG8*/// SERIALPRINT("___SELECTED COMMAND IDX IS: %d \r\n", tableIdx);
+				SERIALOUT(" \r\n"); // Here is needed due to a bug on mbed serial!
+				found = 1;
+			}
+
+		}while(tableIdx && found == 0 );
+
+    }
+
+    if( hostOperatingMode == HOSTMODEBOOTLOADER) {
+
+
+    	tableIdx = NUMCMDSBOOTLDRAPI;
+		do{
+			tableIdx -= 1;
+			if (starts_with(&cmd_str[0], CMDTABLEBOOTLDR[tableIdx].cmdStr)){
+
+				CMDTABLEBOOTLDR[tableIdx].execute(cmd_str);
+				/*MYG DEBUG8*/// SERIALPRINT("___SELECTED COMMAND IDX IS: %d \r\n", tableIdx);
+				SERIALOUT(" \r\n"); // Here is needed due to a bug on mbed serial!
+				found = 1;
+			}
+
+		}while(tableIdx && found == 0 );
+    }
+
+    return found;
+}
+
+
+/**
+* @brief    Command builder from serial i/o device.
+* @details  Reads character and builds commands for application.
+*
+* @param[in]    ch Input character from i/o device.
+*/
+//__attribute__((__always_inline__))
+void cmdIntf_build_command(char ch)
+{
+	static char cmd_str[1024];
+    static int cmd_idx = 0;
+    int status;
+
+    if(hostCommEchoMode == HOSTCOMMMODE_ECHO_ON)
+    	SERIALOUT("%c", ch);
+
+	if (ch == 0x00) {
+		return;
+	}
+
+	if ((ch == '\n') || (ch == '\r')) {
+		if (cmd_idx < 1024)
+		cmd_str[cmd_idx++] = '\0';
+		status = parse_execute_command(cmd_str);
+
+		//Clear cmd_str
+		while (cmd_idx > 0)
+			cmd_str[--cmd_idx] = '\0';
+
+	} else if ((ch == 0x08 || ch == 0x7F) && cmd_idx > 0) {
+		//Backspace character
+		if (cmd_idx > 0)
+			cmd_str[--cmd_idx] = '\0';
+	} else {
+
+		if (cmd_idx < 1024)
+			cmd_str[cmd_idx++] = ch;
+	}
+
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmdUI/cmdInterface.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,40 @@
+/*
+ * cmdInterface.h
+ *
+ *  Created on: Jan 30, 2019
+ *      Author: Yagmur.Gok
+ */
+
+#ifndef SOURCE_CMDUI_CMDINTERFACE_H_
+#define SOURCE_CMDUI_CMDINTERFACE_H_
+
+#define COMM_SUCCESS        0
+#define COMM_GENERAL_ERROR  -1
+#define COMM_INVALID_PARAM  -254
+#define COMM_NOT_RECOGNIZED -255
+
+#define FLASH_ERR_GENERAL   -1
+#define FLASH_ERR_CHECKSUM  -2
+#define FLASH_ERR_AUTH      -3
+
+
+
+
+enum{
+	HOSTMODEAPPLICATION = 0,
+	HOSTMODEBOOTLOADER  = 1
+};
+
+enum{
+	HOSTCOMMMODE_ECHO_OFF = 0,
+	HOSTCOMMMODE_ECHO_ON  = 1,
+};
+
+
+
+void cmdIntf_build_command(char ch);
+uint8_t get_internal_operating_mode(void);
+
+
+#endif /* SOURCE_CMDUI_CMDINTERFACE_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoDefinitions.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,25 @@
+/*
+ * demoDefinitions.h
+ *
+ *  Created on: Feb 13, 2019
+ *      Author: Yagmur.Gok
+ */
+
+#ifndef SOURCE_DEMODEFINITIONS_H_
+#define SOURCE_DEMODEFINITIONS_H_
+
+
+#include "USBSerial.h"
+
+extern Serial daplink;
+extern USBSerial microUSB;
+//#define SERIALOUT printf
+#define SERIALOUT microUSB.printf
+#define SERIALIN microUSB._getc
+#define SERIAL_AVAILABLE microUSB.readable
+
+
+#define RAW_DATA_ONLY
+
+#endif /* SOURCE_DEMODEFINITIONS_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/demoUI.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,393 @@
+
+
+/*
+ * Note: This API i intended for demo purposes and specific to display screen LS013B7DH03. Being targeted for result display only
+ *       performance/memory measures are not taken into account! It is kept simple and some rules of embedded sw developmentare are
+ *       sacrified for being easily understandable.
+ *
+ * */
+
+#include "demoUI.h"
+/*demo specific display screen driver*/
+#include "screen/LS013B7DH03.h"
+
+const unsigned char UbuntuCondensed16x21[] = {
+		49, 16,21,3,
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char
+        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xCF, 0x01, 0xFC, 0xCF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char !
+        0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char "
+        0x0B, 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0xFE, 0x01, 0xFC, 0x1F, 0x00, 0x7C, 0x10, 0x00, 0x40, 0x10, 0x00, 0x40, 0xF0, 0x01, 0xC0, 0xFF, 0x01, 0xFC, 0x1F, 0x00, 0x7C, 0x10, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char #
+        0x08, 0x00, 0x00, 0x00, 0xE0, 0x60, 0x00, 0xF0, 0xC1, 0x00, 0x18, 0xC3, 0x00, 0x1E, 0xC7, 0x07, 0x1E, 0xC6, 0x07, 0x18, 0xFE, 0x00, 0x18, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char $
+        0x0D, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x00, 0xFC, 0x03, 0x00, 0x04, 0x02, 0x01, 0xFC, 0xE3, 0x01, 0xF8, 0x79, 0x00, 0x00, 0x1E, 0x00, 0xC0, 0x03, 0x00, 0xF0, 0xFC, 0x00, 0x3C, 0xFE, 0x01, 0x04, 0x02, 0x01, 0x00, 0xFE, 0x01, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char %
+        0x0A, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0xFE, 0x00, 0xFC, 0xC7, 0x01, 0x8C, 0x83, 0x01, 0x8C, 0x8F, 0x01, 0xFC, 0x9C, 0x01, 0x78, 0xF0, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x8E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char &
+        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char '
+        0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0xF0, 0xFF, 0x03, 0x3C, 0x00, 0x0F, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char (
+        0x04, 0x06, 0x00, 0x18, 0x3C, 0x00, 0x0F, 0xF0, 0xFF, 0x03, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char )
+        0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x58, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x3C, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x58, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char *
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x80, 0x7F, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char +
+        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x0F, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ,
+        0x05, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char -
+        0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char .
+        0x06, 0x00, 0x80, 0x1F, 0x00, 0xF8, 0x07, 0x80, 0x7F, 0x00, 0xF8, 0x07, 0x00, 0x7E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char /
+        0x08, 0x00, 0x00, 0x00, 0xF0, 0x7F, 0x00, 0xF8, 0xFF, 0x00, 0x1C, 0xC0, 0x01, 0x0C, 0x80, 0x01, 0x1C, 0xC0, 0x01, 0xF8, 0xFF, 0x00, 0xF0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 0
+        0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 1
+        0x07, 0x00, 0x00, 0x00, 0x08, 0xC0, 0x01, 0x0C, 0xF8, 0x01, 0x0C, 0x9C, 0x01, 0x0C, 0x87, 0x01, 0xFC, 0x83, 0x01, 0xF8, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 2
+        0x08, 0x00, 0x00, 0x00, 0x08, 0xC0, 0x00, 0x0C, 0x80, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x9C, 0xC7, 0x01, 0xF8, 0xFF, 0x00, 0xF0, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 3
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x80, 0x1F, 0x00, 0xF0, 0x19, 0x00, 0x3C, 0x18, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 4
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xFC, 0x83, 0x01, 0xFC, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0xC7, 0x01, 0x0C, 0xFE, 0x00, 0x0C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 5
+        0x08, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0xF0, 0xFF, 0x00, 0x78, 0xC3, 0x01, 0x18, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 6
+        0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0xC0, 0x01, 0x0C, 0xFC, 0x01, 0x8C, 0x1F, 0x00, 0xEC, 0x01, 0x00, 0x7C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 7
+        0x08, 0x00, 0x00, 0x00, 0xF0, 0x78, 0x00, 0xF8, 0xFD, 0x00, 0x0C, 0x87, 0x01, 0x0C, 0x82, 0x01, 0x0C, 0x87, 0x01, 0xF8, 0xFD, 0x00, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 8
+        0x08, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x00, 0xF8, 0x83, 0x01, 0x0C, 0x87, 0x01, 0x0C, 0xC6, 0x00, 0x1C, 0xF6, 0x00, 0xF8, 0x7F, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 9
+        0x03, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x01, 0xE0, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char :
+        0x04, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x18, 0xE0, 0x80, 0x0F, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ;
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x11, 0x00, 0x80, 0x31, 0x00, 0xC0, 0x60, 0x00, 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char <
+        0x08, 0x00, 0x00, 0x00, 0x80, 0x31, 0x00, 0x80, 0x31, 0x00, 0x80, 0x31, 0x00, 0x80, 0x31, 0x00, 0x80, 0x31, 0x00, 0x80, 0x31, 0x00, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char =
+        0x08, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x00, 0xC0, 0x60, 0x00, 0x80, 0x31, 0x00, 0x00, 0x11, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char >
+        0x07, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0xCE, 0x01, 0x0C, 0xCF, 0x01, 0x8C, 0x03, 0x00, 0xF8, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ?
+        0x10, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0xE0, 0xFF, 0x01, 0xF0, 0xC0, 0x03, 0x38, 0x00, 0x07, 0x18, 0x3E, 0x0E, 0x0C, 0x7F, 0x0C, 0x8C, 0x61, 0x0C, 0x8C, 0x61, 0x0C, 0x8C, 0x3F, 0x0C, 0x8C, 0x7F, 0x0C, 0x1C, 0x60, 0x00, 0x18, 0x60, 0x00, 0x70, 0x70, 0x00, 0xE0, 0x3F, 0x00, 0xC0, 0x1F, 0x00,  // Code for char @
+        0x0B, 0x00, 0x80, 0x01, 0x00, 0xF8, 0x01, 0x00, 0x7F, 0x00, 0xE0, 0x3F, 0x00, 0xFC, 0x30, 0x00, 0x0C, 0x30, 0x00, 0xFC, 0x30, 0x00, 0xE0, 0x37, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char A
+        0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x9C, 0xC7, 0x01, 0xF8, 0xFF, 0x00, 0xF0, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char B
+        0x09, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0xF0, 0x7F, 0x00, 0x38, 0xE0, 0x00, 0x0C, 0xC0, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x18, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char C
+        0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x1C, 0xC0, 0x01, 0x38, 0xE0, 0x00, 0xF0, 0x7F, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char D
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0x83, 0x01, 0x0C, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char E
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x0C, 0x03, 0x00, 0x0C, 0x03, 0x00, 0x0C, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char F
+        0x0A, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0xF0, 0x7F, 0x00, 0x38, 0xE0, 0x00, 0x1C, 0xC0, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0xFE, 0x01, 0x08, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char G
+        0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char H
+        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char I
+        0x06, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0xFC, 0xFF, 0x01, 0xFC, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char J
+        0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x80, 0x03, 0x00, 0xE0, 0x07, 0x00, 0x78, 0x1C, 0x00, 0x1C, 0xF8, 0x00, 0x04, 0xE0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char K
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char L
+        0x0E, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x1C, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x70, 0x00, 0x00, 0x7E, 0x00, 0xE0, 0x0F, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xE0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char M
+        0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x7C, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char N
+        0x0C, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0xF0, 0x7F, 0x00, 0x38, 0xE0, 0x00, 0x1C, 0xC0, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x01, 0x1C, 0xC0, 0x01, 0x38, 0xE0, 0x00, 0xF0, 0x7F, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char O
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x1C, 0x0E, 0x00, 0xF8, 0x07, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char P
+        0x0C, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0xF0, 0x7F, 0x00, 0x38, 0xE0, 0x00, 0x1C, 0xC0, 0x01, 0x0C, 0x80, 0x01, 0x0C, 0x80, 0x07, 0x0C, 0x80, 0x0F, 0x1C, 0xC0, 0x0D, 0x38, 0xE0, 0x18, 0xF0, 0x7F, 0x18, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char Q
+        0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x1C, 0x3E, 0x00, 0xF8, 0xF7, 0x00, 0xF0, 0xC3, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char R
+        0x07, 0x00, 0x00, 0x00, 0xF0, 0xC0, 0x00, 0xF8, 0x83, 0x01, 0x8C, 0x83, 0x01, 0x0C, 0x87, 0x01, 0x0C, 0xFE, 0x00, 0x1C, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char S
+        0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFC, 0xFF, 0x01, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char T
+        0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x7F, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xC0, 0x01, 0xFC, 0xFF, 0x00, 0xFC, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char U
+        0x09, 0x1C, 0x00, 0x00, 0xFC, 0x03, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x80, 0x01, 0x00, 0xFC, 0x01, 0xE0, 0x7F, 0x00, 0xFC, 0x07, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char V
+        0x0F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFC, 0x7F, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x80, 0x01, 0x00, 0xF8, 0x01, 0x80, 0x7F, 0x00, 0xF0, 0x07, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x80, 0x01, 0x80, 0xFF, 0x01, 0xFC, 0xFF, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char W
+        0x09, 0x04, 0x00, 0x01, 0x1C, 0xC0, 0x01, 0x78, 0xF0, 0x00, 0xE0, 0x1F, 0x00, 0x80, 0x07, 0x00, 0xE0, 0x1F, 0x00, 0x78, 0xF0, 0x00, 0x1C, 0xC0, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char X
+        0x0A, 0x04, 0x00, 0x00, 0x3C, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xFF, 0x01, 0x00, 0xFF, 0x01, 0xC0, 0x03, 0x00, 0xF8, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char Y
+        0x08, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x01, 0x0C, 0xF0, 0x01, 0x0C, 0xBE, 0x01, 0x8C, 0x8F, 0x01, 0xEC, 0x81, 0x01, 0x7C, 0x80, 0x01, 0x1C, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char Z
+        0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x1F, 0xFE, 0xFF, 0x1F, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char [
+        0x06, 0x7E, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x80, 0x7F, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char BackSlash
+        0x04, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0xFE, 0xFF, 0x1F, 0xFE, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ]
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xE0, 0x03, 0x00, 0x7C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ^
+        0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char _
+        0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char `
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xC0, 0xFC, 0x01, 0xC0, 0x8C, 0x01, 0xC0, 0x8C, 0x01, 0xC0, 0xFF, 0x01, 0x80, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char a
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0xFE, 0xFF, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0xC1, 0x01, 0x80, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char b
+        0x07, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0xFF, 0x00, 0xC0, 0xC1, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char c
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0xFF, 0x00, 0xC0, 0xC1, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xFE, 0xFF, 0x01, 0xFE, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char d
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0xFF, 0x00, 0xC0, 0xCD, 0x01, 0xC0, 0x8C, 0x01, 0xC0, 0x8C, 0x01, 0x80, 0x8F, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char e
+        0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xFE, 0xFF, 0x01, 0xC6, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char f
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0xFF, 0x18, 0xC0, 0xC1, 0x19, 0xC0, 0x80, 0x19, 0xC0, 0x80, 0x19, 0xC0, 0xFF, 0x0F, 0xC0, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char g
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0xFE, 0xFF, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x80, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char h
+        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xFF, 0x01, 0xCC, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char i
+        0x04, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0xCC, 0xFF, 0x1F, 0xCC, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char j
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0xFE, 0xFF, 0x01, 0x00, 0x1C, 0x00, 0x80, 0xFF, 0x00, 0xC0, 0xE3, 0x01, 0x40, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char k
+        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char l
+        0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0xC0, 0xFF, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x80, 0xFF, 0x01, 0xC0, 0xFF, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x80, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char m
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0xC0, 0xFF, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char n
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0xFF, 0x00, 0xC0, 0xC1, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0xC1, 0x01, 0x80, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char o
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x1F, 0xC0, 0xFF, 0x1F, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0xC1, 0x01, 0x80, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char p
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0xFF, 0x00, 0xC0, 0xC1, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0xFF, 0x1F, 0xC0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char q
+        0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0xC0, 0xFF, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char r
+        0x06, 0x00, 0x00, 0x00, 0x80, 0x87, 0x01, 0xC0, 0x8F, 0x01, 0xC0, 0x9C, 0x01, 0xC0, 0xF8, 0x01, 0xC0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char s
+        0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0xF8, 0xFF, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC0, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char t
+        0x08, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0xC0, 0xFF, 0x01, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char u
+        0x08, 0xC0, 0x01, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xFE, 0x01, 0xC0, 0x7F, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char v
+        0x0B, 0xC0, 0x03, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x80, 0x01, 0x00, 0xFE, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x80, 0x01, 0x00, 0xFE, 0x01, 0xC0, 0xFF, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char w
+        0x08, 0x40, 0x00, 0x01, 0xC0, 0xC1, 0x01, 0x80, 0xF7, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x80, 0xF7, 0x00, 0xC0, 0xC1, 0x01, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char x
+        0x07, 0xC0, 0x01, 0x18, 0xC0, 0x3F, 0x18, 0x00, 0xFE, 0x1F, 0x00, 0xE0, 0x0F, 0x00, 0xFE, 0x03, 0xC0, 0x3F, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char y
+        0x06, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x01, 0xC0, 0xF8, 0x01, 0xC0, 0xBE, 0x01, 0xC0, 0x87, 0x01, 0xC0, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char z
+        0x06, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFC, 0xFF, 0x0F, 0xFE, 0xF3, 0x1F, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char {
+        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x1F, 0xFE, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char |
+        0x05, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0xFE, 0xF3, 0x1F, 0xFC, 0xFF, 0x0F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char }
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ~
+        0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // Code for char 
+        };
+
+
+
+static const unsigned char maxim128Bitmaps[] =
+{
+
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //              #########
+		0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //            ##############
+		0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //          ##################                                               ##
+		0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //        #####################                                              ##
+		0x00, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //       ########################
+		0x00, 0x07, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //      ##########################
+		0x00, 0x0F, 0xFF, 0xFF, 0xFE, 0x00, 0x2F, 0xB8, 0x7C, 0xE3, 0x32, 0x7B, 0xC0, 0x00, 0x00, 0x00, //     ###########################           # ##### ###    #####  ###   ##  ##  #  #### ####
+		0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFC, 0x7E, 0x77, 0x33, 0xFF, 0xE0, 0x00, 0x00, 0x00, //    #############################          ############   ######  ### ###  ##  #############
+		0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x80, 0x31, 0x8C, 0x02, 0x3E, 0x33, 0x1C, 0x60, 0x00, 0x00, 0x00, //    ##############################         ##   ##   ##        #   #####   ##  ##   ###   ##
+		0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x31, 0x8C, 0x1E, 0x1C, 0x33, 0x18, 0x60, 0x00, 0x00, 0x00, //   ###############################         ##   ##   ##     ####    ###    ##  ##   ##    ##
+		0x00, 0x3E, 0x01, 0xF8, 0x0F, 0xC0, 0x31, 0x8C, 0xFA, 0x1C, 0x33, 0x18, 0x60, 0x00, 0x00, 0x00, //   #####        ######       ######        ##   ##   ##  ##### #    ###    ##  ##   ##    ##
+		0x00, 0x7E, 0x00, 0xF0, 0x07, 0xE0, 0x31, 0x8C, 0xC2, 0x1E, 0x33, 0x18, 0x60, 0x00, 0x00, 0x00, //  ######         ####         ######       ##   ##   ##  ##    #    ####   ##  ##   ##    ##
+		0x00, 0x7E, 0x18, 0xE1, 0x87, 0xE0, 0x31, 0x8C, 0xC6, 0x37, 0x33, 0x18, 0x60, 0x00, 0x00, 0x00, //  ######    ##   ###    ##    ######       ##   ##   ##  ##   ##   ## ###  ##  ##   ##    ##
+		0x00, 0xFE, 0x18, 0xE3, 0x87, 0xE0, 0x31, 0x8C, 0xEE, 0x63, 0xB3, 0x18, 0x60, 0x00, 0x00, 0x00, // #######    ##   ###   ###    ######       ##   ##   ##  ### ###  ##   ### ##  ##   ##    ##
+		0x00, 0xFE, 0x1C, 0xC3, 0x87, 0xE0, 0x31, 0x8C, 0x7A, 0xE1, 0xB3, 0x18, 0x60, 0x00, 0x00, 0x00, // #######    ###  ##    ###    ######       ##   ##   ##   #### # ###    ## ##  ##   ##    ##
+		0x00, 0xFE, 0x1C, 0xC7, 0x87, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #######    ###  ##   ####    ######
+		0x00, 0xFE, 0x1F, 0x87, 0x87, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #######    ######    ####    ######
+		0x00, 0xFE, 0x1F, 0x8F, 0x87, 0xE0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, // #######    ######   #####    ######       ##                                                                      ##
+		0x00, 0xFE, 0x1F, 0x0F, 0x87, 0xE0, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x30, // #######    #####    #####    ######       ##            ##                                    ##                  ##
+		0x00, 0xFE, 0x1E, 0x0F, 0x87, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x30, // #######    ####     #####    ######                     ##                                    ##                  ##
+		0x00, 0xFE, 0x1E, 0x07, 0x87, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x30, // #######    ####      ####    ######                     ##                                    ##                  ##
+		0x00, 0xFE, 0x1E, 0x07, 0x87, 0xE0, 0x33, 0xF1, 0xF3, 0xF1, 0xFD, 0xBB, 0xE7, 0xE7, 0xC3, 0xF0, // #######    ####      ####    ######       ##  ######   #####  ######   ####### ## ### #####  ######  #####    ######
+		0x00, 0x7E, 0x1C, 0x43, 0x87, 0xE0, 0x33, 0x98, 0xC2, 0x31, 0x19, 0xE4, 0x33, 0x0C, 0x66, 0x30, //  ######    ###   #    ###    ######       ##  ###  ##   ##    #   ##   #   ##  ####  #    ##  ##    ##   ##  ##   ##
+		0x00, 0x7E, 0x18, 0x63, 0x87, 0xE0, 0x33, 0x18, 0xC6, 0x1B, 0x19, 0xC0, 0x33, 0x0C, 0x66, 0x30, //  ######    ##    ##   ###    ######       ##  ##   ##   ##   ##    ## ##   ##  ###        ##  ##    ##   ##  ##   ##
+		0x00, 0x7E, 0x18, 0xE1, 0x87, 0xC0, 0x33, 0x18, 0xC7, 0xFB, 0x19, 0x81, 0xF3, 0x1F, 0xEE, 0x30, //  ######    ##   ###    ##    #####        ##  ##   ##   ##   ######## ##   ##  ##      #####  ##   ######## ###   ##
+		0x00, 0x3E, 0x10, 0xF1, 0x87, 0xC0, 0x33, 0x18, 0xC7, 0xF1, 0xF1, 0x87, 0xB3, 0x1F, 0xCC, 0x30, //   #####    #    ####   ##    #####        ##  ##   ##   ##   #######   #####   ##    #### ##  ##   #######  ##    ##
+		0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x33, 0x18, 0xC6, 0x01, 0xE1, 0x86, 0x33, 0x0C, 0x0E, 0x30, //   ###############################         ##  ##   ##   ##   ##        ####    ##    ##   ##  ##    ##      ###   ##
+		0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x80, 0x33, 0x18, 0xC6, 0x09, 0x81, 0x84, 0x33, 0x8C, 0x26, 0x30, //    ##############################         ##  ##   ##   ##   ##     #  ##      ##    #    ##  ###   ##    #  ##   ##
+		0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x33, 0x18, 0xF3, 0xF1, 0xF9, 0x87, 0xF1, 0xEF, 0xE7, 0xF0, //     ############################          ##  ##   ##   ####  ######   ######  ##    #######   #### #######  #######
+		0x00, 0x07, 0xFF, 0xFF, 0xFE, 0x00, 0x33, 0x18, 0x71, 0xE3, 0x1D, 0x83, 0xD0, 0xE3, 0x83, 0x90, //      ##########################           ##  ##   ##    ###   ####   ##   ### ##     #### #    ###   ###     ###  #
+		0x00, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, //       ########################                                       ##     ##
+		0x00, 0x01, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, //        ######################                                         ### ####
+		0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, //         ####################                                           #####
+		0x00, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //           ################
+		0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //             ###########
+		0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //                 ####
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+// Bitmap sizes for maxim128
+const unsigned char maxim128WidthPages   = 16;
+const unsigned char maxim128HeightPixels = 36;
+
+#define	PIN_displayCS		P0_7
+#define	PIN_displayEXTCOM	P6_4
+#define	PIN_MODE_BUTTON		P6_5
+#define	PIN_MODE_BUTTON		P2_3
+
+//#define USE_BIGFONT
+
+
+static Ticker periodicButtonCheckTimer;
+DigitalIn swithcButton(PIN_MODE_BUTTON);
+
+typedef struct{
+	PwmOut *dispPWM;
+	SPI *dispPSI;
+	DigitalOut 	*dispCS;
+	silabs::LS013B7DH03 *display;
+	InterruptIn  *button;
+	uint8_t buttonMode;
+	volatile uint8_t algoMode;
+	volatile uint8_t prevAlgoMode;
+	char buffer[32];
+
+}demo_ui_t;
+
+static demo_ui_t demoUIDEV;
+
+/*need protection with mutex or update in critical section outside isr context*/
+static unsigned int dispCnt = 0;
+
+/* Dummy Debounce Handling just for Demo Purposes*/
+void button_isr(void){
+
+    int i;
+    volatile uint32_t isr_delay  = 0;
+    demoUIDEV.button->disable_irq();
+    demoUIDEV.algoMode = 1- demoUIDEV.algoMode;
+    for(i = 10000000 ; i; i--){
+    	isr_delay++;
+    }
+    dispCnt = 0;
+    demoUIDEV.button->enable_irq();
+}
+
+void checkButtonPressed(void){
+
+    static volatile uint32_t buttonState       = 1;
+    static volatile uint32_t prevButtonState   = 1;
+    static volatile uint32_t pressDetectedFlag = 0;
+    static volatile uint32_t pressCnt = 0;
+
+    //demoUIDEV.button->disable_irq();
+    buttonState = swithcButton.read();
+    //demoUIDEV.button->enable_irq();
+
+
+}
+
+
+void demoUI_init_(demo_ui_t *demoUIDEV )
+{
+
+	static PwmOut	           displayPWM(PIN_displayEXTCOM);
+	static SPI                 displaySPI(P0_5, P0_6, P0_4, NC);
+	static DigitalOut 	       displayCS(PIN_displayCS);
+	static silabs::LS013B7DH03 display(&displaySPI , &displayCS);
+    static InterruptIn         button(PIN_MODE_BUTTON);
+
+	demoUIDEV->dispCS  = &displayCS;
+	demoUIDEV->dispPWM = &displayPWM;
+	demoUIDEV->dispPSI = &displaySPI;
+	demoUIDEV->display = &display;
+
+	demoUIDEV->button = &button;
+	demoUIDEV->buttonMode = 0;
+	demoUIDEV->algoMode       = DISPLAY_WHRM;
+	demoUIDEV->prevAlgoMode   = DISPLAY_WHRM;
+
+	demoUIDEV->dispPSI->frequency(1000000);
+	demoUIDEV->dispPWM->period_ms(16);
+	demoUIDEV->dispPWM->pulsewidth_ms(8);
+	demoUIDEV->display->clearImmediate(NULL);
+#if defined(USE_BIGFONT)
+	display.set_font(UbuntuCondensed16x21);
+#endif
+	demoUIDEV->button->fall(button_isr);
+	demoUIDEV->button->disable_irq();
+	wait_ms(20);
+	demoUIDEV->button->enable_irq();
+
+	periodicButtonCheckTimer.attach(checkButtonPressed, 0.05);
+
+}
+
+
+void demoUI_display_algo_estimations_(demo_ui_t *demoUIDEV , int integer , int confidence)
+{
+
+
+	//demoUIDEV->display->locate(3,10);
+	demoUIDEV->display->foreground(Black);
+	demoUIDEV->display->background(White);
+
+#if defined(USE_BIGFONT)
+	demoUIDEV->display->locate(2,6);
+
+#else
+	demoUIDEV->display->locate(2,4);
+#endif
+
+
+    switch( demoUIDEV->algoMode ){
+      case DISPLAY_WHRM:
+#if defined(USE_BIGFONT)
+    	    demoUIDEV->display->locate(2,22);
+			demoUIDEV->display->printf("HEART RATE");
+
+			if(integer > 10 && integer < 100)
+				 snprintf(demoUIDEV->buffer, 32, "BpS: %s%d ","  ", integer);
+			else if( integer > 100 &&  integer < 205)
+			   snprintf(demoUIDEV->buffer, 32, "BpS: %s%d "," ", integer);
+#else
+
+    	     demoUIDEV->display->printf("HEART RATE    ");
+    	     if(integer > 10 && integer < 100)
+                    snprintf(demoUIDEV->buffer, 32, "BpS: %s%d    ","  ", integer);
+      	     else if( integer > 100 &&  integer < 205)
+      	            snprintf(demoUIDEV->buffer, 32, "BpS: %s%d   "," ", integer);
+#endif
+    	     break;
+
+      case DISPLAY_REINIT:
+    	     demoUIDEV->display->printf(" PRESS AGAIN  ");
+    	     snprintf(demoUIDEV->buffer, 32, "TO REINIT HRM");
+    	     break;
+
+     }
+
+#if defined(USE_BIGFONT)
+    demoUIDEV->display->locate(10,42);
+#else
+    demoUIDEV->display->locate(2,6);
+#endif
+    demoUIDEV->display->printf(demoUIDEV->buffer);
+
+    if(confidence >= 0){
+    	demoUIDEV->display->locate(2,8);
+    	snprintf(demoUIDEV->buffer, 32, "Conf: %s%d    ","%%", confidence);
+    	demoUIDEV->display->printf(demoUIDEV->buffer);
+   }else {
+	   demoUIDEV->display->locate(2,8);
+	   snprintf(demoUIDEV->buffer, 32, "              ");
+	   demoUIDEV->display->printf(demoUIDEV->buffer);
+   }
+    demoUIDEV->display->showBMP((uint8_t*)maxim128Bitmaps, 128, 40, 0, 86);
+    demoUIDEV->display->update();
+
+	/*DEBUG*///wait_ms(20);
+}
+
+void demoUI_display_set_algoMode_( demo_ui_t *demoUIDEV , int algo){
+
+	demoUIDEV->algoMode = (algo == 0)? DISPLAY_WHRM : DISPLAY_REINIT;
+}
+int demoUI_display_get_algoMode_(demo_ui_t *demoUIDEV){
+   return (demoUIDEV->algoMode);
+}
+
+void demoUI_init(void ){
+	demoUI_init_(&demoUIDEV);
+	demoUI_display_set_algoMode_(&demoUIDEV ,DISPLAY_WHRM);
+	return;
+}
+
+void demoUI_display_algo_estimations(int integer , int confidence){
+	demoUI_display_algo_estimations_(&demoUIDEV,integer, confidence);
+	return;
+
+}
+
+
+void demoUI_display_bootldr_screen_(demo_ui_t *demoUIDEV){
+
+	demoUIDEV->display->foreground(Black);
+	demoUIDEV->display->background(White);
+	demoUIDEV->display->locate(2,4);
+	demoUIDEV->display->printf("HOST IN MODE");
+	snprintf(demoUIDEV->buffer, 32, " BOOTLOADER ");
+	demoUIDEV->display->locate(2,6);
+	demoUIDEV->display->printf(demoUIDEV->buffer);
+    demoUIDEV->display->showBMP((uint8_t*)maxim128Bitmaps, 128, 40, 0, 86);
+    demoUIDEV->display->update();
+    return;
+}
+
+
+void demoUI_display_bootldr_screen(void){
+
+	demoUI_display_bootldr_screen_(&demoUIDEV);
+	return;
+
+}
+
+void demoUI_display_set_algoMode(int algo){
+	demoUI_display_set_algoMode_(&demoUIDEV ,algo);
+	return;
+}
+
+int demoUI_display_get_mode(void){
+   return demoUI_display_get_algoMode_(&demoUIDEV);
+}
+
+void demoUI_display(int algoResult){
+     static bool is_initialized = false;
+     if( !is_initialized){
+    	 demoUI_init_(&demoUIDEV);
+    	 is_initialized = true;
+    	 return;
+     }
+     demoUI_display_algo_estimations_(&demoUIDEV,algoResult , 0);
+}
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/demoUI.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,44 @@
+/*
+ * demoUI.h
+ *
+ *  Created on: Nov 29, 2018
+ *      Author: Yagmur.Gok
+ */
+
+#ifndef SOURCE_DEMOUI_DEMOUI_H_
+#define SOURCE_DEMOUI_DEMOUI_H_
+
+#include <events/mbed_events.h>
+#include <mbed.h>
+
+#include "screen/LS013B7DH03.h"
+
+enum{
+	DISPLAY_WHRM             = 0,
+	DISPLAY_REINIT           = 1,
+};
+
+#define USE_DEMO_DISPDEV
+#if defined(USE_DEMO_DISPDEV)
+
+
+	void demoUI_init();
+	void demoUI_display_algo_estimations(int integer , int confidence);
+	void demoUI_display_set_algoMode(int algo);
+	int demoUI_display_get_mode(void);
+	void demoUI_display(int algoResult);
+	void demoUI_display_bootldr_screen(void);
+
+
+#else
+	void start_demo_display(void);
+	void display_algo_estimations( uint8_t mode , int integer, int fraction);
+	void setup_mode_button(void);
+
+#endif
+
+
+extern volatile uint8_t algoMode;
+
+#endif /* SOURCE_DEMOUI_DEMOUI_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/BufferedDisplay.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,140 @@
+/***************************************************************************//**
+ * @file BufferedDisplay.cpp
+ * @brief Buffered version of GraphicsDisplay
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include "../screen/BufferedDisplay.h"
+
+#define SWAP8(a) ((((a) & 0x80) >> 7) | (((a) & 0x40) >> 5) | (((a) & 0x20) >> 3) | (((a) & 0x10) >> 1) | (((a) & 0x08) << 1) | (((a) & 0x04) << 3) | (((a) & 0x02) << 5) | (((a) & 0x01) << 7))
+
+namespace silabs {
+
+	BufferedDisplay::BufferedDisplay(const char *name) : GraphicsDisplay(name) {
+		memset((uint8_t*)_pixelBuffer, White, sizeof(_pixelBuffer));	// init full frame buffer
+		memset((uint8_t*)_dirtyRows, 0xFF, sizeof(_dirtyRows)); 		// init dirty status
+	}
+
+	/**
+	 * Override of GraphicsDisplay's pixel()
+	 */
+
+	void BufferedDisplay::pixel(int x, int y, int colour) {
+	    /* Apply constraint to x and y */
+	    if(x < 0 || y < 0) return;
+	    if(x >= DISPLAY_WIDTH || y >= DISPLAY_HEIGHT) return;
+	    
+	    /***************************************************************************************************************** 
+	     * The display expects LSB input, while the SPI is configured for 8bit MSB transfers. Therefore, we should  
+	     * construct the framebuffer accordingly, so that an MSB transmission will put pixel 0 first on the wire.
+	     *
+	     * So the actual pixel layout in framebuffer (for 128x128) is as follows:
+	     * {                                                    //Framebuffer
+	     *	{                                                   //Line 0
+	     *	 {p0, p1, p2, p3, p4, p5, p6, p7},                  //Line 0 byte 0 (byte 0)
+	     *   {p8, p9,p10,p11,p12,p13,p14,p15},                  //Line 0 byte 1 (byte 1)
+	     *   ...
+	     *   {p120,p121,p122,p123,p124,p125,p126,p127}          //Line 0 byte 15 (byte 15)
+	     *  },        
+	     *  {													//Line 1
+	     *	 {p128,p129,p130,p131,p132,p133,p134,p135},         //Line 1 byte 0 (byte 16)
+	     *   ...
+	     *  },
+	     *  ...
+	     *  {													//Line 127
+	     *	 {...},              								//Line 127 byte 0 (byte 2032)
+	     *   ...
+	     *   {...}												//Line 127 byte 15 (byte 2047) = 128*128 bits
+	     *	}
+	     * }
+	     *
+	     * This means that to calculate the actual bit position in the framebuffer byte, we need to swap the bit 
+	     * order of the lower three bits. So pixel 7 becomes bit offset 0, 6 -> 1, 5 -> 2, 4->3, 3->4, 2->5, 1->6 and 0->7.
+	     *****************************************************************************************************************/
+	    uint8_t swapx = 7 - ((unsigned int)x & 0x07);
+	    x = ((unsigned int)x & 0xFFFFFFF8) | swapx;
+
+	    /* Since we are dealing with 1-bit pixels, we can avoid having to do bitshift and comparison operations twice.
+	     * Basically, do the comparison with the requested state and current state, and if it changed, do an XOR on the framebuffer pixel and set the line to dirty.
+	     */
+	    bool change = ((_pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] & (1 << (x & DISPLAY_BUFFER_TYPE_MASK))) != ((colour & 0x01) << (x & DISPLAY_BUFFER_TYPE_MASK)));
+		if(change) {
+			/* Pixel's value and requested value are different, so since it's binary, we can simply do an XOR */
+            _pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] ^= (1 << (x & DISPLAY_BUFFER_TYPE_MASK));
+
+            /* notify dirty status of this line */
+            _dirtyRows[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y & DISPLAY_BUFFER_TYPE_MASK));
+		}
+	}
+
+	int BufferedDisplay::width() {
+		return DISPLAY_WIDTH;
+	}
+	int BufferedDisplay::height() {
+		return DISPLAY_HEIGHT;
+	}
+
+	/**
+	 * Function to move bitmap into frame buffer
+	 * arguments:
+	 * 	* bitmap: pointer to uint8 array containing horizontal pixel data
+	 * 	* bmpWidth: width of the bitmap in pixels (must be multiple of 8)
+	 * 	* bmpHeight: height of the bitmap in pixels
+	 * 	* startX: starting position to apply bitmap in horizontal direction (0 = leftmost) (must be multiple of 8)
+	 * 	* startY: starting position to apply bitmap in vertical direction (0 = topmost)
+	 */
+	void BufferedDisplay::showBMP(const uint8_t* bitmap, const uint32_t bmpWidth, const uint32_t bmpHeight, const uint32_t startX, const uint32_t startY) {
+		uint32_t bmpLine = 0, y = startY, bytesPerLine = ((bmpWidth >= (DISPLAY_WIDTH - startX)) ? (DISPLAY_WIDTH - startX) : bmpWidth) / 8;
+
+		/* Apply constraints */
+		if((bmpWidth & 0x07) != 0) return;
+		if((startX & 0x07) != 0) return;
+		if(startX >= DISPLAY_WIDTH) return;
+		
+		//Superflouous due to for-loop check
+		//if((startY >= DISPLAY_HEIGHT) return;
+
+		/* Copy over bytes to the framebuffer, do not write outside framebuffer boundary */
+		for(; y < DISPLAY_HEIGHT; y++) {
+			/* Check that we are not writing more than the BMP height */
+			if(bmpLine >= bmpHeight) break;
+			
+			/* Copy over one line (bmpLine) from the BMP file to the corresponding line (y) in the pixel buffer */
+			memcpy( (void*) &(((uint8_t*)_pixelBuffer)[((y * DISPLAY_WIDTH) + startX) / 8]),
+					(const void*) &(bitmap[bmpLine * (bmpWidth / 8)]),
+					bytesPerLine);
+
+			/* Set dirty status for the line we just overwrote */
+			_dirtyRows[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y % DISPLAY_BUFFER_TYPE_SIZE));
+			bmpLine++;
+		}
+
+		return;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/BufferedDisplay.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,82 @@
+/***************************************************************************//**
+ * @file BufferedDisplay.h
+ * @brief Framebuffered version of GraphicsDisplay
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#ifndef SILABS_BUFFEREDDISPLAY_H
+#define SILABS_BUFFEREDDISPLAY_H
+
+#include "../screen/GraphicsDisplay.h"
+#include "../screen/LCDSettings.h"
+
+namespace silabs {
+/** Framebuffered version of GraphicsDisplay
+ * 
+ * This has been implemented as part of the MemoryLCD library.
+ */
+class BufferedDisplay : public GraphicsDisplay {
+
+public:
+
+	BufferedDisplay(const char *name=NULL);
+
+	/**
+	 * Override of GraphicsDisplay pixel() function to set a pixel in the buffer
+     *
+     * @param x      Zero-based x-axis index of pixel to set. 0 = leftmost.
+     * @param y      Zero-based y-axis index of pixel to set. 0 = topmost.
+     * @param colour Colour value to set pixel to. In this implementation, only LSB is taken into account.
+	 */
+	virtual void pixel(int x, int y, int colour);
+	virtual int width();
+	virtual int height();
+
+	/**
+	 * Function to move bitmap into frame buffer
+	 * 
+	 * @param bitmap      pointer to uint8 array containing horizontal pixel data
+	 * @param bmpWidth    width of the bitmap in pixels (must be multiple of 8)
+	 * @param bmpHeight   height of the bitmap in pixels
+	 * @param startX      starting position to apply bitmap in horizontal direction (0 = leftmost) (must be multiple of 8)
+	 * @param startY      starting position to apply bitmap in vertical direction (0 = topmost)
+	 */
+	void showBMP(const uint8_t* bitmap, const uint32_t bmpWidth, const uint32_t bmpHeight, const uint32_t startX, const uint32_t startY);
+
+protected:
+	volatile DISPLAY_BUFFER_TYPE _pixelBuffer[DISPLAY_BUFFER_ELEMENTS]; // one full frame buffer
+	volatile DISPLAY_BUFFER_TYPE _dirtyRows[DISPLAY_HEIGHT/DISPLAY_BUFFER_TYPE_SIZE]; // 1 bit per row to indicate dirty status
+};
+
+} // namespace silabs
+
+
+
+
+#endif //SILABS_BUFFEREDDISPLAY_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/GraphicsDisplay.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,457 @@
+/* mbed GraphicsDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+ 
+#include "../screen/GraphicsDisplay.h"
+
+#define incx() x++, dxt += d2xt, t += dxt
+#define incy() y--, dyt += d2yt, t += dyt
+
+const unsigned char FONT8x8[97][8] = {
+{0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, num_bytes_per_char
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space 0x20
+{0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // !
+{0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // "
+{0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // #
+{0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $
+{0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // %
+{0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // &
+{0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // '
+{0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // (
+{0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // )
+{0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // *
+{0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // +
+{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // ,
+{0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // -
+{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // .
+{0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / (forward slash)
+{0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 0x30
+{0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1
+{0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2
+{0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3
+{0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4
+{0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5
+{0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6
+{0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7
+{0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8
+{0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9
+{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // :
+{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ;
+{0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // <
+{0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // =
+{0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // >
+{0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ?
+{0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ 0x40
+{0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A
+{0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B
+{0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C
+{0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D
+{0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E
+{0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F
+{0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G
+{0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H
+{0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I
+{0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J
+{0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K
+{0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L
+{0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M
+{0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N
+{0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O
+{0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P 0x50
+{0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q
+{0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R
+{0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S
+{0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T
+{0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U
+{0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V
+{0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W
+{0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X
+{0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y
+{0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z
+{0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [
+{0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // \ (back slash)
+{0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ]
+{0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _
+{0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` 0x60
+{0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a
+{0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b
+{0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c
+{0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d
+{0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e
+{0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f
+{0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g
+{0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h
+{0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i
+{0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j
+{0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k
+{0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l
+{0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m
+{0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n
+{0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o
+{0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p
+{0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q
+{0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r
+{0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s
+{0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t
+{0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u
+{0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v
+{0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w
+{0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x
+{0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y
+{0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z
+{0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // {
+{0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // |
+{0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // }
+{0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
+{0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00}}; // DEL
+    
+GraphicsDisplay::GraphicsDisplay(const char *name):TextDisplay(name) {
+    foreground((uint16_t)Black);
+    background((uint16_t)White);
+    // current pixel location
+	_x = 0;
+	_y = 0;
+	// window settings
+	_x1 = 0;
+	_x2 = 0;
+	_y1 = 0;
+	_y2 = 0;
+}
+    
+void GraphicsDisplay::character(int column, int row, int value) { 
+    if(externalfont){ // send external font
+        unsigned int hor,vert,offset,bpl,j,i,b;
+        const unsigned char* sign;
+        unsigned char z,w;
+        if ((value < 31) || (value > 127)) return;   // test char range
+        // read font parameter from start of array
+        offset = font[0];                    // bytes / char
+        hor = font[1];                       // get hor size of font
+        vert = font[2];                      // get vert size of font
+        bpl = font[3];                       // bytes per line
+        if (char_x + hor > width()) {
+            char_x = 0;
+            char_y = char_y + vert;
+            if (char_y >= height() - font[2]) {
+                char_y = 0;
+            }
+        }     
+        window(char_x, char_y,hor,vert); // char box
+        sign = &font[((value -32) * offset) + 4]; // start of char bitmap
+        w = sign[0];                          // width of actual char
+        for (j=0; j<vert; j++) {  //  vert line
+            for (i=0; i<hor; i++) {   //  horz line
+                z =  sign[bpl * i + ((j & 0xF8) >> 3)+1];
+                b = 1 << (j & 0x07);
+                if (( z & b ) == 0x00) {               
+                    putp(_foreground);              
+                } 
+                else {                     
+                    putp(_background);                                
+                }
+            }
+        }
+        if ((w + 2) < hor) {                   // x offset to next char
+            char_x += w + 2;
+            }
+            else char_x += hor;
+    }   
+    // send default font            
+    else {
+        blitbit(column * 8, row * 8, 8, 8, (char*)&(FONT8x8[value - 0x1F][0]));
+    }
+}
+
+void GraphicsDisplay::window(int x, int y, int w, int h) {
+    // current pixel location
+    _x = x;
+    _y = y;
+    // window settings
+    _x1 = x;
+    _x2 = x + w - 1;
+    _y1 = y;
+    _y2 = y + h - 1;
+}
+    
+void GraphicsDisplay::putp(int colour) {
+    // put pixel at current pixel location
+    pixel(_x, _y, colour);
+    // update pixel location based on window settings
+    _x++;
+    if(_x > _x2) {
+        _x = _x1;
+        _y++;
+        if(_y > _y2) {
+            _y = _y1;
+        }
+    }
+}
+
+void GraphicsDisplay::rect(int x0, int y0, int x1, int y1, int color) {
+    if (x1 > x0) hline(x0,x1,y0,color);
+    else  hline(x1,x0,y0,color);
+    if (y1 > y0) vline(x0,y0,y1,color);
+    else vline(x0,y1,y0,color);
+    if (x1 > x0) hline(x0,x1,y1,color);
+    else  hline(x1,x0,y1,color);
+    if (y1 > y0) vline(x1,y0,y1,color);
+    else vline(x1,y1,y0,color);
+    return;
+}
+ 
+void GraphicsDisplay::fillrect(int x0, int y0, int w, int h, int colour) {
+    unsigned long int index=0;
+    if (w < 0) {
+        x0 = x0 + w;
+        w = -w;
+    }
+    if (h < 0) {
+        y0 = y0 + h;
+        h = -h;
+    }
+    window(x0,y0,w,h);
+    int num = h*w;
+    for( index = 0; index<num; index++ ) {
+       putp(colour); 
+    }
+    return;
+}
+
+void GraphicsDisplay::fill(int x, int y, int w, int h, int colour) { 
+    fillrect(x, y, w, h, colour);
+}
+
+void GraphicsDisplay::circle(int x, int y, int r,int colour){
+	int ce = -r;
+	int cx = r;
+	int cy = 0;
+	while(cx >= cy){
+		pixel(x+cx,y+cy,colour);
+		pixel(x-cx,y-cy,colour);
+		pixel(x-cx,y+cy,colour);
+		pixel(x+cx,y-cy,colour);
+		pixel(x+cy,y+cx,colour);
+		pixel(x-cy,y+cx,colour);
+		pixel(x-cy,y-cx,colour);
+		pixel(x+cy,y-cx,colour);
+		ce += 2*cy++ + 1;
+		if(ce >= 0){
+			ce -= 2*cx---1;	
+		}
+		
+	}
+
+}
+
+// To draw circle set a and b to the same values
+void GraphicsDisplay::ellipse(int xc, int yc, int a, int b, unsigned int colour)
+{
+    /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
+    int x = 0, y = b;
+    long a2 = (long)a*a, b2 = (long)b*b;
+    long crit1 = -(a2/4 + a%2 + b2);
+    long crit2 = -(b2/4 + b%2 + a2);
+    long crit3 = -(b2/4 + b%2);
+    long t = -a2*y;                         // e(x+1/2,y-1/2) - (a^2+b^2)/4
+    long dxt = 2*b2*x, dyt = -2*a2*y;
+    long d2xt = 2*b2, d2yt = 2*a2;
+ 
+    while (y>=0 && x<=a) {
+        pixel(xc+x, yc+y, colour);
+        if (x!=0 || y!=0)
+            pixel(xc-x, yc-y, colour);
+        if (x!=0 && y!=0) {
+            pixel(xc+x, yc-y, colour);
+            pixel(xc-x, yc+y, colour);
+        }
+        if (t + b2*x <= crit1 ||            // e(x+1,y-1/2) <= 0
+                t + a2*y <= crit3)          // e(x+1/2,y) <= 0
+            incx();
+        else if (t - a2*y > crit2)          // e(x+1/2,y-1) > 0
+            incy();
+        else {
+            incx();
+            incy();
+        }
+    }
+}
+// To draw circle set a and b to the same values
+void GraphicsDisplay::fillellipse(int xc, int yc, int a, int b, unsigned int colour)
+{
+    /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
+    int x = 0, y = b;
+    int rx = x, ry = y;
+    unsigned int width = 1;
+    unsigned int height = 1;
+    long a2 = (long)a*a, b2 = (long)b*b;
+    long crit1 = -(a2/4 + a%2 + b2);
+    long crit2 = -(b2/4 + b%2 + a2);
+    long crit3 = -(b2/4 + b%2);
+    long t = -a2*y;                         // e(x+1/2,y-1/2) - (a^2+b^2)/4
+    long dxt = 2*b2*x, dyt = -2*a2*y;
+    long d2xt = 2*b2, d2yt = 2*a2;
+    if (b == 0) {
+        fillrect(xc-a, yc, 2*a+1, 1, colour);
+        return;
+    }
+    while (y>=0 && x<=a) {
+        if (t + b2*x <= crit1 ||            // e(x+1,y-1/2) <= 0
+                t + a2*y <= crit3) {        // e(x+1/2,y) <= 0
+            if (height == 1)
+                ;                           // draw nothing
+            else if (ry*2+1 > (height-1)*2) {
+                fillrect(xc-rx, yc-ry, width, height-1, colour);
+                fillrect(xc-rx, yc+ry+1, width, 1-height, colour);
+                ry -= height-1;
+                height = 1;
+            } else {
+                fillrect(xc-rx, yc-ry, width, ry*2+1, colour);
+                ry -= ry;
+                height = 1;
+            }
+            incx();
+            rx++;
+            width += 2;
+        } else if (t - a2*y > crit2) {      // e(x+1/2,y-1) > 0
+            incy();
+            height++;
+        } else {
+            if (ry*2+1 > height*2) {
+                fillrect(xc-rx, yc-ry, width, height, colour);
+                fillrect(xc-rx, yc+ry+1, width, -height, colour);
+            } else {
+                fillrect(xc-rx, yc-ry, width, ry*2+1, colour);
+            }
+            incx();
+            incy();
+            rx++;
+            width += 2;
+            ry -= height;
+            height = 1;
+        }
+    }
+    if (ry > height) {
+        fillrect(xc-rx, yc-ry, width, height, colour);
+        fillrect(xc-rx, yc+ry+1, width, -height, colour);
+    } else {
+        fillrect(xc-rx, yc-ry, width, ry*2+1, colour);
+    }
+}
+ 
+ 
+void GraphicsDisplay::line(int x0, int y0, int x1, int y1, int colour) {
+    //window(x0, y, w, h);
+    int   dx = 0, dy = 0;
+    int   dx_sym = 0, dy_sym = 0;
+    int   dx_x2 = 0, dy_x2 = 0;
+    int   di = 0;
+    dx = x1-x0;
+    dy = y1-y0;
+ 
+    if (dx == 0) {        /* vertical line */
+        if (y1 > y0) vline(x0,y0,y1,colour);
+        else vline(x0,y1,y0,colour);
+        return;
+    }
+    if (dx > 0) {
+        dx_sym = 1;
+    } else {
+        dx_sym = -1;
+    }
+    if (dy == 0) {        /* horizontal line */
+        if (x1 > x0) hline(x0,x1,y0,colour);
+        else  hline(x1,x0,y0,colour);
+        return;
+    }
+    if (dy > 0) {
+        dy_sym = 1;
+    } else {
+        dy_sym = -1;
+    }
+    dx = dx_sym*dx;
+    dy = dy_sym*dy;
+    dx_x2 = dx*2;
+    dy_x2 = dy*2;
+    if (dx >= dy) {
+        di = dy_x2 - dx;
+        while (x0 != x1) {
+ 
+            pixel(x0, y0, colour);
+            x0 += dx_sym;
+            if (di<0) {
+                di += dy_x2;
+            } else {
+                di += dy_x2 - dx_x2;
+                y0 += dy_sym;
+            }
+        }
+        pixel(x0, y0, colour);
+    } else {
+        di = dx_x2 - dy;
+        while (y0 != y1) {
+            pixel(x0, y0, colour);
+            y0 += dy_sym;
+            if (di < 0) {
+                di += dx_x2;
+            } else {
+                di += dx_x2 - dy_x2;
+                x0 += dx_sym;
+            }
+        }
+        pixel(x0, y0, colour);
+    }
+    return;
+}
+ 
+void GraphicsDisplay::hline(int x0, int x1, int y, int colour) {
+    int w;
+    w = x1 - x0 + 1;
+    window(x0,y,w,1);
+    for (int x=0; x<w; x++) {
+        putp(colour);
+    }
+    return;
+}
+ 
+void GraphicsDisplay::vline(int x, int y0, int y1, int colour) {
+    int h;
+    h = y1 - y0 + 1;
+    window(x,y0,1,h);
+    for (int y=0; y<h; y++) {
+        putp(colour);
+    }
+    return;
+}
+
+void GraphicsDisplay::cls() {
+    fill(0, 0, width(), height(), _background);
+}
+    
+void GraphicsDisplay::blit(int x, int y, int w, int h, const int *colour) { 
+    window(x, y, w, h);
+    for(int i=0; i<w*h; i++) {
+        putp(colour[i]);
+    }
+}
+    
+void GraphicsDisplay::blitbit(int x, int y, int w, int h, const char* colour) {
+    window(x, y, w, h);
+    for(int i = 0; i < w*h; i++) {
+        char byte = colour[i >> 3];
+        int offset = i & 0x7;
+        int c = ((byte << (offset)) & 0x80) ? _foreground : _background;
+        putp(c);
+    }
+}
+    
+int GraphicsDisplay::columns() { 
+    return width() / 8; 
+}
+
+int GraphicsDisplay::rows() { 
+    return height() / 8; 
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/GraphicsDisplay.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,69 @@
+/* mbed GraphicsDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * A library for providing a common base class for Graphics displays
+ * To port a new display, derive from this class and implement
+ * the constructor (setup the display), pixel (put a pixel
+ * at a location), width and height functions. Everything else
+ * (locate, printf, putc, cls, window, putp, fill, blit, blitbit) 
+ * will come for free. You can also provide a specialised implementation
+ * of window and putp to speed up the results
+ */
+
+#ifndef MBED_GRAPHICSDISPLAY_H
+#define MBED_GRAPHICSDISPLAY_H
+
+#include "../screen/TextDisplay.h"
+
+class GraphicsDisplay : public TextDisplay {
+
+public:         
+          
+    GraphicsDisplay(const char* name);
+     
+    virtual void pixel(int x, int y, int colour) = 0;
+    virtual int width() = 0;
+    virtual int height() = 0;
+        
+    virtual void window(int x, int y, int w, int h);
+    virtual void putp(int colour);
+    
+    virtual void cls();
+    virtual void rect(int x0, int y0, int x1, int y1, int colour);
+    virtual void fillrect(int x0, int y0, int w, int h, int colour);
+    // fill equals fillrect, name has been kept to not break compatibility
+    virtual void fill(int x, int y, int w, int h, int colour);
+    
+    // To draw circle using ellipse, set a and b to the same values
+    virtual void ellipse(int xc, int yc, int a, int b, unsigned int colour);
+    virtual void fillellipse(int xc, int yc, int a, int b, unsigned int colour);
+    virtual void circle(int x, int y, int r, int colour);
+    
+    virtual void hline(int x0, int x1, int y, int colour);
+    virtual void vline(int x0, int y0, int y1, int colour);
+    virtual void line(int x0, int y0, int x1, int y1, int colour);
+    
+    virtual void blit(int x, int y, int w, int h, const int *colour);    
+    virtual void blitbit(int x, int y, int w, int h, const char* colour);
+    
+    virtual void character(int column, int row, int value);
+    virtual int columns();
+    virtual int rows();
+    
+protected:
+
+    // pixel location
+    short _x;
+    short _y;
+    
+    // window location
+    short _x1;
+    short _x2;
+    short _y1;
+    short _y2;
+
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/LCDSettings.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,30 @@
+#ifndef LCDSETTINGS_H
+#define LCDSETTINGS_H
+
+/** MemoryLCD width in pixels */ 
+#define DISPLAY_WIDTH				(128)
+
+/** MemoryLCD height in pixels */
+#define DISPLAY_HEIGHT				(128)
+
+/** Data type for storing buffer the pixel buffer */
+#if	((DISPLAY_WIDTH % 32) == 0)
+#define	DISPLAY_BUFFER_TYPE			uint32_t
+#define DISPLAY_BUFFER_TYPE_MASK    (0x1F)
+#else
+#define DISPLAY_BUFFER_TYPE			uint8_t
+#define DISPLAY_BUFFER_TYPE_MASK    (0x07)
+#endif
+
+#define DISPLAY_BUFFER_TYPE_SIZE	(sizeof(DISPLAY_BUFFER_TYPE) * 8)
+#define DISPLAY_BUFFER_ELEMENTS 	((DISPLAY_WIDTH*DISPLAY_HEIGHT)/DISPLAY_BUFFER_TYPE_SIZE)
+
+/** Maximum length of a printf to the display */
+#define MAX_PRINTF_CHARS			40
+
+/** Color definitions */
+#define White						0xFFFFFFFF
+#define Black						0x00000000
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/LS013B7DH03.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,246 @@
+/***************************************************************************//**
+ * @file LS013B7DH03.cpp
+ * @brief Driver class for the Sharp LS013B7DH03 memory LCD on some kits.
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include "../screen/LS013B7DH03.h"
+
+#include <mbed.h>
+#include "SPI.h"
+//#include "Peripherals.h"
+
+/* LS013B7DH03 SPI commands */
+#define LS013B7DH03_CMD_UPDATE     (0x01)
+#define LS013B7DH03_CMD_ALL_CLEAR  (0x04)
+
+/* Macro to switch endianness on char value */
+#define SWAP8(a) ((((a) & 0x80) >> 7) | (((a) & 0x40) >> 5) | (((a) & 0x20) >> 3) | (((a) & 0x10) >> 1) | (((a) & 0x08) << 1) | (((a) & 0x04) << 3) | (((a) & 0x02) << 5) | (((a) & 0x01) << 7))
+
+namespace silabs {
+
+
+LS013B7DH03::LS013B7DH03(mbed::SPI * spi, DigitalOut * CS, const char *name) : BufferedDisplay( name )  {
+	//Save pointer to ChipSelect pin
+	_CS = CS;
+	_CS->write(0);
+	DigitalOut DISP(P6_6);
+
+//Save pointer to ExtCom pin
+///	_EXTCOM = ExtCom;
+///	_EXTCOM->write(0);
+
+	DISP  = 0;
+	wait_ms(1);
+	DISP = 1;
+
+	//Save pointer to spi peripheral
+	_spi = spi;
+	//_spi->frequency(600000);
+	_spi->format( 8, 0 );
+
+	_internalEventCallback.attach(this, &LS013B7DH03::_cbHandler);
+
+	//Initialize
+	//_spi->set_dma_usage((DMAUsage)DMA_USAGE_NEVER);
+	_refreshCount = 0;
+	_lcdPolarity = 0;
+	_state = IDLE;
+	_completionCallbackPtr = NULL;
+	_rowCount = 0;
+
+	//Start toggling the EXTCOM pin
+	//_displayToggler.attach(this, &LS013B7DH03::toggle, 0.008f);
+}
+
+/**
+ * Call this function at 55 ~ 65 Hz to keep the display up-to-date.
+ */
+void LS013B7DH03::toggle() {
+//	_EXTCOM->write(!_EXTCOM->read());
+//	_refreshCount++;
+}
+
+/**
+ * Function to get internal refresh counter
+ */
+uint32_t LS013B7DH03::getRefreshTicks() {
+	return _refreshCount;
+}
+
+/**
+ * Call this function to push all changes to the display
+ */
+int LS013B7DH03::update( cbptr_t callback ) {
+	uint32_t rowCount = 0;
+	bool update = false;
+
+	// Check if something actually changed in the pixelbuffer
+	for(rowCount = 0; rowCount < DISPLAY_HEIGHT/DISPLAY_BUFFER_TYPE_SIZE; rowCount++) {
+		if(_dirtyRows[rowCount] != 0) update = true;
+	}
+
+	if(update == false) return LS013B7DH03_NO_ACTION;
+
+	// Watch out to not mess up a transfer
+	if(_state != IDLE) return LS013B7DH03_ERROR_BUSY;
+
+	_completionCallbackPtr = callback;
+
+	// Take control
+	_state = WAIT_WRITE;
+	_rowCount = 0;
+
+	//Initialize the command vector
+	_cmd[0] = (uint8_t)SWAP8(LS013B7DH03_CMD_UPDATE);
+	_cmd[1] = SWAP8(1);
+
+	// Activate LCD
+	_CS->write(1);
+	_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.01f);
+
+	return LS013B7DH03_OK;
+}
+
+/**
+ * Function to test display buffer
+ */
+int LS013B7DH03::showDemo() {
+	for(uint32_t i = 0; i < DISPLAY_BUFFER_ELEMENTS; i+=2) {
+		_pixelBuffer[i] = 0x00555345;
+	}
+	memset((void*)_dirtyRows, 0x33, sizeof(_dirtyRows));
+
+	return LS013B7DH03_OK;
+}
+
+/**
+ * Call this function to immediately clear the display
+ */
+int LS013B7DH03::clearImmediate( cbptr_t callback ) {
+	// Watch out to not mess up a transfer
+	if(_state != IDLE) return LS013B7DH03_ERROR_BUSY;
+
+	_state = WAIT_CLEAR;
+	_completionCallbackPtr = callback;
+
+	// Clear out the pixel buffer
+	memset((void*)_pixelBuffer, White, sizeof(_pixelBuffer));
+	memset((void*)_dirtyRows, 0, sizeof(_dirtyRows));
+
+	_cmd[0] = (uint8_t)(SWAP8(LS013B7DH03_CMD_ALL_CLEAR | _lcdPolarity));
+	_cmd[1] = 0;
+
+	// Wait for the ChipSelect line
+	_CS->write(1);
+	_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.01f);
+
+	return LS013B7DH03_OK;
+}
+
+void LS013B7DH03::_cbHandlerTimeout( void ) {
+	this->_cbHandler(0);
+}
+
+void LS013B7DH03::_cbHandler( int event ) {
+	if((_state == WAIT_WRITE) || (_state == WRITING))
+	{
+		_state = WRITING;
+		while(_rowCount < DISPLAY_HEIGHT) {
+			// Determine the next line to send
+			if((_dirtyRows[_rowCount / DISPLAY_BUFFER_TYPE_SIZE] & (1 << (_rowCount % DISPLAY_BUFFER_TYPE_SIZE))) != 0) {
+
+				// Row is dirty, send an update to the display
+				_cmd[1] = (uint8_t)SWAP8(_rowCount + 1);
+				memcpy((void*)&(_cmd[2]), (const void*)&(_pixelBuffer[_rowCount*(DISPLAY_WIDTH/DISPLAY_BUFFER_TYPE_SIZE)]), DISPLAY_WIDTH / DISPLAY_BUFFER_TYPE_SIZE * sizeof(DISPLAY_BUFFER_TYPE));
+
+				if(_spi->write((const char*)_cmd, (2 + (DISPLAY_WIDTH / DISPLAY_BUFFER_TYPE_SIZE * sizeof(DISPLAY_BUFFER_TYPE))) , (char*)NULL, 0/*, _internalEventCallback, SPI_EVENT_COMPLETE*/) != (2 + (DISPLAY_WIDTH / DISPLAY_BUFFER_TYPE_SIZE * sizeof(DISPLAY_BUFFER_TYPE)))) {
+					// SPI is busy, with another transaction. This means the data to the LCD has been corrupted, so fail here.
+					_state = DONE;
+					//printf("Failed at _cbHandler\n");
+					// Make sure the handler is called again
+					_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.1f);
+				}else{	//sc...
+					_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.001f);
+				}
+
+				// Transaction is in progress, so update row state
+				_dirtyRows[_rowCount / DISPLAY_BUFFER_TYPE_SIZE] &= ~(1 << (_rowCount % DISPLAY_BUFFER_TYPE_SIZE));
+				_rowCount++;
+				return;
+			}
+
+			// Row wasn't touched, so check the next row
+			_rowCount++;
+		}
+
+		// Done sending!
+		_cmd[1] = 0xFF;
+		_state = TRANSFERS_DONE;
+		if(_spi->write((const char*)_cmd, 2, (char*)NULL, 0/*, _internalEventCallback, SPI_EVENT_COMPLETE*/) != 2) {
+			// SPI is busy, with another transaction. This means the data to the LCD has been corrupted, so fail here.
+			_state = DONE;
+
+			// Make sure the handler is called again
+			_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.1f);
+		}else{	//sc...
+			_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.001f);
+		}
+		return;
+	}
+	else if (_state == WAIT_CLEAR)
+	{
+		_state = TRANSFERS_DONE;
+		if(_spi->write((const char*)_cmd, 2, (char*)NULL, 0/*, _internalEventCallback, SPI_EVENT_COMPLETE*/) != 2) {
+			// SPI is busy, with another transaction. This means the data to the LCD has been corrupted, so fail here.
+			_state = DONE;
+
+			// Make sure the handler is called again
+			_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.1f);
+		}else{	//sc...
+			_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.001f);
+		}
+		return;
+	}
+	else if (_state == TRANSFERS_DONE)
+	{
+		_state = DONE;
+		_csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.01f);
+		return;
+	}
+	else if (_state == DONE)
+	{
+		_CS->write(0);
+		_state = IDLE;
+		if(_completionCallbackPtr != 0) _completionCallbackPtr();
+		return;
+	}
+}
+
+} // namespace silabs
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/LS013B7DH03.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,124 @@
+/***************************************************************************//**
+ * @file LS013B7DH03.h
+ * @brief Driver class for the Sharp LS013B7DH03 memory LCD on some kits.
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#ifndef SILABS_LS013B7DH03_H
+#define SILABS_LS013B7DH03_H
+
+#include "platform.h"
+#include <mbed.h>
+#include "../screen/BufferedDisplay.h"
+#include "../screen/LCDSettings.h"
+//#include "Peripherals.h"
+
+typedef void (*cbptr_t)(void);
+
+#define LS013B7DH03_ERROR_BUSY		-1
+#define LS013B7DH03_ERROR_SPI_BUSY	-2
+#define LS013B7DH03_NO_ACTION		-3
+#define LS013B7DH03_ERROR_ARGUMENT	-4
+#define	LS013B7DH03_OK				0
+
+typedef enum {
+	IDLE,			// No operation currently ongoing
+	CLEARING,		// In the process of clearing the display
+	WRITING,		// In the process of sending a display update
+	WAIT_CLEAR,		// Going to clear after CS pin timeout
+	WAIT_WRITE,		// Going to write after CS pin timeout
+	TRANSFERS_DONE, // Last transfer in progress
+	DONE			// Done with transmission, waiting for CS pin to become high
+} LS013B7DH03_state_t;
+
+namespace silabs {
+class LS013B7DH03 : public BufferedDisplay {
+
+public:
+
+	LS013B7DH03(SPI * spi, DigitalOut * CS,  const char *name=NULL);
+
+	/**
+	 * Call this function to push all changes to the display
+	 */
+	int update( cbptr_t callback = NULL );
+
+	/**
+	 * Immediately clear the display: set pixel buffer to zero and clear out the display.
+	 */
+	int clearImmediate( cbptr_t callback = NULL );
+
+	/**
+	 * Function to test display buffer
+	 */
+	int showDemo();
+
+
+
+	/**
+	 * Function to get internal refresh counter
+	 */
+	uint32_t getRefreshTicks();
+
+
+protected:
+	mbed::SPI *_spi;
+	//mbed::DigitalOut *_EXTCOM;
+	mbed::DigitalOut *_CS;
+
+	mbed::Ticker _displayToggler;
+	mbed::Timeout _csTimeout;
+
+	event_callback_t _internalEventCallback;
+	volatile uint32_t _refreshCount;
+	uint8_t _lcdPolarity;
+	LS013B7DH03_state_t _state;
+	cbptr_t _completionCallbackPtr;
+	volatile uint32_t _rowCount;
+	uint8_t _cmd[2 + (DISPLAY_WIDTH / DISPLAY_BUFFER_TYPE_SIZE * sizeof(DISPLAY_BUFFER_TYPE))];
+
+	/**
+	 * Callback handler for internal SPI transfers.
+	 */
+	void _cbHandler( int event );
+
+	/**
+	 * Callback handler for internal SPI transfers triggered by timeout.
+	 */
+	void _cbHandlerTimeout( void );
+
+	/**
+	 * Call this function at 55 ~ 65 Hz to keep the display from losing contrast.
+	 */
+	void toggle();
+};
+
+} // namespace silabs
+
+#endif //SILABS_LS013B7DH03_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/TextDisplay.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,94 @@
+/* mbed TextDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+ 
+#include "../screen/TextDisplay.h"
+
+#include <cstdarg>
+
+TextDisplay::TextDisplay(const char *name){
+    _row = 0;
+    _column = 0;
+
+    if (name == NULL) {
+        _path = NULL;
+    } else {
+        _path = new char[strlen(name) + 2];
+        sprintf(_path, "/%s", name);
+    }
+}
+    
+int TextDisplay::_putc(int value) {
+    if(value == '\n') {
+        _column = 0;
+        _row++;
+        if(_row >= rows()) {
+            _row = 0;
+        }
+    } else {
+        character(_column, _row, value);
+        _column++;
+        if(_column >= columns()) {
+            _column = 0;
+            _row++;
+            if(_row >= rows()) {
+                _row = 0;
+            }
+        }
+    }
+    return value;
+}
+
+// crude cls implementation, should generally be overwritten in derived class
+void TextDisplay::cls() {
+    locate(0, 0);
+    for(int i=0; i<columns()*rows(); i++) {
+        _putc(' ');
+    }
+}
+
+void TextDisplay::set_font(const unsigned char * f) {
+    font = f;
+    if(font==NULL) {
+    	externalfont = 0;  // set display.font
+    	locate(0, 0);
+    }    
+    else{
+    	externalfont = 1;
+    	locate(0, 0);
+    }
+}
+
+void TextDisplay::locate(int column, int row) {
+    _column = column;
+    _row = row;
+    char_x = column;
+    char_y = row;
+}
+
+int TextDisplay::_getc() {
+    return -1;
+}
+        
+void TextDisplay::foreground(uint16_t colour) {
+    _foreground = colour;
+}
+
+void TextDisplay::background(uint16_t colour) {
+    _background = colour;
+}
+
+void TextDisplay::printf(const char* format, ...) {
+	char buffer[MAX_PRINTF_CHARS + 1] = { 0 };
+	uint32_t iterator = 0;
+	va_list args;
+	va_start(args, format);
+	vsprintf(buffer, format, args);
+	va_end(args);
+
+	while((buffer[iterator] != 0) && (iterator < MAX_PRINTF_CHARS)) {
+		_putc(buffer[iterator++]);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demoUI/screen/TextDisplay.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,93 @@
+/* mbed TextDisplay Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * A common base class for Text displays
+ * To port a new display, derive from this class and implement
+ * the constructor (setup the display), character (put a character
+ * at a location), rows and columns (number of rows/cols) functions.
+ * Everything else (locate, printf, putc, cls) will come for free
+ *
+ * The model is the display will wrap at the right and bottom, so you can
+ * keep writing and will always get valid characters. The location is 
+ * maintained internally to the class to make this easy
+ */
+
+#ifndef MBED_TEXTDISPLAY_H
+#define MBED_TEXTDISPLAY_H
+
+#include "../screen/LCDSettings.h"
+#include "mbed.h"
+
+class TextDisplay {
+public:
+
+  // functions needing implementation in derived implementation class
+  /** Create a TextDisplay interface
+     *
+     * @param name The name used in the path to access the strean through the filesystem
+     */
+    TextDisplay(const char *name = NULL);
+
+    /** output a character at the given position
+     *
+     * @param column column where charater must be written
+     * @param  row where character must be written
+     * @param c the character to be written to the TextDisplay
+     */
+    virtual void character(int column, int row, int c) = 0;
+
+    /** return number if rows on TextDisplay
+     * @result number of rows
+     */
+    virtual int rows() = 0;
+
+    /** return number if columns on TextDisplay
+    * @result number of rows
+    */
+    virtual int columns() = 0;
+    
+    // Sets external font usage, eg. dispaly.set_font(Arial12x12);
+    // This uses pixel positioning.
+    // display.set_font(NULL); returns to internal default font.
+    void set_font(const unsigned char * f);
+    
+    // set position of the next character or string print.
+    // External font, set pixel x(column),y(row) position.
+    // internal(default) font, set character column and row position 
+    virtual void locate(int column, int row);
+    
+    // functions that come for free, but can be overwritten
+
+    /** clear screen
+    */
+    virtual void cls();
+    virtual void foreground(uint16_t colour);
+    virtual void background(uint16_t colour);
+    // putc (from Stream)
+    // printf (from Stream)
+    virtual void printf(const char* format, ...);
+    
+protected:
+
+    virtual int _putc(int value);
+    virtual int _getc();
+    
+    // external font functions
+    const unsigned char* font;
+    int externalfont;
+ 
+    // character location
+    uint16_t _column;
+    uint16_t _row;
+    unsigned int char_x;
+    unsigned int char_y;
+
+    // colours
+    uint16_t _foreground;
+    uint16_t _background;
+    char *_path;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+
+/**********************************************************************************
+ *
+ *  Desc: Example Code to get algorithm estimation results of Heart rate( HRM) from sensor hub and display it on screen.
+ *        Example starts by monitoring heart rate and reinits WHRM algorithm via a button press (switch button)
+ *
+ *        Example,
+ *
+ *        1. Initializes user interface
+ *                   initialize display screen and switch button for algo selection.
+ *
+ *        2. Initializes underlying hardware port for sensor hub communication:
+ *                   setup i2c comm. inits reset pin and mfio event pin and connects interrupt to mfio pin.
+ *
+ *        3. When switched to a minitoring mode
+ *                   disables previous algorithm, clears mfio event
+ *                   calls default init function for the sensor whose data is used by enabled algorithms. Algorithms are
+ *                   registered under sesnor instance for this example. Fcunction
+ *                   	        1. initialize algorithm config struct enabled
+ *                              2. enable data type to both raw sensor and algorithm data
+ *                              3. get input fifo size to learn fifo capacity
+ *                              4. set fifo threshold for mfio event frequency
+ *                              5. reaenable sensor to acquire ppg data
+ *                              6. enable accompanying accel sensor
+ *                              7. enable switched algorithm
+ *
+ *     4. Sensor Hub now starts to write raw sensor/algorithm data to its data report FIFO which
+ *        reports mfio event when data size determined by fifo threshold is written to report fifo.
+ *
+ *     5. Example calls SH_Max8614x_data_report_execute() which
+ *                 1. calls SH API's sh_ss_execute_once() function which:
+ *                            writes sensor hub's report fifo content (sensor/algorithm data samples) to a buffer(1).
+ *                 2. calls CSTMR_SH_FeedAccDataIntoSH() to send accelerometer data to sensor hub which os required for heart rate
+ *                 3. Parses buffer(1) data to extract numeric sensor and algorithm samples according to enabled algorithms.
+ *                    look: whrm_data_rx() , max8614x_data_rx() and sample structs whrm_mode1_data and max8614x_mode1_data
+ *
+ *     6. numeric values  are written to HrmResult  within MAX8614x  whrm_data_rx() ... and included as extern in main.cpp
+ *
+ *     7. Example calls demoUI_display_algo_estimations() to display result on watch screen
+ *
+ *
+ ***********************************************************************************/
+
+#include <events/mbed_events.h>
+#include <mbed.h>
+#include "max32630hsp.h"
+#include "SHComm.h"
+#include "SH_Max8614x_BareMetal.h"
+#include "bmi160.h"
+#include "cmdInterface.h"
+#include "demoUI.h"
+#include "demoDefinitions.h"
+
+extern uint16_t HrmResult;
+extern uint8_t  HrmConfidence;
+
+DigitalOut debugled(LED1, 1);
+// Hardware serial port over DAPLink
+Serial daplink(USBTX, USBRX, 115200);
+
+#include "USBSerial.h"
+USBSerial microUSB(0x1f00, 0x2012, 0x0001, false);
+
+
+
+// ICARUS Board initialization
+InterruptIn interruptIn_PowerButton(P7_6);
+MAX32630HSP icarus(MAX32630HSP::VIO_1V8, &interruptIn_PowerButton);
+
+#define WAIT_SENSORHUB_STABLE_BOOTUP_MS  ((uint32_t)2000)
+
+
+static bool isWhrmInitialized     = false;
+
+int main() {
+
+	wait_ms(WAIT_SENSORHUB_STABLE_BOOTUP_MS);
+
+	int hostMode = HOSTMODEAPPLICATION;
+
+	demoUI_init();
+
+	sh_init_hwcomm_interface();
+	sh_disable_irq_mfioevent();
+	sh_clear_mfio_event_flag();
+	sh_enable_irq_mfioevent();
+	int i = 0;
+
+	int displayMode;
+	uint16_t resultToDisplay;
+	uint8_t  confidenceToDisplay;
+
+	while(1) {
+
+		char ch;
+		while ( SERIAL_AVAILABLE()) {
+
+			ch = SERIALIN();
+			cmdIntf_build_command(ch);
+		}
+
+        hostMode  = get_internal_operating_mode();
+		if( hostMode  == HOSTMODEAPPLICATION) {
+
+				displayMode = demoUI_display_get_mode();
+
+				if( displayMode == kAlgoModeHeartRate ){
+					 if( !isWhrmInitialized){
+#if defined(DEBUG_INFO)
+						 SERIALOUT(" WHRM inititalized \r\n");
+#endif
+						 SH_Max8614x_stop();
+						 SH_Max8614x_default_init(kAlgoModeHeartRate);
+						 isWhrmInitialized = true;
+						 wait_ms(100); /* for display screen*/
+					 }
+					 resultToDisplay     = HrmResult;
+					 confidenceToDisplay = HrmConfidence;
+
+				}else if( displayMode == reinitHeartRate ){
+					isWhrmInitialized = false;
+              	}
+
+				int cumSampleCNt = SH_Max8614x_data_report_execute();
+
+				if(cumSampleCNt){ /* If data samples ara avaliable display on screen*/
+#if defined(DEBUG_INFO)
+					//SERIALOUT("estimate: =%d conf: %d dispMode: %d \r\n", resultToDisplay , confidenceToDisplay, displayMode);
+#endif					if( displayMode == kAlgoModeHeartRate)
+						     demoUI_display_algo_estimations(resultToDisplay, -1);
+
+				}
+
+
+		}else {
+
+				demoUI_display_bootldr_screen();
+               //wait_ms(10);
+		}
+
+	}
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#0fdfcf7350896a9c0b57c4a18237677abfe25f1a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/MAX20303.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,367 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+
+#include "MAX20303.h"
+
+
+
+//******************************************************************************
+MAX20303::MAX20303(I2C *i2c):
+	m_i2c(i2c), m_writeAddress(MAX20303_SLAVE_WR_ADDR),
+	m_readAddress(MAX20303_SLAVE_RD_ADDR)
+{
+}
+
+
+//******************************************************************************
+MAX20303::~MAX20303(void)
+{
+  //empty block
+}
+
+
+//******************************************************************************
+int MAX20303::LDO1Config()
+{
+	int32_t ret = 0;
+	uint8_t val;
+//	ret |= writeReg(MAX20303::REG_AP_CMDOUT, 0x40);
+//	ret |= writeReg(MAX20303::REG_AP_DATOUT0, 0x05);
+//	ret |= writeReg(MAX20303::REG_AP_DATOUT1, 0x34);
+//
+//	readReg(MAX20303::REG_AP_CMDOUT, val);
+//	readReg(MAX20303::REG_AP_DATOUT0, val);
+//	readReg(MAX20303::REG_AP_DATOUT1, val);
+	appcmdoutvalue_ = 0x40;
+	appdatainoutbuffer_[0] = 0x05;
+	appdatainoutbuffer_[1] = 0x34;
+	AppWrite(2);
+
+	return ret;
+}
+
+//******************************************************************************
+int MAX20303::LDO2Config()
+{
+	int32_t ret = 0;
+	uint8_t val;
+	appcmdoutvalue_ = 0x42;
+	appdatainoutbuffer_[0] = 0x01;
+	appdatainoutbuffer_[1] = 0x15;     // 0.9V + (0.1V * number)   =  3V
+	AppWrite(2);
+
+	return ret;
+}
+
+
+//******************************************************************************
+int MAX20303::writeReg(registers_t reg, uint8_t value)
+{
+	int32_t ret;
+
+	char cmdData[2] = {reg, value};
+
+	ret = m_i2c->write(m_writeAddress, cmdData, sizeof(cmdData));
+	//printf("MAX20303 write reg[0x%X]=0x%X, ret=%d\r\n", (uint32_t)reg, value, ret)
+
+	if (ret != 0)
+		return MAX20303_ERROR;
+
+	return MAX20303_NO_ERROR;
+}
+
+
+//******************************************************************************
+int MAX20303::readReg(registers_t reg, uint8_t &value)
+{
+	int32_t ret;
+
+	char data = reg;
+
+	ret = m_i2c->write(m_writeAddress, &data, sizeof(data));
+	if (ret != 0) {
+		printf("%s - failed - ret: %d\n", __func__);
+		return MAX20303_ERROR;
+	}
+
+	ret = m_i2c->read(m_readAddress, &data, sizeof(data));
+	if (ret != 0) {
+		printf("%s - failed - ret: %d\n", __func__);
+		return MAX20303_ERROR;
+	}
+
+	value = data;
+	printf("MAX20303 read reg[0x%X]=0x%X, ret=%d\r\n", (uint32_t)reg, value, ret);
+	return MAX20303_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX20303::readRegMulti(registers_t reg, uint8_t *value, uint8_t len){
+	int32_t ret;
+	char data = reg;
+
+	ret = m_i2c->write(m_writeAddress, &data, sizeof(data));
+	if (ret != 0) {
+		printf("%s - failed - ret: %d\n", __func__);
+		return MAX20303_ERROR;
+	}
+
+	ret = m_i2c->read(m_readAddress, (char *)value, len);
+	if (ret != 0) {
+		printf("%s - failed - ret: %d\n", __func__);
+		return MAX20303_ERROR;
+	}
+
+	printf("MAX20303 read reg[0x%X]=0x%X, ret=%d\r\n", (uint32_t)reg, value, ret);
+	return MAX20303_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX20303::writeRegMulti(registers_t reg, uint8_t *value, uint8_t len){
+	int32_t ret;
+	i2cbuffer_[0] = reg;
+	memcpy(&i2cbuffer_[1], value, len);
+
+	ret = m_i2c->write(m_writeAddress, (char *)i2cbuffer_, (len+1));
+	//printf("MAX20303 write reg[0x%X]=0x%X, ret=%d\r\n", (uint32_t)reg, value, ret)
+
+	if (ret != 0)
+		return MAX20303_ERROR;
+
+	return MAX20303_NO_ERROR;
+}
+//******************************************************************************
+int MAX20303::mv2bits(int mV)
+{
+    int regBits;
+
+    if (( MAX20303_LDO_MIN_MV <= mV) && (mV <= MAX20303_LDO_MAX_MV)) {
+        regBits = (mV -  MAX20303_LDO_MIN_MV) /  MAX20303_LDO_STEP_MV;
+    } else {
+        return -1;
+    }
+
+    return regBits;
+}
+//******************************************************************************
+int MAX20303::PowerOffthePMIC(){
+	int ret;
+	appdatainoutbuffer_[0] = 0xB2;
+	appcmdoutvalue_ = 0x80;
+	ret = AppWrite(1);
+
+	if(appcmdoutvalue_ != 0x80){
+		ret |= MAX20303_ERROR;
+	}
+
+	return ret;
+}
+//******************************************************************************
+int MAX20303::PowerOffDelaythePMIC(){
+	int ret;
+	appdatainoutbuffer_[0] = 0xB2;
+	appcmdoutvalue_ = 0x84;
+	ret = AppWrite(1);
+
+	if(appcmdoutvalue_ != 0x80){
+		ret |= MAX20303_ERROR;
+	}
+
+	return ret;
+}
+
+//******************************************************************************
+int MAX20303::SoftResetthePMIC(){
+	int ret;
+	appdatainoutbuffer_[0] = 0xB3;
+	appcmdoutvalue_ = 0x81;
+	ret = AppWrite(1);
+
+	if(appcmdoutvalue_ != 0x81){
+		ret |= MAX20303_ERROR;
+	}
+
+	return ret;
+}
+//******************************************************************************
+int MAX20303::HardResetthePMIC(){
+	int ret;
+	appdatainoutbuffer_[0] = 0xB4;
+	appcmdoutvalue_ = 0x82;
+	ret = AppWrite(1);
+
+	if(appcmdoutvalue_ != 0x82){
+		ret |= MAX20303_ERROR;
+	}
+
+	return ret;
+}
+
+//******************************************************************************
+int MAX20303::AppWrite(uint8_t dataoutlen){
+	int ret;
+
+	ret = writeRegMulti(MAX20303::REG_AP_DATOUT0, appdatainoutbuffer_, dataoutlen);
+	ret |= writeReg(MAX20303::REG_AP_CMDOUT, appcmdoutvalue_);
+	wait_ms(10);
+	ret |= readReg(MAX20303::REG_AP_RESPONSE, appcmdoutvalue_);
+
+	if(ret != 0)
+		return MAX20303_ERROR;
+
+	return MAX20303_NO_ERROR;
+}
+
+
+//******************************************************************************
+int MAX20303::AppRead(uint8_t datainlen){
+	int ret;
+
+	ret = writeReg(MAX20303::REG_AP_CMDOUT, appcmdoutvalue_);
+	wait_ms(10);
+	ret |= readRegMulti(MAX20303::REG_AP_RESPONSE, i2cbuffer_, datainlen);
+	if(ret != 0)
+		return MAX20303_ERROR;
+
+	return MAX20303_NO_ERROR;
+}
+
+//******************************************************************************
+char MAX20303::CheckPMICHWID(){
+	int ret;
+	uint8_t value = 0x00;
+
+	ret = readReg(MAX20303::REG_HARDWARE_ID, value);
+	if(ret != MAX20303_NO_ERROR)
+		return false;
+
+	if(value == 0x02)
+		return true;
+	else
+		return false;
+}
+
+//******************************************************************************
+int MAX20303::CheckPMICStatusRegisters(unsigned char buf_results[5]){
+	int ret;
+	ret  = readReg(MAX20303::REG_STATUS0, buf_results[0]);
+	ret |= readReg(MAX20303::REG_STATUS1, buf_results[1]);
+	ret |= readReg(MAX20303::REG_STATUS2, buf_results[2]);
+	ret |= readReg(MAX20303::REG_STATUS3, buf_results[3]);
+	ret |= readReg(MAX20303::REG_SYSTEM_ERROR, buf_results[4]);
+	return ret;
+}
+
+//******************************************************************************
+int MAX20303::Max20303_BatteryGauge(unsigned char *batterylevel){
+    int ret;
+    char data[2];
+
+    data[0] = 0x04;
+    ret = m_i2c->write(MAX20303_I2C_ADDR_FUEL_GAUGE, data, 1);
+    if(ret != 0){
+        printf("Max20303_FuelGauge has failed\r\n");
+    }
+
+    ret = m_i2c->read(MAX20303_I2C_ADDR_FUEL_GAUGE | 1, data, 2);
+    if(ret != 0){
+        printf("Max20303_FuelGauge has failed\r\n");
+    }
+
+    // if the level is more than 100 assume the battery is not connected
+    if(data[0] > 100){
+        *batterylevel = 0;
+    } else{
+
+        *batterylevel = data[0];
+    }
+    return 0;
+}
+
+
+//******************************************************************************
+int MAX20303::led0on(char enable) {
+
+	if(enable)
+		return writeReg(REG_LED0_DIRECT, 0x21);
+	else
+		return writeReg(REG_LED0_DIRECT, 0x01);
+}
+
+//******************************************************************************
+int MAX20303::led1on(char enable) {
+	if(enable)
+		return writeReg(REG_LED1_DIRECT, 0x21);
+	else
+		return writeReg(REG_LED1_DIRECT, 0x01);
+}
+
+//******************************************************************************
+int MAX20303::led2on(char enable) {
+	if(enable)
+		return writeReg(REG_LED2_DIRECT, 0x21);
+	else
+		return writeReg(REG_LED2_DIRECT, 0x01);
+}
+
+
+//******************************************************************************
+int MAX20303::BoostEnable(void) {
+	writeReg(REG_AP_DATOUT3, 0x00);	// 00 : 5V
+	writeReg(REG_AP_DATOUT0, 0x01);	// Boost Enabled
+	writeReg(REG_AP_CMDOUT, 0x30);
+	return MAX20303_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX20303::BuckBoostEnable(void)
+{
+	int ret = 0;
+
+	ret |= writeReg( REG_AP_DATOUT0,  0x00);    // Reserved = 0x00
+	ret |= writeReg( REG_AP_DATOUT1,  0x04);    // BBstlSet = 0b'100   Buck Boost Peak current Limit = 200mA
+	ret |= writeReg( REG_AP_DATOUT2,  0x19);    // BBstVSet = 0b'11001  Buck Boost Output Voltage = 5V
+	ret |= writeReg( REG_AP_DATOUT3,  0x01);    // BBstRipRed = 1 Ripple Reduction
+	// BBstAct    = 1 Actively discharged in Hard-Reset or Enable Low
+	// BBstPas    = 1 Passively discharged in Hard-Reset or Enable Low
+	// BBstMd     = 1 Damping Enabled
+	// BBstInd    = 0  Inductance is 4.7uH
+	// BBstEn     = 0b'01 Enabled
+	ret |= writeReg( REG_AP_CMDOUT, 0x70);
+	if (ret != 0)
+		return MAX20303_ERROR;
+
+	return MAX20303_NO_ERROR;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/MAX20303.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef __MAX20303_H_
+#define __MAX20303_H_
+
+#include "mbed.h"
+
+#define MAX20303_SLAVE_ADDR		(0x50 >> 1)
+#define MAX20303_SLAVE_WR_ADDR		((MAX20303_SLAVE_ADDR << 1))
+#define MAX20303_SLAVE_RD_ADDR		((MAX20303_SLAVE_ADDR << 1) | 1)
+
+
+#define MAX20303_NO_ERROR   0
+#define MAX20303_ERROR      -1
+
+#define MAX20303_I2C_ADDR_FUEL_GAUGE	0x6c
+#define MAX20303_I2C_ADDR_FUEL_GAUGE    0x6C
+
+#define MAX20303_LDO_MIN_MV 800
+#define MAX20303_LDO_MAX_MV 3600
+#define MAX20303_LDO_STEP_MV 100
+
+#define MAX20303_OFF_COMMAND 0xB2
+
+class MAX20303
+{
+
+public:
+	/**
+	 * @brief   Register Addresses
+	 * @details Enumerated MAX20303 register addresses
+	 */
+	enum registers_t {
+		REG_HARDWARE_ID		= 0x00,		///< HardwareID Register
+		REG_FIRMWARE_REV	= 0x01,		///< FirmwareID Register
+		//					= 0x02,		///<
+		REG_INT0			= 0x03,		///< Int0 Register
+		REG_INT1			= 0x04,		///< Int1 Register
+		REG_INT2			= 0x05,		///< Int2 Register
+		REG_STATUS0			= 0x06,		///< Status Register 0
+		REG_STATUS1			= 0x07,		///< Status Register 1
+		REG_STATUS2			= 0x08,		///< Status Register 2
+		REG_STATUS3			= 0x09,		///< Status Register 2
+		//					= 0x0A,		///<
+		REG_SYSTEM_ERROR	= 0x0B,		///< SystemError Register
+		REG_INT_MASK0		= 0x0C,		///< IntMask0 Register
+		REG_INT_MASK1		= 0x0D,		///< IntMask1 Register
+		REG_INT_MASK2		= 0x0E,		///< IntMask1 Register
+		REG_AP_DATOUT0		= 0x0F,     ///< APDataOut0 Register
+		REG_AP_DATOUT1		= 0x10,     ///< APDataOut1 Register
+		REG_AP_DATOUT2		= 0x11,     ///< APDataOut2 Register
+		REG_AP_DATOUT3		= 0x12,     ///< APDataOut3 Register
+		REG_AP_DATOUT4		= 0x13,     ///< APDataOut4 Register
+		REG_AP_DATOUT5		= 0x14,     ///< APDataOut5 Register
+		REG_AP_DATOUT6		= 0x15,     ///< APDataOut6 Register
+		REG_AP_CMDOUT		= 0x17,     ///< APCmdOut Register
+		REG_AP_RESPONSE		= 0x18,     ///< APResponse Register
+		REG_AP_DATAIN0		= 0x19,
+		REG_AP_DATAIN1		= 0x1A,
+		REG_AP_DATAIN2		= 0x1B,
+		REG_AP_DATAIN3		= 0x1C,
+		REG_AP_DATAIN4		= 0x1D,
+		REG_AP_DATAIN5		= 0x1E,
+		//					= 0x1F,		///<
+		REG_LDO_DIRECT		= 0x20,
+		REG_MPC_DIRECTWRITE	= 0x21,
+		REG_MPC_DIRECTRED	= 0x22,
+
+		REG_LED_STEP_DIRECT	= 0x2C,
+		REG_LED0_DIRECT		= 0x2D,
+		REG_LED1_DIRECT		= 0x2E,
+		REG_LED2_DIRECT		= 0x2F,
+
+
+		REG_LDO1_CONFIG_WRITE = 0x40,
+		REG_LDO1_CONFIG_READ  = 0x41,
+		REG_LDO2_CONFIG_WRITE = 0x42,
+		REG_LDO2_CONFIG_READ  = 0x43
+
+		/*
+		REG_CHG_TMR = 0x0C,   ///< Charger Timers
+		REG_BUCK1_CFG = 0x0D,   ///< Buck 1 Configuration
+		REG_BUCK1_VSET = 0x0E,   ///< Buck 1 Voltage Setting
+		REG_BUCK2_CFG = 0x0F,   ///< Buck 2 Configuration
+		REG_BUCK2_VSET = 0x10,   ///< Buck 2 Voltage Setting
+		REG_RSVD_11 = 0x11,   ///< Reserved 0x11
+		REG_LDO1_CFG = 0x12,   ///< LDO 1 Configuration
+		REG_LDO1_VSET = 0x13,   ///< LDO 1 Voltage Setting
+		REG_LDO2_CFG = 0x14,   ///< LDO 2 Configuration
+		REG_LDO2_VSET = 0x15,   ///< LDO 2 Voltage Setting
+		REG_LDO3_CFG = 0x16,   ///< LDO 3 Configuration
+		REG_LDO3_VSET = 0x17,   ///< LDO 3 Voltage Setting
+		REG_THRM_CFG = 0x18,   ///< Thermistor Configuration
+		REG_MON_CFG = 0x19,   ///< Monitor Multiplexer Configuration
+		REG_BOOT_CFG = 0x1A,   ///< Boot Configuration
+		REG_PIN_STATUS = 0x1B,   ///< Pin Status
+		REG_BUCK_EXTRA = 0x1C,   ///< Additional Buck Settings
+		REG_PWR_CFG = 0x1D,   ///< Power Configuration
+		REG_NULL = 0x1E,   ///< Reserved 0x1E
+		REG_PWR_OFF = 0x1F,   ///< Power Off Register
+		*/
+	};
+
+	/**
+	* @brief  Constructor using reference to I2C object
+	* @param i2c - Reference to I2C object
+	* @param slaveAddress - 7-bit I2C address
+	*/
+	MAX20303(I2C *i2c);
+
+	/** @brief Destructor */
+	~MAX20303(void);
+
+	int led0on(char enable);
+	int led1on(char enable);
+	int led2on(char enable);
+	int BoostEnable(void);
+	int BuckBoostEnable(void);
+
+	/// @brief Enable the 1.8V output rail **/
+	int LDO1Config(void);
+
+	/// @brief Enable the 3V output rail **/
+	int LDO2Config(void);
+
+
+	int mv2bits(int mV);
+
+	/** @brief Power Off the board
+	 */
+	int PowerOffthePMIC();
+
+	/** @brief Power Off the board with 30ms delay
+	 */
+	int PowerOffDelaythePMIC();
+
+	/** @brief Soft reset the PMIC
+	 */
+	int SoftResetthePMIC();
+
+	/** @brief Hard reset the PMIC
+	 */
+	int HardResetthePMIC();
+
+	/** @brief check if can communicate with max20303
+	*/
+	char CheckPMICHWID();
+
+	/** @brief CheckPMICStatusRegisters
+	*/
+	int CheckPMICStatusRegisters(unsigned char buf_results[5]);
+
+    int Max20303_BatteryGauge(unsigned char *batterylevel);
+
+private:
+
+	int writeReg(registers_t reg, uint8_t value);
+	int readReg(registers_t reg, uint8_t &value);
+
+	int writeRegMulti(registers_t reg, uint8_t *value, uint8_t len);
+	int readRegMulti(registers_t reg, uint8_t *value, uint8_t len);
+
+	/// I2C object
+	I2C  *m_i2c;
+
+	/// Device slave addresses
+	uint8_t m_writeAddress, m_readAddress;
+
+	// Application Processor Interface Related Variables
+	uint8_t i2cbuffer_[16];
+	uint8_t appdatainoutbuffer_[8];
+	uint8_t appcmdoutvalue_;
+
+
+	/** @brief API Related Functions ***/
+
+	/***
+	 *  @brief  starts writing from ApResponse register 0x0F
+	 *  check the datasheet to determine the value of dataoutlen
+	 */
+	int AppWrite(uint8_t dataoutlen);
+
+	/** @brief starts reading from ApResponse register 0x18
+	 *  check the datasheet to determine the value of datainlen
+	 *  the result values are written into i2cbuffer
+	 *
+	*/
+	int AppRead(uint8_t datainlen);
+};
+
+#endif /* __MAX20303_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/max32630hsp.cpp	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "mbed.h"
+#include "max3263x.h"
+#include "ioman_regs.h"
+#include "PinNames.h"
+#include "max32630hsp.h"
+
+
+//******************************************************************************
+MAX32630HSP::MAX32630HSP() : i2c(P5_7, P6_0), max20303(&i2c)
+{
+}
+
+//******************************************************************************
+MAX32630HSP::MAX32630HSP(vio_t vio) : i2c(P5_7, P6_0), max20303(&i2c)
+{
+
+    init(vio);
+}
+
+//******************************************************************************
+MAX32630HSP::MAX32630HSP(vio_t vio, InterruptIn *max32630hsp3_powerButtonInterrupt) : i2c(P5_7, P6_0), max20303(&i2c), m_max32630hsp3_powerButtonInterrupt(max32630hsp3_powerButtonInterrupt)
+{
+    init(vio);
+
+    m_max32630hsp3_powerButtonInterrupt->disable_irq();
+    m_max32630hsp3_powerButtonInterrupt->rise(this, &MAX32630HSP::event_powerButtonReleased);
+    m_max32630hsp3_powerButtonInterrupt->mode(PullUp);
+	m_max32630hsp3_powerButtonInterrupt->enable_irq();
+}
+
+
+//******************************************************************************
+MAX32630HSP::~MAX32630HSP()
+{
+
+}
+
+
+//******************************************************************************
+int MAX32630HSP::init(vio_t hdrVio)
+{
+	/* Wait for pmic to settle down */
+	wait_ms(800);
+
+
+
+	/*Set LDO1 to 1.8v*/
+	max20303.LDO1Config();
+
+	/*Set LDO2 to 3v*/
+    max20303.LDO2Config();
+
+	//max20303.BoostEnable();
+	max20303.BuckBoostEnable();
+
+
+	max20303.led0on(0);
+	max20303.led1on(0);
+	max20303.led2on(0);
+
+	/* Wait for pmic to settle down */
+    wait_ms(200);
+
+    // Set LED pins to 3.3V
+    vddioh(P2_4, VIO_3V3);
+    vddioh(P2_5, VIO_3V3);
+    vddioh(P2_6, VIO_3V3);
+
+    // set i2c pins to 1.8V
+    vddioh(P3_4, VIO_1V8);
+    vddioh(P3_5, VIO_1V8);
+    //ble module pins to 1.8V
+    vddioh(P0_0, VIO_1V8);
+    vddioh(P0_1, VIO_1V8);
+    vddioh(P0_2, VIO_1V8);
+    vddioh(P0_3, VIO_1V8);
+
+    // Set header pins to hdrVio
+    vddioh(P3_0, hdrVio);
+    vddioh(P3_1, hdrVio);
+    vddioh(P3_2, hdrVio);
+    vddioh(P3_3, hdrVio);
+    vddioh(P4_0, hdrVio);
+    vddioh(P4_1, hdrVio);
+    vddioh(P4_2, hdrVio);
+    vddioh(P4_3, hdrVio);
+    vddioh(P4_4, hdrVio);
+    vddioh(P4_5, hdrVio);
+    vddioh(P4_6, hdrVio);
+    vddioh(P4_7, hdrVio);
+    vddioh(P5_0, hdrVio);
+    vddioh(P5_1, hdrVio);
+    vddioh(P5_2, hdrVio);
+    vddioh(P5_3, hdrVio);
+    vddioh(P5_4, hdrVio);
+    vddioh(P5_5, hdrVio);
+    vddioh(P5_6, hdrVio);
+
+
+    button_longpressdetected = false;
+
+    return 0;
+}
+
+
+void MAX32630HSP::event_powerButtonPressed(void) {
+
+	max20303.led0on(0);
+	max20303.led1on(0);
+	max20303.led2on(1);
+
+	/* Button press detected. Wait for button release */
+    m_max32630hsp3_powerButtonInterrupt->disable_irq();
+    m_max32630hsp3_powerButtonInterrupt->rise(this, &MAX32630HSP::event_powerButtonReleased);
+    m_max32630hsp3_powerButtonInterrupt->mode(PullUp);
+	m_max32630hsp3_powerButtonInterrupt->enable_irq();
+
+	/* Button press detected. Start Timeout object for checking long key press event */
+	button_timeout.attach( this, &MAX32630HSP::event_longpresscheck , 2.0 );
+
+	/* Button is pressed */
+	button_status = true;
+}
+
+//******************************************************************************
+void MAX32630HSP::event_powerButtonReleased(void) {
+
+
+	if ( button_longpressdetected ) {
+
+		/* Power of the PMIC if long key press is detected */
+		max20303.PowerOffDelaythePMIC();
+
+	}
+	else {
+
+		/* Button released before a long key press is detected */
+		button_status = false;
+
+	}
+
+	/* Button is released. Stop timeout object */
+	button_timeout.detach();
+
+	max20303.led0on(0);
+	max20303.led1on(0);
+	max20303.led2on(0);
+
+	/* Button is released. Expect for button press event next time */
+    m_max32630hsp3_powerButtonInterrupt->disable_irq();
+    m_max32630hsp3_powerButtonInterrupt->fall(this, &MAX32630HSP::event_powerButtonPressed);
+    m_max32630hsp3_powerButtonInterrupt->mode(PullUp);
+	m_max32630hsp3_powerButtonInterrupt->enable_irq();
+
+
+}
+
+void MAX32630HSP::event_longpresscheck(void) {
+
+	/* This is the callback for timeout object to detect long key press for power down */
+
+	if ( button_status == 1 ) {
+
+		/* If button_status is still 1 when timeout is triggered, it will be interpreted as a long key press */
+		button_longpressdetected = true;
+
+		/* The PMIC will be powered of when the button is released */
+		max20303.led0on(0);
+		max20303.led1on(1);
+		max20303.led2on(0);
+	}
+
+}
+
+void MAX32630HSP::enableDisplay(void)
+{
+	vddioh(P6_4, VIO_3V3); //EXTCOM
+	vddioh(P6_1, VIO_3V3); //SCLK
+	vddioh(P6_2, VIO_3V3); //MOSI1
+	vddioh(P6_5, VIO_3V3); //SCS
+	vddioh(P6_4, VIO_3V3); //EXTCOM
+	vddioh(P6_6, VIO_3V3); //DISP
+}
+
+//******************************************************************************
+int MAX32630HSP::vddioh(PinName pin, vio_t vio)
+{
+    __IO uint32_t *use_vddioh = &((mxc_ioman_regs_t *)MXC_IOMAN)->use_vddioh_0;
+
+    if (pin == NOT_CONNECTED) {
+        return -1;
+    }
+
+    use_vddioh += PINNAME_TO_PORT(pin) >> 2;
+    if (vio) {
+        *use_vddioh |= (1 << (PINNAME_TO_PIN(pin) + ((PINNAME_TO_PORT(pin) & 0x3) << 3)));
+    } else {
+        *use_vddioh &= ~(1 << (PINNAME_TO_PIN(pin) + ((PINNAME_TO_PORT(pin) & 0x3) << 3)));
+    }
+
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/max32630hsp.h	Mon Mar 18 10:21:53 2019 +0300
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#ifndef _MAX32630HSP_H_
+#define _MAX32630HSP_H_
+
+#include "mbed.h"
+#include "MAX20303.h"
+
+
+/**
+ * @brief MAX32630HSP Board Support Library
+ *
+ * @details The MAX32630HSP is a rapid development application board for
+ * ultra low power wearable applications.  It includes common peripherals and
+ * expansion connectors all power optimized for getting the longest life from
+ * the battery.  This library configures the power and I/O for the board.
+ * <br>https://www.maximintegrated.com/max32630hsp
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "max32630hsp.h"
+ *
+ * DigitalOut led1(LED1);
+ * MAX32630HSP icarus(MAX32630HSP::VIO_3V3);
+ *
+ * // main() runs in its own thread in the OS
+ * // (note the calls to Thread::wait below for delays)
+ * int main()
+ * {
+ *     // initialize power and I/O on MAX32630HSP board
+ *     icarus.init();
+ *
+ *     while (true) {
+ *         led1 = !led1;
+ *         Thread::wait(500);
+ *     }
+ * }
+ * @endcode
+ */
+
+// Sharp LS013B7DH03 Memory Display
+#define SCK_PIN     		P6_1
+#define MOSI_PIN    		P6_2
+#define CS_PIN      		P6_5
+#define EXTCOM_PIN  		P6_4
+#define DISP_PIN    		P6_6
+#define DISPSEL_PIN 		NC
+#define	PIN_POWERBUTTON		P7_6
+#define	PIN_UPBUTTON		P2_3
+#define	PIN_DOWNBUTTON		P6_5
+
+class MAX32630HSP
+{
+public:
+// max32630hsp configuration utilities
+
+    /**
+      * @brief   IO Voltage
+      * @details Enumerated options for operating voltage
+      */
+    typedef enum {
+        VIO_1V8 = 0x00,    ///< 1.8V IO voltage at headers (from BUCK2)
+        VIO_3V3 = 0x01,    ///< 3.3V IO voltage at headers (from LDO2)
+    } vio_t;
+
+    enum ButtonStatus {
+    	BUTTONSTATUS_RELEASED = 1,
+		BUTTONSTATUS_PRESSED
+    } ;
+
+    /**
+        * MAX32630HSP constructor.
+        *
+        */
+    MAX32630HSP();
+
+    /**
+        * MAX32630HSP constructor.
+        *
+        */
+    MAX32630HSP(vio_t vio);
+
+    /**
+        * MAX32630HSP constructor.
+        *
+        */
+    MAX32630HSP(vio_t vio, InterruptIn *max32630hsp3_powerButtonInterrupt);
+
+    /**
+        * MAX32630HSP destructor.
+        */
+    ~MAX32630HSP();
+
+    //InterruptIn _interruptIn_PowerButton;
+
+    /**
+     * @brief   Initialize MAX32630HSP board
+     * @details Initializes PMIC and I/O on MAX32630HSP board.
+     *  Configures PMIC to enable LDO2 and LDO3 at 3.3V.
+     *  Disables resisitive pulldown on MON(AIN_0)
+     *  Sets default I/O voltages to 3V3 for micro SD card.
+     *  Sets I/O voltage for header pins to hdrVio specified.
+     * @param hdrVio I/O voltage for header pins
+     * @returns 0 if no errors, -1 if error.
+    */
+    int init(vio_t hdrVio);
+
+    /**
+     * @brief   Sets I/O Voltage
+     * @details Sets the voltage rail to be used for a given pin.
+     *  VIO_1V8 selects VDDIO which is supplied by Buck2, which is set at 1.8V,
+     *  VIO_3V3 selects VDDIOH which is supplied by LDO2, which is typically 3.3V/
+     * @param   pin Pin whose voltage supply is being assigned.
+     * @param   vio Voltage rail to be used for specified pin.
+     * @returns 0 if no errors, -1 if error.
+    */
+    int vddioh(PinName pin, vio_t vio);
+
+    /**Interrupt Hander for Power Button Press**/
+
+    //InterruptIn _interruptIn_UpButton(PIN_UPBUTTON);
+    //InterruptIn _interruptIn_DownButton(PIN_DOWNBUTTON);
+
+    /* Set vddio for Sharp LS013B7DH03 Display */
+	void enableDisplay(void);
+
+    /// Local I2C bus for configuring PMIC and accessing BMI160 IMU.
+    I2C i2c;
+
+    /// MAX20303 PMIC Instance
+    MAX20303 max20303;
+
+
+    InterruptIn *m_max32630hsp3_powerButtonInterrupt;
+    bool	button_status;
+    bool	button_longpressdetected;
+    Timeout	button_timeout;
+
+    ButtonStatus status_powerButton;
+    ButtonStatus status_upButton;
+    ButtonStatus status_downButton;
+    void event_powerButtonPressed(void);
+    void event_powerButtonReleased(void);
+    void event_longpresscheck(void);
+};
+
+#endif /* _MAX32630HSP_H_ */
+