From 39a5c822a2a2e798e2e39ff8a98b7af84253026c Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Sat, 28 Aug 2021 12:50:18 -0400 Subject: add tinyusb --- tinyusb/hw/bsp/ea4357/board.mk | 46 +++++ tinyusb/hw/bsp/ea4357/ea4357.c | 291 ++++++++++++++++++++++++++++++++ tinyusb/hw/bsp/ea4357/lpc4357.ld | 324 +++++++++++++++++++++++++++++++++++ tinyusb/hw/bsp/ea4357/pca9532.c | 352 +++++++++++++++++++++++++++++++++++++++ tinyusb/hw/bsp/ea4357/pca9532.h | 94 +++++++++++ 5 files changed, 1107 insertions(+) create mode 100755 tinyusb/hw/bsp/ea4357/board.mk create mode 100755 tinyusb/hw/bsp/ea4357/ea4357.c create mode 100755 tinyusb/hw/bsp/ea4357/lpc4357.ld create mode 100755 tinyusb/hw/bsp/ea4357/pca9532.c create mode 100755 tinyusb/hw/bsp/ea4357/pca9532.h (limited to 'tinyusb/hw/bsp/ea4357') diff --git a/tinyusb/hw/bsp/ea4357/board.mk b/tinyusb/hw/bsp/ea4357/board.mk new file mode 100755 index 00000000..86391ab5 --- /dev/null +++ b/tinyusb/hw/bsp/ea4357/board.mk @@ -0,0 +1,46 @@ +DEPS_SUBMODULES += hw/mcu/nxp/lpcopen + +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib \ + -DCORE_M4 \ + -D__USE_LPCOPEN \ + -DCFG_TUSB_MCU=OPT_MCU_LPC43XX + +# mcu driver cause following warnings +CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes + +MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/$(BOARD)/lpc4357.ld + +SRC_C += \ + src/portable/nxp/transdimension/dcd_transdimension.c \ + $(MCU_DIR)/../gcc/cr_startup_lpc43xx.c \ + $(MCU_DIR)/src/chip_18xx_43xx.c \ + $(MCU_DIR)/src/clock_18xx_43xx.c \ + $(MCU_DIR)/src/gpio_18xx_43xx.c \ + $(MCU_DIR)/src/sysinit_18xx_43xx.c \ + $(MCU_DIR)/src/i2c_18xx_43xx.c \ + $(MCU_DIR)/src/i2cm_18xx_43xx.c \ + $(MCU_DIR)/src/uart_18xx_43xx.c \ + $(MCU_DIR)/src/fpu_init.c + +INC += \ + $(TOP)/$(MCU_DIR)/inc \ + $(TOP)/$(MCU_DIR)/inc/config_43xx + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = LPC4357_M4 + +# flash using jlink +flash: flash-jlink diff --git a/tinyusb/hw/bsp/ea4357/ea4357.c b/tinyusb/hw/bsp/ea4357/ea4357.c new file mode 100755 index 00000000..aa206a28 --- /dev/null +++ b/tinyusb/hw/bsp/ea4357/ea4357.c @@ -0,0 +1,291 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "chip.h" +#include "../board.h" +#include "pca9532.h" + +#define UART_DEV LPC_USART0 +#define UART_PORT 0x0f +#define UART_PIN_TX 10 +#define UART_PIN_RX 11 + +// P9_1 joystick down +#define BUTTON_PORT 4 +#define BUTTON_PIN 13 + +//static const struct { +// uint8_t mux_port; +// uint8_t mux_pin; +// +// uint8_t gpio_port; +// uint8_t gpio_pin; +//}buttons[] = +//{ +// {0x0a, 3, 4, 10 }, // Joystick up +// {0x09, 1, 4, 13 }, // Joystick down +// {0x0a, 2, 4, 9 }, // Joystick left +// {0x09, 0, 4, 12 }, // Joystick right +// {0x0a, 1, 4, 8 }, // Joystick press +// {0x02, 7, 0, 7 }, // SW6 +//}; + +/*------------------------------------------------------------------*/ +/* BOARD API + *------------------------------------------------------------------*/ + +/* System configuration variables used by chip driver */ +const uint32_t OscRateIn = 12000000; +const uint32_t ExtRateIn = 0; + +static const PINMUX_GRP_T pinmuxing[] = +{ + // Button ( Joystick down ) + {0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP)}, + + // UART + {UART_PORT, UART_PIN_TX, SCU_MODE_PULLDOWN | SCU_MODE_FUNC1}, + {UART_PORT, UART_PIN_RX, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC1}, + + // USB +}; + +/* Pin clock mux values, re-used structure, value in first index is meaningless */ +static const PINMUX_GRP_T pinclockmuxing[] = +{ + {0, 0, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, + {0, 1, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, + {0, 2, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, + {0, 3, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, +}; + +// Invoked by startup code +void SystemInit(void) +{ +#ifdef __USE_LPCOPEN + extern void (* const g_pfnVectors[])(void); + unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; + *pSCB_VTOR = (unsigned int) g_pfnVectors; + +#if __FPU_USED == 1 + fpuInit(); +#endif +#endif // __USE_LPCOPEN + + /* Setup system level pin muxing */ + Chip_SCU_SetPinMuxing(pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); + + /* Clock pins only, group field not used */ + for (int i = 0; i <(int) (sizeof(pinclockmuxing) / sizeof(pinclockmuxing[0])); i++) + { + Chip_SCU_ClockPinMuxSet(pinclockmuxing[i].pinnum, pinclockmuxing[i].modefunc); + } + + Chip_SetupXtalClocking(); +} + +void board_init(void) +{ + SystemCoreClockUpdate(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + Chip_GPIO_Init(LPC_GPIO_PORT); + + // LED via pca9532 I2C + Chip_SCU_I2C0PinConfig(I2C0_STANDARD_FAST_MODE); + Chip_I2C_Init(I2C0); + Chip_I2C_SetClockRate(I2C0, 100000); + Chip_I2C_SetMasterEventHandler(I2C0, Chip_I2C_EventHandlerPolling); + + pca9532_init(); + + // Button + Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN); + + //------------- UART -------------// + Chip_UART_Init(UART_DEV); + Chip_UART_SetBaud(UART_DEV, CFG_BOARD_UART_BAUDRATE); + Chip_UART_ConfigData(UART_DEV, UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS); + Chip_UART_TXEnable(UART_DEV); + + //------------- USB -------------// + enum { + USBMODE_DEVICE = 2, + USBMODE_HOST = 3 + }; + + enum { + USBMODE_VBUS_LOW = 0, + USBMODE_VBUS_HIGH = 1 + }; + + /* From EA4357 user manual + * + * USB0 Device operation: + * - Insert jumpers in position 1-2 in JP17/JP18/JP19. + * - GPIO28 controls USB connect functionality + * - LED32 lights when the USB Device is connected. SJ4 has pads 1-2 shorted by default. + * - LED33 is controlled by GPIO27 and signals USB-up state. GPIO54 is used for VBUS + * sensing. + * + * USB0 Host operation: + * - insert jumpers in position 2-3 in JP17/JP18/JP19. + * - USB Host power is controlled via distribution switch U20 (found in schematic page 11). + * - Signal GPIO26 is active low and enables +5V on VBUS2. + * - LED35 light whenever +5V is present on VBUS2. + * - GPIO55 is connected to status feedback from the distribution switch. + * - GPIO54 is used for VBUS sensing. 15Kohm pull-down resistors are always active + * + * Note: + * - Insert jumpers in position 2-3 in JP17/JP18/JP19 + * - Insert jumpers in JP31 (OTG) + */ +#if CFG_TUSB_RHPORT0_MODE + Chip_USB0_Init(); +#endif + + /* From EA4357 user manual + * + * For USB1 Device: + * - a 1.5Kohm pull-up resistor is needed on the USB DP data signal. There are two methods to create this. + * JP15 is inserted and the pull-up resistor is always enabled. Alternatively, the pull-up resistor is activated + * inside the USB OTG chip (U31), and this has to be done via the I2C interface of GPIO52/GPIO53. In the latter case, + * JP15 shall not be inserted. + * - J19 is the connector to use when USB Device is used. Normally it should be a USB-B connector for + * creating a USB Device interface, but the mini-AB connector can also be used in this case. The status + * of VBUS can be read via U31. + * - JP16 shall not be inserted. + * + * For USB1 Host: + * - 15Kohm pull-down resistors are needed on the USB data signals. These are activated inside the USB OTG chip (U31), + * and this has to be done via the I2C interface of GPIO52/GPIO53. + * - J20 is the connector to use when USB Host is used. In order to provide +5V to the external USB + * device connected to this connector (J20), channel A of U20 must be enabled. It is enabled by default + * since SJ5 is normally connected between pin 1-2. + * - LED34 lights green when +5V is available on J20. + * - JP15 shall not be inserted. JP16 has no effect + */ +#if CFG_TUSB_RHPORT1_MODE + Chip_USB1_Init(); +#endif + + // USB0 Vbus Power: P2_3 on EA4357 channel B U20 GPIO26 active low (base board) + Chip_SCU_PinMuxSet(2, 3, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC7); + + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE + // P9_5 (GPIO5[18]) (GPIO28 on oem base) as USB connect, active low. + Chip_SCU_PinMuxSet(9, 5, SCU_MODE_PULLDOWN | SCU_MODE_FUNC4); + Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 5, 18); + #endif + + // USB1 Power: EA4357 channel A U20 is enabled by SJ5 connected to pad 1-2, no more action required + // TODO Remove R170, R171, solder a pair of 15K to USB1 D+/D- to test with USB1 Host +} + +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +void USB0_IRQHandler(void) +{ + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST + tuh_int_handler(0); + #endif + + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE + tud_int_handler(0); + #endif +} + +void USB1_IRQHandler(void) +{ + #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + tuh_int_handler(1); + #endif + + #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + tud_int_handler(1); + #endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + if (state) + { + pca9532_setLeds( LED1, 0 ); + }else + { + pca9532_setLeds( 0, LED1); + } +} + +uint32_t board_button_read(void) +{ + // active low + return Chip_GPIO_GetPinState(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN) ? 0 : 1; +} + +int board_uart_read(uint8_t* buf, int len) +{ + //return UART_ReceiveByte(BOARD_UART_DEV); + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + uint8_t const* buf8 = (uint8_t const*) buf; + for(int i=0; i MFlashB512 + + /* MAIN TEXT SECTION */ + .text : ALIGN(4) + { + FILL(0xff) + __vectors_start__ = ABSOLUTE(.) ; + KEEP(*(.isr_vector)) + /* Global Section Table */ + . = ALIGN(4) ; + __section_table_start = .; + __data_section_table = .; + LONG(LOADADDR(.data)); + LONG( ADDR(.data)); + LONG( SIZEOF(.data)); + LONG(LOADADDR(.data_RAM2)); + LONG( ADDR(.data_RAM2)); + LONG( SIZEOF(.data_RAM2)); + LONG(LOADADDR(.data_RAM3)); + LONG( ADDR(.data_RAM3)); + LONG( SIZEOF(.data_RAM3)); + LONG(LOADADDR(.data_RAM4)); + LONG( ADDR(.data_RAM4)); + LONG( SIZEOF(.data_RAM4)); + LONG(LOADADDR(.data_RAM5)); + LONG( ADDR(.data_RAM5)); + LONG( SIZEOF(.data_RAM5)); + __data_section_table_end = .; + __bss_section_table = .; + LONG( ADDR(.bss)); + LONG( SIZEOF(.bss)); + LONG( ADDR(.bss_RAM2)); + LONG( SIZEOF(.bss_RAM2)); + LONG( ADDR(.bss_RAM3)); + LONG( SIZEOF(.bss_RAM3)); + LONG( ADDR(.bss_RAM4)); + LONG( SIZEOF(.bss_RAM4)); + LONG( ADDR(.bss_RAM5)); + LONG( SIZEOF(.bss_RAM5)); + __bss_section_table_end = .; + __section_table_end = . ; + /* End of Global Section Table */ + + *(.after_vectors*) + + } > MFlashA512 + + .text : ALIGN(4) + { + *(.text*) + *(.rodata .rodata.* .constdata .constdata.*) + . = ALIGN(4); + } > MFlashA512 + /* + * for exception handling/unwind - some Newlib functions (in common + * with C++ and STDC++) use this. + */ + .ARM.extab : ALIGN(4) + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > MFlashA512 + + __exidx_start = .; + + .ARM.exidx : ALIGN(4) + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > MFlashA512 + __exidx_end = .; + + _etext = .; + + /* DATA section for RamLoc40 */ + + .data_RAM2 : ALIGN(4) + { + FILL(0xff) + PROVIDE(__start_data_RAM2 = .) ; + *(.ramfunc.$RAM2) + *(.ramfunc.$RamLoc40) + *(.data.$RAM2*) + *(.data.$RamLoc40*) + . = ALIGN(4) ; + PROVIDE(__end_data_RAM2 = .) ; + } > RamLoc40 AT>MFlashA512 + /* DATA section for RamAHB32 */ + + .data_RAM3 : ALIGN(4) + { + FILL(0xff) + PROVIDE(__start_data_RAM3 = .) ; + *(.ramfunc.$RAM3) + *(.ramfunc.$RamAHB32) + *(.data.$RAM3*) + *(.data.$RamAHB32*) + . = ALIGN(4) ; + PROVIDE(__end_data_RAM3 = .) ; + } > RamAHB32 AT>MFlashA512 + /* DATA section for RamAHB16 */ + + .data_RAM4 : ALIGN(4) + { + FILL(0xff) + PROVIDE(__start_data_RAM4 = .) ; + *(.ramfunc.$RAM4) + *(.ramfunc.$RamAHB16) + *(.data.$RAM4*) + *(.data.$RamAHB16*) + . = ALIGN(4) ; + PROVIDE(__end_data_RAM4 = .) ; + } > RamAHB16 AT>MFlashA512 + /* DATA section for RamAHB_ETB16 */ + + .data_RAM5 : ALIGN(4) + { + FILL(0xff) + PROVIDE(__start_data_RAM5 = .) ; + *(.ramfunc.$RAM5) + *(.ramfunc.$RamAHB_ETB16) + *(.data.$RAM5*) + *(.data.$RamAHB_ETB16*) + . = ALIGN(4) ; + PROVIDE(__end_data_RAM5 = .) ; + } > RamAHB_ETB16 AT>MFlashA512 + /* MAIN DATA SECTION */ + .uninit_RESERVED : ALIGN(4) + { + KEEP(*(.bss.$RESERVED*)) + . = ALIGN(4) ; + _end_uninit_RESERVED = .; + } > RamLoc32 + + /* Main DATA section (RamLoc32) */ + .data : ALIGN(4) + { + FILL(0xff) + _data = . ; + *(vtable) + *(.ramfunc*) + *(.data*) + . = ALIGN(4) ; + _edata = . ; + } > RamLoc32 AT>MFlashA512 + + /* BSS section for RamLoc40 */ + .bss_RAM2 : ALIGN(4) + { + PROVIDE(__start_bss_RAM2 = .) ; + *(.bss.$RAM2*) + *(.bss.$RamLoc40*) + . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */ + PROVIDE(__end_bss_RAM2 = .) ; + } > RamLoc40 + + /* BSS section for RamAHB32 */ + .bss_RAM3 : ALIGN(4) + { + PROVIDE(__start_bss_RAM3 = .) ; + *(.bss.$RAM3*) + *(.bss.$RamAHB32*) + . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */ + PROVIDE(__end_bss_RAM3 = .) ; + } > RamAHB32 + + /* BSS section for RamAHB16 */ + .bss_RAM4 : ALIGN(4) + { + PROVIDE(__start_bss_RAM4 = .) ; + *(.bss.$RAM4*) + *(.bss.$RamAHB16*) + . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */ + PROVIDE(__end_bss_RAM4 = .) ; + } > RamAHB16 + + /* BSS section for RamAHB_ETB16 */ + .bss_RAM5 : ALIGN(4) + { + PROVIDE(__start_bss_RAM5 = .) ; + *(.bss.$RAM5*) + *(.bss.$RamAHB_ETB16*) + . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */ + PROVIDE(__end_bss_RAM5 = .) ; + } > RamAHB_ETB16 + + /* MAIN BSS SECTION */ + .bss : ALIGN(4) + { + _bss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4) ; + _ebss = .; + PROVIDE(end = .); + } > RamLoc32 + + /* NOINIT section for RamLoc40 */ + .noinit_RAM2 (NOLOAD) : ALIGN(4) + { + *(.noinit.$RAM2*) + *(.noinit.$RamLoc40*) + . = ALIGN(4) ; + } > RamLoc40 + + /* NOINIT section for RamAHB32 */ + .noinit_RAM3 (NOLOAD) : ALIGN(4) + { + *(.noinit.$RAM3*) + *(.noinit.$RamAHB32*) + . = ALIGN(4) ; + } > RamAHB32 + + /* NOINIT section for RamAHB16 */ + .noinit_RAM4 (NOLOAD) : ALIGN(4) + { + *(.noinit.$RAM4*) + *(.noinit.$RamAHB16*) + . = ALIGN(4) ; + } > RamAHB16 + + /* NOINIT section for RamAHB_ETB16 */ + .noinit_RAM5 (NOLOAD) : ALIGN(4) + { + *(.noinit.$RAM5*) + *(.noinit.$RamAHB_ETB16*) + . = ALIGN(4) ; + } > RamAHB_ETB16 + + /* DEFAULT NOINIT SECTION */ + .noinit (NOLOAD): ALIGN(4) + { + _noinit = .; + *(.noinit*) + . = ALIGN(4) ; + _end_noinit = .; + } > RamLoc32 + PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .); + PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc32 - 0); + + /* ## Create checksum value (used in startup) ## */ + PROVIDE(__valid_user_code_checksum = 0 - + (_vStackTop + + (ResetISR + 1) + + (NMI_Handler + 1) + + (HardFault_Handler + 1) + + (( DEFINED(MemManage_Handler) ? MemManage_Handler : 0 ) + 1) /* MemManage_Handler may not be defined */ + + (( DEFINED(BusFault_Handler) ? BusFault_Handler : 0 ) + 1) /* BusFault_Handler may not be defined */ + + (( DEFINED(UsageFault_Handler) ? UsageFault_Handler : 0 ) + 1) /* UsageFault_Handler may not be defined */ + ) ); + + /* Provide basic symbols giving location and size of main text + * block, including initial values of RW data sections. Note that + * these will need extending to give a complete picture with + * complex images (e.g multiple Flash banks). + */ + _image_start = LOADADDR(.text); + _image_end = LOADADDR(.data) + SIZEOF(.data); + _image_size = _image_end - _image_start; +} \ No newline at end of file diff --git a/tinyusb/hw/bsp/ea4357/pca9532.c b/tinyusb/hw/bsp/ea4357/pca9532.c new file mode 100755 index 00000000..eae3805c --- /dev/null +++ b/tinyusb/hw/bsp/ea4357/pca9532.c @@ -0,0 +1,352 @@ +/***************************************************************************** + * + * Copyright(C) 2011, Embedded Artists AB + * All rights reserved. + * + ****************************************************************************** + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * products. This software is supplied "AS IS" without any warranties. + * Embedded Artists AB assumes no responsibility or liability for the + * use of the software, conveys no license or title under any patent, + * copyright, or mask work right to the product. Embedded Artists AB + * reserves the right to make changes in the software without + * notification. Embedded Artists AB also make no representation or + * warranty that such application will be suitable for the specified + * use without further testing or modification. + *****************************************************************************/ + +/* + * NOTE: I2C must have been initialized before calling any functions in this + * file. + */ + +/****************************************************************************** + * Includes + *****************************************************************************/ + +//#include "board.h" +#include "chip.h" + +#include "pca9532.h" + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + +#define I2C_PORT (LPC_I2C0) + +#define LS_MODE_ON 0x01 +#define LS_MODE_BLINK0 0x02 +#define LS_MODE_BLINK1 0x03 + +/****************************************************************************** + * External global variables + *****************************************************************************/ + + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +static uint16_t blink0Shadow = 0; +static uint16_t blink1Shadow = 0; +static uint16_t ledStateShadow = 0; + +/****************************************************************************** + * Local Functions + *****************************************************************************/ + +static Status I2CWrite(uint32_t addr, uint8_t* buf, uint32_t len) +{ + I2CM_XFER_T i2cData; + + i2cData.slaveAddr = addr; + i2cData.options = 0; + i2cData.status = 0; + i2cData.txBuff = buf; + i2cData.txSz = len; + i2cData.rxBuff = NULL; + i2cData.rxSz = 0; + + if (Chip_I2CM_XferBlocking(LPC_I2C0, &i2cData) == 0) { + return ERROR; + } + return SUCCESS; +} + +static Status I2CRead(uint32_t addr, uint8_t* buf, uint32_t len) +{ + I2CM_XFER_T i2cData; + + i2cData.slaveAddr = addr; + i2cData.options = 0; + i2cData.status = 0; + i2cData.txBuff = NULL; + i2cData.txSz = 0; + i2cData.rxBuff = buf; + i2cData.rxSz = len; + + if (Chip_I2CM_XferBlocking(LPC_I2C0, &i2cData) == 0) { + return ERROR; + } + return SUCCESS; +} + +static void setLsStates(uint16_t states, uint8_t* ls, uint8_t mode) +{ +#define IS_LED_SET(bit, x) ( ( ((x) & (bit)) != 0 ) ? 1 : 0 ) + + int i = 0; + + for (i = 0; i < 4; i++) { + + ls[i] |= ( (IS_LED_SET(0x0001, states)*mode << 0) + | (IS_LED_SET(0x0002, states)*mode << 2) + | (IS_LED_SET(0x0004, states)*mode << 4) + | (IS_LED_SET(0x0008, states)*mode << 6) ); + + states >>= 4; + } +} + +static void setLeds(void) +{ + uint8_t buf[5]; + uint8_t ls[4] = {0,0,0,0}; + uint16_t states = ledStateShadow; + + /* LEDs in On/Off state */ + setLsStates(states, ls, LS_MODE_ON); + + /* set the LEDs that should blink */ + setLsStates(blink0Shadow, ls, LS_MODE_BLINK0); + setLsStates(blink1Shadow, ls, LS_MODE_BLINK1); + + + buf[0] = PCA9532_LS0 | PCA9532_AUTO_INC; + buf[1] = ls[0]; + buf[2] = ls[1]; + buf[3] = ls[2]; + buf[4] = ls[3]; + I2CWrite(PCA9532_I2C_ADDR, buf, 5); +} + +/****************************************************************************** + * Public Functions + *****************************************************************************/ + +/****************************************************************************** + * + * Description: + * Initialize the PCA9532 Device + * + *****************************************************************************/ +void pca9532_init (void) +{ + /* nothing to initialize */ +} + +/****************************************************************************** + * + * Description: + * Get the LED states + * + * Params: + * [in] shadow - TRUE if the states should be retrieved from the shadow + * variables. The shadow variable are updated when any + * of setLeds, setBlink0Leds and/or setBlink1Leds are + * called. + * + * FALSE if the state should be retrieved from the PCA9532 + * device. A blinkin LED may be reported as on or off + * depending on the state when calling the function. + * + * Returns: + * A mask where a 1 indicates that a LED is on (or blinking). + * + *****************************************************************************/ +uint16_t pca9532_getLedState (uint32_t shadow) +{ + uint8_t buf[2]; + uint16_t ret = 0; + + if (shadow) { + /* a blink LED is reported as on*/ + ret = (ledStateShadow | blink0Shadow | blink1Shadow); + } + else { + + /* + * A blinking LED may be reported as on or off depending on + * its state when reading the Input register. + */ + + buf[0] = PCA9532_INPUT0; + I2CWrite(PCA9532_I2C_ADDR, buf, 1); + + I2CRead(PCA9532_I2C_ADDR, buf, 1); + ret = buf[0]; + + + buf[0] = PCA9532_INPUT1; + I2CWrite(PCA9532_I2C_ADDR, buf, 1); + + I2CRead(PCA9532_I2C_ADDR, buf, 1); + ret |= (buf[0] << 8); + + + /* invert since LEDs are active low */ + ret = ((~ret) & 0xFFFF); + } + + return (ret & ~PCA9532_NOT_USED); +} + + +/****************************************************************************** + * + * Description: + * Set LED states (on or off). + * + * Params: + * [in] ledOnMask - The LEDs that should be turned on. This mask has + * priority over ledOffMask + * [in] ledOffMask - The LEDs that should be turned off. + * + *****************************************************************************/ +void pca9532_setLeds (uint16_t ledOnMask, uint16_t ledOffMask) +{ + /* turn off leds */ + ledStateShadow &= (~(ledOffMask) & 0xffff); + + /* ledOnMask has priority over ledOffMask */ + ledStateShadow |= ledOnMask; + + /* turn off blinking */ + blink0Shadow &= (~(ledOffMask) & 0xffff); + blink1Shadow &= (~(ledOffMask) & 0xffff); + + setLeds(); +} + +/****************************************************************************** + * + * Description: + * Set the blink period for PWM0. Valid values are 0 - 255 where 0 + * means 152 Hz and 255 means 0.59 Hz. A value of 151 means 1 Hz. + * + * Params: + * [in] period - the period for pwm0 + * + *****************************************************************************/ +void pca9532_setBlink0Period(uint8_t period) +{ + uint8_t buf[2]; + + buf[0] = PCA9532_PSC0; + buf[1] = period; + I2CWrite(PCA9532_I2C_ADDR, buf, 2); +} + +/****************************************************************************** + * + * Description: + * Set the duty cycle for PWM0. Valid values are 0 - 100. 25 means the LED + * is on 25% of the period. + * + * Params: + * [in] duty - duty cycle + * + *****************************************************************************/ +void pca9532_setBlink0Duty(uint8_t duty) +{ + uint8_t buf[2]; + uint32_t tmp = duty; + if (tmp > 100) { + tmp = 100; + } + + tmp = (256 * tmp)/100; + + buf[0] = PCA9532_PWM0; + buf[1] = tmp; + I2CWrite(PCA9532_I2C_ADDR, buf, 2); +} + +/****************************************************************************** + * + * Description: + * Set the LEDs that should blink with rate and duty cycle from PWM0. + * Blinking is turned off with pca9532_setLeds. + * + * Params: + * [in] ledMask - LEDs that should blink. + * + *****************************************************************************/ +void pca9532_setBlink0Leds(uint16_t ledMask) +{ + blink0Shadow |= ledMask; + setLeds(); +} + +/****************************************************************************** + * + * Description: + * Set the blink period for PWM1. Valid values are 0 - 255 where 0 + * means 152 Hz and 255 means 0.59 Hz. A value of 151 means 1 Hz. + * + * Params: + * [in] period - The period for PWM1 + * + *****************************************************************************/ +void pca9532_setBlink1Period(uint8_t period) +{ + uint8_t buf[2]; + + buf[0] = PCA9532_PSC1; + buf[1] = period; + I2CWrite(PCA9532_I2C_ADDR, buf, 2); +} + +/****************************************************************************** + * + * Description: + * Set the duty cycle for PWM1. Valid values are 0 - 100. 25 means the LED + * is on 25% of the period. + * + * Params: + * [in] duty - duty cycle. + * + *****************************************************************************/ +void pca9532_setBlink1Duty(uint8_t duty) +{ + uint8_t buf[2]; + + uint32_t tmp = duty; + if (tmp > 100) { + tmp = 100; + } + + tmp = (256 * tmp)/100; + + buf[0] = PCA9532_PWM1; + buf[1] = tmp; + I2CWrite(PCA9532_I2C_ADDR, buf, 2); +} + +/****************************************************************************** + * + * Description: + * Set the LEDs that should blink with rate and duty cycle from PWM1. + * Blinking is turned off with pca9532_setLeds. + * + * Params: + * [in] ledMask - LEDs that should blink. + * + *****************************************************************************/ +void pca9532_setBlink1Leds(uint16_t ledMask) +{ + blink1Shadow |= ledMask; + setLeds(); +} diff --git a/tinyusb/hw/bsp/ea4357/pca9532.h b/tinyusb/hw/bsp/ea4357/pca9532.h new file mode 100755 index 00000000..7a7c6e14 --- /dev/null +++ b/tinyusb/hw/bsp/ea4357/pca9532.h @@ -0,0 +1,94 @@ +/***************************************************************************** + * + * Copyright(C) 2011, Embedded Artists AB + * All rights reserved. + * + ****************************************************************************** + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * products. This software is supplied "AS IS" without any warranties. + * Embedded Artists AB assumes no responsibility or liability for the + * use of the software, conveys no license or title under any patent, + * copyright, or mask work right to the product. Embedded Artists AB + * reserves the right to make changes in the software without + * notification. Embedded Artists AB also make no representation or + * warranty that such application will be suitable for the specified + * use without further testing or modification. + *****************************************************************************/ +#ifndef __PCA9532C_H +#define __PCA9532C_H + + +#define PCA9532_I2C_ADDR (0xC0>>1) + +#define PCA9532_INPUT0 0x00 +#define PCA9532_INPUT1 0x01 +#define PCA9532_PSC0 0x02 +#define PCA9532_PWM0 0x03 +#define PCA9532_PSC1 0x04 +#define PCA9532_PWM1 0x05 +#define PCA9532_LS0 0x06 +#define PCA9532_LS1 0x07 +#define PCA9532_LS2 0x08 +#define PCA9532_LS3 0x09 + +#define PCA9532_AUTO_INC 0x10 + + +/* + * The Keys on the base board are mapped to LED0 -> LED3 on + * the PCA9532. + */ + +#define KEY1 0x0001 +#define KEY2 0x0002 +#define KEY3 0x0004 +#define KEY4 0x0008 + +#define KEY_MASK 0x000F + +/* + * MMC Card Detect and MMC Write Protect are mapped to LED4 + * and LED5 on the PCA9532. Please note that WP is active low. + */ + +#define MMC_CD 0x0010 +#define MMC_WP 0x0020 + +#define MMC_MASK 0x30 + +/* NOTE: LED6 and LED7 on PCA9532 are not connected to anything */ +#define PCA9532_NOT_USED 0xC0 + +/* + * Below are the LED constants to use when enabling/disabling a LED. + * The LED names are the names printed on the base board and not + * the names from the PCA9532 device. base_LED1 -> LED8 on PCA9532, + * base_LED2 -> LED9, and so on. + */ + +#define LED1 0x0100 +#define LED2 0x0200 +#define LED3 0x0400 +#define LED4 0x0800 +#define LED5 0x1000 +#define LED6 0x2000 +#define LED7 0x4000 +#define LED8 0x8000 + +#define LED_MASK 0xFF00 + +void pca9532_init (void); +uint16_t pca9532_getLedState (uint32_t shadow); +void pca9532_setLeds (uint16_t ledOnMask, uint16_t ledOffMask); +void pca9532_setBlink0Period(uint8_t period); +void pca9532_setBlink0Duty(uint8_t duty); +void pca9532_setBlink0Leds(uint16_t ledMask); +void pca9532_setBlink1Period(uint8_t period); +void pca9532_setBlink1Duty(uint8_t duty); +void pca9532_setBlink1Leds(uint16_t ledMask); + +#endif /* end __PCA9532C_H */ +/**************************************************************************** +** End Of File +*****************************************************************************/ -- cgit v1.2.3