# Maple Reference Documentation: USB

- Function Reference
- Code Examples
- Recommended Reading

### Changes and Caveats

The SerialUSB functionality was modified for the 0.0.6 IDE release. It now includes a 50 millisecond timeout for writes and does not try to detect if the USB host is "really" connected or just enumerated and initialized. This means that if you have a number of SerialUSB writes or prints in your code and you are not monitoring on a computer your program will run much, much slower than if it is being monitored or totally disconnected (battery).
You can avoid this behavior by deciphering the port status using the DTR and RTS line status; the behavior of these control lines is platform dependent and we no longer interpret them by default.

The Maple stm32 microprocessor includes a dedicated USB peripheral which can be configured to act as a general USB slave device with transfer rates up to 12mbps (it unfortunately can not be configured as a host or on-the-go device). By default the peripheral is configured for two uses: first to receive sketch/program uploads from the IDE, and second to emulate a regular serial port for use as a terminal (text read/write).

The emulated terminal is relatively slow and inefficient; it is best for transferring data at regular serial speeds (kilobaud). Users requiring faster data transfer should consider implementing a different communications protocol; the Maple could be reprogrammed to appear as a mass storage device (thumb drive), human interface device (mouse or keyboard), microphone, or any other USB device.

The SerialUSB channel is also used as part of the auto-reset feature of the IDE to program the board: a magic sequence of control line toggles and transmitted data causes the Maple to reset itself and enter bootloader mode. As an unfortunate consequence, the auto-reset will not work if the IDE can not access the serial port, either do to a conflict with another program (serial monitor) or because the interface has been disabled from the Maple side (`SerialUSB.end()`).

## Function Reference

`SerialUSB.print(...)`
`SerialUSB.println(...)`
`SerialUSB.write(bytes)`
  Writes data into the port buffer to be transmitted as soon as possible. Accepts strings (character arrays). If a raw integer is passed the corresponding ASCII character will be transmitted; to print out a number in human readable form add a second parameter with the base system. Eg, to print out the decimal number '1234' use `print(1234,DEC)`; to print out the binary number '1001' use `print(9,BIN)`.
  `write()` is a lower-level function that writes bytes directly into the buffer. `print()` often calls this function dozens of times to write out a single formatted number; usercode can optimize raw data speed by calling this function with 64-bytes chunks instead.
`SerialUSB.available()`
`SerialUSB.read()`
  `read()` will return any data that has been received over the port and `available()` will tell if any such data actually exists, and if so how many bytes. If there is no data `read()` will block/fail, so the usual program structure is to poll with `available()` and only `read()` if there's something ready.
`uint8 SerialUSB.pending()`
  Returns the number of bytes waiting in the transmit buffer. Usercode can use this to prevent any blocking/waiting when using the direct `write()` functions, or to check if data was actually requested/received by the host.
`uint8 getRTS()`
  Returns the state (1 or 0) of the virtual RTS ("ready to send") line. This can be used to guess if the USB host is actively waiting for data (aka a serial monitor program is running) or just "configured" (the virtual serial port is configured but no program is reading data).
`uint8 getDTR()`
  Returns the state (1 or 0) of the virtual DTR ("data terminal ready") line. This can be used to guess if the USB host is actively waiting for data (aka a serial monitor program is running) or just "configured" (the virtual serial port is configured but no program is reading data).
`uint8 isConnected()`
  Returns 1 if the USB host is connected and the virtual serial interface is initialized (though not necessarily active), otherwise 0.
`SerialUSB.end()`
`SerialUSB.begin()`
  The USB peripheral is enabled by default so that the auto-reset feature will work, but it can be disabled/restarted at any time with the `end()` and `begin()` functions. The `end()` is a relatively hard shutdown, similar to unplugging the board; this may crash or confuse any programs running host-side. It's probably wise to wait a few seconds between an `end()`/`begin()` or a `begin()`/`print()` to let the computer reconfigure.

## Code Examples

### Safe Print

This function should run smoothly and not block; the LED should blink at roughly the same speed whether being monitored, running from battery, or connected but not monitored. You may need to experiment with the DTR/RTS logic for your platform and device configuration.

    #define LED_PIN 13

    void setup() {
        /* Set up the LED to blink  */
        pinMode(LED_PIN, OUTPUT);
    }

    void loop() {
        // LED will stay off if we are disconnected;
        // will blink quickly if USB is unplugged (battery etc)
        if(SerialUSB.isConnected()) {
            digitalWrite(LED_PIN, 1);
        }
        delay(100);

        // If this logic fails to detect if bytes are going to
        // be read by the USB host, then the println() will fully
        // many times, causing a very slow LED blink.
        // If the characters are printed and read, the blink will
        // only slow a small amount when "really" connected, and fast
        // when the virtual port is only configured.
        if(SerialUSB.isConnected() && (SerialUSB.getDTR() || SerialUSB.getRTS())) {
            for(int i=0; i<10; i++) {
               SerialUSB.println(123456,BIN);
            }
        }
        digitalWrite(LED_PIN, 0);
        delay(100);
    }

## Recommended Reading

- USB in a NutShell overview from Beyond Logic
- Wikipedia article on Universal Serial Bus (USB)
- Linux Kernel documentation for USB ACM and USB Serial
- STMicro documentation for STM32F103RB microcontroller:
  - All
  - Datasheet (pdf)
  - Reference Manual (pdf)

### About this Document

A more recent version of this document may be available from the LeafLabs website. Our documentation is versioned on github; you can track changes to the master branch at this link.

This documentation is released under a Creative Commons Attribution-Share Alike 3.0 license.

Translations are welcomed; give us a ping to make sure we aren't in the process of revising or editing first.