Integration

Bliss-Box API (Application programming interface)

 

The 4-play and the Gamer-Pro products have both a software and hardware Interface that can be used to communicate with the controller at both high and low levels. USB is a great solution but it does have limitations. Also the HID USB driver is even more limited in the sense of features vs a driver based USB implementation. Bliss-Box products use HID for convenience as dealing with drivers was never any fun but also has an API for advanced features.  The mechanism for the API is in two parts (Software and hardware).

 

The Software interface uses USB control transfers. This does still rely on the USB HID driver but allows data to be transferred that HID does not allow. For example but not limited to; Pressure buttons, LCD and memory pack data exchange, faster poll rates, and direct native talk to the controller. Bliss-Box has developed a software application that shows how this works. The application is an open source application that demos most all the API has to offer.  The source can be found here. And the application can be downloaded  here.

For the documented API see the following link.

 

( Only available on 3.0) – If the 3.0 download is not available please contact us. When the Hardware API is better documented, the link will be available.

The hardware interface uses the already available USB lines. To invoke the API you simply bring both d- and d+ high with at least 1k pull ups.  This condition will not cause any abnormal condition to existing USB hardware so it’s safe to use in both cases. When the Gamer-Pro or 4-Play detects the condition, it will go in to bridge mode. So this can be asserted via software or hardware in your connecting device.

PORTB |= 0x60;//bring both high to tell slave we are attached.

Once the Gamer-Pro or 4-Play sees the condition it goes in to bridge  mode and you can now send and receive data. More information will be available once the API is finalized.

Timing Chart

 

 

Command function notes
0x01 GET_CONTROLLER_STATUS
0x00  CONTROLLER_POLL
0x02 GET_PRESSURE_STATUS
0x11 RUBMLE_CONST_START_FROM_PARMS must set parms first
0x12 RUBMLE_CONST_END
0x14 RUBMLE_SINE_START_FROM_PARMS must set parms first
0x18 RUBMLE_SINE_END
0x1A RUBMLE_CONST_JOLT
0x1B RUBMLE_SINE_JOLT

 

errors type notes
0x00 ERROR_NODATA
0x01 NO_ERROR
0x03 ERROR_AP_NO_REPORT

 

Send / Set function parms (parms follow command)
0x1C BRIDGE_RUBMLE_PARMS (rumbleLevel, rumbleLoop

 

Here are some examples on a ATMEGA with a 16Mhz clock.

#define MAX_TIME 1500
#define MAX_TIME2 15000
#define WHILE_LINE_IS_LO while (count <MAX_TIME2 &&(PINB &0x60)==0x00){count++;};
#define WHILE_DATA_IS_LO while (count <MAX_TIME &&(PINB &0x60)==0x00){count++;};
#define WHILE_DATA_IS_HI while (count <MAX_TIME &&(PINB &0x60)==0x60){count++;};

#define BRIDGE_GET_CONTROLLER_STATUS 01
#define BRIDGE_CONTROLLER_POLL 0
#define BRDIGE_GET_PRESSURE_STATUS 02

#define BRIDGE_ERROR_NODATA 0
#define BRIDGE_NO_ERROR 1
#define BRIDGE_ERROR_AP_NO_REPORT 3

void Write(unsigned char data)
{
    int count=0;
    WHILE_LINE_IS_LO//this will wait up to near 8 ms
    PORTD = 0; //debug
    DDRB |= 0x60;//pb6,5 out
    PORTB &= ~0x60;//start talk both low
    for (char bit=0;bit<8;bit++) 
    }
        PORTB |= 0x40;//set bit hi
        if (data & 0x01) PORTB &= ~0x40; _delay_us(2); data >>=1;
    }
    PORTB |= 0x60;//end talk. both hi.
    DDRB &= ~0x60;//pb6,5 in
    _delay_us(25);//let settle
    PORTD = 0x40; //debug
}

char Read( unsigned char size)
{
    //return 0 no data received.
    //return ff for no controller attached
    //return 1 BB good
    //return 3 BB do not report or AP
    int count=0;
    for (char b = 0; b < size; b++)
    {
        BB_ReadBuffer[b]=0;
        WHILE_DATA_IS_HI//find end of reset state
        for (char i = 0; i < 8; i++)
        {
            _delay_us(4.4); //jump to bit BB_ReadBuffer[b] >>=1;
            asm("nop\nnop\n");//timing help - remove for debug (PORTD = 0; )
            if (PINB & 0x40) BB_ReadBuffer[b] |= 0x80; else { _delay_us(.35);}
            asm("nop\nnop\n");//timing help - remove for debug (PORTD = 0x40;)
        }
        _delay_us(1);
    }
    _delay_us(10);//best to pause out reads.
    return BB_ReadBuffer[0];
}

//example calls
bridgeInterface->write(BRIDGE_CONTROLLER_POLL);
bridgeInterface->write(BRDIGE_GET_PRESSURE_STATUS);
reply =bridgeInterface->read(13);
if (reply == BRIDGE_NO_ERROR)
{
    for (char i=1; i<13;i++) {pressureData[i-1]=BB_ReadBuffer[i];}
}

bridgeInterface->write(BRIDGE_GET_CONTROLLER_STATUS);
reply =bridgeInterface->read(13);
if (reply == BRIDGE_NO_ERROR) 
{
  //do stuff with payload. 
}