crashtest-r0ket/firmware/usb/usbhid.c

223 lines
7.8 KiB
C

/**************************************************************************/
/*!
@file usbhid.c
@author K. Townsend (microBuilder.eu)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2010, microBuilder SARL
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#include <string.h>
#include "core/rom_drivers.h"
#include "core/gpio/gpio.h"
#include "core/adc/adc.h"
#include "core/systick/systick.h"
#include "usb.h"
#include "usbconfig.h"
#include "usbhid.h"
static USB_DEV_INFO DeviceInfo;
static HID_DEVICE_INFO HidDevInfo;
static ROM ** rom = (ROM **)0x1fff1ff8;
typedef struct usbhid_out_s
{
uint16_t gpio1Dir;
uint16_t gpio1Data;
uint16_t gpio2Dir;
uint16_t gpio2Data;
uint16_t gpio3Dir;
uint16_t gpio3Data;
uint16_t adc0;
uint16_t adc1;
uint16_t adc2;
uint16_t adc3;
uint32_t systicks;
uint32_t rollovers;
} usbhid_out_t;
/**************************************************************************/
/*!
@brief Gets the HID In Report (the report going from the LPC1343 to
the USB host)
*/
/**************************************************************************/
void usbHIDGetInReport (uint8_t src[], uint32_t length)
{
usbhid_out_t out;
out.gpio1Dir = GPIO_GPIO1DIR;
out.gpio1Data = GPIO_GPIO1DATA;
out.gpio2Dir = GPIO_GPIO2DIR;
out.gpio2Data = GPIO_GPIO2DATA;
out.gpio3Dir = GPIO_GPIO3DIR;
out.gpio3Data = GPIO_GPIO3DATA;
out.adc0 = adcRead(0);
out.adc1 = adcRead(1);
out.adc2 = adcRead(2);
out.adc3 = adcRead(3);
out.systicks = systickGetTicks();
out.rollovers = systickGetRollovers();
size_t i = 0;
memcpy(&src[i], &out.gpio1Dir, sizeof out.gpio1Dir);
i += sizeof out.gpio1Dir;
memcpy(&src[i], &out.gpio1Data, sizeof out.gpio1Data);
i += sizeof out.gpio1Data;
memcpy(&src[i], &out.gpio2Dir, sizeof out.gpio2Dir);
i += sizeof out.gpio2Dir;
memcpy(&src[i], &out.gpio2Data, sizeof out.gpio2Data);
i += sizeof out.gpio2Data;
memcpy(&src[i], &out.gpio3Dir, sizeof out.gpio3Dir);
i += sizeof out.gpio3Dir;
memcpy(&src[i], &out.gpio3Data, sizeof out.gpio3Data);
i += sizeof out.gpio3Data;
memcpy(&src[i], &out.adc0, sizeof out.adc0);
i += sizeof out.adc0;
memcpy(&src[i], &out.adc1, sizeof out.adc1);
i += sizeof out.adc1;
memcpy(&src[i], &out.adc2, sizeof out.adc2);
i += sizeof out.adc2;
memcpy(&src[i], &out.adc3, sizeof out.adc3);
i += sizeof out.adc3;
memcpy(&src[i], &out.systicks, sizeof out.systicks);
i += sizeof out.systicks;
memcpy(&src[i], &out.rollovers, sizeof out.rollovers);
i += sizeof out.rollovers;
}
/**************************************************************************/
/*!
@brief Sets the HID Out Report (the report coming in from the USB
host to the LPC1343).
*/
/**************************************************************************/
void usbHIDSetOutReport (uint8_t dst[], uint32_t length)
{
uint8_t PCOutReportData = dst[0];
// Check bit 0 in the incoming report to determine is LED should
// be enabled or disabled (1 = enabled, 0 = disabled)
if (PCOutReportData & (1<<0))
{
// Enable LED (set low)
gpioSetValue (CFG_LED_PORT, CFG_LED_PIN, 0);
}
else
{
// Disable LED (set high)
gpioSetValue (CFG_LED_PORT, CFG_LED_PIN, 1);
}
}
/**************************************************************************/
/*!
@brief Initialises the USB port
The ROM-based USB HID code is capable of configuring the PLL and pins
for USB, but there seems to be a bug in the code that sets the system
clock to 48MHz (normally the USB and System clocks can be configured
seperately). As such, this code does not use the "init_clk_pins()"
function in the rom, and the USB clock and pins are manually
configured.
*/
/**************************************************************************/
void usbHIDInit (void)
{
// Setup USB clock
SCB_PDRUNCFG &= ~(SCB_PDSLEEPCFG_USBPAD_PD); // Power-up USB PHY
SCB_PDRUNCFG &= ~(SCB_PDSLEEPCFG_USBPLL_PD); // Power-up USB PLL
SCB_USBPLLCLKSEL = SCB_USBPLLCLKSEL_SOURCE_MAINOSC; // Select PLL Input
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_UPDATE; // Update Clock Source
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_DISABLE; // Toggle Update Register
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_UPDATE;
// Wait until the USB clock is updated
while (!(SCB_USBPLLCLKUEN & SCB_USBPLLCLKUEN_UPDATE));
// Set USB clock to 48MHz (12MHz x 4)
SCB_USBPLLCTRL = (SCB_USBPLLCTRL_MULT_4);
while (!(SCB_USBPLLSTAT & SCB_USBPLLSTAT_LOCK)); // Wait Until PLL Locked
SCB_USBCLKSEL = SCB_USBCLKSEL_SOURCE_USBPLLOUT;
// Set USB pin functions
IOCON_PIO0_1 &= ~IOCON_PIO0_1_FUNC_MASK;
IOCON_PIO0_1 |= IOCON_PIO0_1_FUNC_CLKOUT; // CLK OUT
IOCON_PIO0_3 &= ~IOCON_PIO0_3_FUNC_MASK;
IOCON_PIO0_3 |= IOCON_PIO0_3_FUNC_USB_VBUS; // VBus
IOCON_PIO0_6 &= ~IOCON_PIO0_6_FUNC_MASK;
IOCON_PIO0_6 |= IOCON_PIO0_6_FUNC_USB_CONNECT; // Soft Connect
// Disable internal resistor on VBUS (0.3)
gpioSetPullup(&IOCON_PIO0_3, gpioPullupMode_Inactive);
// HID Device Info
volatile int n;
HidDevInfo.idVendor = USB_VENDOR_ID;
HidDevInfo.idProduct = USB_PROD_ID;
HidDevInfo.bcdDevice = USB_DEVICE;
HidDevInfo.StrDescPtr = (uint32_t)&USB_HIDStringDescriptor[0];
HidDevInfo.InReportCount = sizeof(usbhid_out_t);
HidDevInfo.OutReportCount = 1;
HidDevInfo.SampleInterval = 0x20;
HidDevInfo.InReport = usbHIDGetInReport;
HidDevInfo.OutReport = usbHIDSetOutReport;
DeviceInfo.DevType = USB_DEVICE_CLASS_HUMAN_INTERFACE;
DeviceInfo.DevDetailPtr = (uint32_t)&HidDevInfo;
/* Enable Timer32_1, IOCON, and USB blocks (for USB ROM driver) */
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B1 | SCB_SYSAHBCLKCTRL_IOCON | SCB_SYSAHBCLKCTRL_USB_REG);
/* Use pll and pin init function in rom */
/* Warning: This will also set the system clock to 48MHz! */
// (*rom)->pUSBD->init_clk_pins();
/* insert a delay between clk init and usb init */
for (n = 0; n < 75; n++) {__asm("nop");}
(*rom)->pUSBD->init(&DeviceInfo); /* USB Initialization */
(*rom)->pUSBD->connect(true); /* USB Connect */
}
/**************************************************************************/
/*!
@brief Passes the USB interrupt to the internal ROM-based handler
*/
/**************************************************************************/
#ifdef CFG_USBHID
void USB_IRQHandler()
{
(*rom)->pUSBD->isr();
}
#endif