mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Commit for AMBX support
This commit is contained in:
parent
37c7c5155a
commit
09fe72e754
4 changed files with 505 additions and 0 deletions
253
AMBX.cpp
Normal file
253
AMBX.cpp
Normal file
|
@ -0,0 +1,253 @@
|
|||
/* Copyright (C) 2021 Aran Vink. All rights reserved.
|
||||
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
|
||||
Contact information
|
||||
-------------------
|
||||
|
||||
Aran Vink
|
||||
e-mail : aranvink@gmail.com
|
||||
*/
|
||||
|
||||
#include "AMBX.h"
|
||||
// To enable serial debugging see "settings.h"
|
||||
//#define EXTRADEBUG // Uncomment to get even more debugging data
|
||||
|
||||
AMBX::AMBX(USB *p) :
|
||||
pUsb(p), // pointer to USB class instance - mandatory
|
||||
bAddress(0) // device address - mandatory
|
||||
{
|
||||
for(uint8_t i = 0; i < AMBX_MAX_ENDPOINTS; i++) {
|
||||
epInfo[i].epAddr = 0;
|
||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||
epInfo[i].bmSndToggle = 0;
|
||||
epInfo[i].bmRcvToggle = 0;
|
||||
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
|
||||
}
|
||||
|
||||
if(pUsb) // register in USB subsystem
|
||||
pUsb->RegisterDeviceClass(this); //set devConfig[] entry
|
||||
}
|
||||
|
||||
uint8_t AMBX::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||
uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
|
||||
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
|
||||
uint8_t rcode;
|
||||
UsbDevice *p = NULL;
|
||||
EpInfo *oldep_ptr = NULL;
|
||||
uint16_t PID;
|
||||
uint16_t VID;
|
||||
|
||||
// get memory address of USB device address pool
|
||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||
#ifdef EXTRADEBUG
|
||||
Notify(PSTR("\r\nAMBX Init"), 0x80);
|
||||
#endif
|
||||
// check if address has already been assigned to an instance
|
||||
if(bAddress) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nAddress in use"), 0x80);
|
||||
#endif
|
||||
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
||||
}
|
||||
|
||||
// Get pointer to pseudo device with address 0 assigned
|
||||
p = addrPool.GetUsbDevicePtr(0);
|
||||
|
||||
if(!p) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nAddress not found"), 0x80);
|
||||
#endif
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
}
|
||||
|
||||
if(!p->epinfo) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nepinfo is null"), 0x80);
|
||||
#endif
|
||||
return USB_ERROR_EPINFO_IS_NULL;
|
||||
}
|
||||
|
||||
// Save old pointer to EP_RECORD of address 0
|
||||
oldep_ptr = p->epinfo;
|
||||
|
||||
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
|
||||
p->epinfo = epInfo;
|
||||
|
||||
p->lowspeed = lowspeed;
|
||||
|
||||
// Get device descriptor
|
||||
rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
|
||||
// Restore p->epinfo
|
||||
p->epinfo = oldep_ptr;
|
||||
|
||||
if(rcode)
|
||||
goto FailGetDevDescr;
|
||||
|
||||
VID = udd->idVendor;
|
||||
PID = udd->idProduct;
|
||||
|
||||
if(VID != AMBX_VID || (PID != AMBX_PID))
|
||||
goto FailUnknownDevice;
|
||||
|
||||
// Allocate new address according to device class
|
||||
bAddress = addrPool.AllocAddress(parent, false, port);
|
||||
|
||||
if(!bAddress)
|
||||
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
|
||||
|
||||
// Extract Max Packet Size from device descriptor
|
||||
epInfo[0].maxPktSize = udd->bMaxPacketSize0;
|
||||
|
||||
// Assign new address to the device
|
||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||
if(rcode) {
|
||||
p->lowspeed = false;
|
||||
addrPool.FreeAddress(bAddress);
|
||||
bAddress = 0;
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nsetAddr: "), 0x80);
|
||||
D_PrintHex<uint8_t > (rcode, 0x80);
|
||||
#endif
|
||||
return rcode;
|
||||
}
|
||||
#ifdef EXTRADEBUG
|
||||
Notify(PSTR("\r\nAddr: "), 0x80);
|
||||
D_PrintHex<uint8_t > (bAddress, 0x80);
|
||||
#endif
|
||||
|
||||
p->lowspeed = false;
|
||||
|
||||
//get pointer to assigned address record
|
||||
p = addrPool.GetUsbDevicePtr(bAddress);
|
||||
if(!p)
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
|
||||
p->lowspeed = lowspeed;
|
||||
|
||||
// Assign epInfo to epinfo pointer - only EP0 is known
|
||||
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
|
||||
if(rcode)
|
||||
goto FailSetDevTblEntry;
|
||||
|
||||
|
||||
/* The application will work in reduced host mode, so we can save program and data
|
||||
memory space. After verifying the PID and VID we will use known values for the
|
||||
configuration values for device, interface, endpoints for the AMBX Controller */
|
||||
|
||||
/* Initialize data structures for endpoints of device */
|
||||
epInfo[ AMBX_OUTPUT_PIPE ].epAddr = AMBX_ENDPOINT_OUT; // AMBX output endpoint
|
||||
epInfo[ AMBX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
|
||||
epInfo[ AMBX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
|
||||
epInfo[ AMBX_OUTPUT_PIPE ].maxPktSize = AMBX_EP_MAXPKTSIZE;
|
||||
epInfo[ AMBX_OUTPUT_PIPE ].bmSndToggle = 0;
|
||||
epInfo[ AMBX_OUTPUT_PIPE ].bmRcvToggle = 0;
|
||||
|
||||
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
|
||||
if(rcode)
|
||||
goto FailSetDevTblEntry;
|
||||
|
||||
delay(200); //Give time for address change
|
||||
|
||||
//For some reason this is need to make it work
|
||||
rcode = pUsb->setConf(bAddress, epInfo[ AMBX_CONTROL_PIPE ].epAddr, 1);
|
||||
if(rcode)
|
||||
goto FailSetConfDescr;
|
||||
|
||||
if(PID == AMBX_PID || PID) {
|
||||
AMBXConnected = true;
|
||||
}
|
||||
onInit();
|
||||
|
||||
Notify(PSTR("\r\n"), 0x80);
|
||||
return 0; // Successful configuration
|
||||
|
||||
/* Diagnostic messages */
|
||||
FailGetDevDescr:
|
||||
#ifdef DEBUG_USB_HOST
|
||||
NotifyFailGetDevDescr();
|
||||
goto Fail;
|
||||
#endif
|
||||
|
||||
FailSetDevTblEntry:
|
||||
#ifdef DEBUG_USB_HOST
|
||||
NotifyFailSetDevTblEntry();
|
||||
goto Fail;
|
||||
#endif
|
||||
|
||||
FailSetConfDescr:
|
||||
#ifdef DEBUG_USB_HOST
|
||||
NotifyFailSetConfDescr();
|
||||
#endif
|
||||
goto Fail;
|
||||
|
||||
FailUnknownDevice:
|
||||
#ifdef DEBUG_USB_HOST
|
||||
NotifyFailUnknownDevice(VID, PID);
|
||||
#endif
|
||||
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||
|
||||
Fail:
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nAMBX Init Failed, error code: "), 0x80);
|
||||
NotifyFail(rcode);
|
||||
#endif
|
||||
Release();
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/* Performs a cleanup after failed Init() attempt */
|
||||
uint8_t AMBX::Release() {
|
||||
AMBXConnected = false;
|
||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||
bAddress = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t AMBX::Poll() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AMBX::Light_Command(uint8_t *data, uint16_t nbytes) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nLight command "), 0x80);
|
||||
#endif
|
||||
pUsb->outTransfer(bAddress, epInfo[ AMBX_OUTPUT_PIPE ].epAddr, nbytes, data);
|
||||
//Do really short delay, I've noticed otherwise the controller will receive all command at once, and might not process all of them.
|
||||
delay(1);
|
||||
}
|
||||
|
||||
void AMBX::setLight(uint8_t ambx_light, uint8_t r, uint8_t g, uint8_t b) {
|
||||
writeBuf[0] = AMBX_PREFIX_COMMAND;
|
||||
writeBuf[1] = ambx_light;
|
||||
writeBuf[2] = AMBX_SET_COLOR_COMMAND;
|
||||
writeBuf[3] = r;
|
||||
writeBuf[4] = g;
|
||||
writeBuf[5] = b;
|
||||
Light_Command(writeBuf, AMBX_LIGHT_COMMAND_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void AMBX::setLight(AmbxLightsEnum ambx_light, AmbxColorsEnum color) { // Use this to set the Light with Color using the predefined in "AMBXEnums.h"
|
||||
setLight(ambx_light, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
|
||||
}
|
||||
|
||||
void AMBX::setAllLights(AmbxColorsEnum color) { // Use this to set the Color using the predefined colors in "AMBXEnums.h"
|
||||
setLight(Sidelight_left, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
|
||||
setLight(Sidelight_right, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
|
||||
setLight(Wallwasher_center, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
|
||||
setLight(Wallwasher_left, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
|
||||
setLight(Wallwasher_right, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
|
||||
}
|
||||
|
||||
void AMBX::onInit() {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nOnInit execute "), 0x80);
|
||||
#endif
|
||||
if(pFuncOnInit)
|
||||
pFuncOnInit(); // Call the user function
|
||||
}
|
159
AMBX.h
Normal file
159
AMBX.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
/* Copyright (C) 2021 Aran Vink. All rights reserved.
|
||||
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
|
||||
Contact information
|
||||
-------------------
|
||||
|
||||
Aran Vink
|
||||
e-mail : aranvink@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef _ambxusb_h_
|
||||
#define _ambxusb_h_
|
||||
|
||||
#include "Usb.h"
|
||||
#include "AMBXEnums.h"
|
||||
|
||||
/* AMBX data taken from descriptors */
|
||||
#define AMBX_EP_MAXPKTSIZE 40 // max size for data via USB
|
||||
|
||||
/* Names we give to the 3 AMBX but note only one is actually used (output) */
|
||||
#define AMBX_CONTROL_PIPE 0
|
||||
#define AMBX_OUTPUT_PIPE 1
|
||||
#define AMBX_INPUT_PIPE 2
|
||||
|
||||
/* PID and VID of the different devices */
|
||||
#define AMBX_VID 0x0471 // Philips
|
||||
#define AMBX_PID 0x083F // AMBX Controller
|
||||
|
||||
/* Endpoint addresses */
|
||||
#define AMBX_ENDPOINT_IN 0x81
|
||||
#define AMBX_ENDPOINT_OUT 0x02
|
||||
#define AMBX_ENDPOINT_PNP 0x83
|
||||
|
||||
/* Output payload constants */
|
||||
#define AMBX_PREFIX_COMMAND 0xA1
|
||||
#define AMBX_SET_COLOR_COMMAND 0x03
|
||||
|
||||
/* LEFT/RIGHT lights. Normally placed adjecent to your screen. */
|
||||
#define AMBX_LIGHT_LEFT 0x0B
|
||||
#define AMBX_LIGHT_RIGHT 0x1B
|
||||
|
||||
/* Wallwasher lights. Normally placed behind your screen. */
|
||||
#define AMBX_LIGHT_WW_LEFT 0x2B
|
||||
#define AMBX_LIGHT_WW_CENTER 0x3B
|
||||
#define AMBX_LIGHT_WW_RIGHT 0x4B
|
||||
|
||||
#define AMBX_LIGHT_COMMAND_BUFFER_SIZE 6
|
||||
|
||||
|
||||
#define AMBX_MAX_ENDPOINTS 3
|
||||
|
||||
/**
|
||||
* This class implements support for AMBX
|
||||
* One can only set the color of the bulbs, no other accesories like rumble pad, fans, etc. are supported
|
||||
*
|
||||
*/
|
||||
class AMBX : public USBDeviceConfig {
|
||||
public:
|
||||
/**
|
||||
* Constructor for the AMBX class.
|
||||
* @param pUsb Pointer to USB class instance.
|
||||
*/
|
||||
AMBX(USB *pUsb);
|
||||
|
||||
/** @name USBDeviceConfig implementation */
|
||||
/**
|
||||
* Initialize the AMBX Controller.
|
||||
* @param parent Hub number.
|
||||
* @param port Port number on the hub.
|
||||
* @param lowspeed Speed of the device.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||
/**
|
||||
* Release the USB device.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
uint8_t Release();
|
||||
/**
|
||||
* Poll the USB Input endpoins and run the state machines.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
uint8_t Poll();
|
||||
|
||||
/**
|
||||
* Get the device address.
|
||||
* @return The device address.
|
||||
*/
|
||||
virtual uint8_t GetAddress() {
|
||||
return bAddress;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used by the USB core to check what this driver support.
|
||||
* @param vid The device's VID.
|
||||
* @param pid The device's PID.
|
||||
* @return Returns true if the device's VID and PID matches this driver.
|
||||
*/
|
||||
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
|
||||
return (vid == AMBX_VID && (pid == AMBX_PID));
|
||||
};
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* Use this to set the Color using RGB values.
|
||||
* @param r,g,b RGB value.
|
||||
*/
|
||||
void setLight(uint8_t ambx_light, uint8_t r, uint8_t g, uint8_t b);
|
||||
/**
|
||||
* Use this to set the color using the predefined colors in ::ColorsEnum.
|
||||
* @param color The desired color.
|
||||
*/
|
||||
void setLight(AmbxLightsEnum ambx_light, AmbxColorsEnum color);
|
||||
|
||||
/**
|
||||
* Use this to set the color using the predefined colors in ::ColorsEnum.
|
||||
* @param color The desired color.
|
||||
*/
|
||||
void setAllLights(AmbxColorsEnum color);
|
||||
|
||||
/**
|
||||
* Used to call your own function when the controller is successfully initialized.
|
||||
* @param funcOnInit Function to call.
|
||||
*/
|
||||
void attachOnInit(void (*funcOnInit)(void)) {
|
||||
pFuncOnInit = funcOnInit;
|
||||
};
|
||||
/**@}*/
|
||||
|
||||
bool AMBXConnected;
|
||||
|
||||
protected:
|
||||
/** Pointer to USB class instance. */
|
||||
USB *pUsb;
|
||||
/** Device address. */
|
||||
uint8_t bAddress;
|
||||
/** Endpoint info structure. */
|
||||
EpInfo epInfo[AMBX_MAX_ENDPOINTS];
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called when the AMBX controller is successfully initialized.
|
||||
*/
|
||||
void onInit();
|
||||
void (*pFuncOnInit)(void); // Pointer to function called in onInit()
|
||||
|
||||
uint8_t writeBuf[AMBX_EP_MAXPKTSIZE]; // General purpose buffer for output data
|
||||
|
||||
/* Private commands */
|
||||
void Light_Command(uint8_t *data, uint16_t nbytes);
|
||||
};
|
||||
|
||||
#endif
|
38
AMBXEnums.h
Normal file
38
AMBXEnums.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Copyright (C) 2021 Aran Vink. All rights reserved.
|
||||
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
|
||||
Contact information
|
||||
-------------------
|
||||
|
||||
Aran Vink
|
||||
e-mail : aranvink@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef _ambxenums_h
|
||||
#define _ambxenums_h
|
||||
|
||||
/** Used to set the colors of the AMBX lights. This is just a limited predefined set, the lights allow ANY value between 0x00 and 0xFF */
|
||||
enum AmbxColorsEnum {
|
||||
Red = 0xFF0000,
|
||||
Green = 0x00FF00,
|
||||
Blue = 0x0000FF,
|
||||
White = 0xFFFFFF,
|
||||
Off = 0x000000,
|
||||
};
|
||||
|
||||
/** Used to select light in the AMBX system */
|
||||
enum AmbxLightsEnum {
|
||||
Sidelight_left = 0x0B,
|
||||
Sidelight_right = 0x1B,
|
||||
Wallwasher_left = 0x2B,
|
||||
Wallwasher_center = 0x3B,
|
||||
Wallwasher_right = 0x4B,
|
||||
};
|
||||
|
||||
#endif
|
55
examples/ambx/AMBX.ino
Normal file
55
examples/ambx/AMBX.ino
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Example sketch for the AMBX library - developed by Aran Vink <aranvink@gmail.com>
|
||||
*/
|
||||
|
||||
#include <AMBX.h>
|
||||
|
||||
// Satisfy the IDE, which needs to see the include statment in the ino too.
|
||||
#ifdef dobogusinclude
|
||||
#include <spi4teensy3.h>
|
||||
#endif
|
||||
#include <SPI.h>
|
||||
|
||||
USB Usb;
|
||||
AMBX AMBX(&Usb); // This will just create the instance
|
||||
|
||||
bool printAngle;
|
||||
uint8_t state = 0;
|
||||
|
||||
void setup() {
|
||||
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
|
||||
if (Usb.Init() == -1) {
|
||||
Serial.print(F("\r\nOSC did not start"));
|
||||
while (1); //halt
|
||||
}
|
||||
Serial.print(F("\r\nAMBX USB Library Started"));
|
||||
}
|
||||
void loop() {
|
||||
Usb.Task();
|
||||
|
||||
if (AMBX.AMBXConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB
|
||||
if (state == 0) {
|
||||
|
||||
} else if (state == 1) {
|
||||
AMBX.setAllLights(Red);
|
||||
} else if (state == 2) {
|
||||
AMBX.setAllLights(Green);
|
||||
} else if (state == 3) {
|
||||
AMBX.setAllLights(Blue);
|
||||
} else if (state == 4) {
|
||||
AMBX.setAllLights(White);
|
||||
}
|
||||
|
||||
//Example using single light:
|
||||
//AMBX.setLight(Wallwasher_center, White);
|
||||
|
||||
state++;
|
||||
if (state > 4)
|
||||
state = 0;
|
||||
delay(1000);
|
||||
}
|
||||
delay(10);
|
||||
}
|
Loading…
Reference in a new issue