223 lines
7.8 KiB
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
|
|
|