diff --git a/.travis.yml b/.travis.yml index 1c7ecaef..c64877dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ env: - PLATFORMIO_CI_SRC=examples/Bluetooth/SPPMulti - PLATFORMIO_CI_SRC=examples/Bluetooth/Wii - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiBalanceBoard - - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiIRCamera + - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiIRCamera PLATFORMIO_BUILD_FLAGS="-DWIICAMERA" - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiMulti - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiUProController - PLATFORMIO_CI_SRC=examples/board_qc @@ -63,7 +63,7 @@ env: install: - pip install -U platformio - - export PLATFORMIO_BUILD_FLAGS="-DDEBUG_USB_HOST -DWIICAMERA -Wall -Werror" + - export PLATFORMIO_BUILD_FLAGS="$PLATFORMIO_BUILD_FLAGS -DDEBUG_USB_HOST -Wall -Werror" # # Libraries from PlatformIO Library Registry: @@ -74,4 +74,5 @@ install: - platformio lib install 62 416 417 script: - - platformio ci --board=uno --board=due --board=genuino101 --board=teensy30 --board=teensy31 --board=teensy35 --board=teensy36 --board=teensylc --lib="." + - platformio ci --lib="." --board=uno --board=due --board=genuino101 --board=teensy30 --board=teensy31 --board=teensy35 --board=teensy36 --board=teensylc + - platformio ci --lib="." --board=esp12e --board=nodemcu --project-option="build_flags=-Wno-unused-function" # Workaround https://github.com/esp8266/Arduino/pull/2881 diff --git a/README.md b/README.md index b26b9503..9a42558e 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,11 @@ Currently the following boards are supported by the library: * Please see: . * STM32F4 * Currently the [NUCLEO-F446RE](http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF262063) is supported featuring the STM32F446. Take a look at the following example code: . +* ESP8266 is supported using the [ESP8266 Arduino core](https://github.com/esp8266/Arduino) + * Note it uses pin 15 and 5 for SS and INT respectively + * Also please be aware that: + * GPIO16 is **NOT** usable, as it will be used for some other purposes. For example, reset the SoC itself from sleep mode. + * GPIO6 to 11 is also **NOT** usable, as they are used to connect SPI flash chip and it is used for storing the executable binary content. The following boards need to be activated manually in [settings.h](settings.h): @@ -317,11 +322,11 @@ HID devices are also supported by the library. However these require you to writ ### [MIDI Library](usbh_midi.cpp) -The library support MIDI devices. +The library support MIDI devices. You can convert USB MIDI keyboard to legacy serial MIDI. -* [USB_MIDI_converter.ino](examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino) -* [USB_MIDI_converter_multi.ino](examples/USBH_MIDI/USB_MIDI_converter_multi/USB_MIDI_converter_multi.ino) +* [USB_MIDI_converter.ino](examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino) +* [USB_MIDI_converter_multi.ino](examples/USBH_MIDI/USB_MIDI_converter_multi/USB_MIDI_converter_multi.ino) For information see the following page: . diff --git a/UsbCore.h b/UsbCore.h index 8a22aa13..f78300ca 100644 --- a/UsbCore.h +++ b/UsbCore.h @@ -39,6 +39,8 @@ typedef MAX3421e MAX3421E; // Arduino Mega ADK typedef MAX3421e MAX3421E; // Balanduino #elif defined(__ARDUINO_X86__) && PLATFORM_ID == 0x06 typedef MAX3421e MAX3421E; // The Intel Galileo supports much faster read and write speed at pin 2 and 3 +#elif defined(ESP8266) +typedef MAX3421e MAX3421E; // ESP8266 boards #else typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.x #endif diff --git a/avrpins.h b/avrpins.h index ce50d16a..8f329fa4 100644 --- a/avrpins.h +++ b/avrpins.h @@ -1326,6 +1326,47 @@ MAKE_PIN(P13, 13); // #undef MAKE_PIN +#elif defined(ESP8266) + +#define pgm_read_pointer(p) pgm_read_ptr(p) + +#define MAKE_PIN(className, pin) \ +class className { \ +public: \ + static void Set() { \ + digitalWrite(pin, HIGH);\ + } \ + static void Clear() { \ + digitalWrite(pin, LOW); \ + } \ + static void SetDirRead() { \ + pinMode(pin, INPUT); \ + } \ + static void SetDirWrite() { \ + pinMode(pin, OUTPUT); \ + } \ + static uint8_t IsSet() { \ + return digitalRead(pin); \ + } \ +}; + +// Pinout for ESP-12 module +// 0 .. 16 - Digital pins +// GPIO 6 to 11 and 16 are not usable in this library. + +MAKE_PIN(P0, 0); +MAKE_PIN(P1, 1); // TX0 +MAKE_PIN(P2, 2); // TX1 +MAKE_PIN(P3, 3); // RX0 +MAKE_PIN(P4, 4); // SDA +MAKE_PIN(P5, 5); // SCL +MAKE_PIN(P12, 12); // MISO +MAKE_PIN(P13, 13); // MOSI +MAKE_PIN(P14, 14); // SCK +MAKE_PIN(P15, 15); // SS + +#undef MAKE_PIN + #else #error "Please define board in avrpins.h" diff --git a/examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino b/examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino index d761076b..34955914 100644 --- a/examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino +++ b/examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino @@ -67,7 +67,8 @@ void MIDI_poll() pid = Midi.pid; } if (Midi.RecvData( &rcvd, bufMidi) == 0 ) { - sprintf(buf, "%08lX: ", (uint32_t)millis()); + uint32_t time = (uint32_t)millis(); + sprintf(buf, "%04X%04X: ", (uint16_t)(time >> 16), (uint16_t)(time & 0xFFFF)); // Split variable to prevent warnings on the ESP8266 platform Serial.print(buf); Serial.print(rcvd); Serial.print(':'); diff --git a/examples/USB_desc/USB_desc.ino b/examples/USB_desc/USB_desc.ino index cda8505c..8341c503 100644 --- a/examples/USB_desc/USB_desc.ino +++ b/examples/USB_desc/USB_desc.ino @@ -104,7 +104,11 @@ void loop() Usb.ForEachUsbDevice(&PrintAllDescriptors); Usb.ForEachUsbDevice(&PrintAllAddresses); - while ( 1 ); //stop + while ( 1 ) { // stop +#ifdef ESP8266 + yield(); // needed in order to reset the watchdog timer on the ESP8266 +#endif + } } } diff --git a/examples/board_qc/board_qc.ino b/examples/board_qc/board_qc.ino index 573c3ce0..8ff41dda 100644 --- a/examples/board_qc/board_qc.ino +++ b/examples/board_qc/board_qc.ino @@ -60,6 +60,9 @@ void setup() { uint8_t sample_rd = 0; uint8_t gpinpol_copy = Usb.regRd(rGPINPOL); for(uint8_t i = 0; i < 16; i++) { +#ifdef ESP8266 + yield(); // needed in order to reset the watchdog timer on the ESP8266 +#endif for(uint16_t j = 0; j < 65535; j++) { Usb.regWr(rGPINPOL, sample_wr); sample_rd = Usb.regRd(rGPINPOL); @@ -85,6 +88,9 @@ void setup() { uint8_t tmpbyte; E_Notify(PSTR("\r\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on"), 0x80); for(uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++) { +#ifdef ESP8266 + yield(); // needed in order to reset the watchdog timer on the ESP8266 +#endif Usb.gpioWr(sample_gpio); tmpbyte = Usb.gpioRd(); /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */ @@ -112,6 +118,9 @@ void setup() { /* Restart oscillator */ E_Notify(PSTR("\r\nResetting oscillator\r\n"), 0x80); for(uint16_t i = 0; i < 100; i++) { +#ifdef ESP8266 + yield(); // needed in order to reset the watchdog timer on the ESP8266 +#endif E_Notify(PSTR("\rReset number "), 0x80); Serial.print(i, DEC); Usb.regWr(rUSBCTL, bmCHIPRES); //reset @@ -206,7 +215,11 @@ void loop() { print_hex(buf.bNumConfigurations, 8); /**/ E_Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test"), 0x80); - while(1); + while(1) { +#ifdef ESP8266 + yield(); // needed in order to reset the watchdog timer on the ESP8266 +#endif + } } break; case( USB_STATE_ERROR): @@ -228,6 +241,9 @@ void halt55() { while(1) { Usb.regWr(0x55, 0x55); +#ifdef ESP8266 + yield(); // needed in order to reset the watchdog timer on the ESP8266 +#endif } } @@ -253,7 +269,11 @@ void print_hex(int v, int num_places) { /* prints "Press any key" and returns when key is pressed */ void press_any_key() { E_Notify(PSTR("\r\nPress any key to continue..."), 0x80); - while(Serial.available() <= 0); //wait for input + while(Serial.available() <= 0) { // wait for input +#ifdef ESP8266 + yield(); // needed in order to reset the watchdog timer on the ESP8266 +#endif + } Serial.read(); //empty input buffer return; } diff --git a/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino b/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino index 8b30622d..af13b6bc 100644 --- a/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino +++ b/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino @@ -150,12 +150,12 @@ void printFloat(double number, int16_t digits) void gpsdump(TinyGPS &gps) { - int32_t lat, lon; + long lat, lon; float flat, flon; - uint32_t age, date, time, chars; - int16_t year; + unsigned long age, date, time, chars; + int year; uint8_t month, day, hour, minute, second, hundredths; - uint16_t sentences, failed; + unsigned short sentences, failed; gps.get_position(&lat, &lon, &age); Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat); Serial.print(", "); Serial.print(lon); @@ -175,7 +175,7 @@ void gpsdump(TinyGPS &gps) feedgps(); - gps.crack_datetime((int*)&year, &month, &day, &hour, &minute, &second, &hundredths, &age); + gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age); Serial.print("Date: "); Serial.print(static_cast(month)); Serial.print("/"); Serial.print(static_cast(day)); Serial.print("/"); Serial.print(year); Serial.print(" Time: "); Serial.print(static_cast(hour)); Serial.print(":"); Serial.print(static_cast(minute)); Serial.print(":"); Serial.print(static_cast(second)); Serial.print("."); Serial.print(static_cast(hundredths)); Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); @@ -189,7 +189,7 @@ void gpsdump(TinyGPS &gps) feedgps(); - gps.stats(&chars, (unsigned short*)&sentences, (unsigned short*)&failed); + gps.stats(&chars, &sentences, &failed); Serial.print("Stats: characters: "); Serial.print(chars); Serial.print(" sentences: "); Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed); } diff --git a/library.json b/library.json index d7973969..f31f5836 100644 --- a/library.json +++ b/library.json @@ -50,6 +50,7 @@ "teensy", "atmelsam", "nordicnrf51", - "ststm32" + "ststm32", + "espressif8266" ] } diff --git a/settings.h b/settings.h index 2890cba8..804725a4 100644 --- a/settings.h +++ b/settings.h @@ -177,4 +177,20 @@ extern SPI_HandleTypeDef SPI_Handle; // Needed to be declared in your main.cpp #define MFK_CASTUINT8T #endif +// Workaround issue: https://github.com/esp8266/Arduino/issues/2078 +#ifdef ESP8266 +#undef PROGMEM +#define PROGMEM +#undef PSTR +#define PSTR(s) (s) +#undef pgm_read_byte +#define pgm_read_byte(addr) (*reinterpret_cast(addr)) +#undef pgm_read_word +#define pgm_read_word(addr) (*reinterpret_cast(addr)) +#endif + +#ifdef ARDUINO_ESP8266_WIFIO +#error "This board is currently not supported" +#endif + #endif /* SETTINGS_H */ diff --git a/usbhost.h b/usbhost.h index 24a6cfee..8f97121e 100644 --- a/usbhost.h +++ b/usbhost.h @@ -39,7 +39,7 @@ public: SPI_SS::SetDirWrite(); SPI_SS::Set(); } -#elif SPI_HAS_TRANSACTION +#elif defined(SPI_HAS_TRANSACTION) static void init() { SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction() SPI_SS::SetDirWrite(); @@ -85,7 +85,19 @@ public: }; /* SPI pin definitions. see avrpins.h */ -#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +#if defined(PIN_SPI_SCK) && defined(PIN_SPI_MOSI) && defined(PIN_SPI_MISO) && defined(PIN_SPI_SS) +// Use pin defines: https://github.com/arduino/Arduino/pull/4814 +// Based on: https://www.mikeash.com/pyblog/friday-qa-2015-03-20-preprocessor-abuse-and-optional-parentheses.html +#define NOTHING_EXTRACT +#define EXTRACT(...) EXTRACT __VA_ARGS__ +#define PASTE(x, ...) x ## __VA_ARGS__ +#define EVALUATING_PASTE(x, ...) PASTE(x, __VA_ARGS__) +#define UNPAREN(x) EVALUATING_PASTE(NOTHING_, EXTRACT x) +#define APPEND_PIN(pin) P ## pin // Appends the pin to 'P', e.g. 1 becomes P1 +#define MAKE_PIN(x) EVALUATING_PASTE(APPEND_, PIN(UNPAREN(x))) +typedef SPi< MAKE_PIN(PIN_SPI_SCK), MAKE_PIN(PIN_SPI_MOSI), MAKE_PIN(PIN_SPI_MISO), MAKE_PIN(PIN_SPI_SS) > spi; +#undef MAKE_PIN +#elif defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; @@ -97,6 +109,8 @@ typedef SPi< P13, P11, P12, P10 > spi; typedef SPi< P76, P75, P74, P10 > spi; #elif defined(RBL_NRF51822) typedef SPi< P16, P18, P17, P10 > spi; +#elif defined(ESP8266) +typedef SPi< P14, P13, P12, P15 > spi; #else #error "No SPI entry in usbhost.h" #endif @@ -152,7 +166,7 @@ MAX3421e< SPI_SS, INTR >::MAX3421e() { template< typename SPI_SS, typename INTR > void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 #endif SPI_SS::Clear(); @@ -162,7 +176,7 @@ void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { c[0] = reg | 0x02; c[1] = data; spi4teensy3::send(c, 2); -#elif SPI_HAS_TRANSACTION +#elif defined(SPI_HAS_TRANSACTION) && !defined(ESP8266) uint8_t c[2]; c[0] = reg | 0x02; c[1] = data; @@ -172,7 +186,7 @@ void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { c[0] = reg | 0x02; c[1] = data; HAL_SPI_Transmit(&SPI_Handle, c, 2, HAL_MAX_DELAY); -#elif !defined(SPDR) +#elif !defined(SPDR) // ESP8266 SPI.transfer(reg | 0x02); SPI.transfer(data); #else @@ -183,7 +197,7 @@ void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { #endif SPI_SS::Set(); -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif XMEM_RELEASE_SPI(); @@ -195,7 +209,7 @@ void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { template< typename SPI_SS, typename INTR > uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 #endif SPI_SS::Clear(); @@ -204,7 +218,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* spi4teensy3::send(reg | 0x02); spi4teensy3::send(data_p, nbytes); data_p += nbytes; -#elif SPI_HAS_TRANSACTION +#elif defined(SPI_HAS_TRANSACTION) && !defined(ESP8266) SPI.transfer(reg | 0x02); SPI.transfer(data_p, nbytes); data_p += nbytes; @@ -217,7 +231,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* HAL_SPI_Transmit(&SPI_Handle, &data, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&SPI_Handle, data_p, nbytes, HAL_MAX_DELAY); data_p += nbytes; -#elif !defined(SPDR) +#elif !defined(SPDR) // ESP8266 SPI.transfer(reg | 0x02); while(nbytes) { SPI.transfer(*data_p); @@ -236,7 +250,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* #endif SPI_SS::Set(); -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif XMEM_RELEASE_SPI(); @@ -258,7 +272,7 @@ void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) { template< typename SPI_SS, typename INTR > uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 #endif SPI_SS::Clear(); @@ -272,7 +286,7 @@ uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { uint8_t rv = 0; HAL_SPI_Receive(&SPI_Handle, &rv, 1, HAL_MAX_DELAY); SPI_SS::Set(); -#elif !defined(SPDR) || SPI_HAS_TRANSACTION +#elif !defined(SPDR) || defined(SPI_HAS_TRANSACTION) SPI.transfer(reg); uint8_t rv = SPI.transfer(0); // Send empty byte SPI_SS::Set(); @@ -285,7 +299,7 @@ uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { uint8_t rv = SPDR; #endif -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif XMEM_RELEASE_SPI(); @@ -297,7 +311,7 @@ uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { template< typename SPI_SS, typename INTR > uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 #endif SPI_SS::Clear(); @@ -306,7 +320,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* spi4teensy3::send(reg); spi4teensy3::receive(data_p, nbytes); data_p += nbytes; -#elif SPI_HAS_TRANSACTION +#elif defined(SPI_HAS_TRANSACTION) && !defined(ESP8266) SPI.transfer(reg); memset(data_p, 0, nbytes); // Make sure we send out empty bytes SPI.transfer(data_p, nbytes); @@ -320,7 +334,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* memset(data_p, 0, nbytes); // Make sure we send out empty bytes HAL_SPI_Receive(&SPI_Handle, data_p, nbytes, HAL_MAX_DELAY); data_p += nbytes; -#elif !defined(SPDR) +#elif !defined(SPDR) // ESP8266 SPI.transfer(reg); while(nbytes) { *data_p++ = SPI.transfer(0); @@ -348,7 +362,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* #endif SPI_SS::Set(); -#if SPI_HAS_TRANSACTION +#if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif XMEM_RELEASE_SPI();