USB Host Shield 2.0 with PS4 Bluetooth Dongle

Hey everyone!
I’m new to sparkfun and I am a senior in college. I’m struggling to figure out how to connect my PS4 controller with the bluetooth dongle on my USB hostshield 2.0. I soldered in the pins for the shield and I uploaded a test code. I found an example code online called QC, which basically debugged what was going on with my UBS HS 2.0. I get the following message in the Serial Monitor:

Circuits At Home 2011

USB Host Shield Quality Control Routine

Reading REVISION register… Die revision 03

SPI long test. Transfers 1MB of data. Each dot is 64K

Test failed. Value written: 01 read: 00

Unrecoverable error - test halted!!

0x55 pattern is transmitted via SPI

Press RESET to restart test

Unfortunately it doesn’t make any sense to me because I’m so new to the topic. Can anyone help me figure out how to get this connected?
Here is the example code I used:

/* USB Host Shield 2.0 board quality control routine */
/* To see the output set your terminal speed to 115200 */
/* for GPIO test to pass you need to connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, etc. */
/* otherwise press any key after getting GPIO error to complete the test */
/**/
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library
#endif
#include <SPI.h> // Hack to use the SPI library

/* variables */
uint8_t rcode;
uint8_t usbstate;
uint8_t laststate;
//uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)];
USB_DEVICE_DESCRIPTOR buf;

/* objects */
USB Usb;
//USBHub hub(&Usb);

void setup() {
        laststate = 0;
        Serial.begin(115200);
#if !defined(__MIPSEL__)
        while(!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
        E_Notify(PSTR("\r\nCircuits At Home 2011"), 0x80);
        E_Notify(PSTR("\r\nUSB Host Shield Quality Control Routine"), 0x80);
        /* SPI quick test - check revision register */
        E_Notify(PSTR("\r\nReading REVISION register... Die revision "), 0x80);
        Usb.Init(); // Initializes SPI, we don't care about the return value here
        {
                uint8_t tmpbyte = Usb.regRd(rREVISION);
                switch(tmpbyte) {
                        case( 0x01): //rev.01
                                E_Notify(PSTR("01"), 0x80);
                                break;
                        case( 0x12): //rev.02
                                E_Notify(PSTR("02"), 0x80);
                                break;
                        case( 0x13): //rev.03
                                E_Notify(PSTR("03"), 0x80);
                                break;
                        default:
                                E_Notify(PSTR("invalid. Value returned: "), 0x80);
                                print_hex(tmpbyte, 8);
                                halt55();
                                break;
                }//switch( tmpbyte...
        }//check revision register
        /* SPI long test */
        {
                E_Notify(PSTR("\r\nSPI long test. Transfers 1MB of data. Each dot is 64K"), 0x80);
                uint8_t sample_wr = 0;
                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);
                                if(sample_rd != sample_wr) {
                                        E_Notify(PSTR("\r\nTest failed.  "), 0x80);
                                        E_Notify(PSTR("Value written: "), 0x80);
                                        print_hex(sample_wr, 8);
                                        E_Notify(PSTR(" read: "), 0x80);
                                        print_hex(sample_rd, 8);
                                        halt55();
                                }//if( sample_rd != sample_wr..
                                sample_wr++;
                        }//for( uint16_t j...
                        E_Notify(PSTR("."), 0x80);
                }//for( uint8_t i...
                Usb.regWr(rGPINPOL, gpinpol_copy);
                E_Notify(PSTR(" SPI long test passed"), 0x80);
        }//SPI long test
        /* GPIO test */
        /* in order to simplify board layout, GPIN pins on text fixture are connected to GPOUT */
        /* in reverse order, i.e, GPIN0 is connected to GPOUT7, GPIN1 to GPOUT6, etc. */
        {
                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 */
                        tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
                        if(sample_gpio != tmpbyte) {
                                E_Notify(PSTR("\r\nTest failed. Value written: "), 0x80);
                                print_hex(sample_gpio, 8);
                                E_Notify(PSTR(" Value read: "), 0x80);
                                print_hex(tmpbyte, 8);
                                E_Notify(PSTR(" "), 0x80);
                                press_any_key();
                                break;
                        }//if( sample_gpio != tmpbyte...
                }//for( uint8_t sample_gpio...
                E_Notify(PSTR("\r\nGPIO test passed."), 0x80);
        }//GPIO test
        /* PLL test. Stops/starts MAX3421E oscillator several times */
        {
                E_Notify(PSTR("\r\nPLL test. 100 chip resets will be performed"), 0x80);
                /* check current state of the oscillator */
                if(!(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ)) { //wrong state - should be on
                        E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80);
                        press_any_key();
                }
                /* 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
                        if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { //wrong state - should be off
                                E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80);
                                halt55();
                        }
                        Usb.regWr(rUSBCTL, 0x00); //release from reset
                        uint16_t j = 0;
                        for(j = 1; j < 65535; j++) { //tracking off to on time
                                if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) {
                                        E_Notify(PSTR(" Time to stabilize - "), 0x80);
                                        Serial.print(j, DEC);
                                        E_Notify(PSTR(" cycles\r\n"), 0x80);
                                        break;
                                }
                        }//for( uint16_t j = 0; j < 65535; j++
                        if(j == 0) {
                                E_Notify(PSTR("PLL failed to stabilize"), 0x80);
                                press_any_key();
                        }
                }//for( uint8_t i = 0; i < 255; i++

        }//PLL test
        /* initializing USB stack */
        if(Usb.Init() == -1) {
                E_Notify(PSTR("\r\nOSCOKIRQ failed to assert"), 0x80);
                halt55();
        }
        E_Notify(PSTR("\r\nChecking USB device communication.\r\n"), 0x80);
}

void loop() {
        delay(200);
        Usb.Task();
        usbstate = Usb.getUsbTaskState();
        if(usbstate != laststate) {
                laststate = usbstate;
                /**/
                switch(usbstate) {
                        case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE):
                                E_Notify(PSTR("\r\nWaiting for device..."), 0x80);
                                break;
                        case( USB_ATTACHED_SUBSTATE_RESET_DEVICE):
                                E_Notify(PSTR("\r\nDevice connected. Resetting..."), 0x80);
                                break;
                        case( USB_ATTACHED_SUBSTATE_WAIT_SOF):
                                E_Notify(PSTR("\r\nReset complete. Waiting for the first SOF..."), 0x80);
                                break;
                        case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE):
                                E_Notify(PSTR("\r\nSOF generation started. Enumerating device..."), 0x80);
                                break;
                        case( USB_STATE_ADDRESSING):
                                E_Notify(PSTR("\r\nSetting device address..."), 0x80);
                                break;
                        case( USB_STATE_RUNNING):
                                E_Notify(PSTR("\r\nGetting device descriptor"), 0x80);
                                rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf);

                                if(rcode) {
                                        E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80);
                                        print_hex(rcode, 8);
                                } else {
                                        /**/
                                        E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80);
                                        print_hex(buf.bLength, 8);
                                        E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80);
                                        print_hex(buf.bDescriptorType, 8);
                                        E_Notify(PSTR("\r\nUSB version:\t\t"), 0x80);
                                        print_hex(buf.bcdUSB, 16);
                                        E_Notify(PSTR("\r\nDevice class:\t\t"), 0x80);
                                        print_hex(buf.bDeviceClass, 8);
                                        E_Notify(PSTR("\r\nDevice Subclass:\t"), 0x80);
                                        print_hex(buf.bDeviceSubClass, 8);
                                        E_Notify(PSTR("\r\nDevice Protocol:\t"), 0x80);
                                        print_hex(buf.bDeviceProtocol, 8);
                                        E_Notify(PSTR("\r\nMax.packet size:\t"), 0x80);
                                        print_hex(buf.bMaxPacketSize0, 8);
                                        E_Notify(PSTR("\r\nVendor  ID:\t\t"), 0x80);
                                        print_hex(buf.idVendor, 16);
                                        E_Notify(PSTR("\r\nProduct ID:\t\t"), 0x80);
                                        print_hex(buf.idProduct, 16);
                                        E_Notify(PSTR("\r\nRevision ID:\t\t"), 0x80);
                                        print_hex(buf.bcdDevice, 16);
                                        E_Notify(PSTR("\r\nMfg.string index:\t"), 0x80);
                                        print_hex(buf.iManufacturer, 8);
                                        E_Notify(PSTR("\r\nProd.string index:\t"), 0x80);
                                        print_hex(buf.iProduct, 8);
                                        E_Notify(PSTR("\r\nSerial number index:\t"), 0x80);
                                        print_hex(buf.iSerialNumber, 8);
                                        E_Notify(PSTR("\r\nNumber of conf.:\t"), 0x80);
                                        print_hex(buf.bNumConfigurations, 8);
                                        /**/
                                        E_Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test"), 0x80);
                                        while(1) {
#ifdef ESP8266
                                                yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
                                        }
                                }
                                break;
                        case( USB_STATE_ERROR):
                                E_Notify(PSTR("\r\nUSB state machine reached error state"), 0x80);
                                break;

                        default:
                                break;
                }//switch( usbstate...
        }
}//loop()...

/* constantly transmits 0x55 via SPI to aid probing */
void halt55() {

        E_Notify(PSTR("\r\nUnrecoverable error - test halted!!"), 0x80);
        E_Notify(PSTR("\r\n0x55 pattern is transmitted via SPI"), 0x80);
        E_Notify(PSTR("\r\nPress RESET to restart test"), 0x80);

        while(1) {
                Usb.regWr(0x55, 0x55);
#ifdef ESP8266
                yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
        }
}

/* prints hex numbers with leading zeroes */
void print_hex(int v, int num_places) {
        int mask = 0, n, num_nibbles, digit;

        for(n = 1; n <= num_places; n++) {
                mask = (mask << 1) | 0x0001;
        }
        v = v & mask; // truncate v to specified number of places

        num_nibbles = num_places / 4;
        if((num_places % 4) != 0) {
                ++num_nibbles;
        }
        do {
                digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;
                Serial.print(digit, HEX);
        } while(--num_nibbles);
}

/* 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
#ifdef ESP8266
                yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
        }
        Serial.read(); //empty input buffer
        return;
}

Thanks for reaching out to us on this.

The test shows intermittent spi connection…try switching to a better power source, or from battery to a regulated power supply, etc.

It is likely either bad contact being made, or (less likely) a bad chip

Several posts around the internet mention connecting a jumper wire from d7 to RST, please research and verify whether this may aid your case or not.

Hope this helps, and happy sparking!