mirror of
https://gitea.tendokyu.moe/tasoller/host-aprom.git
synced 2025-02-17 10:58:39 +01:00
Initial commit
This commit is contained in:
commit
81873aa1ec
6
.clang-format
Normal file
6
.clang-format
Normal file
@ -0,0 +1,6 @@
|
||||
BasedOnStyle: Google
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Custom
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 100
|
||||
Cpp11BracedListStyle: false
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Picolibc
|
||||
picolibc/*
|
||||
# Misc testing files
|
||||
*.py
|
||||
# Build artifacts
|
||||
obj/*
|
||||
host_aprom.bin
|
11
.vscode/c_cpp_properties.json
vendored
Normal file
11
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "GCC",
|
||||
"includePath": ["C:/Program Files (x86)/Arm GNU Toolchain arm-none-eabi/13.2 Rel1/arm-none-eabi/include", "NUC123/inc", "NUC123/StdDriver/inc"],
|
||||
"defines": [],
|
||||
"intelliSenseMode": "gcc-arm"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"aaron-bond.better-comments",
|
||||
"marus25.cortex-debug",
|
||||
"llvm-vs-code-extensions.vscode-clangd"
|
||||
]
|
||||
}
|
18
.vscode/launch.json
vendored
Normal file
18
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Host APROM Debug",
|
||||
"preLaunchTask": "Build Host APROM",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"executable": "./obj/host_aprom.elf",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"runToEntryPoint": "_start",
|
||||
"servertype": "openocd",
|
||||
"serverpath": "../../openocd-0.12.0-3/bin/openocd",
|
||||
"configFiles": ["interface/stlink-v2.cfg", "../../nucxxx.cfg"],
|
||||
"showDevDebugOutput": "raw",
|
||||
}
|
||||
]
|
||||
}
|
16
.vscode/settings.json
vendored
Normal file
16
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"clangd.arguments": ["--query-driver=*arm-none-eabi-*"],
|
||||
"clangd.fallbackFlags": [
|
||||
"-IC:/Program Files (x86)/GNU Arm Embedded Toolchain/13.2 Rel1/arm-none-eabi/include",
|
||||
"-I${workspaceFolder}/NUC123/inc",
|
||||
"-I${workspaceFolder}/NUC123/StdDriver/inc",
|
||||
"-D__GNUC__",
|
||||
"-Wno-pointer-to-int-cast",
|
||||
"-Wno-int-to-pointer-cast",
|
||||
],
|
||||
"cortex-debug.variableUseNaturalFormat": true,
|
||||
"cortex-debug.liveWatchRefreshRate": 1000,
|
||||
"cortex-debug.enableTelemetry": false,
|
||||
"files.trimFinalNewlines": true,
|
||||
"editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd",
|
||||
}
|
19
.vscode/tasks.json
vendored
Normal file
19
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build Host APROM",
|
||||
"command": "make",
|
||||
"args": [
|
||||
"-j",
|
||||
"all"
|
||||
],
|
||||
"type": "shell",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
27
Development.md
Normal file
27
Development.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Development
|
||||
## Requirements
|
||||
- Windows (Strongly recommend. Compiling on anything else is not officially supported.)
|
||||
- [Make for Windows](https://gnuwin32.sourceforge.net/packages/make.htm)
|
||||
- On the path, please
|
||||
- [Arm GNU Toolchain](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads) (Currently using 13.2 Rel1)
|
||||
- To make your life easier, ensure this is located at `C:\Program Files (x86)\GNU Arm Embedded Toolchain\13.2 Rel1`
|
||||
- [picolibc 1.8.6](https://github.com/picolibc/picolibc/releases/download/1.8.6/picolibc-1.8.6-13.2.Rel1.zip)
|
||||
- Place the contents of this zip file in `picolibc`
|
||||
|
||||
VSCode is recommended for development, and all recommended extensions should be installed.
|
||||
|
||||
## Compiling and Uploading
|
||||
Run `make -j` to compile the firmware.
|
||||
|
||||
For rapid development, the HID bootloader is quite annoying. `flash.cmd` is provided which reprograms the chip using an ST-Link V2. This requires an OpenOCD installation in the root project folder, along with an existing compiled host bootloader binary.
|
||||
|
||||
For debugging in VSCode, install the recommended extensions then hit F5. This requires an OpenOCD installation in the root project folder, and an ST-Link V2.
|
||||
|
||||
## NUC123 BSP
|
||||
The `NUC123` folder is a heavily reduced form of the complete BSP provided by Nuvoton. Modifications should not be made to any files within the `inc` or `StdDriver` folder.
|
||||
|
||||
`startup_NUC123.s` is the program entrypoint, and may require modification.
|
||||
|
||||
`NUC123.ld` is a modified version of the GCC linker script provided by Nuvoton, and may require modification.
|
||||
|
||||
To pull in additional BSP library modules, if required, the `Makefile` should be modified.
|
21
GCC.mk
Normal file
21
GCC.mk
Normal file
@ -0,0 +1,21 @@
|
||||
PREFIX = arm-none-eabi-
|
||||
CC = $(PREFIX)gcc
|
||||
CXX = $(PREFIX)g++
|
||||
AS = $(PREFIX)gcc # Rather than AS, so we get preprocessing
|
||||
AR = $(PREFIX)ar
|
||||
LD = $(PREFIX)gcc # To pull in stdlib as needed
|
||||
OBJCOPY = $(PREFIX)objcopy
|
||||
OBJDUMP = $(PREFIX)objdump
|
||||
SIZE = $(PREFIX)size
|
||||
|
||||
SPECS := -specs=./picolibc/lib/gcc/arm-none-eabi/13.2.1/picolibc.specs
|
||||
|
||||
INCLUDES += -I./picolibc/arm-none-eabi/picolibc/arm-none-eabi/include
|
||||
|
||||
OPTIM ?= -flto -Os
|
||||
GCCFLAGS := $(SPECS) -nolibc -nostdlib -nostartfiles -nodefaultlibs -mcpu=cortex-m0 -mthumb -Wl,--gc-sections $(OPTIM) -g
|
||||
|
||||
CFLAGS := $(GCCFLAGS) -c -ffunction-sections -fdata-sections -fsigned-char \
|
||||
-fmessage-length=0 -ffreestanding
|
||||
ASFLAGS := $(GCCFLAGS) -c -x assembler-with-cpp
|
||||
LDFLAGS := $(GCCFLAGS) -Lpicolibc/arm-none-eabi/picolibc/arm-none-eabi/lib/thumb/v6-m/nofp
|
14
Makefile
Normal file
14
Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
SRC_DIR := src
|
||||
OBJ_DIR := obj
|
||||
BINARY_NAME := host_aprom
|
||||
|
||||
OPTIM := -O0
|
||||
# OPTIM := -Ofast -flto
|
||||
# OPTIM := -Os -flto
|
||||
include GCC.mk
|
||||
LIBRARY_MODULES := clk uart timer i2c
|
||||
include NUC123/NUC123.mk
|
||||
|
||||
CFLAGS += -Wno-gnu-variable-sized-type-not-at-end
|
||||
|
||||
include generic.mk
|
165
NUC123/NUC123.ld
Normal file
165
NUC123/NUC123.ld
Normal file
@ -0,0 +1,165 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x10000 /* 64k */
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x5000 /* 20k */
|
||||
}
|
||||
|
||||
/* Library configurations */
|
||||
GROUP(libgcc.a libc.a libm.a libnosys.a)
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
* __Vectors_End
|
||||
* __Vectors_Size
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.vectors))
|
||||
__Vectors_End = .;
|
||||
__Vectors_Size = __Vectors_End - __Vectors;
|
||||
__end__ = .;
|
||||
|
||||
. = . + 16;
|
||||
|
||||
*(.text*)
|
||||
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
KEEP(*(.eh_frame*))
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__etext = .;
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
KEEP(*(.jcr*))
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__HeapBase = .;
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
KEEP(*(.heap*))
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
KEEP(*(.stack*))
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
32
NUC123/NUC123.mk
Normal file
32
NUC123/NUC123.mk
Normal file
@ -0,0 +1,32 @@
|
||||
SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
INCLUDES += -I${SELF_DIR}inc
|
||||
INCLUDES += -I${SELF_DIR}StdDriver/inc
|
||||
|
||||
LDFLAGS += -T ${SELF_DIR}NUC123.ld
|
||||
|
||||
$(OBJ_DIR)/startup_NUC123.o: $(SELF_DIR)startup_NUC123.s
|
||||
@echo Compiling $<
|
||||
@$(AS) $(ASFLAGS) -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/system_NUC123.o: $(SELF_DIR)system_NUC123.c
|
||||
@echo Compiling $<
|
||||
@$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/_syscalls.o: $(SELF_DIR)_syscalls.c
|
||||
@echo Compiling $<
|
||||
@$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
.PRECIOUS: $(OBJ_DIR)/NUC123_%.o
|
||||
$(OBJ_DIR)/NUC123_%.o: $(SELF_DIR)StdDriver/src/%.c
|
||||
@echo Compiling $<
|
||||
@$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
DEVICE_OBJECTS :=
|
||||
DEVICE_OBJECTS += $(OBJ_DIR)/system_NUC123.o
|
||||
ifneq ($(USE_CUSTOM_STARTUP_ASSEMBLY), 1)
|
||||
DEVICE_OBJECTS += $(OBJ_DIR)/startup_NUC123.o
|
||||
endif
|
||||
DEVICE_OBJECTS += $(OBJ_DIR)/_syscalls.o
|
||||
|
||||
$(foreach module,$(LIBRARY_MODULES),$(eval DEVICE_OBJECTS += $(OBJ_DIR)/NUC123_$(module).o))
|
786
NUC123/NUC123.svd
Normal file
786
NUC123/NUC123.svd
Normal file
@ -0,0 +1,786 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- File naming: <part/series name>.svd -->
|
||||
|
||||
<!--
|
||||
Copyright (C) 2012-2014 ARM Limited. All rights reserved.
|
||||
|
||||
Purpose: System Viewer Description (SVD) Example (Schema Version 1.1)
|
||||
This is a description of a none-existent and incomplete device
|
||||
for demonstration purposes only.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- 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.
|
||||
- Neither the name of ARM 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 AND CONTRIBUTORS "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 COPYRIGHT HOLDERS AND CONTRIBUTORS 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.
|
||||
-->
|
||||
|
||||
<device schemaVersion="1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" >
|
||||
<vendor>ARM Ltd.</vendor> <!-- device vendor name -->
|
||||
<vendorID>ARM</vendorID> <!-- device vendor short name -->
|
||||
<name>ARM_Example</name> <!-- name of part-->
|
||||
<series>ARMCM3</series> <!-- device series the device belongs to -->
|
||||
<version>1.2</version> <!-- version of this description, adding CMSIS-SVD 1.1 tags -->
|
||||
<description>ARM 32-bit Cortex-M3 Microcontroller based device, CPU clock up to 80MHz, etc. </description>
|
||||
<licenseText> <!-- this license text will appear in header file. \n force line breaks -->
|
||||
ARM Limited (ARM) is supplying this software for use with Cortex-M\n
|
||||
processor based microcontroller, but can be equally used for other\n
|
||||
suitable processor architectures. This file can be freely distributed.\n
|
||||
Modifications to this file shall be clearly marked.\n
|
||||
\n
|
||||
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED\n
|
||||
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF\n
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.\n
|
||||
ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR\n
|
||||
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
</licenseText>
|
||||
<cpu> <!-- details about the cpu embedded in the device -->
|
||||
<name>CM3</name>
|
||||
<revision>r1p0</revision>
|
||||
<endian>little</endian>
|
||||
<mpuPresent>true</mpuPresent>
|
||||
<fpuPresent>false</fpuPresent>
|
||||
<nvicPrioBits>3</nvicPrioBits>
|
||||
<vendorSystickConfig>false</vendorSystickConfig>
|
||||
</cpu>
|
||||
<addressUnitBits>8</addressUnitBits> <!-- byte addressable memory -->
|
||||
<width>32</width> <!-- bus width is 32 bits -->
|
||||
<!-- default settings implicitly inherited by subsequent sections -->
|
||||
<size>32</size> <!-- this is the default size (number of bits) of all peripherals
|
||||
and register that do not define "size" themselves -->
|
||||
<access>read-write</access> <!-- default access permission for all subsequent registers -->
|
||||
<resetValue>0x00000000</resetValue> <!-- by default all bits of the registers are initialized to 0 on reset -->
|
||||
<resetMask>0xFFFFFFFF</resetMask> <!-- by default all 32Bits of the registers are used -->
|
||||
|
||||
<peripherals>
|
||||
<!-- Timer 0 -->
|
||||
<peripheral>
|
||||
<name>TIMER0</name>
|
||||
<version>1.0</version>
|
||||
<description>32 Timer / Counter, counting up or down from different sources</description>
|
||||
<groupName>TIMER</groupName>
|
||||
<baseAddress>0x40010000</baseAddress>
|
||||
<size>32</size>
|
||||
<access>read-write</access>
|
||||
|
||||
<addressBlock>
|
||||
<offset>0</offset>
|
||||
<size>0x100</size>
|
||||
<usage>registers</usage>
|
||||
</addressBlock>
|
||||
|
||||
<interrupt>
|
||||
<name>TIMER0</name>
|
||||
<value>0</value>
|
||||
</interrupt>
|
||||
|
||||
<registers>
|
||||
<!-- CR: Control Register -->
|
||||
<register>
|
||||
<name>CR</name>
|
||||
<description>Control Register</description>
|
||||
<addressOffset>0x00</addressOffset>
|
||||
<size>32</size>
|
||||
<access>read-write</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0x1337F7F</resetMask>
|
||||
|
||||
<fields>
|
||||
<!-- EN: Enable -->
|
||||
<field>
|
||||
<name>EN</name>
|
||||
<description>Enable</description>
|
||||
<bitRange>[0:0]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Disable</name>
|
||||
<description>Timer is disabled and does not operate</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Enable</name>
|
||||
<description>Timer is enabled and can operate</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- RST: Reset -->
|
||||
<field>
|
||||
<name>RST</name>
|
||||
<description>Reset Timer</description>
|
||||
<bitRange>[1:1]</bitRange>
|
||||
<access>write-only</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>No_Action</name>
|
||||
<description>Write as ZERO if necessary</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Reset_Timer</name>
|
||||
<description>Reset the Timer</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- CNT: Counting Direction -->
|
||||
<field>
|
||||
<name>CNT</name>
|
||||
<description>Counting direction</description>
|
||||
<bitRange>[3:2]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Count_UP</name>
|
||||
<description>Timer Counts UO and wraps, if no STOP condition is set</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Count_DOWN</name>
|
||||
<description>Timer Counts DOWN and wraps, if no STOP condition is set</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Toggle</name>
|
||||
<description>Timer Counts up to MAX, then DOWN to ZERO, if no STOP condition is set</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- MODE: Operation Mode -->
|
||||
<field>
|
||||
<name>MODE</name>
|
||||
<description>Operation Mode</description>
|
||||
<bitRange>[6:4]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Continous</name>
|
||||
<description>Timer runs continously</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Single_ZERO_MAX</name>
|
||||
<description>Timer counts to 0x00 or 0xFFFFFFFF (depending on CNT) and stops</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Single_MATCH</name>
|
||||
<description>Timer counts to the Value of MATCH Register and stops</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Reload_ZERO_MAX</name>
|
||||
<description>Timer counts to 0x00 or 0xFFFFFFFF (depending on CNT), loads the RELOAD Value and continues</description>
|
||||
<value>3</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Reload_MATCH</name>
|
||||
<description>Timer counts to the Value of MATCH Register, loads the RELOAD Value and continues</description>
|
||||
<value>4</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- PSC: Use Prescaler -->
|
||||
<field>
|
||||
<name>PSC</name>
|
||||
<description>Use Prescaler</description>
|
||||
<bitRange>[7:7]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Disabled</name>
|
||||
<description>Prescaler is not used</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Enabled</name>
|
||||
<description>Prescaler is used as divider</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- CNTSRC: Timer / Counter Soruce Divider -->
|
||||
<field>
|
||||
<name>CNTSRC</name>
|
||||
<description>Timer / Counter Source Divider</description>
|
||||
<bitRange>[11:8]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC</name>
|
||||
<description>Capture Source is used directly</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div2</name>
|
||||
<description>Capture Source is divided by 2</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div4</name>
|
||||
<description>Capture Source is divided by 4</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div8</name>
|
||||
<description>Capture Source is divided by 8</description>
|
||||
<value>3</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div16</name>
|
||||
<description>Capture Source is divided by 16</description>
|
||||
<value>4</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div32</name>
|
||||
<description>Capture Source is divided by 32</description>
|
||||
<value>5</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div64</name>
|
||||
<description>Capture Source is divided by 64</description>
|
||||
<value>6</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div128</name>
|
||||
<description>Capture Source is divided by 128</description>
|
||||
<value>7</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>CAP_SRC_div256</name>
|
||||
<description>Capture Source is divided by 256</description>
|
||||
<value>8</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- CAPSRC: Timer / COunter Capture Source -->
|
||||
<field>
|
||||
<name>CAPSRC</name>
|
||||
<description>Timer / Counter Capture Source</description>
|
||||
<bitRange>[15:12]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>CClk</name>
|
||||
<description>Core Clock</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_0</name>
|
||||
<description>GPIO A, PIN 0</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_1</name>
|
||||
<description>GPIO A, PIN 1</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_2</name>
|
||||
<description>GPIO A, PIN 2</description>
|
||||
<value>3</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_3</name>
|
||||
<description>GPIO A, PIN 3</description>
|
||||
<value>4</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_4</name>
|
||||
<description>GPIO A, PIN 4</description>
|
||||
<value>5</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_5</name>
|
||||
<description>GPIO A, PIN 5</description>
|
||||
<value>6</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_6</name>
|
||||
<description>GPIO A, PIN 6</description>
|
||||
<value>7</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOA_7</name>
|
||||
<description>GPIO A, PIN 7</description>
|
||||
<value>8</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOB_0</name>
|
||||
<description>GPIO B, PIN 0</description>
|
||||
<value>9</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOB_1</name>
|
||||
<description>GPIO B, PIN 1</description>
|
||||
<value>10</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOB_2</name>
|
||||
<description>GPIO B, PIN 2</description>
|
||||
<value>11</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOB_3</name>
|
||||
<description>GPIO B, PIN 3</description>
|
||||
<value>12</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOC_0</name>
|
||||
<description>GPIO C, PIN 0</description>
|
||||
<value>13</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOC_5</name>
|
||||
<description>GPIO C, PIN 1</description>
|
||||
<value>14</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>GPIOC_6</name>
|
||||
<description>GPIO C, PIN 2</description>
|
||||
<value>15</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- CAPEDGE: Capture Edge -->
|
||||
<field>
|
||||
<name>CAPEDGE</name>
|
||||
<description>Capture Edge, select which Edge should result in a counter increment or decrement</description>
|
||||
<bitRange>[17:16]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>RISING</name>
|
||||
<description>Only rising edges result in a counter increment or decrement</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>FALLING</name>
|
||||
<description>Only falling edges result in a counter increment or decrement</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>BOTH</name>
|
||||
<description>Rising and falling edges result in a counter increment or decrement</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- TRGEXT: Triggers an other Peripheral -->
|
||||
<field>
|
||||
<name>TRGEXT</name>
|
||||
<description>Triggers an other Peripheral</description>
|
||||
<bitRange>[21:20]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>NONE</name>
|
||||
<description>No Trigger is emitted</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>DMA1</name>
|
||||
<description>DMA Controller 1 is triggered, dependant on MODE</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>DMA2</name>
|
||||
<description>DMA Controller 2 is triggered, dependant on MODE</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>UART</name>
|
||||
<description>UART is triggered, dependant on MODE</description>
|
||||
<value>3</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- Reload: Selects Reload Register n -->
|
||||
<field>
|
||||
<name>RELOAD</name>
|
||||
<description>Select RELOAD Register n to reload Timer on condition</description>
|
||||
<bitRange>[25:24]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD0</name>
|
||||
<description>Selects Reload Register number 0</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD1</name>
|
||||
<description>Selects Reload Register number 1</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD2</name>
|
||||
<description>Selects Reload Register number 2</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD3</name>
|
||||
<description>Selects Reload Register number 3</description>
|
||||
<value>3</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- IDR: Inc or dec Reload Register Selection -->
|
||||
<field>
|
||||
<name>IDR</name>
|
||||
<description>Selects, if Reload Register number is incremented, decremented or not modified</description>
|
||||
<bitRange>[27:26]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>KEEP</name>
|
||||
<description>Reload Register number does not change automatically</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>INCREMENT</name>
|
||||
<description>Reload Register number is incremented on each match</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>DECREMENT</name>
|
||||
<description>Reload Register number is decremented on each match</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- START: Starts / Stops the Timer/Counter -->
|
||||
<field>
|
||||
<name>S</name>
|
||||
<description>Starts and Stops the Timer / Counter</description>
|
||||
<bitRange>[31:31]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>STOP</name>
|
||||
<description>Timer / Counter is stopped</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>START</name>
|
||||
<description>Timer / Counter is started</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
|
||||
<!-- SR: Status Register -->
|
||||
<register>
|
||||
<name>SR</name>
|
||||
<description>Status Register</description>
|
||||
<addressOffset>0x04</addressOffset>
|
||||
<size>16</size>
|
||||
<access>read-write</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0xD701</resetMask>
|
||||
|
||||
<fields>
|
||||
<!-- RUN: Shows if Timer is running -->
|
||||
<field>
|
||||
<name>RUN</name>
|
||||
<description>Shows if Timer is running or not</description>
|
||||
<bitRange>[0:0]</bitRange>
|
||||
<access>read-only</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Stopped</name>
|
||||
<description>Timer is not running</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Running</name>
|
||||
<description>Timer is running</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- MATCH: Shows if a Match was hit -->
|
||||
<field>
|
||||
<name>MATCH</name>
|
||||
<description>Shows if the MATCH was hit</description>
|
||||
<bitRange>[8:8]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>No_Match</name>
|
||||
<description>The MATCH condition was not hit</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Match_Hit</name>
|
||||
<description>The MATCH condition was hit</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- UN: Shows if an underflow occured -->
|
||||
<field>
|
||||
<name>UN</name>
|
||||
<description>Shows if an underflow occured. This flag is sticky</description>
|
||||
<bitRange>[9:9]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>No_Underflow</name>
|
||||
<description>No underflow occured since last clear</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Underflow</name>
|
||||
<description>A minimum of one underflow occured since last clear</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- OV: Shows if an overflow occured -->
|
||||
<field>
|
||||
<name>OV</name>
|
||||
<description>Shows if an overflow occured. This flag is sticky</description>
|
||||
<bitRange>[10:10]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>No_Overflow</name>
|
||||
<description>No overflow occured since last clear</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Overflow_occured</name>
|
||||
<description>A minimum of one overflow occured since last clear</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- RST: Shows if Timer is in RESET state -->
|
||||
<field>
|
||||
<name>RST</name>
|
||||
<description>Shows if Timer is in RESET state</description>
|
||||
<bitRange>[12:12]</bitRange>
|
||||
<access>read-only</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Ready</name>
|
||||
<description>Timer is not in RESET state and can operate</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>In_Reset</name>
|
||||
<description>Timer is in RESET state and can not operate</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- RELOAD: Shows the currently active Reload Register -->
|
||||
<field>
|
||||
<name>RELOAD</name>
|
||||
<description>Shows the currently active RELOAD Register</description>
|
||||
<bitRange>[15:14]</bitRange>
|
||||
<access>read-only</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD0</name>
|
||||
<description>Reload Register number 0 is active</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD1</name>
|
||||
<description>Reload Register number 1 is active</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD2</name>
|
||||
<description>Reload Register number 2 is active</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>RELOAD3</name>
|
||||
<description>Reload Register number 3 is active</description>
|
||||
<value>3</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
|
||||
<!-- INT: Interrupt Register -->
|
||||
<register>
|
||||
<name>INT</name>
|
||||
<description>Interrupt Register</description>
|
||||
<addressOffset>0x10</addressOffset>
|
||||
<size>16</size>
|
||||
<access>read-write</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0x0771</resetMask>
|
||||
|
||||
<fields>
|
||||
<!-- EN: Interrupt Enable -->
|
||||
<field>
|
||||
<name>EN</name>
|
||||
<description>Interrupt Enable</description>
|
||||
<bitRange>[0:0]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Disabled</name>
|
||||
<description>Timer does not generate Interrupts</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Enable</name>
|
||||
<description>Timer triggers the TIMERn Interrupt</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
|
||||
<!-- MODE: Interrupt Mode -->
|
||||
<field>
|
||||
<name>MODE</name>
|
||||
<description>Interrupt Mode, selects on which condition the Timer should generate an Interrupt</description>
|
||||
<bitRange>[6:4]</bitRange>
|
||||
<access>read-write</access>
|
||||
<enumeratedValues>
|
||||
<enumeratedValue>
|
||||
<name>Match</name>
|
||||
<description>Timer generates an Interrupt when the MATCH condition is hit</description>
|
||||
<value>0</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Underflow</name>
|
||||
<description>Timer generates an Interrupt when it underflows</description>
|
||||
<value>1</value>
|
||||
</enumeratedValue>
|
||||
<enumeratedValue>
|
||||
<name>Overflow</name>
|
||||
<description>Timer generates an Interrupt when it overflows</description>
|
||||
<value>2</value>
|
||||
</enumeratedValue>
|
||||
</enumeratedValues>
|
||||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
|
||||
<!-- COUNT: Counter Register -->
|
||||
<register>
|
||||
<name>COUNT</name>
|
||||
<description>The Counter Register reflects the actual Value of the Timer/Counter</description>
|
||||
<addressOffset>0x20</addressOffset>
|
||||
<size>32</size>
|
||||
<access>read-write</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0xFFFFFFFF</resetMask>
|
||||
</register>
|
||||
|
||||
<!-- MATCH: Match Register -->
|
||||
<register>
|
||||
<name>MATCH</name>
|
||||
<description>The Match Register stores the compare Value for the MATCH condition</description>
|
||||
<addressOffset>0x24</addressOffset>
|
||||
<size>32</size>
|
||||
<access>read-write</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0xFFFFFFFF</resetMask>
|
||||
</register>
|
||||
|
||||
<!-- PRESCALE: Prescale Read Register -->
|
||||
<register>
|
||||
<name>PRESCALE_RD</name>
|
||||
<description>The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value</description>
|
||||
<addressOffset>0x28</addressOffset>
|
||||
<size>32</size>
|
||||
<access>read-only</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0xFFFFFFFF</resetMask>
|
||||
</register>
|
||||
|
||||
<!-- PRESCALE: Prescale Write Register -->
|
||||
<register>
|
||||
<name>PRESCALE_WR</name>
|
||||
<description>The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value</description>
|
||||
<addressOffset>0x28</addressOffset>
|
||||
<size>32</size>
|
||||
<access>write-only</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0xFFFFFFFF</resetMask>
|
||||
</register>
|
||||
|
||||
|
||||
<!-- RELOAD: Array of Reload Register with 4 elements-->
|
||||
<register>
|
||||
<dim>4</dim>
|
||||
<dimIncrement>4</dimIncrement>
|
||||
<dimIndex>0,1,2,3</dimIndex>
|
||||
<name>RELOAD[%s]</name>
|
||||
<description>The Reload Register stores the Value the COUNT Register gets reloaded on a when a condition was met.</description>
|
||||
<addressOffset>0x50</addressOffset>
|
||||
<size>32</size>
|
||||
<access>read-write</access>
|
||||
<resetValue>0x00000000</resetValue>
|
||||
<resetMask>0xFFFFFFFF</resetMask>
|
||||
</register>
|
||||
</registers>
|
||||
</peripheral>
|
||||
|
||||
<!-- Timer 1 -->
|
||||
<peripheral derivedFrom="TIMER0">
|
||||
<name>TIMER1</name>
|
||||
<baseAddress>0x40010100</baseAddress>
|
||||
<interrupt>
|
||||
<name>TIMER1</name>
|
||||
<value>4</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
|
||||
<!-- Timer 2 -->
|
||||
<peripheral derivedFrom="TIMER0">
|
||||
<name>TIMER2</name>
|
||||
<baseAddress>0x40010200</baseAddress>
|
||||
<interrupt>
|
||||
<name>TIMER2</name>
|
||||
<value>6</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
</peripherals>
|
||||
</device>
|
343
NUC123/StdDriver/inc/adc.h
Normal file
343
NUC123/StdDriver/inc/adc.h
Normal file
@ -0,0 +1,343 @@
|
||||
/**************************************************************************//**
|
||||
* @file adc.h
|
||||
* @version V3.00
|
||||
* $Revision: 7 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series ADC Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __ADC_H__
|
||||
#define __ADC_H__
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup ADC_Driver ADC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup ADC_EXPORTED_CONSTANTS ADC Exported Constants
|
||||
@{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ADCR Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_ADCR_ADEN_CONVERTER_DISABLE (0UL<<ADC_ADCR_ADEN_Pos) /*!< ADC converter disable */
|
||||
#define ADC_ADCR_ADEN_CONVERTER_ENABLE (1UL<<ADC_ADCR_ADEN_Pos) /*!< ADC converter enable */
|
||||
|
||||
#define ADC_ADCR_ADMD_SINGLE (0UL<<ADC_ADCR_ADMD_Pos) /*!< Single mode */
|
||||
#define ADC_ADCR_ADMD_SINGLE_CYCLE (2UL<<ADC_ADCR_ADMD_Pos) /*!< Single cycle scan mode */
|
||||
#define ADC_ADCR_ADMD_CONTINUOUS (3UL<<ADC_ADCR_ADMD_Pos) /*!< Continuous scan mode */
|
||||
|
||||
#define ADC_ADCR_TRGEN_DISABLE (0UL<<ADC_ADCR_TRGEN_Pos) /*!< Disable triggering of A/D conversion by external STADC pin or PWM */
|
||||
#define ADC_ADCR_TRGEN_ENABLE (1UL<<ADC_ADCR_TRGEN_Pos) /*!< Enable triggering of A/D conversion by external STADC pin or PWM */
|
||||
|
||||
#define ADC_ADCR_TRGS_STADC (0UL<<ADC_ADCR_TRGS_Pos) /*!< A/D conversion is started by external STADC pin */
|
||||
#define ADC_ADCR_TRGS_PWM (3UL<<ADC_ADCR_TRGS_Pos) /*!< A/D conversion is started by PWM */
|
||||
|
||||
#define ADC_ADCR_TRGCOND_LOW_LEVEL (0UL<<ADC_ADCR_TRGCOND_Pos) /*!< STADC Low level active */
|
||||
#define ADC_ADCR_TRGCOND_HIGH_LEVEL (1UL<<ADC_ADCR_TRGCOND_Pos) /*!< STADC High level active */
|
||||
#define ADC_ADCR_TRGCOND_FALLING_EDGE (2UL<<ADC_ADCR_TRGCOND_Pos) /*!< STADC Falling edge active */
|
||||
#define ADC_ADCR_TRGCOND_RISING_EDGE (3UL<<ADC_ADCR_TRGCOND_Pos) /*!< STADC Rising edge active */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ADCHER Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_ADCHER_PRESEL_EXT_INPUT_SIGNAL (0UL<<ADC_ADCHER_PRESEL_Pos) /*!< The input source of channel 7 is the external analog input */
|
||||
#define ADC_ADCHER_PRESEL_INT_BANDGAP (1UL<<ADC_ADCHER_PRESEL_Pos) /*!< The input source of channel 7 is the internal bandgap voltage */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ADCMPR Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_ADCMPR_CMPD(x) ((x) << ADC_ADCMPR_CMPD_Pos) /*!< Compare value for compare function */
|
||||
#define ADC_ADCMPR_CMPMATCNT(x) (((x)-1) << ADC_ADCMPR_CMPMATCNT_Pos) /*!< Match count for compare function */
|
||||
#define ADC_ADCMPR_CMPCH(x) ((x) << ADC_ADCMPR_CMPCH_Pos) /*!< Compare channel for compare function */
|
||||
#define ADC_ADCMPR_CMPCOND_LESS_THAN (0<<ADC_ADCMPR_CMPCOND_Pos) /*!< The compare condition is "less than" */
|
||||
#define ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL (1<<ADC_ADCMPR_CMPCOND_Pos) /*!< The compare condition is "greater than or equal to" */
|
||||
#define ADC_ADCMPR_CMPIE_INTERRUPT_ENABLE (ADC_ADCMPR_CMPIE_Msk) /*!< The compare function interrupt enable */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ADC Interrupt Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_ADF_INT (ADC_ADSR_ADF_Msk) /*!< ADC convert complete interrupt */
|
||||
#define ADC_CMP0_INT (ADC_ADSR_CMPF0_Msk) /*!< ADC comparator 0 interrupt */
|
||||
#define ADC_CMP1_INT (ADC_ADSR_CMPF1_Msk) /*!< ADC comparator 1 interrupt */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ADC Operation Mode Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_SINGLE_MODE 0 /*!< ADC single mode */
|
||||
#define ADC_SINGLE_CYCLE_MODE 2 /*!< ADC single-cycle scan mode */
|
||||
#define ADC_CONTINUOUS_MODE 3 /*!< ADC continuous scan mode */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ADC Trigger Condition Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_LOW_LEVEL 0 /*!< ADC external trigger condition is low level trigger */
|
||||
#define ADC_HIGH_LEVEL 1 /*!< ADC external trigger condition is high level trigger */
|
||||
#define ADC_FALLING_EDGE 2 /*!< ADC external trigger condition is falling edge trigger */
|
||||
#define ADC_RISING_EDGE 3 /*!< ADC external trigger condition is rising edge trigger */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ADC Compare Condition Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_LESS_THAN 0 /*!< ADC compare condition is "less than the compare value" */
|
||||
#define ADC_GREATER_OR_EQUAL 1 /*!< ADC compare condition is "greater than or equal to the compare value" */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Constant Definitions of ADC Channel 7 Input Source */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define ADC_CH7_EXT_INPUT_SIGNAL 0 /*!< External input signal */
|
||||
#define ADC_CH7_INT_BANDGAP 1 /*!< Internal band-gap voltage */
|
||||
|
||||
|
||||
/*@}*/ /* end of group ADC_EXPORTED_CONSTANTS */
|
||||
|
||||
/** @addtogroup ADC_EXPORTED_FUNCTIONS ADC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configure the analog input source of channel 7.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32Source Decides the analog input source of channel 7. Valid values are:
|
||||
* - \ref ADC_ADCHER_PRESEL_EXT_INPUT_SIGNAL : External analog input.
|
||||
* - \ref ADC_ADCHER_PRESEL_INT_BANDGAP : Internal bandgap voltage.
|
||||
* @return None
|
||||
* @details Channel 7 supports 2 input sources: External analog voltage, and internal Band-gap voltage.
|
||||
* @note While using VBG as channel 7 source, ADC module clock must /b not exceed 300kHz.
|
||||
*/
|
||||
#define ADC_CONFIG_CH7(adc, u32Source) ((adc)->ADCHER = ((adc)->ADCHER & ~ADC_ADCHER_PRESEL_Msk) | (u32Source))
|
||||
|
||||
/**
|
||||
* @brief Enable PDMA transfer.
|
||||
* @param[in] adc The pointer of the specified ADC module
|
||||
* @return None
|
||||
* @details Enable PDMA to transfer the conversion data.
|
||||
* @note While enable PDMA transfer, software must set ADIE = 0 to disable interrupt.
|
||||
*/
|
||||
#define ADC_ENABLE_PDMA(adc) ((adc)->ADCR |= ADC_ADCR_PTEN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable PDMA transfer.
|
||||
* @param[in] adc The pointer of the specified ADC module
|
||||
* @return None
|
||||
* @details Disable PDMA to transfer the conversion data.
|
||||
*/
|
||||
#define ADC_DISABLE_PDMA(adc) ((adc)->ADCR &= ~ADC_ADCR_PTEN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Get conversion data of specified channel.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32ChNum ADC Channel, valid value are from 0 to 7.
|
||||
* @return 16-bit data.
|
||||
* @details Read RSLT bit field to get conversion data.
|
||||
*/
|
||||
#define ADC_GET_CONVERSION_DATA(adc, u32ChNum) ((adc)->ADDR[(u32ChNum)] & ADC_ADDR_RSLT_Msk)
|
||||
|
||||
/**
|
||||
* @brief Return the user-specified interrupt flags.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32Mask The combination of following interrupt status bits. Each bit corresponds to a interrupt status.
|
||||
* Valid values are:
|
||||
* - \ref ADC_ADF_INT :Convert complete interrupt flag.
|
||||
* - \ref ADC_CMP0_INT :Comparator 0 interrupt flag.
|
||||
* - \ref ADC_CMP1_INT :Comparator 1 interrupt flag.
|
||||
* @return User specified interrupt flags.
|
||||
* @details Get the status of the ADC interrupt flag.
|
||||
*/
|
||||
#define ADC_GET_INT_FLAG(adc, u32Mask) ((adc)->ADSR & (u32Mask))
|
||||
|
||||
/**
|
||||
* @brief This macro clear the selected interrupt status bits.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32Mask The combination of following interrupt status bits. Each bit corresponds to a interrupt status.
|
||||
* Valid values are:
|
||||
* - \ref ADC_ADF_INT :Convert complete interrupt flag.
|
||||
* - \ref ADC_CMP0_INT :Comparator 0 interrupt flag.
|
||||
* - \ref ADC_CMP1_INT :Comparator 1 interrupt flag.
|
||||
* @return None
|
||||
* @details ADF (ADSR[0])/CMPF0 (ADSR[1])/CMPF0 (ADSR[2]) can be cleared by writing 1 to itself.
|
||||
*/
|
||||
#define ADC_CLR_INT_FLAG(adc, u32Mask) ((adc)->ADSR = (u32Mask))
|
||||
|
||||
/**
|
||||
* @brief Get the busy state of ADC.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @retval 0 ADC is not busy.
|
||||
* @retval 1 ADC is busy.
|
||||
* @details BUSY(ADSR[3])is mirror of as ADST bit (ADCR[11]).
|
||||
*/
|
||||
#define ADC_IS_BUSY(adc) ((adc)->ADSR & ADC_ADSR_BUSY_Msk ? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Check if the ADC conversion data is over written or not.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32ChNum ADC Channel, valid value are from 0 to 7.
|
||||
* @retval 0 ADC data is not overrun.
|
||||
* @retval 1 ADC data is overrun.
|
||||
* @details OVERRUN (ADSR[23:16]) is a mirror to OVERRUN (ADDR0~7[16]).
|
||||
*/
|
||||
#define ADC_IS_DATA_OVERRUN(adc, u32ChNum) ((adc)->ADSR & (0x1 << (ADC_ADSR_OVERRUN_Pos + (u32ChNum))) ? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Check if the ADC conversion data is valid or not.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32ChNum ADC Channel, valid value are from 0 to 7.
|
||||
* @retval 0 ADC data is not valid.
|
||||
* @retval 1 ADC data is valid.
|
||||
* @details VALID (ADDR0~7[17]) is set to 1 when corresponding channel analog input conversion is completed and cleared by hardware after ADDR register is read.
|
||||
*/
|
||||
#define ADC_IS_DATA_VALID(adc, u32ChNum) ((adc)->ADSR & (0x1 << (ADC_ADSR_VALID_Pos + (u32ChNum))) ? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Power down ADC module.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details Disable A/D converter analog circuit for saving power consumption.
|
||||
* @note None
|
||||
*/
|
||||
#define ADC_POWER_DOWN(adc) ((adc)->ADCR &= ~ADC_ADCR_ADEN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Power on ADC module.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details Before starting A/D conversion function, ADEN bit (ADCR[0]) should be set to 1.
|
||||
*/
|
||||
#define ADC_POWER_ON(adc) ((adc)->ADCR |= ADC_ADCR_ADEN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Configure the comparator 0 and enable it.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32ChNum Specifies the source channel, valid value are from 0 to 7.
|
||||
* @param[in] u32Condition Specifies the compare condition. Valid values are:
|
||||
* - \ref ADC_ADCMPR_CMPCOND_LESS_THAN :The compare condition is "less than the compare value".
|
||||
* - \ref ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value.
|
||||
* @param[in] u32Data Specifies the compare value, valid value are between 0 ~ 0x3FF.
|
||||
* @param[in] u32MatchCount Specifies the match count setting, valid values are between 1~16.
|
||||
* @return None
|
||||
* @details For example, ADC_ENABLE_CMP0(ADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x200, 10);
|
||||
* Means ADC will assert comparator 0 flag if channel 5 conversion result is greater or
|
||||
* equal to 0x200 for 10 times continuously.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define ADC_ENABLE_CMP0(adc, \
|
||||
u32ChNum, \
|
||||
u32Condition, \
|
||||
u32Data, \
|
||||
u32MatchCount) ((adc)->ADCMPR[0] = ((u32ChNum) << ADC_ADCMPR_CMPCH_Pos) | \
|
||||
(u32Condition) | \
|
||||
((u32Data) << ADC_ADCMPR_CMPD_Pos) | \
|
||||
(((u32MatchCount) - 1) << ADC_ADCMPR_CMPMATCNT_Pos) |\
|
||||
ADC_ADCMPR_CMPEN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable comparator 0.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details Set CMPEN (ADCMPR0[0]) to 0 to disable ADC controller to compare CMPD (ADCMPR0[25:16]).
|
||||
*/
|
||||
#define ADC_DISABLE_CMP0(adc) ((adc)->ADCMPR[0] = 0)
|
||||
|
||||
/**
|
||||
* @brief Configure the comparator 1 and enable it.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32ChNum Specifies the source channel, valid value are from 0 to 7.
|
||||
* @param[in] u32Condition Specifies the compare condition. Valid values are:
|
||||
* - \ref ADC_ADCMPR_CMPCOND_LESS_THAN :The compare condition is "less than the compare value".
|
||||
* - \ref ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value.
|
||||
* @param[in] u32Data Specifies the compare value, valid value are between 0 ~ 0x3FF.
|
||||
* @param[in] u32MatchCount Specifies the match count setting, valid values are between 1~16.
|
||||
* @return None
|
||||
* @details For example, ADC_ENABLE_CMP1(ADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x200, 10);
|
||||
* Means ADC will assert comparator 1 flag if channel 5 conversion result is greater or
|
||||
* equal to 0x200 for 10 times continuously.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define ADC_ENABLE_CMP1(adc, \
|
||||
u32ChNum, \
|
||||
u32Condition, \
|
||||
u32Data, \
|
||||
u32MatchCount) ((adc)->ADCMPR[1] = ((u32ChNum) << ADC_ADCMPR_CMPCH_Pos) | \
|
||||
(u32Condition) | \
|
||||
((u32Data) << ADC_ADCMPR_CMPD_Pos) | \
|
||||
(((u32MatchCount) - 1) << ADC_ADCMPR_CMPMATCNT_Pos) |\
|
||||
ADC_ADCMPR_CMPEN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable comparator 1.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details Set CMPEN (ADCMPR1[0]) to 0 to disable ADC controller to compare CMPD (ADCMPR1[25:16]).
|
||||
*/
|
||||
#define ADC_DISABLE_CMP1(adc) ((adc)->ADCMPR[1] = 0)
|
||||
|
||||
/**
|
||||
* @brief Set ADC input channel.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32Mask Channel enable bit. Each bit corresponds to a input channel. Bit 0 is channel 0, bit 1 is channel 1..., bit 7 is channel 7.
|
||||
* @return None
|
||||
* @details Enabled channel will be converted while ADC starts.
|
||||
* @note NUC123 series MCU ADC can only convert 1 channel at a time. If more than 1 channels are enabled, only channel
|
||||
* with smallest number will be convert.
|
||||
*/
|
||||
#define ADC_SET_INPUT_CHANNEL(adc, u32Mask) ((adc)->ADCHER = ((adc)->ADCHER & ~ADC_ADCHER_CHEN_Msk) | (u32Mask))
|
||||
|
||||
/**
|
||||
* @brief Start the A/D conversion.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details ADST (ADCR[11]) can be set to 1 from three sources: software, PWM Center-aligned trigger and external pin STADC.
|
||||
*/
|
||||
#define ADC_START_CONV(adc) ((adc)->ADCR |= ADC_ADCR_ADST_Msk)
|
||||
|
||||
/**
|
||||
* @brief Stop the A/D conversion.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details ADST (ADCR[11]) will be cleared to 0 by hardware automatically at the ends of single mode and single-cycle scan mode.
|
||||
* In continuous scan mode, A/D conversion is continuously performed until software writes 0 to this bit or chip reset.
|
||||
*/
|
||||
#define ADC_STOP_CONV(adc) ((adc)->ADCR &= ~ADC_ADCR_ADST_Msk)
|
||||
|
||||
void ADC_Open(ADC_T *adc,
|
||||
uint32_t u32InputMode,
|
||||
uint32_t u32OpMode,
|
||||
uint32_t u32ChMask);
|
||||
void ADC_Close(ADC_T *adc);
|
||||
void ADC_EnableHWTrigger(ADC_T *adc,
|
||||
uint32_t u32Source,
|
||||
uint32_t u32Param);
|
||||
void ADC_DisableHWTrigger(ADC_T *adc);
|
||||
void ADC_EnableInt(ADC_T *adc, uint32_t u32Mask);
|
||||
void ADC_DisableInt(ADC_T *adc, uint32_t u32Mask);
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group ADC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group ADC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__ADC_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
453
NUC123/StdDriver/inc/clk.h
Normal file
453
NUC123/StdDriver/inc/clk.h
Normal file
@ -0,0 +1,453 @@
|
||||
/**************************************************************************//**
|
||||
* @file clk.h
|
||||
* @version V3.0
|
||||
* $Revision: 16 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series Clock Control Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __CLK_H__
|
||||
#define __CLK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CLK_Driver CLK Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CLK_EXPORTED_CONSTANTS CLK Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
#define FREQ_25MHZ 25000000
|
||||
#define FREQ_50MHZ 50000000
|
||||
#define FREQ_72MHZ 72000000
|
||||
#define FREQ_100MHZ 100000000
|
||||
#define FREQ_200MHZ 200000000
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* CLKSEL0 constant definitions. */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CLK_CLKSEL0_HCLK_S_HXT (0x0UL<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Setting HCLK clock source as HXT */
|
||||
#define CLK_CLKSEL0_HCLK_S_PLL_DIV2 (0x1UL<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Setting HCLK clock source as PLL/2 */
|
||||
#define CLK_CLKSEL0_HCLK_S_PLL (0x2UL<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Setting HCLK clock source as PLL */
|
||||
#define CLK_CLKSEL0_HCLK_S_LIRC (0x3UL<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Setting HCLK clock source as LIRC */
|
||||
#define CLK_CLKSEL0_HCLK_S_HIRC (0x7UL<<CLK_CLKSEL0_HCLK_S_Pos) /*!< Setting HCLK clock source as HIRC */
|
||||
|
||||
#define CLK_CLKSEL0_STCLK_S_HXT (0x0UL<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Setting STCLK clock source as HXT */
|
||||
#define CLK_CLKSEL0_STCLK_S_HXT_DIV2 (0x2UL<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Setting STCLK clock source as HXT/2 */
|
||||
#define CLK_CLKSEL0_STCLK_S_HCLK_DIV2 (0x3UL<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Setting STCLK clock source as HCLK/2 */
|
||||
#define CLK_CLKSEL0_STCLK_S_HIRC_DIV2 (0x7UL<<CLK_CLKSEL0_STCLK_S_Pos) /*!< Setting STCLK clock source as HIRC/2 */
|
||||
#define CLK_CLKSEL0_STCLK_S_HCLK (0x1UL<<SysTick_CTRL_CLKSOURCE_Pos) /*!< Setting STCLK clock source as HCLK */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* CLKSEL1 constant definitions. */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CLK_CLKSEL1_WDT_S_HCLK_DIV2048 (0x2UL<<CLK_CLKSEL1_WDT_S_Pos) /*!< Setting WDT clock source as HCLK/2048 */
|
||||
#define CLK_CLKSEL1_WDT_S_LIRC (0x3UL<<CLK_CLKSEL1_WDT_S_Pos) /*!< Setting WDT clock source as LIRC */
|
||||
|
||||
#define CLK_CLKSEL1_ADC_S_HXT (0x0UL<<CLK_CLKSEL1_ADC_S_Pos) /*!< Setting ADC clock source as HXT */
|
||||
#define CLK_CLKSEL1_ADC_S_PLL (0x1UL<<CLK_CLKSEL1_ADC_S_Pos) /*!< Setting ADC clock source as PLL */
|
||||
#define CLK_CLKSEL1_ADC_S_HCLK (0x2UL<<CLK_CLKSEL1_ADC_S_Pos) /*!< Setting ADC clock source as HCLK */
|
||||
#define CLK_CLKSEL1_ADC_S_HIRC (0x3UL<<CLK_CLKSEL1_ADC_S_Pos) /*!< Setting ADC clock source as HIRC */
|
||||
|
||||
#define CLK_CLKSEL1_SPI0_S_PLL (0x0UL<<CLK_CLKSEL1_SPI0_S_Pos) /*!< Setting SPI0 clock source as PLL */
|
||||
#define CLK_CLKSEL1_SPI0_S_HCLK (0x1UL<<CLK_CLKSEL1_SPI0_S_Pos) /*!< Setting SPI0 clock source as HCLK */
|
||||
#define CLK_CLKSEL1_SPI1_S_PLL (0x0UL<<CLK_CLKSEL1_SPI1_S_Pos) /*!< Setting SPI1 clock source as PLL */
|
||||
#define CLK_CLKSEL1_SPI1_S_HCLK (0x1UL<<CLK_CLKSEL1_SPI1_S_Pos) /*!< Setting SPI1 clock source as HCLK */
|
||||
#define CLK_CLKSEL1_SPI2_S_PLL (0x0UL<<CLK_CLKSEL1_SPI2_S_Pos) /*!< Setting SPI2 clock source as PLL */
|
||||
#define CLK_CLKSEL1_SPI2_S_HCLK (0x1UL<<CLK_CLKSEL1_SPI2_S_Pos) /*!< Setting SPI2 clock source as HCLK */
|
||||
|
||||
#define CLK_CLKSEL1_TMR0_S_HXT (0x0UL<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Setting TMR0 clock source as HXT */
|
||||
#define CLK_CLKSEL1_TMR0_S_HCLK (0x2UL<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Setting TMR0 clock source as HCLK */
|
||||
#define CLK_CLKSEL1_TMR0_S_EXT_TRG (0x3UL<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Setting TMR0 clock source as external trigger */
|
||||
#define CLK_CLKSEL1_TMR0_S_LIRC (0x5UL<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Setting TMR0 clock source as LIRC */
|
||||
#define CLK_CLKSEL1_TMR0_S_HIRC (0x7UL<<CLK_CLKSEL1_TMR0_S_Pos) /*!< Setting TMR0 clock source as HIRC */
|
||||
#define CLK_CLKSEL1_TMR1_S_HXT (0x0UL<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Setting TMR1 clock source as HXT */
|
||||
#define CLK_CLKSEL1_TMR1_S_HCLK (0x2UL<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Setting TMR1 clock source as HCLK */
|
||||
#define CLK_CLKSEL1_TMR1_S_EXT_TRG (0x3UL<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Setting TMR1 clock source as external trigger */
|
||||
#define CLK_CLKSEL1_TMR1_S_LIRC (0x5UL<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Setting TMR1 clock source as LIRC */
|
||||
#define CLK_CLKSEL1_TMR1_S_HIRC (0x7UL<<CLK_CLKSEL1_TMR1_S_Pos) /*!< Setting TMR1 clock source as HIRC*/
|
||||
#define CLK_CLKSEL1_TMR2_S_HXT (0x0UL<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Setting TMR2 clock source as external X'tal */
|
||||
#define CLK_CLKSEL1_TMR2_S_HCLK (0x2UL<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Setting TMR2 clock source as HCLK */
|
||||
#define CLK_CLKSEL1_TMR2_S_EXT_TRG (0x3UL<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Setting TMR2 clock source as external trigger */
|
||||
#define CLK_CLKSEL1_TMR2_S_LIRC (0x5UL<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Setting TMR2 clock source as LIRC */
|
||||
#define CLK_CLKSEL1_TMR2_S_HIRC (0x7UL<<CLK_CLKSEL1_TMR2_S_Pos) /*!< Setting TMR2 clock source as HIRC */
|
||||
#define CLK_CLKSEL1_TMR3_S_HXT (0x0UL<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Setting TMR3 clock source as HXT */
|
||||
#define CLK_CLKSEL1_TMR3_S_HCLK (0x2UL<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Setting TMR3 clock source as HCLK */
|
||||
#define CLK_CLKSEL1_TMR3_S_EXT_TRG (0x3UL<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Setting TMR3 clock source as external trigger */
|
||||
#define CLK_CLKSEL1_TMR3_S_LIRC (0x5UL<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Setting TMR3 clock source as LIRC*/
|
||||
#define CLK_CLKSEL1_TMR3_S_HIRC (0x7UL<<CLK_CLKSEL1_TMR3_S_Pos) /*!< Setting TMR3 clock source as HIRC */
|
||||
|
||||
#define CLK_CLKSEL1_UART_S_HXT (0x0UL<<CLK_CLKSEL1_UART_S_Pos) /*!< Setting UART clock source as HXT */
|
||||
#define CLK_CLKSEL1_UART_S_PLL (0x1UL<<CLK_CLKSEL1_UART_S_Pos) /*!< Setting UART clock source as PLL */
|
||||
#define CLK_CLKSEL1_UART_S_HIRC (0x3UL<<CLK_CLKSEL1_UART_S_Pos) /*!< Setting UART clock source as HIRC */
|
||||
|
||||
#define CLK_CLKSEL1_PWM01_S_HXT (0x0UL<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Setting PWM01 clock source as HXT,
|
||||
user must set CLK_CLKSEL2_PWM01_EXT_HXT concurrently to complete clock source as HXT setting*/
|
||||
#define CLK_CLKSEL1_PWM01_S_HCLK (0x2UL<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Setting PWM01 clock source as HCLK
|
||||
user must set CLK_CLKSEL2_PWM01_EXT_HCLK concurrently to complete clock source as HCLK setting*/
|
||||
#define CLK_CLKSEL1_PWM01_S_HIRC (0x3UL<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Setting PWM01 clock source as HIRC clock,
|
||||
user must set CLK_CLKSEL2_PWM01_EXT_HIRC concurrently to complete clock source as HIRC clock setting*/
|
||||
#define CLK_CLKSEL1_PWM01_S_LIRC (0x3UL<<CLK_CLKSEL1_PWM01_S_Pos) /*!< Setting PWM01 clock source as LIRC clock,
|
||||
user must set CLK_CLKSEL2_PWM01_EXT_LIRC concurrently to complete clock source as LIRC clock setting*/
|
||||
|
||||
#define CLK_CLKSEL1_PWM23_S_HXT (0x0UL<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Setting PWM23 clock source as HXT,
|
||||
user must set CLK_CLKSEL2_PWM23_EXT_HXT concurrently to complete clock source as HXT setting*/
|
||||
#define CLK_CLKSEL1_PWM23_S_HCLK (0x2UL<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Setting PWM23 clock source as HCLK,
|
||||
user must set CLK_CLKSEL2_PWM23_EXT_HCLK concurrently to complete clock source as HCLK setting*/
|
||||
#define CLK_CLKSEL1_PWM23_S_HIRC (0x3UL<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Setting PWM23 clock source as HIRC clock,
|
||||
user must set CLK_CLKSEL2_PWM23_EXT_HIRC concurrently to complete clock source as HIRC clock setting*/
|
||||
#define CLK_CLKSEL1_PWM23_S_LIRC (0x3UL<<CLK_CLKSEL1_PWM23_S_Pos) /*!< Setting PWM23 clock source as LIRC clock,
|
||||
user must set CLK_CLKSEL2_PWM23_EXT_LIRC concurrently to complete clock source as LIRC setting*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* CLKSEL2 constant definitions. */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CLK_CLKSEL2_I2S_S_HXT (0x0UL<<CLK_CLKSEL2_I2S_S_Pos) /*!< Setting I2S clock source as HXT */
|
||||
#define CLK_CLKSEL2_I2S_S_PLL (0x1UL<<CLK_CLKSEL2_I2S_S_Pos) /*!< Setting I2S clock source as PLL */
|
||||
#define CLK_CLKSEL2_I2S_S_HCLK (0x2UL<<CLK_CLKSEL2_I2S_S_Pos) /*!< Setting I2S clock source as HCLK */
|
||||
#define CLK_CLKSEL2_I2S_S_HIRC (0x3UL<<CLK_CLKSEL2_I2S_S_Pos) /*!< Setting I2S clock source as HIRC */
|
||||
|
||||
#define CLK_CLKSEL2_FRQDIV_S_HXT (0x0UL<<CLK_CLKSEL2_FRQDIV_S_Pos) /*!< Setting FRQDIV clock source as HXT */
|
||||
#define CLK_CLKSEL2_FRQDIV_S_HCLK (0x2UL<<CLK_CLKSEL2_FRQDIV_S_Pos) /*!< Setting FRQDIV clock source as HCLK */
|
||||
#define CLK_CLKSEL2_FRQDIV_S_HIRC (0x3UL<<CLK_CLKSEL2_FRQDIV_S_Pos) /*!< Setting FRQDIV clock source as HIRC */
|
||||
|
||||
#define CLK_CLKSEL2_PWM01_EXT_HXT (0x0UL<<CLK_CLKSEL2_PWM01_S_E_Pos)/*!< Setting PWM01 clock source as HXT,
|
||||
user must set CLK_CLKSEL1_PWM01_HXT concurrently to complete clock source as HXT setting*/
|
||||
#define CLK_CLKSEL2_PWM01_EXT_HCLK (0x0UL<<CLK_CLKSEL2_PWM01_S_E_Pos)/*!< Setting PWM01 clock source as HCLK,
|
||||
user must set CLK_CLKSEL1_PWM01_HCLK concurrently to complete clock source as HCLK setting*/
|
||||
#define CLK_CLKSEL2_PWM01_EXT_HIRC (0x0UL<<CLK_CLKSEL2_PWM01_S_E_Pos)/*!< Setting PWM01 clock source as HIRC,
|
||||
user must set CLK_CLKSEL1_PWM01_HIRC concurrently to complete clock source as HIRC setting*/
|
||||
#define CLK_CLKSEL2_PWM01_EXT_LIRC (0x1UL<<CLK_CLKSEL2_PWM01_S_E_Pos)/*!< Setting PWM01 clock source as LIRC,
|
||||
user must set CLK_CLKSEL1_PWM01_LIRC concurrently to complete clock source as LIRC setting*/
|
||||
|
||||
#define CLK_CLKSEL2_PWM23_EXT_HXT (0x0UL<<CLK_CLKSEL2_PWM23_S_E_Pos)/*!< Setting PWM23 clock source as HXT,
|
||||
user must set CLK_CLKSEL1_PWM23_HXT concurrently to complete clock source as HXT setting*/
|
||||
#define CLK_CLKSEL2_PWM23_EXT_HCLK (0x0UL<<CLK_CLKSEL2_PWM23_S_E_Pos)/*!< Setting PWM23 clock source as HCLK,
|
||||
user must set CLK_CLKSEL1_PWM23_HCLK concurrently to complete clock source as HCLK setting*/
|
||||
#define CLK_CLKSEL2_PWM23_EXT_HIRC (0x0UL<<CLK_CLKSEL2_PWM23_S_E_Pos)/*!< Setting PWM23 clock source as HIRC clock,
|
||||
user must set CLK_CLKSEL1_PWM23_HIRC concurrently to complete clock source as HIRC setting*/
|
||||
#define CLK_CLKSEL2_PWM23_EXT_LIRC (0x1UL<<CLK_CLKSEL2_PWM23_S_E_Pos)/*!< Setting PWM23 clock source as LIRC,
|
||||
user must set CLK_CLKSEL1_PWM23_LIRC concurrently to complete clock source as LIRC setting*/
|
||||
|
||||
#define CLK_CLKSEL2_WWDT_S_HCLK_DIV2048 (0x2UL<<CLK_CLKSEL2_WWDT_S_Pos) /*!< Setting WWDT clock source as HCLK/2048 */
|
||||
#define CLK_CLKSEL2_WWDT_S_LIRC (0x3UL<<CLK_CLKSEL2_WWDT_S_Pos) /*!< Setting WWDT clock source as LIRC */
|
||||
|
||||
|
||||
|
||||
#define CLK_CLKSEL12_PWM01_S_HXT (CLK_CLKSEL1_PWM01_S_HXT | CLK_CLKSEL2_PWM01_EXT_HXT ) /*!< Setting PWM01 clock source as HXT */
|
||||
#define CLK_CLKSEL12_PWM01_S_HCLK (CLK_CLKSEL1_PWM01_S_HCLK | CLK_CLKSEL2_PWM01_EXT_HCLK) /*!< Setting PWM01 clock source as HCLK */
|
||||
#define CLK_CLKSEL12_PWM01_S_HIRC (CLK_CLKSEL1_PWM01_S_HIRC | CLK_CLKSEL2_PWM01_EXT_HIRC) /*!< Setting PWM01 clock source as HIRC */
|
||||
#define CLK_CLKSEL12_PWM01_S_LIRC (CLK_CLKSEL1_PWM01_S_LIRC | CLK_CLKSEL2_PWM01_EXT_LIRC) /*!< Setting PWM01 clock source as LIRC */
|
||||
#define CLK_CLKSEL12_PWM23_S_HXT (CLK_CLKSEL1_PWM23_S_HXT | CLK_CLKSEL2_PWM23_EXT_HXT ) /*!< Setting PWM23 clock source as HXT */
|
||||
#define CLK_CLKSEL12_PWM23_S_HCLK (CLK_CLKSEL1_PWM23_S_HCLK | CLK_CLKSEL2_PWM23_EXT_HCLK) /*!< Setting PWM23 clock source as HCLK */
|
||||
#define CLK_CLKSEL12_PWM23_S_HIRC (CLK_CLKSEL1_PWM23_S_HIRC | CLK_CLKSEL2_PWM23_EXT_HIRC) /*!< Setting PWM23 clock source as HIRC */
|
||||
#define CLK_CLKSEL12_PWM23_S_LIRC (CLK_CLKSEL1_PWM23_S_LIRC | CLK_CLKSEL2_PWM23_EXT_LIRC) /*!< Setting PWM23 clock source as LIRC */
|
||||
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* CLKDIV constant definitions. */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CLK_CLKDIV_HCLK(x) ((x)-1) /*!< CLKDIV Setting for HCLK clock divider. It could be 1~16 */
|
||||
#define CLK_CLKDIV_USB(x) (((x)-1) << CLK_CLKDIV_USB_N_Pos) /*!< CLKDIV Setting for USB clock divider. It could be 1~16 */
|
||||
#define CLK_CLKDIV_UART(x) (((x)-1) << CLK_CLKDIV_UART_N_Pos) /*!< CLKDIV Setting for UART clock divider. It could be 1~16 */
|
||||
#define CLK_CLKDIV_ADC(x) (((x)-1) << CLK_CLKDIV_ADC_N_Pos) /*!< CLKDIV Setting for ADC clock divider. It could be 1~256 */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* PLLCON constant definitions. PLL = FIN * NF / NR / NO */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CLK_PLLCON_PLL_SRC_HXT 0x00000000UL /*!< For PLL clock source is HXT. 4MHz < FIN < 24MHz */
|
||||
#define CLK_PLLCON_PLL_SRC_HIRC 0x00080000UL /*!< For PLL clock source is HIRC.4MHz < FIN < 24MHz */
|
||||
|
||||
#define CLK_PLLCON_NR(x) (((x)-2)<<9) /*!< x must be constant and 2 <= x <= 33. 1.6MHz < FIN/NR < 15MHz */
|
||||
#define CLK_PLLCON_NF(x) ((x)-2) /*!< x must be constant and 2 <= x <= 513. 100MHz < FIN*NF/NR < 200MHz. (120MHz < FIN*NF/NR < 200MHz is preferred.) */
|
||||
|
||||
#define CLK_PLLCON_NO_1 0x0000UL /*!< For output divider is 1 */
|
||||
#define CLK_PLLCON_NO_2 0x4000UL /*!< For output divider is 2 */
|
||||
#define CLK_PLLCON_NO_4 0xC000UL /*!< For output divider is 4 */
|
||||
|
||||
#if (__HXT == 12000000)
|
||||
#define CLK_PLLCON_FOR_I2S (0xA54) /*!< Predefined PLLCON setting for 147428571.428571Hz PLL output with 12MHz X'tal */
|
||||
#define CLK_PLLCON_144MHz_HXT (CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(2) | CLK_PLLCON_NF( 24) | CLK_PLLCON_NO_1) /*!< Predefined PLLCON setting for 72MHz PLL output with 12MHz X'tal */
|
||||
#define CLK_PLLCON_72MHz_HXT (CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(2) | CLK_PLLCON_NF( 24) | CLK_PLLCON_NO_2) /*!< Predefined PLLCON setting for 72MHz PLL output with 12MHz X'tal */
|
||||
#define CLK_PLLCON_50MHz_HXT (CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF( 25) | CLK_PLLCON_NO_2) /*!< Predefined PLLCON setting for 50MHz PLL output with 12MHz X'tal */
|
||||
#define CLK_PLLCON_48MHz_HXT (CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(7) | CLK_PLLCON_NF(112) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 48MHz PLL output with 12MHz X'tal */
|
||||
#define CLK_PLLCON_36MHz_HXT (CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(7) | CLK_PLLCON_NF( 84) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 36MHz PLL output with 12MHz X'tal */
|
||||
#define CLK_PLLCON_32MHz_HXT (CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(6) | CLK_PLLCON_NF( 64) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 32MHz PLL output with 12MHz X'tal */
|
||||
#define CLK_PLLCON_24MHz_HXT (CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(2) | CLK_PLLCON_NF( 16) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 24MHz PLL output with 12MHz X'tal */
|
||||
#else
|
||||
# error "The PLL pre-definitions are only valid when external crystal is 12MHz"
|
||||
#endif
|
||||
|
||||
#define CLK_PLLCON_72MHz_HIRC (CLK_PLLCON_PLL_SRC_HIRC | CLK_PLLCON_NR( 4) | CLK_PLLCON_NF( 26) | CLK_PLLCON_NO_2) /*!< Predefined PLLCON setting for 71.88488MHz PLL output with 22.1184MHz IRC */
|
||||
#define CLK_PLLCON_50MHz_HIRC (CLK_PLLCON_PLL_SRC_HIRC | CLK_PLLCON_NR(13) | CLK_PLLCON_NF( 59) | CLK_PLLCON_NO_2) /*!< Predefined PLLCON setting for 50.1918MHz PLL output with 22.1184MHz IRC */
|
||||
#define CLK_PLLCON_48MHz_HIRC (CLK_PLLCON_PLL_SRC_HIRC | CLK_PLLCON_NR(13) | CLK_PLLCON_NF(113) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 48.064985MHz PLL output with 22.1184MHz IRC*/
|
||||
#define CLK_PLLCON_36MHz_HIRC (CLK_PLLCON_PLL_SRC_HIRC | CLK_PLLCON_NR(12) | CLK_PLLCON_NF( 78) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 35.9424MHz PLL output with 22.1184MHz IRC */
|
||||
#define CLK_PLLCON_32MHz_HIRC (CLK_PLLCON_PLL_SRC_HIRC | CLK_PLLCON_NR( 9) | CLK_PLLCON_NF( 52) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 31.9488MHz PLL output with 22.1184MHz IRC*/
|
||||
#define CLK_PLLCON_24MHz_HIRC (CLK_PLLCON_PLL_SRC_HIRC | CLK_PLLCON_NR( 3) | CLK_PLLCON_NF( 13) | CLK_PLLCON_NO_4) /*!< Predefined PLLCON setting for 23.9616MHz PLL output with 22.1184MHz IRC*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* MODULE constant definitions. */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* APBCLK(31:30)|CLKSEL(29:28)|CLKSEL_Msk(27:25) |CLKSEL_Pos(24:20)|CLKDIV(19:18)|CLKDIV_Msk(17:10)|CLKDIV_Pos(9:5)|IP_EN_Pos(4:0) */
|
||||
|
||||
#define MODULE_APBCLK(x) (((x) >>30) & 0x3) /*!< Calculate APBCLK offset on MODULE index, 0x0:AHBCLK, 0x1:APBCLK */
|
||||
#define MODULE_CLKSEL(x) (((x) >>28) & 0x3) /*!< Calculate CLKSEL offset on MODULE index, 0x0:CLKSEL0, 0x1:CLKSEL1, 0x2:CLKSEL2 */
|
||||
#define MODULE_CLKSEL_Msk(x) (((x) >>25) & 0x7) /*!< Calculate CLKSEL mask offset on MODULE index */
|
||||
#define MODULE_CLKSEL_Pos(x) (((x) >>20) & 0x1f) /*!< Calculate CLKSEL position offset on MODULE index */
|
||||
#define MODULE_CLKDIV(x) (((x) >>18) & 0x3) /*!< Calculate APBCLK CLKDIV on MODULE index, 0x0:CLKDIV */
|
||||
#define MODULE_CLKDIV_Msk(x) (((x) >>10) & 0xff) /*!< Calculate CLKDIV mask offset on MODULE index */
|
||||
#define MODULE_CLKDIV_Pos(x) (((x) >>5 ) & 0x1f) /*!< Calculate CLKDIV position offset on MODULE index */
|
||||
#define MODULE_IP_EN_Pos(x) (((x) >>0 ) & 0x1f) /*!< Calculate APBCLK offset on MODULE index */
|
||||
#define MODULE_NoMsk 0x0 /*!< Not mask on MODULE index */
|
||||
#define NA MODULE_NoMsk /*!< Not Available */
|
||||
|
||||
#define MODULE_APBCLK_ENC(x) (((x) & 0x03) << 30) /*!< MODULE index, 0x0:AHBCLK, 0x1:APBCLK */
|
||||
#define MODULE_CLKSEL_ENC(x) (((x) & 0x03) << 28) /*!< CLKSEL offset on MODULE index, 0x0:CLKSEL0, 0x1:CLKSEL1, 0x2:CLKSEL2 */
|
||||
#define MODULE_CLKSEL_Msk_ENC(x) (((x) & 0x07) << 25) /*!< CLKSEL mask offset on MODULE index */
|
||||
#define MODULE_CLKSEL_Pos_ENC(x) (((x) & 0x1f) << 20) /*!< CLKSEL position offset on MODULE index */
|
||||
#define MODULE_CLKDIV_ENC(x) (((x) & 0x03) << 18) /*!< APBCLK CLKDIV on MODULE index, 0x0:CLKDIV */
|
||||
#define MODULE_CLKDIV_Msk_ENC(x) (((x) & 0xff) << 10) /*!< CLKDIV mask offset on MODULE index */
|
||||
#define MODULE_CLKDIV_Pos_ENC(x) (((x) & 0x1f) << 5) /*!< CLKDIV position offset on MODULE index */
|
||||
#define MODULE_IP_EN_Pos_ENC(x) (((x) & 0x1f) << 0) /*!< APBCLK offset on MODULE index */
|
||||
|
||||
|
||||
#define PDMA_MODULE (MODULE_APBCLK_ENC( 0)|MODULE_IP_EN_Pos_ENC(CLK_AHBCLK_PDMA_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< PDMA Module */
|
||||
#define ISP_MODULE (MODULE_APBCLK_ENC( 0)|MODULE_IP_EN_Pos_ENC(CLK_AHBCLK_ISP_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< ISP Module */
|
||||
|
||||
#define WDT_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_WDT_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC( 0)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< WDT Module */
|
||||
#define TMR0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_TMR0_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC( 8)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR0 Module */
|
||||
#define TMR1_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_TMR1_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(12)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR1 Module */
|
||||
#define TMR2_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_TMR2_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(16)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR2 Module */
|
||||
#define TMR3_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_TMR3_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 7)|MODULE_CLKSEL_Pos_ENC(20)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< TMR3 Module */
|
||||
#define FDIV_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_FDIV_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC( 2)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< FDIV Module */
|
||||
|
||||
#define I2C0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_I2C0_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< I2C0 Module */
|
||||
#define I2C1_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_I2C1_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< I2C1 Module */
|
||||
#define SPI0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_SPI0_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC( 4)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< SPI0 Module */
|
||||
#define SPI1_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_SPI1_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC( 5)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< SPI1 Module */
|
||||
#define SPI2_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_SPI2_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 1)|MODULE_CLKSEL_Pos_ENC( 6)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< SPI2 Module */
|
||||
|
||||
#define UART0_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_UART0_EN_Pos)|\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(24)|\
|
||||
MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0x0F)|MODULE_CLKDIV_Pos_ENC( 8)) /*!< UART0 Module */
|
||||
#define UART1_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_UART1_EN_Pos)|\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(24)|\
|
||||
MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0x0F)|MODULE_CLKDIV_Pos_ENC( 8)) /*!< UART1 Module */
|
||||
|
||||
#define PWM01_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_PWM01_EN_Pos)|\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(28)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< PWM01 Module */
|
||||
#define PWM23_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_PWM23_EN_Pos)|\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(30)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< PWM23 Module */
|
||||
#define USBD_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_USBD_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\
|
||||
MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0x0F)|MODULE_CLKDIV_Pos_ENC(4)) /*!< USBD Module */
|
||||
#define ADC_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_ADC_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 1)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC( 2)|\
|
||||
MODULE_CLKDIV_ENC( 0)|MODULE_CLKDIV_Msk_ENC(0xFF)|MODULE_CLKDIV_Pos_ENC(16)) /*!< ADC Module */
|
||||
#define I2S_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_I2S_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC( 0)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< I2S Module */
|
||||
#define PS2_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_PS2_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC(NA)|MODULE_CLKSEL_Msk_ENC(NA)|MODULE_CLKSEL_Pos_ENC(NA)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< PS2 Module */
|
||||
|
||||
#define WWDT_MODULE (MODULE_APBCLK_ENC( 1)|MODULE_IP_EN_Pos_ENC(CLK_APBCLK_WDT_EN_Pos) |\
|
||||
MODULE_CLKSEL_ENC( 2)|MODULE_CLKSEL_Msk_ENC( 3)|MODULE_CLKSEL_Pos_ENC(16)|\
|
||||
MODULE_CLKDIV_ENC(NA)|MODULE_CLKDIV_Msk_ENC(NA)|MODULE_CLKDIV_Pos_ENC(NA)) /*!< WWDT Module */
|
||||
|
||||
/*@}*/ /* end of group CLK_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get PLL clock frequency
|
||||
* @param None
|
||||
* @return PLL frequency
|
||||
* @details This function get PLL frequency. The frequency unit is Hz.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t CLK_GetPLLClockFreq(void)
|
||||
{
|
||||
uint32_t u32PllFreq = 0, u32PllReg;
|
||||
uint32_t u32FIN, u32NF, u32NR, u32NO;
|
||||
uint8_t au8NoTbl[4] = {1, 2, 2, 4};
|
||||
|
||||
u32PllReg = CLK->PLLCON;
|
||||
|
||||
if(u32PllReg & (CLK_PLLCON_PD_Msk | CLK_PLLCON_OE_Msk))
|
||||
return 0; /* PLL is in power down mode or fix low */
|
||||
|
||||
if(u32PllReg & CLK_PLLCON_PLL_SRC_HIRC)
|
||||
u32FIN = __HIRC; /* PLL source clock from HIRC */
|
||||
else
|
||||
u32FIN = __HXT; /* PLL source clock from HXT */
|
||||
|
||||
if(u32PllReg & CLK_PLLCON_BP_Msk)
|
||||
return u32FIN; /* PLL is in bypass mode */
|
||||
|
||||
/* PLL is output enabled in normal work mode */
|
||||
u32NO = au8NoTbl[((u32PllReg & CLK_PLLCON_OUT_DV_Msk) >> CLK_PLLCON_OUT_DV_Pos)];
|
||||
u32NF = ((u32PllReg & CLK_PLLCON_FB_DV_Msk) >> CLK_PLLCON_FB_DV_Pos) + 2;
|
||||
u32NR = ((u32PllReg & CLK_PLLCON_IN_DV_Msk) >> CLK_PLLCON_IN_DV_Pos) + 2;
|
||||
|
||||
/* u32FIN is shifted 2 bits to avoid overflow */
|
||||
u32PllFreq = (((u32FIN >> 2) * u32NF) / (u32NR * u32NO) << 2);
|
||||
|
||||
return u32PllFreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function execute delay function.
|
||||
* @param[in] us Delay time. The Max value is 2^24 / CPU Clock(MHz). Ex:
|
||||
* 72MHz => 233016us, 50MHz => 335544us,
|
||||
48MHz => 349525us, 28MHz => 699050us ...
|
||||
* @return None
|
||||
* @details Use the SysTick to generate the delay time and the UNIT is in us.
|
||||
* The SysTick clock source is from HCLK, i.e the same as system core clock.
|
||||
* User can use SystemCoreClockUpdate() to calculate CyclesPerUs automatically before using this function.
|
||||
*/
|
||||
__STATIC_INLINE void CLK_SysTickDelay(uint32_t us)
|
||||
{
|
||||
SysTick->LOAD = us * CyclesPerUs;
|
||||
SysTick->VAL = (0x00);
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
|
||||
|
||||
/* Waiting for down-count to zero */
|
||||
while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0);
|
||||
|
||||
/* Disable SysTick counter */
|
||||
SysTick->CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function execute long delay function.
|
||||
* @param[in] us Delay time.
|
||||
* @return None
|
||||
* @details Use the SysTick to generate the long delay time and the UNIT is in us.
|
||||
* The SysTick clock source is from HCLK, i.e the same as system core clock.
|
||||
* User can use SystemCoreClockUpdate() to calculate CyclesPerUs automatically before using this function.
|
||||
*/
|
||||
__STATIC_INLINE void CLK_SysTickLongDelay(uint32_t us)
|
||||
{
|
||||
uint32_t delay;
|
||||
|
||||
/* It should <= 233016us for each delay loop */
|
||||
delay = 233016L;
|
||||
|
||||
do
|
||||
{
|
||||
if(us > delay)
|
||||
{
|
||||
us -= delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
delay = us;
|
||||
us = 0UL;
|
||||
}
|
||||
|
||||
SysTick->LOAD = delay * CyclesPerUs;
|
||||
SysTick->VAL = (0x0UL);
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
|
||||
|
||||
/* Waiting for down-count to zero */
|
||||
while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0UL);
|
||||
|
||||
/* Disable SysTick counter */
|
||||
SysTick->CTRL = 0UL;
|
||||
|
||||
}while(us > 0UL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CLK_DisableCKO(void);
|
||||
void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En);
|
||||
void CLK_PowerDown(void);
|
||||
void CLK_Idle(void);
|
||||
uint32_t CLK_GetHXTFreq(void);
|
||||
uint32_t CLK_GetHCLKFreq(void);
|
||||
uint32_t CLK_GetPCLKFreq(void);
|
||||
uint32_t CLK_GetCPUFreq(void);
|
||||
uint32_t CLK_SetCoreClock(uint32_t u32Hclk);
|
||||
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv);
|
||||
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv);
|
||||
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc);
|
||||
void CLK_EnableXtalRC(uint32_t u32ClkMask);
|
||||
void CLK_DisableXtalRC(uint32_t u32ClkMask);
|
||||
void CLK_EnableModuleClock(uint32_t u32ModuleIdx);
|
||||
void CLK_DisableModuleClock(uint32_t u32ModuleIdx);
|
||||
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq);
|
||||
void CLK_DisablePLL(void);
|
||||
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask);
|
||||
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count);
|
||||
void CLK_DisableSysTick(void);
|
||||
|
||||
|
||||
/*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group CLK_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__CLK_H__
|
||||
|
||||
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
166
NUC123/StdDriver/inc/crc.h
Normal file
166
NUC123/StdDriver/inc/crc.h
Normal file
@ -0,0 +1,166 @@
|
||||
/**************************************************************************//**
|
||||
* @file crc.h
|
||||
* @version V3.00
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series CRC driver header file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#ifndef __CRC_H__
|
||||
#define __CRC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CRC_Driver CRC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CRC_EXPORTED_CONSTANTS CRC Exported Constants
|
||||
@{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* CRC Polynomial Mode Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CRC_CCITT 0x00000000UL /*!<CRC Polynomial Mode - CCITT */
|
||||
#define CRC_8 0x40000000UL /*!<CRC Polynomial Mode - CRC8 */
|
||||
#define CRC_16 0x80000000UL /*!<CRC Polynomial Mode - CRC16 */
|
||||
#define CRC_32 0xC0000000UL /*!<CRC Polynomial Mode - CRC32 */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Checksum, Write data Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CRC_CHECKSUM_COM 0x08000000UL /*!<CRC Checksum Complement */
|
||||
#define CRC_CHECKSUM_RVS 0x02000000UL /*!<CRC Checksum Reverse */
|
||||
#define CRC_WDATA_COM 0x04000000UL /*!<CRC Write Data Complement */
|
||||
#define CRC_WDATA_RVS 0x01000000UL /*!<CRC Write Data Reverse */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* CPU Write Data Length Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define CRC_CPU_WDATA_8 0x00000000UL /*!<CRC 8-bit CPU Write Data */
|
||||
#define CRC_CPU_WDATA_16 0x10000000UL /*!<CRC 16-bit CPU Write Data */
|
||||
#define CRC_CPU_WDATA_32 0x20000000UL /*!<CRC 32-bit CPU Write Data */
|
||||
|
||||
/*@}*/ /* end of group CRC_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup CRC_EXPORTED_FUNCTIONS CRC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable CRC Interrupt
|
||||
*
|
||||
* @param[in] u32Mask Interrupt mask. Valid values are:
|
||||
* - \ref CRC_DMAIER_CRC_BLKD_IE_Msk
|
||||
* - \ref CRC_DMAIER_CRC_TABORT_IE_Msk
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro enable the specify CRC interrupt function by u32Mask setting.
|
||||
*/
|
||||
#define CRC_ENABLE_INT(u32Mask) (CRC->DMAIER |= (u32Mask))
|
||||
|
||||
/**
|
||||
* @brief Disable CRC Interrupt
|
||||
*
|
||||
* @param[in] u32Mask Interrupt mask. Valid values are:
|
||||
* - \ref CRC_DMAIER_CRC_BLKD_IE_Msk
|
||||
* - \ref CRC_DMAIER_CRC_TABORT_IE_Msk
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro disable the specify CRC interrupt function by u32Mask setting.
|
||||
*/
|
||||
#define CRC_DISABLE_INT(u32Mask) (CRC->DMAIER &= ~(u32Mask))
|
||||
|
||||
/**
|
||||
* @brief Get CRC Interrupt Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return Interrupt Flag Status
|
||||
*
|
||||
* @details This macro gets the CRC interrupt flags.
|
||||
*/
|
||||
#define CRC_GET_INT_FLAG() ((uint32_t)(CRC->DMAISR))
|
||||
|
||||
/**
|
||||
* @brief Clear CRC Interrupt Flag
|
||||
*
|
||||
* @param[in] u32Mask Interrupt mask. Valid values are:
|
||||
* - \ref CRC_DMAISR_CRC_BLKD_IF_Msk
|
||||
* - \ref CRC_DMAISR_CRC_TABORT_IF_Msk
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro clear the specify CRC interrupt flag by u32Mask setting.
|
||||
*/
|
||||
#define CRC_CLR_INT_FLAG(u32Mask) (CRC->DMAISR = (u32Mask))
|
||||
|
||||
/**
|
||||
* @brief Set CRC seed value
|
||||
*
|
||||
* @param[in] u32Seed Seed value
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro set CRC seed value.
|
||||
*
|
||||
* @note User must to setting CRC_RST (CRC_CTL[1] CRC Engine Reset) to reload the new seed value
|
||||
* to CRC controller.
|
||||
*/
|
||||
#define CRC_SET_SEED(u32Seed) { CRC->SEED = (u32Seed); CRC->CTL |= CRC_CTL_CRC_RST_Msk; }
|
||||
|
||||
/**
|
||||
* @brief Get CRC Seed value
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return Seed Value
|
||||
*
|
||||
* @details This macro gets the current CRC seed value.
|
||||
*/
|
||||
#define CRC_GET_SEED() ((uint32_t)(CRC->SEED))
|
||||
|
||||
/**
|
||||
* @brief CRC write data
|
||||
*
|
||||
* @param[in] u32Data write data
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details User can write data directly by this macro to perform CRC operation.
|
||||
*/
|
||||
#define CRC_WRITE_DATA(u32Data) (CRC->WDATA = (u32Data))
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
void CRC_Open(uint32_t u32Mode, uint32_t u32Attribute, uint32_t u32Seed, uint32_t u32DataLen);
|
||||
void CRC_StartDMATransfer(uint32_t u32SrcAddr, uint32_t u32ByteCount);
|
||||
uint32_t CRC_GetChecksum(void);
|
||||
|
||||
/*@}*/ /* end of group CRC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group CRC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__CRC_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
481
NUC123/StdDriver/inc/fmc.h
Normal file
481
NUC123/StdDriver/inc/fmc.h
Normal file
@ -0,0 +1,481 @@
|
||||
/**************************************************************************//**
|
||||
* @file FMC.h
|
||||
* @version V3.0
|
||||
* $Revision: 10 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series Flash Memory Controller Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __FMC_H__
|
||||
#define __FMC_H__
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup FMC_Driver FMC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup FMC_EXPORTED_CONSTANTS FMC Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Define Base Address */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define FMC_APROM_BASE 0x00000000UL /*!< APROM Base Address */
|
||||
#define FMC_LDROM_BASE 0x00100000UL /*!< LDROM Base Address */
|
||||
#define FMC_CONFIG_BASE 0x00300000UL /*!< CONFIG Base Address */
|
||||
|
||||
#define FMC_FLASH_PAGE_SIZE 0x200 /*!< Flash Page Size (512 Bytes) */
|
||||
#define FMC_LDROM_SIZE 0x1000 /*!< LDROM Size (4K Bytes) */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ISPCON constant definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define FMC_ISPCON_BS_LDROM 0x2 /*!< ISPCON setting to select to boot from LDROM */
|
||||
#define FMC_ISPCON_BS_APROM 0x0 /*!< ISPCON setting to select to boot from APROM */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* ISPCMD constant definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define FMC_ISPCMD_READ 0x00 /*!< ISP Command: Read Flash */
|
||||
#define FMC_ISPCMD_PROGRAM 0x21 /*!< ISP Command: Program Flash */
|
||||
#define FMC_ISPCMD_PAGE_ERASE 0x22 /*!< ISP Command: Page Erase Flash */
|
||||
#define FMC_ISPCMD_VECMAP 0x2e /*!< ISP Command: Set VECMAP */
|
||||
#define FMC_ISPCMD_READ_UID 0x04 /*!< ISP Command: Read Unique ID */
|
||||
#define FMC_ISPCMD_READ_CID 0x0B /*!< ISP Command: Read Company ID */
|
||||
#define FMC_ISPCMD_READ_DID 0x0C /*!< ISP Command: Read Device ID */
|
||||
|
||||
|
||||
/*@}*/ /* end of group FMC_EXPORTED_CONSTANTS */
|
||||
|
||||
/** @addtogroup FMC_EXPORTED_FUNCTIONS FMC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* FMC Macro Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Enable ISP Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will set ISPEN bit of ISPCON control register to enable ISP function.
|
||||
*
|
||||
*/
|
||||
#define FMC_ENABLE_ISP() (FMC->ISPCON |= FMC_ISPCON_ISPEN_Msk)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable ISP Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will clear ISPEN bit of ISPCON control register to disable ISP function.
|
||||
*
|
||||
*/
|
||||
#define FMC_DISABLE_ISP() (FMC->ISPCON &= ~FMC_ISPCON_ISPEN_Msk)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable LDROM Update Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will set LDUEN bit of ISPCON control register to enable LDROM update function.
|
||||
* User needs to set LDUEN bit before they can update LDROM.
|
||||
*
|
||||
*/
|
||||
#define FMC_ENABLE_LD_UPDATE() (FMC->ISPCON |= FMC_ISPCON_LDUEN_Msk)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable LDROM Update Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will set ISPEN bit of ISPCON control register to disable LDROM update function.
|
||||
*
|
||||
*/
|
||||
#define FMC_DISABLE_LD_UPDATE() (FMC->ISPCON &= ~FMC_ISPCON_LDUEN_Msk) /*!< Disable LDROM Update Function */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable User Configuration Update Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will set CFGUEN bit of ISPCON control register to enable User Configuration update function.
|
||||
* User needs to set CFGUEN bit before they can update User Configuration area.
|
||||
*
|
||||
*/
|
||||
#define FMC_ENABLE_CFG_UPDATE() (FMC->ISPCON |= FMC_ISPCON_CFGUEN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable User Configuration Update Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will clear CFGUEN bit of ISPCON control register to disable User Configuration update function.
|
||||
*
|
||||
*/
|
||||
#define FMC_DISABLE_CFG_UPDATE() (FMC->ISPCON &= ~FMC_ISPCON_CFGUEN_Msk) /*!< Disable CONFIG Update Function */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable APROM Update Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will set APUEN bit of ISPCON control register to enable APROM update function.
|
||||
* User needs to set APUEN bit before they can update APROM in APROM boot mode.
|
||||
*
|
||||
*/
|
||||
#define FMC_ENABLE_AP_UPDATE() (FMC->ISPCON |= FMC_ISPCON_APUEN_Msk)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable APROM Update Function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will clear APUEN bit of ISPCON control register to disable APROM update function.
|
||||
*
|
||||
*/
|
||||
#define FMC_DISABLE_AP_UPDATE() (FMC->ISPCON &= ~FMC_ISPCON_APUEN_Msk) /*!< Disable APROM Update Function */
|
||||
|
||||
/**
|
||||
* @brief Get ISP fail flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 Previous ISP command execution result is successful
|
||||
* @retval 1 Previous ISP command execution result is fail
|
||||
*
|
||||
* @details ISPFF flag of ISPCON is used to indicate ISP command success or fail.
|
||||
* This function will return the ISPFF flag to identify ISP command OK or fail.
|
||||
*
|
||||
*/
|
||||
#define FMC_GET_FAIL_FLAG() ((FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) ? 1 : 0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Select booting from APROM
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details If MCU is working without IAP, user need to set BS bit of ISPCON and reset CPU to execute the code of LDROM/APROM.
|
||||
* This function is used to set BS bit of ISPCON to boot to APROM.
|
||||
*
|
||||
* @note To valid new BS bit setting, user also need to trigger CPU reset or System Reset Request after setting BS bit.
|
||||
*
|
||||
*/
|
||||
#define FMC_SET_APROM_BOOT() (FMC->ISPCON &= ~FMC_ISPCON_BS_Msk)
|
||||
|
||||
/**
|
||||
* @brief Select booting from APROM
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details If MCU is working without IAP, user need to set/clear BS bit of ISPCON and reset CPU to execute the code of APROM/LDROM.
|
||||
* This function is used to clear BS bit of ISPCON to boot to LDROM.
|
||||
*
|
||||
* @note To valid new BS bit setting, user also need to trigger CPU reset or System Reset Request after clear BS bit.
|
||||
*
|
||||
*/
|
||||
#define FMC_SET_LDROM_BOOT() (FMC->ISPCON |= FMC_ISPCON_BS_Msk)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* inline functions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Program 32-bit data into specified address of flash
|
||||
*
|
||||
* @param[in] u32addr Flash address include APROM, LDROM, Data Flash, and CONFIG
|
||||
* @param[in] u32data 32-bit Data to program
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To program word data into Flash include APROM, LDROM, Data Flash, and CONFIG.
|
||||
* The corresponding functions in CONFIG are listed in FMC section of Technical Reference Manual.
|
||||
*
|
||||
*/
|
||||
static __INLINE void FMC_Write(uint32_t u32addr, uint32_t u32data)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_PROGRAM; /* Set ISP Command Code */
|
||||
FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be word alignment. */
|
||||
FMC->ISPDAT = u32data; /* Set Data to Program */
|
||||
FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG); /* Waiting for ISP Done */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read 32-bit Data from specified address of flash
|
||||
*
|
||||
* @param[in] u32addr Flash address include APROM, LDROM, Data Flash, and CONFIG
|
||||
*
|
||||
* @return The data of specified address
|
||||
*
|
||||
* @details To read word data from Flash include APROM, LDROM, Data Flash, and CONFIG.
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t FMC_Read(uint32_t u32addr)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ; /* Set ISP Command Code */
|
||||
FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be word alignment. */
|
||||
FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG); /* Waiting for ISP Done */
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Flash page erase
|
||||
*
|
||||
* @param[in] u32addr Flash address including APROM, LDROM, Data Flash, and CONFIG
|
||||
*
|
||||
* @details To do flash page erase. The target address could be APROM, LDROM, Data Flash, or CONFIG.
|
||||
* The page size is 512 bytes.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -1 Erase failed
|
||||
*
|
||||
*/
|
||||
static __INLINE int32_t FMC_Erase(uint32_t u32addr)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; /* Set ISP Command Code */
|
||||
FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be page alignment. */
|
||||
FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG); /* Waiting for ISP Done */
|
||||
|
||||
/* Check ISPFF flag to know whether erase OK or fail. */
|
||||
if(FMC->ISPCON & FMC_ISPCON_ISPFF_Msk)
|
||||
{
|
||||
FMC->ISPCON |= FMC_ISPCON_ISPFF_Msk;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Unique ID
|
||||
*
|
||||
* @param[in] u8index UID index. 0 = UID[31:0], 1 = UID[63:32], 2 = UID[95:64]
|
||||
*
|
||||
* @return The 32-bit unique ID data of specified UID index.
|
||||
*
|
||||
* @details To read out 96-bit Unique ID.
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t FMC_ReadUID(uint8_t u8index)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_UID; /* Set ISP Command Code */
|
||||
FMC->ISPADR = (u8index << 2); /* Set UID Address. It must be word alignment. */
|
||||
FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG); /* Waiting for ISP Done */
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read company ID
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The company ID (32-bit)
|
||||
*
|
||||
* @details The company ID of Nuvoton is fixed to be 0xDA
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t FMC_ReadCID(void)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_CID; /* Set ISP Command Code */
|
||||
FMC->ISPADR = 0x0; /* Must keep 0x0 when read CID */
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; /* Waiting for ISP Done */
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read device ID
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The device ID (32-bit)
|
||||
*
|
||||
* @details This function is used to read device ID.
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t FMC_ReadDID(void)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_DID; /* Set ISP Command Code */
|
||||
FMC->ISPADR = 0; /* Must keep 0x0 when read DID */
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk); /* Waiting for ISP Done */
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read product ID
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The product ID (32-bit)
|
||||
*
|
||||
* @details This function is used to read product ID.
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t FMC_ReadPID(void)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_DID; /* Set ISP Command Code */
|
||||
FMC->ISPADR = 0x04; /* Must keep 0x4 when read PID */
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk); /* Waiting for ISP Done */
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief To read UCID
|
||||
*
|
||||
* @param[in] u32Index Index of the UCID to read. u32Index must be 0, 1, 2, or 3.
|
||||
*
|
||||
* @return The UCID of specified index
|
||||
*
|
||||
* @details This function is used to read unique chip ID (UCID).
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t FMC_ReadUCID(uint32_t u32Index)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_UID; /* Set ISP Command Code */
|
||||
FMC->ISPADR = (0x04 * u32Index) + 0x10; /* The UCID is at offset 0x10 with word alignment. */
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk); /* Waiting for ISP Done */
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set vector mapping address
|
||||
*
|
||||
* @param[in] u32PageAddr The page address to remap to address 0x0. The address must be page alignment.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to set VECMAP to map specified page to vector page (0x0).
|
||||
*
|
||||
* @note
|
||||
* VECMAP only valid when new IAP function is enabled. (CBS = 10'b or 00'b)
|
||||
*
|
||||
*/
|
||||
static __INLINE void FMC_SetVectorPageAddr(uint32_t u32PageAddr)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_VECMAP; /* Set ISP Command Code */
|
||||
FMC->ISPADR = u32PageAddr; /* The address of specified page which will be map to address 0x0. It must be page alignment. */
|
||||
FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
|
||||
__ISB(); /* To make sure ISP/CPU be Synchronized */
|
||||
while(FMC->ISPTRG); /* Waiting for ISP Done */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get current vector mapping address.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The current vector mapping address.
|
||||
*
|
||||
* @details To get VECMAP value which is the page address for remapping to vector page (0x0).
|
||||
*
|
||||
* @note
|
||||
* VECMAP only valid when new IAP function is enabled. (CBS = 10'b or 00'b)
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t FMC_GetVECMAP(void)
|
||||
{
|
||||
return (FMC->ISPSTA & FMC_ISPSTA_VECMAP_Msk);
|
||||
}
|
||||
|
||||
extern void FMC_Open(void);
|
||||
extern void FMC_Close(void);
|
||||
extern void FMC_EnableAPUpdate(void);
|
||||
extern void FMC_DisableAPUpdate(void);
|
||||
extern void FMC_EnableConfigUpdate(void);
|
||||
extern void FMC_DisableConfigUpdate(void);
|
||||
extern void FMC_EnableLDUpdate(void);
|
||||
extern void FMC_DisableLDUpdate(void);
|
||||
extern int32_t FMC_ReadConfig(uint32_t *u32Config, uint32_t u32Count);
|
||||
extern int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count);
|
||||
extern void FMC_SetBootSource(int32_t i32BootSrc);
|
||||
extern int32_t FMC_GetBootSource(void);
|
||||
extern uint32_t FMC_ReadDataFlashBaseAddr(void);
|
||||
|
||||
/*@}*/ /* end of group FMC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group FMC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
458
NUC123/StdDriver/inc/gpio.h
Normal file
458
NUC123/StdDriver/inc/gpio.h
Normal file
@ -0,0 +1,458 @@
|
||||
/**************************************************************************//**
|
||||
* @file GPIO.h
|
||||
* @version V3.00
|
||||
* $Revision: 13 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series General Purpose I/O Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __GPIO_H__
|
||||
#define __GPIO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup GPIO_Driver GPIO Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup GPIO_EXPORTED_CONSTANTS GPIO Exported Constants
|
||||
@{
|
||||
*/
|
||||
#define GPIO_PIN_MAX 16 /*!< Specify Maximum Pins of Each GPIO Port */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* PMD Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define GPIO_PMD_INPUT 0x0UL /*!< Input Mode */
|
||||
#define GPIO_PMD_OUTPUT 0x1UL /*!< Output Mode */
|
||||
#define GPIO_PMD_OPEN_DRAIN 0x2UL /*!< Open-Drain Mode */
|
||||
#define GPIO_PMD_QUASI 0x3UL /*!< Quasi-bidirectional Mode */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* GPIO Interrupt Type Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define GPIO_INT_RISING 0x00010000UL /*!< Interrupt enable by Input Rising Edge */
|
||||
#define GPIO_INT_FALLING 0x00000001UL /*!< Interrupt enable by Input Falling Edge */
|
||||
#define GPIO_INT_BOTH_EDGE 0x00010001UL /*!< Interrupt enable by both Rising Edge and Falling Edge */
|
||||
#define GPIO_INT_HIGH 0x01010000UL /*!< Interrupt enable by Level-High */
|
||||
#define GPIO_INT_LOW 0x01000001UL /*!< Interrupt enable by Level-Level */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* IMD Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define GPIO_IMD_EDGE 0UL /*!< IMD Setting for Edge Trigger Mode */
|
||||
#define GPIO_IMD_LEVEL 1UL /*!< IMD Setting for Edge Level Mode */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* DBNCECON Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define GPIO_INT_CLK_ON 0x00000020UL /*!< DBNCECON setting for all IO pins edge detection circuit is always active after reset */
|
||||
#define GPIO_INT_CLK_OFF 0x00000000UL /*!< DBNCECON setting for edge detection circuit is active only if IO pin corresponding GPIOx_IEN bit is set to 1 */
|
||||
|
||||
#define GPIO_DBCLKSRC_LIRC 0x00000010UL /*!< DBNCECON setting for de-bounce counter clock source is the internal 10 kHz */
|
||||
#define GPIO_DBCLKSRC_HCLK 0x00000000UL /*!< DBNCECON setting for de-bounce counter clock source is the HCLK */
|
||||
|
||||
#define GPIO_DBCLKSEL_1 0x00000000UL /*!< DBNCECON setting for sampling cycle = 1 clocks */
|
||||
#define GPIO_DBCLKSEL_2 0x00000001UL /*!< DBNCECON setting for sampling cycle = 2 clocks */
|
||||
#define GPIO_DBCLKSEL_4 0x00000002UL /*!< DBNCECON setting for sampling cycle = 4 clocks */
|
||||
#define GPIO_DBCLKSEL_8 0x00000003UL /*!< DBNCECON setting for sampling cycle = 8 clocks */
|
||||
#define GPIO_DBCLKSEL_16 0x00000004UL /*!< DBNCECON setting for sampling cycle = 16 clocks */
|
||||
#define GPIO_DBCLKSEL_32 0x00000005UL /*!< DBNCECON setting for sampling cycle = 32 clocks */
|
||||
#define GPIO_DBCLKSEL_64 0x00000006UL /*!< DBNCECON setting for sampling cycle = 64 clocks */
|
||||
#define GPIO_DBCLKSEL_128 0x00000007UL /*!< DBNCECON setting for sampling cycle = 128 clocks */
|
||||
#define GPIO_DBCLKSEL_256 0x00000008UL /*!< DBNCECON setting for sampling cycle = 256 clocks */
|
||||
#define GPIO_DBCLKSEL_512 0x00000009UL /*!< DBNCECON setting for sampling cycle = 512 clocks */
|
||||
#define GPIO_DBCLKSEL_1024 0x0000000AUL /*!< DBNCECON setting for sampling cycle = 1024 clocks */
|
||||
#define GPIO_DBCLKSEL_2048 0x0000000BUL /*!< DBNCECON setting for sampling cycle = 2048 clocks */
|
||||
#define GPIO_DBCLKSEL_4096 0x0000000CUL /*!< DBNCECON setting for sampling cycle = 4096 clocks */
|
||||
#define GPIO_DBCLKSEL_8192 0x0000000DUL /*!< DBNCECON setting for sampling cycle = 8192 clocks */
|
||||
#define GPIO_DBCLKSEL_16384 0x0000000EUL /*!< DBNCECON setting for sampling cycle = 16384 clocks */
|
||||
#define GPIO_DBCLKSEL_32768 0x0000000FUL /*!< DBNCECON setting for sampling cycle = 32768 clocks */
|
||||
|
||||
|
||||
/* Define GPIO Pin Data Input/Output. It could be used to control each I/O pin by pin address mapping.
|
||||
Example 1:
|
||||
|
||||
PA10 = 1;
|
||||
|
||||
It is used to set GPIO PA.10 to high;
|
||||
|
||||
Example 2:
|
||||
|
||||
if (PA10)
|
||||
PA10 = 0;
|
||||
|
||||
If GPIO PA.10 pin status is high, then set GPIO PA.10 data output to low.
|
||||
*/
|
||||
#define GPIO_PIN_DATA(port, pin) (*((volatile uint32_t *)((GPIO_PIN_DATA_BASE+(0x40*(port))) + ((pin)<<2))))
|
||||
#define PA10 GPIO_PIN_DATA(0, 10) /*!< Specify PA.10 Pin Data Input/Output */
|
||||
#define PA11 GPIO_PIN_DATA(0, 11) /*!< Specify PA.11 Pin Data Input/Output */
|
||||
#define PA12 GPIO_PIN_DATA(0, 12) /*!< Specify PA.12 Pin Data Input/Output */
|
||||
#define PA13 GPIO_PIN_DATA(0, 13) /*!< Specify PA.13 Pin Data Input/Output */
|
||||
#define PA14 GPIO_PIN_DATA(0, 14) /*!< Specify PA.14 Pin Data Input/Output */
|
||||
#define PA15 GPIO_PIN_DATA(0, 15) /*!< Specify PA.15 Pin Data Input/Output */
|
||||
#define PB0 GPIO_PIN_DATA(1, 0 ) /*!< Specify PB.0 Pin Data Input/Output */
|
||||
#define PB1 GPIO_PIN_DATA(1, 1 ) /*!< Specify PB.1 Pin Data Input/Output */
|
||||
#define PB2 GPIO_PIN_DATA(1, 2 ) /*!< Specify PB.2 Pin Data Input/Output */
|
||||
#define PB3 GPIO_PIN_DATA(1, 3 ) /*!< Specify PB.3 Pin Data Input/Output */
|
||||
#define PB4 GPIO_PIN_DATA(1, 4 ) /*!< Specify PB.4 Pin Data Input/Output */
|
||||
#define PB5 GPIO_PIN_DATA(1, 5 ) /*!< Specify PB.5 Pin Data Input/Output */
|
||||
#define PB6 GPIO_PIN_DATA(1, 6 ) /*!< Specify PB.6 Pin Data Input/Output */
|
||||
#define PB7 GPIO_PIN_DATA(1, 7 ) /*!< Specify PB.7 Pin Data Input/Output */
|
||||
#define PB8 GPIO_PIN_DATA(1, 8 ) /*!< Specify PB.8 Pin Data Input/Output */
|
||||
#define PB9 GPIO_PIN_DATA(1, 9 ) /*!< Specify PB.9 Pin Data Input/Output */
|
||||
#define PB10 GPIO_PIN_DATA(1, 10) /*!< Specify PB.10 Pin Data Input/Output */
|
||||
#define PB12 GPIO_PIN_DATA(1, 12) /*!< Specify PB.12 Pin Data Input/Output */
|
||||
#define PB13 GPIO_PIN_DATA(1, 13) /*!< Specify PB.13 Pin Data Input/Output */
|
||||
#define PB14 GPIO_PIN_DATA(1, 14) /*!< Specify PB.14 Pin Data Input/Output */
|
||||
#define PB15 GPIO_PIN_DATA(1, 15) /*!< Specify PB.15 Pin Data Input/Output */
|
||||
#define PC0 GPIO_PIN_DATA(2, 0 ) /*!< Specify PC.0 Pin Data Input/Output */
|
||||
#define PC1 GPIO_PIN_DATA(2, 1 ) /*!< Specify PC.1 Pin Data Input/Output */
|
||||
#define PC2 GPIO_PIN_DATA(2, 2 ) /*!< Specify PC.2 Pin Data Input/Output */
|
||||
#define PC3 GPIO_PIN_DATA(2, 3 ) /*!< Specify PC.3 Pin Data Input/Output */
|
||||
#define PC4 GPIO_PIN_DATA(2, 4 ) /*!< Specify PC.4 Pin Data Input/Output */
|
||||
#define PC5 GPIO_PIN_DATA(2, 5 ) /*!< Specify PC.5 Pin Data Input/Output */
|
||||
#define PC8 GPIO_PIN_DATA(2, 8 ) /*!< Specify PC.8 Pin Data Input/Output */
|
||||
#define PC9 GPIO_PIN_DATA(2, 9 ) /*!< Specify PC.9 Pin Data Input/Output */
|
||||
#define PC10 GPIO_PIN_DATA(2, 10) /*!< Specify PC.10 Pin Data Input/Output */
|
||||
#define PC11 GPIO_PIN_DATA(2, 11) /*!< Specify PC.11 Pin Data Input/Output */
|
||||
#define PC12 GPIO_PIN_DATA(2, 12) /*!< Specify PC.12 Pin Data Input/Output */
|
||||
#define PC13 GPIO_PIN_DATA(2, 13) /*!< Specify PC.13 Pin Data Input/Output */
|
||||
#define PD0 GPIO_PIN_DATA(3, 0 ) /*!< Specify PD.0 Pin Data Input/Output */
|
||||
#define PD1 GPIO_PIN_DATA(3, 1 ) /*!< Specify PD.1 Pin Data Input/Output */
|
||||
#define PD2 GPIO_PIN_DATA(3, 2 ) /*!< Specify PD.2 Pin Data Input/Output */
|
||||
#define PD3 GPIO_PIN_DATA(3, 3 ) /*!< Specify PD.3 Pin Data Input/Output */
|
||||
#define PD4 GPIO_PIN_DATA(3, 4 ) /*!< Specify PD.4 Pin Data Input/Output */
|
||||
#define PD5 GPIO_PIN_DATA(3, 5 ) /*!< Specify PD.5 Pin Data Input/Output */
|
||||
#define PD8 GPIO_PIN_DATA(3, 8 ) /*!< Specify PD.8 Pin Data Input/Output */
|
||||
#define PD9 GPIO_PIN_DATA(3, 9 ) /*!< Specify PD.9 Pin Data Input/Output */
|
||||
#define PD10 GPIO_PIN_DATA(3, 10) /*!< Specify PD.10 Pin Data Input/Output */
|
||||
#define PD11 GPIO_PIN_DATA(3, 11) /*!< Specify PD.11 Pin Data Input/Output */
|
||||
#define PF0 GPIO_PIN_DATA(5, 0 ) /*!< Specify PF.0 Pin Data Input/Output */
|
||||
#define PF1 GPIO_PIN_DATA(5, 1 ) /*!< Specify PF.1 Pin Data Input/Output */
|
||||
#define PF2 GPIO_PIN_DATA(5, 2 ) /*!< Specify PF.2 Pin Data Input/Output */
|
||||
#define PF3 GPIO_PIN_DATA(5, 3 ) /*!< Specify PF.3 Pin Data Input/Output */
|
||||
|
||||
|
||||
/*@}*/ /* end of group GPIO_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clear GPIO Pin Interrupt Flag
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Clear the interrupt status of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_CLR_INT_FLAG(port, u32PinMask) ((port)->ISRC = (u32PinMask))
|
||||
|
||||
/**
|
||||
* @brief Disable Pin De-bounce Function
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Disable the interrupt de-bounce function of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_DISABLE_DEBOUNCE(port, u32PinMask) ((port)->DBEN &= ~(u32PinMask))
|
||||
|
||||
/**
|
||||
* @brief Enable Pin De-bounce Function
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable the interrupt de-bounce function of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_ENABLE_DEBOUNCE(port, u32PinMask) ((port)->DBEN |= (u32PinMask))
|
||||
|
||||
/**
|
||||
* @brief Disable I/O Digital Input Path
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Disable I/O digital input path of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_DISABLE_DIGITAL_PATH(port, u32PinMask) ((port)->OFFD |= ((u32PinMask)<<16))
|
||||
|
||||
/**
|
||||
* @brief Enable I/O Digital Input Path
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port \n.
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable I/O digital input path of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_ENABLE_DIGITAL_PATH(port, u32PinMask) ((port)->OFFD &= ~((u32PinMask)<<16))
|
||||
|
||||
/**
|
||||
* @brief Disable I/O DOUT mask
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Disable I/O DOUT mask of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_DISABLE_DOUT_MASK(port, u32PinMask) ((port)->DMASK &= ~(u32PinMask))
|
||||
|
||||
/**
|
||||
* @brief Enable I/O DOUT mask
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable I/O DOUT mask of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_ENABLE_DOUT_MASK(port, u32PinMask) ((port)->DMASK |= (u32PinMask))
|
||||
|
||||
/**
|
||||
* @brief Get GPIO Pin Interrupt Flag
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
*
|
||||
* @retval 0 No interrupt at specified GPIO pin
|
||||
* @retval 1 The specified GPIO pin generate an interrupt
|
||||
*
|
||||
* @details Get the interrupt status of specified GPIO pin.
|
||||
*/
|
||||
#define GPIO_GET_INT_FLAG(port, u32PinMask) ((port)->ISRC & (u32PinMask))
|
||||
|
||||
/**
|
||||
* @brief Set De-bounce Sampling Cycle Time
|
||||
*
|
||||
* @param[in] u32ClkSrc The de-bounce counter clock source. It could be :
|
||||
* - \ref GPIO_DBCLKSRC_HCLK
|
||||
* - \ref GPIO_DBCLKSRC_LIRC
|
||||
* @param[in] u32ClkSel The de-bounce sampling cycle selection. It could be :
|
||||
* - \ref GPIO_DBCLKSEL_1
|
||||
* - \ref GPIO_DBCLKSEL_2
|
||||
* - \ref GPIO_DBCLKSEL_4
|
||||
* - \ref GPIO_DBCLKSEL_8
|
||||
* - \ref GPIO_DBCLKSEL_16
|
||||
* - \ref GPIO_DBCLKSEL_32
|
||||
* - \ref GPIO_DBCLKSEL_64
|
||||
* - \ref GPIO_DBCLKSEL_128
|
||||
* - \ref GPIO_DBCLKSEL_256
|
||||
* - \ref GPIO_DBCLKSEL_512
|
||||
* - \ref GPIO_DBCLKSEL_1024
|
||||
* - \ref GPIO_DBCLKSEL_2048
|
||||
* - \ref GPIO_DBCLKSEL_4096
|
||||
* - \ref GPIO_DBCLKSEL_8192
|
||||
* - \ref GPIO_DBCLKSEL_16384
|
||||
* - \ref GPIO_DBCLKSEL_32768
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set the interrupt de-bounce sampling cycle time based on the debounce counter clock source. \n
|
||||
* Example: GPIO_SET_DEBOUNCE_TIME(GPIO_DBNCECON_DBCLKSRC_LIRC, GPIO_DBCLKSEL_4). \n
|
||||
* It's meaning the De-debounce counter clock source is internal 10 KHz and sampling cycle selection is 4. \n
|
||||
* Then the target de-bounce sampling cycle time is (4)*(1/(10*1000)) s = 4*0.0001 s = 400 us,
|
||||
* and system will sampling interrupt input once per 400 us.
|
||||
*/
|
||||
#define GPIO_SET_DEBOUNCE_TIME(u32ClkSrc, u32ClkSel) (GPIO->DBNCECON = (GPIO_DBNCECON_ICLK_ON_Msk | (u32ClkSrc) | (u32ClkSel)))
|
||||
|
||||
/**
|
||||
* @brief Get GPIO Port IN Data
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
*
|
||||
* @return The specified port data
|
||||
*
|
||||
* @details Get the PIN register of specified GPIO port.
|
||||
*/
|
||||
#define GPIO_GET_IN_DATA(port) ((port)->PIN)
|
||||
|
||||
/**
|
||||
* @brief Set GPIO Port OUT Data
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32Data GPIO port data.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set the Data into specified GPIO port.
|
||||
*/
|
||||
#define GPIO_SET_OUT_DATA(port, u32Data) ((port)->DOUT = (u32Data))
|
||||
|
||||
/**
|
||||
* @brief Toggle Specified GPIO pin
|
||||
*
|
||||
* @param[in] u32Pin Pxy
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Toggle the specified GPIO pint.
|
||||
*/
|
||||
#define GPIO_TOGGLE(u32Pin) ((u32Pin) ^= 1)
|
||||
|
||||
/**
|
||||
* @brief Enable External GPIO Interrupt 0
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. \n
|
||||
* It could be 10 ~ 15 for PA GPIO port. \n
|
||||
* It could be 0 ~ 10 and 12 ~ 15 for PB GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 13 for PC GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 11 for PD GPIO port. \n
|
||||
* It could be 0 ~ 3 for PF GPIO port.
|
||||
* @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be \n
|
||||
* - \ref GPIO_INT_RISING
|
||||
* - \ref GPIO_INT_FALLING
|
||||
* - \ref GPIO_INT_BOTH_EDGE
|
||||
* - \ref GPIO_INT_HIGH
|
||||
* - \ref GPIO_INT_LOW
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable specified GPIO pin interrupt.
|
||||
*/
|
||||
#define GPIO_EnableEINT0 GPIO_EnableInt
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable External GPIO Interrupt 0
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. \n
|
||||
* It could be 10 ~ 15 for PA GPIO port. \n
|
||||
* It could be 0 ~ 10 and 12 ~ 15 for PB GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 13 for PC GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 11 for PD GPIO port. \n
|
||||
* It could be 0 ~ 3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable specified GPIO pin interrupt.
|
||||
*/
|
||||
#define GPIO_DisableEINT0 GPIO_DisableInt
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable External GPIO Interrupt 1
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. \n
|
||||
* It could be 10 ~ 15 for PA GPIO port. \n
|
||||
* It could be 0 ~ 10 and 12 ~ 15 for PB GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 13 for PC GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 11 for PD GPIO port. \n
|
||||
* It could be 0 ~ 3 for PF GPIO port.
|
||||
* @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be \n
|
||||
* GPIO_INT_RISING, GPIO_INT_FALLING, GPIO_INT_BOTH_EDGE, GPIO_INT_HIGH, GPIO_INT_LOW.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable specified GPIO pin interrupt.
|
||||
*/
|
||||
#define GPIO_EnableEINT1 GPIO_EnableInt
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable External GPIO Interrupt 1
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. \n
|
||||
* It could be 10 ~ 15 for PA GPIO port. \n
|
||||
* It could be 0 ~ 10 and 12 ~ 15 for PB GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 13 for PC GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 11 for PD GPIO port. \n
|
||||
* It could be 0 ~ 3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable specified GPIO pin interrupt.
|
||||
*/
|
||||
#define GPIO_DisableEINT1 GPIO_DisableInt
|
||||
|
||||
|
||||
void GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode);
|
||||
void GPIO_EnableInt(GPIO_T *port, uint32_t u32Pin, uint32_t u32IntAttribs);
|
||||
void GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin);
|
||||
|
||||
|
||||
/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group GPIO_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__GPIO_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
212
NUC123/StdDriver/inc/i2c.h
Normal file
212
NUC123/StdDriver/inc/i2c.h
Normal file
@ -0,0 +1,212 @@
|
||||
/**************************************************************************//**
|
||||
* @file I2C.h
|
||||
* @version V3.0
|
||||
* $Revision: 10 $
|
||||
* $Date: 16/06/22 11:46a $
|
||||
* @brief NUC123 Series I2C Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __I2C_H__
|
||||
#define __I2C_H__
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C_Driver I2C Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C_EXPORTED_CONSTANTS I2C Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* I2CON constant definitions. */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define I2C_I2CON_STA_STO_SI 0x38UL /*!< I2CON setting for I2C control bits. It would set STA, STO and SI bits */
|
||||
#define I2C_I2CON_STA_STO_SI_AA 0x3CUL /*!< I2CON setting for I2C control bits. It would set STA, STO, SI and AA bits */
|
||||
#define I2C_I2CON_STA_SI 0x28UL /*!< I2CON setting for I2C control bits. It would set STA and SI bits */
|
||||
#define I2C_I2CON_STA_SI_AA 0x2CUL /*!< I2CON setting for I2C control bits. It would set STA, SI and AA bits */
|
||||
#define I2C_I2CON_STO_SI 0x18UL /*!< I2CON setting for I2C control bits. It would set STO and SI bits */
|
||||
#define I2C_I2CON_STO_SI_AA 0x1CUL /*!< I2CON setting for I2C control bits. It would set STO, SI and AA bits */
|
||||
#define I2C_I2CON_SI 0x08UL /*!< I2CON setting for I2C control bits. It would set SI bit */
|
||||
#define I2C_I2CON_SI_AA 0x0CUL /*!< I2CON setting for I2C control bits. It would set SI and AA bits */
|
||||
#define I2C_I2CON_STA 0x20UL /*!< I2CON setting for I2C control bits. It would set STA bit */
|
||||
#define I2C_I2CON_STO 0x10UL /*!< I2CON setting for I2C control bits. It would set STO bit */
|
||||
#define I2C_I2CON_AA 0x04UL /*!< I2CON setting for I2C control bits. It would set AA bit */
|
||||
|
||||
#define I2C_GCMODE_ENABLE 1 /*!< Enable I2C GC Mode */
|
||||
#define I2C_GCMODE_DISABLE 0 /*!< Disable I2C GC Mode */
|
||||
|
||||
/*@}*/ /* end of group I2C_EXPORTED_CONSTANTS */
|
||||
|
||||
/** @addtogroup I2C_EXPORTED_FUNCTIONS I2C Exported Functions
|
||||
@{
|
||||
*/
|
||||
/**
|
||||
* @brief The macro is used to set I2C bus condition at One Time
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
* @param[in] u8Ctrl A byte writes to I2C control register
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set I2CON register to control I2C bus conditions of START, STOP, SI, ACK.
|
||||
*/
|
||||
#define I2C_SET_CONTROL_REG(i2c, u8Ctrl) ((i2c)->I2CON = ((i2c)->I2CON & ~0x3c) | (u8Ctrl))
|
||||
|
||||
/**
|
||||
* @brief The macro is used to set START condition of I2C Bus
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set the I2C bus START condition in I2CON register.
|
||||
*/
|
||||
#define I2C_START(i2c) ((i2c)->I2CON = ((i2c)->I2CON | I2C_I2CON_SI_Msk) | I2C_I2CON_STA_Msk)
|
||||
|
||||
/**
|
||||
* @brief The macro is used to set STOP condition of I2C Bus
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set the I2C bus STOP condition in I2CON register.
|
||||
*/
|
||||
#define I2C_STOP(i2c) ((i2c)->I2CON = ((i2c)->I2CON | I2C_I2CON_SI_Msk) | I2C_I2CON_STO_Msk)
|
||||
|
||||
/**
|
||||
* @brief The macro is used to wait I2C bus status get ready
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details When a new status is presented of I2C bus, the SI flag will be set in I2CON register.
|
||||
*/
|
||||
#define I2C_WAIT_READY(i2c) while(!((i2c)->I2CON & I2C_I2CON_SI_Msk))
|
||||
|
||||
/**
|
||||
* @brief The macro is used to Read I2C Bus Data Register
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @return A byte of I2C data register
|
||||
*
|
||||
* @details I2C controller read data from bus and save it in I2CDAT register.
|
||||
*/
|
||||
#define I2C_GET_DATA(i2c) ((i2c)->I2CDAT)
|
||||
|
||||
/**
|
||||
* @brief Write a Data to I2C Data Register
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
* @param[in] u8Data A byte that writes to data register
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details When write a data to I2CDAT register, the I2C controller will shift it to I2C bus.
|
||||
*/
|
||||
#define I2C_SET_DATA(i2c, u8Data) ((i2c)->I2CDAT = (u8Data))
|
||||
|
||||
/**
|
||||
* @brief Get I2C Bus status code
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @return I2C status code
|
||||
*
|
||||
* @details To get this status code to monitor I2C bus event.
|
||||
*/
|
||||
#define I2C_GET_STATUS(i2c) ((i2c)->I2CSTATUS)
|
||||
|
||||
/**
|
||||
* @brief Get Time-out flag from I2C Bus
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @retval 0 I2C Bus time-out is not happened
|
||||
* @retval 1 I2C Bus time-out is happened
|
||||
*
|
||||
* @details When I2C bus occurs time-out event, the time-out flag will be set.
|
||||
*/
|
||||
#define I2C_GET_TIMEOUT_FLAG(i2c) ( ((i2c)->I2CTOC & I2C_I2CTOC_TIF_Msk) == I2C_I2CTOC_TIF_Msk ? 1:0 )
|
||||
|
||||
/**
|
||||
* @brief To get wake-up flag from I2C Bus
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @retval 0 Chip is not woken-up from power-down mode
|
||||
* @retval 1 Chip is woken-up from power-down mode
|
||||
*
|
||||
* @details I2C bus occurs wake-up event, wake-up flag will be set.
|
||||
*/
|
||||
#define I2C_GET_WAKEUP_FLAG(i2c) ( ((i2c)->I2CWKUPSTS & I2C_I2CWKUPSTS_WKUPIF_Msk) == I2C_I2CWKUPSTS_WKUPIF_Msk ? 1:0 )
|
||||
|
||||
/**
|
||||
* @brief To clear wake-up flag
|
||||
*
|
||||
* @param[in] i2c Specify I2C port
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details If wake-up flag is set, use this macro to clear it.
|
||||
*/
|
||||
#define I2C_CLEAR_WAKEUP_FLAG(i2c) ((i2c)->I2CWKUPSTS |= I2C_I2CWKUPSTS_WKUPIF_Msk)
|
||||
|
||||
void I2C_ClearTimeoutFlag(I2C_T *i2c);
|
||||
void I2C_Close(I2C_T *i2c);
|
||||
void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack);
|
||||
void I2C_DisableInt(I2C_T *i2c);
|
||||
void I2C_EnableInt(I2C_T *i2c);
|
||||
uint32_t I2C_GetBusClockFreq(I2C_T *i2c);
|
||||
uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock);
|
||||
uint32_t I2C_GetIntFlag(I2C_T *i2c);
|
||||
uint32_t I2C_GetStatus(I2C_T *i2c);
|
||||
uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock);
|
||||
uint8_t I2C_GetData(I2C_T *i2c);
|
||||
void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode);
|
||||
void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask);
|
||||
void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout);
|
||||
void I2C_DisableTimeout(I2C_T *i2c);
|
||||
void I2C_EnableWakeup(I2C_T *i2c);
|
||||
void I2C_DisableWakeup(I2C_T *i2c);
|
||||
void I2C_SetData(I2C_T *i2c, uint8_t u8Data);
|
||||
uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, const uint8_t data);
|
||||
uint32_t I2C_WriteMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, const uint8_t *data, uint32_t u32wLen);
|
||||
uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, const uint8_t data);
|
||||
uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, const uint8_t *data, uint32_t u32wLen);
|
||||
uint8_t I2C_WriteByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, const uint8_t data);
|
||||
uint32_t I2C_WriteMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, const uint8_t *data, uint32_t u32wLen);
|
||||
uint8_t I2C_ReadByte(I2C_T *i2c, uint8_t u8SlaveAddr);
|
||||
uint32_t I2C_ReadMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t *rdata, uint32_t u32rLen);
|
||||
uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr);
|
||||
uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t *rdata, uint32_t u32rLen);
|
||||
uint8_t I2C_ReadByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr);
|
||||
uint32_t I2C_ReadMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t *rdata, uint32_t u32rLen);
|
||||
/*@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group I2C_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //__I2C_H__
|
324
NUC123/StdDriver/inc/i2s.h
Normal file
324
NUC123/StdDriver/inc/i2s.h
Normal file
@ -0,0 +1,324 @@
|
||||
/**************************************************************************//**
|
||||
* @file i2s.h
|
||||
* @version V3.0
|
||||
* $Revision: 6 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series I2S driver header file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
******************************************************************************/
|
||||
#ifndef __I2S_H__
|
||||
#define __I2S_H__
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_Driver I2S Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_EXPORTED_CONSTANTS I2S Exported Constants
|
||||
@{
|
||||
*/
|
||||
#define I2S_DATABIT_8 (0 << I2S_CON_WORDWIDTH_Pos) /*!< I2S data width is 8-bit */
|
||||
#define I2S_DATABIT_16 (1 << I2S_CON_WORDWIDTH_Pos) /*!< I2S data width is 16-bit */
|
||||
#define I2S_DATABIT_24 (2 << I2S_CON_WORDWIDTH_Pos) /*!< I2S data width is 24-bit */
|
||||
#define I2S_DATABIT_32 (3 << I2S_CON_WORDWIDTH_Pos) /*!< I2S data width is 32-bit */
|
||||
|
||||
/* Audio Format */
|
||||
#define I2S_MONO I2S_CON_MONO_Msk /*!< Mono channel */
|
||||
#define I2S_STEREO 0 /*!< Stereo channel */
|
||||
|
||||
/* I2S Data Format */
|
||||
#define I2S_FORMAT_MSB I2S_CON_FORMAT_Msk /*!< MSB data format */
|
||||
#define I2S_FORMAT_I2S 0 /*!< I2S data format */
|
||||
#define I2S_FORMAT_PCM_A I2S_CON_PCM_Msk /*!< PCM mode A data format */
|
||||
#define I2S_FORMAT_PCM_B (I2S_CON_PCM_Msk|I2S_CON_FORMAT_Msk) /*!< PCM mode B data format */
|
||||
|
||||
/* I2S Operation mode */
|
||||
#define I2S_MODE_SLAVE I2S_CON_SLAVE_Msk /*!< As slave mode */
|
||||
#define I2S_MODE_MASTER 0 /*!< As master mode */
|
||||
|
||||
/* I2S FIFO Threshold */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_0 0 /*!< TX threshold is 0 word */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_1 (1 << I2S_CON_TXTH_Pos) /*!< TX threshold is 1 word */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_2 (2 << I2S_CON_TXTH_Pos) /*!< TX threshold is 2 words */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_3 (3 << I2S_CON_TXTH_Pos) /*!< TX threshold is 3 words */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_4 (4 << I2S_CON_TXTH_Pos) /*!< TX threshold is 4 words */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_5 (5 << I2S_CON_TXTH_Pos) /*!< TX threshold is 5 words */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_6 (6 << I2S_CON_TXTH_Pos) /*!< TX threshold is 6 words */
|
||||
#define I2S_FIFO_TX_LEVEL_WORD_7 (7 << I2S_CON_TXTH_Pos) /*!< TX threshold is 7 words */
|
||||
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_1 0 /*!< RX threshold is 1 word */
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_2 (1 << I2S_CON_RXTH_Pos) /*!< RX threshold is 2 words */
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_3 (2 << I2S_CON_RXTH_Pos) /*!< RX threshold is 3 words */
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_4 (3 << I2S_CON_RXTH_Pos) /*!< RX threshold is 4 words */
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_5 (4 << I2S_CON_RXTH_Pos) /*!< RX threshold is 5 words */
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_6 (5 << I2S_CON_RXTH_Pos) /*!< RX threshold is 6 words */
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_7 (6 << I2S_CON_RXTH_Pos) /*!< RX threshold is 7 words */
|
||||
#define I2S_FIFO_RX_LEVEL_WORD_8 (7 << I2S_CON_RXTH_Pos) /*!< RX threshold is 8 words */
|
||||
|
||||
/* I2S Record Channel */
|
||||
#define I2S_MONO_RIGHT 0 /*!< Record mono right channel */
|
||||
#define I2S_MONO_LEFT I2S_CON_RXLCH_Msk /*!< Record mono left channel */
|
||||
|
||||
/* I2S Channel */
|
||||
#define I2S_RIGHT 0 /*!< Select right channel */
|
||||
#define I2S_LEFT 1 /*!< Select left channel */
|
||||
|
||||
/*@}*/ /* end of group I2S_EXPORTED_CONSTANTS */
|
||||
|
||||
/** @addtogroup I2S_EXPORTED_FUNCTIONS I2S Exported Functions
|
||||
@{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* inline functions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Enable zero cross detection function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32ChMask The mask for left or right channel. Valid values are:
|
||||
* - \ref I2S_RIGHT
|
||||
* - \ref I2S_LEFT
|
||||
* @return None
|
||||
* @details This function will set RCHZCEN or LCHZCEN bit of I2SCON register to enable zero cross detection function.
|
||||
*/
|
||||
static __INLINE void I2S_ENABLE_TX_ZCD(I2S_T *i2s, uint32_t u32ChMask)
|
||||
{
|
||||
if(u32ChMask == I2S_RIGHT)
|
||||
i2s->CON |= I2S_CON_RCHZCEN_Msk;
|
||||
else
|
||||
i2s->CON |= I2S_CON_LCHZCEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable zero cross detection function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32ChMask The mask for left or right channel. Valid values are:
|
||||
* - \ref I2S_RIGHT
|
||||
* - \ref I2S_LEFT
|
||||
* @return None
|
||||
* @details This function will clear RCHZCEN or LCHZCEN bit of I2SCON register to disable zero cross detection function.
|
||||
*/
|
||||
static __INLINE void I2S_DISABLE_TX_ZCD(I2S_T *i2s, uint32_t u32ChMask)
|
||||
{
|
||||
if(u32ChMask == I2S_RIGHT)
|
||||
i2s->CON &= ~I2S_CON_RCHZCEN_Msk;
|
||||
else
|
||||
i2s->CON &= ~I2S_CON_LCHZCEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2S TX DMA function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will set TXDMA bit of I2SCON register to transmit data with PDMA.
|
||||
*/
|
||||
#define I2S_ENABLE_TXDMA(i2s) ( (i2s)->CON |= I2S_CON_TXDMA_Msk )
|
||||
|
||||
/**
|
||||
* @brief Disable I2S TX DMA function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will clear TXDMA bit of I2SCON register to disable TX DMA function.
|
||||
*/
|
||||
#define I2S_DISABLE_TXDMA(i2s) ( (i2s)->CON &= ~I2S_CON_TXDMA_Msk )
|
||||
|
||||
/**
|
||||
* @brief Enable I2S RX DMA function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will set RXDMA bit of I2SCON register to receive data with PDMA.
|
||||
*/
|
||||
#define I2S_ENABLE_RXDMA(i2s) ( (i2s)->CON |= I2S_CON_RXDMA_Msk )
|
||||
|
||||
/**
|
||||
* @brief Disable I2S RX DMA function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will clear RXDMA bit of I2SCON register to disable RX DMA function.
|
||||
*/
|
||||
#define I2S_DISABLE_RXDMA(i2s) ( (i2s)->CON &= ~I2S_CON_RXDMA_Msk )
|
||||
|
||||
/**
|
||||
* @brief Enable I2S TX function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will set TXEN bit of I2SCON register to enable I2S TX function.
|
||||
*/
|
||||
#define I2S_ENABLE_TX(i2s) ( (i2s)->CON |= I2S_CON_TXEN_Msk )
|
||||
|
||||
/**
|
||||
* @brief Disable I2S TX function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will clear TXEN bit of I2SCON register to disable I2S TX function.
|
||||
*/
|
||||
#define I2S_DISABLE_TX(i2s) ( (i2s)->CON &= ~I2S_CON_TXEN_Msk )
|
||||
|
||||
/**
|
||||
* @brief Enable I2S RX function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will set RXEN bit of I2SCON register to enable I2S RX function.
|
||||
*/
|
||||
#define I2S_ENABLE_RX(i2s) ( (i2s)->CON |= I2S_CON_RXEN_Msk )
|
||||
|
||||
/**
|
||||
* @brief Disable I2S RX function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will clear RXEN bit of I2SCON register to disable I2S RX function.
|
||||
*/
|
||||
#define I2S_DISABLE_RX(i2s) ( (i2s)->CON &= ~I2S_CON_RXEN_Msk )
|
||||
|
||||
/**
|
||||
* @brief Enable TX Mute function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will set MUTE bit of I2SCON register to enable I2S TX mute function.
|
||||
*/
|
||||
#define I2S_ENABLE_TX_MUTE(i2s) ( (i2s)->CON |= I2S_CON_MUTE_Msk )
|
||||
|
||||
/**
|
||||
* @brief Disable TX Mute function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will clear MUTE bit of I2SCON register to disable I2S TX mute function.
|
||||
*/
|
||||
#define I2S_DISABLE_TX_MUTE(i2s) ( (i2s)->CON &= ~I2S_CON_MUTE_Msk )
|
||||
|
||||
/**
|
||||
* @brief Clear TX FIFO.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will clear TX FIFO. The internal TX FIFO pointer will be reset to FIFO start point.
|
||||
*/
|
||||
#define I2S_CLR_TX_FIFO(i2s) ( (i2s)->CON |= I2S_CON_CLR_TXFIFO_Msk )
|
||||
|
||||
/**
|
||||
* @brief Clear RX FIFO.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details This macro will clear RX FIFO. The internal RX FIFO pointer will be reset to FIFO start point.
|
||||
*/
|
||||
#define I2S_CLR_RX_FIFO(i2s) ( (i2s)->CON |= I2S_CON_CLR_RXFIFO_Msk )
|
||||
|
||||
/**
|
||||
* @brief This function sets the recording source channel when mono mode is used.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32Ch Left or right channel. Valid values are:
|
||||
* - \ref I2S_MONO_LEFT
|
||||
* - \ref I2S_MONO_RIGHT
|
||||
* @return None
|
||||
* @details This function selects the recording source channel of monaural mode.
|
||||
*/
|
||||
static __INLINE void I2S_SET_MONO_RX_CHANNEL(I2S_T *i2s, uint32_t u32Ch)
|
||||
{
|
||||
u32Ch == I2S_MONO_LEFT ?
|
||||
(i2s->CON |= I2S_CON_RXLCH_Msk) :
|
||||
(i2s->CON &= ~I2S_CON_RXLCH_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data to I2S TX FIFO.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32Data The value written to TX FIFO.
|
||||
* @return None
|
||||
* @details This macro will write a value to TX FIFO.
|
||||
*/
|
||||
#define I2S_WRITE_TX_FIFO(i2s, u32Data) ( (i2s)->TXFIFO = (u32Data) )
|
||||
|
||||
/**
|
||||
* @brief Read RX FIFO.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return The value read from RX FIFO.
|
||||
* @details This function will return a value read from RX FIFO.
|
||||
*/
|
||||
#define I2S_READ_RX_FIFO(i2s) ( (i2s)->RXFIFO )
|
||||
|
||||
/**
|
||||
* @brief Get the interrupt flag.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32Mask The mask value for all interrupt flags. Valid values are:
|
||||
* - \ref I2S_STATUS_LZCF_Msk
|
||||
* - \ref I2S_STATUS_RZCF_Msk
|
||||
* - \ref I2S_STATUS_TXTHF_Msk
|
||||
* - \ref I2S_STATUS_TXOVF_Msk
|
||||
* - \ref I2S_STATUS_TXUDF_Msk
|
||||
* - \ref I2S_STATUS_RXTHF_Msk
|
||||
* - \ref I2S_STATUS_RXOVF_Msk
|
||||
* - \ref I2S_STATUS_RXUDF_Msk
|
||||
* - \ref I2S_STATUS_I2STXINT_Msk
|
||||
* - \ref I2S_STATUS_I2SRXINT_Msk
|
||||
* - \ref I2S_STATUS_I2SINT_Msk
|
||||
* @return The interrupt flags specified by the u32mask parameter.
|
||||
* @details This macro will return the combination flags of I2SSTATUS register. The flags are specified by the u32mask parameter.
|
||||
*/
|
||||
#define I2S_GET_INT_FLAG(i2s, u32Mask) ( (i2s)->STATUS & (u32Mask) )
|
||||
|
||||
/**
|
||||
* @brief Clear the interrupt flag.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32Mask The mask value for all interrupt flags. Valid values are:
|
||||
* - \ref I2S_STATUS_LZCF_Msk
|
||||
* - \ref I2S_STATUS_RZCF_Msk
|
||||
* - \ref I2S_STATUS_TXOVF_Msk
|
||||
* - \ref I2S_STATUS_TXUDF_Msk
|
||||
* - \ref I2S_STATUS_RXOVF_Msk
|
||||
* - \ref I2S_STATUS_RXUDF_Msk
|
||||
* @return None
|
||||
* @details This macro will clear the interrupt flags specified by the u32mask parameter.
|
||||
*/
|
||||
#define I2S_CLR_INT_FLAG(i2s, u32Mask) ( (i2s)->STATUS = (u32Mask) )
|
||||
|
||||
/**
|
||||
* @brief Get transmit FIFO level
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return TX FIFO level
|
||||
* @details This macro will return the number of available words in TX FIFO.
|
||||
*/
|
||||
#define I2S_GET_TX_FIFO_LEVEL(i2s) ( (((i2s)->STATUS & I2S_STATUS_TX_LEVEL_Msk) >> I2S_STATUS_TX_LEVEL_Pos) & 0xF )
|
||||
|
||||
/**
|
||||
* @brief Get receive FIFO level
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return RX FIFO level
|
||||
* @details This macro will return the number of available words in RX FIFO.
|
||||
*/
|
||||
#define I2S_GET_RX_FIFO_LEVEL(i2s) ( (((i2s)->STATUS & I2S_STATUS_RX_LEVEL_Msk) >> I2S_STATUS_RX_LEVEL_Pos) & 0xF )
|
||||
|
||||
|
||||
/* Function prototype declaration */
|
||||
uint32_t I2S_Open(I2S_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat);
|
||||
void I2S_Close(I2S_T *i2s);
|
||||
void I2S_EnableInt(I2S_T *i2s, uint32_t u32Mask);
|
||||
void I2S_DisableInt(I2S_T *i2s, uint32_t u32Mask);
|
||||
uint32_t I2S_EnableMCLK(I2S_T *i2s, uint32_t u32BusClock);
|
||||
void I2S_DisableMCLK(I2S_T *i2s);
|
||||
|
||||
/*@}*/ /* end of group I2S_EXPORTED_FUNCTIONS */
|
||||
|
||||
|
||||
/*@}*/ /* end of group I2S_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
||||
|
199
NUC123/StdDriver/inc/pdma.h
Normal file
199
NUC123/StdDriver/inc/pdma.h
Normal file
@ -0,0 +1,199 @@
|
||||
/**************************************************************************//**
|
||||
* @file PDMA.h
|
||||
* @version V1.00
|
||||
* $Revision: 6 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series PDMA Controller Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __PDMA_H__
|
||||
#define __PDMA_H__
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup PDMA_Driver PDMA Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup PDMA_EXPORTED_CONSTANTS PDMA Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Data Width Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define PDMA_WIDTH_8 0x00080000UL /*!<DMA Transfer Width 8-bit */
|
||||
#define PDMA_WIDTH_16 0x00100000UL /*!<DMA Transfer Width 16-bit */
|
||||
#define PDMA_WIDTH_32 0x00000000UL /*!<DMA Transfer Width 32-bit */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Address Attribute Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define PDMA_SAR_INC 0x00000000UL /*!<DMA SAR increment */
|
||||
#define PDMA_SAR_FIX 0x00000020UL /*!<DMA SAR fix address */
|
||||
#define PDMA_DAR_INC 0x00000000UL /*!<DMA DAR increment */
|
||||
#define PDMA_DAR_FIX 0x00000080UL /*!<DMA DAR fix address */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Peripheral Transfer Mode Constant Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define PDMA_SPI0_TX 0x00000000UL /*!<DMA Connect to SPI0 TX */
|
||||
#define PDMA_SPI1_TX 0x00000001UL /*!<DMA Connect to SPI1 TX */
|
||||
#define PDMA_SPI2_TX 0x00000002UL /*!<DMA Connect to SPI2 TX */
|
||||
#define PDMA_UART0_TX 0x00000003UL /*!<DMA Connect to UART0 TX */
|
||||
#define PDMA_UART1_TX 0x00000004UL /*!<DMA Connect to UART1 TX */
|
||||
#define PDMA_I2S_TX 0x00000005UL /*!<DMA Connect to I2S TX */
|
||||
#define PDMA_SPI0_RX 0x00000006UL /*!<DMA Connect to SPI0 RX */
|
||||
#define PDMA_SPI1_RX 0x00000007UL /*!<DMA Connect to SPI1 RX */
|
||||
#define PDMA_SPI2_RX 0x00000008UL /*!<DMA Connect to SPI2 RX */
|
||||
#define PDMA_UART0_RX 0x00000009UL /*!<DMA Connect to UART0 RX */
|
||||
#define PDMA_UART1_RX 0x0000000AUL /*!<DMA Connect to UART1 RX */
|
||||
#define PDMA_I2S_RX 0x0000000BUL /*!<DMA Connect to I2S RX */
|
||||
#define PDMA_ADC 0x0000000CUL /*!<DMA Connect to ADC */
|
||||
#define PDMA_PWM0_RX 0x0000000DUL /*!<DMA Connect to PWM0 RX */
|
||||
#define PDMA_PWM1_RX 0x0000000EUL /*!<DMA Connect to PWM1 RX */
|
||||
#define PDMA_PWM2_RX 0x0000000FUL /*!<DMA Connect to PWM2 RX */
|
||||
#define PDMA_PWM3_RX 0x00000010UL /*!<DMA Connect to PWM3 RX */
|
||||
#define PDMA_MEM 0x0000001FUL /*!<DMA Connect to Memory */
|
||||
|
||||
|
||||
/*@}*/ /* end of group PDMA_EXPORTED_CONSTANTS */
|
||||
|
||||
/** @addtogroup PDMA_EXPORTED_FUNCTIONS PDMA Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get PDMA Global Interrupt Status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return Interrupt Status
|
||||
*
|
||||
* @details This macro gets the global interrupt status.
|
||||
*/
|
||||
#define PDMA_GET_INT_STATUS() ((uint32_t)(PDMA_GCR->GCRISR))
|
||||
|
||||
/**
|
||||
* @brief Get PDMA Channel Interrupt Status
|
||||
*
|
||||
* @param[in] u32Ch Selected DMA channel
|
||||
*
|
||||
* @return Interrupt Status
|
||||
*
|
||||
* @details This macro gets the channel interrupt status.
|
||||
*/
|
||||
#define PDMA_GET_CH_INT_STS(u32Ch) (*((__IO uint32_t *)((uint32_t)&PDMA0->ISR + (uint32_t)((u32Ch)*0x100))))
|
||||
|
||||
/**
|
||||
* @brief Clear PDMA Channel Interrupt Flag
|
||||
*
|
||||
* @param[in] u32Ch Selected DMA channel
|
||||
* @param[in] u32Mask Interrupt Mask
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro clear the channel interrupt flag.
|
||||
*/
|
||||
#define PDMA_CLR_CH_INT_FLAG(u32Ch, u32Mask) (*((__IO uint32_t *)((uint32_t)&PDMA0->ISR + (uint32_t)((u32Ch)*0x100))) = (u32Mask))
|
||||
|
||||
/**
|
||||
* @brief Check Channel Status
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
*
|
||||
* @retval 0 The selected channel is idle
|
||||
* @retval 1 The selected channel is busy
|
||||
*
|
||||
* @details Check the selected channel is busy or not.
|
||||
*/
|
||||
#define PDMA_IS_CH_BUSY(u32Ch) ((*((__IO uint32_t *)((uint32_t)&PDMA0->CSR +(uint32_t)((u32Ch)*0x100)))&PDMA_CSR_TRIG_EN_Msk)? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Set Source Address
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32Addr The selected address
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro set the selected channel source address.
|
||||
*/
|
||||
#define PDMA_SET_SRC_ADDR(u32Ch, u32Addr) (*((__IO uint32_t *)((uint32_t)&PDMA0->SAR + (uint32_t)((u32Ch)*0x100))) = (u32Addr))
|
||||
|
||||
/**
|
||||
* @brief Set Destination Address
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32Addr The selected address
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro set the selected channel destination address.
|
||||
*/
|
||||
#define PDMA_SET_DST_ADDR(u32Ch, u32Addr) (*((__IO uint32_t *)((uint32_t)&PDMA0->DAR + (uint32_t)((u32Ch)*0x100))) = (u32Addr))
|
||||
|
||||
/**
|
||||
* @brief Set Transfer Count
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32Count Transfer Count
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro set the selected channel transfer count.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PDMA_SET_TRANS_CNT(u32Ch, u32Count) { \
|
||||
if (((uint32_t)*((__IO uint32_t *)((uint32_t)&PDMA0->CSR + (uint32_t)((u32Ch)*0x100))) & PDMA_CSR_APB_TWS_Msk) == PDMA_WIDTH_32) \
|
||||
*((__IO uint32_t *)((uint32_t)&PDMA0->BCR + (uint32_t)((u32Ch)*0x100))) = ((u32Count) << 2); \
|
||||
else if (((uint32_t)*((__IO uint32_t *)((uint32_t)&PDMA0->CSR + (uint32_t)((u32Ch)*0x100))) & PDMA_CSR_APB_TWS_Msk) == PDMA_WIDTH_8) \
|
||||
*((__IO uint32_t *)((uint32_t)&PDMA0->BCR + (uint32_t)((u32Ch)*0x100))) = (u32Count); \
|
||||
else if (((uint32_t)*((__IO uint32_t *)((uint32_t)&PDMA0->CSR + (uint32_t)((u32Ch)*0x100))) & PDMA_CSR_APB_TWS_Msk) == PDMA_WIDTH_16) \
|
||||
*((__IO uint32_t *)((uint32_t)&PDMA0->BCR + (uint32_t)((u32Ch)*0x100))) = ((u32Count) << 1); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the channel
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro stop the selected channel.
|
||||
*/
|
||||
#define PDMA_STOP(u32Ch) (*((__IO uint32_t *)((uint32_t)&PDMA0->CSR + (uint32_t)((u32Ch)*0x100))) &= ~PDMA_CSR_PDMACEN_Msk)
|
||||
|
||||
void PDMA_Open(uint32_t u32Mask);
|
||||
void PDMA_Close(void);
|
||||
void PDMA_SetTransferCnt(uint32_t u32Ch, uint32_t u32Width, uint32_t u32TransCount);
|
||||
void PDMA_SetTransferAddr(uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl);
|
||||
void PDMA_SetTransferMode(uint32_t u32Ch, uint32_t u32Periphral, uint32_t u32ScatterEn, uint32_t u32DescAddr);
|
||||
void PDMA_Trigger(uint32_t u32Ch);
|
||||
void PDMA_EnableInt(uint32_t u32Ch, uint32_t u32Mask);
|
||||
void PDMA_DisableInt(uint32_t u32Ch, uint32_t u32Mask);
|
||||
|
||||
|
||||
/**
|
||||
* @} End of PDMA Device Function Interface
|
||||
*/
|
||||
|
||||
/**
|
||||
* @} End of Function Interface
|
||||
*/
|
||||
|
||||
/**
|
||||
* @} End of PDMA_Driver
|
||||
*/
|
||||
|
||||
|
||||
#endif // __PDMA_H__
|
255
NUC123/StdDriver/inc/ps2.h
Normal file
255
NUC123/StdDriver/inc/ps2.h
Normal file
@ -0,0 +1,255 @@
|
||||
/**************************************************************************//**
|
||||
* @file PS2.h
|
||||
* @version V3.00
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series PS/2 Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
******************************************************************************/
|
||||
#ifndef __PS2_H__
|
||||
#define __PS2_H__
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Include related headers */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#include "NUC123.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup PS2_Driver PS2 Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup PS2_EXPORTED_FUNCTIONS PS2 Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Define Macros and functions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief To Set PS/2 Tx FIFO length
|
||||
*
|
||||
* @param[in] u32Count Tx FIFO length
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Before PS/2 data transmit, program needs to set the FIFO depth.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PS2_SET_TX_BYTE_CNT(u32Count) (PS2->PS2CON = (PS2->PS2CON & ~PS2_PS2CON_TXFIFO_DEPTH_Msk) \
|
||||
| (((u32Count)-1) << PS2_PS2CON_TXFIFO_DEPTH_Pos))
|
||||
|
||||
/**
|
||||
* @brief This function use to Get PS/2 Status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return PS/2 bus status
|
||||
*
|
||||
* @details To get PS/2 bus status which are about Byte index, Tx/Rx status, Error status and PS/2 line status.
|
||||
*/
|
||||
#define PS2_GET_STATUS() (PS2->PS2STATUS)
|
||||
|
||||
/**
|
||||
* @brief This function is used to Clear PS/2 Status
|
||||
*
|
||||
* @param[in] u32Mask Clear the specified status of PS/2 module:
|
||||
* 1. PS2D_PS2STATUS_FRAMERR_Msk 2. PS2D_PS2STATUS_RXOVF_Msk
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To clear PS/2 bus status which are about Byte index, TX/RX status, Error status, PS/2 line status.
|
||||
*/
|
||||
#define PS2_CLR_STATUS(u32Mask) (PS2->PS2STATUS = (u32Mask))
|
||||
|
||||
/**
|
||||
* @brief This function is used to Clear PS/2 Tx FIFO
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Write 1 to terminate PS/2 device to host transmission.
|
||||
*
|
||||
* @note Write 1 is always clear Tx FIFO, and need write 0 to STOP the clear action.
|
||||
*/
|
||||
__STATIC_INLINE void PS2_CLEAR_TX_FIFO(void)
|
||||
{
|
||||
PS2->PS2CON |= PS2_PS2CON_CLRFIFO_Msk;
|
||||
PS2->PS2CON &= ~PS2_PS2CON_CLRFIFO_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is used to Clear PS2 Rx interrupt
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To disable PS/2 receive interrupt occurs.
|
||||
*/
|
||||
#define PS2_CLR_RX_INT_FLAG() (PS2->PS2INTID = PS2_PS2INTID_RXINT_Msk)
|
||||
|
||||
/**
|
||||
* @brief This function is used to Clear PS/2 Tx Interrupt
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To disable PS/2 transmit interrupt occurs.
|
||||
*/
|
||||
#define PS2_CLR_TX_INT_FLAG() (PS2->PS2INTID = PS2_PS2INTID_TXINT_Msk)
|
||||
|
||||
/**
|
||||
* @brief This function is used to Get PS/2 Interrupt
|
||||
*
|
||||
* @param[in] u32IntFlag Interrupt flag of PS2D_PS2INTID_TXINT_Msk, PS2D_PS2INTID_RXINT_Msk
|
||||
*
|
||||
* @retval 1 Interrupt occurs
|
||||
* @retval 0 Interrupt not occurs
|
||||
*
|
||||
* @details To check PS/2 bus interrupt occur from TX or RX
|
||||
*/
|
||||
#define PS2_GET_INT_FLAG(u32IntFlag) ((PS2->PS2INTID & (u32IntFlag))?1:0)
|
||||
|
||||
/**
|
||||
* @brief Disable PS2CLK and PS2DATA pins override.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To disable the override control of PS2CLK and PS2DATA pins.
|
||||
*/
|
||||
#define PS2_DISABLE_OVERRIDE() (PS2->PS2CON &= ~PS2_PS2CON_OVERRIDE_Msk)
|
||||
|
||||
/**
|
||||
* @brief Enable PS2CLK and PS2DATA pins Override.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details TO enable the override control of PS2CLK and PS2DATA pins.
|
||||
*/
|
||||
#define PS2_ENABLE_OVERRIDE() (PS2->PS2CON |= PS2_PS2CON_OVERRIDE_Msk)
|
||||
|
||||
/**
|
||||
* @brief This function is used to Get Indicates which data byte in transmit data shift register
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The indicates which data byte in transmit data shift register.
|
||||
*
|
||||
* @details To get a indication which a data byte in the data shift register.
|
||||
*/
|
||||
#define PS2_GET_TX_BYTE_INDEX() ((PS2->PS2STATUS & PS2_PS2STATUS_BYTEIDX_Msk) >> PS2_PS2STATUS_BYTEIDX_Pos)
|
||||
|
||||
/**
|
||||
* @brief This function is used to set PS2DATA Pin low.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To control the PS2DATA pin state to low.
|
||||
*/
|
||||
#define PS2_SET_DATA_LOW() (PS2->PS2CON &= ~PS2_PS2CON_FPS2DAT_Msk)
|
||||
|
||||
/**
|
||||
* @brief This function is used to set PS2DATA Pin high
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To control the PS2DATA pin state to high.
|
||||
*/
|
||||
#define PS2_SET_DATA_HIGH() (PS2->PS2CON |= PS2_PS2CON_FPS2DAT_Msk)
|
||||
|
||||
/**
|
||||
* @brief This function is used to set PS2CLK Pin low.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To control the PS2CLK pin state to low.
|
||||
*/
|
||||
#define PS2_SET_CLK_LOW() (PS2->PS2CON &= ~PS2_PS2CON_FPS2CLK_Msk)
|
||||
|
||||
/**
|
||||
* @brief This function is used to set PS2CLK Pin high.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To control the PS2CLK pin state to high.
|
||||
*/
|
||||
#define PS2_SET_CLK_HIGH() (PS2->PS2CON |= PS2_PS2CON_FPS2CLK_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable always sends acknowledge
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details If parity error or Stop bit is not received correctly, acknowledge will not be sent to host at 12th clock.
|
||||
*/
|
||||
#define PS2_DISABLE_ACK_ALWAYS() (PS2->PS2CON |= PS2_PS2CON_ACK_Msk)
|
||||
|
||||
/**
|
||||
* @brief Always sends acknowledge
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Always send acknowledge to host at 12th clock for host to device communication.
|
||||
*/
|
||||
#define PS2_ENABLE_ACK_ALWAYS() (PS2->PS2CON &= ~PS2_PS2CON_ACK_Msk)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Define Function Prototypes */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
void PS2_Open(void);
|
||||
void PS2_Close(void);
|
||||
uint8_t PS2_Read(void);
|
||||
int32_t PS2_Write(uint32_t *pu32Buf, uint32_t u32ByteCount);
|
||||
void PS2_EnableInt(uint32_t u32Mask);
|
||||
void PS2_DisableInt(uint32_t u32Mask);
|
||||
|
||||
|
||||
/*@}*/ /* end of group PS2_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group PS2_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__PS2_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
||||
|
231
NUC123/StdDriver/inc/pwm.h
Normal file
231
NUC123/StdDriver/inc/pwm.h
Normal file
@ -0,0 +1,231 @@
|
||||
/**************************************************************************//**
|
||||
* @file pwm.h
|
||||
* @version V3.00
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series PWM driver header file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#ifndef __PWM_H__
|
||||
#define __PWM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup PWM_Driver PWM Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup PWM_EXPORTED_CONSTANTS PWM Exported Constants
|
||||
@{
|
||||
*/
|
||||
#define PWM_CHANNEL_NUM (4) /*!< PWM channel number */
|
||||
#define PWM_CLK_DIV_1 (4UL) /*!< PWM clock divide by 1 */
|
||||
#define PWM_CLK_DIV_2 (0UL) /*!< PWM clock divide by 2 */
|
||||
#define PWM_CLK_DIV_4 (1UL) /*!< PWM clock divide by 4 */
|
||||
#define PWM_CLK_DIV_8 (2UL) /*!< PWM clock divide by 8 */
|
||||
#define PWM_CLK_DIV_16 (3UL) /*!< PWM clock divide by 16 */
|
||||
#define PWM_EDGE_ALIGNED (0UL) /*!< PWM working in edge aligned type */
|
||||
#define PWM_CENTER_ALIGNED (1UL) /*!< PWM working in center aligned type */
|
||||
#define PWM_PERIOD_INT_UNDERFLOW (0) /*!< PWM period interrupt triggered if counter underflow */
|
||||
#define PWM_PERIOD_INT_MATCH_CNR (PWM_PIER_INT01TYPE_Msk) /*!< PWM period interrupt triggered if counter match CNR */
|
||||
#define PWM_CAPTURE_INT_RISING_LATCH (PWM_CCR0_CRL_IE0_Msk) /*!< PWM capture interrupt if channel has rising transition */
|
||||
#define PWM_CAPTURE_INT_FALLING_LATCH (PWM_CCR0_CFL_IE0_Msk) /*!< PWM capture interrupt if channel has falling transition */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* PWM Group channel number constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define PWM_CH0 0x0 /*!< PWM Group A channel 0 */
|
||||
#define PWM_CH1 0x1 /*!< PWM Group A channel 1 */
|
||||
#define PWM_CH2 0x2 /*!< PWM Group A channel 2 */
|
||||
#define PWM_CH3 0x3 /*!< PWM Group A channel 3 */
|
||||
#define PWM_CCR_MASK 0x000F000F /*!< PWM CCR0/CCR2 bit0~3 and bit16~19 mask */
|
||||
|
||||
/*@}*/ /* end of group PWM_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup PWM_EXPORTED_FUNCTIONS PWM Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable output inverter of specified channel(s)
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
|
||||
* Bit 0 represents channel 0, bit 1 represents channel 1...
|
||||
* @return None
|
||||
* @details This macro is used to enable capture input inverter for specified channel(s).
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PWM_ENABLE_OUTPUT_INVERTER(pwm, u32ChannelMask) \
|
||||
do{ \
|
||||
int i;\
|
||||
(pwm)->PCR &= ~(PWM_PCR_CH0INV_Msk|PWM_PCR_CH1INV_Msk|PWM_PCR_CH2INV_Msk|PWM_PCR_CH3INV_Msk);\
|
||||
for(i = 0; i < 4; i++) { \
|
||||
if((u32ChannelMask) & (1 << i)) \
|
||||
(pwm)->PCR |= (PWM_PCR_CH0INV_Msk << (PWM_PCR_CH0INV_Pos * (i * 4))); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
/**
|
||||
* @brief Get captured rising data of specified channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return The timer counter, 0~0xFFFF
|
||||
* @details This macro is used to get captured rising data for specified channel.
|
||||
*/
|
||||
#define PWM_GET_CAPTURE_RISING_DATA(pwm, u32ChannelNum) (*((__IO uint32_t *) ((((uint32_t)&((pwm)->CRLR0)) + (u32ChannelNum) * 8))))
|
||||
|
||||
/**
|
||||
* @brief Get captured falling data of specified channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return The timer counter, 0~0xFFFF
|
||||
* @details This macro is used to get captured falling data for specified channel.
|
||||
*/
|
||||
#define PWM_GET_CAPTURE_FALLING_DATA(pwm, u32ChannelNum) (*((__IO uint32_t *) ((((uint32_t)&((pwm)->CFLR0)) + (u32ChannelNum) * 8))))
|
||||
|
||||
/**
|
||||
* @brief Set the prescaler of the selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Prescaler Clock prescaler of specified channel. Valid values are between 1 ~ 0xFF
|
||||
* @return None
|
||||
* @details This macro is used to set timer pre-scale for specified channel.
|
||||
* @note If u32Prescaler = 0, corresponding PWM-timer will be stopped.
|
||||
* @note If u32Prescaler = x (x not equal to 0), it means Clock input is divided by (x + 1) before it is fed to the corresponding PWM counter.
|
||||
*/
|
||||
#define PWM_SET_PRESCALER(pwm, u32ChannelNum, u32Prescaler) \
|
||||
((pwm)->PPR = ((pwm)->PPR & ~(PWM_PPR_CP01_Msk << (((u32ChannelNum) >> 1) * 8))) | ((u32Prescaler) << (((u32ChannelNum) >> 1) * 8)))
|
||||
|
||||
/**
|
||||
* @brief Set the divider of the selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Divider Clock divider of specified channel. Valid values are
|
||||
* - \ref PWM_CLK_DIV_1
|
||||
* - \ref PWM_CLK_DIV_2
|
||||
* - \ref PWM_CLK_DIV_4
|
||||
* - \ref PWM_CLK_DIV_8
|
||||
* - \ref PWM_CLK_DIV_16
|
||||
* @return None
|
||||
* @details This macro is used to set Timer clock source divider selection for specified channel.
|
||||
*/
|
||||
#define PWM_SET_DIVIDER(pwm, u32ChannelNum, u32Divider) \
|
||||
((pwm)->CSR = ((pwm)->CSR & ~(PWM_CSR_CSR0_Msk << ((u32ChannelNum) * 4))) | ((u32Divider) << ((u32ChannelNum) * 4)))
|
||||
|
||||
/**
|
||||
* @brief Set the duty of the selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32CMR Duty of specified channel. Valid values are between 0~0xFFFF
|
||||
* @return None
|
||||
* @details This macro is used to set PWM Comparator value for specified channel.
|
||||
* @note This new setting will take effect on next PWM period.
|
||||
*/
|
||||
#define PWM_SET_CMR(pwm, u32ChannelNum, u32CMR) (*((__IO uint32_t *) ((((uint32_t)&((pwm)->CMR0)) + (u32ChannelNum) * 12))) = (u32CMR))
|
||||
|
||||
/**
|
||||
* @brief Set the period of the selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32CNR Period of specified channel. Valid values are between 0~0xFFFF
|
||||
* @return None
|
||||
* @details This macro is used to set timer loaded value(CNR) for specified channel.\n
|
||||
* Loaded value determines the PWM period.
|
||||
* @note This new setting will take effect on next PWM period.
|
||||
* @note PWM counter will stop if period length set to 0.
|
||||
*/
|
||||
#define PWM_SET_CNR(pwm, u32ChannelNum, u32CNR) (*((__IO uint32_t *) ((((uint32_t)&((pwm)->CNR0)) + (u32ChannelNum) * 12))) = (u32CNR))
|
||||
|
||||
/**
|
||||
* @brief Set the PWM aligned type
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
|
||||
* Bit 0 represents channel 0, bit 1 represents channel 1...
|
||||
* @param[in] u32AlignedType PWM aligned type, valid values are:
|
||||
* - \ref PWM_EDGE_ALIGNED
|
||||
* - \ref PWM_CENTER_ALIGNED
|
||||
* @return None
|
||||
* @details This macro is used to set the PWM aligned type.
|
||||
* @note PWM trigger ADC function is only supported when PWM operating at Center-aligned type.
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PWM_SET_ALIGNED_TYPE(pwm, u32ChannelMask, u32AlignedType) \
|
||||
do{ \
|
||||
int i; \
|
||||
for(i = 0; i < 4; i++) { \
|
||||
if((u32ChannelMask) & (1 << i)) \
|
||||
(pwm)->PCR = ((pwm)->PCR & ~(PWM_PCR_PWM01TYPE_Msk << (i >> 1))) | ((u32AlignedType) << (PWM_PCR_PWM01TYPE_Pos + (i >> 1))); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
|
||||
uint32_t PWM_ConfigCaptureChannel(PWM_T *pwm,
|
||||
uint32_t u32ChannelNum,
|
||||
uint32_t u32UnitTimeNsec,
|
||||
uint32_t u32CaptureEdge);
|
||||
uint32_t PWM_ConfigOutputChannel(PWM_T *pwm,
|
||||
uint32_t u32ChannelNum,
|
||||
uint32_t u32Frequncy,
|
||||
uint32_t u32DutyCycle);
|
||||
void PWM_Start(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_Stop(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_ForceStop(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_EnableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition);
|
||||
void PWM_DisableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
void PWM_ClearADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition);
|
||||
uint32_t PWM_GetADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
void PWM_EnableCapture(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_DisableCapture(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_EnableOutput(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_DisableOutput(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_EnablePDMA(PWM_T *pwm, uint32_t u32ChannelMask, uint32_t u32RisingFirst);
|
||||
void PWM_DisablePDMA(PWM_T *pwm, uint32_t u32ChannelMask);
|
||||
void PWM_EnableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration);
|
||||
void PWM_DisableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
void PWM_EnableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge);
|
||||
void PWM_DisableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge);
|
||||
void PWM_ClearCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge);
|
||||
uint32_t PWM_GetCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
void PWM_EnableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType);
|
||||
void PWM_DisableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
void PWM_ClearDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
uint32_t PWM_GetDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
void PWM_EnablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType);
|
||||
void PWM_DisablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
void PWM_ClearPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
uint32_t PWM_GetPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum);
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group PWM_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group PWM_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__PWM_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
393
NUC123/StdDriver/inc/spi.h
Normal file
393
NUC123/StdDriver/inc/spi.h
Normal file
@ -0,0 +1,393 @@
|
||||
/**************************************************************************//**
|
||||
* @file spi.h
|
||||
* @version V3.0
|
||||
* $Revision: 11 $
|
||||
* $Date: 15/07/02 3:18p $
|
||||
* @brief NUC123 Series SPI Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __SPI_H__
|
||||
#define __SPI_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_Driver SPI Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_EXPORTED_CONSTANTS SPI Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
#define SPI_MODE_0 (SPI_CNTRL_TX_NEG_Msk) /*!< CLKP=0; RX_NEG=0; TX_NEG=1 */
|
||||
#define SPI_MODE_1 (SPI_CNTRL_RX_NEG_Msk) /*!< CLKP=0; RX_NEG=1; TX_NEG=0 */
|
||||
#define SPI_MODE_2 (SPI_CNTRL_CLKP_Msk | SPI_CNTRL_RX_NEG_Msk) /*!< CLKP=1; RX_NEG=1; TX_NEG=0 */
|
||||
#define SPI_MODE_3 (SPI_CNTRL_CLKP_Msk | SPI_CNTRL_TX_NEG_Msk) /*!< CLKP=1; RX_NEG=0; TX_NEG=1 */
|
||||
|
||||
#define SPI_SLAVE (SPI_CNTRL_SLAVE_Msk) /*!< Set as slave */
|
||||
#define SPI_MASTER (0x0) /*!< Set as master */
|
||||
|
||||
#define SPI_SS0 (1<<SPI_SSR_SSR_Pos) /*!< Select SPIn_SS0 */
|
||||
#define SPI_SS1 (2<<SPI_SSR_SSR_Pos) /*!< Select SPIn_SS1 */
|
||||
#define SPI_SS_ACTIVE_HIGH (SPI_SSR_SS_LVL_Msk) /*!< SS active high */
|
||||
#define SPI_SS_ACTIVE_LOW (0x0) /*!< SS active low */
|
||||
|
||||
#define SPI_UNIT_INT_MASK (0x01) /*!< Unit transfer interrupt mask */
|
||||
#define SPI_SSTA_INT_MASK (0x02) /*!< Slave 3-Wire mode start interrupt mask */
|
||||
#define SPI_FIFO_TX_INT_MASK (0x04) /*!< FIFO TX interrupt mask */
|
||||
#define SPI_FIFO_RX_INT_MASK (0x08) /*!< FIFO RX interrupt mask */
|
||||
#define SPI_FIFO_RXOV_INT_MASK (0x10) /*!< FIFO RX overrun interrupt mask */
|
||||
#define SPI_FIFO_TIMEOUT_INT_MASK (0x20) /*!< FIFO RX timeout interrupt mask */
|
||||
|
||||
#define SPI_BUSY_MASK (0x01) /*!< Busy status mask */
|
||||
#define SPI_RX_EMPTY_MASK (0x02) /*!< RX empty status mask */
|
||||
#define SPI_RX_FULL_MASK (0x04) /*!< RX full status mask */
|
||||
#define SPI_TX_EMPTY_MASK (0x08) /*!< TX empty status mask */
|
||||
#define SPI_TX_FULL_MASK (0x10) /*!< TX full status mask */
|
||||
|
||||
/*@}*/ /* end of group SPI_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup SPI_EXPORTED_FUNCTIONS SPI Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer in Slave 3-wire mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set the SLV_ABORT bit of SPI_CNTRL2 register to abort the current transfer in Slave 3-wire mode.
|
||||
*/
|
||||
#define SPI_ABORT_3WIRE_TRANSFER(spi) ((spi)->CNTRL2 |= SPI_CNTRL2_SLV_ABORT_Msk)
|
||||
|
||||
/**
|
||||
* @brief Clear the Slave 3-wire mode start interrupt flag.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Write 1 to SLV_START_INTSTS bit of SPI_STATUS register to clear the Slave 3-wire mode start interrupt flag.
|
||||
*/
|
||||
#define SPI_CLR_3WIRE_START_INT_FLAG(spi) ((spi)->STATUS = SPI_STATUS_SLV_START_INTSTS_Msk)
|
||||
|
||||
/**
|
||||
* @brief Clear the unit transfer interrupt flag.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Write 1 to IF bit of SPI_STATUS register to clear the unit transfer interrupt flag.
|
||||
*/
|
||||
#define SPI_CLR_UNIT_TRANS_INT_FLAG(spi) ((spi)->STATUS = SPI_STATUS_IF_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable 2-bit Transfer mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Clear TWOB bit of SPI_CNTRL register to disable 2-bit Transfer mode.
|
||||
*/
|
||||
#define SPI_DISABLE_2BIT_MODE(spi) ((spi)->CNTRL &= ~SPI_CNTRL_TWOB_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable Slave 3-wire mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Clear NOSLVSEL bit of SPI_CNTRL2 register to disable Slave 3-wire mode.
|
||||
*/
|
||||
#define SPI_DISABLE_3WIRE_MODE(spi) ((spi)->CNTRL2 &= ~SPI_CNTRL2_NOSLVSEL_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable Dual I/O mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Clear DUAL_IO_EN bit of SPI_CNTRL2 register to disable Dual I/O mode.
|
||||
*/
|
||||
#define SPI_DISABLE_DUAL_MODE(spi) ((spi)->CNTRL2 &= ~SPI_CNTRL2_DUAL_IO_EN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Enable 2-bit Transfer mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set TWOB bit of SPI_CNTRL register to enable 2-bit Transfer mode.
|
||||
*/
|
||||
#define SPI_ENABLE_2BIT_MODE(spi) ((spi)->CNTRL |= SPI_CNTRL_TWOB_Msk)
|
||||
|
||||
/**
|
||||
* @brief Enable Slave 3-wire mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set NOSLVSEL bit of SPI_CNTRL2 register to enable Slave 3-wire mode.
|
||||
* Only available in Slave mode.
|
||||
*/
|
||||
#define SPI_ENABLE_3WIRE_MODE(spi) ((spi)->CNTRL2 |= SPI_CNTRL2_NOSLVSEL_Msk)
|
||||
|
||||
/**
|
||||
* @brief Enable Dual input mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Clear DUAL_IO_DIR bit and set DUAL_IO_EN bit of SPI_CNTRL2 register to enable Dual input mode.
|
||||
*/
|
||||
#define SPI_ENABLE_DUAL_INPUT_MODE(spi) ((spi)->CNTRL2 = ((spi)->CNTRL2 & (~SPI_CNTRL2_DUAL_IO_DIR_Msk)) | SPI_CNTRL2_DUAL_IO_EN_Msk)
|
||||
|
||||
/**
|
||||
* @brief Enable Dual output mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set DUAL_IO_DIR bit and DUAL_IO_EN bit of SPI_CNTRL2 register to enable Dual output mode.
|
||||
*/
|
||||
#define SPI_ENABLE_DUAL_OUTPUT_MODE(spi) ((spi)->CNTRL2 |= (SPI_CNTRL2_DUAL_IO_EN_Msk | SPI_CNTRL2_DUAL_IO_DIR_Msk))
|
||||
|
||||
/**
|
||||
* @brief Trigger RX PDMA function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set RX_DMA_GO bit of SPI_DMA register to enable RX PDMA transfer function.
|
||||
*/
|
||||
#define SPI_TRIGGER_RX_PDMA(spi) ((spi)->DMA |= SPI_DMA_RX_DMA_GO_Msk)
|
||||
|
||||
/**
|
||||
* @brief Trigger TX PDMA function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set TX_DMA_GO bit of SPI_DMA register to enable TX PDMA transfer function.
|
||||
*/
|
||||
#define SPI_TRIGGER_TX_PDMA(spi) ((spi)->DMA |= SPI_DMA_TX_DMA_GO_Msk)
|
||||
|
||||
/**
|
||||
* @brief Trigger TX and RX PDMA function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set TX_DMA_GO bit and RX_DMA_GO bit of SPI_DMA register to enable TX and RX PDMA transfer function.
|
||||
*/
|
||||
#define SPI_TRIGGER_TX_RX_PDMA(spi) ((spi)->DMA |= (SPI_DMA_TX_DMA_GO_Msk | SPI_DMA_RX_DMA_GO_Msk))
|
||||
|
||||
/**
|
||||
* @brief Get the count of available data in RX FIFO.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return The count of available data in RX FIFO.
|
||||
* @details Read RX_FIFO_COUNT (SPI_STATUS[15:12]) to get the count of available data in RX FIFO.
|
||||
*/
|
||||
#define SPI_GET_RX_FIFO_COUNT(spi) (((spi)->STATUS & SPI_STATUS_RX_FIFO_COUNT_Msk) >> SPI_STATUS_RX_FIFO_COUNT_Pos)
|
||||
|
||||
/**
|
||||
* @brief Get the RX FIFO empty flag.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @retval 0 RX FIFO is not empty.
|
||||
* @retval 1 RX FIFO is empty.
|
||||
* @details Read RX_EMPTY bit of SPI_STATUS register to get the RX FIFO empty flag.
|
||||
*/
|
||||
#define SPI_GET_RX_FIFO_EMPTY_FLAG(spi) (((spi)->STATUS & SPI_STATUS_RX_EMPTY_Msk)>>SPI_STATUS_RX_EMPTY_Pos)
|
||||
|
||||
/**
|
||||
* @brief Get the TX FIFO empty flag.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @retval 0 TX FIFO is not empty.
|
||||
* @retval 1 TX FIFO is empty.
|
||||
* @details Read TX_EMPTY bit of SPI_STATUS register to get the TX FIFO empty flag.
|
||||
*/
|
||||
#define SPI_GET_TX_FIFO_EMPTY_FLAG(spi) (((spi)->STATUS & SPI_STATUS_TX_EMPTY_Msk)>>SPI_STATUS_TX_EMPTY_Pos)
|
||||
|
||||
/**
|
||||
* @brief Get the TX FIFO full flag.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @retval 0 TX FIFO is not full.
|
||||
* @retval 1 TX FIFO is full.
|
||||
* @details Read TX_FULL bit of SPI_STATUS register to get the TX FIFO full flag.
|
||||
*/
|
||||
#define SPI_GET_TX_FIFO_FULL_FLAG(spi) (((spi)->STATUS & SPI_STATUS_TX_FULL_Msk)>>SPI_STATUS_TX_FULL_Pos)
|
||||
|
||||
/**
|
||||
* @brief Get the datum read from RX0 register.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return Data in RX0 register.
|
||||
* @details Read SPI_RX0 register to get the received datum.
|
||||
*/
|
||||
#define SPI_READ_RX0(spi) ((spi)->RX[0])
|
||||
|
||||
/**
|
||||
* @brief Get the datum read from RX1 register.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return Data in RX1 register.
|
||||
* @details Read SPI_RX1 register to get the received datum.
|
||||
*/
|
||||
#define SPI_READ_RX1(spi) ((spi)->RX[1])
|
||||
|
||||
/**
|
||||
* @brief Write datum to TX0 register.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32TxData The datum which user attempt to transfer through SPI bus.
|
||||
* @return None.
|
||||
* @details Write u32TxData to TX0 register.
|
||||
*/
|
||||
#define SPI_WRITE_TX0(spi, u32TxData) ((spi)->TX[0] = (u32TxData))
|
||||
|
||||
/**
|
||||
* @brief Write datum to TX1 register.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32TxData The datum which user attempt to transfer through SPI bus.
|
||||
* @return None.
|
||||
* @details Write u32TxData to TX1 register.
|
||||
*/
|
||||
#define SPI_WRITE_TX1(spi, u32TxData) ((spi)->TX[1] = (u32TxData))
|
||||
|
||||
/**
|
||||
* @brief Set SPIn_SS0, SPIn_SS1 pin to high or low state.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] ss0 0 = Set SPIn_SS0 to low. 1 = Set SPIn_SS0 to high.
|
||||
* @param[in] ss1 0 = Set SPIn_SS1 to low. 1 = Set SPIn_SS1 to high.
|
||||
* @return None.
|
||||
* @details Disable automatic slave selection function and set SPIn_SS0/SPIn_SS1 pin to specified high/low state.
|
||||
* Only available in Master mode.
|
||||
*/
|
||||
#define SPI_SET_SS_LEVEL(spi, ss0, ss1) ((spi)->SSR = ((spi)->SSR & ~(SPI_SSR_AUTOSS_Msk|SPI_SSR_SS_LVL_Msk|SPI_SSR_SSR_Msk)) | (((ss1)^1) << 1) | ((ss0)^1))
|
||||
|
||||
/**
|
||||
* @brief Set SPIn_SS0 pin to high state.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Disable automatic slave selection function and set SPIn_SS0 pin to high state. Only available in Master mode.
|
||||
*/
|
||||
#define SPI_SET_SS0_HIGH(spi) ((spi)->SSR = ((spi)->SSR & ~(SPI_SSR_AUTOSS_Msk|SPI_SSR_SS_LVL_Msk|SPI_SS0)))
|
||||
|
||||
/**
|
||||
* @brief Set SPIn_SS1 pin to high state.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Disable automatic slave selection function and set SPIn_SS1 pin to high state. Only available in Master mode.
|
||||
*/
|
||||
#define SPI_SET_SS1_HIGH(spi) ((spi)->SSR = ((spi)->SSR & ~(SPI_SSR_AUTOSS_Msk|SPI_SSR_SS_LVL_Msk|SPI_SS1)))
|
||||
|
||||
/**
|
||||
* @brief Set SPIn_SS0 pin to low state.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Disable automatic slave selection function and set SPIn_SS0 pin to low state. Only available in Master mode.
|
||||
*/
|
||||
#define SPI_SET_SS0_LOW(spi) ((spi)->SSR = ((spi)->SSR & ~(SPI_SSR_AUTOSS_Msk|SPI_SSR_SS_LVL_Msk|SPI_SS0)) | SPI_SS0)
|
||||
|
||||
/**
|
||||
* @brief Set SPIn_SS1 pin to low state.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Disable automatic slave selection function and set SPIn_SS1 pin to low state. Only available in Master mode.
|
||||
*/
|
||||
#define SPI_SET_SS1_LOW(spi) ((spi)->SSR = ((spi)->SSR & ~(SPI_SSR_AUTOSS_Msk|SPI_SSR_SS_LVL_Msk|SPI_SS1)) | SPI_SS1)
|
||||
|
||||
/**
|
||||
* @brief Enable Byte Reorder function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set REORDER bit of SPI_CNTRL register to enable Byte Reorder function.
|
||||
*/
|
||||
#define SPI_ENABLE_BYTE_REORDER(spi) ((spi)->CNTRL |= SPI_CNTRL_REORDER_Msk)
|
||||
|
||||
/**
|
||||
* @brief Disable Byte Reorder function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Clear REORDER bit of SPI_CNTRL register to disable Byte Reorder function.
|
||||
*/
|
||||
#define SPI_DISABLE_BYTE_REORDER(spi) ((spi)->CNTRL &= ~SPI_CNTRL_REORDER_Msk)
|
||||
|
||||
/**
|
||||
* @brief Set the length of suspend interval.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32SuspCycle Decides the length of suspend interval. It could be 0 ~ 15.
|
||||
* @return None.
|
||||
* @details Set the length of suspend interval according to u32SuspCycle.
|
||||
* The length of suspend interval is ((u32SuspCycle + 0.5) * the length of one SPI bus clock cycle).
|
||||
* Only available in Master mode.
|
||||
*/
|
||||
#define SPI_SET_SUSPEND_CYCLE(spi, u32SuspCycle) ((spi)->CNTRL = ((spi)->CNTRL & ~SPI_CNTRL_SP_CYCLE_Msk) | ((u32SuspCycle) << SPI_CNTRL_SP_CYCLE_Pos))
|
||||
|
||||
/**
|
||||
* @brief Set the SPI transfer sequence with LSB first.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Set LSB bit of SPI_CNTRL register to set the SPI transfer sequence with LSB first.
|
||||
*/
|
||||
#define SPI_SET_LSB_FIRST(spi) ((spi)->CNTRL |= SPI_CNTRL_LSB_Msk)
|
||||
|
||||
/**
|
||||
* @brief Set the SPI transfer sequence with MSB first.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details Clear LSB bit of SPI_CNTRL register to set the SPI transfer sequence with MSB first.
|
||||
*/
|
||||
#define SPI_SET_MSB_FIRST(spi) ((spi)->CNTRL &= ~SPI_CNTRL_LSB_Msk)
|
||||
|
||||
/**
|
||||
* @brief Set the data width of a SPI transaction.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32Width The bit width of transfer data.
|
||||
* @return None.
|
||||
* @details The data width can be 8 ~ 32 bits.
|
||||
*/
|
||||
#define SPI_SET_DATA_WIDTH(spi, u32Width) ((spi)->CNTRL = ((spi)->CNTRL & ~SPI_CNTRL_TX_BIT_LEN_Msk) | (((u32Width)&0x1F) << SPI_CNTRL_TX_BIT_LEN_Pos))
|
||||
|
||||
/**
|
||||
* @brief Get the SPI busy state.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @retval 0 SPI controller is not busy.
|
||||
* @retval 1 SPI controller is busy.
|
||||
* @details This macro will return the busy state of SPI controller.
|
||||
*/
|
||||
#define SPI_IS_BUSY(spi) ( ((spi)->CNTRL & SPI_CNTRL_GO_BUSY_Msk)>>SPI_CNTRL_GO_BUSY_Pos )
|
||||
|
||||
/**
|
||||
* @brief Set the GO_BUSY bit to trigger SPI transfer.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None.
|
||||
* @details If FIFO mode is disabled, user can use this macro to trigger the data transfer after all configuration is ready.
|
||||
* If FIFO mode is enabled, user should not use this macro to trigger the data transfer. SPI controller will trigger the data transfer
|
||||
* automatically after user write to SPI_TX0/1 register.
|
||||
*/
|
||||
#define SPI_TRIGGER(spi) ((spi)->CNTRL |= SPI_CNTRL_GO_BUSY_Msk)
|
||||
|
||||
|
||||
|
||||
/* Function prototype declaration */
|
||||
uint32_t SPI_Open(SPI_T *spi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock);
|
||||
void SPI_Close(SPI_T *spi);
|
||||
void SPI_ClearRxFIFO(SPI_T *spi);
|
||||
void SPI_ClearTxFIFO(SPI_T *spi);
|
||||
void SPI_DisableAutoSS(SPI_T *spi);
|
||||
void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel);
|
||||
uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock);
|
||||
void SPI_EnableFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold);
|
||||
void SPI_DisableFIFO(SPI_T *spi);
|
||||
uint32_t SPI_GetBusClock(SPI_T *spi);
|
||||
void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask);
|
||||
void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask);
|
||||
uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask);
|
||||
void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask);
|
||||
uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @} End of SPI Device Function Interface
|
||||
*/
|
||||
|
||||
/**
|
||||
* @} End of NUC123 Function Interface
|
||||
*/
|
||||
|
||||
/**
|
||||
* @} End of Standard_Driver
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
1369
NUC123/StdDriver/inc/sys.h
Normal file
1369
NUC123/StdDriver/inc/sys.h
Normal file
File diff suppressed because it is too large
Load Diff
394
NUC123/StdDriver/inc/timer.h
Normal file
394
NUC123/StdDriver/inc/timer.h
Normal file
@ -0,0 +1,394 @@
|
||||
/**************************************************************************//**
|
||||
* @file timer.h
|
||||
* @version V3.00
|
||||
* $Revision: 7 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series Timer driver header file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#ifndef __TIMER_H__
|
||||
#define __TIMER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup TIMER_Driver TIMER Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup TIMER_EXPORTED_CONSTANTS TIMER Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
#define TIMER_ONESHOT_MODE (0UL << TIMER_TCSR_MODE_Pos) /*!< Timer working in one-shot mode */
|
||||
#define TIMER_PERIODIC_MODE (1UL << TIMER_TCSR_MODE_Pos) /*!< Timer working in periodic mode */
|
||||
#define TIMER_TOGGLE_MODE (2UL << TIMER_TCSR_MODE_Pos) /*!< Timer working in toggle-output mode */
|
||||
#define TIMER_CONTINUOUS_MODE (3UL << TIMER_TCSR_MODE_Pos) /*!< Timer working in continuous counting mode */
|
||||
#define TIMER_CAPTURE_FREE_COUNTING_MODE (0UL << TIMER_TEXCON_RSTCAPSEL_Pos) /*!< Timer capture event to get timer counter value */
|
||||
#define TIMER_CAPTURE_COUNTER_RESET_MODE (1UL << TIMER_TEXCON_RSTCAPSEL_Pos) /*!< Timer capture event to reset timer counter */
|
||||
#define TIMER_CAPTURE_FALLING_EDGE (0UL << TIMER_TEXCON_TEX_EDGE_Pos) /*!< Falling edge trigger timer capture */
|
||||
#define TIMER_CAPTURE_RISING_EDGE (1UL << TIMER_TEXCON_TEX_EDGE_Pos) /*!< Rising edge trigger timer capture */
|
||||
#define TIMER_CAPTURE_FALLING_AND_RISING_EDGE (2UL << TIMER_TEXCON_TEX_EDGE_Pos) /*!< Both falling and rising edge trigger timer capture */
|
||||
#define TIMER_COUNTER_FALLING_EDGE (0UL << TIMER_TEXCON_TX_PHASE_Pos) /*!< Counter increase on falling edge */
|
||||
#define TIMER_COUNTER_RISING_EDGE (1UL << TIMER_TEXCON_TX_PHASE_Pos) /*!< Counter increase on rising edge */
|
||||
|
||||
/*@}*/ /* end of group TIMER_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set Timer Compare Value
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
* @param[in] u32Value Timer compare value. Valid values are between 2 to 0xFFFFFF.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro is used to set new Timer compared value.
|
||||
*/
|
||||
#define TIMER_SET_CMP_VALUE(timer, u32Value) ((timer)->TCMPR = (u32Value))
|
||||
|
||||
/**
|
||||
* @brief Set Timer Prescale Value
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
* @param[in] u32Value Timer prescale value. Valid values are between 0 to 0xFF.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro is used to set new Timer prescale value.
|
||||
* @note Clock input is divided by (prescale + 1) before it is fed into timer.
|
||||
*/
|
||||
#define TIMER_SET_PRESCALE_VALUE(timer, u32Value) ((timer)->TCSR = ((timer)->TCSR & ~TIMER_TCSR_PRESCALE_Msk) | (u32Value))
|
||||
|
||||
/**
|
||||
* @brief Check specify Timer Status
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @retval 0 Timer 24-bit up counter is inactive
|
||||
* @retval 1 Timer 24-bit up counter is active
|
||||
*
|
||||
* @details This macro is used to check if specify Timer channel is inactive or active.
|
||||
*/
|
||||
#define TIMER_IS_ACTIVE(timer) ((timer)->TCSR & TIMER_TCSR_CACT_Msk ? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Start Timer Counting
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to start Timer counting.
|
||||
*/
|
||||
static __INLINE void TIMER_Start(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR |= TIMER_TCSR_CEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop Timer Counting
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to stop/suspend Timer counting.
|
||||
*/
|
||||
static __INLINE void TIMER_Stop(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR &= ~TIMER_TCSR_CEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Timer Interrupt Wakeup Function
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable the Timer interrupt wake-up function.
|
||||
* @note To wake the system from Power-down mode, timer clock source must be ether LXT or LIRC.
|
||||
*/
|
||||
static __INLINE void TIMER_EnableWakeup(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR |= TIMER_TCSR_WAKE_EN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Timer Wakeup Function
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable the Timer interrupt wake-up function.
|
||||
*/
|
||||
static __INLINE void TIMER_DisableWakeup(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR &= ~TIMER_TCSR_WAKE_EN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Capture Pin De-bounce
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable the capture pin detection de-bounce function.
|
||||
*/
|
||||
static __INLINE void TIMER_EnableCaptureDebounce(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXCON |= TIMER_TEXCON_TEXDB_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Capture Pin De-bounce
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable the capture pin detection de-bounce function.
|
||||
*/
|
||||
static __INLINE void TIMER_DisableCaptureDebounce(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXCON &= ~TIMER_TEXCON_TEXDB_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Counter Pin De-bounce
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable the counter pin detection de-bounce function.
|
||||
*/
|
||||
static __INLINE void TIMER_EnableEventCounterDebounce(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXCON |= TIMER_TEXCON_TCDB_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Counter Pin De-bounce
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable the counter pin detection de-bounce function.
|
||||
*/
|
||||
static __INLINE void TIMER_DisableEventCounterDebounce(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXCON &= ~TIMER_TEXCON_TCDB_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Timer Time-out Interrupt
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable the Timer time-out interrupt function.
|
||||
*/
|
||||
static __INLINE void TIMER_EnableInt(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR |= TIMER_TCSR_IE_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Timer Time-out Interrupt
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable the Timer time-out interrupt function.
|
||||
*/
|
||||
static __INLINE void TIMER_DisableInt(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR &= ~TIMER_TCSR_IE_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Capture Interrupt
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable the Timer capture trigger interrupt function.
|
||||
*/
|
||||
static __INLINE void TIMER_EnableCaptureInt(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXCON |= TIMER_TEXCON_TEXIEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Capture Interrupt
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable the Timer capture trigger interrupt function.
|
||||
*/
|
||||
static __INLINE void TIMER_DisableCaptureInt(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXCON &= ~TIMER_TEXCON_TEXIEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Timer Time-out Interrupt Flag
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @retval 0 Timer time-out interrupt did not occur
|
||||
* @retval 1 Timer time-out interrupt occurred
|
||||
*
|
||||
* @details This function indicates Timer time-out interrupt occurred or not.
|
||||
*/
|
||||
static __INLINE uint32_t TIMER_GetIntFlag(TIMER_T *timer)
|
||||
{
|
||||
return (timer->TISR & TIMER_TISR_TIF_Msk ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear Timer time-out Interrupt Flag
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function clears Timer time-out interrupt flag.
|
||||
*/
|
||||
static __INLINE void TIMER_ClearIntFlag(TIMER_T *timer)
|
||||
{
|
||||
timer->TISR = TIMER_TISR_TIF_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Timer Capture Interrupt Flag
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @retval 0 Timer capture interrupt did not occur
|
||||
* @retval 1 Timer capture interrupt occurred
|
||||
*
|
||||
* @details This function indicates Timer capture interrupt occurred or not.
|
||||
*/
|
||||
static __INLINE uint32_t TIMER_GetCaptureIntFlag(TIMER_T *timer)
|
||||
{
|
||||
return timer->TEXISR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear Timer capture Interrupt Flag
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function clears Timer capture interrupt flag.
|
||||
*/
|
||||
static __INLINE void TIMER_ClearCaptureIntFlag(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXISR = TIMER_TEXISR_TEXIF_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Timer Wakeup Flag
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @retval 0 Timer did not wake up system
|
||||
* @retval 1 Timer Timer wake up system
|
||||
*
|
||||
* @details This function indicates Timer has waked up system or not.
|
||||
*/
|
||||
static __INLINE uint32_t TIMER_GetWakeupFlag(TIMER_T *timer)
|
||||
{
|
||||
return (timer->TISR & TIMER_TISR_TWF_Msk ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear Timer Wake-up Flag
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function clears the Timer wake-up system flag.
|
||||
*/
|
||||
static __INLINE void TIMER_ClearWakeupFlag(TIMER_T *timer)
|
||||
{
|
||||
timer->TISR = TIMER_TISR_TWF_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Capture value
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return Capture Value
|
||||
*
|
||||
* @details This function reports the current timer capture data value.
|
||||
*/
|
||||
static __INLINE uint32_t TIMER_GetCaptureData(TIMER_T *timer)
|
||||
{
|
||||
return timer->TCAP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Counter value
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return Counter Value
|
||||
*
|
||||
* @details This function reports the current 24-bit timer counter value.
|
||||
*/
|
||||
static __INLINE uint32_t TIMER_GetCounter(TIMER_T *timer)
|
||||
{
|
||||
return timer->TDR;
|
||||
}
|
||||
|
||||
uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq);
|
||||
void TIMER_Close(TIMER_T *timer);
|
||||
void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec);
|
||||
void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge);
|
||||
void TIMER_DisableCapture(TIMER_T *timer);
|
||||
void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge);
|
||||
void TIMER_DisableEventCounter(TIMER_T *timer);
|
||||
uint32_t TIMER_GetModuleClock(TIMER_T *timer);
|
||||
|
||||
/*@}*/ /* end of group TIMER_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group TIMER_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__TIMER_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
428
NUC123/StdDriver/inc/uart.h
Normal file
428
NUC123/StdDriver/inc/uart.h
Normal file
@ -0,0 +1,428 @@
|
||||
/**************************************************************************//**
|
||||
* @file UART.h
|
||||
* @version V3.0
|
||||
* $Revision: 15 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series UART Interface Controller Driver Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __UART_H__
|
||||
#define __UART_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup UART_Driver UART Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup UART_EXPORTED_CONSTANTS UART Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* UART FIFO size constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#define UART0_FIFO_SIZE 16 /*!< UART0 supports separated receive/transmit 16/16 bytes entry FIFO */
|
||||
#define UART1_FIFO_SIZE 16 /*!< UART1 supports separated receive/transmit 16/16 bytes entry FIFO */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* UA_FCR constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#define UART_FCR_RFITL_1BYTE (0x0 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 1 byte */
|
||||
#define UART_FCR_RFITL_4BYTES (0x1 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 4 bytes */
|
||||
#define UART_FCR_RFITL_8BYTES (0x2 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 8 bytes */
|
||||
#define UART_FCR_RFITL_14BYTES (0x3 << UART_FCR_RFITL_Pos) /*!< UA_FCR setting to set RX FIFO Trigger Level to 14 bytes */
|
||||
|
||||
#define UART_FCR_RTS_TRI_LEV_1BYTE (0x0 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 1 byte */
|
||||
#define UART_FCR_RTS_TRI_LEV_4BYTES (0x1 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 4 bytes */
|
||||
#define UART_FCR_RTS_TRI_LEV_8BYTES (0x2 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 8 bytes */
|
||||
#define UART_FCR_RTS_TRI_LEV_14BYTES (0x3 << UART_FCR_RTS_TRI_LEV_Pos) /*!< UA_FCR setting to set RTS Trigger Level to 14 bytes */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* UA_LCR constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define UART_WORD_LEN_5 (0) /*!< UA_LCR setting to set UART word length to 5 bits */
|
||||
#define UART_WORD_LEN_6 (1) /*!< UA_LCR setting to set UART word length to 6 bits */
|
||||
#define UART_WORD_LEN_7 (2) /*!< UA_LCR setting to set UART word length to 7 bits */
|
||||
#define UART_WORD_LEN_8 (3) /*!< UA_LCR setting to set UART word length to 8 bits */
|
||||
|
||||
#define UART_PARITY_NONE (0x0 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to set UART as no parity */
|
||||
#define UART_PARITY_ODD (0x1 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to set UART as odd parity */
|
||||
#define UART_PARITY_EVEN (0x3 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to set UART as even parity */
|
||||
#define UART_PARITY_MARK (0x5 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to keep parity bit as '1' */
|
||||
#define UART_PARITY_SPACE (0x7 << UART_LCR_PBE_Pos) /*!< UA_LCR setting to keep parity bit as '0' */
|
||||
|
||||
#define UART_STOP_BIT_1 (0x0 << UART_LCR_NSB_Pos) /*!< UA_LCR setting for one stop bit */
|
||||
#define UART_STOP_BIT_1_5 (0x1 << UART_LCR_NSB_Pos) /*!< UA_LCR setting for 1.5 stop bit when 5-bit word length */
|
||||
#define UART_STOP_BIT_2 (0x1 << UART_LCR_NSB_Pos) /*!< UA_LCR setting for two stop bit when 6, 7, 8-bit word length */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* UART RTS LEVEL TRIGGER constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define UART_RTS_IS_LOW_LEV_ACTIVE (0x1 << UART_MCR_LEV_RTS_Pos) /*!< Set RTS is Low Level Active */
|
||||
#define UART_RTS_IS_HIGH_LEV_ACTIVE (0x0 << UART_MCR_LEV_RTS_Pos) /*!< Set RTS is High Level Active */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* UA_IRCR constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define UART_IRCR_TX_SELECT (0x1 << UART_IRCR_TX_SELECT_Pos) /*!< Set IrDA function Tx mode */
|
||||
#define UART_IRCR_RX_SELECT (0x0 << UART_IRCR_TX_SELECT_Pos) /*!< Set IrDA function Rx mode */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* UA_FUNC_SEL constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define UART_FUNC_SEL_UART (0x0 << UART_FUN_SEL_FUN_SEL_Pos) /*!< UA_FUNC_SEL setting to set UART Function (Default) */
|
||||
#define UART_FUNC_SEL_IrDA (0x2 << UART_FUN_SEL_FUN_SEL_Pos) /*!< UA_FUNC_SEL setting to set IrDA Function */
|
||||
#define UART_FUNC_SEL_RS485 (0x3 << UART_FUN_SEL_FUN_SEL_Pos) /*!< UA_FUNC_SEL setting to set RS485 Function */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* UART BAUDRATE MODE constants definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define UART_BAUD_MODE0 (0) /*!< Set UART Baudrate Mode is Mode0 */
|
||||
#define UART_BAUD_MODE2 (UART_BAUD_DIV_X_EN_Msk | UART_BAUD_DIV_X_ONE_Msk) /*!< Set UART Baudrate Mode is Mode2 */
|
||||
|
||||
|
||||
/*@}*/ /* end of group UART_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup UART_EXPORTED_FUNCTIONS UART Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate UART baudrate mode0 divider
|
||||
*
|
||||
* @param[in] u32SrcFreq UART clock frequency
|
||||
* @param[in] u32BaudRate Baudrate of UART module
|
||||
*
|
||||
* @return UART baudrate mode0 divider
|
||||
*
|
||||
* @details This macro calculate UART baudrate mode0 divider.
|
||||
*/
|
||||
#define UART_BAUD_MODE0_DIVIDER(u32SrcFreq, u32BaudRate) ((((u32SrcFreq) + ((u32BaudRate)*8)) / (u32BaudRate) >> 4)-2)
|
||||
|
||||
/**
|
||||
* @brief Calculate UART baudrate mode2 divider
|
||||
*
|
||||
* @param[in] u32SrcFreq UART clock frequency
|
||||
* @param[in] u32BaudRate Baudrate of UART module
|
||||
*
|
||||
* @return UART baudrate mode2 divider
|
||||
*
|
||||
* @details This macro calculate UART baudrate mode2 divider.
|
||||
*/
|
||||
#define UART_BAUD_MODE2_DIVIDER(u32SrcFreq, u32BaudRate) ((((u32SrcFreq) + ((u32BaudRate)/2)) / (u32BaudRate))-2)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write data
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
* @param[in] u8Data Data byte to transmit
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro write Data to Tx data register.
|
||||
*/
|
||||
#define UART_WRITE(uart, u8Data) ((uart)->THR = (u8Data))
|
||||
|
||||
/**
|
||||
* @brief Read data
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @return The oldest data byte in RX FIFO
|
||||
*
|
||||
* @details This macro read Rx data register.
|
||||
*/
|
||||
#define UART_READ(uart) ((uart)->RBR)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get Tx empty
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 0 Tx FIFO is not empty
|
||||
* @retval >=1 Tx FIFO is empty
|
||||
*
|
||||
* @details This macro get Tx empty register value.
|
||||
*/
|
||||
#define UART_GET_TX_EMPTY(uart) ((uart)->FSR & UART_FSR_TX_EMPTY_Msk)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get Rx empty
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 0 Rx FIFO is not empty
|
||||
* @retval >=1 Rx FIFO is empty
|
||||
*
|
||||
* @details This macro get Rx empty register value.
|
||||
*/
|
||||
#define UART_GET_RX_EMPTY(uart) ((uart)->FSR & UART_FSR_RX_EMPTY_Msk)
|
||||
|
||||
/**
|
||||
* @brief Check specified uart port transmission is over.
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 0 Transmission is not over.
|
||||
* @retval 1 Transmission is over.
|
||||
*
|
||||
* @details This macro return if Tx FIFO is empty and specified uart port transmission is over nor not.
|
||||
*/
|
||||
#define UART_IS_TX_EMPTY(uart) (((uart)->FSR & UART_FSR_TE_FLAG_Msk) >> UART_FSR_TE_FLAG_Pos)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wait specified uart port transmission is over
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro wait specified uart port transmission is over.
|
||||
*/
|
||||
#define UART_WAIT_TX_EMPTY(uart) while(!((((uart)->FSR) & UART_FSR_TE_FLAG_Msk) >> UART_FSR_TE_FLAG_Pos))
|
||||
|
||||
/**
|
||||
* @brief Check RX is ready or not
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 0 The number of bytes in the RX FIFO is less than the RFITL
|
||||
* @retval 1 The number of bytes in the RX FIFO equals or larger than RFITL
|
||||
*
|
||||
* @details This macro check receive data available interrupt flag is set or not.
|
||||
*/
|
||||
#define UART_IS_RX_READY(uart) (((uart)->ISR & UART_ISR_RDA_IF_Msk)>>UART_ISR_RDA_IF_Pos)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check TX FIFO is full or not
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 1 TX FIFO is full
|
||||
* @retval 0 TX FIFO is not full
|
||||
*
|
||||
* @details This macro check TX FIFO is full or not.
|
||||
*/
|
||||
#define UART_IS_TX_FULL(uart) (((uart)->FSR & UART_FSR_TX_FULL_Msk)>>UART_FSR_TX_FULL_Pos)
|
||||
|
||||
/**
|
||||
* @brief Check RX FIFO is full or not
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 1 RX FIFO is full
|
||||
* @retval 0 RX FIFO is not full
|
||||
*
|
||||
* @details This macro check RX FIFO is full or not.
|
||||
*/
|
||||
#define UART_IS_RX_FULL(uart) (((uart)->FSR & UART_FSR_RX_FULL_Msk)>>UART_FSR_RX_FULL_Pos)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get Tx full register value
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 0 Tx FIFO is not full.
|
||||
* @retval >=1 Tx FIFO is full.
|
||||
*
|
||||
* @details This macro get Tx full register value.
|
||||
*/
|
||||
#define UART_GET_TX_FULL(uart) ((uart)->FSR & UART_FSR_TX_FULL_Msk)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get Rx full register value
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 0 Rx FIFO is not full.
|
||||
* @retval >=1 Rx FIFO is full.
|
||||
*
|
||||
* @details This macro get Rx full register value.
|
||||
*/
|
||||
#define UART_GET_RX_FULL(uart) ((uart)->FSR & UART_FSR_RX_FULL_Msk)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable specified UART interrupt
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
* @param[in] u32eIntSel Interrupt type select
|
||||
* - UART_IER_WAKE_EN_Msk : Wakeup interrupt
|
||||
* - UART_IER_BUF_ERR_IEN_Msk : Buffer Error interrupt
|
||||
* - UART_IER_TOUT_IEN_Msk : Rx time-out interrupt
|
||||
* - UART_IER_MODEM_IEN_Msk : Modem interrupt
|
||||
* - UART_IER_RLS_IEN_Msk : Rx Line status interrupt
|
||||
* - UART_IER_THRE_IEN_Msk : Tx empty interrupt
|
||||
* - UART_IER_RDA_IEN_Msk : Rx ready interrupt
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro enable specified UART interrupt.
|
||||
*/
|
||||
#define UART_ENABLE_INT(uart, u32eIntSel) ((uart)->IER |= (u32eIntSel))
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable specified UART interrupt
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
* @param[in] u32eIntSel Interrupt type select
|
||||
* - UART_IER_WAKE_EN_Msk : Wakeup interrupt
|
||||
* - UART_IER_BUF_ERR_IEN_Msk : Buffer Error interrupt
|
||||
* - UART_IER_TOUT_IEN_Msk : Rx time-out interrupt
|
||||
* - UART_IER_MODEM_IEN_Msk : Modem interrupt
|
||||
* - UART_IER_RLS_IEN_Msk : Rx Line status interrupt
|
||||
* - UART_IER_THRE_IEN_Msk : Tx empty interrupt
|
||||
* - UART_IER_RDA_IEN_Msk : Rx ready interrupt
|
||||
* @return None
|
||||
*
|
||||
* @details This macro disable specified UART interrupt.
|
||||
*/
|
||||
#define UART_DISABLE_INT(uart, u32eIntSel) ((uart)->IER &= ~ (u32eIntSel))
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get specified interrupt indicator status
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32eIntTypeFlag Interrupt Type Flag, should be
|
||||
* - UART_ISR_HW_BUF_ERR_INT_Msk : In DMA Mode, Buffer Error Interrupt Indicator
|
||||
* - UART_ISR_HW_TOUT_INT_Msk : In DMA Mode, Rx Time-out Interrupt Indicator
|
||||
* - UART_ISR_HW_MODEM_INT_Msk : In DMA Mode, MODEM Status Interrupt Indicator
|
||||
* - UART_ISR_HW_RLS_INT_Msk : In DMA Mode, Rx Line Status Interrupt Indicator
|
||||
* - UART_ISR_HW_BUF_ERR_IF_Msk : In DMA Mode, Buffer Error Interrupt Flag
|
||||
* - UART_ISR_HW_TOUT_IF_Msk : In DMA Mode, Rx Time-out Interrupt Flag
|
||||
* - UART_ISR_HW_MODEM_IF_Msk : In DMA Mode, MODEM Status Interrupt Flag
|
||||
* - UART_ISR_HW_RLS_IF_Msk : In DMA Mode, Rx Line Status Interrupt Flag
|
||||
* - UART_ISR_LIN_INT_Msk : LIN Bus Interrupt Indicator
|
||||
* - UART_ISR_BUF_ERR_INT_Msk : Buffer Error Interrupt Indicator
|
||||
* - UART_ISR_TOUT_INT_Msk : Rx Time-out Interrupt Indicator
|
||||
* - UART_ISR_MODEM_INT_Msk : MODEM Status Interrupt Indicator
|
||||
* - UART_ISR_RLS_INT_Msk : Rx Line Status Interrupt Indicator
|
||||
* - UART_ISR_THRE_INT_Msk : Tx Empty Interrupt Indicator
|
||||
* - UART_ISR_RDA_INT_Msk : Rx Ready Interrupt Indicator
|
||||
* - UART_ISR_LIN_IF_Msk : LIN Bus Interrupt Flag
|
||||
* - UART_ISR_BUF_ERR_IF_Msk : Buffer Error Interrupt Flag
|
||||
* - UART_ISR_TOUT_IF_Msk : Rx Time-out Interrupt Flag
|
||||
* - UART_ISR_MODEM_IF_Msk : MODEM Status Interrupt Flag
|
||||
* - UART_ISR_RLS_IF_Msk : Rx Line Status Interrupt Flag
|
||||
* - UART_ISR_THRE_IF_Msk : Tx Empty Interrupt Flag
|
||||
* - UART_ISR_RDA_IF_Msk : Rx Ready Interrupt Flag
|
||||
*
|
||||
* @retval 0 The specified interrupt is not happened.
|
||||
* @retval 1 The specified interrupt is happened.
|
||||
*
|
||||
* @details This macro get specified interrupt flag or interrupt indicator status.
|
||||
*/
|
||||
#define UART_GET_INT_FLAG(uart,u32eIntTypeFlag) (((uart)->ISR & (u32eIntTypeFlag))?1:0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set RTS pin to low
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro set RTS pin to low.
|
||||
*/
|
||||
__STATIC_INLINE void UART_CLEAR_RTS(UART_T* uart)
|
||||
{
|
||||
(uart)->MCR |= UART_MCR_LEV_RTS_Msk;
|
||||
(uart)->MCR &= ~UART_MCR_RTS_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RTS pin to high
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
* @return None
|
||||
*
|
||||
* @details This macro set RTS pin to high.
|
||||
*/
|
||||
__STATIC_INLINE void UART_SET_RTS(UART_T* uart)
|
||||
{
|
||||
(uart)->MCR |= UART_MCR_LEV_RTS_Msk | UART_MCR_RTS_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear RS-485 Address Byte Detection Flag
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro clear RS-485 address byte detection flag.
|
||||
*/
|
||||
#define UART_RS485_CLEAR_ADDR_FLAG(uart) ((uart)->FSR = UART_FSR_RS485_ADD_DETF_Msk)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get RS-485 Address Byte Detection Flag
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
*
|
||||
* @retval 0 Receiver detects a data that is not an address bit.
|
||||
* @retval 1 Receiver detects a data that is an address bit.
|
||||
*
|
||||
* @details This macro get RS-485 address byte detection flag.
|
||||
*/
|
||||
#define UART_RS485_GET_ADDR_FLAG(uart) (((uart)->FSR & UART_FSR_RS485_ADD_DETF_Msk) >> UART_FSR_RS485_ADD_DETF_Pos)
|
||||
|
||||
|
||||
void UART_ClearIntFlag(UART_T* uart , uint32_t u32InterruptFlag);
|
||||
void UART_Close(UART_T* uart);
|
||||
void UART_DisableFlowCtrl(UART_T* uart);
|
||||
void UART_DisableInt(UART_T* uart, uint32_t u32InterruptFlag);
|
||||
void UART_EnableFlowCtrl(UART_T* uart);
|
||||
void UART_EnableInt(UART_T* uart, uint32_t u32InterruptFlag);
|
||||
void UART_Open(UART_T* uart, uint32_t u32baudrate);
|
||||
uint32_t UART_Read(UART_T* uart, uint8_t *pu8RxBuf, uint32_t u32ReadBytes);
|
||||
void UART_SetLine_Config(UART_T* uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits);
|
||||
void UART_SetTimeoutCnt(UART_T* uart, uint32_t u32TOC);
|
||||
void UART_SelectIrDAMode(UART_T* uart, uint32_t u32Buadrate, uint32_t u32Direction);
|
||||
void UART_SelectRS485Mode(UART_T* uart, uint32_t u32Mode, uint32_t u32Addr);
|
||||
uint32_t UART_Write(UART_T* uart, uint8_t *pu8TxBuf, uint32_t u32WriteBytes);
|
||||
|
||||
|
||||
/*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group UART_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__UART_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
||||
|
663
NUC123/StdDriver/inc/usbd.h
Normal file
663
NUC123/StdDriver/inc/usbd.h
Normal file
@ -0,0 +1,663 @@
|
||||
/**************************************************************************//**
|
||||
* @file usbd.h
|
||||
* @version V3.0
|
||||
* $Revision: 18 $
|
||||
* $Date: 15/09/03 11:15a $
|
||||
* @brief NUC123 series USB driver header file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __USBD_H__
|
||||
#define __USBD_H__
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBD_Driver USBD Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBD_EXPORTED_STRUCTS USBD Exported Structs
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
typedef struct s_usbd_info
|
||||
{
|
||||
const uint8_t *gu8DevDesc; /*!< Pointer for USB Device Descriptor */
|
||||
const uint8_t *gu8ConfigDesc; /*!< Pointer for USB Configuration Descriptor */
|
||||
const uint8_t **gu8StringDesc; /*!< Pointer for USB String Descriptor pointers */
|
||||
const uint8_t **gu8HidReportDesc; /*!< Pointer for USB HID Report Descriptor */
|
||||
const uint32_t *gu32HidReportSize; /*!< Pointer for HID Report descriptor Size */
|
||||
const uint32_t *gu32ConfigHidDescIdx; /*!< Pointer for HID Descriptor start index */
|
||||
|
||||
} S_USBD_INFO_T;
|
||||
|
||||
extern const S_USBD_INFO_T gsInfo;
|
||||
|
||||
/*@}*/ /* end of group USBD_EXPORTED_STRUCTS */
|
||||
|
||||
|
||||
|
||||
/** @addtogroup USBD_EXPORTED_CONSTANTS USBD Exported Constants
|
||||
@{
|
||||
*/
|
||||
|
||||
#define USBD_BUF_BASE (USBD_BASE+0x100)
|
||||
|
||||
|
||||
|
||||
#define USBD_MAX_EP 8
|
||||
|
||||
#define EP0 0 /*!< Endpoint 0 */
|
||||
#define EP1 1 /*!< Endpoint 1 */
|
||||
#define EP2 2 /*!< Endpoint 2 */
|
||||
#define EP3 3 /*!< Endpoint 3 */
|
||||
#define EP4 4 /*!< Endpoint 4 */
|
||||
#define EP5 5 /*!< Endpoint 5 */
|
||||
#define EP6 6 /*!< Endpoint 6 */
|
||||
#define EP7 7 /*!< Endpoint 7 */
|
||||
|
||||
|
||||
/*!<USB Request Type */
|
||||
#define REQ_STANDARD 0x00
|
||||
#define REQ_CLASS 0x20
|
||||
#define REQ_VENDOR 0x40
|
||||
|
||||
/*!<USB Standard Request */
|
||||
#define GET_STATUS 0x00
|
||||
#define CLEAR_FEATURE 0x01
|
||||
#define SET_FEATURE 0x03
|
||||
#define SET_ADDRESS 0x05
|
||||
#define GET_DESCRIPTOR 0x06
|
||||
#define SET_DESCRIPTOR 0x07
|
||||
#define GET_CONFIGURATION 0x08
|
||||
#define SET_CONFIGURATION 0x09
|
||||
#define GET_INTERFACE 0x0A
|
||||
#define SET_INTERFACE 0x0B
|
||||
#define SYNC_FRAME 0x0C
|
||||
|
||||
/*!<USB Descriptor Type */
|
||||
#define DESC_DEVICE 0x01
|
||||
#define DESC_CONFIG 0x02
|
||||
#define DESC_STRING 0x03
|
||||
#define DESC_INTERFACE 0x04
|
||||
#define DESC_ENDPOINT 0x05
|
||||
#define DESC_QUALIFIER 0x06
|
||||
#define DESC_OTHERSPEED 0x07
|
||||
|
||||
/*!<USB HID Descriptor Type */
|
||||
#define DESC_HID 0x21
|
||||
#define DESC_HID_RPT 0x22
|
||||
|
||||
/*!<USB Descriptor Length */
|
||||
#define LEN_DEVICE 18
|
||||
#define LEN_CONFIG 9
|
||||
#define LEN_INTERFACE 9
|
||||
#define LEN_ENDPOINT 7
|
||||
#define LEN_HID 9
|
||||
#define LEN_CCID 0x36
|
||||
|
||||
/*!<USB Endpoint Type */
|
||||
#define EP_ISO 0x01
|
||||
#define EP_BULK 0x02
|
||||
#define EP_INT 0x03
|
||||
|
||||
#define EP_INPUT 0x80
|
||||
#define EP_OUTPUT 0x00
|
||||
|
||||
/*!<USB Feature Selector */
|
||||
#define FEATURE_DEVICE_REMOTE_WAKEUP 0x01
|
||||
#define FEATURE_ENDPOINT_HALT 0x00
|
||||
|
||||
/******************************************************************************/
|
||||
/* USB Specific Macros */
|
||||
/******************************************************************************/
|
||||
|
||||
#define USBD_WAKEUP_EN USBD_INTEN_WAKEUP_EN_Msk /*!< USB Wake-up Enable */
|
||||
#define USBD_DRVSE0 USBD_DRVSE0_DRVSE0_Msk /*!< Drive SE0 */
|
||||
|
||||
#define USBD_DPPU_EN USBD_ATTR_DPPU_EN_Msk /*!< USB D+ Pull-up Enable */
|
||||
#define USBD_PWRDN USBD_ATTR_PWRDN_Msk /*!< PHY Turn-On */
|
||||
#define USBD_PHY_EN USBD_ATTR_PHY_EN_Msk /*!< PHY Enable */
|
||||
#define USBD_USB_EN USBD_ATTR_USB_EN_Msk /*!< USB Enable */
|
||||
|
||||
#define USBD_INT_BUS USBD_INTEN_BUS_IE_Msk /*!< USB Bus Event Interrupt */
|
||||
#define USBD_INT_USB USBD_INTEN_USB_IE_Msk /*!< USB USB Event Interrupt */
|
||||
#define USBD_INT_FLDET USBD_INTEN_FLDET_IE_Msk /*!< USB Float Detect Interrupt */
|
||||
#define USBD_INT_WAKEUP (USBD_INTEN_WAKEUP_IE_Msk | USBD_INTEN_WAKEUP_EN_Msk) /*!< USB Wake-up Interrupt */
|
||||
|
||||
#define USBD_INTSTS_WAKEUP USBD_INTSTS_WAKEUP_STS_Msk /*!< USB Wakeup Interrupt Status */
|
||||
#define USBD_INTSTS_FLDET USBD_INTSTS_FLDET_STS_Msk /*!< USB Float Detect Interrupt Status */
|
||||
#define USBD_INTSTS_BUS USBD_INTSTS_BUS_STS_Msk /*!< USB Bus Event Interrupt Status */
|
||||
#define USBD_INTSTS_USB USBD_INTSTS_USB_STS_Msk /*!< USB USB Event Interrupt Status */
|
||||
#define USBD_INTSTS_SETUP USBD_INTSTS_SETUP_Msk /*!< USB Setup Event */
|
||||
#define USBD_INTSTS_EP0 USBD_INTSTS_EPEVT0_Msk /*!< USB Endpoint 0 Event */
|
||||
#define USBD_INTSTS_EP1 USBD_INTSTS_EPEVT1_Msk /*!< USB Endpoint 1 Event */
|
||||
#define USBD_INTSTS_EP2 USBD_INTSTS_EPEVT2_Msk /*!< USB Endpoint 2 Event */
|
||||
#define USBD_INTSTS_EP3 USBD_INTSTS_EPEVT3_Msk /*!< USB Endpoint 3 Event */
|
||||
#define USBD_INTSTS_EP4 USBD_INTSTS_EPEVT4_Msk /*!< USB Endpoint 4 Event */
|
||||
#define USBD_INTSTS_EP5 USBD_INTSTS_EPEVT5_Msk /*!< USB Endpoint 5 Event */
|
||||
#define USBD_INTSTS_EP6 USBD_INTSTS_EPEVT6_Msk /*!< USB Endpoint 6 Event */
|
||||
#define USBD_INTSTS_EP7 USBD_INTSTS_EPEVT7_Msk /*!< USB Endpoint 7 Event */
|
||||
|
||||
#define USBD_STATE_USBRST USBD_ATTR_USBRST_Msk /*!< USB Bus Reset */
|
||||
#define USBD_STATE_SUSPEND USBD_ATTR_SUSPEND_Msk /*!< USB Bus Suspend */
|
||||
#define USBD_STATE_RESUME USBD_ATTR_RESUME_Msk /*!< USB Bus Resume */
|
||||
#define USBD_STATE_TIMEOUT USBD_ATTR_TIMEOUT_Msk /*!< USB Bus Timeout */
|
||||
|
||||
#define USBD_CFGP_SSTALL USBD_CFGP_SSTALL_Msk /*!< Set Stall */
|
||||
#define USBD_CFG_CSTALL USBD_CFG_CSTALL_Msk /*!< Clear Stall */
|
||||
|
||||
#define USBD_CFG_EPMODE_DISABLE (0ul << USBD_CFG_STATE_Pos)/*!< Endpoint Disable */
|
||||
#define USBD_CFG_EPMODE_OUT (1ul << USBD_CFG_STATE_Pos)/*!< Out Endpoint */
|
||||
#define USBD_CFG_EPMODE_IN (2ul << USBD_CFG_STATE_Pos)/*!< In Endpoint */
|
||||
#define USBD_CFG_TYPE_ISO (1ul << USBD_CFG_ISOCH_Pos) /*!< Isochronous */
|
||||
|
||||
|
||||
/*@}*/ /* end of group USBD_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
|
||||
/** @addtogroup USBD_EXPORTED_FUNCTIONS USBD Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Compare two input numbers and return maximum one.
|
||||
*
|
||||
* @param[in] a First number to be compared.
|
||||
* @param[in] b Second number to be compared.
|
||||
*
|
||||
* @return Maximum value between a and b.
|
||||
*
|
||||
* @details If a > b, then return a. Otherwise, return b.
|
||||
*/
|
||||
#define Maximum(a,b) ((a)>(b) ? (a) : (b))
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compare two input numbers and return minimum one
|
||||
*
|
||||
* @param[in] a First number to be compared
|
||||
* @param[in] b Second number to be compared
|
||||
*
|
||||
* @return Minimum value between a and b
|
||||
*
|
||||
* @details If a < b, then return a. Otherwise, return b.
|
||||
*/
|
||||
#define Minimum(a,b) ((a)<(b) ? (a) : (b))
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable USB
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To set USB ATTR control register to enable USB and PHY.
|
||||
*
|
||||
*/
|
||||
#define USBD_ENABLE_USB() ((uint32_t)(USBD->ATTR |= (USBD_USB_EN|USBD_PHY_EN)))
|
||||
|
||||
/**
|
||||
* @brief Disable USB
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To set USB ATTR control register to disable USB.
|
||||
*
|
||||
*/
|
||||
#define USBD_DISABLE_USB() ((uint32_t)(USBD->ATTR &= ~USBD_USB_EN))
|
||||
|
||||
/**
|
||||
* @brief Enable USB PHY
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To set USB ATTR control register to enable USB PHY.
|
||||
*
|
||||
*/
|
||||
#define USBD_ENABLE_PHY() ((uint32_t)(USBD->ATTR |= USBD_PHY_EN))
|
||||
|
||||
/**
|
||||
* @brief Disable USB PHY
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details To set USB ATTR control register to disable USB PHY.
|
||||
*
|
||||
*/
|
||||
#define USBD_DISABLE_PHY() ((uint32_t)(USBD->ATTR &= ~USBD_PHY_EN))
|
||||
|
||||
/**
|
||||
* @brief Enable SE0. Force USB PHY transceiver to drive SE0.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set DRVSE0 bit of USB_DRVSE0 register to enable software-disconnect function. Force USB PHY transceiver to drive SE0 to bus.
|
||||
*
|
||||
*/
|
||||
#define USBD_SET_SE0() ((uint32_t)(USBD->DRVSE0 |= USBD_DRVSE0))
|
||||
|
||||
/**
|
||||
* @brief Disable SE0
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Clear DRVSE0 bit of USB_DRVSE0 register to disable software-disconnect function.
|
||||
*
|
||||
*/
|
||||
#define USBD_CLR_SE0() ((uint32_t)(USBD->DRVSE0 &= ~USBD_DRVSE0))
|
||||
|
||||
/**
|
||||
* @brief Set USB device address
|
||||
*
|
||||
* @param[in] addr The USB device address.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Write USB device address to USB_FADDR register.
|
||||
*
|
||||
*/
|
||||
#define USBD_SET_ADDR(addr) (USBD->FADDR = (addr))
|
||||
|
||||
/**
|
||||
* @brief Get USB device address
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return USB device address
|
||||
*
|
||||
* @details Read USB_FADDR register to get USB device address.
|
||||
*
|
||||
*/
|
||||
#define USBD_GET_ADDR() ((uint32_t)(USBD->FADDR))
|
||||
|
||||
/**
|
||||
* @brief Enable USB interrupt function
|
||||
*
|
||||
* @param[in] intr The combination of the specified interrupt enable bits.
|
||||
* Each bit corresponds to a interrupt enable bit.
|
||||
* This parameter decides which interrupts will be enabled.
|
||||
* (USBD_INT_WAKEUP, USBD_INT_FLDET, USBD_INT_USB, USBD_INT_BUS)
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable USB related interrupt functions specified by intr parameter.
|
||||
*
|
||||
*/
|
||||
#define USBD_ENABLE_INT(intr) (USBD->INTEN |= (intr))
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The value of USB_INTSTS register
|
||||
*
|
||||
* @details Return all interrupt flags of USB_INTSTS register.
|
||||
*
|
||||
*/
|
||||
#define USBD_GET_INT_FLAG() ((uint32_t)(USBD->INTSTS))
|
||||
|
||||
/**
|
||||
* @brief Clear USB interrupt flag
|
||||
*
|
||||
* @param[in] flag The combination of the specified interrupt flags.
|
||||
* Each bit corresponds to a interrupt source.
|
||||
* This parameter decides which interrupt flags will be cleared.
|
||||
* (USBD_INTSTS_WAKEUP, USBD_INTSTS_FLDET, USBD_INTSTS_BUS, USBD_INTSTS_USB)
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Clear USB related interrupt flags specified by flag parameter.
|
||||
*
|
||||
*/
|
||||
#define USBD_CLR_INT_FLAG(flag) (USBD->INTSTS = (flag))
|
||||
|
||||
/**
|
||||
* @brief Get endpoint status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The value of USB_EPSTS register.
|
||||
*
|
||||
* @details Return all endpoint status.
|
||||
*
|
||||
*/
|
||||
#define USBD_GET_EP_FLAG() ((uint32_t)(USBD->EPSTS))
|
||||
|
||||
/**
|
||||
* @brief Get USB bus state
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The value of USB_ATTR[3:0].
|
||||
* Bit 0 indicates USB bus reset status.
|
||||
* Bit 1 indicates USB bus suspend status.
|
||||
* Bit 2 indicates USB bus resume status.
|
||||
* Bit 3 indicates USB bus time-out status.
|
||||
*
|
||||
* @details Return USB_ATTR[3:0] for USB bus events.
|
||||
*
|
||||
*/
|
||||
#define USBD_GET_BUS_STATE() ((uint32_t)(USBD->ATTR & 0xf))
|
||||
|
||||
/**
|
||||
* @brief Check cable connection state
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 USB cable is not attached.
|
||||
* @retval 1 USB cable is attached.
|
||||
*
|
||||
* @details Check the connection state by FLDET bit of USB_FLDET register.
|
||||
*
|
||||
*/
|
||||
#define USBD_IS_ATTACHED() ((uint32_t)(USBD->FLDET & USBD_FLDET_FLDET_Msk))
|
||||
|
||||
/**
|
||||
* @brief Stop USB transaction of the specified endpoint ID
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Write 1 to CLRRDY bit of USB_CFGPx register to stop USB transaction of the specified endpoint ID.
|
||||
*
|
||||
*/
|
||||
#define USBD_STOP_TRANSACTION(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFGP + (uint32_t)((ep) << 4))) |= USBD_CFGP_CLRRDY_Msk)
|
||||
|
||||
/**
|
||||
* @brief Set USB DATA1 PID for the specified endpoint ID
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set DSQ_SYNC bit of USB_CFGx register to specify the DATA1 PID for the following IN token transaction.
|
||||
* Base on this setting, hardware will toggle PID between DATA0 and DATA1 automatically for IN token transactions.
|
||||
*
|
||||
*/
|
||||
#define USBD_SET_DATA1(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFG + (uint32_t)((ep) << 4))) |= USBD_CFG_DSQ_SYNC_Msk)
|
||||
|
||||
/**
|
||||
* @brief Set USB DATA0 PID for the specified endpoint ID
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Clear DSQ_SYNC bit of USB_CFGx register to specify the DATA0 PID for the following IN token transaction.
|
||||
* Base on this setting, hardware will toggle PID between DATA0 and DATA1 automatically for IN token transactions.
|
||||
*
|
||||
*/
|
||||
#define USBD_SET_DATA0(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFG + (uint32_t)((ep) << 4))) &= (~USBD_CFG_DSQ_SYNC_Msk))
|
||||
|
||||
/**
|
||||
* @brief Set USB payload size (IN data)
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @param[in] size The transfer length.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro will write the transfer length to USB_MXPLDx register for IN data transaction.
|
||||
*
|
||||
*/
|
||||
#define USBD_SET_PAYLOAD_LEN(ep, size) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].MXPLD + (uint32_t)((ep) << 4))) = (size))
|
||||
|
||||
/**
|
||||
* @brief Get USB payload size (OUT data)
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @return The value of USB_MXPLDx register.
|
||||
*
|
||||
* @details Get the data length of OUT data transaction by reading USB_MXPLDx register.
|
||||
*
|
||||
*/
|
||||
#define USBD_GET_PAYLOAD_LEN(ep) ((uint32_t)*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].MXPLD + (uint32_t)((ep) << 4))))
|
||||
|
||||
/**
|
||||
* @brief Configure endpoint
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @param[in] config The USB configuration.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro will write config parameter to USB_CFGx register of specified endpoint ID.
|
||||
*
|
||||
*/
|
||||
#define USBD_CONFIG_EP(ep, config) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFG + (uint32_t)((ep) << 4))) = (config))
|
||||
|
||||
/**
|
||||
* @brief Set USB endpoint buffer
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @param[in] offset The SRAM offset.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro will set the SRAM offset for the specified endpoint ID.
|
||||
*
|
||||
*/
|
||||
#define USBD_SET_EP_BUF_ADDR(ep, offset) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].BUFSEG + (uint32_t)((ep) << 4))) = (offset))
|
||||
|
||||
/**
|
||||
* @brief Get the offset of the specified USB endpoint buffer
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @return The offset of the specified endpoint buffer.
|
||||
*
|
||||
* @details This macro will return the SRAM offset of the specified endpoint ID.
|
||||
*
|
||||
*/
|
||||
#define USBD_GET_EP_BUF_ADDR(ep) ((uint32_t)*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].BUFSEG + (uint32_t)((ep) << 4))))
|
||||
|
||||
/**
|
||||
* @brief Set USB endpoint stall state
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set USB endpoint stall state for the specified endpoint ID. Endpoint will respond STALL token automatically.
|
||||
*
|
||||
*/
|
||||
#define USBD_SET_EP_STALL(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFGP + (uint32_t)((ep) << 4))) |= USBD_CFGP_SSTALL_Msk)
|
||||
|
||||
/**
|
||||
* @brief Clear USB endpoint stall state
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Clear USB endpoint stall state for the specified endpoint ID. Endpoint will respond ACK/NAK token.
|
||||
*/
|
||||
#define USBD_CLR_EP_STALL(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFGP + (uint32_t)((ep) << 4))) &= ~USBD_CFGP_SSTALL_Msk)
|
||||
|
||||
/**
|
||||
* @brief Get USB endpoint stall state
|
||||
*
|
||||
* @param[in] ep The USB endpoint ID. NUC123 supports 8 hardware endpoint ID. This parameter could be 0 ~ 7.
|
||||
*
|
||||
* @retval 0 USB endpoint is not stalled.
|
||||
* @retval Others USB endpoint is stalled.
|
||||
*
|
||||
* @details Get USB endpoint stall state of the specified endpoint ID.
|
||||
*
|
||||
*/
|
||||
#define USBD_GET_EP_STALL(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EP[0].CFGP + (uint32_t)((ep) << 4))) & USBD_CFGP_SSTALL_Msk)
|
||||
|
||||
/**
|
||||
* @brief To support byte access between USB SRAM and system SRAM
|
||||
*
|
||||
* @param[in] dest Destination pointer.
|
||||
*
|
||||
* @param[in] src Source pointer.
|
||||
*
|
||||
* @param[in] size Byte count.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will copy the number of data specified by size and src parameters to the address specified by dest parameter.
|
||||
*
|
||||
*/
|
||||
static __INLINE void USBD_MemCopy(uint8_t *dest, uint8_t *src, int32_t size)
|
||||
{
|
||||
while(size--) *dest++ = *src++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set USB endpoint stall state
|
||||
*
|
||||
* @param[in] epnum USB endpoint number
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Set USB endpoint stall state. Endpoint will respond STALL token automatically.
|
||||
*
|
||||
*/
|
||||
static __INLINE void USBD_SetStall(uint8_t epnum)
|
||||
{
|
||||
uint32_t u32CfgAddr;
|
||||
uint32_t u32Cfg;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < USBD_MAX_EP; i++)
|
||||
{
|
||||
u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFG; /* USBD_CFG0 */
|
||||
u32Cfg = *((__IO uint32_t *)(u32CfgAddr));
|
||||
|
||||
if((u32Cfg & 0xf) == epnum)
|
||||
{
|
||||
u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFGP; /* USBD_CFGP0 */
|
||||
u32Cfg = *((__IO uint32_t *)(u32CfgAddr));
|
||||
|
||||
*((__IO uint32_t *)(u32CfgAddr)) = (u32Cfg | USBD_CFGP_SSTALL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear USB endpoint stall state
|
||||
*
|
||||
* @param[in] epnum USB endpoint number
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Clear USB endpoint stall state. Endpoint will respond ACK/NAK token.
|
||||
*/
|
||||
static __INLINE void USBD_ClearStall(uint8_t epnum)
|
||||
{
|
||||
uint32_t u32CfgAddr;
|
||||
uint32_t u32Cfg;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < USBD_MAX_EP; i++)
|
||||
{
|
||||
u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFG; /* USBD_CFG0 */
|
||||
u32Cfg = *((__IO uint32_t *)(u32CfgAddr));
|
||||
|
||||
if((u32Cfg & 0xf) == epnum)
|
||||
{
|
||||
u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFGP; /* USBD_CFGP0 */
|
||||
u32Cfg = *((__IO uint32_t *)(u32CfgAddr));
|
||||
|
||||
*((__IO uint32_t *)(u32CfgAddr)) = (u32Cfg & ~USBD_CFGP_SSTALL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get USB endpoint stall state
|
||||
*
|
||||
* @param[in] epnum USB endpoint number
|
||||
*
|
||||
* @retval 0 USB endpoint is not stalled.
|
||||
* @retval Others USB endpoint is stalled.
|
||||
*
|
||||
* @details Get USB endpoint stall state.
|
||||
*
|
||||
*/
|
||||
static __INLINE uint32_t USBD_GetStall(uint8_t epnum)
|
||||
{
|
||||
uint32_t u32CfgAddr;
|
||||
uint32_t u32Cfg;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < USBD_MAX_EP; i++)
|
||||
{
|
||||
u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFG; /* USBD_CFG0 */
|
||||
u32Cfg = *((__IO uint32_t *)(u32CfgAddr));
|
||||
|
||||
if((u32Cfg & 0xf) == epnum)
|
||||
{
|
||||
u32CfgAddr = (uint32_t)(i << 4) + (uint32_t)&USBD->EP[0].CFGP; /* USBD_CFGP0 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ((*((__IO uint32_t *)(u32CfgAddr))) & USBD_CFGP_SSTALL);
|
||||
}
|
||||
|
||||
|
||||
extern volatile uint8_t g_usbd_RemoteWakeupEn;
|
||||
|
||||
typedef void (*VENDOR_REQ)(void); /*!< Functional pointer type declaration for Vendor class */
|
||||
typedef void (*CLASS_REQ)(void); /*!< Functional pointer type declaration for USB class request callback handler */
|
||||
typedef void (*SET_INTERFACE_REQ)(void); /*!< Functional pointer type declaration for USB set interface request callback handler */
|
||||
typedef void (*SET_CONFIG_CB)(void); /*!< Functional pointer type declaration for USB set configuration request callback handler */
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface);
|
||||
void USBD_Start(void);
|
||||
void USBD_GetSetupPacket(uint8_t *buf);
|
||||
void USBD_ProcessSetupPacket(void);
|
||||
void USBD_StandardRequest(void);
|
||||
void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size);
|
||||
void USBD_CtrlIn(void);
|
||||
void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size);
|
||||
void USBD_CtrlOut(void);
|
||||
void USBD_SwReset(void);
|
||||
void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq);
|
||||
void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback);
|
||||
void USBD_LockEpStall(uint32_t u32EpBitmap);
|
||||
|
||||
/*@}*/ /* end of group USBD_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group USBD_Driver */
|
||||
|
||||
/*@}*/ /* end of group Device_Driver */
|
||||
|
||||
|
||||
#endif //__USBD_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
201
NUC123/StdDriver/inc/wdt.h
Normal file
201
NUC123/StdDriver/inc/wdt.h
Normal file
@ -0,0 +1,201 @@
|
||||
/**************************************************************************//**
|
||||
* @file wdt.h
|
||||
* @version V3.00
|
||||
* $Revision: 3 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series WDT driver header file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#ifndef __WDT_H__
|
||||
#define __WDT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WDT_Driver WDT Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WDT_EXPORTED_CONSTANTS WDT Exported Constants
|
||||
@{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* WTCR Constants Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define WDT_TIMEOUT_2POW4 (0UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^4 * WDT clocks */
|
||||
#define WDT_TIMEOUT_2POW6 (1UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^6 * WDT clocks */
|
||||
#define WDT_TIMEOUT_2POW8 (2UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^8 * WDT clocks */
|
||||
#define WDT_TIMEOUT_2POW10 (3UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^10 * WDT clocks */
|
||||
#define WDT_TIMEOUT_2POW12 (4UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^12 * WDT clocks */
|
||||
#define WDT_TIMEOUT_2POW14 (5UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^14 * WDT clocks */
|
||||
#define WDT_TIMEOUT_2POW16 (6UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^16 * WDT clocks */
|
||||
#define WDT_TIMEOUT_2POW18 (7UL << WDT_WTCR_WTIS_Pos) /*!< Setting WDT time-out interval to 2^18 * WDT clocks */
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* WTCRALT Constants Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define WDT_RESET_DELAY_1026CLK (0UL << WDT_WTCRALT_WTRDSEL_Pos) /*!< Setting WDT reset delay period to 1026 * WDT clocks */
|
||||
#define WDT_RESET_DELAY_130CLK (1UL << WDT_WTCRALT_WTRDSEL_Pos) /*!< Setting WDT reset delay period to 130 * WDT clocks */
|
||||
#define WDT_RESET_DELAY_18CLK (2UL << WDT_WTCRALT_WTRDSEL_Pos) /*!< Setting WDT reset delay period to 18 * WDT clocks */
|
||||
#define WDT_RESET_DELAY_3CLK (3UL << WDT_WTCRALT_WTRDSEL_Pos) /*!< Setting WDT reset delay period to 3 * WDT clocks */
|
||||
|
||||
/*@}*/ /* end of group WDT_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup WDT_EXPORTED_FUNCTIONS WDT Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clear WDT Reset System Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro clear WDT time-out reset system flag.
|
||||
*/
|
||||
#define WDT_CLEAR_RESET_FLAG() (WDT->WTCR = (WDT->WTCR & ~(WDT_WTCR_WTIF_Msk | WDT_WTCR_WTWKF_Msk)) | WDT_WTCR_WTRF_Msk)
|
||||
|
||||
/**
|
||||
* @brief Clear WDT Time-out Interrupt Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro clear WDT time-out interrupt flag.
|
||||
*/
|
||||
#define WDT_CLEAR_TIMEOUT_INT_FLAG() (WDT->WTCR = (WDT->WTCR & ~(WDT_WTCR_WTRF_Msk | WDT_WTCR_WTWKF_Msk)) | WDT_WTCR_WTIF_Msk)
|
||||
|
||||
/**
|
||||
* @brief Clear WDT Wake-up Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro clear WDT time-out wake-up system flag.
|
||||
*/
|
||||
#define WDT_CLEAR_TIMEOUT_WAKEUP_FLAG() (WDT->WTCR = (WDT->WTCR & ~(WDT_WTCR_WTRF_Msk | WDT_WTCR_WTIF_Msk)) | WDT_WTCR_WTWKF_Msk)
|
||||
|
||||
/**
|
||||
* @brief Get WDT Time-out Reset Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 WDT did not cause system reset
|
||||
* @retval 1 WDT caused system reset
|
||||
*
|
||||
* @details This macro indicate WDT time-out to reset system or not.
|
||||
*/
|
||||
#define WDT_GET_RESET_FLAG() ((WDT->WTCR & WDT_WTCR_WTRF_Msk)? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Get WDT Time-out Interrupt Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 WDT time-out interrupt did not occur
|
||||
* @retval 1 WDT time-out interrupt occurred
|
||||
*
|
||||
* @details This macro indicate WDT time-out interrupt occurred or not.
|
||||
*/
|
||||
#define WDT_GET_TIMEOUT_INT_FLAG() ((WDT->WTCR & WDT_WTCR_WTIF_Msk)? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Get WDT Time-out Wake-up Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 WDT did not wake up system
|
||||
* @retval 1 WDT waked up system
|
||||
*
|
||||
* @details This macro indicate WDT time-out waked system up or not
|
||||
*/
|
||||
#define WDT_GET_TIMEOUT_WAKEUP_FLAG() ((WDT->WTCR & WDT_WTCR_WTWKF_Msk)? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief Reset WDT Counter
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro is used to reset 18-bit WDT counter.
|
||||
* @note If WDT is activated and enabled to reset system, user must reset WDT counter \n
|
||||
* before WDT time-out plus reset delay reached. Or WDT generate a reset signal.
|
||||
*/
|
||||
#define WDT_RESET_COUNTER() (WDT->WTCR = (WDT->WTCR & ~(WDT_WTCR_WTIF_Msk | WDT_WTCR_WTWKF_Msk | WDT_WTCR_WTRF_Msk)) | WDT_WTCR_WTR_Msk)
|
||||
|
||||
/**
|
||||
* @brief Stop WDT Counting
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function stops WDT counting and disable WDT module.
|
||||
*/
|
||||
static __INLINE void WDT_Close(void)
|
||||
{
|
||||
WDT->WTCR = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable WDT Time-out Interrupt
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function enable the WDT time-out interrupt.
|
||||
*/
|
||||
static __INLINE void WDT_EnableInt(void)
|
||||
{
|
||||
WDT->WTCR |= WDT_WTCR_WTIE_Msk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable WDT Time-out Interrupt
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function disables the WDT time-out interrupt.
|
||||
*/
|
||||
static __INLINE void WDT_DisableInt(void)
|
||||
{
|
||||
// Do not touch write 1 clear bits
|
||||
WDT->WTCR &= ~(WDT_WTCR_WTIE_Msk | WDT_WTCR_WTRF_Msk | WDT_WTCR_WTIF_Msk | WDT_WTCR_WTWKF_Msk);
|
||||
return;
|
||||
}
|
||||
|
||||
void WDT_Open(uint32_t u32TimeoutInterval, uint32_t u32ResetDelay, uint32_t u32EnableReset, uint32_t u32EnableWakeup);
|
||||
|
||||
/*@}*/ /* end of group WDT_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group WDT_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__WDT_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
145
NUC123/StdDriver/inc/wwdt.h
Normal file
145
NUC123/StdDriver/inc/wwdt.h
Normal file
@ -0,0 +1,145 @@
|
||||
/**************************************************************************//**
|
||||
* @file wwdt.h
|
||||
* @version V3.00
|
||||
* $Revision: 3 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief WWDT driver header file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#ifndef __WWDT_H__
|
||||
#define __WWDT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WWDT_Driver WWDT Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WWDT_EXPORTED_CONSTANTS WWDT Exported Constants
|
||||
@{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* WWDTCR Constants Definitions */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#define WWDT_PRESCALER_1 (0 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 1 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_2 (1 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 2 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_4 (2 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 4 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_8 (3 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 8 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_16 (4 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 16 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_32 (5 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 32 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_64 (6 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 64 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_128 (7 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 128 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_192 (8 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 192 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_256 (9 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 256 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_384 (10 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 384 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_512 (11 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 512 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_768 (12 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 768 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_1024 (13 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 1024 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_1536 (14 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 1536 * (64*WWDT_CLK) */
|
||||
#define WWDT_PRESCALER_2048 (15 << WWDT_WWDTCR_PERIODSEL_Pos) /*!< Select max time-out period to 2048 * (64*WWDT_CLK) */
|
||||
|
||||
#define WWDT_RELOAD_WORD (0x00005AA5) /*!< Fill this value to WWDTRLD register to reload WWDT counter */
|
||||
|
||||
/*@}*/ /* end of group WWDT_EXPORTED_CONSTANTS */
|
||||
|
||||
|
||||
/** @addtogroup WWDT_EXPORTED_FUNCTIONS WWDT Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clear WWDT Reset System Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro is used to clear WWDT counter time-out reset system flag.
|
||||
*/
|
||||
#define WWDT_CLEAR_RESET_FLAG() (WWDT->WWDTSR = WWDT_WWDTSR_WWDTRF_Msk)
|
||||
|
||||
/**
|
||||
* @brief Clear WWDT Compared Match Interrupt Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro is used to clear WWDT counter compare match interrupt flag.
|
||||
*/
|
||||
#define WWDT_CLEAR_INT_FLAG() (WWDT->WWDTSR = WWDT_WWDTSR_WWDTIF_Msk)
|
||||
|
||||
/**
|
||||
* @brief Get WWDT Reset Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 WWDT did not cause system reset
|
||||
* @retval 1 WWDT counter time-out caused system reset
|
||||
*
|
||||
* @details This macro is used to indicate WWDT counter time-out reset system flag.
|
||||
*/
|
||||
#define WWDT_GET_RESET_FLAG() ((WWDT->WWDTSR & WWDT_WWDTSR_WWDTRF_Msk)? 1:0)
|
||||
|
||||
/**
|
||||
* @brief Get WWDT Compared Match Interrupt Flag
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 WWDT counter compare match interrupt did not occur
|
||||
* @retval 1 WWDT counter compare match interrupt occurred
|
||||
*
|
||||
* @details This macro is used to indicate WWDT counter compare match interrupt occurred or not.
|
||||
*/
|
||||
#define WWDT_GET_INT_FLAG() ((WWDT->WWDTSR & WWDT_WWDTSR_WWDTIF_Msk)? 1:0)
|
||||
|
||||
/**
|
||||
* @brief Get WWDT Counter value
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return WWDT Counter Value
|
||||
*
|
||||
* @details This macro to reflects the current WWDT counter value.
|
||||
*/
|
||||
#define WWDT_GET_COUNTER() (WWDT->WWDTCVR)
|
||||
|
||||
/**
|
||||
* @brief Reload WWDT Counter
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This macro is used to reload the WWDT counter value to 0x3F.
|
||||
* @note After WWDT enabled, user must reload WWDT counter while current counter is less than compare value \n
|
||||
* and larger than 0, otherwise WWDT will cause system reset immediately.
|
||||
*/
|
||||
#define WWDT_RELOAD_COUNTER() (WWDT->WWDTRLD = WWDT_RELOAD_WORD)
|
||||
|
||||
void WWDT_Open(uint32_t u32PreScale, uint32_t u32CmpValue, uint32_t u32EnableInt);
|
||||
|
||||
/*@}*/ /* end of group WWDT_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group WWDT_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__WWDT_H__
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
152
NUC123/StdDriver/src/adc.c
Normal file
152
NUC123/StdDriver/src/adc.c
Normal file
@ -0,0 +1,152 @@
|
||||
/**************************************************************************//**
|
||||
* @file adc.c
|
||||
* @version V3.00
|
||||
* $Revision: 7 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series ADC driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup ADC_Driver ADC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup ADC_EXPORTED_FUNCTIONS ADC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function configures ADC module to be ready for convert the input from selected channel.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32InputMode Decides the ADC analog input mode. This parameter is not used.
|
||||
* @param[in] u32OpMode Decides the ADC operation mode. Valid values are:
|
||||
* - \ref ADC_ADCR_ADMD_SINGLE :Single mode.
|
||||
* - \ref ADC_ADCR_ADMD_SINGLE_CYCLE :Single cycle scan mode.
|
||||
* - \ref ADC_ADCR_ADMD_CONTINUOUS :Continuous scan mode.
|
||||
* @param[in] u32ChMask Channel enable bit. Each bit corresponds to a input channel. Bit 0 is channel 0, bit 1 is channel 1..., bit 7 is channel 7.
|
||||
* @return None
|
||||
* @details Before starting A/D conversion function, ADEN(ADCR[0]) should be set to 1.
|
||||
* @note NUC123 series MCU ADC can only convert 1 channel at a time. If more than 1 channels are enabled, only channel
|
||||
* with smallest number will be convert.
|
||||
* @note This function does not turn on ADC power nor does trigger ADC conversion.
|
||||
*/
|
||||
void ADC_Open(ADC_T *adc,
|
||||
uint32_t u32InputMode,
|
||||
uint32_t u32OpMode,
|
||||
uint32_t u32ChMask)
|
||||
{
|
||||
|
||||
(adc)->ADCR = ((adc)->ADCR & (~ADC_ADCR_ADMD_Msk)) | (u32OpMode);
|
||||
|
||||
(adc)->ADCHER = ((adc)->ADCHER & ~ADC_ADCHER_CHEN_Msk) | (u32ChMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable ADC module.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details Disable A/D converter analog circuit for saving power consumption.
|
||||
*/
|
||||
void ADC_Close(ADC_T *adc)
|
||||
{
|
||||
(adc)->ADCR &= (~ADC_ADCR_ADEN_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the hardware trigger condition and enable hardware trigger.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32Source Decides the hardware trigger source. Valid values are:
|
||||
* - \ref ADC_ADCR_TRGS_STADC :A/D conversion is started by external STADC pin.
|
||||
* - \ref ADC_ADCR_TRGS_PWM :A/D conversion is started by PWM.
|
||||
* @param[in] u32Param ADC trigger by external pin, this parameter is used to set trigger condition. Valid values are:
|
||||
* - \ref ADC_ADCR_TRGCOND_LOW_LEVEL :STADC Low level active.
|
||||
* - \ref ADC_ADCR_TRGCOND_HIGH_LEVEL :STADC High level active.
|
||||
* - \ref ADC_ADCR_TRGCOND_FALLING_EDGE :STADC Falling edge active.
|
||||
* - \ref ADC_ADCR_TRGCOND_RISING_EDGE :STADC Rising edge active.
|
||||
* @return None
|
||||
* @details Software should disable TRGEN (ADCR[8]) and ADST (ADCR[11]) before change TRGS(ADCR[5:4]).
|
||||
*/
|
||||
void ADC_EnableHWTrigger(ADC_T *adc,
|
||||
uint32_t u32Source,
|
||||
uint32_t u32Param)
|
||||
{
|
||||
(adc)->ADCR &= ~(ADC_ADCR_TRGS_Msk | ADC_ADCR_TRGCOND_Msk | ADC_ADCR_TRGEN_Msk);
|
||||
|
||||
(adc)->ADCR |= (u32Source) | (u32Param) | ADC_ADCR_TRGEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable hardware trigger ADC function.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @return None
|
||||
* @details Disable triggering of A/D conversion by hardware (external STADC pin or PWM Center-aligned trigger).
|
||||
*/
|
||||
void ADC_DisableHWTrigger(ADC_T *adc)
|
||||
{
|
||||
(adc)->ADCR &= ~(ADC_ADCR_TRGS_Msk | ADC_ADCR_TRGCOND_Msk | ADC_ADCR_TRGEN_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the interrupt(s) selected by u32Mask parameter.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32Mask The combination of interrupt status bits listed below. Each bit
|
||||
* corresponds to a interrupt status. This parameter decides which
|
||||
* interrupts will be enabled.
|
||||
* - \ref ADC_ADF_INT :ADC convert complete interrupt.
|
||||
* - \ref ADC_CMP0_INT :ADC comparator 0 interrupt.
|
||||
* - \ref ADC_CMP1_INT :ADC comparator 1 interrupt.
|
||||
* @return None
|
||||
* @details A/D conversion end interrupt request is generated if ADIE bit (ADCR[1]) is set to 1.
|
||||
* If the compare function is enabled and the compare condition matches the setting of CMPCOND (ADCMPR0/1[2])
|
||||
* and CMPMATCNT (ADCMPR0/1[11:8]), CMPF0/1 bit (ADSR[1]/[2]) will be asserted, in the meanwhile,
|
||||
* if CMPIE (ADCMPR0/1[1]) is set to 1, a compare interrupt request is generated.
|
||||
*/
|
||||
void ADC_EnableInt(ADC_T *adc, uint32_t u32Mask)
|
||||
{
|
||||
if((u32Mask) & ADC_ADF_INT)
|
||||
(adc)->ADCR |= ADC_ADCR_ADIE_Msk;
|
||||
if((u32Mask) & ADC_CMP0_INT)
|
||||
(adc)->ADCMPR[0] |= ADC_ADCMPR_CMPIE_Msk;
|
||||
if((u32Mask) & ADC_CMP1_INT)
|
||||
(adc)->ADCMPR[1] |= ADC_ADCMPR_CMPIE_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the interrupt(s) selected by u32Mask parameter.
|
||||
* @param[in] adc The pointer of the specified ADC module.
|
||||
* @param[in] u32Mask The combination of interrupt status bits listed below. Each bit
|
||||
* corresponds to a interrupt status. This parameter decides which
|
||||
* interrupts will be disabled.
|
||||
* - \ref ADC_ADF_INT :ADC convert complete interrupt.
|
||||
* - \ref ADC_CMP0_INT :ADC comparator 0 interrupt.
|
||||
* - \ref ADC_CMP1_INT :ADC comparator 1 interrupt.
|
||||
* @return None
|
||||
* @details The function is used to disable convert complete interrupt, comparator 0 interrupt or comparator 1 interrupt.
|
||||
*/
|
||||
void ADC_DisableInt(ADC_T *adc, uint32_t u32Mask)
|
||||
{
|
||||
if((u32Mask) & ADC_ADF_INT)
|
||||
(adc)->ADCR &= ~ADC_ADCR_ADIE_Msk;
|
||||
if((u32Mask) & ADC_CMP0_INT)
|
||||
(adc)->ADCMPR[0] &= ~ADC_ADCMPR_CMPIE_Msk;
|
||||
if((u32Mask) & ADC_CMP1_INT)
|
||||
(adc)->ADCMPR[1] &= ~ADC_ADCMPR_CMPIE_Msk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group ADC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group ADC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
679
NUC123/StdDriver/src/clk.c
Normal file
679
NUC123/StdDriver/src/clk.c
Normal file
@ -0,0 +1,679 @@
|
||||
/**************************************************************************//**
|
||||
* @file clk.c
|
||||
* @version V3.00
|
||||
* $Revision: 26 $
|
||||
* $Date: 15/10/30 8:44a $
|
||||
* @brief NUC123 series CLK driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CLK_Driver CLK Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Disable frequency output function
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function disable frequency output function.
|
||||
*/
|
||||
void CLK_DisableCKO(void)
|
||||
{
|
||||
/* Disable CKO clock source */
|
||||
CLK_DisableModuleClock(FDIV_MODULE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable frequency divider module clock.
|
||||
* enable frequency divider clock function and configure frequency divider.
|
||||
* @param[in] u32ClkSrc is frequency divider function clock source. Including :
|
||||
* - \ref CLK_CLKSEL2_FRQDIV_S_HXT
|
||||
* - \ref CLK_CLKSEL2_FRQDIV_S_HCLK
|
||||
* - \ref CLK_CLKSEL2_FRQDIV_S_HIRC
|
||||
* @param[in] u32ClkDiv is divider output frequency selection.
|
||||
* @param[in] u32ClkDivBy1En is not supported.
|
||||
* @return None
|
||||
*
|
||||
* @details Output selected clock to CKO. The output clock frequency is divided by u32ClkDiv.
|
||||
* The formula is:
|
||||
* CKO frequency = (Clock source frequency) / 2^(u32ClkDiv + 1)
|
||||
* This function is just used to set CKO clock.
|
||||
* User must enable I/O for CKO clock output pin by themselves.
|
||||
*/
|
||||
void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
|
||||
{
|
||||
/* CKO = clock source / 2^(u32ClkDiv + 1) */
|
||||
CLK->FRQDIV = (CLK_FRQDIV_DIVIDER_EN_Msk | u32ClkDiv) ;
|
||||
|
||||
/* Enable CKO clock source */
|
||||
CLK_EnableModuleClock(FDIV_MODULE);
|
||||
|
||||
/* Select CKO clock source */
|
||||
CLK_SetModuleClock(FDIV_MODULE, u32ClkSrc, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enter to Power-down mode
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function is used to let system enter to Power-down mode.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_PowerDown(void)
|
||||
{
|
||||
/* Set the processor uses deep sleep as its low power mode */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* Set system Power-down enabled and Power-down entry condition */
|
||||
CLK->PWRCON |= (CLK_PWRCON_PWR_DOWN_EN_Msk | CLK_PWRCON_PD_WAIT_CPU_Msk);
|
||||
|
||||
/* Chip enter Power-down mode after CPU run WFI instruction */
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enter to Idle mode
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function let system enter to Idle mode.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_Idle(void)
|
||||
{
|
||||
/* Set the processor uses sleep as its low power mode */
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* Set chip in idle mode because of WFI command */
|
||||
CLK->PWRCON &= ~CLK_PWRCON_PWR_DOWN_EN_Msk;
|
||||
|
||||
/* Chip enter idle mode after CPU run WFI instruction */
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get external high speed crystal clock frequency
|
||||
* @param None
|
||||
* @return External high frequency crystal frequency
|
||||
* @details This function get external high frequency crystal frequency. The frequency unit is Hz.
|
||||
*/
|
||||
uint32_t CLK_GetHXTFreq(void)
|
||||
{
|
||||
if(CLK->PWRCON & CLK_PWRCON_XTL12M_EN_Msk)
|
||||
return __HXT;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get HCLK frequency
|
||||
* @param None
|
||||
* @return HCLK frequency
|
||||
* @details This function get HCLK frequency. The frequency unit is Hz.
|
||||
*/
|
||||
uint32_t CLK_GetHCLKFreq(void)
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
return SystemCoreClock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCLK frequency
|
||||
* @param None
|
||||
* @return PCLK frequency
|
||||
* @details This function get PCLK frequency. The frequency unit is Hz.
|
||||
*/
|
||||
uint32_t CLK_GetPCLKFreq(void)
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
if(CLK->APBDIV & CLK_APBDIV_APBDIV_Msk)
|
||||
return SystemCoreClock / 2;
|
||||
else
|
||||
return SystemCoreClock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CPU frequency
|
||||
* @param None
|
||||
* @return CPU frequency
|
||||
* @details This function get CPU frequency. The frequency unit is Hz.
|
||||
*/
|
||||
uint32_t CLK_GetCPUFreq(void)
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
return SystemCoreClock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set HCLK frequency
|
||||
* @param[in] u32Hclk is HCLK frequency. The range of u32Hclk is 25 MHz ~ 72 MHz.
|
||||
* @return HCLK frequency
|
||||
* @details This function is used to set HCLK frequency. The frequency unit is Hz.
|
||||
* It would configure PLL frequency to 50MHz ~ 144MHz,
|
||||
* set HCLK clock divider as 2 and switch HCLK clock source to PLL.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
|
||||
{
|
||||
uint32_t u32HIRCSTB;
|
||||
|
||||
/* Read HIRC clock source stable flag */
|
||||
u32HIRCSTB = CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk;
|
||||
|
||||
/* The range of u32Hclk is 25 MHz ~ 72 MHz */
|
||||
if(u32Hclk > FREQ_72MHZ)
|
||||
u32Hclk = FREQ_72MHZ;
|
||||
if(u32Hclk < FREQ_25MHZ)
|
||||
u32Hclk = FREQ_25MHZ;
|
||||
|
||||
/* Switch HCLK clock source to HIRC clock for safe */
|
||||
CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
|
||||
CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_Msk;
|
||||
CLK->CLKDIV &= (~CLK_CLKDIV_HCLK_N_Msk);
|
||||
|
||||
/* Configure PLL setting if HXT clock is stable */
|
||||
if(CLK->CLKSTATUS & CLK_CLKSTATUS_XTL12M_STB_Msk)
|
||||
u32Hclk = CLK_EnablePLL(CLK_PLLCON_PLL_SRC_HXT, (u32Hclk << 1));
|
||||
|
||||
/* Configure PLL setting if HXT clock is not stable */
|
||||
else
|
||||
{
|
||||
u32Hclk = CLK_EnablePLL(CLK_PLLCON_PLL_SRC_HIRC, (u32Hclk << 1));
|
||||
|
||||
/* Read HIRC clock source stable flag */
|
||||
u32HIRCSTB = CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk;
|
||||
}
|
||||
|
||||
/* Select HCLK clock source to PLL,
|
||||
Select HCLK clock source divider as 2
|
||||
and update system core clock
|
||||
*/
|
||||
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_PLL, CLK_CLKDIV_HCLK(2));
|
||||
|
||||
/* Disable HIRC if HIRC is disabled before setting core clock */
|
||||
if( u32HIRCSTB == 0 )
|
||||
CLK->PWRCON &= ~CLK_PWRCON_OSC22M_EN_Msk;
|
||||
|
||||
/* Return actually HCLK frequency is PLL frequency divide 2 */
|
||||
return u32Hclk >> 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set HCLK clock source and HCLK clock divider
|
||||
* @param[in] u32ClkSrc is HCLK clock source. Including :
|
||||
* - \ref CLK_CLKSEL0_HCLK_S_HXT
|
||||
* - \ref CLK_CLKSEL0_HCLK_S_PLL_DIV2
|
||||
* - \ref CLK_CLKSEL0_HCLK_S_PLL
|
||||
* - \ref CLK_CLKSEL0_HCLK_S_LIRC
|
||||
* - \ref CLK_CLKSEL0_HCLK_S_HIRC
|
||||
* @param[in] u32ClkDiv is HCLK clock divider. Including :
|
||||
* - \ref CLK_CLKDIV_HCLK(x)
|
||||
* @return None
|
||||
* @details This function set HCLK clock source and HCLK clock divider.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
|
||||
{
|
||||
uint32_t u32HIRCSTB;
|
||||
|
||||
/* Read HIRC clock source stable flag */
|
||||
u32HIRCSTB = CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk;
|
||||
|
||||
/* Switch to HIRC for Safe. Avoid HCLK too high when applying new divider. */
|
||||
CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
|
||||
CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLK_S_Msk)) | CLK_CLKSEL0_HCLK_S_HIRC;
|
||||
|
||||
/* Apply new Divider */
|
||||
CLK->CLKDIV = (CLK->CLKDIV & (~CLK_CLKDIV_HCLK_N_Msk)) | u32ClkDiv;
|
||||
|
||||
/* Switch HCLK to new HCLK source */
|
||||
CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLK_S_Msk)) | u32ClkSrc;
|
||||
|
||||
/* Update System Core Clock */
|
||||
SystemCoreClockUpdate();
|
||||
|
||||
/* Disable HIRC if HIRC is disabled before switching HCLK source */
|
||||
if( u32HIRCSTB == 0 )
|
||||
CLK->PWRCON &= ~CLK_PWRCON_OSC22M_EN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function set selected module clock source and module clock divider
|
||||
* @param[in] u32ModuleIdx is module index.
|
||||
* @param[in] u32ClkSrc is module clock source.
|
||||
* @param[in] u32ClkDiv is module clock divider.
|
||||
* @return None
|
||||
* @details Valid parameter combinations listed in following table:
|
||||
*
|
||||
* |Module index |Clock source |Divider |
|
||||
* | :---------------- | :------------------------------------| :--------------------- |
|
||||
* |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDT_S_LIRC | x |
|
||||
* |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDT_S_HCLK_DIV2048 | x |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADC_S_HXT |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADC_S_PLL |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADC_S_HCLK |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADC_S_HIRC |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref SPI0_MODULE |\ref CLK_CLKSEL1_SPI0_S_HCLK | x |
|
||||
* |\ref SPI0_MODULE |\ref CLK_CLKSEL1_SPI0_S_PLL | x |
|
||||
* |\ref SPI1_MODULE |\ref CLK_CLKSEL1_SPI1_S_HCLK | x |
|
||||
* |\ref SPI1_MODULE |\ref CLK_CLKSEL1_SPI1_S_PLL | x |
|
||||
* |\ref SPI2_MODULE |\ref CLK_CLKSEL1_SPI2_S_HCLK | x |
|
||||
* |\ref SPI2_MODULE |\ref CLK_CLKSEL1_SPI2_S_PLL | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0_S_HXT | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0_S_HCLK | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0_S_EXT_TRG | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0_S_LIRC | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0_S_HIRC | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1_S_HXT | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1_S_HCLK | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1_S_EXT_TRG | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1_S_LIRC | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1_S_HIRC | x |
|
||||
* |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2_S_HXT | x |
|
||||
* |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2_S_HCLK | x |
|
||||
* |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2_S_EXT_TRG | x |
|
||||
* |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2_S_LIRC | x |
|
||||
* |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2_S_HIRC | x |
|
||||
* |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3_S_HXT | x |
|
||||
* |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3_S_HCLK | x |
|
||||
* |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3_S_EXT_TRG | x |
|
||||
* |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3_S_LIRC | x |
|
||||
* |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3_S_HIRC | x |
|
||||
* |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART_S_HXT |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART_S_PLL |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART_S_HIRC |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART_S_HXT |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART_S_PLL |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART_S_HIRC |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref PWM01_MODULE |\ref CLK_CLKSEL12_PWM01_S_HXT | x |
|
||||
* |\ref PWM01_MODULE |\ref CLK_CLKSEL12_PWM01_S_HCLK | x |
|
||||
* |\ref PWM01_MODULE |\ref CLK_CLKSEL12_PWM01_S_HIRC | x |
|
||||
* |\ref PWM01_MODULE |\ref CLK_CLKSEL12_PWM01_S_LIRC | x |
|
||||
* |\ref PWM23_MODULE |\ref CLK_CLKSEL12_PWM23_S_HXT | x |
|
||||
* |\ref PWM23_MODULE |\ref CLK_CLKSEL12_PWM23_S_HCLK | x |
|
||||
* |\ref PWM23_MODULE |\ref CLK_CLKSEL12_PWM23_S_HIRC | x |
|
||||
* |\ref PWM23_MODULE |\ref CLK_CLKSEL12_PWM23_S_LIRC | x |
|
||||
* |\ref I2S_MODULE |\ref CLK_CLKSEL2_I2S_S_HXT | x |
|
||||
* |\ref I2S_MODULE |\ref CLK_CLKSEL2_I2S_S_PLL | x |
|
||||
* |\ref I2S_MODULE |\ref CLK_CLKSEL2_I2S_S_HCLK | x |
|
||||
* |\ref I2S_MODULE |\ref CLK_CLKSEL2_I2S_S_HIRC | x |
|
||||
* |\ref FDIV_MODULE |\ref CLK_CLKSEL2_FRQDIV_S_HXT | x |
|
||||
* |\ref FDIV_MODULE |\ref CLK_CLKSEL2_FRQDIV_S_HCLK | x |
|
||||
* |\ref FDIV_MODULE |\ref CLK_CLKSEL2_FRQDIV_S_HIRC | x |
|
||||
* |\ref WWDT_MODULE |\ref CLK_CLKSEL2_WWDT_S_HCLK_DIV2048 | x |
|
||||
* |\ref WWDT_MODULE |\ref CLK_CLKSEL2_WWDT_S_LIRC | x |
|
||||
* |\ref USBD_MODULE | x |\ref CLK_CLKDIV_USB(x) |
|
||||
*/
|
||||
|
||||
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
|
||||
{
|
||||
uint32_t u32sel = 0, u32div = 0;
|
||||
uint32_t u32SelTbl[3] = {0x0, 0x4, 0xC};
|
||||
|
||||
if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
|
||||
{
|
||||
/* Get clock select control register address */
|
||||
u32sel = (uint32_t)&CLK->CLKSEL0 + (u32SelTbl[MODULE_CLKSEL(u32ModuleIdx)]);
|
||||
/* Set new clock selection setting */
|
||||
M32(u32sel) = (M32(u32sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc;
|
||||
|
||||
/* We need to set CLKSEL2 ext control bit for PWM */
|
||||
if(u32ModuleIdx == PWM01_MODULE)
|
||||
CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_PWM01_S_E_Msk)) | (u32ClkSrc & CLK_CLKSEL2_PWM01_S_E_Msk);
|
||||
else if(u32ModuleIdx == PWM23_MODULE)
|
||||
CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_PWM23_S_E_Msk)) | (u32ClkSrc & CLK_CLKSEL2_PWM23_S_E_Msk);
|
||||
}
|
||||
|
||||
if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
|
||||
{
|
||||
/* Get clock divider control register address */
|
||||
u32div = (uint32_t)&CLK->CLKDIV + ((MODULE_CLKDIV(u32ModuleIdx)) * 4);
|
||||
/* Apply new divider */
|
||||
M32(u32div) = (M32(u32div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set SysTick clock source
|
||||
* @param[in] u32ClkSrc is module clock source. Including:
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HXT
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HXT_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HCLK_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HIRC_DIV2
|
||||
* @return None
|
||||
* @details This function set SysTick clock source.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
|
||||
{
|
||||
CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLK_S_Msk) | u32ClkSrc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable clock source
|
||||
* @param[in] u32ClkMask is clock source mask. Including :
|
||||
* - \ref CLK_PWRCON_XTL12M_EN_Msk
|
||||
* - \ref CLK_PWRCON_OSC22M_EN_Msk
|
||||
* - \ref CLK_PWRCON_OSC10K_EN_Msk
|
||||
* @return None
|
||||
* @details This function enable clock source.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_EnableXtalRC(uint32_t u32ClkMask)
|
||||
{
|
||||
CLK->PWRCON |= u32ClkMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable clock source
|
||||
* @param[in] u32ClkMask is clock source mask. Including :
|
||||
* - \ref CLK_PWRCON_XTL12M_EN_Msk
|
||||
* - \ref CLK_PWRCON_OSC22M_EN_Msk
|
||||
* - \ref CLK_PWRCON_OSC10K_EN_Msk
|
||||
* @return None
|
||||
* @details This function disable clock source.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_DisableXtalRC(uint32_t u32ClkMask)
|
||||
{
|
||||
CLK->PWRCON &= ~u32ClkMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable module clock
|
||||
* @param[in] u32ModuleIdx is module index. Including :
|
||||
* - \ref PDMA_MODULE
|
||||
* - \ref ISP_MODULE
|
||||
* - \ref WDT_MODULE
|
||||
* - \ref TMR0_MODULE
|
||||
* - \ref TMR1_MODULE
|
||||
* - \ref TMR2_MODULE
|
||||
* - \ref TMR3_MODULE
|
||||
* - \ref FDIV_MODULE
|
||||
* - \ref I2C0_MODULE
|
||||
* - \ref I2C1_MODULE
|
||||
* - \ref SPI0_MODULE
|
||||
* - \ref SPI1_MODULE
|
||||
* - \ref SPI2_MODULE
|
||||
* - \ref UART0_MODULE
|
||||
* - \ref UART1_MODULE
|
||||
* - \ref PWM01_MODULE
|
||||
* - \ref PWM23_MODULE
|
||||
* - \ref USBD_MODULE
|
||||
* - \ref ADC_MODULE
|
||||
* - \ref I2S_MODULE
|
||||
* - \ref PS2_MODULE
|
||||
* @return None
|
||||
* @details This function enable module clock.
|
||||
*/
|
||||
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
|
||||
{
|
||||
*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + ((MODULE_APBCLK(u32ModuleIdx)) * 4)) |= 1 << MODULE_IP_EN_Pos(u32ModuleIdx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable module clock
|
||||
* @param[in] u32ModuleIdx is module index. Including :
|
||||
* - \ref PDMA_MODULE
|
||||
* - \ref ISP_MODULE
|
||||
* - \ref WDT_MODULE
|
||||
* - \ref TMR0_MODULE
|
||||
* - \ref TMR1_MODULE
|
||||
* - \ref TMR2_MODULE
|
||||
* - \ref TMR3_MODULE
|
||||
* - \ref FDIV_MODULE
|
||||
* - \ref I2C0_MODULE
|
||||
* - \ref I2C1_MODULE
|
||||
* - \ref SPI0_MODULE
|
||||
* - \ref SPI1_MODULE
|
||||
* - \ref SPI2_MODULE
|
||||
* - \ref UART0_MODULE
|
||||
* - \ref UART1_MODULE
|
||||
* - \ref PWM01_MODULE
|
||||
* - \ref PWM23_MODULE
|
||||
* - \ref USBD_MODULE
|
||||
* - \ref ADC_MODULE
|
||||
* - \ref I2S_MODULE
|
||||
* - \ref PS2_MODULE
|
||||
* @return None
|
||||
* @details This function disable module clock.
|
||||
*/
|
||||
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
|
||||
{
|
||||
*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + ((MODULE_APBCLK(u32ModuleIdx)) * 4)) &= ~(1 << MODULE_IP_EN_Pos(u32ModuleIdx));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set PLL frequency
|
||||
* @param[in] u32PllClkSrc is PLL clock source. Including :
|
||||
* - \ref CLK_PLLCON_PLL_SRC_HXT
|
||||
* - \ref CLK_PLLCON_PLL_SRC_HIRC
|
||||
* @param[in] u32PllFreq is PLL frequency
|
||||
* @return PLL frequency
|
||||
* @details This function is used to configure PLLCON register to set specified PLL frequency.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
|
||||
{
|
||||
uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC;
|
||||
uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR;
|
||||
|
||||
/* Disable PLL first to avoid unstable when setting PLL. */
|
||||
CLK->PLLCON = CLK_PLLCON_PD_Msk;
|
||||
|
||||
/* PLL source clock is from HXT */
|
||||
if(u32PllClkSrc == CLK_PLLCON_PLL_SRC_HXT)
|
||||
{
|
||||
/* Enable HXT clock */
|
||||
CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;
|
||||
|
||||
/* Wait for HXT clock ready */
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);
|
||||
|
||||
/* Select PLL source clock from HXT */
|
||||
u32CLK_SRC = CLK_PLLCON_PLL_SRC_HXT;
|
||||
u32PllSrcClk = __HXT;
|
||||
|
||||
/* u32NR start from 2 */
|
||||
u32NR = 2;
|
||||
}
|
||||
|
||||
/* PLL source clock is from HIRC */
|
||||
else
|
||||
{
|
||||
/* Enable HIRC clock */
|
||||
CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;
|
||||
|
||||
/* Wait for HIRC clock ready */
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
|
||||
|
||||
/* Select PLL source clock from HIRC */
|
||||
u32CLK_SRC = CLK_PLLCON_PLL_SRC_HIRC;
|
||||
u32PllSrcClk = __HIRC;
|
||||
|
||||
/* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */
|
||||
u32NR = 4;
|
||||
}
|
||||
|
||||
/* Select "NO" according to request frequency */
|
||||
if((u32PllFreq <= FREQ_200MHZ) && (u32PllFreq > FREQ_100MHZ))
|
||||
{
|
||||
u32NO = 0;
|
||||
}
|
||||
else if((u32PllFreq <= FREQ_100MHZ) && (u32PllFreq > FREQ_50MHZ))
|
||||
{
|
||||
u32NO = 1;
|
||||
u32PllFreq = u32PllFreq << 1;
|
||||
}
|
||||
else if((u32PllFreq <= FREQ_50MHZ) && (u32PllFreq >= FREQ_25MHZ))
|
||||
{
|
||||
u32NO = 3;
|
||||
u32PllFreq = u32PllFreq << 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wrong frequency request. Just return default setting. */
|
||||
goto lexit;
|
||||
}
|
||||
|
||||
/* Find best solution */
|
||||
u32Min = (uint32_t) - 1;
|
||||
u32MinNR = 0;
|
||||
u32MinNF = 0;
|
||||
for(; u32NR <= 33; u32NR++)
|
||||
{
|
||||
u32Tmp = u32PllSrcClk / u32NR;
|
||||
if((u32Tmp > 1600000) && (u32Tmp < 16000000))
|
||||
{
|
||||
for(u32NF = 2; u32NF <= 513; u32NF++)
|
||||
{
|
||||
u32Tmp2 = u32Tmp * u32NF;
|
||||
if((u32Tmp2 >= 100000000) && (u32Tmp2 <= 200000000))
|
||||
{
|
||||
u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
|
||||
if(u32Tmp3 < u32Min)
|
||||
{
|
||||
u32Min = u32Tmp3;
|
||||
u32MinNR = u32NR;
|
||||
u32MinNF = u32NF;
|
||||
|
||||
/* Break when get good results */
|
||||
if(u32Min == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable and apply new PLL setting. */
|
||||
CLK->PLLCON = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
|
||||
|
||||
/* Waiting for PLL clock stable */
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk);
|
||||
|
||||
/* Return actual PLL output clock frequency */
|
||||
return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
|
||||
|
||||
lexit:
|
||||
|
||||
/* Apply default PLL setting and return */
|
||||
if(u32PllClkSrc == CLK_PLLCON_PLL_SRC_HXT)
|
||||
CLK->PLLCON = 0xC22E; /* 48MHz */
|
||||
else
|
||||
CLK->PLLCON = 0x8D66F; /* 48.06498462MHz */
|
||||
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk);
|
||||
return CLK_GetPLLClockFreq();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable PLL
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function disable PLL.
|
||||
*/
|
||||
void CLK_DisablePLL(void)
|
||||
{
|
||||
CLK->PLLCON |= CLK_PLLCON_PD_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function check selected clock source status
|
||||
* @param[in] u32ClkMask is selected clock source. Including :
|
||||
* - \ref CLK_CLKSTATUS_XTL12M_STB_Msk
|
||||
* - \ref CLK_CLKSTATUS_OSC22M_STB_Msk
|
||||
* - \ref CLK_CLKSTATUS_OSC10K_STB_Msk
|
||||
* - \ref CLK_CLKSTATUS_PLL_STB_Msk
|
||||
*
|
||||
* @retval 0 clock is not stable
|
||||
* @retval 1 clock is stable
|
||||
*
|
||||
* @details To wait for clock ready by specified CLKSTATUS bit or timeout (~300ms)
|
||||
*/
|
||||
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
|
||||
{
|
||||
int32_t i32TimeOutCnt = 2160000;
|
||||
|
||||
while((CLK->CLKSTATUS & u32ClkMask) != u32ClkMask)
|
||||
{
|
||||
if(i32TimeOutCnt-- <= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable System Tick counter
|
||||
* @param[in] u32ClkSrc is System Tick clock source. Including:
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HXT
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HXT_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HCLK_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HIRC_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLK_S_HCLK
|
||||
* @param[in] u32Count is System Tick reload value. It could be 0~0xFFFFFF.
|
||||
* @return None
|
||||
* @details This function set System Tick clock source, reload value, enable System Tick counter and interrupt.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
|
||||
{
|
||||
/* Set System Tick counter disabled */
|
||||
SysTick->CTRL = 0;
|
||||
|
||||
/* Set System Tick clock source */
|
||||
if( u32ClkSrc == CLK_CLKSEL0_STCLK_S_HCLK )
|
||||
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
|
||||
else
|
||||
CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLK_S_Msk) | u32ClkSrc;
|
||||
|
||||
/* Set System Tick reload value */
|
||||
SysTick->LOAD = u32Count;
|
||||
|
||||
/* Clear System Tick current value and counter flag */
|
||||
SysTick->VAL = 0;
|
||||
|
||||
/* Set System Tick interrupt enabled and counter enabled */
|
||||
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable System Tick counter
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function disable System Tick counter.
|
||||
*/
|
||||
void CLK_DisableSysTick(void)
|
||||
{
|
||||
/* Set System Tick counter disabled */
|
||||
SysTick->CTRL = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group CLK_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
113
NUC123/StdDriver/src/crc.c
Normal file
113
NUC123/StdDriver/src/crc.c
Normal file
@ -0,0 +1,113 @@
|
||||
/**************************************************************************//**
|
||||
* @file crc.c
|
||||
* @version V3.00
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series CRC driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CRC_Driver CRC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup CRC_EXPORTED_FUNCTIONS CRC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief CRC Open
|
||||
*
|
||||
* @param[in] u32Mode CRC operation polynomial mode. Valid values are:
|
||||
* - \ref CRC_CCITT
|
||||
* - \ref CRC_8
|
||||
* - \ref CRC_16
|
||||
* - \ref CRC_32
|
||||
* @param[in] u32Attribute CRC operation data attribute. Valid values are combined with:
|
||||
* - \ref CRC_CHECKSUM_COM
|
||||
* - \ref CRC_CHECKSUM_RVS
|
||||
* - \ref CRC_WDATA_COM
|
||||
* - \ref CRC_WDATA_RVS
|
||||
* @param[in] u32Seed Seed value.
|
||||
* @param[in] u32DataLen CPU Write Data Length. Valid values are:
|
||||
* - \ref CRC_CPU_WDATA_8
|
||||
* - \ref CRC_CPU_WDATA_16
|
||||
* - \ref CRC_CPU_WDATA_32
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function enable the CRC channel by specify CRC polynomial mode, data attribute, initial seed and write data length.
|
||||
*/
|
||||
void CRC_Open(uint32_t u32Mode, uint32_t u32Attribute, uint32_t u32Seed, uint32_t u32DataLen)
|
||||
{
|
||||
/* Enable CRC channel clock */
|
||||
PDMA_GCR->GCRCSR |= PDMA_GCRCSR_CRC_CLK_EN_Msk;
|
||||
|
||||
CRC->SEED = u32Seed;
|
||||
CRC->CTL = u32Mode | u32Attribute | u32DataLen | CRC_CTL_CRCCEN_Msk;
|
||||
|
||||
/* Setting RST bit will reload the initial seed value (CRC_SEED register) */
|
||||
CRC->CTL |= CRC_CTL_CRC_RST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CRC Start DMA transfer
|
||||
*
|
||||
* @param[in] u32SrcAddr Starting source address of CRC DMA transfer.
|
||||
* @param[in] u32ByteCount Calculate byte counts of CRC DMA transfer.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function start CRC DMA transfer from specify source address and byte counts.
|
||||
*/
|
||||
void CRC_StartDMATransfer(uint32_t u32SrcAddr, uint32_t u32ByteCount)
|
||||
{
|
||||
CRC->DMASAR = u32SrcAddr;
|
||||
CRC->DMABCR = u32ByteCount;
|
||||
CRC->CTL |= CRC_CTL_TRIG_EN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CRC Checksum
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return Checksum Value
|
||||
*
|
||||
* @details This macro get the CRC checksum result by current CRC polynomial mode.
|
||||
*/
|
||||
uint32_t CRC_GetChecksum(void)
|
||||
{
|
||||
switch(CRC->CTL & CRC_CTL_CRC_MODE_Msk)
|
||||
{
|
||||
case CRC_CCITT:
|
||||
case CRC_16:
|
||||
return (CRC->CHECKSUM & 0xFFFF);
|
||||
|
||||
case CRC_32:
|
||||
return (CRC->CHECKSUM);
|
||||
|
||||
case CRC_8:
|
||||
return (CRC->CHECKSUM & 0xFF);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group CRC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group CRC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
282
NUC123/StdDriver/src/fmc.c
Normal file
282
NUC123/StdDriver/src/fmc.c
Normal file
@ -0,0 +1,282 @@
|
||||
/**************************************************************************//**
|
||||
* @file fmc.c
|
||||
* @version V3.00
|
||||
* $Revision: 4 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series FMC driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
//* Includes ------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include "NUC123.h"
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup FMC_Driver FMC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup FMC_EXPORTED_FUNCTIONS FMC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set boot source from LDROM or APROM after next software reset
|
||||
*
|
||||
* @param[in] i32BootSrc
|
||||
* 1: Boot from LDROM,
|
||||
* 0: Boot from APROM
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to switch APROM boot or LDROM boot. User need to call
|
||||
* FMC_SetBootSource to select boot source first, then use CPU reset or
|
||||
* System Reset Request to reset system.
|
||||
*
|
||||
*/
|
||||
void FMC_SetBootSource(int32_t i32BootSrc)
|
||||
{
|
||||
if(i32BootSrc)
|
||||
FMC->ISPCON |= FMC_ISPCON_BS_Msk; /* Boot from LDROM */
|
||||
else
|
||||
FMC->ISPCON &= ~FMC_ISPCON_BS_Msk;/* Boot from APROM */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable ISP Functions
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will clear ISPEN bit of ISPCON to disable ISP function
|
||||
*
|
||||
*/
|
||||
void FMC_Close(void)
|
||||
{
|
||||
FMC->ISPCON &= ~FMC_ISPCON_ISPEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable APROM update function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Disable APROM update function will forbid APROM programming when boot form APROM.
|
||||
* APROM update is default to be disable.
|
||||
*
|
||||
*/
|
||||
void FMC_DisableAPUpdate(void)
|
||||
{
|
||||
FMC->ISPCON &= ~FMC_ISPCON_APUEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable User Configuration update function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Disable User Configuration update function will forbid User Configuration programming.
|
||||
* User Configuration update is default to be disable.
|
||||
*/
|
||||
void FMC_DisableConfigUpdate(void)
|
||||
{
|
||||
FMC->ISPCON &= ~FMC_ISPCON_CFGUEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable LDROM update function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
|
||||
* @details Disable LDROM update function will forbid LDROM programming.
|
||||
* LDROM update is default to be disable.
|
||||
*/
|
||||
void FMC_DisableLDUpdate(void)
|
||||
{
|
||||
FMC->ISPCON &= ~FMC_ISPCON_LDUEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable APROM update function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable APROM to be able to program when boot from APROM.
|
||||
*
|
||||
*/
|
||||
void FMC_EnableAPUpdate(void)
|
||||
{
|
||||
FMC->ISPCON |= FMC_ISPCON_APUEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable User Configuration update function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable User Configuration to be able to program.
|
||||
*
|
||||
*/
|
||||
void FMC_EnableConfigUpdate(void)
|
||||
{
|
||||
FMC->ISPCON |= FMC_ISPCON_CFGUEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable LDROM update function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable LDROM to be able to program.
|
||||
*
|
||||
*/
|
||||
void FMC_EnableLDUpdate(void)
|
||||
{
|
||||
FMC->ISPCON |= FMC_ISPCON_LDUEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the current boot source
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 0 This chip is currently booting from APROM
|
||||
* @retval 1 This chip is currently booting from LDROM
|
||||
*
|
||||
* @note This function only show the boot source.
|
||||
* User need to read ISPSTA register to know if IAP mode supported or not in relative boot.
|
||||
*/
|
||||
int32_t FMC_GetBootSource(void)
|
||||
{
|
||||
if(FMC->ISPCON & FMC_ISPCON_BS_Msk)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable FMC ISP function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details ISPEN bit of ISPCON must be set before we can use ISP commands.
|
||||
* Therefore, To use all FMC function APIs, user needs to call FMC_Open() first to enable ISP functions.
|
||||
*
|
||||
* @note ISP functions are write-protected. user also needs to unlock it by calling SYS_UnlockReg() before using all ISP functions.
|
||||
*
|
||||
*/
|
||||
void FMC_Open(void)
|
||||
{
|
||||
FMC->ISPCON |= FMC_ISPCON_ISPEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the base address of Data Flash if enabled.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return The base address of Data Flash
|
||||
*
|
||||
* @details This function is used to return the base address of Data Flash.
|
||||
*
|
||||
*/
|
||||
uint32_t FMC_ReadDataFlashBaseAddr(void)
|
||||
{
|
||||
return FMC->DFBADR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the User Configuration words.
|
||||
*
|
||||
* @param[out] u32Config The word buffer to store the User Configuration data.
|
||||
* @param[in] u32Count The word count to be read.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -1 Failed
|
||||
*
|
||||
* @details This function is used to read the settings of user configuration.
|
||||
* if u32Count = 1, Only CONFIG0 will be returned to the buffer specified by u32Config.
|
||||
* if u32Count = 2, Both CONFIG0 and CONFIG1 will be returned.
|
||||
*/
|
||||
int32_t FMC_ReadConfig(uint32_t *u32Config, uint32_t u32Count)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
for(i = 0; i < u32Count; i++)
|
||||
u32Config[i] = FMC_Read(FMC_CONFIG_BASE + i * 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write User Configuration
|
||||
*
|
||||
* @param[in] u32Config The word buffer to store the User Configuration data.
|
||||
* @param[in] u32Count The word count to program to User Configuration.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -1 Failed
|
||||
*
|
||||
* @details User must enable User Configuration update before writing it.
|
||||
* User must erase User Configuration before writing it.
|
||||
* User Configuration is also be page erase. User needs to backup necessary data
|
||||
* before erase User Configuration.
|
||||
*/
|
||||
int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
for(i = 0; i < u32Count; i++)
|
||||
{
|
||||
FMC_Write(FMC_CONFIG_BASE + i * 4, u32Config[i]);
|
||||
if(FMC_Read(FMC_CONFIG_BASE + i * 4) != u32Config[i])
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group FMC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group FMC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
||||
|
||||
|
122
NUC123/StdDriver/src/gpio.c
Normal file
122
NUC123/StdDriver/src/gpio.c
Normal file
@ -0,0 +1,122 @@
|
||||
/**************************************************************************//**
|
||||
* @file gpio.c
|
||||
* @version V3.00
|
||||
* $Revision: 8 $
|
||||
* $Date: 16/06/08 9:58a $
|
||||
* @brief NUC123 series GPIO driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup GPIO_Driver GPIO Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set GPIO operation mode
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \n
|
||||
* It could be BIT10 ~ BIT15 for PA GPIO port. \n
|
||||
* It could be BIT0 ~ BIT10 and BIT12 ~ BIT15 for PB GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT13 for PC GPIO port. \n
|
||||
* It could be BIT0 ~ BIT5 and BIT8 ~ BIT11 for PD GPIO port. \n
|
||||
* It could be BIT0 ~ BIT3 for PF GPIO port.
|
||||
* @param[in] u32Mode Operation mode. It could be :
|
||||
* - \ref GPIO_PMD_INPUT,
|
||||
* - \ref GPIO_PMD_OUTPUT,
|
||||
* - \ref GPIO_PMD_OPEN_DRAIN,
|
||||
* - \ref GPIO_PMD_QUASI
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to set specified GPIO operation mode.
|
||||
*/
|
||||
void GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < GPIO_PIN_MAX; i++)
|
||||
{
|
||||
if(u32PinMask & (1 << i))
|
||||
{
|
||||
port->PMD = (port->PMD & ~(0x3 << (i << 1))) | (u32Mode << (i << 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable GPIO interrupt
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. \n
|
||||
* It could be 10 ~ 15 for PA GPIO port. \n
|
||||
* It could be 0 ~ 10 and 12 ~ 15 for PB GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 13 for PC GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 11 for PD GPIO port. \n
|
||||
* It could be 0 ~ 3 for PF GPIO port.
|
||||
* @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be :
|
||||
* - \ref GPIO_INT_RISING
|
||||
* - \ref GPIO_INT_FALLING
|
||||
* - \ref GPIO_INT_BOTH_EDGE
|
||||
* - \ref GPIO_INT_HIGH
|
||||
* - \ref GPIO_INT_LOW
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable specified GPIO pin interrupt.
|
||||
*/
|
||||
void GPIO_EnableInt(GPIO_T *port, uint32_t u32Pin, uint32_t u32IntAttribs)
|
||||
{
|
||||
/* Configure interrupt mode of specified pin */
|
||||
port->IMD = (port->IMD & ~(1ul << u32Pin)) | (((u32IntAttribs >> 24) & 0xFFUL) << u32Pin);
|
||||
|
||||
/* Enable interrupt function of specified pin */
|
||||
port->IEN = (port->IEN & ~(0x00010001ul << u32Pin)) | ((u32IntAttribs & 0xFFFFFFUL) << u32Pin);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable GPIO interrupt
|
||||
*
|
||||
* @param[in] port GPIO port. It could be PA, PB, PC, PD or PF.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. \n
|
||||
* It could be 10 ~ 15 for PA GPIO port. \n
|
||||
* It could be 0 ~ 10 and 12 ~ 15 for PB GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 13 for PC GPIO port. \n
|
||||
* It could be 0 ~ 5 and 8 ~ 11 for PD GPIO port. \n
|
||||
* It could be 0 ~ 3 for PF GPIO port.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to disable specified GPIO pin interrupt.
|
||||
*/
|
||||
void GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin)
|
||||
{
|
||||
/* Configure interrupt mode of specified pin */
|
||||
port->IMD &= ~(1UL << u32Pin);
|
||||
|
||||
/* Disable interrupt function of specified pin */
|
||||
port->IEN &= ~((0x00010001UL) << u32Pin);
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group GPIO_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
1159
NUC123/StdDriver/src/i2c.c
Normal file
1159
NUC123/StdDriver/src/i2c.c
Normal file
File diff suppressed because it is too large
Load Diff
222
NUC123/StdDriver/src/i2s.c
Normal file
222
NUC123/StdDriver/src/i2s.c
Normal file
@ -0,0 +1,222 @@
|
||||
/**************************************************************************//**
|
||||
* @file i2s.c
|
||||
* @version V3.0
|
||||
* $Revision: 7 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series I2S driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "NUC123.h"
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_Driver I2S Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_EXPORTED_FUNCTIONS I2S Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function is used to get I2S source clock frequency.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return I2S source clock frequency (Hz).
|
||||
* @details Return the source clock frequency according to the setting of I2S_S (CLKSEL2[1:0]).
|
||||
*/
|
||||
static uint32_t I2S_GetSourceClockFreq(I2S_T *i2s)
|
||||
{
|
||||
uint32_t u32Freq, u32ClkSrcSel;
|
||||
|
||||
u32ClkSrcSel = CLK->CLKSEL2 & CLK_CLKSEL2_I2S_S_Msk;
|
||||
|
||||
switch(u32ClkSrcSel)
|
||||
{
|
||||
case CLK_CLKSEL2_I2S_S_HXT:
|
||||
u32Freq = __HXT;
|
||||
break;
|
||||
|
||||
case CLK_CLKSEL2_I2S_S_PLL:
|
||||
u32Freq = CLK_GetPLLClockFreq();
|
||||
break;
|
||||
|
||||
case CLK_CLKSEL2_I2S_S_HIRC:
|
||||
u32Freq = __HIRC;
|
||||
break;
|
||||
|
||||
case CLK_CLKSEL2_I2S_S_HCLK:
|
||||
u32Freq = SystemCoreClock;
|
||||
break;
|
||||
|
||||
default:
|
||||
u32Freq = __HIRC;
|
||||
break;
|
||||
}
|
||||
|
||||
return u32Freq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function configures some parameters of I2S interface for general purpose use.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32MasterSlave I2S operation mode. Valid values are:
|
||||
* - \ref I2S_MODE_MASTER
|
||||
* - \ref I2S_MODE_SLAVE
|
||||
* @param[in] u32SampleRate Sample rate
|
||||
* @param[in] u32WordWidth Data length. Valid values are:
|
||||
* - \ref I2S_DATABIT_8
|
||||
* - \ref I2S_DATABIT_16
|
||||
* - \ref I2S_DATABIT_24
|
||||
* - \ref I2S_DATABIT_32
|
||||
* @param[in] u32Channels Audio format. Valid values are:
|
||||
* - \ref I2S_MONO
|
||||
* - \ref I2S_STEREO
|
||||
* @param[in] u32DataFormat Data format. Valid values are:
|
||||
* - \ref I2S_FORMAT_I2S
|
||||
* - \ref I2S_FORMAT_MSB
|
||||
* - \ref I2S_FORMAT_PCM_A
|
||||
* - \ref I2S_FORMAT_PCM_B
|
||||
* @return Real sample rate.
|
||||
* @details This function will configure I2S controller according to the input parameters. Set TX and RX FIFO threshold to middle value.
|
||||
* The actual sample rate may be different from the target sample rate. The real sample rate will be returned for reference.
|
||||
* @note Both the TX and RX functions will be enabled.
|
||||
*/
|
||||
uint32_t I2S_Open(I2S_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat)
|
||||
{
|
||||
uint32_t u32Divider;
|
||||
uint32_t u32BitRate, u32SrcClk;
|
||||
|
||||
/* Reset I2S */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_I2S_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_I2S_RST_Msk;
|
||||
|
||||
/* Configure I2S controller according to input parameters. */
|
||||
i2s->CON = u32MasterSlave | u32WordWidth | u32Channels | u32DataFormat | I2S_FIFO_TX_LEVEL_WORD_4 | I2S_FIFO_RX_LEVEL_WORD_4;
|
||||
|
||||
/* Get I2S source clock frequency */
|
||||
u32SrcClk = I2S_GetSourceClockFreq(i2s);
|
||||
|
||||
/* Calculate bit clock rate */
|
||||
u32BitRate = u32SampleRate * (((u32WordWidth >> 4) & 0x3) + 1) * 16;
|
||||
u32Divider = ((u32SrcClk / u32BitRate) >> 1) - 1;
|
||||
i2s->CLKDIV = (i2s->CLKDIV & ~I2S_CLKDIV_BCLK_DIV_Msk) | (u32Divider << 8);
|
||||
|
||||
/* Calculate real sample rate */
|
||||
u32BitRate = u32SrcClk / ((u32Divider + 1) * 2);
|
||||
u32SampleRate = u32BitRate / ((((u32WordWidth >> 4) & 0x3) + 1) * 16);
|
||||
|
||||
/* Enable TX, RX and I2S controller */
|
||||
i2s->CON |= (I2S_CON_RXEN_Msk | I2S_CON_TXEN_Msk | I2S_CON_I2SEN_Msk);
|
||||
|
||||
return u32SampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2S function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details Disable I2S function.
|
||||
*/
|
||||
void I2S_Close(I2S_T *i2s)
|
||||
{
|
||||
i2s->CON &= ~I2S_CON_I2SEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32Mask The combination of all related interrupt enable bits.
|
||||
* Each bit corresponds to a interrupt bit. Valid values are:
|
||||
* - \ref I2S_IE_LZCIE_Msk
|
||||
* - \ref I2S_IE_RZCIE_Msk
|
||||
* - \ref I2S_IE_TXTHIE_Msk
|
||||
* - \ref I2S_IE_TXOVFIE_Msk
|
||||
* - \ref I2S_IE_TXUDFIE_Msk
|
||||
* - \ref I2S_IE_RXTHIE_Msk
|
||||
* - \ref I2S_IE_RXOVFIE_Msk
|
||||
* - \ref I2S_IE_RXUDFIE_Msk
|
||||
* @return None
|
||||
* @details This function enables the interrupt according to the mask parameter.
|
||||
*/
|
||||
void I2S_EnableInt(I2S_T *i2s, uint32_t u32Mask)
|
||||
{
|
||||
i2s->IE |= u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt function.
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32Mask The combination of all related interrupt enable bits.
|
||||
* Each bit corresponds to a interrupt bit. Valid values are:
|
||||
* - \ref I2S_IE_LZCIE_Msk
|
||||
* - \ref I2S_IE_RZCIE_Msk
|
||||
* - \ref I2S_IE_TXTHIE_Msk
|
||||
* - \ref I2S_IE_TXOVFIE_Msk
|
||||
* - \ref I2S_IE_TXUDFIE_Msk
|
||||
* - \ref I2S_IE_RXTHIE_Msk
|
||||
* - \ref I2S_IE_RXOVFIE_Msk
|
||||
* - \ref I2S_IE_RXUDFIE_Msk
|
||||
* @return None
|
||||
* @details This function disables the interrupt according to the mask parameter.
|
||||
*/
|
||||
void I2S_DisableInt(I2S_T *i2s, uint32_t u32Mask)
|
||||
{
|
||||
i2s->IE &= ~u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable master clock (MCLK).
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @param[in] u32BusClock The target MCLK clock.
|
||||
* @return Actual MCLK clock
|
||||
* @details Set the master clock rate according to u32BusClock parameter and enable master clock output.
|
||||
* The actual master clock rate may be different from the target master clock rate. The real master clock rate will be returned for reference.
|
||||
*/
|
||||
uint32_t I2S_EnableMCLK(I2S_T *i2s, uint32_t u32BusClock)
|
||||
{
|
||||
uint32_t u32Divider;
|
||||
uint32_t u32SrcClk, u32Reg;
|
||||
|
||||
u32SrcClk = I2S_GetSourceClockFreq(i2s);
|
||||
if(u32BusClock == u32SrcClk)
|
||||
u32Divider = 0;
|
||||
else
|
||||
u32Divider = (u32SrcClk / u32BusClock) >> 1;
|
||||
|
||||
i2s->CLKDIV = (i2s->CLKDIV & ~I2S_CLKDIV_MCLK_DIV_Msk) | u32Divider;
|
||||
|
||||
i2s->CON |= I2S_CON_MCLKEN_Msk;
|
||||
|
||||
u32Reg = i2s->CLKDIV & I2S_CLKDIV_MCLK_DIV_Msk;
|
||||
|
||||
if(u32Reg == 0)
|
||||
return u32SrcClk;
|
||||
else
|
||||
return ((u32SrcClk >> 1) / u32Reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable master clock (MCLK).
|
||||
* @param[in] i2s The pointer of the specified I2S module.
|
||||
* @return None
|
||||
* @details Disable master clock output.
|
||||
*/
|
||||
void I2S_DisableMCLK(I2S_T *i2s)
|
||||
{
|
||||
i2s->CON &= ~I2S_CON_MCLKEN_Msk;
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group I2S_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group I2S_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
292
NUC123/StdDriver/src/pdma.c
Normal file
292
NUC123/StdDriver/src/pdma.c
Normal file
@ -0,0 +1,292 @@
|
||||
/**************************************************************************//**
|
||||
* @file pdma.c
|
||||
* @version V3.00
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series PDMA driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup PDMA_Driver PDMA Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup PDMA_EXPORTED_FUNCTIONS PDMA Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief PDMA Open
|
||||
*
|
||||
* @param[in] u32Mask Channel enable bits.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function enable the PDMA channels.
|
||||
*/
|
||||
void PDMA_Open(uint32_t u32Mask)
|
||||
{
|
||||
PDMA_GCR->GCRCSR |= (u32Mask << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PDMA Close
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function disable all PDMA channels.
|
||||
*/
|
||||
void PDMA_Close(void)
|
||||
{
|
||||
PDMA_GCR->GCRCSR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PDMA Transfer Count
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32Width Data width. Valid values are
|
||||
* - \ref PDMA_WIDTH_8
|
||||
* - \ref PDMA_WIDTH_16
|
||||
* - \ref PDMA_WIDTH_32
|
||||
* @param[in] u32TransCount Transfer count
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function set the selected channel data width and transfer count.
|
||||
*/
|
||||
void PDMA_SetTransferCnt(uint32_t u32Ch, uint32_t u32Width, uint32_t u32TransCount)
|
||||
{
|
||||
PDMA_T *pdma;
|
||||
pdma = (PDMA_T *)((uint32_t) PDMA0_BASE + (0x100 * u32Ch));
|
||||
pdma->CSR = (pdma->CSR & ~PDMA_CSR_APB_TWS_Msk) | u32Width;
|
||||
switch(u32Width)
|
||||
{
|
||||
case PDMA_WIDTH_32:
|
||||
pdma->BCR = (u32TransCount << 2);
|
||||
break;
|
||||
|
||||
case PDMA_WIDTH_8:
|
||||
pdma->BCR = u32TransCount;
|
||||
break;
|
||||
|
||||
case PDMA_WIDTH_16:
|
||||
pdma->BCR = (u32TransCount << 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PDMA Transfer Address
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32SrcAddr Source address
|
||||
* @param[in] u32SrcCtrl Source control attribute. Valid values are
|
||||
* - \ref PDMA_SAR_INC
|
||||
* - \ref PDMA_SAR_FIX
|
||||
* @param[in] u32DstAddr destination address
|
||||
* @param[in] u32DstCtrl destination control attribute. Valid values are
|
||||
* - \ref PDMA_DAR_INC
|
||||
* - \ref PDMA_DAR_FIX
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function set the selected channel source/destination address and attribute.
|
||||
*/
|
||||
void PDMA_SetTransferAddr(uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl)
|
||||
{
|
||||
PDMA_T *pdma;
|
||||
pdma = (PDMA_T *)((uint32_t) PDMA0_BASE + (0x100 * u32Ch));
|
||||
|
||||
pdma->SAR = u32SrcAddr;
|
||||
pdma->DAR = u32DstAddr;
|
||||
pdma->CSR = (pdma->CSR & ~(PDMA_CSR_SAD_SEL_Msk | PDMA_CSR_DAD_SEL_Msk)) | (u32SrcCtrl | u32DstCtrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PDMA Transfer Mode
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32Peripheral The selected peripheral. Valid values are
|
||||
* - \ref PDMA_SPI0_TX
|
||||
* - \ref PDMA_SPI1_TX
|
||||
* - \ref PDMA_SPI2_TX
|
||||
* - \ref PDMA_UART0_TX
|
||||
* - \ref PDMA_UART1_TX
|
||||
* - \ref PDMA_I2S_TX
|
||||
* - \ref PDMA_SPI0_RX
|
||||
* - \ref PDMA_SPI1_RX
|
||||
* - \ref PDMA_SPI2_RX
|
||||
* - \ref PDMA_UART0_RX
|
||||
* - \ref PDMA_UART1_RX
|
||||
* - \ref PDMA_I2S_RX
|
||||
* - \ref PDMA_ADC
|
||||
* - \ref PDMA_PWM0_RX
|
||||
* - \ref PDMA_PWM1_RX
|
||||
* - \ref PDMA_PWM2_RX
|
||||
* - \ref PDMA_PWM3_RX
|
||||
* - \ref PDMA_MEM
|
||||
* @param[in] u32ScatterEn Scatter-gather mode enable
|
||||
* @param[in] u32DescAddr Scatter-gather descriptor address
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function set the selected channel transfer mode. Include peripheral setting.
|
||||
*/
|
||||
void PDMA_SetTransferMode(uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr)
|
||||
{
|
||||
uint32_t u32Index = 0;
|
||||
PDMA_T *pdma;
|
||||
pdma = (PDMA_T *)((uint32_t) PDMA0_BASE + (0x100 * u32Ch));
|
||||
|
||||
if(u32Peripheral > PDMA_PWM3_RX) /* Memory-to-Memory */
|
||||
pdma->CSR = (pdma->CSR & ~(PDMA_CSR_MODE_SEL_Msk));
|
||||
else if(u32Peripheral > PDMA_I2S_TX) /* Peripheral-to-Memory */
|
||||
pdma->CSR = (pdma->CSR & ~(PDMA_CSR_MODE_SEL_Msk) | (0x1 << PDMA_CSR_MODE_SEL_Pos));
|
||||
else /* Memory-to-Peripheral */
|
||||
pdma->CSR = (pdma->CSR & ~(PDMA_CSR_MODE_SEL_Msk) | (0x2 << PDMA_CSR_MODE_SEL_Pos));
|
||||
|
||||
switch(u32Peripheral)
|
||||
{
|
||||
case 0:
|
||||
PDMA_GCR->PDSSR0 = (PDMA_GCR->PDSSR0 & ~PDMA_PDSSR0_SPI0_TXSEL_Msk) | (u32Ch << PDMA_PDSSR0_SPI0_TXSEL_Pos);
|
||||
break;
|
||||
case 1:
|
||||
PDMA_GCR->PDSSR0 = (PDMA_GCR->PDSSR0 & ~PDMA_PDSSR0_SPI1_TXSEL_Msk) | (u32Ch << PDMA_PDSSR0_SPI1_TXSEL_Pos);
|
||||
break;
|
||||
case 2:
|
||||
PDMA_GCR->PDSSR0 = (PDMA_GCR->PDSSR0 & ~PDMA_PDSSR0_SPI2_TXSEL_Msk) | (u32Ch << PDMA_PDSSR0_SPI2_TXSEL_Pos);
|
||||
break;
|
||||
case 3:
|
||||
PDMA_GCR->PDSSR1 = (PDMA_GCR->PDSSR1 & ~PDMA_PDSSR1_UART0_TXSEL_Msk) | (u32Ch << PDMA_PDSSR1_UART0_TXSEL_Pos);
|
||||
break;
|
||||
case 4:
|
||||
PDMA_GCR->PDSSR1 = (PDMA_GCR->PDSSR1 & ~PDMA_PDSSR1_UART1_TXSEL_Msk) | (u32Ch << PDMA_PDSSR1_UART1_TXSEL_Pos);
|
||||
break;
|
||||
case 5:
|
||||
PDMA_GCR->PDSSR2 = (PDMA_GCR->PDSSR2 & ~PDMA_PDSSR2_I2S_TXSEL_Msk) | (u32Ch << PDMA_PDSSR2_I2S_TXSEL_Pos);
|
||||
break;
|
||||
case 6:
|
||||
PDMA_GCR->PDSSR0 = (PDMA_GCR->PDSSR0 & ~PDMA_PDSSR0_SPI0_RXSEL_Msk) | (u32Ch << PDMA_PDSSR0_SPI0_RXSEL_Pos);
|
||||
break;
|
||||
case 7:
|
||||
PDMA_GCR->PDSSR0 = (PDMA_GCR->PDSSR0 & ~PDMA_PDSSR0_SPI1_RXSEL_Msk) | (u32Ch << PDMA_PDSSR0_SPI1_RXSEL_Pos);
|
||||
break;
|
||||
case 8:
|
||||
PDMA_GCR->PDSSR0 = (PDMA_GCR->PDSSR0 & ~PDMA_PDSSR0_SPI2_RXSEL_Msk) | (u32Ch << PDMA_PDSSR0_SPI2_RXSEL_Pos);
|
||||
break;
|
||||
case 9:
|
||||
PDMA_GCR->PDSSR1 = (PDMA_GCR->PDSSR1 & ~PDMA_PDSSR1_UART0_RXSEL_Msk) | (u32Ch << PDMA_PDSSR1_UART0_RXSEL_Pos);
|
||||
break;
|
||||
case 10:
|
||||
PDMA_GCR->PDSSR1 = (PDMA_GCR->PDSSR1 & ~PDMA_PDSSR1_UART1_RXSEL_Msk) | (u32Ch << PDMA_PDSSR1_UART1_RXSEL_Pos);
|
||||
break;
|
||||
case 11:
|
||||
PDMA_GCR->PDSSR2 = (PDMA_GCR->PDSSR2 & ~PDMA_PDSSR2_I2S_RXSEL_Msk) | (u32Ch << PDMA_PDSSR2_I2S_RXSEL_Pos);
|
||||
break;
|
||||
case 12:
|
||||
PDMA_GCR->PDSSR1 = (PDMA_GCR->PDSSR1 & ~PDMA_PDSSR1_ADC_RXSEL_Msk) | (u32Ch << PDMA_PDSSR1_ADC_RXSEL_Pos);
|
||||
break;
|
||||
case 13:
|
||||
PDMA_GCR->PDSSR2 = (PDMA_GCR->PDSSR2 & ~PDMA_PDSSR2_PWM0_RXSEL_Msk) | (u32Ch << PDMA_PDSSR2_PWM0_RXSEL_Pos);
|
||||
break;
|
||||
case 14:
|
||||
PDMA_GCR->PDSSR2 = (PDMA_GCR->PDSSR2 & ~PDMA_PDSSR2_PWM1_RXSEL_Msk) | (u32Ch << PDMA_PDSSR2_PWM1_RXSEL_Pos);
|
||||
break;
|
||||
case 15:
|
||||
PDMA_GCR->PDSSR2 = (PDMA_GCR->PDSSR2 & ~PDMA_PDSSR2_PWM2_RXSEL_Msk) | (u32Ch << PDMA_PDSSR2_PWM2_RXSEL_Pos);
|
||||
break;
|
||||
case 16:
|
||||
PDMA_GCR->PDSSR2 = (PDMA_GCR->PDSSR2 & ~PDMA_PDSSR2_PWM3_RXSEL_Msk) | (u32Ch << PDMA_PDSSR2_PWM3_RXSEL_Pos);
|
||||
break;
|
||||
|
||||
default:/* select PDMA channel as memory to memory */
|
||||
for(u32Index = 0; u32Index < 8; u32Index++)
|
||||
{
|
||||
if((PDMA_GCR->PDSSR0 & (0xF << (u32Index * 4))) == (u32Ch << (u32Index * 4)))
|
||||
PDMA_GCR->PDSSR0 |= 0xF << (u32Index * 4);
|
||||
if((PDMA_GCR->PDSSR1 & (0xF << (u32Index * 4))) == (u32Ch << (u32Index * 4)))
|
||||
PDMA_GCR->PDSSR1 |= 0xF << (u32Index * 4);
|
||||
if((PDMA_GCR->PDSSR2 & (0xF << (u32Index * 4))) == (u32Ch << (u32Index * 4)))
|
||||
PDMA_GCR->PDSSR2 |= 0xF << (u32Index * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trigger PDMA
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function trigger the selected channel.
|
||||
*/
|
||||
void PDMA_Trigger(uint32_t u32Ch)
|
||||
{
|
||||
PDMA_T *pdma;
|
||||
pdma = (PDMA_T *)((uint32_t) PDMA0_BASE + (0x100 * u32Ch));
|
||||
|
||||
pdma->CSR |= (PDMA_CSR_TRIG_EN_Msk | PDMA_CSR_PDMACEN_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Interrupt
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32Mask The Interrupt Type
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function enable the selected channel interrupt.
|
||||
*/
|
||||
void PDMA_EnableInt(uint32_t u32Ch, uint32_t u32Mask)
|
||||
{
|
||||
PDMA_T *pdma;
|
||||
pdma = (PDMA_T *)((uint32_t) PDMA0_BASE + (0x100 * u32Ch));
|
||||
|
||||
pdma->IER |= u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Interrupt
|
||||
*
|
||||
* @param[in] u32Ch The selected channel
|
||||
* @param[in] u32Mask The Interrupt Type
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function disable the selected channel interrupt.
|
||||
*/
|
||||
void PDMA_DisableInt(uint32_t u32Ch, uint32_t u32Mask)
|
||||
{
|
||||
PDMA_T *pdma;
|
||||
pdma = (PDMA_T *)((uint32_t) PDMA0_BASE + (0x100 * u32Ch));
|
||||
|
||||
pdma->IER &= ~u32Mask;
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group PDMA_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
201
NUC123/StdDriver/src/ps2.c
Normal file
201
NUC123/StdDriver/src/ps2.c
Normal file
@ -0,0 +1,201 @@
|
||||
/**************************************************************************//**
|
||||
* @file ps2.c
|
||||
* @version V3.00
|
||||
* $Revision: 7 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series PS/2 driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "NUC123.h"
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Includes of local headers */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#include "ps2.h"
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup PS2_Driver PS2 Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup PS2_EXPORTED_FUNCTIONS PS2 Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable PS/2 Interrupt
|
||||
*
|
||||
* @param[in] u32Mask The specified interrupt of PS/2 module:
|
||||
* - PS2D_PS2CON_TXINTEN_Msk: PS/2 Tx interrupt
|
||||
* - PS2D_PS2CON_RXINTEN_Msk: PS/2 Rx interrupt
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to enable PS/2 specified Tx or Rx interrupt.
|
||||
*/
|
||||
void PS2_EnableInt(uint32_t u32Mask)
|
||||
{
|
||||
PS2->PS2CON |= u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PS/2 Interrupt.
|
||||
*
|
||||
* @param[in] u32Mask The specified interrupt of PS2 module:
|
||||
* - PS2D_PS2CON_TXINTEN_Msk: PS2 Tx interrupt
|
||||
* - PS2D_PS2CON_RXINTEN_Msk: PS2 Rx interrupt
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to disable PS/2 specified Tx or Rx interrupt.
|
||||
*/
|
||||
void PS2_DisableInt(uint32_t u32Mask)
|
||||
{
|
||||
PS2->PS2CON &= ~u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PS/2 function and Set Parameter
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable PS/2 function and set one byte per transfer.
|
||||
*/
|
||||
void PS2_Open(void)
|
||||
{
|
||||
/* Reset PS2 device */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_PS2_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_PS2_RST_Msk;
|
||||
|
||||
/* Enable PS2 module */
|
||||
PS2->PS2CON |= PS2_PS2CON_PS2EN_Msk;
|
||||
|
||||
/* Set One byte per transfer */
|
||||
PS2->PS2CON &= ~PS2_PS2CON_TXFIFO_DEPTH_Msk;
|
||||
|
||||
/* Clear Tx FIFO */
|
||||
PS2->PS2CON |= PS2_PS2CON_CLRFIFO_Msk;
|
||||
PS2->PS2CON &= (~PS2_PS2CON_CLRFIFO_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PS/2 function
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function use to disable PS/2 function.
|
||||
*/
|
||||
void PS2_Close(void)
|
||||
{
|
||||
/* Enable PS2 module */
|
||||
PS2->PS2CON &= ~PS2_PS2CON_PS2EN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function use to read PS/2 Rx data.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return Rx data
|
||||
*
|
||||
* @details To get PS/2 receive 8 bits data from PS2RXDATA register.
|
||||
*/
|
||||
uint8_t PS2_Read(void)
|
||||
{
|
||||
return (uint8_t)(PS2->PS2RXDATA & PS2_PS2RXDATA_RXDATA_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function use to transmit PS/2 data.
|
||||
*
|
||||
* @param[in] pu32Buf The buffer to send the data to PS/2 transmission FIFO.
|
||||
* @param[in] u32ByteCount The byte number of data.
|
||||
*
|
||||
* @retval 0 transmit data time-out
|
||||
* @retval 1 transmit data successful
|
||||
*
|
||||
* @details Write data to PS/2 transmit FIFO and set the depth of Tx transmit bytes, then check every data transmission success or time-out.
|
||||
*/
|
||||
int32_t PS2_Write(uint32_t *pu32Buf, uint32_t u32ByteCount)
|
||||
{
|
||||
uint32_t u32TxFIFO_Depth = 16;
|
||||
uint32_t u32delayno, txcnt, remainder;
|
||||
uint8_t i = 0;
|
||||
|
||||
txcnt = u32ByteCount / u32TxFIFO_Depth;
|
||||
|
||||
remainder = u32ByteCount % u32TxFIFO_Depth;
|
||||
if(remainder) txcnt++;
|
||||
|
||||
u32delayno = 0;
|
||||
while(!(PS2->PS2STATUS & PS2_PS2STATUS_TXEMPTY_Msk))
|
||||
{
|
||||
u32delayno++;
|
||||
if(u32delayno >= 0xF00000)
|
||||
return FALSE; // Time Out
|
||||
}
|
||||
|
||||
if(u32ByteCount >= u32TxFIFO_Depth)//Tx FIFO is 16 bytes
|
||||
PS2_SET_TX_BYTE_CNT(u32TxFIFO_Depth);
|
||||
|
||||
do
|
||||
{
|
||||
u32delayno = 0;
|
||||
while(!(PS2->PS2STATUS & PS2_PS2STATUS_TXEMPTY_Msk))
|
||||
{
|
||||
u32delayno++;
|
||||
if(u32delayno >= 0xF00000)
|
||||
return FALSE; // Time Out
|
||||
}
|
||||
|
||||
if((txcnt == 1) && (remainder != 0))
|
||||
PS2_SET_TX_BYTE_CNT(u32ByteCount);
|
||||
|
||||
PS2->PS2TXDATA0 = pu32Buf[i];
|
||||
PS2->PS2TXDATA1 = pu32Buf[i + 1];
|
||||
PS2->PS2TXDATA2 = pu32Buf[i + 2];
|
||||
PS2->PS2TXDATA3 = pu32Buf[i + 3];
|
||||
|
||||
i = i + 4;
|
||||
|
||||
}
|
||||
while(--txcnt);
|
||||
|
||||
u32delayno = 0;
|
||||
while(!(PS2->PS2STATUS & PS2_PS2STATUS_TXEMPTY_Msk))
|
||||
{
|
||||
u32delayno++;
|
||||
if(u32delayno >= 0xF00000)
|
||||
return FALSE; // Time Out
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group PS2_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group PS2_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
||||
|
||||
|
||||
|
678
NUC123/StdDriver/src/pwm.c
Normal file
678
NUC123/StdDriver/src/pwm.c
Normal file
@ -0,0 +1,678 @@
|
||||
/**************************************************************************//**
|
||||
* @file pwm.c
|
||||
* @version V3.00
|
||||
* $Revision: 9 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series PWM driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup PWM_Driver PWM Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup PWM_EXPORTED_FUNCTIONS PWM Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configure PWM capture and get the nearest unit time.
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32UnitTimeNsec The unit time of counter
|
||||
* @param[in] u32CaptureEdge The condition to latch the counter. This parameter is not used
|
||||
* @return The nearest unit time in nano second.
|
||||
* @details This function is used to configure PWM capture and get the nearest unit time.
|
||||
*/
|
||||
uint32_t PWM_ConfigCaptureChannel(PWM_T *pwm,
|
||||
uint32_t u32ChannelNum,
|
||||
uint32_t u32UnitTimeNsec,
|
||||
uint32_t u32CaptureEdge)
|
||||
{
|
||||
uint32_t u32Src;
|
||||
uint32_t u32PWMClockSrc;
|
||||
uint32_t u32PWMClkTbl[8] = {__HXT, NULL, NULL, __HIRC, NULL, NULL, NULL, __LIRC};
|
||||
uint32_t u32NearestUnitTimeNsec;
|
||||
uint8_t u8Divider = 1;
|
||||
/* this table is mapping divider value to register configuration */
|
||||
uint32_t u32PWMDividerToRegTbl[17] = {NULL, 4, 0, NULL, 1, NULL, NULL, NULL, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3};
|
||||
uint16_t u16Prescale = 2;
|
||||
uint16_t u16CNR = 0xFFFF;
|
||||
|
||||
if(u32ChannelNum < 2)/* channel 0 and channel 1 */
|
||||
u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM01_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM01_S_EXT_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk)) >> (CLK_CLKSEL1_PWM01_S_Pos);
|
||||
else /* channel 2 and channel 3 */
|
||||
u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM23_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM23_S_EXT_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM23_S_Msk)) >> (CLK_CLKSEL1_PWM23_S_Pos);
|
||||
|
||||
if(u32Src == 2)
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
u32PWMClockSrc = SystemCoreClock;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32PWMClockSrc = u32PWMClkTbl[u32Src];
|
||||
}
|
||||
|
||||
u32PWMClockSrc /= 1000;
|
||||
for(; u16Prescale <= 0x100; u16Prescale++)
|
||||
{
|
||||
u32NearestUnitTimeNsec = (1000000 * u16Prescale * u8Divider) / u32PWMClockSrc;
|
||||
if(u32NearestUnitTimeNsec < (u32UnitTimeNsec))
|
||||
{
|
||||
if((u16Prescale == 0x100) && (u8Divider == 16)) //limit to the maximum unit time(nano second)
|
||||
break;
|
||||
if(u16Prescale == 0x100)
|
||||
{
|
||||
u16Prescale = 2;
|
||||
u8Divider <<= 1; // clk divider could only be 1, 2, 4, 8, 16
|
||||
continue;
|
||||
}
|
||||
if(!((1000000 * ((u16Prescale * u8Divider) + 1)) > (u32NearestUnitTimeNsec * u32PWMClockSrc)))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Store return value here 'cos we're gonna change u8Divider & u16Prescale & u16CNR to the real value to fill into register
|
||||
u16Prescale -= 1;
|
||||
|
||||
// convert to real register value
|
||||
u8Divider = u32PWMDividerToRegTbl[u8Divider];
|
||||
|
||||
// every two channels share a prescaler
|
||||
(pwm)->PPR = ((pwm)->PPR & ~(PWM_PPR_CP01_Msk << ((u32ChannelNum >> 1) * 8))) | (u16Prescale << ((u32ChannelNum >> 1) * 8));
|
||||
(pwm)->CSR = ((pwm)->CSR & ~(PWM_CSR_CSR0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
|
||||
// set PWM to edge aligned type
|
||||
(pwm)->PCR &= ~(PWM_PCR_PWM01TYPE_Msk << (u32ChannelNum >> 1));
|
||||
(pwm)->PCR |= PWM_PCR_CH0MOD_Msk << (8 * u32ChannelNum);
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CNR0)) + u32ChannelNum * 12))) = u16CNR;
|
||||
|
||||
return (u32NearestUnitTimeNsec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure PWM generator and get the nearest frequency in edge aligned auto-reload mode
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Frequency Target generator frequency
|
||||
* @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0 ~ 100. 10 means 10%, 20 means 20%...
|
||||
* @return Nearest frequency clock in nano second
|
||||
* @details This function is used to configure PWM generator and get the nearest frequency in edge aligned auto-reload mode.
|
||||
* @note Since every two channels, (0 & 1), (2 & 3), shares a prescaler. Call this API to configure PWM frequency may affect
|
||||
* existing frequency of other channel.
|
||||
*/
|
||||
uint32_t PWM_ConfigOutputChannel(PWM_T *pwm,
|
||||
uint32_t u32ChannelNum,
|
||||
uint32_t u32Frequency,
|
||||
uint32_t u32DutyCycle)
|
||||
{
|
||||
uint32_t u32Src;
|
||||
uint32_t u32PWMClockSrc;
|
||||
uint32_t u32PWMClkTbl[8] = {__HXT, NULL, NULL, __HIRC, NULL, NULL, NULL, __LIRC};
|
||||
uint32_t i;
|
||||
uint8_t u8Divider = 1, u8Prescale = 0xFF;
|
||||
/* this table is mapping divider value to register configuration */
|
||||
uint32_t u32PWMDividerToRegTbl[17] = {NULL, 4, 0, NULL, 1, NULL, NULL, NULL, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3};
|
||||
uint16_t u16CNR = 0xFFFF;
|
||||
|
||||
if(u32ChannelNum < 2)/* channel 0 and channel 1 */
|
||||
u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM01_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM01_S_EXT_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk)) >> (CLK_CLKSEL1_PWM01_S_Pos);
|
||||
else /* channel 2 and channel 3 */
|
||||
u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM23_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM23_S_EXT_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM23_S_Msk)) >> (CLK_CLKSEL1_PWM23_S_Pos);
|
||||
|
||||
if(u32Src == 2)
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
u32PWMClockSrc = SystemCoreClock;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32PWMClockSrc = u32PWMClkTbl[u32Src];
|
||||
}
|
||||
|
||||
for(; u8Divider < 17; u8Divider <<= 1) // clk divider could only be 1, 2, 4, 8, 16
|
||||
{
|
||||
i = (u32PWMClockSrc / (u32Frequency)) / u8Divider;
|
||||
// If target value is larger than CNR * prescale, need to use a larger divider
|
||||
if(i > (0x10000 * 0x100))
|
||||
continue;
|
||||
|
||||
// CNR = 0xFFFF + 1, get a prescaler that CNR value is below 0xFFFF
|
||||
u8Prescale = (i + 0xFFFF) / 0x10000;
|
||||
|
||||
// u8Prescale must at least be 2, otherwise the output stop
|
||||
if(u8Prescale < 3)
|
||||
u8Prescale = 2;
|
||||
|
||||
i /= u8Prescale;
|
||||
|
||||
if(i <= 0x10000)
|
||||
{
|
||||
if(i == 1)
|
||||
u16CNR = 1; // Too fast, and PWM cannot generate expected frequency...
|
||||
else
|
||||
u16CNR = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Store return value here 'cos we're gonna change u8Divider & u8Prescale & u16CNR to the real value to fill into register
|
||||
i = u32PWMClockSrc / (u8Prescale * u8Divider * u16CNR);
|
||||
|
||||
u8Prescale -= 1;
|
||||
u16CNR -= 1;
|
||||
// convert to real register value
|
||||
u8Divider = u32PWMDividerToRegTbl[u8Divider];
|
||||
|
||||
// every two channels share a prescaler
|
||||
(pwm)->PPR = ((pwm)->PPR & ~(PWM_PPR_CP01_Msk << ((u32ChannelNum >> 1) * 8))) | (u8Prescale << ((u32ChannelNum >> 1) * 8));
|
||||
(pwm)->CSR = ((pwm)->CSR & ~(PWM_CSR_CSR0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
|
||||
// set PWM to edge aligned type
|
||||
(pwm)->PCR &= ~(PWM_PCR_PWM01TYPE_Msk << (u32ChannelNum >> 1));
|
||||
(pwm)->PCR |= PWM_PCR_CH0MOD_Msk << (8 * u32ChannelNum);
|
||||
|
||||
if(u32DutyCycle)
|
||||
{
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CMR0)) + u32ChannelNum * 12))) = u32DutyCycle * (u16CNR + 1) / 100 - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CMR0)) + u32ChannelNum * 12))) = 0;
|
||||
}
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CNR0)) + u32ChannelNum * 12))) = u16CNR;
|
||||
|
||||
return(i);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start PWM module
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
* @details This function is used to start PWM module.
|
||||
*/
|
||||
void PWM_Start(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t u32Mask = 0, i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++)
|
||||
{
|
||||
if(u32ChannelMask & (1 << i))
|
||||
{
|
||||
u32Mask |= (PWM_PCR_CH0EN_Msk << (i * 8));
|
||||
}
|
||||
}
|
||||
(pwm)->PCR |= u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop PWM module
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
* @details This function is used to stop PWM module.
|
||||
*/
|
||||
void PWM_Stop(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++)
|
||||
{
|
||||
if(u32ChannelMask & (1 << i))
|
||||
{
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CNR0)) + i * 12))) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop PWM generation immediately by clear channel enable bit
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
* @details This function is used to stop PWM generation immediately by clear channel enable bit.
|
||||
*/
|
||||
void PWM_ForceStop(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t u32Mask = 0, i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++)
|
||||
{
|
||||
if(u32ChannelMask & (1 << i))
|
||||
{
|
||||
u32Mask |= (PWM_PCR_CH0EN_Msk << (i * 8));
|
||||
}
|
||||
}
|
||||
(pwm)->PCR &= ~u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable selected channel to trigger ADC
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Condition This parameter is not used
|
||||
* @return None
|
||||
* @details This function is used to enable selected channel to trigger ADC.
|
||||
* @note This function is only supported when PWM operating at Center-aligned type.
|
||||
*/
|
||||
void PWM_EnableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
|
||||
{
|
||||
(pwm)->TCON |= (PWM_TCON_PWM0TEN_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable selected channel to trigger ADC
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return None
|
||||
* @details This function is used to disable selected channel to trigger ADC.
|
||||
*/
|
||||
void PWM_DisableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->TCON = ((pwm)->TCON & ~(PWM_TCON_PWM0TEN_Msk << u32ChannelNum));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear selected channel trigger ADC flag
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Condition This parameter is not used
|
||||
* @return None
|
||||
* @details This function is used to clear selected channel trigger ADC flag.
|
||||
*/
|
||||
void PWM_ClearADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
|
||||
{
|
||||
(pwm)->TSTATUS = (PWM_TSTATUS_PWM0TF_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get selected channel trigger ADC flag
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @retval 0 The specified channel trigger ADC to start of conversion flag is not set
|
||||
* @retval 1 The specified channel trigger ADC to start of conversion flag is set
|
||||
* @details This function is used to get PWM trigger ADC to start of conversion flag for specified channel.
|
||||
*/
|
||||
uint32_t PWM_GetADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
return (((pwm)->TSTATUS & (PWM_TSTATUS_PWM0TF_Msk << (u32ChannelNum))) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable capture of selected channel(s)
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
* @details This function is used to enable capture of selected channel(s).
|
||||
*/
|
||||
void PWM_EnableCapture(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++)
|
||||
{
|
||||
if(u32ChannelMask & (1 << i))
|
||||
{
|
||||
if(i < 2)
|
||||
{
|
||||
(pwm)->CCR0 |= PWM_CCR0_CAPCH0EN_Msk << (i * 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
(pwm)->CCR2 |= PWM_CCR2_CAPCH2EN_Msk << ((i - 2) * 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
(pwm)->CAPENR |= u32ChannelMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable capture of selected channel(s)
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
* @details This function is used to disable capture of selected channel(s).
|
||||
*/
|
||||
void PWM_DisableCapture(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++)
|
||||
{
|
||||
if(u32ChannelMask & (1 << i))
|
||||
{
|
||||
if(i < 2)
|
||||
{
|
||||
(pwm)->CCR0 &= ~(PWM_CCR0_CAPCH0EN_Msk << (i * 16));
|
||||
}
|
||||
else
|
||||
{
|
||||
(pwm)->CCR2 &= ~(PWM_CCR2_CAPCH2EN_Msk << ((i - 2) * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
(pwm)->CAPENR &= ~u32ChannelMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables PWM output generation of selected channel(s)
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Set bit 0 to 1 enables channel 0 output, set bit 1 to 1 enables channel 1 output...
|
||||
* @return None
|
||||
* @details This function is used to enables PWM output generation of selected channel(s).
|
||||
*/
|
||||
void PWM_EnableOutput(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
(pwm)->POE |= u32ChannelMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables PWM output generation of selected channel(s)
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
|
||||
* Set bit 0 to 1 disables channel 0 output, set bit 1 to 1 disables channel 1 output...
|
||||
* @return None
|
||||
* @details This function is used to disables PWM output generation of selected channel(s).
|
||||
*/
|
||||
void PWM_DisableOutput(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
(pwm)->POE &= ~u32ChannelMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables PDMA transfer of selected channel(s) for PWM capture
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Set bit 0 to 1 enables channel 0 output, set bit 1 to 1 enables channel 1 output...
|
||||
* @param[in] u32RisingFirst The capture order is rising, falling first. Every two channels share the same setting.
|
||||
* @return None
|
||||
* @details This function is used to enables PDMA transfer of selected channel(s) for PWM capture
|
||||
*/
|
||||
void PWM_EnablePDMA(PWM_T *pwm, uint32_t u32ChannelMask, uint32_t u32RisingFirst)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++)
|
||||
{
|
||||
if(u32ChannelMask & (1 << i))
|
||||
{
|
||||
(pwm)->CAPPDMACTL = ((pwm)->CAPPDMACTL & ~(PWM_CAPPDMACTL_CAP0RFORDER_Msk << (i * 8))) | \
|
||||
(((u32RisingFirst << PWM_CAPPDMACTL_CAP0RFORDER_Pos) | \
|
||||
PWM_CAPPDMACTL_CAP0PDMAMOD_Msk | PWM_CAPPDMACTL_CAP0PDMAEN_Msk) << (i * 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables PDMA transfer of selected channel(s) for PWM capture
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Set bit 0 to 1 enables channel 0 output, set bit 1 to 1 enables channel 1 output...
|
||||
* @return None
|
||||
* @details This function is used to enables PDMA transfer of selected channel(s) for PWM capture
|
||||
*/
|
||||
void PWM_DisablePDMA(PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++)
|
||||
{
|
||||
if(u32ChannelMask & (1 << i))
|
||||
{
|
||||
(pwm)->CAPPDMACTL &= ~(PWM_CAPPDMACTL_CAP0PDMAEN_Msk << (i * 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Dead zone of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Duration Dead Zone length in PWM clock count, valid values are between 0~0xFF, but 0 means there is no
|
||||
* dead zone.
|
||||
* @return None
|
||||
* @details This function is used to enable Dead zone of selected channel.
|
||||
*/
|
||||
void PWM_EnableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration)
|
||||
{
|
||||
// every two channels shares the same setting
|
||||
u32ChannelNum >>= 1;
|
||||
// set duration
|
||||
(pwm)->PPR = ((pwm)->PPR & ~(PWM_PPR_DZI01_Msk << (8 * u32ChannelNum))) | (u32Duration << (PWM_PPR_DZI01_Pos + 8 * u32ChannelNum));
|
||||
// enable dead zone
|
||||
(pwm)->PCR |= (PWM_PCR_DZEN01_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Dead zone of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return None
|
||||
* @details This function is used to disable Dead zone of selected channel.
|
||||
*/
|
||||
void PWM_DisableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
// every two channels shares the same setting
|
||||
u32ChannelNum >>= 1;
|
||||
// enable dead zone
|
||||
(pwm)->PCR &= ~(PWM_PCR_DZEN01_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable capture interrupt of selected channel.
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Edge Rising or falling edge to latch counter.
|
||||
* - \ref PWM_CAPTURE_INT_RISING_LATCH
|
||||
* - \ref PWM_CAPTURE_INT_FALLING_LATCH
|
||||
* @return None
|
||||
* @details This function is used to enable capture interrupt of selected channel.
|
||||
*/
|
||||
void PWM_EnableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
|
||||
{
|
||||
if(u32ChannelNum < 2)
|
||||
(pwm)->CCR0 |= u32Edge << (u32ChannelNum * 16);
|
||||
else
|
||||
(pwm)->CCR2 |= u32Edge << ((u32ChannelNum - 2) * 16);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable capture interrupt of selected channel.
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Edge Rising or falling edge to latch counter.
|
||||
* - \ref PWM_CAPTURE_INT_RISING_LATCH
|
||||
* - \ref PWM_CAPTURE_INT_FALLING_LATCH
|
||||
* @return None
|
||||
* @details This function is used to disable capture interrupt of selected channel.
|
||||
*/
|
||||
void PWM_DisableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
|
||||
{
|
||||
if(u32ChannelNum < 2)
|
||||
(pwm)->CCR0 &= ~(u32Edge << (u32ChannelNum * 16));
|
||||
else
|
||||
(pwm)->CCR2 &= ~(u32Edge << ((u32ChannelNum - 2) * 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear capture interrupt of selected channel.
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32Edge Rising or falling edge to latch counter.
|
||||
* - \ref PWM_CAPTURE_INT_RISING_LATCH
|
||||
* - \ref PWM_CAPTURE_INT_FALLING_LATCH
|
||||
* @return None
|
||||
* @details This function is used to clear capture interrupt of selected channel.
|
||||
*/
|
||||
void PWM_ClearCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
|
||||
{
|
||||
//clear capture interrupt flag, and clear CRLR or CFLR latched indicator
|
||||
if(u32ChannelNum < 2)
|
||||
(pwm)->CCR0 = ((pwm)->CCR0 & PWM_CCR_MASK) | (PWM_CCR0_CAPIF0_Msk << (u32ChannelNum * 16)) | (u32Edge << (u32ChannelNum * 16 + 5));
|
||||
else
|
||||
(pwm)->CCR2 = ((pwm)->CCR2 & PWM_CCR_MASK) | (PWM_CCR2_CAPIF2_Msk << ((u32ChannelNum - 2) * 16)) | (u32Edge << ((u32ChannelNum - 2) * 16 + 5));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get capture interrupt of selected channel.
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @retval 0 No capture interrupt
|
||||
* @retval 1 Rising edge latch interrupt
|
||||
* @retval 2 Falling edge latch interrupt
|
||||
* @retval 3 Rising and falling latch interrupt
|
||||
* @details This function is used to get capture interrupt of selected channel.
|
||||
*/
|
||||
uint32_t PWM_GetCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
if(u32ChannelNum < 2)
|
||||
{
|
||||
return (((pwm)->CCR0 & ((PWM_CCR0_CRLRI0_Msk | PWM_CCR0_CFLRI0_Msk) << (u32ChannelNum * 16))) >> (PWM_CCR0_CRLRI0_Pos + u32ChannelNum * 16));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (((pwm)->CCR2 & ((PWM_CCR2_CRLRI2_Msk | PWM_CCR2_CFLRI2_Msk) << ((u32ChannelNum - 2) * 16))) >> (PWM_CCR2_CRLRI2_Pos + (u32ChannelNum - 2) * 16));
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Enable duty interrupt of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32IntDutyType This parameter is not used
|
||||
* @return None
|
||||
* @details This function is used to enable duty interrupt of selected channel.
|
||||
*/
|
||||
void PWM_EnableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType)
|
||||
{
|
||||
(pwm)->PIER |= (PWM_PIER_PWMDIE0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable duty interrupt of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* - PWMA : PWM Group A
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return None
|
||||
* @details This function is used to disable duty interrupt of selected channel.
|
||||
*/
|
||||
void PWM_DisableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->PIER &= ~(PWM_PIER_PWMDIE0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear duty interrupt flag of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return None
|
||||
* @details This function is used to clear duty interrupt flag of selected channel.
|
||||
*/
|
||||
void PWM_ClearDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->PIIR = PWM_PIIR_PWMDIF0_Msk << u32ChannelNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get duty interrupt flag of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @retval 0 Duty interrupt did not occur
|
||||
* @retval 1 Duty interrupt occurred
|
||||
* @details This function is used to get duty interrupt flag of selected channel.
|
||||
*/
|
||||
uint32_t PWM_GetDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
return (((pwm)->PIIR & (PWM_PIIR_PWMDIF0_Msk << u32ChannelNum)) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable period interrupt of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @param[in] u32IntPeriodType Period interrupt type, could be either
|
||||
* - \ref PWM_PERIOD_INT_UNDERFLOW
|
||||
* - \ref PWM_PERIOD_INT_MATCH_CNR
|
||||
* @return None
|
||||
* @details This function is used to enable period interrupt of selected channel.
|
||||
* Every two channels, (0 & 1), (2 & 3), shares the period interrupt type setting.
|
||||
*/
|
||||
void PWM_EnablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType)
|
||||
{
|
||||
(pwm)->PIER = ((pwm)->PIER & ~(PWM_PIER_INT01TYPE_Msk << (u32ChannelNum >> 1))) | \
|
||||
(PWM_PIER_PWMIE0_Msk << u32ChannelNum) | (u32IntPeriodType << (u32ChannelNum >> 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable period interrupt of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return None
|
||||
* @details This function is used to disable period interrupt of selected channel.
|
||||
*/
|
||||
void PWM_DisablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->PIER &= ~(PWM_PIER_PWMIE0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear period interrupt of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @return None
|
||||
* @details This function is used to clear period interrupt of selected channel.
|
||||
*/
|
||||
void PWM_ClearPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->PIIR = (PWM_PIIR_PWMIF0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get period interrupt of selected channel
|
||||
* @param[in] pwm The pointer of the specified PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
|
||||
* @retval 0 Period interrupt did not occur
|
||||
* @retval 1 Period interrupt occurred
|
||||
* @details This function is used to get period interrupt of selected channel.
|
||||
*/
|
||||
uint32_t PWM_GetPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
return (((pwm)->PIIR & (PWM_PIIR_PWMIF0_Msk << (u32ChannelNum))) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group PWM_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group PWM_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
761
NUC123/StdDriver/src/retarget.c
Normal file
761
NUC123/StdDriver/src/retarget.c
Normal file
@ -0,0 +1,761 @@
|
||||
/**************************************************************************//**
|
||||
* @file retarget.c
|
||||
* @version V3.00
|
||||
* $Revision: 13 $
|
||||
* $Date: 16/06/13 7:50p $
|
||||
* @brief NUC123 Series Debug Port and Semihost Setting Source File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "NUC123.h"
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
#if (__ARMCC_VERSION < 400000)
|
||||
#else
|
||||
/* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
|
||||
#pragma import _printf_widthprec
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Global variables */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#if !(defined(__ICCARM__) && (__VER__ >= 6010000)) || (defined(__ICCARM__) && (__VER__ >= 8000000))
|
||||
struct __FILE
|
||||
{
|
||||
int handle; /* Add whatever you need here */
|
||||
};
|
||||
#endif
|
||||
FILE __stdout;
|
||||
FILE __stdin;
|
||||
|
||||
enum { r0, r1, r2, r3, r12, lr, pc, psr};
|
||||
|
||||
/**
|
||||
* @brief Helper function to dump register while hard fault occurred
|
||||
* @param[in] stack pointer points to the dumped registers in SRAM
|
||||
* @return None
|
||||
* @details This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr
|
||||
*/
|
||||
static void stackDump(uint32_t stack[])
|
||||
{
|
||||
printf("r0 = 0x%x\n", stack[r0]);
|
||||
printf("r1 = 0x%x\n", stack[r1]);
|
||||
printf("r2 = 0x%x\n", stack[r2]);
|
||||
printf("r3 = 0x%x\n", stack[r3]);
|
||||
printf("r12 = 0x%x\n", stack[r12]);
|
||||
printf("lr = 0x%x\n", stack[lr]);
|
||||
printf("pc = 0x%x\n", stack[pc]);
|
||||
printf("psr = 0x%x\n", stack[psr]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hard fault handler
|
||||
* @param[in] stack pointer points to the dumped registers in SRAM
|
||||
* @return None
|
||||
* @details Replace while(1) at the end of this function with chip reset if WDT is not enabled for end product
|
||||
*/
|
||||
void Hard_Fault_Handler(uint32_t stack[])
|
||||
{
|
||||
printf("In Hard Fault Handler\n");
|
||||
|
||||
stackDump(stack);
|
||||
|
||||
// Replace while(1) with chip reset if WDT is not enabled for end product
|
||||
while(1);
|
||||
//SYS->IPRSTC1 = SYS_IPRSTC1_CHIP_RST_Msk;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Routine to write a char */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(DEBUG_ENABLE_SEMIHOST)
|
||||
/* The static buffer is used to speed up the semihost */
|
||||
static char g_buf[16];
|
||||
static char g_buf_len = 0;
|
||||
|
||||
/* Make sure won't goes here only because --gnu is defined , so
|
||||
add !__CC_ARM and !__ICCARM__ checking */
|
||||
# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
|
||||
|
||||
# elif defined(__ICCARM__)
|
||||
|
||||
|
||||
void SH_End(void)
|
||||
{
|
||||
asm("MOVS R0,#1 \n" //; Set return value to 1
|
||||
"BX lr \n" //; Return
|
||||
);
|
||||
}
|
||||
|
||||
void SH_ICE(void)
|
||||
{
|
||||
asm("CMP R2,#0 \n"
|
||||
"BEQ SH_End \n"
|
||||
"STR R0,[R2] \n" //; Save the return value to *pn32Out_R0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief The function to process semihosted command
|
||||
* @param[in] n32In_R0 : semihost register 0
|
||||
* @param[in] n32In_R1 : semihost register 1
|
||||
* @param[out] pn32Out_R0: semihost register 0
|
||||
* @retval 0: No ICE debug
|
||||
* @retval 1: ICE debug
|
||||
*
|
||||
*/
|
||||
int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
|
||||
{
|
||||
asm("BKPT 0xAB \n" //; This instruction will cause ICE trap or system HardFault
|
||||
"B SH_ICE \n"
|
||||
"SH_HardFault: \n" //; Captured by HardFault
|
||||
"MOVS R0,#0 \n" //; Set return value to 0
|
||||
"BX lr \n" //; Return
|
||||
);
|
||||
|
||||
return 1; //; Return 1 when it is trap by ICE
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LR value and branch to Hard_Fault_Handler function
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function is use to get LR value and branch to Hard_Fault_Handler function.
|
||||
*/
|
||||
void Get_LR_and_Branch(void)
|
||||
{
|
||||
asm("MOV R1, LR \n" //; LR current value
|
||||
"B Hard_Fault_Handler \n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get MSP value and branch to Get_LR_and_Branch function
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function is use to get stack pointer value and branch to Get_LR_and_Branch function.
|
||||
*/
|
||||
void Stack_Use_MSP(void)
|
||||
{
|
||||
asm("MRS R0, MSP \n" //; read MSP
|
||||
"B Get_LR_and_Branch \n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get stack pointer value and branch to Get_LR_and_Branch function
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function is use to get stack pointer value and branch to Get_LR_and_Branch function.
|
||||
*/
|
||||
void HardFault_Handler_Ret(void)
|
||||
{
|
||||
asm("MOVS r0, #4 \n"
|
||||
"MOV r1, LR \n"
|
||||
"TST r0, r1 \n" //; check LR bit 2
|
||||
"BEQ Stack_Use_MSP \n" //; stack use MSP
|
||||
"MRS R0, PSP \n" //; stack use PSP, read PSP
|
||||
"B Get_LR_and_Branch \n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is implemented to support semihost
|
||||
* @param None
|
||||
* @returns None
|
||||
* @details This function is implement to support semihost message print.
|
||||
*
|
||||
*/
|
||||
void SP_Read_Ready(void)
|
||||
{
|
||||
asm("LDR R1, [R0, #24] \n" //; Get previous PC
|
||||
"LDRH R3, [R1] \n" //; Get instruction
|
||||
"LDR R2, [pc, #8] \n" //; The special BKPT instruction
|
||||
"CMP R3, R2 \n" //; Test if the instruction at previous PC is BKPT
|
||||
"BNE HardFault_Handler_Ret \n" //; Not BKPT
|
||||
"ADDS R1, #4 \n" //; Skip BKPT and next line
|
||||
"STR R1, [R0, #24] \n" //; Save previous PC
|
||||
"BX lr \n" //; Return
|
||||
"DCD 0xBEAB \n" //; BKPT instruction code
|
||||
"B HardFault_Handler_Ret \n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get stack pointer value and branch to Get_LR_and_Branch function
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function is use to get stack pointer value and branch to Get_LR_and_Branch function.
|
||||
*/
|
||||
void SP_is_PSP(void)
|
||||
{
|
||||
asm(
|
||||
"MRS R0, PSP \n" //; stack use PSP, read PSP
|
||||
"B Get_LR_and_Branch \n"
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to support semihost
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details This function is implement to support semihost message print.
|
||||
*
|
||||
*/
|
||||
void HardFault_Handler (void)
|
||||
{
|
||||
asm("MOV R0, lr \n"
|
||||
"LSLS R0, #29 \n" //; Check bit 2
|
||||
"BMI SP_is_PSP \n" //; previous stack is PSP
|
||||
"MRS R0, MSP \n" //; previous stack is MSP, read MSP
|
||||
"B SP_Read_Ready \n"
|
||||
);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
# else
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to support semihost
|
||||
* @param None
|
||||
* @returns None
|
||||
* @details This function is implement to support semihost message print.
|
||||
*
|
||||
*/
|
||||
__asm int32_t HardFault_Handler(void)
|
||||
{
|
||||
MOV R0, LR
|
||||
LSLS R0, #29 //; Check bit 2
|
||||
BMI SP_is_PSP //; previous stack is PSP
|
||||
MRS R0, MSP //; previous stack is MSP, read MSP
|
||||
B SP_Read_Ready
|
||||
SP_is_PSP
|
||||
MRS R0, PSP //; Read PSP
|
||||
|
||||
SP_Read_Ready
|
||||
LDR R1, [R0, #24] //; Get previous PC
|
||||
LDRH R3, [R1] //; Get instruction
|
||||
LDR R2, =0xBEAB //; The special BKPT instruction
|
||||
CMP R3, R2 //; Test if the instruction at previous PC is BKPT
|
||||
BNE HardFault_Handler_Ret //; Not BKPT
|
||||
|
||||
ADDS R1, #4 //; Skip BKPT and next line
|
||||
STR R1, [R0, #24] //; Save previous PC
|
||||
|
||||
BX LR //; Return
|
||||
HardFault_Handler_Ret
|
||||
|
||||
/* TODO: Implement your own hard fault handler here. */
|
||||
MOVS r0, #4
|
||||
MOV r1, LR
|
||||
TST r0, r1 //; check LR bit 2
|
||||
BEQ Stack_Use_MSP //; stack use MSP
|
||||
MRS R0, PSP ;stack use PSP //; stack use PSP, read PSP
|
||||
B Get_LR_and_Branch
|
||||
Stack_Use_MSP
|
||||
MRS R0, MSP ; stack use MSP //; read MSP
|
||||
Get_LR_and_Branch
|
||||
MOV R1, LR ; LR current value //; LR current value
|
||||
LDR R2,=__cpp(Hard_Fault_Handler) //; branch to Hard_Fault_Handler
|
||||
BX R2
|
||||
|
||||
B .
|
||||
|
||||
ALIGN
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief The function to process semihosted command
|
||||
* @param[in] n32In_R0 : semihost register 0
|
||||
* @param[in] n32In_R1 : semihost register 1
|
||||
* @param[out] pn32Out_R0: semihost register 0
|
||||
* @retval 0: No ICE debug
|
||||
* @retval 1: ICE debug
|
||||
*
|
||||
*/
|
||||
__asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
|
||||
{
|
||||
BKPT 0xAB //; Wait ICE or HardFault
|
||||
//; ICE will step over BKPT directly
|
||||
//; HardFault will step BKPT and the next line
|
||||
B SH_ICE
|
||||
|
||||
SH_HardFault //; Captured by HardFault
|
||||
MOVS R0, #0 //; Set return value to 0
|
||||
BX lr //; Return
|
||||
|
||||
SH_ICE //; Captured by ICE
|
||||
//; Save return value
|
||||
CMP R2, #0
|
||||
BEQ SH_End
|
||||
STR R0, [R2] //; Save the return value to *pn32Out_R0
|
||||
|
||||
SH_End
|
||||
MOVS R0, #1 //; Set return value to 1
|
||||
BX lr //; Return
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Make sure won't goes here only because --gnu is defined , so
|
||||
add !__CC_ARM and !__ICCARM__ checking */
|
||||
# if defined ( __GNUC__ ) && !(__CC_ARM) && !(__ICCARM__)
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr.
|
||||
*
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
asm("MOVS r0, #4 \n"
|
||||
"MOV r1, LR \n"
|
||||
"TST r0, r1 \n" /*; check LR bit 2 */
|
||||
"BEQ 1f \n" /*; stack use MSP */
|
||||
"MRS R0, PSP \n" /*; stack use PSP, read PSP */
|
||||
"MOV R1, LR \n" /*; LR current value */
|
||||
"B Hard_Fault_Handler \n"
|
||||
"1: \n"
|
||||
"MRS R0, MSP \n" /*; LR current value */
|
||||
"B Hard_Fault_Handler \n"
|
||||
::[Hard_Fault_Handler] "r" (Hard_Fault_Handler) // input
|
||||
);
|
||||
while(1);
|
||||
}
|
||||
|
||||
# elif defined(__ICCARM__)
|
||||
|
||||
|
||||
void Get_LR_and_Branch(void)
|
||||
{
|
||||
asm("MOV R1, LR \n" //; LR current value
|
||||
"B Hard_Fault_Handler \n"
|
||||
);
|
||||
}
|
||||
|
||||
void Stack_Use_MSP(void)
|
||||
{
|
||||
asm("MRS R0, MSP \n" //; read MSP
|
||||
"B Get_LR_and_Branch \n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr.
|
||||
*
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
asm("MOVS r0, #4 \n"
|
||||
"MOV r1, LR \n"
|
||||
"TST r0, r1 \n" //; check LR bit 2
|
||||
"BEQ Stack_Use_MSP \n" //; stack use MSP
|
||||
"MRS R0, PSP \n" //; stack use PSP, read PSP
|
||||
"B Get_LR_and_Branch \n"
|
||||
);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function extracts the location of stack frame and passes it to Hard_Fault_Handler function as a pointer
|
||||
*
|
||||
*/
|
||||
__asm int32_t HardFault_Handler(void)
|
||||
{
|
||||
MOVS r0, #4
|
||||
MOV r1, LR
|
||||
TST r0, r1 //; check LR bit 2
|
||||
BEQ Stack_Use_MSP //; stack use MSP
|
||||
MRS R0, PSP //; stack use PSP, read PSP
|
||||
B Get_LR_and_Branch
|
||||
Stack_Use_MSP
|
||||
MRS R0, MSP //; read MSP
|
||||
Get_LR_and_Branch
|
||||
MOV R1, LR //; LR current value
|
||||
LDR R2,=__cpp(Hard_Fault_Handler) //; branch to Hard_Fault_Handler
|
||||
BX R2
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Routine to send a char
|
||||
*
|
||||
* @param[in] ch Character to send to debug port.
|
||||
*
|
||||
* @returns Send value from UART debug port
|
||||
*
|
||||
* @details Send a target char to UART debug port .
|
||||
*/
|
||||
|
||||
#ifndef NONBLOCK_PRINTF
|
||||
|
||||
void SendChar_ToUART(int ch)
|
||||
{
|
||||
|
||||
while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_Msk);
|
||||
if(ch == '\n')
|
||||
{
|
||||
DEBUG_PORT->DATA = '\r';
|
||||
while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_Msk);
|
||||
}
|
||||
|
||||
DEBUG_PORT->DATA = ch;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Non-block implement of send char */
|
||||
#define BUF_SIZE 2048
|
||||
void SendChar_ToUART(int ch)
|
||||
{
|
||||
static uint8_t u8Buf[BUF_SIZE] = {0};
|
||||
static int32_t i32Head = 0;
|
||||
static int32_t i32Tail = 0;
|
||||
int32_t i32Tmp;
|
||||
|
||||
/* Only flush the data in buffer to UART when ch == 0 */
|
||||
if(ch)
|
||||
{
|
||||
// Push char
|
||||
if(ch == '\n')
|
||||
{
|
||||
i32Tmp = i32Head + 1;
|
||||
if(i32Tmp >= BUF_SIZE) i32Tmp = 0;
|
||||
if(i32Tmp != i32Tail)
|
||||
{
|
||||
u8Buf[i32Head] = '\r';
|
||||
i32Head = i32Tmp;
|
||||
}
|
||||
}
|
||||
|
||||
i32Tmp = i32Head + 1;
|
||||
if(i32Tmp >= BUF_SIZE) i32Tmp = 0;
|
||||
if(i32Tmp != i32Tail)
|
||||
{
|
||||
u8Buf[i32Head] = ch;
|
||||
i32Head = i32Tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i32Tail == i32Head)
|
||||
return;
|
||||
}
|
||||
|
||||
// pop char
|
||||
do
|
||||
{
|
||||
i32Tmp = i32Tail + 1;
|
||||
if(i32Tmp > BUF_SIZE) i32Tmp = 0;
|
||||
|
||||
if((DEBUG_PORT->FSR & UART_FSR_TX_FULL_Msk) == 0)
|
||||
{
|
||||
DEBUG_PORT->THR = u8Buf[i32Tail];
|
||||
i32Tail = i32Tmp;
|
||||
}
|
||||
else
|
||||
break; // FIFO full
|
||||
}
|
||||
while(i32Tail != i32Head);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Routine to send a char
|
||||
*
|
||||
* @param[in] ch Character to send to debug port.
|
||||
*
|
||||
* @returns Send value from UART debug port or semihost
|
||||
*
|
||||
* @details Send a target char to UART debug port or semihost.
|
||||
*/
|
||||
void SendChar(int ch)
|
||||
{
|
||||
#if defined(DEBUG_ENABLE_SEMIHOST)
|
||||
g_buf[g_buf_len++] = ch;
|
||||
g_buf[g_buf_len] = '\0';
|
||||
if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
|
||||
{
|
||||
/* Send the char */
|
||||
if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
|
||||
{
|
||||
g_buf_len = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_buf_len = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
SendChar_ToUART(ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Routine to get a char
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns Get value from UART debug port or semihost
|
||||
*
|
||||
* @details Wait UART debug port or semihost to input a char.
|
||||
*/
|
||||
char GetChar(void)
|
||||
{
|
||||
#ifdef DEBUG_ENABLE_SEMIHOST
|
||||
# if defined ( __CC_ARM )
|
||||
int nRet;
|
||||
while(SH_DoCommand(0x101, 0, &nRet) != 0)
|
||||
{
|
||||
if(nRet != 0)
|
||||
{
|
||||
SH_DoCommand(0x07, 0, &nRet);
|
||||
return (char)nRet;
|
||||
}
|
||||
}
|
||||
# else
|
||||
int nRet;
|
||||
while(SH_DoCommand(0x7, 0, &nRet) != 0)
|
||||
{
|
||||
if(nRet != 0)
|
||||
return (char)nRet;
|
||||
}
|
||||
# endif
|
||||
return (0);
|
||||
#else
|
||||
|
||||
while(1)
|
||||
{
|
||||
if((DEBUG_PORT->FSR & UART_FSR_RX_EMPTY_Msk) == 0)
|
||||
{
|
||||
return (DEBUG_PORT->DATA);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check any char input from UART
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 1: No any char input
|
||||
* @retval 0: Have some char input
|
||||
*
|
||||
* @details Check UART RSR RX EMPTY or not to determine if any char input from UART
|
||||
*/
|
||||
|
||||
int kbhit(void)
|
||||
{
|
||||
return !((DEBUG_PORT->FSR & UART_FSR_RX_EMPTY_Msk) == 0);
|
||||
}
|
||||
/**
|
||||
* @brief Check if debug message finished
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @retval 1: Message is finished
|
||||
* @retval 0: Message is transmitting.
|
||||
*
|
||||
* @details Check if message finished (FIFO empty of debug port)
|
||||
*/
|
||||
|
||||
int IsDebugFifoEmpty(void)
|
||||
{
|
||||
return ((DEBUG_PORT->FSR & UART_FSR_TE_FLAG_Msk) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief C library retargetting
|
||||
*
|
||||
* @param[in] ch Character to send to debug port.
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details Check if message finished (FIFO empty of debug port)
|
||||
*/
|
||||
|
||||
void _ttywrch(int ch)
|
||||
{
|
||||
SendChar(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write character to stream
|
||||
*
|
||||
* @param[in] ch Character to be written. The character is passed as its int promotion.
|
||||
* @param[in] stream Pointer to a FILE object that identifies the stream where the character is to be written.
|
||||
*
|
||||
* @returns If there are no errors, the same character that has been written is returned.
|
||||
* If an error occurs, EOF is returned and the error indicator is set (see ferror).
|
||||
*
|
||||
* @details Writes a character to the stream and advances the position indicator.\n
|
||||
* The character is written at the current position of the stream as indicated \n
|
||||
* by the internal position indicator, which is then advanced one character.
|
||||
*
|
||||
* @note The above descriptions are copied from http://www.cplusplus.com/reference/clibrary/cstdio/fputc/.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
int fputc(int ch, FILE *stream)
|
||||
{
|
||||
SendChar(ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
#if defined ( __GNUC__ )
|
||||
|
||||
#if !defined (OS_USE_SEMIHOSTING)
|
||||
int _write (int fd, char *ptr, int len)
|
||||
{
|
||||
int i = len;
|
||||
|
||||
while(i--)
|
||||
{
|
||||
while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_Msk);
|
||||
|
||||
if(*ptr == '\n')
|
||||
{
|
||||
DEBUG_PORT->DATA = '\r';
|
||||
while(DEBUG_PORT->FSR & UART_FSR_TX_FULL_Msk);
|
||||
}
|
||||
|
||||
DEBUG_PORT->DATA = *ptr++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int _read (int fd, char *ptr, int len)
|
||||
{
|
||||
|
||||
while((DEBUG_PORT->FSR & UART_FSR_RX_EMPTY_Msk) != 0);
|
||||
*ptr = DEBUG_PORT->DATA;
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief Get character from UART debug port or semihosting input
|
||||
*
|
||||
* @param[in] stream Pointer to a FILE object that identifies the stream on which the operation is to be performed.
|
||||
*
|
||||
* @returns The character read from UART debug port or semihosting
|
||||
*
|
||||
* @details For get message from debug port or semihosting.
|
||||
*
|
||||
*/
|
||||
|
||||
int fgetc(FILE *stream)
|
||||
{
|
||||
return (GetChar());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check error indicator
|
||||
*
|
||||
* @param[in] stream Pointer to a FILE object that identifies the stream.
|
||||
*
|
||||
* @returns If the error indicator associated with the stream was set, the function returns a nonzero value.
|
||||
* Otherwise, it returns a zero value.
|
||||
*
|
||||
* @details Checks if the error indicator associated with stream is set, returning a value different
|
||||
* from zero if it is. This indicator is generally set by a previous operation on the stream that failed.
|
||||
*
|
||||
* @note The above descriptions are copied from http://www.cplusplus.com/reference/clibrary/cstdio/ferror/.
|
||||
*
|
||||
*/
|
||||
|
||||
int ferror(FILE *stream)
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLE_SEMIHOST
|
||||
# ifdef __ICCARM__
|
||||
void __exit(int return_code)
|
||||
{
|
||||
|
||||
/* Check if link with ICE */
|
||||
if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
|
||||
{
|
||||
/* Make sure all message is print out */
|
||||
while(IsDebugFifoEmpty() == 0);
|
||||
}
|
||||
label:
|
||||
goto label; /* endless loop */
|
||||
}
|
||||
# else
|
||||
void _sys_exit(int return_code)
|
||||
{
|
||||
|
||||
/* Check if link with ICE */
|
||||
if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
|
||||
{
|
||||
/* Make sure all message is print out */
|
||||
while(IsDebugFifoEmpty() == 0);
|
||||
}
|
||||
label:
|
||||
goto label; /* endless loop */
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
603
NUC123/StdDriver/src/spi.c
Normal file
603
NUC123/StdDriver/src/spi.c
Normal file
@ -0,0 +1,603 @@
|
||||
/**************************************************************************//**
|
||||
* @file spi.c
|
||||
* @version V3.00
|
||||
* $Revision: 8 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series SPI driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_Driver SPI Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup SPI_EXPORTED_FUNCTIONS SPI Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function make SPI module be ready to transfer.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32MasterSlave Decides the SPI module is operating in master mode or in Slave mode. (SPI_SLAVE, SPI_MASTER)
|
||||
* @param[in] u32SPIMode Decides the transfer timing. (SPI_MODE_0, SPI_MODE_1, SPI_MODE_2, SPI_MODE_3)
|
||||
* @param[in] u32DataWidth Decides the data width of a SPI transaction.
|
||||
* @param[in] u32BusClock The expected frequency of SPI bus clock in Hz.
|
||||
* @return Actual frequency of SPI peripheral clock.
|
||||
* @details By default, the SPI transfer sequence is MSB first and the automatic slave selection function is disabled.
|
||||
* In Slave mode, the u32BusClock parameter is useless and the SPI clock divider setting will be 0.
|
||||
* The actual clock rate may be different from the target SPI clock rate.
|
||||
* For example, if the SPI source clock rate is 12 MHz and the target SPI bus clock rate is 7 MHz, the
|
||||
* actual SPI clock rate will be 6MHz.
|
||||
* @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value.
|
||||
* @note If u32BusClock >= system clock frequency, SPI peripheral clock source will be set to HCLK and DIVIDER will be set to 0.
|
||||
* @note In Slave mode, the SPI peripheral clock rate will be set to equal the system clock rate, and slave selection signal is low level active.
|
||||
*/
|
||||
uint32_t SPI_Open(SPI_T *spi,
|
||||
uint32_t u32MasterSlave,
|
||||
uint32_t u32SPIMode,
|
||||
uint32_t u32DataWidth,
|
||||
uint32_t u32BusClock)
|
||||
{
|
||||
uint32_t u32ClkSrc = 0, u32Div, u32HCLKFreq;
|
||||
|
||||
if(u32DataWidth == 32)
|
||||
u32DataWidth = 0;
|
||||
|
||||
/* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */
|
||||
spi->CNTRL = u32MasterSlave | (u32DataWidth << SPI_CNTRL_TX_BIT_LEN_Pos) | (u32SPIMode);
|
||||
|
||||
/* Set BCn = 1: f_spi = f_spi_clk_src / (DIVIDER + 1) */
|
||||
spi->CNTRL2 |= SPI_CNTRL2_BCn_Msk;
|
||||
/* Get system clock frequency */
|
||||
u32HCLKFreq = CLK_GetHCLKFreq();
|
||||
|
||||
if(u32MasterSlave == SPI_MASTER)
|
||||
{
|
||||
/* Default setting: slave select signal is active low; disable automatic slave select function. */
|
||||
spi->SSR = SPI_SS_ACTIVE_LOW;
|
||||
|
||||
/* Check clock source of SPI */
|
||||
if(spi == SPI0)
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI0_S_Msk) == CLK_CLKSEL1_SPI0_S_HCLK)
|
||||
u32ClkSrc = u32HCLKFreq;
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
else if(spi == SPI1)
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI1_S_Msk) == CLK_CLKSEL1_SPI1_S_HCLK)
|
||||
u32ClkSrc = u32HCLKFreq;
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
else
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI2_S_Msk) == CLK_CLKSEL1_SPI2_S_HCLK)
|
||||
u32ClkSrc = u32HCLKFreq;
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
|
||||
if(u32BusClock >= u32HCLKFreq)
|
||||
{
|
||||
/* Select HCLK as the clock source of SPI */
|
||||
if(spi == SPI0)
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI0_S_Msk)) | CLK_CLKSEL1_SPI0_S_HCLK;
|
||||
else if(spi == SPI1)
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI1_S_Msk)) | CLK_CLKSEL1_SPI1_S_HCLK;
|
||||
else
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI2_S_Msk)) | CLK_CLKSEL1_SPI2_S_HCLK;
|
||||
|
||||
/* Set DIVIDER = 0 */
|
||||
spi->DIVIDER = 0;
|
||||
/* Return slave peripheral clock rate */
|
||||
return u32HCLKFreq;
|
||||
}
|
||||
else if(u32BusClock >= u32ClkSrc)
|
||||
{
|
||||
/* Set DIVIDER = 0 */
|
||||
spi->DIVIDER = 0;
|
||||
/* Return master peripheral clock rate */
|
||||
return u32ClkSrc;
|
||||
}
|
||||
else if(u32BusClock == 0)
|
||||
{
|
||||
/* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */
|
||||
spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk);
|
||||
/* Set DIVIDER to the maximum value 0xFF */
|
||||
spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (0xFF << SPI_DIVIDER_DIVIDER_Pos);
|
||||
/* Return master peripheral clock rate */
|
||||
return (u32ClkSrc / ((0xFF + 1) * 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */
|
||||
if(u32Div > 0xFF)
|
||||
{
|
||||
/* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */
|
||||
spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk);
|
||||
u32Div = (((u32ClkSrc * 10) / (u32BusClock * 2) + 5) / 10) - 1; /* Round to the nearest integer */
|
||||
if(u32Div > 0xFF)
|
||||
u32Div = 0xFF;
|
||||
spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos);
|
||||
/* Return master peripheral clock rate */
|
||||
return (u32ClkSrc / ((u32Div + 1) * 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos);
|
||||
/* Return master peripheral clock rate */
|
||||
return (u32ClkSrc / (u32Div + 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else /* For Slave mode, force the SPI peripheral clock rate to equal the system clock rate. */
|
||||
{
|
||||
/* Default setting: slave selection signal is low level active. */
|
||||
spi->SSR = SPI_SSR_SS_LTRIG_Msk;
|
||||
|
||||
/* Select HCLK as the clock source of SPI */
|
||||
if(spi == SPI0)
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI0_S_Msk)) | CLK_CLKSEL1_SPI0_S_HCLK;
|
||||
else if(spi == SPI1)
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI1_S_Msk)) | CLK_CLKSEL1_SPI1_S_HCLK;
|
||||
else
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI2_S_Msk)) | CLK_CLKSEL1_SPI2_S_HCLK;
|
||||
|
||||
/* Set DIVIDER = 0 */
|
||||
spi->DIVIDER = 0;
|
||||
/* Return slave peripheral clock rate */
|
||||
return u32HCLKFreq;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable SPI controller.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None
|
||||
* @details This function will reset SPI controller.
|
||||
*/
|
||||
void SPI_Close(SPI_T *spi)
|
||||
{
|
||||
if(spi == SPI0)
|
||||
{
|
||||
/* Reset SPI */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_SPI0_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_SPI0_RST_Msk;
|
||||
}
|
||||
else if(spi == SPI1)
|
||||
{
|
||||
/* Reset SPI */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_SPI1_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_SPI1_RST_Msk;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset SPI */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_SPI2_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_SPI2_RST_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear RX FIFO buffer.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None
|
||||
* @details This function will clear SPI RX FIFO buffer.
|
||||
*/
|
||||
void SPI_ClearRxFIFO(SPI_T *spi)
|
||||
{
|
||||
spi->FIFO_CTL |= SPI_FIFO_CTL_RX_CLR_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear TX FIFO buffer.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None
|
||||
* @details This function will clear SPI TX FIFO buffer.
|
||||
*/
|
||||
void SPI_ClearTxFIFO(SPI_T *spi)
|
||||
{
|
||||
spi->FIFO_CTL |= SPI_FIFO_CTL_TX_CLR_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the automatic slave selection function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None
|
||||
* @details This function will disable the automatic slave selection function and set slave selection signal to inactive state.
|
||||
*/
|
||||
void SPI_DisableAutoSS(SPI_T *spi)
|
||||
{
|
||||
spi->SSR &= ~(SPI_SSR_AUTOSS_Msk | SPI_SSR_SSR_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the automatic slave selection function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32SSPinMask Specifies slave selection pins. (SPI_SS0, SPI_SS1)
|
||||
* @param[in] u32ActiveLevel Specifies the active level of slave selection signal. (SPI_SS_ACTIVE_HIGH, SPI_SS_ACTIVE_LOW)
|
||||
* @return None
|
||||
* @details This function will enable the automatic slave selection function. Only available in Master mode.
|
||||
* The slave selection pin and the active level will be set in this function.
|
||||
*/
|
||||
void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel)
|
||||
{
|
||||
spi->SSR = (spi->SSR & (~(SPI_SSR_AUTOSS_Msk | SPI_SSR_SS_LVL_Msk | SPI_SSR_SSR_Msk))) | (u32SSPinMask | u32ActiveLevel | SPI_SSR_AUTOSS_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the SPI bus clock.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32BusClock The expected frequency of SPI bus clock in Hz.
|
||||
* @return Actual frequency of SPI bus clock.
|
||||
* @details This function is only available in Master mode. The actual clock rate may be different from the target SPI bus clock rate.
|
||||
* For example, if the SPI source clock rate is 12MHz and the target SPI bus clock rate is 7MHz, the actual SPI bus clock
|
||||
* rate will be 6MHz.
|
||||
* @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value.
|
||||
* @note If u32BusClock >= system clock frequency, SPI peripheral clock source will be set to HCLK and DIVIDER will be set to 0.
|
||||
*/
|
||||
uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock)
|
||||
{
|
||||
uint32_t u32ClkSrc, u32HCLKFreq;
|
||||
uint32_t u32Div;
|
||||
|
||||
/* Set BCn = 1: f_spi = f_spi_clk_src / (DIVIDER + 1) */
|
||||
spi->CNTRL2 |= SPI_CNTRL2_BCn_Msk;
|
||||
/* Get system clock frequency */
|
||||
u32HCLKFreq = CLK_GetHCLKFreq();
|
||||
|
||||
/* Check clock source of SPI */
|
||||
if(spi == SPI0)
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI0_S_Msk) == CLK_CLKSEL1_SPI0_S_HCLK)
|
||||
u32ClkSrc = u32HCLKFreq;
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
else if(spi == SPI1)
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI1_S_Msk) == CLK_CLKSEL1_SPI1_S_HCLK)
|
||||
u32ClkSrc = u32HCLKFreq;
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
else
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI2_S_Msk) == CLK_CLKSEL1_SPI2_S_HCLK)
|
||||
u32ClkSrc = u32HCLKFreq;
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
|
||||
if(u32BusClock >= u32HCLKFreq)
|
||||
{
|
||||
/* Select HCLK as the clock source of SPI */
|
||||
if(spi == SPI0)
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI0_S_Msk)) | CLK_CLKSEL1_SPI0_S_HCLK;
|
||||
else if(spi == SPI1)
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI1_S_Msk)) | CLK_CLKSEL1_SPI1_S_HCLK;
|
||||
else
|
||||
CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI2_S_Msk)) | CLK_CLKSEL1_SPI2_S_HCLK;
|
||||
|
||||
/* Set DIVIDER = 0 */
|
||||
spi->DIVIDER = 0;
|
||||
/* Return slave peripheral clock rate */
|
||||
return u32HCLKFreq;
|
||||
}
|
||||
else if(u32BusClock >= u32ClkSrc)
|
||||
{
|
||||
/* Set DIVIDER = 0 */
|
||||
spi->DIVIDER = 0;
|
||||
/* Return master peripheral clock rate */
|
||||
return u32ClkSrc;
|
||||
}
|
||||
else if(u32BusClock == 0)
|
||||
{
|
||||
/* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */
|
||||
spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk);
|
||||
/* Set DIVIDER to the maximum value 0xFF */
|
||||
spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (0xFF << SPI_DIVIDER_DIVIDER_Pos);
|
||||
/* Return master peripheral clock rate */
|
||||
return (u32ClkSrc / ((0xFF + 1) * 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */
|
||||
if(u32Div > 0xFF)
|
||||
{
|
||||
/* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */
|
||||
spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk);
|
||||
u32Div = (((u32ClkSrc * 10) / (u32BusClock * 2) + 5) / 10) - 1; /* Round to the nearest integer */
|
||||
if(u32Div > 0xFF)
|
||||
u32Div = 0xFF;
|
||||
spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos);
|
||||
/* Return master peripheral clock rate */
|
||||
return (u32ClkSrc / ((u32Div + 1) * 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos);
|
||||
/* Return master peripheral clock rate */
|
||||
return (u32ClkSrc / (u32Div + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable FIFO mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32TxThreshold Decides the TX FIFO threshold.
|
||||
* @param[in] u32RxThreshold Decides the RX FIFO threshold.
|
||||
* @return None
|
||||
* @details Enable FIFO mode with user-specified TX FIFO threshold and RX FIFO threshold configurations.
|
||||
*/
|
||||
void SPI_EnableFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
|
||||
{
|
||||
spi->FIFO_CTL = (spi->FIFO_CTL & ~(SPI_FIFO_CTL_TX_THRESHOLD_Msk | SPI_FIFO_CTL_RX_THRESHOLD_Msk) |
|
||||
(u32TxThreshold << SPI_FIFO_CTL_TX_THRESHOLD_Pos) |
|
||||
(u32RxThreshold << SPI_FIFO_CTL_RX_THRESHOLD_Pos));
|
||||
|
||||
spi->CNTRL |= SPI_CNTRL_FIFO_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable FIFO mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return None
|
||||
* @details Clear FIFO bit of SPI_CNTRL register to disable FIFO mode.
|
||||
*/
|
||||
void SPI_DisableFIFO(SPI_T *spi)
|
||||
{
|
||||
spi->CNTRL &= ~SPI_CNTRL_FIFO_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the actual frequency of SPI bus clock. Only available in Master mode.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @return Actual SPI bus clock frequency.
|
||||
* @details This function will calculate the actual SPI bus clock rate according to the settings of SPIn_S, BCn and DIVIDER. Only available in Master mode.
|
||||
*/
|
||||
uint32_t SPI_GetBusClock(SPI_T *spi)
|
||||
{
|
||||
uint32_t u32Div;
|
||||
uint32_t u32ClkSrc;
|
||||
|
||||
/* Get DIVIDER setting */
|
||||
u32Div = (spi->DIVIDER & SPI_DIVIDER_DIVIDER_Msk) >> SPI_DIVIDER_DIVIDER_Pos;
|
||||
|
||||
/* Check clock source of SPI */
|
||||
if(spi == SPI0)
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI0_S_Msk) == CLK_CLKSEL1_SPI0_S_HCLK)
|
||||
u32ClkSrc = CLK_GetHCLKFreq();
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
else if(spi == SPI1)
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI1_S_Msk) == CLK_CLKSEL1_SPI1_S_HCLK)
|
||||
u32ClkSrc = CLK_GetHCLKFreq();
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
else
|
||||
{
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI2_S_Msk) == CLK_CLKSEL1_SPI2_S_HCLK)
|
||||
u32ClkSrc = CLK_GetHCLKFreq();
|
||||
else
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
}
|
||||
|
||||
if(spi->CNTRL2 & SPI_CNTRL2_BCn_Msk) /* BCn = 1: f_spi = f_spi_clk_src / (DIVIDER + 1) */
|
||||
{
|
||||
/* Return SPI bus clock rate */
|
||||
return (u32ClkSrc / (u32Div + 1));
|
||||
}
|
||||
else /* BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */
|
||||
{
|
||||
/* Return SPI bus clock rate */
|
||||
return (u32ClkSrc / ((u32Div + 1) * 2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32Mask The combination of all related interrupt enable bits.
|
||||
* Each bit corresponds to a interrupt bit.
|
||||
* This parameter decides which interrupts will be enabled.
|
||||
* (SPI_UNIT_INT_MASK, SPI_SSTA_INT_MASK, SPI_FIFO_TX_INT_MASK,
|
||||
* SPI_FIFO_RX_INT_MASK, SPI_FIFO_RXOV_INT_MASK, SPI_FIFO_TIMEOUT_INT_MASK)
|
||||
* @return None
|
||||
* @details Enable SPI related interrupts specified by u32Mask parameter.
|
||||
*/
|
||||
void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask)
|
||||
{
|
||||
/* Enable unit transfer interrupt flag */
|
||||
if((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK)
|
||||
spi->CNTRL |= SPI_CNTRL_IE_Msk;
|
||||
|
||||
/* Enable slave 3-wire mode start interrupt flag */
|
||||
if((u32Mask & SPI_SSTA_INT_MASK) == SPI_SSTA_INT_MASK)
|
||||
spi->CNTRL2 |= SPI_CNTRL2_SSTA_INTEN_Msk;
|
||||
|
||||
/* Enable TX threshold interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_TX_INT_MASK) == SPI_FIFO_TX_INT_MASK)
|
||||
spi->FIFO_CTL |= SPI_FIFO_CTL_TX_INTEN_Msk;
|
||||
|
||||
/* Enable RX threshold interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_RX_INT_MASK) == SPI_FIFO_RX_INT_MASK)
|
||||
spi->FIFO_CTL |= SPI_FIFO_CTL_RX_INTEN_Msk;
|
||||
|
||||
/* Enable RX overrun interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_RXOV_INT_MASK) == SPI_FIFO_RXOV_INT_MASK)
|
||||
spi->FIFO_CTL |= SPI_FIFO_CTL_RXOV_INTEN_Msk;
|
||||
|
||||
/* Enable RX time-out interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_TIMEOUT_INT_MASK) == SPI_FIFO_TIMEOUT_INT_MASK)
|
||||
spi->FIFO_CTL |= SPI_FIFO_CTL_TIMEOUT_INTEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt function.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32Mask The combination of all related interrupt enable bits.
|
||||
* Each bit corresponds to a interrupt bit.
|
||||
* This parameter decides which interrupts will be disabled.
|
||||
* (SPI_UNIT_INT_MASK, SPI_SSTA_INT_MASK, SPI_FIFO_TX_INT_MASK,
|
||||
* SPI_FIFO_RX_INT_MASK, SPI_FIFO_RXOV_INT_MASK, SPI_FIFO_TIMEOUT_INT_MASK)
|
||||
* @return None
|
||||
* @details Disable SPI related interrupts specified by u32Mask parameter.
|
||||
*/
|
||||
void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask)
|
||||
{
|
||||
/* Disable unit transfer interrupt flag */
|
||||
if((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK)
|
||||
spi->CNTRL &= ~SPI_CNTRL_IE_Msk;
|
||||
|
||||
/* Disable slave 3-wire mode start interrupt flag */
|
||||
if((u32Mask & SPI_SSTA_INT_MASK) == SPI_SSTA_INT_MASK)
|
||||
spi->CNTRL2 &= ~SPI_CNTRL2_SSTA_INTEN_Msk;
|
||||
|
||||
/* Disable TX threshold interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_TX_INT_MASK) == SPI_FIFO_TX_INT_MASK)
|
||||
spi->FIFO_CTL &= ~SPI_FIFO_CTL_TX_INTEN_Msk;
|
||||
|
||||
/* Disable RX threshold interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_RX_INT_MASK) == SPI_FIFO_RX_INT_MASK)
|
||||
spi->FIFO_CTL &= ~SPI_FIFO_CTL_RX_INTEN_Msk;
|
||||
|
||||
/* Disable RX overrun interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_RXOV_INT_MASK) == SPI_FIFO_RXOV_INT_MASK)
|
||||
spi->FIFO_CTL &= ~SPI_FIFO_CTL_RXOV_INTEN_Msk;
|
||||
|
||||
/* Disable RX time-out interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_TIMEOUT_INT_MASK) == SPI_FIFO_TIMEOUT_INT_MASK)
|
||||
spi->FIFO_CTL &= ~SPI_FIFO_CTL_TIMEOUT_INTEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get interrupt flag.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32Mask The combination of all related interrupt sources.
|
||||
* Each bit corresponds to a interrupt source.
|
||||
* This parameter decides which interrupt flags will be read.
|
||||
* (SPI_UNIT_INT_MASK, SPI_SSTA_INT_MASK, SPI_FIFO_TX_INT_MASK,
|
||||
* SPI_FIFO_RX_INT_MASK, SPI_FIFO_RXOV_INT_MASK, SPI_FIFO_TIMEOUT_INT_MASK)
|
||||
* @return Interrupt flags of selected sources.
|
||||
* @details Get SPI related interrupt flags specified by u32Mask parameter.
|
||||
*/
|
||||
uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask)
|
||||
{
|
||||
uint32_t u32IntFlag = 0;
|
||||
|
||||
/* Check unit transfer interrupt flag */
|
||||
if((u32Mask & SPI_UNIT_INT_MASK) && (spi->CNTRL & SPI_CNTRL_IF_Msk))
|
||||
u32IntFlag |= SPI_UNIT_INT_MASK;
|
||||
|
||||
/* Check slave 3-wire mode start interrupt flag */
|
||||
if((u32Mask & SPI_SSTA_INT_MASK) && (spi->CNTRL2 & SPI_CNTRL2_SLV_START_INTSTS_Msk))
|
||||
u32IntFlag |= SPI_SSTA_INT_MASK;
|
||||
|
||||
/* Check TX threshold interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_TX_INT_MASK) && (spi->STATUS & SPI_STATUS_TX_INTSTS_Msk))
|
||||
u32IntFlag |= SPI_FIFO_TX_INT_MASK;
|
||||
|
||||
/* Check RX threshold interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_RX_INT_MASK) && (spi->STATUS & SPI_STATUS_RX_INTSTS_Msk))
|
||||
u32IntFlag |= SPI_FIFO_RX_INT_MASK;
|
||||
|
||||
/* Check RX overrun interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_RXOV_INT_MASK) && (spi->STATUS & SPI_STATUS_RX_OVERRUN_Msk))
|
||||
u32IntFlag |= SPI_FIFO_RXOV_INT_MASK;
|
||||
|
||||
/* Check RX time-out interrupt flag */
|
||||
if((u32Mask & SPI_FIFO_TIMEOUT_INT_MASK) && (spi->STATUS & SPI_STATUS_TIMEOUT_Msk))
|
||||
u32IntFlag |= SPI_FIFO_TIMEOUT_INT_MASK;
|
||||
|
||||
return u32IntFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt flag.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32Mask The combination of all related interrupt sources.
|
||||
* Each bit corresponds to a interrupt source.
|
||||
* This parameter decides which interrupt flags will be cleared.
|
||||
* (SPI_UNIT_INT_MASK, SPI_SSTA_INT_MASK,
|
||||
* SPI_FIFO_RXOV_INT_MASK, SPI_FIFO_TIMEOUT_INT_MASK)
|
||||
* @return None
|
||||
* @details Clear SPI related interrupt flags specified by u32Mask parameter.
|
||||
*/
|
||||
void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask)
|
||||
{
|
||||
if(u32Mask & SPI_UNIT_INT_MASK)
|
||||
spi->CNTRL |= SPI_CNTRL_IF_Msk; /* Clear unit transfer interrupt flag */
|
||||
|
||||
if(u32Mask & SPI_SSTA_INT_MASK)
|
||||
spi->CNTRL2 |= SPI_CNTRL2_SLV_START_INTSTS_Msk; /* Clear slave 3-wire mode start interrupt flag */
|
||||
|
||||
if(u32Mask & SPI_FIFO_RXOV_INT_MASK)
|
||||
spi->STATUS = SPI_STATUS_RX_OVERRUN_Msk; /* Clear RX overrun interrupt flag */
|
||||
|
||||
if(u32Mask & SPI_FIFO_TIMEOUT_INT_MASK)
|
||||
spi->STATUS = SPI_STATUS_TIMEOUT_Msk; /* Clear RX time-out interrupt flag */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get SPI status.
|
||||
* @param[in] spi The pointer of the specified SPI module.
|
||||
* @param[in] u32Mask The combination of all related sources.
|
||||
* Each bit corresponds to a source.
|
||||
* This parameter decides which flags will be read.
|
||||
* (SPI_BUSY_MASK, SPI_RX_EMPTY_MASK, SPI_RX_FULL_MASK,
|
||||
* SPI_TX_EMPTY_MASK, SPI_TX_FULL_MASK)
|
||||
* @return Flags of selected sources.
|
||||
* @details Get SPI related status specified by u32Mask parameter.
|
||||
*/
|
||||
uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask)
|
||||
{
|
||||
uint32_t u32Flag = 0;
|
||||
|
||||
/* Check busy status */
|
||||
if((u32Mask & SPI_BUSY_MASK) && (spi->CNTRL & SPI_CNTRL_GO_BUSY_Msk))
|
||||
u32Flag |= SPI_BUSY_MASK;
|
||||
|
||||
/* Check RX empty flag */
|
||||
if((u32Mask & SPI_RX_EMPTY_MASK) && (spi->CNTRL & SPI_CNTRL_RX_EMPTY_Msk))
|
||||
u32Flag |= SPI_RX_EMPTY_MASK;
|
||||
|
||||
/* Check RX full flag */
|
||||
if((u32Mask & SPI_RX_FULL_MASK) && (spi->CNTRL & SPI_CNTRL_RX_FULL_Msk))
|
||||
u32Flag |= SPI_RX_FULL_MASK;
|
||||
|
||||
/* Check TX empty flag */
|
||||
if((u32Mask & SPI_TX_EMPTY_MASK) && (spi->CNTRL & SPI_CNTRL_TX_EMPTY_Msk))
|
||||
u32Flag |= SPI_TX_EMPTY_MASK;
|
||||
|
||||
/* Check TX full flag */
|
||||
if((u32Mask & SPI_TX_FULL_MASK) && (spi->CNTRL & SPI_CNTRL_TX_FULL_Msk))
|
||||
u32Flag |= SPI_TX_FULL_MASK;
|
||||
|
||||
return u32Flag;
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group SPI_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group SPI_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
205
NUC123/StdDriver/src/sys.c
Normal file
205
NUC123/StdDriver/src/sys.c
Normal file
@ -0,0 +1,205 @@
|
||||
/**************************************************************************//**
|
||||
* @file sys.c
|
||||
* @version V3.00
|
||||
* $Revision: 7 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series SYS driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "NUC123.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup SYS_Driver SYS Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup SYS_EXPORTED_FUNCTIONS SYS Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clear reset source
|
||||
* @param[in] u32Src is system reset source. Including :
|
||||
* - \ref SYS_RSTSRC_RSTS_CPU_Msk
|
||||
* - \ref SYS_RSTSRC_RSTS_SYS_Msk
|
||||
* - \ref SYS_RSTSRC_RSTS_BOD_Msk
|
||||
* - \ref SYS_RSTSRC_RSTS_LVR_Msk
|
||||
* - \ref SYS_RSTSRC_RSTS_WDT_Msk
|
||||
* - \ref SYS_RSTSRC_RSTS_RESET_Msk
|
||||
* - \ref SYS_RSTSRC_RSTS_POR_Msk
|
||||
* @return None
|
||||
* @details This function clear the selected system reset source.
|
||||
*/
|
||||
void SYS_ClearResetSrc(uint32_t u32Src)
|
||||
{
|
||||
SYS->RSTSRC |= u32Src;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Brown-out detector output status
|
||||
* @param None
|
||||
* @retval 0 System voltage is higher than BOD_VL setting or BOD_EN is 0.
|
||||
* @retval 1 System voltage is lower than BOD_VL setting.
|
||||
* @details This function get Brown-out detector output status.
|
||||
*/
|
||||
uint32_t SYS_GetBODStatus(void)
|
||||
{
|
||||
return (SYS->BODCR & SYS_BODCR_BOD_OUT_Msk) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get reset status register value
|
||||
* @param None
|
||||
* @return Reset source
|
||||
* @details This function get the system reset status register value.
|
||||
*/
|
||||
uint32_t SYS_GetResetSrc(void)
|
||||
{
|
||||
return (SYS->RSTSRC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if register lock is set
|
||||
* @param None
|
||||
* @retval 0 Write-protection function is disabled.
|
||||
* @retval 1 Write-protection function is enabled.
|
||||
* @details This function check register write-protection bit setting.
|
||||
*/
|
||||
uint32_t SYS_IsRegLocked(void)
|
||||
{
|
||||
return !(SYS->REGWRPROT & SYS_REGWRPROT_REGPROTDIS_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get product ID
|
||||
* @param None
|
||||
* @return Product ID
|
||||
* @details This function get product ID.
|
||||
*/
|
||||
uint32_t SYS_ReadPDID(void)
|
||||
{
|
||||
return SYS->PDID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset chip with chip reset
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function reset chip with chip reset.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void SYS_ResetChip(void)
|
||||
{
|
||||
SYS->IPRSTC1 |= SYS_IPRSTC1_CHIP_RST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset chip with CPU reset
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function reset CPU with CPU reset.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void SYS_ResetCPU(void)
|
||||
{
|
||||
SYS->IPRSTC1 |= SYS_IPRSTC1_CPU_RST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset Module
|
||||
* @param[in] u32ModuleIndex is module index. Including :
|
||||
* - \ref PDMA_RST
|
||||
* - \ref GPIO_RST
|
||||
* - \ref TMR0_RST
|
||||
* - \ref TMR1_RST
|
||||
* - \ref TMR2_RST
|
||||
* - \ref TMR3_RST
|
||||
* - \ref I2C0_RST
|
||||
* - \ref I2C1_RST
|
||||
* - \ref SPI0_RST
|
||||
* - \ref SPI1_RST
|
||||
* - \ref SPI2_RST
|
||||
* - \ref UART0_RST
|
||||
* - \ref UART1_RST
|
||||
* - \ref PWM03_RST
|
||||
* - \ref PS2_RST
|
||||
* - \ref USBD_RST
|
||||
* - \ref ADC_RST
|
||||
* - \ref I2S_RST
|
||||
* @return None
|
||||
* @details This function reset selected modules.
|
||||
*/
|
||||
void SYS_ResetModule(uint32_t u32ModuleIndex)
|
||||
{
|
||||
/* Generate reset signal to the corresponding module */
|
||||
*(volatile uint32_t *)((uint32_t)&SYS->IPRSTC1 + (u32ModuleIndex >> 24)) |= 1 << (u32ModuleIndex & 0x00ffffff);
|
||||
|
||||
/* Release corresponding module from reset state */
|
||||
*(volatile uint32_t *)((uint32_t)&SYS->IPRSTC1 + (u32ModuleIndex >> 24)) &= ~(1 << (u32ModuleIndex & 0x00ffffff));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable and set Brown-out detector function
|
||||
* @param[in] i32Mode is reset or interrupt mode. Including :
|
||||
* - \ref SYS_BODCR_BOD_RST_EN
|
||||
* - \ref SYS_BODCR_BOD_INTERRUPT_EN
|
||||
* @param[in] u32BODLevel is Brown-out voltage level. Including :
|
||||
* - \ref SYS_BODCR_BOD_VL_4_5V
|
||||
* - \ref SYS_BODCR_BOD_VL_3_8V
|
||||
* - \ref SYS_BODCR_BOD_VL_2_7V
|
||||
* - \ref SYS_BODCR_BOD_VL_2_2V
|
||||
* @return None
|
||||
* @details This function configure Brown-out detector reset or interrupt mode, enable Brown-out function and set Brown-out voltage level.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*
|
||||
*/
|
||||
void SYS_EnableBOD(int32_t i32Mode, uint32_t u32BODLevel)
|
||||
{
|
||||
/* Enable Brown-out Detector function */
|
||||
SYS->BODCR |= SYS_BODCR_BOD_EN_Msk;
|
||||
|
||||
/* Enable Brown-out interrupt or reset function */
|
||||
SYS->BODCR = (SYS->BODCR & ~SYS_BODCR_BOD_RSTEN_Msk) | i32Mode;
|
||||
|
||||
/* Select Brown-out Detector threshold voltage */
|
||||
SYS->BODCR = (SYS->BODCR & ~SYS_BODCR_BOD_VL_Msk) | u32BODLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Brown-out detector function
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function disable Brown-out detector function.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void SYS_DisableBOD(void)
|
||||
{
|
||||
SYS->BODCR &= ~SYS_BODCR_BOD_EN_Msk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group SYS_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group SYS_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
269
NUC123/StdDriver/src/timer.c
Normal file
269
NUC123/StdDriver/src/timer.c
Normal file
@ -0,0 +1,269 @@
|
||||
/**************************************************************************//**
|
||||
* @file timer.c
|
||||
* @version V3.00
|
||||
* $Revision: 6 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series Timer driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup TIMER_Driver TIMER Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Open Timer in specified mode and frequency
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
* @param[in] u32Mode Operation mode. Possible options are
|
||||
* - \ref TIMER_ONESHOT_MODE
|
||||
* - \ref TIMER_PERIODIC_MODE
|
||||
* - \ref TIMER_TOGGLE_MODE
|
||||
* - \ref TIMER_CONTINUOUS_MODE
|
||||
* @param[in] u32Freq Target working frequency
|
||||
*
|
||||
* @return Real Timer working frequency
|
||||
*
|
||||
* @details This API is used to configure timer to operate in specified mode and frequency.
|
||||
* If timer cannot work in target frequency, a closest frequency will be chose and returned.
|
||||
* @note After calling this API, Timer is \b NOT running yet. But could start timer running be calling
|
||||
* \ref TIMER_Start macro or program registers directly.
|
||||
*/
|
||||
uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
|
||||
{
|
||||
uint32_t u32Clk = TIMER_GetModuleClock(timer);
|
||||
uint32_t u32Cmpr = 0UL, u32Prescale = 0UL;
|
||||
|
||||
/* Fastest possible timer working freq is (u32Clk / 2). While cmpr = 2, prescaler = 0. */
|
||||
if(u32Freq > (u32Clk / 2UL))
|
||||
{
|
||||
u32Cmpr = 2UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32Cmpr = u32Clk / u32Freq;
|
||||
u32Prescale = (u32Cmpr >> 24); /* for 24 bits CMPDAT */
|
||||
if (u32Prescale > 0UL)
|
||||
u32Cmpr = u32Cmpr / (u32Prescale + 1UL);
|
||||
}
|
||||
|
||||
timer->TCSR = u32Mode | u32Prescale;
|
||||
timer->TCMPR = u32Cmpr;
|
||||
|
||||
return(u32Clk / (u32Cmpr * (u32Prescale + 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop Timer Counting
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This API stops Timer counting and disable all Timer interrupt function.
|
||||
*/
|
||||
void TIMER_Close(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR = 0;
|
||||
timer->TEXCON = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a specify delay time
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
* @param[in] u32Usec Delay period in micro seconds. Valid values are between 100~1000000 (100 micro second ~ 1 second).
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This API is used to create a delay loop for u32usec micro seconds.
|
||||
* @note This API overwrites the register setting of the timer used to count the delay time.
|
||||
* @note This API use polling mode. So there is no need to enable interrupt for the timer module used to generate delay.
|
||||
*/
|
||||
void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
|
||||
{
|
||||
uint32_t u32Clk = TIMER_GetModuleClock(timer);
|
||||
uint32_t u32Prescale = 0UL, u32Delay = (SystemCoreClock / u32Clk) + 1UL;
|
||||
uint32_t u32Cmpr, u32NsecPerTick;
|
||||
|
||||
/* Clear current timer configuration */
|
||||
timer->TCSR = 0UL;
|
||||
timer->TEXCON = 0UL;
|
||||
|
||||
if(u32Clk <= 1000000UL) /* min delay is 1000 us if timer clock source is <= 1 MHz */
|
||||
{
|
||||
if(u32Usec < 1000UL)
|
||||
{
|
||||
u32Usec = 1000UL;
|
||||
}
|
||||
if(u32Usec > 1000000UL)
|
||||
{
|
||||
u32Usec = 1000000UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(u32Usec < 100UL)
|
||||
{
|
||||
u32Usec = 100UL;
|
||||
}
|
||||
if(u32Usec > 1000000UL)
|
||||
{
|
||||
u32Usec = 1000000UL;
|
||||
}
|
||||
}
|
||||
|
||||
if(u32Clk <= 1000000UL)
|
||||
{
|
||||
u32Prescale = 0UL;
|
||||
u32NsecPerTick = 1000000000UL / u32Clk;
|
||||
u32Cmpr = (u32Usec * 1000UL) / u32NsecPerTick;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32Cmpr = u32Usec * (u32Clk / 1000000UL);
|
||||
u32Prescale = (u32Cmpr >> 24); /* for 24 bits CMPDAT */
|
||||
if (u32Prescale > 0UL)
|
||||
u32Cmpr = u32Cmpr / (u32Prescale + 1UL);
|
||||
}
|
||||
|
||||
timer->TCMPR = u32Cmpr;
|
||||
timer->TCSR = TIMER_TCSR_CEN_Msk | TIMER_ONESHOT_MODE | u32Prescale;
|
||||
|
||||
/*
|
||||
When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
|
||||
And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
|
||||
*/
|
||||
for(; u32Delay > 0; u32Delay--)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
|
||||
while(timer->TCSR & TIMER_TCSR_CACT_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Timer Capture Function
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
* @param[in] u32CapMode Timer capture mode. Could be
|
||||
* - \ref TIMER_CAPTURE_FREE_COUNTING_MODE
|
||||
* - \ref TIMER_CAPTURE_COUNTER_RESET_MODE
|
||||
* @param[in] u32Edge Timer capture edge. Possible values are
|
||||
* - \ref TIMER_CAPTURE_FALLING_EDGE
|
||||
* - \ref TIMER_CAPTURE_RISING_EDGE
|
||||
* - \ref TIMER_CAPTURE_FALLING_AND_RISING_EDGE
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This API is used to enable timer capture function with specified mode and capture edge.
|
||||
* @note Timer frequency should be configured separately by using \ref TIMER_Open API, or program registers directly.
|
||||
*/
|
||||
void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
|
||||
{
|
||||
|
||||
timer->TEXCON = (timer->TEXCON & ~(TIMER_TEXCON_RSTCAPSEL_Msk |
|
||||
TIMER_TEXCON_TEX_EDGE_Msk)) |
|
||||
u32CapMode | u32Edge | TIMER_TEXCON_TEXEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Timer Capture Function
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This API is used to disable the Timer capture function.
|
||||
*/
|
||||
void TIMER_DisableCapture(TIMER_T *timer)
|
||||
{
|
||||
timer->TEXCON &= ~TIMER_TEXCON_TEXEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Timer Counter Function
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
* @param[in] u32Edge Detection edge of counter pin. Could be ether
|
||||
* - \ref TIMER_COUNTER_FALLING_EDGE, or
|
||||
* - \ref TIMER_COUNTER_RISING_EDGE
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable the Timer counter function with specify detection edge.
|
||||
* @note Timer compare value should be configured separately by using \ref TIMER_SET_CMP_VALUE macro or program registers directly.
|
||||
* @note While using event counter function, \ref TIMER_TOGGLE_MODE cannot set as timer operation mode.
|
||||
*/
|
||||
void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
|
||||
{
|
||||
timer->TEXCON = (timer->TEXCON & ~TIMER_TEXCON_TX_PHASE_Msk) | u32Edge;
|
||||
timer->TCSR |= TIMER_TCSR_CTB_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Timer Counter Function
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This API is used to disable the Timer event counter function.
|
||||
*/
|
||||
void TIMER_DisableEventCounter(TIMER_T *timer)
|
||||
{
|
||||
timer->TCSR &= ~TIMER_TCSR_CTB_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Timer Clock Frequency
|
||||
*
|
||||
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
|
||||
*
|
||||
* @return Timer clock frequency
|
||||
*
|
||||
* @details This API is used to get the clock frequency of Timer.
|
||||
* @note This API cannot return correct clock rate if timer source is external clock input.
|
||||
*/
|
||||
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
|
||||
{
|
||||
uint32_t u32Src;
|
||||
const uint32_t au32Clk[] = {__HXT, 0, 0, 0, 0, __LIRC, 0, __HIRC};
|
||||
|
||||
if(timer == TIMER0)
|
||||
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0_S_Msk) >> CLK_CLKSEL1_TMR0_S_Pos;
|
||||
else if(timer == TIMER1)
|
||||
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1_S_Msk) >> CLK_CLKSEL1_TMR1_S_Pos;
|
||||
else if(timer == TIMER2)
|
||||
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR2_S_Msk) >> CLK_CLKSEL1_TMR2_S_Pos;
|
||||
else // Timer 3
|
||||
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR3_S_Msk) >> CLK_CLKSEL1_TMR3_S_Pos;
|
||||
|
||||
if(u32Src == 2)
|
||||
{
|
||||
return(SystemCoreClock);
|
||||
}
|
||||
|
||||
return(au32Clk[u32Src]);
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group TIMER_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group TIMER_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
453
NUC123/StdDriver/src/uart.c
Normal file
453
NUC123/StdDriver/src/uart.c
Normal file
@ -0,0 +1,453 @@
|
||||
/**************************************************************************//**
|
||||
* @file uart.c
|
||||
* @version V3.00
|
||||
* $Revision: 11 $
|
||||
* $Date: 16/03/04 9:22a $
|
||||
* @brief NUC123 series UART driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "NUC123.h"
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup UART_Driver UART Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup UART_EXPORTED_FUNCTIONS UART Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clear UART specified interrupt flag
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32InterruptFlag The specified interrupt of UART module.
|
||||
* - UART_ISR_BUF_ERR_INT_Msk : Buffer Error interrupt
|
||||
* - UART_ISR_MODEM_INT_Msk : Modem interrupt
|
||||
* - UART_ISR_RLS_INT_Msk : Rx Line status interrupt
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to clear UART specified interrupt flag.
|
||||
*/
|
||||
void UART_ClearIntFlag(UART_T* uart , uint32_t u32InterruptFlag)
|
||||
{
|
||||
|
||||
if(u32InterruptFlag & UART_ISR_RLS_INT_Msk) /* clear Receive Line Status Interrupt */
|
||||
{
|
||||
uart->FSR = UART_FSR_BIF_Msk | UART_FSR_FEF_Msk | UART_FSR_PEF_Msk;
|
||||
uart->FSR = UART_FSR_RS485_ADD_DETF_Msk;
|
||||
}
|
||||
|
||||
if(u32InterruptFlag & UART_ISR_MODEM_INT_Msk) /* clear Modem Interrupt */
|
||||
uart->MSR |= UART_MSR_DCTSF_Msk;
|
||||
|
||||
if(u32InterruptFlag & UART_ISR_BUF_ERR_INT_Msk) /* clear Buffer Error Interrupt */
|
||||
{
|
||||
uart->FSR = UART_FSR_RX_OVER_IF_Msk | UART_FSR_TX_OVER_IF_Msk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable UART interrupt
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to disable UART interrupt.
|
||||
*/
|
||||
void UART_Close(UART_T* uart)
|
||||
{
|
||||
uart->IER = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable UART auto flow control function
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to disable UART auto flow control.
|
||||
*/
|
||||
void UART_DisableFlowCtrl(UART_T* uart)
|
||||
{
|
||||
uart->IER &= ~(UART_IER_AUTO_RTS_EN_Msk | UART_IER_AUTO_CTS_EN_Msk);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable UART specified interrupt
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32InterruptFlag The specified interrupt of UART module.
|
||||
* - UART_IER_WAKE_EN_Msk : Wakeup interrupt
|
||||
* - UART_IER_BUF_ERR_IEN_Msk : Buffer Error interrupt
|
||||
* - UART_IER_RTO_IEN_Msk : Rx time-out interrupt
|
||||
* - UART_IER_MODEM_IEN_Msk : Modem interrupt
|
||||
* - UART_IER_RLS_IEN_Msk : Rx Line status interrupt
|
||||
* - UART_IER_THRE_IEN_Msk : Tx empty interrupt
|
||||
* - UART_IER_RDA_IEN_Msk : Rx ready interrupt
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to disable UART specified interrupt and disable NVIC UART IRQ.
|
||||
*/
|
||||
void UART_DisableInt(UART_T* uart, uint32_t u32InterruptFlag)
|
||||
{
|
||||
/* Disable UART specified interrupt */
|
||||
UART_DISABLE_INT(uart, u32InterruptFlag);
|
||||
|
||||
/* Disable NVIC UART IRQ */
|
||||
if(uart == UART0)
|
||||
NVIC_DisableIRQ(UART0_IRQn);
|
||||
else
|
||||
NVIC_DisableIRQ(UART1_IRQn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable UART auto flow control function
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to enable UART auto flow control.
|
||||
*/
|
||||
void UART_EnableFlowCtrl(UART_T* uart)
|
||||
{
|
||||
/* Set RTS pin output is low level active */
|
||||
uart->MCR |= UART_MCR_LEV_RTS_Msk;
|
||||
|
||||
/* Set CTS pin input is low level active */
|
||||
uart->MSR |= UART_MSR_LEV_CTS_Msk;
|
||||
|
||||
/* Set RTS and CTS auto flow control enable */
|
||||
uart->IER |= UART_IER_AUTO_RTS_EN_Msk | UART_IER_AUTO_CTS_EN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable UART specified interrupt
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32InterruptFlag The specified interrupt of UART module:
|
||||
* - UART_IER_WAKE_EN_Msk : Wakeup interrupt
|
||||
* - UART_IER_BUF_ERR_IEN_Msk : Buffer Error interrupt
|
||||
* - UART_IER_RTO_IEN_Msk : Rx time-out interrupt
|
||||
* - UART_IER_MODEM_IEN_Msk : Modem interrupt
|
||||
* - UART_IER_RLS_IEN_Msk : Rx Line status interrupt
|
||||
* - UART_IER_THRE_IEN_Msk : Tx empty interrupt
|
||||
* - UART_IER_RDA_IEN_Msk : Rx ready interrupt
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to enable UART specified interrupt and enable NVIC UART IRQ.
|
||||
*/
|
||||
void UART_EnableInt(UART_T* uart, uint32_t u32InterruptFlag)
|
||||
{
|
||||
/* Enable UART specified interrupt */
|
||||
UART_ENABLE_INT(uart, u32InterruptFlag);
|
||||
|
||||
/* Enable NVIC UART IRQ */
|
||||
if(uart == UART0)
|
||||
NVIC_EnableIRQ(UART0_IRQn);
|
||||
else
|
||||
NVIC_EnableIRQ(UART1_IRQn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open and set UART function
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32baudrate The baudrate of UART module.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function use to enable UART function and set baud-rate.
|
||||
*/
|
||||
void UART_Open(UART_T* uart, uint32_t u32baudrate)
|
||||
{
|
||||
uint8_t u8UartClkSrcSel, u8UartClkDivNum;
|
||||
uint32_t u32ClkTbl[4] = {__HXT, 0, 0, __HIRC};
|
||||
uint32_t u32Baud_Div = 0;
|
||||
|
||||
/* Get UART clock source selection */
|
||||
u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART_S_Msk) >> CLK_CLKSEL1_UART_S_Pos;
|
||||
|
||||
/* Get UART clock divider number */
|
||||
u8UartClkDivNum = (CLK->CLKDIV & CLK_CLKDIV_UART_N_Msk) >> CLK_CLKDIV_UART_N_Pos;
|
||||
|
||||
/* Select UART function */
|
||||
uart->FUN_SEL = UART_FUNC_SEL_UART;
|
||||
|
||||
/* Set UART line configuration */
|
||||
uart->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
|
||||
|
||||
/* Set UART Rx and RTS trigger level */
|
||||
uart->FCR &= ~(UART_FCR_RFITL_Msk | UART_FCR_RTS_TRI_LEV_Msk);
|
||||
|
||||
/* Get PLL clock frequency if UART clock source selection is PLL */
|
||||
if(u8UartClkSrcSel == 1)
|
||||
u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq();
|
||||
|
||||
/* Set UART baud rate */
|
||||
if(u32baudrate != 0)
|
||||
{
|
||||
u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate);
|
||||
|
||||
if(u32Baud_Div > 0xFFFF)
|
||||
uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate));
|
||||
else
|
||||
uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read UART data
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] pu8RxBuf The buffer to receive the data of receive FIFO.
|
||||
* @param[in] u32ReadBytes The read bytes number of data.
|
||||
*
|
||||
* @return u32Count Receive byte count
|
||||
*
|
||||
* @details The function is used to read Rx data from RX FIFO and the data will be stored in pu8RxBuf.
|
||||
*/
|
||||
uint32_t UART_Read(UART_T* uart, uint8_t *pu8RxBuf, uint32_t u32ReadBytes)
|
||||
{
|
||||
uint32_t u32Count, u32delayno;
|
||||
|
||||
for(u32Count = 0; u32Count < u32ReadBytes; u32Count++)
|
||||
{
|
||||
u32delayno = 0;
|
||||
|
||||
while(uart->FSR & UART_FSR_RX_EMPTY_Msk) /* Check RX empty => failed */
|
||||
{
|
||||
u32delayno++;
|
||||
if(u32delayno >= 0x40000000)
|
||||
return u32Count;
|
||||
}
|
||||
pu8RxBuf[u32Count] = uart->RBR; /* Get Data from UART RX */
|
||||
}
|
||||
|
||||
return u32Count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set UART line configuration
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32baudrate The baudrate of UART module.
|
||||
* If u32baudrate = 0, UART baudrate will not change.
|
||||
* @param[in] u32data_width The data length of UART module.
|
||||
* - UART_WORD_LEN_5
|
||||
* - UART_WORD_LEN_6
|
||||
* - UART_WORD_LEN_7
|
||||
* - UART_WORD_LEN_8
|
||||
* @param[in] u32parity The parity setting (none/odd/even/mark/space) of UART module.
|
||||
* - UART_PARITY_NONE
|
||||
* - UART_PARITY_ODD
|
||||
* - UART_PARITY_EVEN
|
||||
* - UART_PARITY_MARK
|
||||
* - UART_PARITY_SPACE
|
||||
* @param[in] u32stop_bits The stop bit length (1/1.5/2 bit) of UART module.
|
||||
* - UART_STOP_BIT_1
|
||||
* - UART_STOP_BIT_1_5
|
||||
* - UART_STOP_BIT_2
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function use to config UART line setting.
|
||||
|
||||
*/
|
||||
void UART_SetLine_Config(UART_T* uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits)
|
||||
{
|
||||
uint8_t u8UartClkSrcSel, u8UartClkDivNum;
|
||||
uint32_t u32ClkTbl[4] = {__HXT, 0, 0, __HIRC};
|
||||
uint32_t u32Baud_Div = 0;
|
||||
|
||||
/* Get UART clock source selection */
|
||||
u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART_S_Msk) >> CLK_CLKSEL1_UART_S_Pos;
|
||||
|
||||
/* Get UART clock divider number */
|
||||
u8UartClkDivNum = (CLK->CLKDIV & CLK_CLKDIV_UART_N_Msk) >> CLK_CLKDIV_UART_N_Pos;
|
||||
|
||||
/* Get PLL clock frequency if UART clock source selection is PLL */
|
||||
if(u8UartClkSrcSel == 1)
|
||||
u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq();
|
||||
|
||||
/* Set UART baud rate */
|
||||
if(u32baudrate != 0)
|
||||
{
|
||||
u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate);
|
||||
|
||||
if(u32Baud_Div > 0xFFFF)
|
||||
uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate));
|
||||
else
|
||||
uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
|
||||
}
|
||||
|
||||
/* Set UART line configuration */
|
||||
uart->LCR = u32data_width | u32parity | u32stop_bits;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set Rx timeout count
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32TOC Rx timeout counter.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function use to set Rx timeout count.
|
||||
*/
|
||||
void UART_SetTimeoutCnt(UART_T* uart, uint32_t u32TOC)
|
||||
{
|
||||
/* Set time-out interrupt comparator */
|
||||
uart->TOR = (uart->TOR & ~UART_TOR_TOIC_Msk) | (u32TOC);
|
||||
|
||||
/* Set time-out counter enable */
|
||||
uart->IER |= UART_IER_TIME_OUT_EN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Select and configure IrDA function
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module
|
||||
* @param[in] u32Buadrate The baudrate of UART module.
|
||||
* @param[in] u32Direction The direction of UART module in IrDA mode:
|
||||
* - UART_IRCR_TX_SELECT
|
||||
* - UART_IRCR_RX_SELECT
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to configure IrDA relative settings. It consists of TX or RX mode and baudrate.
|
||||
*/
|
||||
void UART_SelectIrDAMode(UART_T* uart, uint32_t u32Buadrate, uint32_t u32Direction)
|
||||
{
|
||||
uint8_t u8UartClkSrcSel, u8UartClkDivNum;
|
||||
uint32_t u32ClkTbl[4] = {__HXT, 0, 0, __HIRC};
|
||||
uint32_t u32Baud_Div;
|
||||
|
||||
/* Select IrDA function mode */
|
||||
uart->FUN_SEL = UART_FUNC_SEL_IrDA;
|
||||
|
||||
/* Get UART clock source selection */
|
||||
u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART_S_Msk) >> CLK_CLKSEL1_UART_S_Pos;
|
||||
|
||||
/* Get UART clock divider number */
|
||||
u8UartClkDivNum = (CLK->CLKDIV & CLK_CLKDIV_UART_N_Msk) >> CLK_CLKDIV_UART_N_Pos;
|
||||
|
||||
/* Get PLL clock frequency if UART clock source selection is PLL */
|
||||
if(u8UartClkSrcSel == 1)
|
||||
u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq();
|
||||
|
||||
/* Set UART IrDA baud rate in mode 0 */
|
||||
if(u32Buadrate != 0)
|
||||
{
|
||||
u32Baud_Div = UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32Buadrate);
|
||||
|
||||
if(u32Baud_Div < 0xFFFF)
|
||||
uart->BAUD = (UART_BAUD_MODE0 | u32Baud_Div);
|
||||
}
|
||||
|
||||
/* Configure IrDA relative settings */
|
||||
if(u32Direction == UART_IRCR_RX_SELECT)
|
||||
{
|
||||
uart->IRCR |= UART_IRCR_INV_RX_Msk; //Rx signal is inverse
|
||||
uart->IRCR &= ~UART_IRCR_TX_SELECT_Msk;
|
||||
}
|
||||
else
|
||||
{
|
||||
uart->IRCR &= ~UART_IRCR_INV_TX_Msk; //Tx signal is not inverse
|
||||
uart->IRCR |= UART_IRCR_TX_SELECT_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Select and configure RS485 function
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] u32Mode The operation mode(NMM/AUD/AAD).
|
||||
* - UART_ALT_CSR_RS485_NMM_Msk
|
||||
* - UART_ALT_CSR_RS485_AUD_Msk
|
||||
* - UART_ALT_CSR_RS485_AAD_Msk
|
||||
* @param[in] u32Addr The RS485 address.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details The function is used to set RS485 relative setting.
|
||||
*/
|
||||
void UART_SelectRS485Mode(UART_T* uart, uint32_t u32Mode, uint32_t u32Addr)
|
||||
{
|
||||
/* Select UART RS485 function mode */
|
||||
uart->FUN_SEL = UART_FUNC_SEL_RS485;
|
||||
|
||||
/* Set RS485 configuration */
|
||||
uart->ALT_CSR &= ~(UART_ALT_CSR_RS485_NMM_Msk | UART_ALT_CSR_RS485_AUD_Msk | UART_ALT_CSR_RS485_AAD_Msk | UART_ALT_CSR_ADDR_MATCH_Msk);
|
||||
uart->ALT_CSR |= (u32Mode | (u32Addr << UART_ALT_CSR_ADDR_MATCH_Pos));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write UART data
|
||||
*
|
||||
* @param[in] uart The pointer of the specified UART module.
|
||||
* @param[in] pu8TxBuf The buffer to send the data to UART transmission FIFO.
|
||||
* @param[out] u32WriteBytes The byte number of data.
|
||||
*
|
||||
* @return u32Count transfer byte count
|
||||
*
|
||||
* @details The function is to write data into TX buffer to transmit data by UART.
|
||||
*/
|
||||
uint32_t UART_Write(UART_T* uart, uint8_t *pu8TxBuf, uint32_t u32WriteBytes)
|
||||
{
|
||||
uint32_t u32Count, u32delayno;
|
||||
|
||||
for(u32Count = 0; u32Count != u32WriteBytes; u32Count++)
|
||||
{
|
||||
u32delayno = 0;
|
||||
while(uart->FSR & UART_FSR_TX_FULL_Msk) /* Wait Tx not full or Time-out manner */
|
||||
{
|
||||
u32delayno++;
|
||||
if(u32delayno >= 0x40000000)
|
||||
return u32Count;
|
||||
}
|
||||
uart->THR = pu8TxBuf[u32Count]; /* Send UART Data from buffer */
|
||||
}
|
||||
|
||||
return u32Count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group UART_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group UART_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
||||
|
||||
|
||||
|
717
NUC123/StdDriver/src/usbd.c
Normal file
717
NUC123/StdDriver/src/usbd.c
Normal file
@ -0,0 +1,717 @@
|
||||
/**************************************************************************//**
|
||||
* @file usbd.c
|
||||
* @version V3.00
|
||||
* $Revision: 22 $
|
||||
* $Date: 15/09/01 3:15p $
|
||||
* @brief NUC123 series USBD driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "NUC123.h"
|
||||
|
||||
#if 0
|
||||
#define DBG_PRINTF printf
|
||||
#else
|
||||
#define DBG_PRINTF(...)
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup USBD_Driver USBD Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup USBD_EXPORTED_FUNCTIONS USBD Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/* Global variables for Control Pipe */
|
||||
uint8_t g_usbd_SetupPacket[8] = {0}; /*!< Setup packet buffer */
|
||||
volatile uint8_t g_usbd_RemoteWakeupEn = 0; /*!< Remote wake up function enable flag */
|
||||
|
||||
/**
|
||||
* @cond HIDDEN_SYMBOLS
|
||||
*/
|
||||
static volatile uint8_t *g_usbd_CtrlInPointer = 0;
|
||||
static volatile uint32_t g_usbd_CtrlInSize = 0;
|
||||
static volatile uint8_t *g_usbd_CtrlOutPointer = 0;
|
||||
static volatile uint32_t g_usbd_CtrlOutSize = 0;
|
||||
static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0;
|
||||
static volatile uint32_t g_usbd_UsbAddr = 0;
|
||||
static volatile uint32_t g_usbd_UsbConfig = 0;
|
||||
static volatile uint32_t g_usbd_CtrlMaxPktSize = 8;
|
||||
static volatile uint32_t g_usbd_UsbAltInterface = 0;
|
||||
static volatile uint32_t g_usbd_CtrlOutToggle = 0;
|
||||
static volatile uint8_t g_usbd_CtrlInZeroFlag = 0;
|
||||
/**
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
const S_USBD_INFO_T *g_usbd_sInfo; /*!< A pointer for USB information structure */
|
||||
|
||||
VENDOR_REQ g_usbd_pfnVendorRequest = NULL; /*!< USB Vendor Request Functional Pointer */
|
||||
CLASS_REQ g_usbd_pfnClassRequest = NULL; /*!< USB Class Request Functional Pointer */
|
||||
SET_INTERFACE_REQ g_usbd_pfnSetInterface = NULL; /*!< USB Set Interface Functional Pointer */
|
||||
SET_CONFIG_CB g_usbd_pfnSetConfigCallback = NULL; /*!< USB Set configuration callback function pointer */
|
||||
uint32_t g_u32EpStallLock = 0; /*!< Bit map flag to lock specified EP when SET_FEATURE */
|
||||
|
||||
/**
|
||||
* @brief This function makes USBD module to be ready to use
|
||||
*
|
||||
* @param[in] param The structure of USBD information.
|
||||
* @param[in] pfnClassReq USB Class request callback function.
|
||||
* @param[in] pfnSetInterface USB Set Interface request callback function.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function will enable USB controller, USB PHY transceiver and pull-up resistor of USB_D+ pin. USB PHY will drive SE0 to bus.
|
||||
*/
|
||||
void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
|
||||
{
|
||||
g_usbd_sInfo = param;
|
||||
g_usbd_pfnClassRequest = pfnClassReq;
|
||||
g_usbd_pfnSetInterface = pfnSetInterface;
|
||||
|
||||
/* get EP0 maximum packet size */
|
||||
g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7];
|
||||
|
||||
/* Initial USB engine */
|
||||
USBD->ATTR = 0x7D0;
|
||||
/* Force SE0 */
|
||||
USBD_SET_SE0();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function makes USB host to recognize the device
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Enable WAKEUP, FLDET, USB and BUS interrupts. Disable software-disconnect function after 100ms delay with SysTick timer.
|
||||
*/
|
||||
void USBD_Start(void)
|
||||
{
|
||||
CLK_SysTickDelay(100000);
|
||||
/* Disable software-disconnect function */
|
||||
USBD_CLR_SE0();
|
||||
|
||||
/* Clear USB-related interrupts before enable interrupt */
|
||||
USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
|
||||
|
||||
/* Enable USB-related interrupts. */
|
||||
USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the received SETUP packet
|
||||
*
|
||||
* @param[in] buf A buffer pointer used to store 8-byte SETUP packet.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Store SETUP packet to a user-specified buffer.
|
||||
*
|
||||
*/
|
||||
void USBD_GetSetupPacket(uint8_t *buf)
|
||||
{
|
||||
USBD_MemCopy(buf, g_usbd_SetupPacket, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process SETUP packet
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Parse SETUP packet and perform the corresponding action.
|
||||
*
|
||||
*/
|
||||
void USBD_ProcessSetupPacket(void)
|
||||
{
|
||||
g_usbd_CtrlOutToggle = 0;
|
||||
/* Get SETUP packet from USB buffer */
|
||||
USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8);
|
||||
|
||||
/* Check the request type */
|
||||
switch(g_usbd_SetupPacket[0] & 0x60)
|
||||
{
|
||||
case REQ_STANDARD: // Standard
|
||||
{
|
||||
USBD_StandardRequest();
|
||||
break;
|
||||
}
|
||||
case REQ_CLASS: // Class
|
||||
{
|
||||
if(g_usbd_pfnClassRequest != NULL)
|
||||
{
|
||||
g_usbd_pfnClassRequest();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REQ_VENDOR: // Vendor
|
||||
{
|
||||
if(g_usbd_pfnVendorRequest != NULL)
|
||||
{
|
||||
g_usbd_pfnVendorRequest();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: // reserved
|
||||
{
|
||||
/* Setup error, stall the device */
|
||||
USBD_SET_EP_STALL(EP0);
|
||||
USBD_SET_EP_STALL(EP1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process GetDescriptor request
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Parse GetDescriptor request and perform the corresponding action.
|
||||
*
|
||||
*/
|
||||
void USBD_GetDescriptor(void)
|
||||
{
|
||||
uint32_t u32Len;
|
||||
|
||||
g_usbd_CtrlInZeroFlag = (uint8_t)0;
|
||||
u32Len = 0;
|
||||
u32Len = g_usbd_SetupPacket[7];
|
||||
u32Len <<= 8;
|
||||
u32Len += g_usbd_SetupPacket[6];
|
||||
|
||||
switch(g_usbd_SetupPacket[3])
|
||||
{
|
||||
// Get Device Descriptor
|
||||
case DESC_DEVICE:
|
||||
{
|
||||
u32Len = Minimum(u32Len, LEN_DEVICE);
|
||||
DBG_PRINTF("Get device desc, %d\n", u32Len);
|
||||
USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
break;
|
||||
}
|
||||
// Get Configuration Descriptor
|
||||
case DESC_CONFIG:
|
||||
{
|
||||
uint32_t u32TotalLen;
|
||||
|
||||
u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3];
|
||||
u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
|
||||
|
||||
if(u32Len > u32TotalLen)
|
||||
{
|
||||
u32Len = u32TotalLen;
|
||||
if((u32Len % g_usbd_CtrlMaxPktSize) == 0)
|
||||
{
|
||||
g_usbd_CtrlInZeroFlag = (uint8_t)1;
|
||||
}
|
||||
}
|
||||
USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len);
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
break;
|
||||
}
|
||||
// Get HID Descriptor
|
||||
case DESC_HID:
|
||||
{
|
||||
/* CV3.0 HID Class Descriptor Test,
|
||||
Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */
|
||||
uint32_t u32ConfigDescOffset; // u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index)
|
||||
u32Len = Minimum(u32Len, LEN_HID);
|
||||
DBG_PRINTF("Get HID desc, %d\n", u32Len);
|
||||
|
||||
u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]];
|
||||
USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len);
|
||||
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
break;
|
||||
}
|
||||
// Get Report Descriptor
|
||||
case DESC_HID_RPT:
|
||||
{
|
||||
if(u32Len > g_usbd_sInfo->gu32HidReportSize[g_usbd_SetupPacket[4]])
|
||||
{
|
||||
u32Len = g_usbd_sInfo->gu32HidReportSize[g_usbd_SetupPacket[4]];
|
||||
if((u32Len % g_usbd_CtrlMaxPktSize) == 0)
|
||||
{
|
||||
g_usbd_CtrlInZeroFlag = (uint8_t)1;
|
||||
}
|
||||
}
|
||||
USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HidReportDesc[g_usbd_SetupPacket[4]], u32Len);
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
break;
|
||||
}
|
||||
// Get String Descriptor
|
||||
case DESC_STRING:
|
||||
{
|
||||
// Get String Descriptor
|
||||
if(g_usbd_SetupPacket[2] < 4)
|
||||
{
|
||||
if(u32Len > g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0])
|
||||
{
|
||||
u32Len = g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0];
|
||||
if((u32Len % g_usbd_CtrlMaxPktSize) == 0)
|
||||
{
|
||||
g_usbd_CtrlInZeroFlag = (uint8_t)1;
|
||||
}
|
||||
}
|
||||
USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]], u32Len);
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not support. Reply STALL.
|
||||
USBD_SET_EP_STALL(EP0);
|
||||
USBD_SET_EP_STALL(EP1);
|
||||
DBG_PRINTF("Unsupported string desc (%d). Stall ctrl pipe.\n", g_usbd_SetupPacket[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Not support. Reply STALL.
|
||||
USBD_SET_EP_STALL(EP0);
|
||||
USBD_SET_EP_STALL(EP1);
|
||||
DBG_PRINTF("Unsupported get desc type. stall ctrl pipe\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process standard request
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Parse standard request and perform the corresponding action.
|
||||
*
|
||||
*/
|
||||
void USBD_StandardRequest(void)
|
||||
{
|
||||
/* clear global variables for new request */
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
|
||||
if(g_usbd_SetupPacket[0] & 0x80) /* request data transfer direction */
|
||||
{
|
||||
// Device to host
|
||||
switch(g_usbd_SetupPacket[1])
|
||||
{
|
||||
case GET_CONFIGURATION:
|
||||
{
|
||||
// Return current configuration setting
|
||||
/* Data stage */
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbConfig;
|
||||
USBD_SET_DATA1(EP1);
|
||||
USBD_SET_PAYLOAD_LEN(EP1, 0);
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 1);
|
||||
/* Status stage */
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
DBG_PRINTF("Get configuration\n");
|
||||
break;
|
||||
}
|
||||
case GET_DESCRIPTOR:
|
||||
{
|
||||
USBD_GetDescriptor();
|
||||
/* Status stage */
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
DBG_PRINTF("Get descriptor\n");
|
||||
break;
|
||||
}
|
||||
case GET_INTERFACE:
|
||||
{
|
||||
// Return current interface setting
|
||||
/* Data stage */
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbAltInterface;
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 1);
|
||||
/* Status stage */
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
DBG_PRINTF("Get interface\n");
|
||||
break;
|
||||
}
|
||||
case GET_STATUS:
|
||||
{
|
||||
// Device
|
||||
if(g_usbd_SetupPacket[0] == 0x80)
|
||||
{
|
||||
uint8_t u8Tmp;
|
||||
|
||||
u8Tmp = 0;
|
||||
if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x40) u8Tmp |= 1; // Self-Powered/Bus-Powered.
|
||||
if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x20) u8Tmp |= (g_usbd_RemoteWakeupEn << 1); // Remote wake up
|
||||
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = u8Tmp;
|
||||
}
|
||||
// Interface
|
||||
else if(g_usbd_SetupPacket[0] == 0x81)
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = 0;
|
||||
// Endpoint
|
||||
else if(g_usbd_SetupPacket[0] == 0x82)
|
||||
{
|
||||
uint8_t ep = g_usbd_SetupPacket[4] & 0xF;
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = USBD_GetStall(ep) ? 1 : 0;
|
||||
}
|
||||
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0) + 1) = 0;
|
||||
/* Data stage */
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 2);
|
||||
/* Status stage */
|
||||
USBD_PrepareCtrlOut(0, 0);
|
||||
DBG_PRINTF("Get status\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* Setup error, stall the device */
|
||||
USBD_SET_EP_STALL(EP0);
|
||||
USBD_SET_EP_STALL(EP1);
|
||||
DBG_PRINTF("Unknown request. stall ctrl pipe.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Host to device
|
||||
switch(g_usbd_SetupPacket[1])
|
||||
{
|
||||
case CLEAR_FEATURE:
|
||||
{
|
||||
if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
|
||||
{
|
||||
int32_t epNum, i;
|
||||
|
||||
/* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
|
||||
a flag: g_u32EpStallLock is added to support it */
|
||||
epNum = g_usbd_SetupPacket[4] & 0xF;
|
||||
for(i = 0; i < USBD_MAX_EP; i++)
|
||||
{
|
||||
if(((USBD->EP[i].CFG & 0xF) == epNum) && ((g_u32EpStallLock & (1 << i)) == 0))
|
||||
{
|
||||
USBD->EP[i].CFGP &= ~USBD_CFGP_SSTALL_Msk;
|
||||
USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
|
||||
DBG_PRINTF("Clr stall ep%d %x\n", i, USBD->EP[i].CFGP);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||
g_usbd_RemoteWakeupEn = 0;
|
||||
/* Status stage */
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 0);
|
||||
DBG_PRINTF("Clear feature op %d\n", g_usbd_SetupPacket[2]);
|
||||
break;
|
||||
}
|
||||
case SET_ADDRESS:
|
||||
{
|
||||
g_usbd_UsbAddr = g_usbd_SetupPacket[2];
|
||||
DBG_PRINTF("Set addr to %d\n", g_usbd_UsbAddr);
|
||||
|
||||
// DATA IN for end of setup
|
||||
/* Status Stage */
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 0);
|
||||
break;
|
||||
}
|
||||
case SET_CONFIGURATION:
|
||||
{
|
||||
g_usbd_UsbConfig = g_usbd_SetupPacket[2];
|
||||
|
||||
if(g_usbd_pfnSetConfigCallback)
|
||||
g_usbd_pfnSetConfigCallback();
|
||||
// DATA IN for end of setup
|
||||
/* Status stage */
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 0);
|
||||
DBG_PRINTF("Set config to %d\n", g_usbd_UsbConfig);
|
||||
break;
|
||||
}
|
||||
case SET_FEATURE:
|
||||
{
|
||||
if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
|
||||
{
|
||||
USBD_SetStall(g_usbd_SetupPacket[4] & 0xF);
|
||||
DBG_PRINTF("Set feature. stall ep %d\n", g_usbd_SetupPacket[4] & 0xF);
|
||||
}
|
||||
else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||
{
|
||||
g_usbd_RemoteWakeupEn = 1;
|
||||
DBG_PRINTF("Set feature. enable remote wakeup\n");
|
||||
}
|
||||
/* Status stage */
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 0);
|
||||
break;
|
||||
}
|
||||
case SET_INTERFACE:
|
||||
{
|
||||
g_usbd_UsbAltInterface = g_usbd_SetupPacket[2];
|
||||
if(g_usbd_pfnSetInterface != NULL)
|
||||
g_usbd_pfnSetInterface();
|
||||
/* Status stage */
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 0);
|
||||
DBG_PRINTF("Set interface to %d\n", g_usbd_UsbAltInterface);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* Setup error, stall the device */
|
||||
USBD_SET_EP_STALL(EP0);
|
||||
USBD_SET_EP_STALL(EP1);
|
||||
DBG_PRINTF("Unsupported request. stall ctrl pipe.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare the first Control IN pipe
|
||||
*
|
||||
* @param[in] pu8Buf The pointer of data sent to USB host.
|
||||
* @param[in] u32Size The IN transfer size.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details Prepare data for Control IN transfer.
|
||||
*
|
||||
*/
|
||||
void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
|
||||
{
|
||||
DBG_PRINTF("Prepare Ctrl In %d\n", u32Size);
|
||||
if(u32Size > g_usbd_CtrlMaxPktSize)
|
||||
{
|
||||
// Data size > MXPLD
|
||||
g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize;
|
||||
g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize;
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, g_usbd_CtrlMaxPktSize);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Data size <= MXPLD
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
USBD_SET_DATA1(EP0);
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, u32Size);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, u32Size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Repeat Control IN pipe
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function processes the remained data of Control IN transfer.
|
||||
*
|
||||
*/
|
||||
void USBD_CtrlIn(void)
|
||||
{
|
||||
if(g_usbd_CtrlInSize)
|
||||
{
|
||||
// Process remained data
|
||||
if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize)
|
||||
{
|
||||
// Data size > MXPLD
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
|
||||
g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize;
|
||||
g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Data size <= MXPLD
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize);
|
||||
USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize);
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
}
|
||||
}
|
||||
else // No more data for IN token
|
||||
{
|
||||
// In ACK for Set address
|
||||
if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == SET_ADDRESS))
|
||||
{
|
||||
if((USBD_GET_ADDR() != g_usbd_UsbAddr) && (USBD_GET_ADDR() == 0))
|
||||
{
|
||||
USBD_SET_ADDR(g_usbd_UsbAddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* For the case of data size is integral times maximum packet size */
|
||||
if(g_usbd_CtrlInZeroFlag)
|
||||
{
|
||||
USBD_SET_PAYLOAD_LEN(EP0, 0);
|
||||
g_usbd_CtrlInZeroFlag = 0;
|
||||
}
|
||||
DBG_PRINTF("Ctrl In done.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare the first Control OUT pipe
|
||||
*
|
||||
* @param[in] pu8Buf The pointer of data received from USB host.
|
||||
* @param[in] u32Size The OUT transfer size.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to prepare the first Control OUT transfer.
|
||||
*
|
||||
*/
|
||||
void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
|
||||
{
|
||||
g_usbd_CtrlOutPointer = pu8Buf;
|
||||
g_usbd_CtrlOutSize = 0;
|
||||
g_usbd_CtrlOutSizeLimit = u32Size;
|
||||
USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Repeat Control OUT pipe
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function processes the successive Control OUT transfer.
|
||||
*
|
||||
*/
|
||||
void USBD_CtrlOut(void)
|
||||
{
|
||||
uint32_t u32Size;
|
||||
|
||||
DBG_PRINTF("Ctrl Out Ack %d\n", g_usbd_CtrlOutSize);
|
||||
if(g_usbd_CtrlOutToggle != (USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk))
|
||||
{
|
||||
g_usbd_CtrlOutToggle = USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk;
|
||||
if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
|
||||
{
|
||||
u32Size = USBD_GET_PAYLOAD_LEN(EP1);
|
||||
USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1), u32Size);
|
||||
g_usbd_CtrlOutPointer += u32Size;
|
||||
g_usbd_CtrlOutSize += u32Size;
|
||||
|
||||
if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
|
||||
USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset software flags
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function resets all variables for protocol and resets USB device address to 0.
|
||||
*
|
||||
*/
|
||||
void USBD_SwReset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Reset all variables for protocol
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
g_usbd_CtrlOutPointer = 0;
|
||||
g_usbd_CtrlOutSize = 0;
|
||||
g_usbd_CtrlOutSizeLimit = 0;
|
||||
g_u32EpStallLock = 0;
|
||||
memset(g_usbd_SetupPacket, 0, 8);
|
||||
|
||||
/* Reset PID DATA0 */
|
||||
for(i=0; i<USBD_MAX_EP; i++)
|
||||
USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
|
||||
|
||||
// Reset USB device address
|
||||
USBD_SET_ADDR(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD Set Vendor Request
|
||||
*
|
||||
* @param[in] pfnVendorReq Vendor Request Callback Function
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to set USBD vendor request callback function
|
||||
*/
|
||||
void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
|
||||
{
|
||||
g_usbd_pfnVendorRequest = pfnVendorReq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The callback function which called when get SET CONFIGURATION request
|
||||
*
|
||||
* @param[in] pfnSetConfigCallback Callback function pointer for SET CONFIGURATION request
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to set the callback function which will be called at SET CONFIGURATION request.
|
||||
*/
|
||||
void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
|
||||
{
|
||||
g_usbd_pfnSetConfigCallback = pfnSetConfigCallback;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief EP stall lock function to avoid stall clear by USB SET FEATURE request.
|
||||
*
|
||||
* @param[in] u32EpBitmap Use bitmap to select which endpoints will be locked
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to lock relative endpoint to avoid stall clear by SET FEATURE requst.
|
||||
* If ep stall locked, user needs to reset USB device or re-configure device to clear it.
|
||||
*/
|
||||
void USBD_LockEpStall(uint32_t u32EpBitmap)
|
||||
{
|
||||
g_u32EpStallLock = u32EpBitmap;
|
||||
}
|
||||
/*@}*/ /* end of group USBD_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group USBD_Driver */
|
||||
|
||||
/*@}*/ /* end of group Device_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
71
NUC123/StdDriver/src/wdt.c
Normal file
71
NUC123/StdDriver/src/wdt.c
Normal file
@ -0,0 +1,71 @@
|
||||
/**************************************************************************//**
|
||||
* @file wdt.c
|
||||
* @version V3.00
|
||||
* $Revision: 4 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series WDT driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WDT_Driver WDT Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WDT_EXPORTED_FUNCTIONS WDT Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize WDT counter and start counting
|
||||
*
|
||||
* @param[in] u32TimeoutInterval Time-out interval period of WDT module. Valid values are:
|
||||
* - \ref WDT_TIMEOUT_2POW4
|
||||
* - \ref WDT_TIMEOUT_2POW6
|
||||
* - \ref WDT_TIMEOUT_2POW8
|
||||
* - \ref WDT_TIMEOUT_2POW10
|
||||
* - \ref WDT_TIMEOUT_2POW12
|
||||
* - \ref WDT_TIMEOUT_2POW14
|
||||
* - \ref WDT_TIMEOUT_2POW16
|
||||
* - \ref WDT_TIMEOUT_2POW18
|
||||
* @param[in] u32ResetDelay Configure reset delay period while WDT time-out happened. Valid values are:
|
||||
* - \ref WDT_RESET_DELAY_1026CLK
|
||||
* - \ref WDT_RESET_DELAY_130CLK
|
||||
* - \ref WDT_RESET_DELAY_18CLK
|
||||
* - \ref WDT_RESET_DELAY_3CLK
|
||||
* @param[in] u32EnableReset Enable WDT reset system function. Valid values are TRUE and FALSE.
|
||||
* @param[in] u32EnableWakeup Enable WDT wake-up system function. Valid values are TRUE and FALSE.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function make WDT module start counting with different time-out interval and reset delay period.
|
||||
* @note Please make sure that Register Write-Protection Function has been disabled before using this function.
|
||||
*/
|
||||
void WDT_Open(uint32_t u32TimeoutInterval,
|
||||
uint32_t u32ResetDelay,
|
||||
uint32_t u32EnableReset,
|
||||
uint32_t u32EnableWakeup)
|
||||
{
|
||||
WDT->WTCRALT = u32ResetDelay;
|
||||
|
||||
WDT->WTCR = u32TimeoutInterval | WDT_WTCR_WTE_Msk |
|
||||
(u32EnableReset << WDT_WTCR_WTRE_Pos) |
|
||||
(u32EnableWakeup << WDT_WTCR_WTWKE_Pos);
|
||||
return;
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group WDT_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group WDT_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
72
NUC123/StdDriver/src/wwdt.c
Normal file
72
NUC123/StdDriver/src/wwdt.c
Normal file
@ -0,0 +1,72 @@
|
||||
/**************************************************************************//**
|
||||
* @file wwdt.c
|
||||
* @version V3.00
|
||||
* $Revision: 3 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 series WWDT driver source file
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "NUC123.h"
|
||||
|
||||
|
||||
/** @addtogroup Standard_Driver Standard Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WWDT_Driver WWDT Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup WWDT_EXPORTED_FUNCTIONS WWDT Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Open WWDT function to start counting
|
||||
*
|
||||
* @param[in] u32PreScale Prescale period for the WWDT counter period. Valid values are:
|
||||
* - \ref WWDT_PRESCALER_1
|
||||
* - \ref WWDT_PRESCALER_2
|
||||
* - \ref WWDT_PRESCALER_4
|
||||
* - \ref WWDT_PRESCALER_8
|
||||
* - \ref WWDT_PRESCALER_16
|
||||
* - \ref WWDT_PRESCALER_32
|
||||
* - \ref WWDT_PRESCALER_64
|
||||
* - \ref WWDT_PRESCALER_128
|
||||
* - \ref WWDT_PRESCALER_192
|
||||
* - \ref WWDT_PRESCALER_256
|
||||
* - \ref WWDT_PRESCALER_384
|
||||
* - \ref WWDT_PRESCALER_512
|
||||
* - \ref WWDT_PRESCALER_768
|
||||
* - \ref WWDT_PRESCALER_1024
|
||||
* - \ref WWDT_PRESCALER_1536
|
||||
* - \ref WWDT_PRESCALER_2048
|
||||
* @param[in] u32CmpValue Setting the window compared value. Valid values are between 0x0 to 0x3F.
|
||||
* @param[in] u32EnableInt Enable WWDT interrupt function. Valid values are TRUE and FALSE.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function make WWDT module start counting with different counter period and compared window value.
|
||||
* @note Application can call this function valid only once after boot up.
|
||||
*/
|
||||
void WWDT_Open(uint32_t u32PreScale,
|
||||
uint32_t u32CmpValue,
|
||||
uint32_t u32EnableInt)
|
||||
{
|
||||
WWDT->WWDTCR = u32PreScale |
|
||||
(u32CmpValue << WWDT_WWDTCR_WINCMP_Pos) |
|
||||
((u32EnableInt == TRUE) ? WWDT_WWDTCR_WWDTIE_Msk : 0) |
|
||||
WWDT_WWDTCR_WWDTEN_Msk;
|
||||
return;
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group WWDT_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group WWDT_Driver */
|
||||
|
||||
/*@}*/ /* end of group Standard_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
|
1168
NUC123/_syscalls.c
Normal file
1168
NUC123/_syscalls.c
Normal file
File diff suppressed because it is too large
Load Diff
8763
NUC123/inc/NUC123.h
Normal file
8763
NUC123/inc/NUC123.h
Normal file
File diff suppressed because it is too large
Load Diff
1373
NUC123/inc/cmsis_gcc.h
Normal file
1373
NUC123/inc/cmsis_gcc.h
Normal file
File diff suppressed because it is too large
Load Diff
798
NUC123/inc/core_cm0.h
Normal file
798
NUC123/inc/core_cm0.h
Normal file
@ -0,0 +1,798 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cm0.h
|
||||
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- 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.
|
||||
- Neither the name of ARM 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 AND CONTRIBUTORS "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 COPYRIGHT HOLDERS AND CONTRIBUTORS 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.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CM0_H_GENERIC
|
||||
#define __CORE_CM0_H_GENERIC
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
\page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
|
||||
CMSIS violates the following MISRA-C:2004 rules:
|
||||
|
||||
\li Required Rule 8.5, object/function definition in header file.<br>
|
||||
Function definitions in header files are used to allow 'inlining'.
|
||||
|
||||
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
|
||||
Unions are used for effective representation of core registers.
|
||||
|
||||
\li Advisory Rule 19.7, Function-like macro defined.<br>
|
||||
Function-like macros are used to allow more efficient code.
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* CMSIS definitions
|
||||
******************************************************************************/
|
||||
/**
|
||||
\ingroup Cortex_M0
|
||||
@{
|
||||
*/
|
||||
|
||||
/* CMSIS CM0 definitions */
|
||||
#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
|
||||
#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
|
||||
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
|
||||
__CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
|
||||
|
||||
#define __CORTEX_M (0x00U) /*!< Cortex-M Core */
|
||||
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
#define __ASM __asm /*!< asm keyword for ARM Compiler */
|
||||
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
|
||||
#define __STATIC_INLINE static __inline
|
||||
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#define __ASM __asm /*!< asm keyword for ARM Compiler */
|
||||
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
|
||||
#define __STATIC_INLINE static __inline
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
#define __ASM __asm /*!< asm keyword for GNU Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for GNU Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
#define __ASM __asm /*!< asm keyword for IAR Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __TMS470__ )
|
||||
#define __ASM __asm /*!< asm keyword for TI CCS Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __TASKING__ )
|
||||
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __CSMC__ )
|
||||
#define __packed
|
||||
#define __ASM _asm /*!< asm keyword for COSMIC Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#else
|
||||
#error Unknown compiler
|
||||
#endif
|
||||
|
||||
/** __FPU_USED indicates whether an FPU is used or not.
|
||||
This core does not support an FPU at all
|
||||
*/
|
||||
#define __FPU_USED 0U
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
#if defined __TARGET_FPU_VFP
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#if defined __ARM_PCS_VFP
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
#if defined __ARMVFP__
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __TMS470__ )
|
||||
#if defined __TI_VFP_SUPPORT__
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __TASKING__ )
|
||||
#if defined __FPU_VFP__
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __CSMC__ )
|
||||
#if ( __CSMC__ & 0x400U)
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "core_cmInstr.h" /* Core Instruction Access */
|
||||
#include "core_cmFunc.h" /* Core Function Access */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CM0_H_GENERIC */
|
||||
|
||||
#ifndef __CMSIS_GENERIC
|
||||
|
||||
#ifndef __CORE_CM0_H_DEPENDANT
|
||||
#define __CORE_CM0_H_DEPENDANT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* check device defines and use defaults */
|
||||
#if defined __CHECK_DEVICE_DEFINES
|
||||
#ifndef __CM0_REV
|
||||
#define __CM0_REV 0x0000U
|
||||
#warning "__CM0_REV not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __NVIC_PRIO_BITS
|
||||
#define __NVIC_PRIO_BITS 2U
|
||||
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __Vendor_SysTickConfig
|
||||
#define __Vendor_SysTickConfig 0U
|
||||
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* IO definitions (access restrictions to peripheral registers) */
|
||||
/**
|
||||
\defgroup CMSIS_glob_defs CMSIS Global Defines
|
||||
|
||||
<strong>IO Type Qualifiers</strong> are used
|
||||
\li to specify the access to peripheral variables.
|
||||
\li for automatic generation of peripheral register debug information.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define __I volatile /*!< Defines 'read only' permissions */
|
||||
#else
|
||||
#define __I volatile const /*!< Defines 'read only' permissions */
|
||||
#endif
|
||||
#define __O volatile /*!< Defines 'write only' permissions */
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
|
||||
/* following defines should be used for structure members */
|
||||
#define __IM volatile const /*! Defines 'read only' structure member permissions */
|
||||
#define __OM volatile /*! Defines 'write only' structure member permissions */
|
||||
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
|
||||
|
||||
/*@} end of group Cortex_M0 */
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Register Abstraction
|
||||
Core Register contain:
|
||||
- Core Register
|
||||
- Core NVIC Register
|
||||
- Core SCB Register
|
||||
- Core SysTick Register
|
||||
******************************************************************************/
|
||||
/**
|
||||
\defgroup CMSIS_core_register Defines and Type Definitions
|
||||
\brief Type definitions and defines for Cortex-M processor based devices.
|
||||
*/
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_CORE Status and Control Registers
|
||||
\brief Core Register type definitions.
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Union type to access the Application Program Status Register (APSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
|
||||
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
|
||||
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
|
||||
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
|
||||
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} APSR_Type;
|
||||
|
||||
/* APSR Register Definitions */
|
||||
#define APSR_N_Pos 31U /*!< APSR: N Position */
|
||||
#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
|
||||
|
||||
#define APSR_Z_Pos 30U /*!< APSR: Z Position */
|
||||
#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
|
||||
|
||||
#define APSR_C_Pos 29U /*!< APSR: C Position */
|
||||
#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
|
||||
|
||||
#define APSR_V_Pos 28U /*!< APSR: V Position */
|
||||
#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
|
||||
|
||||
|
||||
/**
|
||||
\brief Union type to access the Interrupt Program Status Register (IPSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
|
||||
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} IPSR_Type;
|
||||
|
||||
/* IPSR Register Definitions */
|
||||
#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
|
||||
#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
|
||||
|
||||
|
||||
/**
|
||||
\brief Union type to access the Special-Purpose Program Status Registers (xPSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
|
||||
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
|
||||
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
|
||||
uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
|
||||
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
|
||||
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
|
||||
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
|
||||
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} xPSR_Type;
|
||||
|
||||
/* xPSR Register Definitions */
|
||||
#define xPSR_N_Pos 31U /*!< xPSR: N Position */
|
||||
#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
|
||||
|
||||
#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
|
||||
#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
|
||||
|
||||
#define xPSR_C_Pos 29U /*!< xPSR: C Position */
|
||||
#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
|
||||
|
||||
#define xPSR_V_Pos 28U /*!< xPSR: V Position */
|
||||
#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
|
||||
|
||||
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
|
||||
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
|
||||
|
||||
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
|
||||
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
|
||||
|
||||
|
||||
/**
|
||||
\brief Union type to access the Control Registers (CONTROL).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t _reserved0:1; /*!< bit: 0 Reserved */
|
||||
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
|
||||
uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} CONTROL_Type;
|
||||
|
||||
/* CONTROL Register Definitions */
|
||||
#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
|
||||
#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
|
||||
|
||||
/*@} end of group CMSIS_CORE */
|
||||
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
|
||||
\brief Type definitions for the NVIC Registers
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[31U];
|
||||
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[31U];
|
||||
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[31U];
|
||||
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[31U];
|
||||
uint32_t RESERVED4[64U];
|
||||
__IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
|
||||
} NVIC_Type;
|
||||
|
||||
/*@} end of group CMSIS_NVIC */
|
||||
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_SCB System Control Block (SCB)
|
||||
\brief Type definitions for the System Control Block Registers
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Structure type to access the System Control Block (SCB).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
|
||||
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
|
||||
uint32_t RESERVED0;
|
||||
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
|
||||
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
|
||||
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
|
||||
uint32_t RESERVED1;
|
||||
__IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
|
||||
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
|
||||
} SCB_Type;
|
||||
|
||||
/* SCB CPUID Register Definitions */
|
||||
#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
|
||||
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
|
||||
|
||||
#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
|
||||
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
|
||||
|
||||
#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
|
||||
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
|
||||
|
||||
#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
|
||||
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
|
||||
|
||||
#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
|
||||
#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
|
||||
|
||||
/* SCB Interrupt Control State Register Definitions */
|
||||
#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
|
||||
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
|
||||
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
|
||||
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
|
||||
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
|
||||
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
|
||||
|
||||
#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
|
||||
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
|
||||
|
||||
#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
|
||||
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
|
||||
|
||||
#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
|
||||
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
|
||||
|
||||
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
|
||||
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
|
||||
|
||||
/* SCB Application Interrupt and Reset Control Register Definitions */
|
||||
#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
|
||||
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
|
||||
|
||||
#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
|
||||
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
|
||||
|
||||
#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
|
||||
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
|
||||
|
||||
#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
|
||||
|
||||
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
|
||||
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
|
||||
|
||||
/* SCB System Control Register Definitions */
|
||||
#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
|
||||
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
|
||||
|
||||
#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
|
||||
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
|
||||
|
||||
#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
|
||||
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
|
||||
|
||||
/* SCB Configuration Control Register Definitions */
|
||||
#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
|
||||
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
|
||||
|
||||
#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
|
||||
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
|
||||
|
||||
/* SCB System Handler Control and State Register Definitions */
|
||||
#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
|
||||
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
|
||||
|
||||
/*@} end of group CMSIS_SCB */
|
||||
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
|
||||
\brief Type definitions for the System Timer Registers.
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Structure type to access the System Timer (SysTick).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
|
||||
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
|
||||
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
|
||||
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
|
||||
} SysTick_Type;
|
||||
|
||||
/* SysTick Control / Status Register Definitions */
|
||||
#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
|
||||
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
|
||||
|
||||
#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
|
||||
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
|
||||
|
||||
#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
|
||||
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
|
||||
|
||||
#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
|
||||
#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
|
||||
|
||||
/* SysTick Reload Register Definitions */
|
||||
#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
|
||||
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
|
||||
|
||||
/* SysTick Current Register Definitions */
|
||||
#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
|
||||
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
|
||||
|
||||
/* SysTick Calibration Register Definitions */
|
||||
#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
|
||||
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
|
||||
|
||||
#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
|
||||
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
|
||||
|
||||
#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
|
||||
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
|
||||
|
||||
/*@} end of group CMSIS_SysTick */
|
||||
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
|
||||
\brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
|
||||
Therefore they are not covered by the Cortex-M0 header file.
|
||||
@{
|
||||
*/
|
||||
/*@} end of group CMSIS_CoreDebug */
|
||||
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_core_bitfield Core register bit field macros
|
||||
\brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Mask and shift a bit field value for use in a register bit range.
|
||||
\param[in] field Name of the register bit field.
|
||||
\param[in] value Value of the bit field.
|
||||
\return Masked and shifted value.
|
||||
*/
|
||||
#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
|
||||
|
||||
/**
|
||||
\brief Mask and shift a register value to extract a bit filed value.
|
||||
\param[in] field Name of the register bit field.
|
||||
\param[in] value Value of register.
|
||||
\return Masked and shifted bit field value.
|
||||
*/
|
||||
#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
|
||||
|
||||
/*@} end of group CMSIS_core_bitfield */
|
||||
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_core_base Core Definitions
|
||||
\brief Definitions for base addresses, unions, and structures.
|
||||
@{
|
||||
*/
|
||||
|
||||
/* Memory mapping of Cortex-M0 Hardware */
|
||||
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
|
||||
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
|
||||
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
|
||||
|
||||
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
|
||||
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
|
||||
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
|
||||
|
||||
|
||||
/*@} */
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Hardware Abstraction Layer
|
||||
Core Function Interface contains:
|
||||
- Core NVIC Functions
|
||||
- Core SysTick Functions
|
||||
- Core Register Access Functions
|
||||
******************************************************************************/
|
||||
/**
|
||||
\defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ########################## NVIC functions #################################### */
|
||||
/**
|
||||
\ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
|
||||
\brief Functions that manage interrupts and exceptions via the NVIC.
|
||||
@{
|
||||
*/
|
||||
|
||||
/* Interrupt Priorities are WORD accessible only under ARMv6M */
|
||||
/* The following MACROS handle generation of the register offset and byte masks */
|
||||
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
|
||||
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
|
||||
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
|
||||
|
||||
|
||||
/**
|
||||
\brief Enable External Interrupt
|
||||
\details Enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Disable External Interrupt
|
||||
\details Disables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Pending Interrupt
|
||||
\details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return 0 Interrupt status is not pending.
|
||||
\return 1 Interrupt status is pending.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Pending Interrupt
|
||||
\details Sets the pending bit of an external interrupt.
|
||||
\param [in] IRQn Interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Clear Pending Interrupt
|
||||
\details Clears the pending bit of an external interrupt.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Interrupt Priority
|
||||
\details Sets the priority of an interrupt.
|
||||
\note The priority cannot be set for every core interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
|
||||
{
|
||||
if ((int32_t)(IRQn) < 0)
|
||||
{
|
||||
SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Interrupt Priority
|
||||
\details Reads the priority of an interrupt.
|
||||
The interrupt number can be positive to specify an external (device specific) interrupt,
|
||||
or negative to specify an internal (core) interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return Interrupt Priority.
|
||||
Value is aligned automatically to the implemented priority bits of the microcontroller.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
|
||||
{
|
||||
|
||||
if ((int32_t)(IRQn) < 0)
|
||||
{
|
||||
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief System Reset
|
||||
\details Initiates a system reset request to reset the MCU.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SystemReset(void)
|
||||
{
|
||||
__DSB(); /* Ensure all outstanding memory accesses included
|
||||
buffered write are completed before reset */
|
||||
SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
|
||||
SCB_AIRCR_SYSRESETREQ_Msk);
|
||||
__DSB(); /* Ensure completion of memory access */
|
||||
|
||||
for(;;) /* wait until reset */
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
/*@} end of CMSIS_Core_NVICFunctions */
|
||||
|
||||
|
||||
|
||||
/* ################################## SysTick function ############################################ */
|
||||
/**
|
||||
\ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
|
||||
\brief Functions that configure the System.
|
||||
@{
|
||||
*/
|
||||
|
||||
#if (__Vendor_SysTickConfig == 0U)
|
||||
|
||||
/**
|
||||
\brief System Tick Configuration
|
||||
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||
Counter is in free running mode to generate periodic interrupts.
|
||||
\param [in] ticks Number of ticks between two interrupts.
|
||||
\return 0 Function succeeded.
|
||||
\return 1 Function failed.
|
||||
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
|
||||
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
|
||||
must contain a vendor-specific implementation of this function.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
|
||||
{
|
||||
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
|
||||
{
|
||||
return (1UL); /* Reload value impossible */
|
||||
}
|
||||
|
||||
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
|
||||
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
|
||||
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
|
||||
return (0UL); /* Function successful */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of CMSIS_Core_SysTickFunctions */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CM0_H_DEPENDANT */
|
||||
|
||||
#endif /* __CMSIS_GENERIC */
|
87
NUC123/inc/core_cmFunc.h
Normal file
87
NUC123/inc/core_cmFunc.h
Normal file
@ -0,0 +1,87 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cmFunc.h
|
||||
* @brief CMSIS Cortex-M Core Function Access Header File
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- 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.
|
||||
- Neither the name of ARM 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 AND CONTRIBUTORS "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 COPYRIGHT HOLDERS AND CONTRIBUTORS 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.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CMFUNC_H
|
||||
#define __CORE_CMFUNC_H
|
||||
|
||||
|
||||
/* ########################### Core Function Access ########################### */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/*------------------ RealView Compiler -----------------*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
/*------------------ ARM Compiler V6 -------------------*/
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#include "cmsis_armcc_V6.h"
|
||||
|
||||
/*------------------ GNU Compiler ----------------------*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
/*------------------ ICC Compiler ----------------------*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
/*------------------ TI CCS Compiler -------------------*/
|
||||
#elif defined ( __TMS470__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
/*------------------ TASKING Compiler ------------------*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
/*------------------ COSMIC Compiler -------------------*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of CMSIS_Core_RegAccFunctions */
|
||||
|
||||
#endif /* __CORE_CMFUNC_H */
|
87
NUC123/inc/core_cmInstr.h
Normal file
87
NUC123/inc/core_cmInstr.h
Normal file
@ -0,0 +1,87 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cmInstr.h
|
||||
* @brief CMSIS Cortex-M Core Instruction Access Header File
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- 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.
|
||||
- Neither the name of ARM 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 AND CONTRIBUTORS "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 COPYRIGHT HOLDERS AND CONTRIBUTORS 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.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CMINSTR_H
|
||||
#define __CORE_CMINSTR_H
|
||||
|
||||
|
||||
/* ########################## Core Instruction Access ######################### */
|
||||
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
|
||||
Access to dedicated instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
/*------------------ RealView Compiler -----------------*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
/*------------------ ARM Compiler V6 -------------------*/
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#include "cmsis_armcc_V6.h"
|
||||
|
||||
/*------------------ GNU Compiler ----------------------*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
/*------------------ ICC Compiler ----------------------*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
/*------------------ TI CCS Compiler -------------------*/
|
||||
#elif defined ( __TMS470__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
/*------------------ TASKING Compiler ------------------*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
/*------------------ COSMIC Compiler -------------------*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
|
||||
|
||||
#endif /* __CORE_CMINSTR_H */
|
66
NUC123/inc/system_NUC123.h
Normal file
66
NUC123/inc/system_NUC123.h
Normal file
@ -0,0 +1,66 @@
|
||||
/**************************************************************************//**
|
||||
* @file system_NUC123.h
|
||||
* @version V3.0
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series CMSIS System Header File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __SYSTEM_NUC123_H
|
||||
#define __SYSTEM_NUC123_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Macro Definition */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
#ifndef DEBUG_PORT
|
||||
# define DEBUG_PORT UART0 /*!< Select Debug Port which is used for retarget.c to output debug message to UART */
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Define SYSCLK
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define __HXT (12000000UL) /*!< External Crystal Clock Frequency */
|
||||
#define __LXT (32768UL) /*!< External Crystal Clock Frequency 32.768KHz */
|
||||
#define __HIRC (22118400UL) /*!< Internal 22M RC Oscillator Frequency */
|
||||
#define __LIRC (10000UL) /*!< Internal 10K RC Oscillator Frequency */
|
||||
#define __HSI (50000000UL) /*!< PLL default output is 50MHz */
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
extern uint32_t CyclesPerUs; /*!< Cycles per micro second */
|
||||
extern uint32_t PllClock; /*!< PLL Output Clock Frequency */
|
||||
|
||||
/**
|
||||
* Initialize the system
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Setup the microcontroller system
|
||||
* Initialize GPIO directions and values
|
||||
*/
|
||||
extern void SystemInit(void);
|
||||
|
||||
|
||||
/**
|
||||
* Update SystemCoreClock variable
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Updates the SystemCoreClock with current core Clock
|
||||
* retrieved from CPU registers.
|
||||
*/
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
116
NUC123/semihosting.h
Normal file
116
NUC123/semihosting.h
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
#ifndef ARM_SEMIHOSTING_H_
|
||||
#define ARM_SEMIHOSTING_H_
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Semihosting operations.
|
||||
enum OperationNumber
|
||||
{
|
||||
// Regular operations
|
||||
SEMIHOSTING_EnterSVC = 0x17,
|
||||
SEMIHOSTING_ReportException = 0x18,
|
||||
SEMIHOSTING_SYS_CLOSE = 0x02,
|
||||
SEMIHOSTING_SYS_CLOCK = 0x10,
|
||||
SEMIHOSTING_SYS_ELAPSED = 0x30,
|
||||
SEMIHOSTING_SYS_ERRNO = 0x13,
|
||||
SEMIHOSTING_SYS_FLEN = 0x0C,
|
||||
SEMIHOSTING_SYS_GET_CMDLINE = 0x15,
|
||||
SEMIHOSTING_SYS_HEAPINFO = 0x16,
|
||||
SEMIHOSTING_SYS_ISERROR = 0x08,
|
||||
SEMIHOSTING_SYS_ISTTY = 0x09,
|
||||
SEMIHOSTING_SYS_OPEN = 0x01,
|
||||
SEMIHOSTING_SYS_READ = 0x06,
|
||||
SEMIHOSTING_SYS_READC = 0x07,
|
||||
SEMIHOSTING_SYS_REMOVE = 0x0E,
|
||||
SEMIHOSTING_SYS_RENAME = 0x0F,
|
||||
SEMIHOSTING_SYS_SEEK = 0x0A,
|
||||
SEMIHOSTING_SYS_SYSTEM = 0x12,
|
||||
SEMIHOSTING_SYS_TICKFREQ = 0x31,
|
||||
SEMIHOSTING_SYS_TIME = 0x11,
|
||||
SEMIHOSTING_SYS_TMPNAM = 0x0D,
|
||||
SEMIHOSTING_SYS_WRITE = 0x05,
|
||||
SEMIHOSTING_SYS_WRITEC = 0x03,
|
||||
SEMIHOSTING_SYS_WRITE0 = 0x04,
|
||||
|
||||
// Codes returned by SEMIHOSTING_ReportException
|
||||
ADP_Stopped_ApplicationExit = ((2 << 16) + 38),
|
||||
ADP_Stopped_RunTimeError = ((2 << 16) + 35),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// SWI numbers and reason codes for RDI (Angel) monitors.
|
||||
#define AngelSWI_ARM 0x123456
|
||||
#ifdef __thumb__
|
||||
#define AngelSWI 0xAB
|
||||
#else
|
||||
#define AngelSWI AngelSWI_ARM
|
||||
#endif
|
||||
// For thumb only architectures use the BKPT instruction instead of SWI.
|
||||
#if defined(__ARM_ARCH_7M__) \
|
||||
|| defined(__ARM_ARCH_7EM__) \
|
||||
|| defined(__ARM_ARCH_6M__)
|
||||
#define AngelSWIInsn "bkpt"
|
||||
#define AngelSWIAsm bkpt
|
||||
#else
|
||||
#define AngelSWIInsn "swi"
|
||||
#define AngelSWIAsm swi
|
||||
#endif
|
||||
|
||||
#if defined(OS_DEBUG_SEMIHOSTING_FAULTS)
|
||||
// Testing the local semihosting handler cannot use another BKPT, since this
|
||||
// configuration cannot trigger HaedFault exceptions while the debugger is
|
||||
// connected, so we use an illegal op code, that will trigger an
|
||||
// UsageFault exception.
|
||||
#define AngelSWITestFault "setend be"
|
||||
#define AngelSWITestFaultOpCode (0xB658)
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
__attribute__ ((always_inline))
|
||||
call_host (int reason, void* arg)
|
||||
{
|
||||
int value;
|
||||
asm volatile (
|
||||
|
||||
" mov r0, %[rsn] \n"
|
||||
" mov r1, %[arg] \n"
|
||||
#if defined(OS_DEBUG_SEMIHOSTING_FAULTS)
|
||||
" " AngelSWITestFault " \n"
|
||||
#else
|
||||
" " AngelSWIInsn " %[swi] \n"
|
||||
#endif
|
||||
" mov %[val], r0"
|
||||
|
||||
: [val] "=r" (value) /* Outputs */
|
||||
: [rsn] "r" (reason), [arg] "r" (arg), [swi] "i" (AngelSWI) /* Inputs */
|
||||
: "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
|
||||
// Clobbers r0 and r1, and lr if in supervisor mode
|
||||
);
|
||||
|
||||
// Accordingly to page 13-77 of ARM DUI 0040D other registers
|
||||
// can also be clobbered. Some memory positions may also be
|
||||
// changed by a system call, so they should not be kept in
|
||||
// registers. Note: we are assuming the manual is right and
|
||||
// Angel is respecting the APCS.
|
||||
return value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Function used in _exit() to return the status code as Angel exception.
|
||||
static inline void
|
||||
__attribute__ ((always_inline,noreturn))
|
||||
report_exception (int reason)
|
||||
{
|
||||
call_host (SEMIHOSTING_ReportException, (void*) reason);
|
||||
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#endif // ARM_SEMIHOSTING_H_
|
232
NUC123/startup_NUC123.s
Normal file
232
NUC123/startup_NUC123.s
Normal file
@ -0,0 +1,232 @@
|
||||
.syntax unified
|
||||
.arch armv8 - m.base
|
||||
|
||||
.section .stack
|
||||
.align 3
|
||||
#ifndef Stack_Size
|
||||
.equ Stack_Size, 0x00000400
|
||||
#endif
|
||||
.global __StackTop
|
||||
.global __StackLimit
|
||||
__StackLimit:
|
||||
.space Stack_Size
|
||||
.size __StackLimit, . - __StackLimit
|
||||
__StackTop:
|
||||
.size __StackTop, . - __StackTop
|
||||
|
||||
.section .heap
|
||||
.align 3
|
||||
#ifndef Heap_Size
|
||||
.equ Heap_Size, 0x00000100
|
||||
#endif
|
||||
|
||||
.global __HeapBase
|
||||
.global __HeapLimit
|
||||
__HeapBase:
|
||||
.if Heap_Size
|
||||
.space Heap_Size
|
||||
.endif
|
||||
.size __HeapBase, . - __HeapBase
|
||||
__HeapLimit:
|
||||
.size __HeapLimit, . - __HeapLimit
|
||||
|
||||
.section .vectors
|
||||
.align 2
|
||||
.global __Vectors
|
||||
__Vectors:
|
||||
.long __StackTop /* Top of Stack */
|
||||
.long Reset_Handler /* Reset Handler */
|
||||
.long NMI_Handler /* NMI Handler */
|
||||
.long HardFault_Handler /* Hard Fault Handler */
|
||||
.long 0 /* Reserved */
|
||||
.long 0 /* Reserved */
|
||||
.long 0 /* Reserved */
|
||||
.long 0 /* Reserved */
|
||||
.long 0 /* Reserved */
|
||||
.long 0 /* Reserved */
|
||||
.long 0 /* Reserved */
|
||||
.long SVC_Handler /* SVCall Handler */
|
||||
.long 0 /* Reserved */
|
||||
.long 0 /* Reserved */
|
||||
.long PendSV_Handler /* PendSV Handler */
|
||||
.long SysTick_Handler /* SysTick Handler */
|
||||
|
||||
/* External interrupts */
|
||||
|
||||
.long BOD_IRQHandler
|
||||
.long WDT_IRQHandler
|
||||
.long EINT0_IRQHandler
|
||||
.long EINT1_IRQHandler
|
||||
.long GPAB_IRQHandler
|
||||
.long GPCDF_IRQHandler
|
||||
.long PWMA_IRQHandler
|
||||
.long Default_Handler
|
||||
.long TMR0_IRQHandler
|
||||
.long TMR1_IRQHandler
|
||||
.long TMR2_IRQHandler
|
||||
.long TMR3_IRQHandler
|
||||
.long UART0_IRQHandler
|
||||
.long UART1_IRQHandler
|
||||
.long SPI0_IRQHandler
|
||||
.long SPI1_IRQHandler
|
||||
.long SPI2_IRQHandler
|
||||
.long SPI3_IRQHandler
|
||||
.long I2C0_IRQHandler
|
||||
.long I2C1_IRQHandler
|
||||
.long CAN0_IRQHandler
|
||||
.long CAN1_IRQHandler
|
||||
.long SC012_IRQHandler
|
||||
.long USBD_IRQHandler
|
||||
.long PS2_IRQHandler
|
||||
.long ACMP_IRQHandler
|
||||
.long PDMA_IRQHandler
|
||||
.long I2S_IRQHandler
|
||||
.long PWRWU_IRQHandler
|
||||
.long ADC_IRQHandler
|
||||
.long Default_Handler
|
||||
.long RTC_IRQHandler
|
||||
|
||||
.size __Vectors, . - __Vectors
|
||||
|
||||
|
||||
|
||||
.text
|
||||
.thumb
|
||||
.thumb_func
|
||||
.align 2
|
||||
.global Reset_Handler
|
||||
.type Reset_Handler, % function
|
||||
|
||||
|
||||
Reset_Handler:
|
||||
/* Single section scheme.
|
||||
*
|
||||
* The ranges of copy from/to are specified by following symbols
|
||||
* __etext: LMA of start of the section to copy from. Usually end of text
|
||||
* __data_start__: VMA of start of the section to copy to
|
||||
* __data_end__: VMA of end of the section to copy to
|
||||
*
|
||||
* All addresses must be aligned to 4 bytes boundary.
|
||||
*/
|
||||
ldr r1, = __etext
|
||||
ldr r2, = __data_start__
|
||||
ldr r3, = __data_end__
|
||||
|
||||
subs r3, r2
|
||||
ble .L_loop1_done
|
||||
.L_loop1:
|
||||
subs r3, #4
|
||||
ldr r0, [r1, r3]
|
||||
str r0, [r2, r3]
|
||||
bgt .L_loop1
|
||||
.L_loop1_done:
|
||||
|
||||
/* Single BSS section scheme.
|
||||
*
|
||||
* The BSS section is specified by following symbols
|
||||
* __bss_start__: start of the BSS section.
|
||||
* __bss_end__: end of the BSS section.
|
||||
*
|
||||
* Both addresses must be aligned to 4 bytes boundary.
|
||||
*/
|
||||
ldr r1, = __bss_start__
|
||||
ldr r2, = __bss_end__
|
||||
|
||||
movs r0, 0
|
||||
|
||||
subs r2, r1
|
||||
ble .L_loop3_done
|
||||
.L_loop3:
|
||||
subs r2, #4
|
||||
str r0, [r1, r2]
|
||||
bgt .L_loop3
|
||||
.L_loop3_done:
|
||||
|
||||
/* There's no SystemInit for NUC123, so no point making a pointless call */
|
||||
// bl SystemInit
|
||||
|
||||
#ifndef __ENTRY
|
||||
#define __ENTRY _entry
|
||||
#endif
|
||||
bl __ENTRY
|
||||
|
||||
.pool
|
||||
.size Reset_Handler, . - Reset_Handler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak Default_Handler
|
||||
.type Default_Handler, % function
|
||||
|
||||
Default_Handler:
|
||||
b .
|
||||
.size Default_Handler, . - Default_Handler
|
||||
|
||||
/* Macro to define default handlers. Default handler
|
||||
* will be weak symbol and just dead loops. They can be
|
||||
* overwritten by other handlers */
|
||||
|
||||
.macro def_irq_handler handler_name
|
||||
.weak \handler_name
|
||||
.set \handler_name, Default_Handler
|
||||
.endm
|
||||
|
||||
def_irq_handler NMI_Handler
|
||||
def_irq_handler HardFault_Handler
|
||||
def_irq_handler SVC_Handler
|
||||
def_irq_handler PendSV_Handler
|
||||
def_irq_handler SysTick_Handler
|
||||
|
||||
|
||||
def_irq_handler BOD_IRQHandler
|
||||
def_irq_handler WDT_IRQHandler
|
||||
def_irq_handler EINT0_IRQHandler
|
||||
def_irq_handler EINT1_IRQHandler
|
||||
def_irq_handler GPAB_IRQHandler
|
||||
def_irq_handler GPCDF_IRQHandler
|
||||
def_irq_handler PWMA_IRQHandler
|
||||
def_irq_handler TMR0_IRQHandler
|
||||
def_irq_handler TMR1_IRQHandler
|
||||
def_irq_handler TMR2_IRQHandler
|
||||
def_irq_handler TMR3_IRQHandler
|
||||
def_irq_handler UART0_IRQHandler
|
||||
def_irq_handler UART1_IRQHandler
|
||||
def_irq_handler SPI0_IRQHandler
|
||||
def_irq_handler SPI1_IRQHandler
|
||||
def_irq_handler SPI2_IRQHandler
|
||||
def_irq_handler SPI3_IRQHandler
|
||||
def_irq_handler I2C0_IRQHandler
|
||||
def_irq_handler I2C1_IRQHandler
|
||||
def_irq_handler CAN0_IRQHandler
|
||||
def_irq_handler CAN1_IRQHandler
|
||||
def_irq_handler SC012_IRQHandler
|
||||
def_irq_handler USBD_IRQHandler
|
||||
def_irq_handler PS2_IRQHandler
|
||||
def_irq_handler ACMP_IRQHandler
|
||||
def_irq_handler PDMA_IRQHandler
|
||||
def_irq_handler I2S_IRQHandler
|
||||
def_irq_handler PWRWU_IRQHandler
|
||||
def_irq_handler ADC_IRQHandler
|
||||
def_irq_handler RTC_IRQHandler
|
||||
|
||||
|
||||
/* ;int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0) */
|
||||
.align 2
|
||||
.thumb_func
|
||||
.type SH_DoCommand, % function
|
||||
|
||||
SH_DoCommand:
|
||||
|
||||
BKPT 0xAB /* ; Wait ICE or HardFault */
|
||||
//LDR R3, = SH_Return
|
||||
MOV R4, lr
|
||||
BLX R3 /* ; Call SH_Return. The return value is in R0 */
|
||||
BX R4 /* ; Return value = R0 */
|
||||
.size SH_DoCommand, . - SH_DoCommand
|
||||
|
||||
.align 2
|
||||
.thumb_func
|
||||
.global __PC
|
||||
.type __PC, % function
|
||||
|
||||
.end
|
80
NUC123/system_NUC123.c
Normal file
80
NUC123/system_NUC123.c
Normal file
@ -0,0 +1,80 @@
|
||||
/**************************************************************************//**
|
||||
* @file system_NUC123.c
|
||||
* @version V3.0
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/07/02 11:21a $
|
||||
* @brief NUC123 Series CMSIS System File
|
||||
*
|
||||
* @note
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "NUC123.h"
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Clock Variable definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint32_t SystemCoreClock = __HSI; /*!< System Clock Frequency (Core Clock) */
|
||||
uint32_t CyclesPerUs = (__HSI / 1000000); /* Cycles per micro second */
|
||||
uint32_t PllClock = __HSI; /*!< PLL Output Clock Frequency */
|
||||
uint32_t gau32ClkSrcTbl[] = {__HXT, NULL, __HSI, __LIRC, NULL, NULL, NULL, __HIRC};
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Clock functions
|
||||
This function is used to update the variable SystemCoreClock
|
||||
and must be called whenever the core clock is changed.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void SystemCoreClockUpdate(void) /* Get Core Clock Frequency */
|
||||
{
|
||||
uint32_t u32Freq, u32ClkSrc;
|
||||
uint32_t u32HclkDiv;
|
||||
|
||||
/* Update PLL Clock */
|
||||
PllClock = CLK_GetPLLClockFreq();
|
||||
|
||||
u32ClkSrc = CLK->CLKSEL0 & CLK_CLKSEL0_HCLK_S_Msk;
|
||||
|
||||
if(u32ClkSrc == CLK_CLKSEL0_HCLK_S_PLL)
|
||||
{
|
||||
/* Use PLL clock */
|
||||
u32Freq = PllClock;
|
||||
}
|
||||
else if(u32ClkSrc == CLK_CLKSEL0_HCLK_S_PLL_DIV2)
|
||||
{
|
||||
/* Use PLL/2 clock */
|
||||
u32Freq = PllClock >> 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the clock sources directly */
|
||||
u32Freq = gau32ClkSrcTbl[u32ClkSrc];
|
||||
}
|
||||
|
||||
u32HclkDiv = (CLK->CLKDIV & CLK_CLKDIV_HCLK_N_Msk) + 1;
|
||||
|
||||
/* Update System Core Clock */
|
||||
SystemCoreClock = u32Freq / u32HclkDiv;
|
||||
|
||||
CyclesPerUs = (SystemCoreClock + 500000) / 1000000;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Function: SystemInit */
|
||||
/* */
|
||||
/* Parameters: */
|
||||
/* None */
|
||||
/* */
|
||||
/* Returns: */
|
||||
/* None */
|
||||
/* */
|
||||
/* Description: */
|
||||
/* The necessary initialization of system. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
void SystemInit(void)
|
||||
{
|
||||
}
|
34
README.md
Normal file
34
README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# TASOLLER Custom Firmware (Host MCU - Application ROM)
|
||||
|
||||
See [Development](./Development.md) for development information.
|
||||
|
||||
Yes, the code is a mess. I just wanted to get something onto git y'know :).
|
||||
|
||||
## Configuration
|
||||
Hold FN2 for configuration. It is not the same as stock DAO.
|
||||
|
||||
- Pad 1/2 (cell 0): Left wing colour
|
||||
- Pad 3/4 (cell 1): Ground colour
|
||||
- Pad 5/6 (cell 2): Ground colour when pressed, and separator colour
|
||||
- Pad 7/8 (cell 3): Right wing colour
|
||||
- Pad 9/10 (cell 4): No function
|
||||
- Pad 11/12 (cell 5): Toggle rainbow effect on/off
|
||||
- Pad 13/14 (cell 6): Increase/decrease ground brightness
|
||||
- Pad 15/16 (cell 7): Increase/decrease wing brightness
|
||||
- Pad 17/18 (cell 8): No function
|
||||
- Pad 19/20 (cell 9): No function
|
||||
- Pad 21/22 (cell 10): No function
|
||||
- Pad 23/24 (cell 11): No function
|
||||
- Pad 25/26 (cell 12): Increase/decrease sensitivity
|
||||
- Pad 27/28 (cell 13): No function
|
||||
- Pad 29/30 (cell 14): Toggle HID keyboard mode
|
||||
- Pad 31/32 (cell 15): Toggle IO4 emulation mode
|
||||
|
||||
## Calibration
|
||||
Make sure no hands or objects are near the slider before starting calibration.
|
||||
|
||||
Hold FN1 for two seconds; the slider will flash red for a few seconds, then fill up with a blue bar.
|
||||
|
||||
The slider will then briefly flash green. After this, begin to rub your hands across the slider as much as possible! The cells will turn increasingly green; the greener you can get them the better. Once the dividers have turned green you can save your calibration by pressing FN2.
|
||||
|
||||
**Note:** Calibration is a separate process to adjusting the sensor sensitivity. It is recommended to re-calibrate after adjustment of sensitivity. For the best performance, run a re-calibration before every play session to account for changes in your room's temperature and humidity.
|
17
flash.cmd
Normal file
17
flash.cmd
Normal file
@ -0,0 +1,17 @@
|
||||
@..\..\openocd-0.12.0-3\bin\openocd.exe -f interface/stlink-v2.cfg -f ..\..\nucxxx.cfg ^
|
||||
-c "SysReset halt" ^
|
||||
-c "flash read_bank 1 dataflash.bin" ^
|
||||
-c "ChipErase" ^
|
||||
-c "exit"
|
||||
|
||||
@..\..\openocd-0.12.0-3\bin\openocd.exe -f interface/stlink-v2.cfg -f ..\..\nucxxx.cfg ^
|
||||
-c "SysReset halt" ^
|
||||
-c "WriteConfigRegs 0xFFFFFF7F 0xFFFFFFFF" ^
|
||||
-c "ReadConfigRegs" ^
|
||||
-c "program ../bootloader/host_bl.bin 0x100000" ^
|
||||
-c "program host_aprom.bin 0" ^
|
||||
-c "program dataflash.bin 0x1F000" ^
|
||||
-c "SysReset aprom run" ^
|
||||
-c "exit"
|
||||
|
||||
@del dataflash.bin
|
40
generic.mk
Normal file
40
generic.mk
Normal file
@ -0,0 +1,40 @@
|
||||
C_SOURCES = $(wildcard $(SRC_DIR)/*.c)
|
||||
ASM_SOURCES = $(wildcard $(SRC_DIR)/*.s)
|
||||
|
||||
C_OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(C_SOURCES))
|
||||
ASM_OBJECTS = $(patsubst $(SRC_DIR)/%.s,$(OBJ_DIR)/%.o,$(ASM_SOURCES))
|
||||
|
||||
OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS) $(DEVICE_OBJECTS)
|
||||
|
||||
all: $(BINARY_NAME).bin
|
||||
.DEFAULT_GOAL=all
|
||||
|
||||
# Speed up compiles by not deleting these
|
||||
.PRECIOUS: $(OBJ_DIR)/%.o
|
||||
.PRECIOUS: $(OBJ_DIR)/%.elf
|
||||
|
||||
%.bin: $(OBJ_DIR)/%.elf
|
||||
@echo Creating binary $@
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
|
||||
$(OBJ_DIR)/%.elf: $(OBJECTS)
|
||||
@echo Linking $@
|
||||
@$(LD) $(LDFLAGS) -o $@ $^
|
||||
@echo ==============================================================================
|
||||
@$(SIZE) $@
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||
@echo Compiling $<
|
||||
@$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
|
||||
@echo Compiling $<
|
||||
@$(AS) $(ASFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
-del $(BINARY_NAME).bin
|
||||
-rmdir /Q /S $(OBJ_DIR)
|
||||
|
||||
$(shell mkdir $(OBJ_DIR))
|
||||
|
||||
.PHONY: all clean
|
0
picolibc/.gitkeep
Normal file
0
picolibc/.gitkeep
Normal file
4
run.cmd
Normal file
4
run.cmd
Normal file
@ -0,0 +1,4 @@
|
||||
@..\..\openocd-0.12.0-3\bin\openocd.exe -f interface/stlink-v2.cfg -f ..\..\nucxxx.cfg ^
|
||||
-c "SysReset halt" ^
|
||||
-c "SysReset aprom run" ^
|
||||
-c "exit"
|
6
src/delay.s
Normal file
6
src/delay.s
Normal file
@ -0,0 +1,6 @@
|
||||
.syntax unified
|
||||
.global DelayCycles
|
||||
DelayCycles:
|
||||
subs r0, r0, #1
|
||||
bcs DelayCycles
|
||||
bx lr
|
466
src/descriptors.c
Normal file
466
src/descriptors.c
Normal file
@ -0,0 +1,466 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "tasoller.h"
|
||||
|
||||
static const uint8_t IO4_ReportDescriptor[] = {
|
||||
// Analog input (28 bytes)
|
||||
HID_USAGE_PAGE(GENERIC_DESKTOP),
|
||||
HID_USAGE(JOYSTICK),
|
||||
HID_COLLECTION(APPLICATION),
|
||||
HID_REPORT_ID(HID_REPORT_ID_IO4),
|
||||
HID_USAGE(POINTER),
|
||||
HID_COLLECTION(PHYSICAL),
|
||||
// 8 ADC channels
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
// 4 Rotary channels
|
||||
HID_USAGE(RX),
|
||||
HID_USAGE(RY),
|
||||
HID_USAGE(RX),
|
||||
HID_USAGE(RY),
|
||||
// 2 Coin chutes
|
||||
HID_USAGE(SLIDER),
|
||||
HID_USAGE(SLIDER),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(4, 65534),
|
||||
HID_PHYSICAL_MINIMUM(1, 0),
|
||||
HID_PHYSICAL_MAXIMUM(4, 65534),
|
||||
HID_REPORT_COUNT(14),
|
||||
HID_REPORT_SIZE(16),
|
||||
HID_INPUT(DATA, VARIABLE, ABSOLUTE, NO_WRAP, LINEAR, PREFERRED_STATE, NO_NULL_POSITION),
|
||||
HID_END_COLLECTION(PHYSICAL),
|
||||
|
||||
// Digital input (6 bytes = 48 bits)
|
||||
// [ 0~15]: Player 1 buttons
|
||||
// [16~31]: Player 2 buttons
|
||||
// [32~39]: System status
|
||||
// -> 01h: ?
|
||||
// -> 02h: ?
|
||||
// -> 04h: ?
|
||||
// -> 08h: ?
|
||||
// -> 10h: Comm timeout set
|
||||
// -> 20h: Sampling count set
|
||||
// [40~47]: USB status
|
||||
// -> 01h: ?
|
||||
// -> 02h: ?
|
||||
// -> 04h: ? (is set on timeout)
|
||||
HID_USAGE_PAGE(SIMULATION),
|
||||
HID_USAGE_PAGE(BUTTONS),
|
||||
HID_USAGE_MINIMUM(1, 1),
|
||||
HID_USAGE_MAXIMUM(1, 48),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(1, 1),
|
||||
HID_PHYSICAL_MAXIMUM(1, 1),
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_REPORT_COUNT(48),
|
||||
HID_INPUT(DATA, VARIABLE, ABSOLUTE, NO_WRAP, LINEAR, PREFERRED_STATE, NO_NULL_POSITION),
|
||||
|
||||
// Reserved for future use. Pad with null. (29 bytes)
|
||||
HID_USAGE(UNDEFINED),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_REPORT_COUNT(29),
|
||||
HID_INPUT(CONSTANT, ARRAY, ABSOLUTE, NO_WRAP, LINEAR, PREFERRED_STATE, NO_NULL_POSITION),
|
||||
HID_USAGE_PAGE2(2, 0xFFA0), // Vendor defined FF0A
|
||||
HID_USAGE(UNDEFINED),
|
||||
|
||||
// General-purpose commands to the board. First byte is the command, then 62 data byte
|
||||
HID_REPORT_ID(HID_REPORT_ID_IO4_CMD),
|
||||
HID_COLLECTION(APPLICATION),
|
||||
HID_USAGE(UNDEFINED),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(1, 255),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_REPORT_COUNT(63),
|
||||
HID_OUTPUT(DATA, VARIABLE, ABSOLUTE, NO_WRAP, LINEAR, PREFERRED_STATE, NO_NULL_POSITION,
|
||||
NON_VOLATILE),
|
||||
HID_END_COLLECTION(APPLICATION),
|
||||
|
||||
HID_END_COLLECTION(APPLICATION),
|
||||
};
|
||||
|
||||
static const uint8_t Keyboard_ReportDescriptor[] = {
|
||||
// Keyboard input descriptor
|
||||
HID_USAGE_PAGE(GENERIC_DESKTOP),
|
||||
HID_USAGE(KEYBOARD),
|
||||
HID_COLLECTION(APPLICATION),
|
||||
HID_REPORT_ID(HID_REPORT_ID_KEYBOARD),
|
||||
|
||||
HID_USAGE_PAGE(KEYBOARD),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(1, 231),
|
||||
HID_USAGE_MINIMUM(1, 0),
|
||||
HID_USAGE_MAXIMUM(1, 231),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_REPORT_COUNT(NUM_FN + NUM_AIR + NUM_GROUND),
|
||||
HID_INPUT(DATA, ARRAY, ABSOLUTE),
|
||||
|
||||
HID_END_COLLECTION(APPLICATION),
|
||||
|
||||
// Debugging reports descriptors (they dump the raw PSoC data)
|
||||
HID_USAGE_PAGE(GENERIC_DESKTOP),
|
||||
HID_USAGE(JOYSTICK),
|
||||
HID_COLLECTION(APPLICATION),
|
||||
|
||||
HID_REPORT_ID(HID_REPORT_ID_DEBUG_A),
|
||||
HID_USAGE(POINTER),
|
||||
HID_COLLECTION(LOGICAL),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(4, 0xffff),
|
||||
HID_PHYSICAL_MINIMUM(1, 0),
|
||||
HID_PHYSICAL_MAXIMUM(4, 0xffff),
|
||||
HID_REPORT_COUNT(16),
|
||||
HID_REPORT_SIZE(16),
|
||||
HID_INPUT(DATA, VARIABLE, ABSOLUTE),
|
||||
HID_END_COLLECTION(LOGICAL),
|
||||
|
||||
HID_REPORT_ID(HID_REPORT_ID_DEBUG_B),
|
||||
HID_USAGE(POINTER),
|
||||
HID_COLLECTION(LOGICAL),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(4, 0xffff),
|
||||
HID_PHYSICAL_MINIMUM(1, 0),
|
||||
HID_PHYSICAL_MAXIMUM(4, 0xffff),
|
||||
HID_REPORT_SIZE(16),
|
||||
HID_REPORT_COUNT(16),
|
||||
HID_INPUT(DATA, VARIABLE, ABSOLUTE),
|
||||
HID_END_COLLECTION(LOGICAL),
|
||||
|
||||
HID_END_COLLECTION(APPLICATION),
|
||||
};
|
||||
|
||||
static const uint8_t Debug_ReportDescriptor[] = {
|
||||
HID_USAGE_PAGE(GENERIC_DESKTOP),
|
||||
HID_USAGE(JOYSTICK),
|
||||
HID_COLLECTION(APPLICATION),
|
||||
|
||||
HID_REPORT_ID(HID_REPORT_ID_DEBUG_A),
|
||||
HID_USAGE(POINTER),
|
||||
HID_COLLECTION(LOGICAL),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(4, 0xffff),
|
||||
HID_PHYSICAL_MINIMUM(1, 0),
|
||||
HID_PHYSICAL_MAXIMUM(4, 0xffff),
|
||||
HID_REPORT_COUNT(16),
|
||||
HID_REPORT_SIZE(16),
|
||||
HID_INPUT(DATA, VARIABLE, ABSOLUTE),
|
||||
HID_END_COLLECTION(LOGICAL),
|
||||
|
||||
HID_REPORT_ID(HID_REPORT_ID_DEBUG_B),
|
||||
HID_USAGE(POINTER),
|
||||
HID_COLLECTION(LOGICAL),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_USAGE(X),
|
||||
HID_USAGE(Y),
|
||||
HID_LOGICAL_MINIMUM(1, 0),
|
||||
HID_LOGICAL_MAXIMUM(4, 0xffff),
|
||||
HID_PHYSICAL_MINIMUM(1, 0),
|
||||
HID_PHYSICAL_MAXIMUM(4, 0xffff),
|
||||
HID_REPORT_SIZE(16),
|
||||
HID_REPORT_COUNT(16),
|
||||
HID_INPUT(DATA, VARIABLE, ABSOLUTE),
|
||||
HID_END_COLLECTION(LOGICAL),
|
||||
|
||||
HID_END_COLLECTION(APPLICATION),
|
||||
};
|
||||
|
||||
usb_device_descr_t gIO4DeviceDescriptor = {
|
||||
sizeof(usb_device_descr_t),
|
||||
DESC_DEVICE,
|
||||
0x0200,
|
||||
USB_CLASS_UNSPECIFIED,
|
||||
0,
|
||||
0,
|
||||
EP0_MAX_PKT_SIZE,
|
||||
// Unfortunately we're forced to always use this VID if we want IO4 support to work
|
||||
IO4_VID,
|
||||
IO4_PID,
|
||||
0x0100,
|
||||
USB_STRING_VENDOR,
|
||||
USB_STRING_PRODUCT,
|
||||
USB_STRING_SERIAL,
|
||||
1,
|
||||
};
|
||||
|
||||
// We have a unified descriptor that covers
|
||||
typedef struct __attribute__((packed)) {
|
||||
const usb_desc_config_t Config;
|
||||
|
||||
const usb_desc_iad_t CDC_IAD;
|
||||
|
||||
const usb_desc_interface_t CDC_CMD_Interface;
|
||||
const usb_desc_cdc_header_t CDC_Header;
|
||||
const usb_desc_cdc_call_t CDC_Call;
|
||||
const usb_desc_cdc_acm_t CDC_ACM;
|
||||
const usb_desc_cdc_union_t CDC_Union;
|
||||
const usb_desc_endpoint_t CDC_CMD_Endpoint;
|
||||
|
||||
const usb_desc_interface_t CDC_Interface;
|
||||
const usb_desc_endpoint_t CDC_IN_Endpoint;
|
||||
const usb_desc_endpoint_t CDC_OUT_Endpoint;
|
||||
|
||||
const usb_desc_interface_t HID_IO4_Interface;
|
||||
const usb_desc_hid_t HID_IO4;
|
||||
const usb_desc_endpoint_t HID_IO4_EndpointIn;
|
||||
/**
|
||||
* We're meant to have an OUT endpoint for IO4, but IO4 uses the Win32 WriteFile API, which will
|
||||
* happily fall back to SET_REPORT calls on the control endpoints if there's no OUT endpoint.
|
||||
*
|
||||
* Chunithm never uses the output capability of IO4, so we have no high-frequency data that
|
||||
* might choke our control endpoints--we just need to support the initial configuration packets.
|
||||
*/
|
||||
// const usb_desc_endpoint_t HID_EndpointOut;
|
||||
|
||||
const usb_desc_interface_t HID_Misc_Interface;
|
||||
const usb_desc_hid_t HID_Misc;
|
||||
const usb_desc_endpoint_t HID_Misc_EndpointIn;
|
||||
const usb_desc_endpoint_t HID_Misc_EndpointOut;
|
||||
} config_desc_t;
|
||||
static const config_desc_t gConfigDescriptor = {
|
||||
// Config
|
||||
{
|
||||
sizeof(usb_desc_config_t),
|
||||
DESC_CONFIG,
|
||||
sizeof gConfigDescriptor,
|
||||
_USBD_ITF_MAX,
|
||||
0x01,
|
||||
0x00,
|
||||
0x80 | (USBD_SELF_POWERED << 6) | (USBD_REMOTE_WAKEUP << 5),
|
||||
USBD_MAX_POWER,
|
||||
},
|
||||
|
||||
// CDC IAD
|
||||
{
|
||||
sizeof(usb_desc_iad_t),
|
||||
DESC_IAD,
|
||||
USBD_ITF_CDC_CMD,
|
||||
2,
|
||||
USB_CLASS_CDC,
|
||||
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
|
||||
CDC_COMM_PROTOCOL_NONE,
|
||||
USB_STRING_CDC,
|
||||
},
|
||||
|
||||
// CDC Control
|
||||
{
|
||||
sizeof(usb_desc_interface_t),
|
||||
DESC_INTERFACE,
|
||||
USBD_ITF_CDC_CMD,
|
||||
0x00,
|
||||
0x01,
|
||||
USB_CLASS_CDC,
|
||||
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
|
||||
CDC_COMM_PROTOCOL_NONE,
|
||||
0,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_cdc_header_t),
|
||||
DESC_CS_INTERFACE,
|
||||
CDC_FUNC_DESC_HEADER,
|
||||
0x0110,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_cdc_call_t),
|
||||
DESC_CS_INTERFACE,
|
||||
CDC_FUNC_DESC_CALL_MANAGEMENT,
|
||||
0,
|
||||
USBD_ITF_CDC_DAT,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_cdc_acm_t),
|
||||
DESC_CS_INTERFACE,
|
||||
CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT,
|
||||
// Supports set line coding
|
||||
2,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_cdc_union_t),
|
||||
DESC_CS_INTERFACE,
|
||||
CDC_FUNC_DESC_UNION,
|
||||
USBD_ITF_CDC_CMD,
|
||||
USBD_ITF_CDC_DAT,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_endpoint_t),
|
||||
DESC_ENDPOINT,
|
||||
USBD_CDC_EP_CMD,
|
||||
EP_INT,
|
||||
USBD_CDC_CMD_MAX_SIZE,
|
||||
1,
|
||||
},
|
||||
// CDC Data
|
||||
{
|
||||
sizeof(usb_desc_interface_t),
|
||||
DESC_INTERFACE,
|
||||
USBD_ITF_CDC_DAT,
|
||||
0,
|
||||
2,
|
||||
USB_CLASS_CDC_DATA,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_endpoint_t),
|
||||
DESC_ENDPOINT,
|
||||
USBD_CDC_EP_IN,
|
||||
EP_BULK,
|
||||
USBD_CDC_IN_MAX_SIZE,
|
||||
0,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_endpoint_t),
|
||||
DESC_ENDPOINT,
|
||||
USBD_CDC_EP_OUT,
|
||||
EP_BULK,
|
||||
USBD_CDC_OUT_MAX_SIZE,
|
||||
0,
|
||||
},
|
||||
|
||||
// IO4 HID
|
||||
{
|
||||
sizeof(usb_desc_interface_t),
|
||||
DESC_INTERFACE,
|
||||
USBD_ITF_HID_IO4,
|
||||
0x00,
|
||||
0x01,
|
||||
USB_CLASS_HID,
|
||||
0,
|
||||
HID_KEYBOARD,
|
||||
USB_STRING_HID_IO4,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_hid_t),
|
||||
DESC_HID,
|
||||
0x0110,
|
||||
0x00,
|
||||
0x01,
|
||||
DESC_HID_RPT,
|
||||
sizeof IO4_ReportDescriptor,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_endpoint_t),
|
||||
DESC_ENDPOINT,
|
||||
USBD_HID_IO4_EP_IN,
|
||||
EP_INT,
|
||||
USBD_HID_BUF_LEN,
|
||||
HID_IO4_INT_IN_INTERVAL,
|
||||
},
|
||||
|
||||
// Misc HID
|
||||
{
|
||||
sizeof(usb_desc_interface_t),
|
||||
DESC_INTERFACE,
|
||||
USBD_ITF_HID_MISC,
|
||||
0x00,
|
||||
0x01,
|
||||
USB_CLASS_HID,
|
||||
0,
|
||||
HID_KEYBOARD,
|
||||
USB_STRING_HID_MISC,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_hid_t),
|
||||
DESC_HID,
|
||||
0x0110,
|
||||
0x00,
|
||||
0x01,
|
||||
DESC_HID_RPT,
|
||||
sizeof Keyboard_ReportDescriptor,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_endpoint_t),
|
||||
DESC_ENDPOINT,
|
||||
USBD_HID_MISC_EP_IN,
|
||||
EP_INT,
|
||||
USBD_HID_BUF_LEN,
|
||||
HID_DEFAULT_INT_IN_INTERVAL,
|
||||
},
|
||||
{
|
||||
sizeof(usb_desc_endpoint_t),
|
||||
DESC_ENDPOINT,
|
||||
USBD_HID_MISC_EP_OUT,
|
||||
EP_INT,
|
||||
USBD_HID_BUF_LEN,
|
||||
HID_DEFAULT_INT_IN_INTERVAL,
|
||||
},
|
||||
};
|
||||
|
||||
const char* gszVendorInitial = "Bottersnike";
|
||||
const char* gszVendor = IO4_VENDOR;
|
||||
const char* gszProduct = "TASOLLER";
|
||||
|
||||
const usb_device_descr_t *gpDeviceDescriptor = &gIO4DeviceDescriptor;
|
||||
const usb_desc_config_t *gpConfigDescriptor = &gConfigDescriptor.Config;
|
||||
const uint32_t gu32HidDescIO4Offset = (offsetof(config_desc_t, HID_IO4));
|
||||
const uint32_t gu32HidDescMiscOffset = (offsetof(config_desc_t, HID_Misc));
|
||||
const uint32_t gu32UsbHidIO4ReportLen = sizeof IO4_ReportDescriptor;
|
||||
const uint32_t gu32UsbHidMiscReportLen = sizeof Keyboard_ReportDescriptor;
|
||||
const uint8_t* gpu8UsbHidIO4Report = (uint8_t*)IO4_ReportDescriptor;
|
||||
const uint8_t* gpu8UsbHidMiscReport = (uint8_t*)Keyboard_ReportDescriptor;
|
99
src/fmc.c
Normal file
99
src/fmc.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
void FMC_Open(void) { FMC->ISPCON |= FMC_ISPCON_ISPEN_Msk; }
|
||||
void FMC_Close(void) { FMC->ISPCON &= ~FMC_ISPCON_ISPEN_Msk; }
|
||||
|
||||
int FMC_Proc(uint32_t u32Cmd, uint32_t addr_start, uint32_t addr_end, uint32_t *pu32Data) {
|
||||
uint32_t u32Addr, Reg;
|
||||
|
||||
for (u32Addr = addr_start; u32Addr < addr_end; pu32Data++) {
|
||||
FMC->ISPCMD = u32Cmd;
|
||||
FMC->ISPADR = u32Addr;
|
||||
|
||||
if (u32Cmd == FMC_ISPCMD_PROGRAM) FMC->ISPDAT = *pu32Data;
|
||||
|
||||
FMC->ISPTRG = 0x1;
|
||||
__ISB();
|
||||
while (FMC->ISPTRG & 0x1)
|
||||
; // Wait for ISP command done.
|
||||
|
||||
Reg = FMC->ISPCON;
|
||||
if (Reg & FMC_ISPCON_ISPFF_Msk) {
|
||||
FMC->ISPCON = Reg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (u32Cmd == FMC_ISPCMD_READ) *pu32Data = FMC->ISPDAT;
|
||||
|
||||
if (u32Cmd == FMC_ISPCMD_PAGE_ERASE) {
|
||||
u32Addr += FMC_FLASH_PAGE_SIZE;
|
||||
} else {
|
||||
u32Addr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DATAFLASH_BASE (FMC->DFBADR) // 1F000
|
||||
// #define DATAFLASH_BASE (0x1F000)
|
||||
// Dao has his data based at FE0. We're going to base ourself at 000 instead
|
||||
#define DATAFLASH_EEPROM_BASE (DATAFLASH_BASE + 0x000)
|
||||
#define DATAFLASH_VERSION (0x02) // Gets merged into the magic number
|
||||
#define DATAFLASH_MAGIC (0x54617300 | DATAFLASH_VERSION)
|
||||
|
||||
flash_t gConfig;
|
||||
|
||||
void FMC_EEPROM_Load(void) {
|
||||
FMC_Open();
|
||||
|
||||
FMC_ReadData(DATAFLASH_EEPROM_BASE, DATAFLASH_EEPROM_BASE + sizeof gConfig, (void *)&gConfig);
|
||||
if (gConfig.u32Magic != DATAFLASH_MAGIC) {
|
||||
// Zeroing flags first means GCC knows we don't care about the other bits
|
||||
gConfig.u8Flags = 0;
|
||||
gConfig.bEnableIO4 = 1;
|
||||
gConfig.bEnableKeyboard = 0;
|
||||
gConfig.bEnableRainbow = 1;
|
||||
|
||||
gConfig.u8Sens = 8;
|
||||
|
||||
gConfig.u16HueWingLeft = 330;
|
||||
gConfig.u16HueWingRight = 180;
|
||||
gConfig.u16HueGround = 45;
|
||||
gConfig.u16HueGroundActive = 330;
|
||||
|
||||
gConfig.u8LedGroundBrightness = 255;
|
||||
gConfig.u8LedWingBrightness = 255;
|
||||
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
gConfig.u16PSoCScaleMin[i] = 0;
|
||||
gConfig.u16PSoCScaleMax[i] = 2000;
|
||||
}
|
||||
|
||||
bConfigDirty = 1;
|
||||
}
|
||||
|
||||
FMC_Close();
|
||||
}
|
||||
uint8_t bConfigDirty = 0;
|
||||
void FMC_EEPROM_Store(void) {
|
||||
if (!bConfigDirty) return;
|
||||
bConfigDirty = 0;
|
||||
|
||||
FMC_Open();
|
||||
FMC->ISPCON |= FMC_ISPCON_LDUEN_Msk;
|
||||
FMC->ISPCON |= FMC_ISPCON_APUEN_Msk;
|
||||
FMC_Erase(DATAFLASH_EEPROM_BASE);
|
||||
|
||||
gConfig.u32Magic = DATAFLASH_MAGIC;
|
||||
FMC_WriteData(DATAFLASH_EEPROM_BASE, DATAFLASH_EEPROM_BASE + sizeof gConfig, (void *)&gConfig);
|
||||
|
||||
// We don't actually have anything to do if we fail, so there's no point checking for now ig
|
||||
// // Check if our write succeeded or not
|
||||
// if (FMC_Read(DATAFLASH_EEPROM_BASE) != DATAFLASH_MAGIC)
|
||||
// ;
|
||||
|
||||
FMC->ISPCON &= ~FMC_ISPCON_APUEN_Msk;
|
||||
FMC->ISPCON &= ~FMC_ISPCON_LDUEN_Msk;
|
||||
FMC_Close();
|
||||
}
|
60
src/fmc_user.h
Normal file
60
src/fmc_user.h
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <NUC123.h>
|
||||
|
||||
#define Config0 FMC_CONFIG_BASE
|
||||
#define Config1 FMC_CONFIG_BASE + 4
|
||||
|
||||
#define ISPGO 0x01
|
||||
#define _FMC_ENABLE_CFG_UPDATE() \
|
||||
(FMC->ISPCTL |= FMC_ISPCTL_CFGUEN_Msk) // Enable CONFIG Update Function
|
||||
#define _FMC_DISABLE_CFG_UPDATE() \
|
||||
(FMC->ISPCTL &= ~FMC_ISPCTL_CFGUEN_Msk) // Disable CONFIG Update Function
|
||||
|
||||
int FMC_Proc(uint32_t u32Cmd, uint32_t addr_start, uint32_t addr_end, uint32_t *data);
|
||||
|
||||
#define FMC_EraseAP(u32Start, u32Size) \
|
||||
FMC_Proc(FMC_ISPCMD_PAGE_ERASE, (u32Start), (u32Start) + (u32Size), NULL)
|
||||
#define FMC_ReadData(u32Start, u32End, pu32Data) \
|
||||
FMC_Proc(FMC_ISPCMD_READ, (u32Start), (u32End), (pu32Data))
|
||||
#define FMC_WriteData(u32Start, u32End, pu32Data) \
|
||||
FMC_Proc(FMC_ISPCMD_PROGRAM, (u32Start), (u32End), (pu32Data))
|
||||
#define FMC_ReadU32(u32Addr, pData) FMC_ReadData((u32Addr), (u32Addr) + 4, (pData))
|
||||
#define FMC_Erase_User(u32Addr) FMC_Proc(FMC_ISPCMD_PAGE_ERASE, (u32Addr), (u32Addr) + 4, 0)
|
||||
|
||||
void FMC_Open(void);
|
||||
void FMC_Close(void);
|
||||
void FMC_EEPROM_Load(void);
|
||||
void FMC_EEPROM_Store(void);
|
||||
|
||||
#define FMC_EEPROM_VERSION 0x01
|
||||
typedef struct __attribute__((aligned(4), packed)) {
|
||||
uint32_t u32Magic;
|
||||
|
||||
// Flags
|
||||
union {
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t bEnableIO4 : 1;
|
||||
uint8_t bEnableKeyboard : 1;
|
||||
uint8_t bEnableRainbow : 1;
|
||||
};
|
||||
uint8_t u8Flags;
|
||||
};
|
||||
|
||||
// Only needs 4 bits but we aren't short atm
|
||||
uint8_t u8Sens; // [1~16], Higher = more sensitive
|
||||
|
||||
uint16_t u16HueWingLeft;
|
||||
uint16_t u16HueWingRight;
|
||||
uint16_t u16HueGround;
|
||||
uint16_t u16HueGroundActive;
|
||||
|
||||
uint8_t u8LedGroundBrightness;
|
||||
uint8_t u8LedWingBrightness;
|
||||
|
||||
// Calibration data
|
||||
uint16_t u16PSoCScaleMin[32];
|
||||
uint16_t u16PSoCScaleMax[32];
|
||||
} flash_t;
|
||||
extern flash_t gConfig;
|
||||
extern uint8_t bConfigDirty;
|
11
src/gpio.c
Normal file
11
src/gpio.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
void GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < GPIO_PIN_MAX; i++) {
|
||||
if (u32PinMask & (1 << i)) {
|
||||
port->PMD = (port->PMD & ~(0x3 << (i << 1))) | (u32Mode << (i << 1));
|
||||
}
|
||||
}
|
||||
}
|
198
src/hid.c
Normal file
198
src/hid.c
Normal file
@ -0,0 +1,198 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
#define HID_IO4_BUF ((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_HID_IO4_IN)))
|
||||
#define HID_MISC_BUF ((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_HID_MISC_IN)))
|
||||
|
||||
static const uint8_t u8GroundThreshold = 20;
|
||||
static const uint8_t u8GroundKeymap[32] = {
|
||||
KEY_I, KEY_COMMA, //
|
||||
KEY_8, KEY_K, //
|
||||
KEY_U, KEY_M, //
|
||||
KEY_7, KEY_J, //
|
||||
KEY_Y, KEY_N, //
|
||||
KEY_6, KEY_H, //
|
||||
KEY_T, KEY_B, //
|
||||
KEY_5, KEY_G, //
|
||||
KEY_R, KEY_V, //
|
||||
KEY_4, KEY_F, //
|
||||
KEY_E, KEY_C, //
|
||||
KEY_3, KEY_D, //
|
||||
KEY_W, KEY_X, //
|
||||
KEY_2, KEY_S, //
|
||||
KEY_Q, KEY_Z, //
|
||||
KEY_1, KEY_A, //
|
||||
};
|
||||
static const uint8_t u8AirKeymap[6] = {
|
||||
HID_KEYBOARD_SLASH_AND_QUESTION_MARK, // VK_OEM_2
|
||||
HID_KEYBOARD_PERIOD_AND_GREATER_THAN, // VK_OEM_PERIOD
|
||||
HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE, // VK_OEM_7
|
||||
HID_KEYBOARD_SEMICOLON_AND_COLON, // VK_OEM_1
|
||||
HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE, // VK_OEM_6
|
||||
HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE, // VK_OEM_4
|
||||
};
|
||||
static inline void _HID_Keyboard_Tick(uint8_t bReal) {
|
||||
hid_report_t *buf = (hid_report_t *)HID_MISC_BUF;
|
||||
|
||||
memset(buf, 0, sizeof *buf);
|
||||
buf->bReportId = HID_REPORT_ID_KEYBOARD;
|
||||
uint8_t kI = 0;
|
||||
|
||||
if (bReal) {
|
||||
if (gu8DigitalButtons & 0x01) buf->bKeyboard[kI++] = HID_KEYBOARD_F1;
|
||||
if (gu8DigitalButtons & 0x02) buf->bKeyboard[kI++] = HID_KEYBOARD_F2;
|
||||
if (gu8DigitalButtons & 0x04) buf->bKeyboard[kI++] = u8AirKeymap[0];
|
||||
if (gu8DigitalButtons & 0x08) buf->bKeyboard[kI++] = u8AirKeymap[1];
|
||||
if (gu8DigitalButtons & 0x10) buf->bKeyboard[kI++] = u8AirKeymap[2];
|
||||
if (gu8DigitalButtons & 0x20) buf->bKeyboard[kI++] = u8AirKeymap[3];
|
||||
if (gu8DigitalButtons & 0x40) buf->bKeyboard[kI++] = u8AirKeymap[4];
|
||||
if (gu8DigitalButtons & 0x80) buf->bKeyboard[kI++] = u8AirKeymap[5];
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (gu8GroundData[i] > u8GroundThreshold) buf->bKeyboard[kI++] = u8GroundKeymap[i];
|
||||
}
|
||||
}
|
||||
|
||||
USBD_SET_PAYLOAD_LEN(EP_HID_MISC_IN, sizeof *buf);
|
||||
}
|
||||
|
||||
#define IO4_BUTTON_TEST (1 << 9)
|
||||
#define IO4_BUTTON_SERVICE (1 << 6)
|
||||
|
||||
#define IO4_CMD_SET_COMM_TIMEOUT 0x01
|
||||
#define IO4_CMD_SET_SAMPLING_COUNT 0x02
|
||||
#define IO4_CMD_CLEAR_BOARD_STATUS 0x03
|
||||
#define IO4_CMD_SET_GENERAL_OUTPUT 0x04
|
||||
#define IO4_CMD_SET_PWM_OUTPUT 0x05
|
||||
#define IO4_CMD_SET_UNIQUE_OUTPUT 0x41
|
||||
#define IO4_CMD_UPDATE_FIRMWARE 0x85
|
||||
|
||||
volatile uint8_t u8IO4SystemStatus = 0;
|
||||
volatile uint8_t u8IO4USBStatus = 0;
|
||||
volatile uint16_t u16IO4CommTimeout = 0;
|
||||
volatile uint8_t u8IO4SamplingCount = 0;
|
||||
|
||||
static void _HID_IO4_Prepare(volatile uint8_t *pu8EpBuf) {
|
||||
io4_hid_in_t *buf = (io4_hid_in_t *)pu8EpBuf;
|
||||
|
||||
memset(buf, 0, sizeof *buf);
|
||||
buf->bReportId = HID_REPORT_ID_IO4;
|
||||
|
||||
// System buttons
|
||||
if (gu8DigitalButtons & 0x01) buf->wButtons[0] |= IO4_BUTTON_TEST;
|
||||
if (gu8DigitalButtons & 0x02) buf->wButtons[0] |= IO4_BUTTON_SERVICE;
|
||||
// Airs
|
||||
if (!(gu8DigitalButtons & 0x04)) buf->wButtons[0] |= 1 << 13;
|
||||
if (!(gu8DigitalButtons & 0x08)) buf->wButtons[1] |= 1 << 13;
|
||||
if (!(gu8DigitalButtons & 0x10)) buf->wButtons[0] |= 1 << 12;
|
||||
if (!(gu8DigitalButtons & 0x20)) buf->wButtons[1] |= 1 << 12;
|
||||
if (!(gu8DigitalButtons & 0x40)) buf->wButtons[0] |= 1 << 11;
|
||||
if (!(gu8DigitalButtons & 0x80)) buf->wButtons[1] |= 1 << 11;
|
||||
|
||||
buf->bUsbStatus = u8IO4USBStatus;
|
||||
buf->bSystemStatus = u8IO4SystemStatus;
|
||||
}
|
||||
static void _HID_IO4_Tick() {
|
||||
_HID_IO4_Prepare(HID_IO4_BUF);
|
||||
|
||||
// We must send data every 8ms! None of that "only sending changed keys" stuff
|
||||
// Trigger a write
|
||||
gu8HIDIO4Ready = 0;
|
||||
USBD_SET_PAYLOAD_LEN(EP_HID_IO4_IN, sizeof(io4_hid_in_t));
|
||||
}
|
||||
static void _HID_Debug_Tick() {
|
||||
debug_hid_report_t *buf = (debug_hid_report_t *)HID_MISC_BUF;
|
||||
memset(buf, 0, sizeof *buf);
|
||||
|
||||
static uint8_t bWhich = 0;
|
||||
if ((bWhich++) & 1) {
|
||||
buf->bReportId = HID_REPORT_ID_DEBUG_A;
|
||||
for (uint8_t i = 0; i < 32; i += 2) buf->wData[i / 2] = gu8GroundData[i];
|
||||
} else {
|
||||
buf->bReportId = HID_REPORT_ID_DEBUG_B;
|
||||
for (uint8_t i = 1; i < 32; i += 2) buf->wData[i / 2] = gu8GroundData[i];
|
||||
}
|
||||
USBD_SET_PAYLOAD_LEN(EP_HID_MISC_IN, sizeof *buf);
|
||||
}
|
||||
|
||||
static void _HID_Misc_Tick() {
|
||||
static uint8_t sbLastEnableKeyboard = 0;
|
||||
if (gConfig.bEnableKeyboard) {
|
||||
sbLastEnableKeyboard = 1;
|
||||
_HID_Keyboard_Tick(1);
|
||||
} else if (sbLastEnableKeyboard) {
|
||||
// If we've just disabled the keyboard, make sure to send a packet with all keys released!
|
||||
sbLastEnableKeyboard = 0;
|
||||
_HID_Keyboard_Tick(0);
|
||||
}
|
||||
// TODO: gbEnableDebug (we'll need to use a toggle to alternate)
|
||||
|
||||
gu8HIDMiscReady = 0;
|
||||
}
|
||||
|
||||
void USBD_HID_PrepareReport() {
|
||||
if (gu8HIDIO4Ready) _HID_IO4_Tick();
|
||||
if (gu8HIDMiscReady) _HID_Misc_Tick();
|
||||
}
|
||||
static uint8_t sIO4InBuffer[sizeof(io4_hid_in_t)] = { 0 };
|
||||
uint8_t *USBD_HID_GetReport(uint8_t u8ReportId, uint32_t *pu32Size) {
|
||||
switch (u8ReportId) {
|
||||
case HID_REPORT_ID_IO4:
|
||||
if (!gConfig.bEnableIO4) return NULL;
|
||||
_HID_IO4_Prepare(sIO4InBuffer);
|
||||
*pu32Size = sizeof sIO4InBuffer;
|
||||
return sIO4InBuffer;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
void USBD_HID_SetReport(volatile uint8_t *pu8EpBuf, uint32_t u32Size) {
|
||||
// TODO: is pu8EpBuf[0] the report ID?
|
||||
// We need to switch on that report ID so we know what we're doing!
|
||||
if (!gConfig.bEnableIO4) return;
|
||||
|
||||
if (u32Size < 2) return;
|
||||
switch (pu8EpBuf[1]) {
|
||||
case IO4_CMD_SET_COMM_TIMEOUT:
|
||||
if (u32Size >= 2 + 1) {
|
||||
u16IO4CommTimeout = (uint16_t)pu8EpBuf[2] * 200;
|
||||
u8IO4SystemStatus |= 0x10;
|
||||
|
||||
gu8HIDIO4Ready = 1;
|
||||
_HID_IO4_Tick();
|
||||
}
|
||||
break;
|
||||
case IO4_CMD_SET_SAMPLING_COUNT:
|
||||
if (u32Size >= 2 + 1) {
|
||||
u8IO4SamplingCount = pu8EpBuf[2];
|
||||
u8IO4SystemStatus |= 0x20;
|
||||
|
||||
gu8HIDIO4Ready = 1;
|
||||
_HID_IO4_Tick();
|
||||
}
|
||||
break;
|
||||
case IO4_CMD_CLEAR_BOARD_STATUS:
|
||||
u8IO4SystemStatus &= 0x0F;
|
||||
u8IO4USBStatus &= 0x04;
|
||||
|
||||
gu8HIDIO4Ready = 1;
|
||||
_HID_IO4_Tick();
|
||||
break;
|
||||
case IO4_CMD_SET_GENERAL_OUTPUT:
|
||||
if (u32Size >= 2 + 3) {
|
||||
// 20 bits of data for GPO (+4 of padding)
|
||||
}
|
||||
break;
|
||||
case IO4_CMD_SET_PWM_OUTPUT:
|
||||
if (u32Size >= 2 + 0) {
|
||||
// 0 bytes of data for PWM duty cycles (IO4 has no PWM!)
|
||||
}
|
||||
break;
|
||||
case IO4_CMD_SET_UNIQUE_OUTPUT:
|
||||
if (u32Size >= 2 + 62) {
|
||||
// 62 bytes of unique output data
|
||||
}
|
||||
break;
|
||||
case IO4_CMD_UPDATE_FIRMWARE:
|
||||
break;
|
||||
}
|
||||
}
|
412
src/led.c
Normal file
412
src/led.c
Normal file
@ -0,0 +1,412 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
hsv_t gaControlledIntLedData[LED_NUM_GROUND] = { 0 };
|
||||
uint8_t gbLedDataIsControlledInt = 0;
|
||||
uint8_t gu8aControlledExtLedData[32 * 3];
|
||||
uint8_t gbLedDataIsControlledExt = 0;
|
||||
|
||||
volatile uint8_t gu8LEDTx[LED_Tx_BUFFER];
|
||||
static void (*s_I2C1HandlerFn)(uint32_t u32Status) = NULL;
|
||||
|
||||
volatile static uint8_t su8LedTxDataLock = 0;
|
||||
|
||||
// Helper definitions
|
||||
#define SLAVE_RX_ADDR_ACK 0x60
|
||||
#define SLAVE_RX_ACK 0x80
|
||||
#define I2C_SLAVE_RX_NACK 0x88
|
||||
#define I2C_SLAVE_TX_REPEAT_START_STOP 0xA0
|
||||
#define SLAVE_TX_ACK 0xA8
|
||||
#define I2C_SLAVE_TX_NACK 0xC0
|
||||
|
||||
void I2C1_IRQHandler(void) {
|
||||
if (I2C_GET_TIMEOUT_FLAG(I2C1)) {
|
||||
I2C_ClearTimeoutFlag(I2C1);
|
||||
} else {
|
||||
if (s_I2C1HandlerFn != NULL) (s_I2C1HandlerFn)(I2C1->I2CSTATUS);
|
||||
}
|
||||
}
|
||||
|
||||
void I2C1_SlaveTx(uint32_t u32Status) {
|
||||
static uint8_t su8I2CReadAddr = 0;
|
||||
|
||||
switch (u32Status) {
|
||||
case SLAVE_RX_ACK:
|
||||
su8I2CReadAddr = I2C1->I2CDAT;
|
||||
su8LedTxDataLock = 1;
|
||||
I2C_SET_CONTROL_REG(I2C1, I2C_I2CON_SI_AA);
|
||||
break;
|
||||
case SLAVE_TX_ACK:
|
||||
I2C_SET_DATA(I2C1, gu8LEDTx[su8I2CReadAddr]);
|
||||
I2C_SET_CONTROL_REG(I2C1, I2C_I2CON_SI_AA);
|
||||
break;
|
||||
|
||||
case SLAVE_RX_ADDR_ACK:
|
||||
case I2C_SLAVE_TX_NACK:
|
||||
case I2C_SLAVE_RX_NACK:
|
||||
case I2C_SLAVE_TX_REPEAT_START_STOP:
|
||||
I2C_SET_CONTROL_REG(I2C1, I2C_I2CON_SI_AA);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Hmm?
|
||||
I2C_SET_CONTROL_REG(I2C1, I2C_I2CON_SI_AA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LED_I2C1_Init(void) {
|
||||
I2C_Open(I2C1, 100000);
|
||||
I2C_SetSlaveAddr(I2C1, 0, 0x18, 0);
|
||||
I2C_SetSlaveAddr(I2C1, 1, 0x30, 0);
|
||||
I2C_SetSlaveAddr(I2C1, 2, 0x55, 0);
|
||||
I2C_SetSlaveAddr(I2C1, 3, 0x18, 0);
|
||||
I2C_SetSlaveAddrMask(I2C1, 0, 1);
|
||||
I2C_SetSlaveAddrMask(I2C1, 1, 4);
|
||||
I2C_SetSlaveAddrMask(I2C1, 2, 1);
|
||||
I2C_SetSlaveAddrMask(I2C1, 3, 4);
|
||||
I2C_EnableInt(I2C1);
|
||||
NVIC_EnableIRQ(I2C1_IRQn);
|
||||
|
||||
// I2C1 enter no address SLV mode
|
||||
I2C_SET_CONTROL_REG(I2C1, I2C_I2CON_SI_AA);
|
||||
|
||||
s_I2C1HandlerFn = I2C1_SlaveTx;
|
||||
}
|
||||
|
||||
// static inline void LEDTxLock(void) {
|
||||
// gu8LEDTx[0] = 0;
|
||||
// }
|
||||
// static inline void LEDTxCommit(uint8_t u8Command, uint8_t u8NExpected) {
|
||||
// gu8LEDTx[0] = u8Command;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief Convert from RGB to HSV
|
||||
*
|
||||
* @param pu8aRGB Destination 3-tuple to receive RGB values
|
||||
* @param u16H Hue, ranging 0~LED_HUE_MAX
|
||||
* @param u8S Saturation, ranging 0~255
|
||||
* @param u8V Value, ranging 0~255
|
||||
*/
|
||||
void HsvToRgb(uint8_t* pu8aRGB, uint16_t u16H, uint8_t u8S, uint8_t u8V) {
|
||||
if (u8S == 0) {
|
||||
pu8aRGB[0] = u8V;
|
||||
pu8aRGB[1] = u8V;
|
||||
pu8aRGB[2] = u8V;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t region = u16H / (LED_HUE_MAX / 6);
|
||||
uint8_t remainder = (u16H - (region * (LED_HUE_MAX / 6))) * (255 / (LED_HUE_MAX / 6));
|
||||
|
||||
uint8_t p = (u8V * (255 - u8S)) >> 8;
|
||||
uint8_t q = (u8V * (255 - ((u8S * remainder) >> 8))) >> 8;
|
||||
uint8_t t = (u8V * (255 - ((u8S * (255 - remainder)) >> 8))) >> 8;
|
||||
|
||||
switch (region) {
|
||||
case 0:
|
||||
pu8aRGB[0] = u8V;
|
||||
pu8aRGB[1] = t;
|
||||
pu8aRGB[2] = p;
|
||||
break;
|
||||
case 1:
|
||||
pu8aRGB[0] = q;
|
||||
pu8aRGB[1] = u8V;
|
||||
pu8aRGB[2] = p;
|
||||
break;
|
||||
case 2:
|
||||
pu8aRGB[0] = p;
|
||||
pu8aRGB[1] = u8V;
|
||||
pu8aRGB[2] = t;
|
||||
break;
|
||||
case 3:
|
||||
pu8aRGB[0] = p;
|
||||
pu8aRGB[1] = q;
|
||||
pu8aRGB[2] = u8V;
|
||||
break;
|
||||
case 4:
|
||||
pu8aRGB[0] = t;
|
||||
pu8aRGB[1] = p;
|
||||
pu8aRGB[2] = u8V;
|
||||
break;
|
||||
default:
|
||||
pu8aRGB[0] = u8V;
|
||||
pu8aRGB[1] = p;
|
||||
pu8aRGB[2] = q;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 0x00: Normal operation (all other values ignore ground data)
|
||||
// 0x01: [Stock] Uses colours. Bar 1 full (from right)
|
||||
// 0x02: [Stock] Uses colours. Bar 2 full (from right)
|
||||
// 0x03: [Stock] Uses colours. Bar 3 full (from right)
|
||||
// 0x04: [Stock] Uses colours. Bar 4 full (from right)
|
||||
// 0x1X: [Stock] All white with black gaps. X bars black (from right)
|
||||
// 0x1X: [CFW] Rainbow with black gaps. X bars black (from right)
|
||||
// 0x20: [CFW] Flashes three times
|
||||
// 0x80: [Stock] Flashes three times
|
||||
static uint8_t su8LedSpecial = 0x05;
|
||||
|
||||
// 0: Separator bar every 4 (4 sections)
|
||||
// 1: Separator bar every 2 (8 sections)
|
||||
// 2: Separator bar every 1 (16 sections)
|
||||
// 3: No separator bars
|
||||
// 4~7: LEDs off
|
||||
// For some reason this value can be |8, even though firmware suggests otherwise
|
||||
static uint8_t su8LedSeparators = 1;
|
||||
|
||||
// 0: Invalid, but functions as 1
|
||||
// 1: 32-key mode
|
||||
// 2: 16-key mode (same as 32key mode)
|
||||
// 3: 8-key mode (bars light in pairs)
|
||||
// 4: 4-key mode (bars light in quads)
|
||||
static uint8_t su8LedNKey = 1;
|
||||
|
||||
// 0x40: Turns off ground LEDs
|
||||
// 0x80: Turns off wing LEDs
|
||||
static uint8_t su8LedOff = 0;
|
||||
|
||||
// 0x8X: Separator 1~(X+1) lit (ie X ranges from 0~E; F is the same as E)
|
||||
static uint8_t su8LedCfwRainbow = 0x8F;
|
||||
|
||||
void LED_WriteBasicGrounds(void) {
|
||||
gu8LEDTx[0] = LED_CMD_BASIC;
|
||||
|
||||
// 32 bits of grounds
|
||||
// (01,02)=key1, (04,08)=key2 (10,20)=key3, (40,80)=key4
|
||||
gu8LEDTx[1] = 0;
|
||||
gu8LEDTx[2] = 0;
|
||||
gu8LEDTx[3] = 0;
|
||||
gu8LEDTx[4] = 0;
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
if (gu8GroundData[i * 8 + j] > PSoC_INTERNAL_DIGITAL_TH) gu8LEDTx[i + 1] |= (1 << j);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LED_FIRMWARE_CFW
|
||||
gu8LEDTx[5] = 0; // Wing fill
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
if (gu8DigitalButtons & (1 << (i + 2))) gu8LEDTx[5] |= 1 << i;
|
||||
gu8LEDTx[6] = su8LedCfwRainbow;
|
||||
gu8LEDTx[7] = 0; // Unused
|
||||
#else
|
||||
// Wings
|
||||
gu8LEDTx[5] = 0; // Wing fill
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
if (gu8DigitalButtons & (1 << (i + 2))) gu8LEDTx[5] |= 1 << i;
|
||||
gu8LEDTx[6] = gConfig.u16HueWingLeft / LED_HUE_SCALE; // Hue left (default 330)
|
||||
gu8LEDTx[7] = gConfig.u16HueWingRight / LED_HUE_SCALE; // Hue right (default 180)
|
||||
#endif
|
||||
|
||||
// Unused in CFW
|
||||
gu8LEDTx[8] = gConfig.u16HueGround / LED_HUE_SCALE; // Hue ground inactive (default 45)
|
||||
gu8LEDTx[9] = gConfig.u16HueGroundActive / LED_HUE_SCALE; // Hue ground active (default 330)
|
||||
|
||||
// In CFW only su8LedOff is respected
|
||||
gu8LEDTx[10] = (su8LedSeparators << 4) | su8LedOff | su8LedNKey;
|
||||
gu8LEDTx[11] = su8LedSpecial;
|
||||
}
|
||||
|
||||
static const uint8_t su8aWingSensors[LED_NUM_LEFT] = {
|
||||
DIGITAL_AIR1_Msk, DIGITAL_AIR1_Msk, DIGITAL_AIR1_Msk, DIGITAL_AIR1_Msk, //
|
||||
DIGITAL_AIR2_Msk, DIGITAL_AIR2_Msk, DIGITAL_AIR2_Msk, DIGITAL_AIR2_Msk, //
|
||||
DIGITAL_AIR3_Msk, DIGITAL_AIR3_Msk, DIGITAL_AIR3_Msk, DIGITAL_AIR3_Msk, //
|
||||
DIGITAL_AIR4_Msk, DIGITAL_AIR4_Msk, DIGITAL_AIR4_Msk, DIGITAL_AIR4_Msk, //
|
||||
DIGITAL_AIR5_Msk, DIGITAL_AIR5_Msk, DIGITAL_AIR5_Msk, DIGITAL_AIR5_Msk, //
|
||||
DIGITAL_AIR6_Msk, DIGITAL_AIR6_Msk, DIGITAL_AIR6_Msk, DIGITAL_AIR6_Msk, //
|
||||
};
|
||||
|
||||
#define SATURATION_ACTIVE 255
|
||||
#define SATURATION_INACTIVE 240
|
||||
#define VALUE_ACTIVE (gConfig.u8LedWingBrightness)
|
||||
#define VALUE_INACTIVE (gConfig.u8LedWingBrightness / 2)
|
||||
|
||||
static void LED_OffGround(void) {
|
||||
memset((uint8_t*)&gu8LEDTx[LED_DATA_OFFSET], 0, LED_NUM_GROUND * 3);
|
||||
}
|
||||
static void LED_OffWings(void) {
|
||||
memset((uint8_t*)&gu8LEDTx[LED_DATA_OFFSET + LED_NUM_GROUND * 3], 0,
|
||||
(LED_NUM_LEFT + LED_NUM_RIGHT) * 3);
|
||||
}
|
||||
static void LED_AirWings(void) {
|
||||
uint8_t u8aRgbActive[3];
|
||||
uint8_t u8aRgbInactive[3];
|
||||
|
||||
uint8_t j, i = LED_NUM_GROUND;
|
||||
|
||||
// Left wing
|
||||
HsvToRgb(u8aRgbActive, gConfig.u16HueWingLeft, SATURATION_ACTIVE, VALUE_ACTIVE);
|
||||
HsvToRgb(u8aRgbInactive, gConfig.u16HueWingLeft, SATURATION_INACTIVE, VALUE_INACTIVE);
|
||||
for (j = 0; i < LED_NUM_GROUND + LED_NUM_LEFT; i++, j++) {
|
||||
// GRB
|
||||
if (gu8DigitalButtons & su8aWingSensors[LED_NUM_LEFT - j - 1]) {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aRgbActive[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aRgbActive[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aRgbActive[2];
|
||||
} else {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aRgbInactive[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aRgbInactive[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aRgbInactive[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Right wing
|
||||
HsvToRgb(u8aRgbActive, gConfig.u16HueWingRight, SATURATION_ACTIVE, VALUE_ACTIVE);
|
||||
HsvToRgb(u8aRgbInactive, gConfig.u16HueWingRight, SATURATION_INACTIVE, VALUE_INACTIVE);
|
||||
for (j = 0; i < LED_NUM_GROUND + LED_NUM_LEFT + LED_NUM_RIGHT; i++, j++) {
|
||||
// GRB
|
||||
if (gu8DigitalButtons & su8aWingSensors[j]) {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aRgbActive[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aRgbActive[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aRgbActive[2];
|
||||
} else {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aRgbInactive[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aRgbInactive[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aRgbInactive[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t LED_ScaleU8(uint8_t u8V, uint8_t u8Scale) {
|
||||
return ((uint16_t)u8V * (uint16_t)u8Scale) / 255;
|
||||
}
|
||||
|
||||
static void LED_GroundRainbow(void) {
|
||||
uint8_t u8aRGB[3];
|
||||
|
||||
// 5 ticks * 360 hue = 1800 calls for one cycle (1.8s)
|
||||
static uint16_t u16Hue = 0;
|
||||
static uint8_t u8Ticker = 0;
|
||||
if (++u8Ticker == 5) {
|
||||
u8Ticker = 0;
|
||||
u16Hue++;
|
||||
if (u16Hue == LED_HUE_MAX) u16Hue = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* There are 48 LEDs for ground, but we only send 31 values
|
||||
* They're mapped to the LEDs as follows:
|
||||
* 00a11b22c33d44f55g66h77i...
|
||||
*
|
||||
* That is, we can't split-colour a key :P
|
||||
*/
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
uint8_t v = 190;
|
||||
uint8_t h = 0;
|
||||
uint8_t nCell = i >> 1;
|
||||
if (i % 2 == 0) {
|
||||
if (gu16PSoCDigital & (1 << nCell)) {
|
||||
v = 255;
|
||||
h = LED_HUE_MAX / 2;
|
||||
}
|
||||
} else if (nCell % 4 == 3) {
|
||||
h = LED_HUE_MAX / 2;
|
||||
}
|
||||
|
||||
// GRB
|
||||
HsvToRgb(u8aRGB, (u16Hue + h + (i * (LED_HUE_MAX / LED_NUM_GROUND))) % LED_HUE_MAX, v,
|
||||
LED_ScaleU8(v - 63, gConfig.u8LedGroundBrightness));
|
||||
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aRGB[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aRGB[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aRGB[2];
|
||||
}
|
||||
}
|
||||
static void LED_GroundStatic(void) {
|
||||
uint8_t u8aGround[3];
|
||||
uint8_t u8aGroundActive[3];
|
||||
|
||||
HsvToRgb(u8aGround, gConfig.u16HueGround, 255, gConfig.u8LedGroundBrightness);
|
||||
HsvToRgb(u8aGroundActive, gConfig.u16HueGroundActive, 255, gConfig.u8LedGroundBrightness);
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
const uint8_t nCell = i >> 1;
|
||||
if (i % 2 == 0) {
|
||||
// This is a cell. Light it according to the touch input
|
||||
if (gu16PSoCDigital & (1 << nCell)) {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aGroundActive[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aGroundActive[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aGroundActive[2];
|
||||
} else {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aGround[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aGround[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aGround[2];
|
||||
}
|
||||
} else if (nCell % 4 == 3) {
|
||||
// This is a separating divider. Light it with the active colour
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aGroundActive[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aGroundActive[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aGroundActive[2];
|
||||
} else {
|
||||
// This is a non-separating divider. Light it based on the two cells either side
|
||||
if (gu16PSoCDigital & (1 << nCell) && gu16PSoCDigital & (1 << (nCell + 1))) {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aGroundActive[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aGroundActive[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aGroundActive[2];
|
||||
} else {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aGround[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aGround[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aGround[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LED_WriteRGB(void) {
|
||||
gu8LEDTx[0] = LED_CMD_RGB_FULL;
|
||||
|
||||
#ifdef LED_FIRMWARE_CFW
|
||||
// "CFW" added this byte
|
||||
gu8LEDTx[1] = su8LedSpecial | su8LedOff;
|
||||
#endif
|
||||
|
||||
// Even when grounds are disabled, internal control overrides that
|
||||
if (gbLedDataIsControlledInt) {
|
||||
PIN_LED_GROUND_PWR = 1;
|
||||
|
||||
uint8_t u8aRGB[3];
|
||||
// Convert from HSV to GRB
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
HsvToRgb(u8aRGB, gaControlledIntLedData[LED_NUM_GROUND - i - 1].u16H,
|
||||
gaControlledIntLedData[LED_NUM_GROUND - i - 1].u8S,
|
||||
gaControlledIntLedData[LED_NUM_GROUND - i - 1].u8V);
|
||||
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] = u8aRGB[1];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] = u8aRGB[0];
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] = u8aRGB[2];
|
||||
}
|
||||
} else if (gConfig.u8LedGroundBrightness) {
|
||||
PIN_LED_GROUND_PWR = 1;
|
||||
|
||||
if (gbLedDataIsControlledExt) {
|
||||
// Swap from BRG to GRB
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 0] =
|
||||
LED_ScaleU8(gu8aControlledExtLedData[i * 3 + 2], gConfig.u8LedGroundBrightness);
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 1] =
|
||||
LED_ScaleU8(gu8aControlledExtLedData[i * 3 + 1], gConfig.u8LedGroundBrightness);
|
||||
gu8LEDTx[LED_DATA_OFFSET + i * 3 + 2] =
|
||||
LED_ScaleU8(gu8aControlledExtLedData[i * 3 + 0], gConfig.u8LedGroundBrightness);
|
||||
}
|
||||
} else if (gConfig.bEnableRainbow) {
|
||||
LED_GroundRainbow();
|
||||
} else {
|
||||
LED_GroundStatic();
|
||||
}
|
||||
} else {
|
||||
PIN_LED_GROUND_PWR = 0;
|
||||
LED_OffGround();
|
||||
}
|
||||
|
||||
if (gConfig.u8LedWingBrightness) {
|
||||
PIN_LED_WING_PWR = 1;
|
||||
// TODO: Get data from game when gbLedDataIsControlledExt (HID, probably)
|
||||
LED_AirWings();
|
||||
} else {
|
||||
PIN_LED_WING_PWR = 0;
|
||||
LED_OffWings();
|
||||
}
|
||||
}
|
73
src/led.h
Normal file
73
src/led.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define LED_FIRMWARE_CFW
|
||||
#ifndef LED_FIRMWARE_CFW
|
||||
#define LED_DATA_OFFSET 1
|
||||
#else
|
||||
#define LED_DATA_OFFSET 2
|
||||
#endif
|
||||
|
||||
// LED count definitions
|
||||
#define LED_NUM_GROUND 31
|
||||
#define LED_NUM_LEFT 24
|
||||
#define LED_NUM_RIGHT 24
|
||||
|
||||
// HSV definitions
|
||||
#define LED_HUE_SCALE 5 // For transmission to LED board in basic mode
|
||||
#define LED_HUE_MAX 360
|
||||
|
||||
// Host->LED MCU commands
|
||||
#define LED_CMD_BASIC 0xA5
|
||||
#define LED_CMD_RGB_FULL 0x5A
|
||||
|
||||
// LED index names
|
||||
#define LED_CELL_0 0
|
||||
#define LED_CELL_1 2
|
||||
#define LED_CELL_2 4
|
||||
#define LED_CELL_3 6
|
||||
#define LED_CELL_4 8
|
||||
#define LED_CELL_5 10
|
||||
#define LED_CELL_6 12
|
||||
#define LED_CELL_7 14
|
||||
#define LED_CELL_8 16
|
||||
#define LED_CELL_9 18
|
||||
#define LED_CELL_10 20
|
||||
#define LED_CELL_11 22
|
||||
#define LED_CELL_12 24
|
||||
#define LED_CELL_13 26
|
||||
#define LED_CELL_14 28
|
||||
#define LED_CELL_15 30
|
||||
|
||||
#define LED_DIVIDER_0_1 1
|
||||
#define LED_DIVIDER_1_2 3
|
||||
#define LED_DIVIDER_2_3 5
|
||||
#define LED_DIVIDER_3_4 7
|
||||
#define LED_DIVIDER_4_5 9
|
||||
#define LED_DIVIDER_5_6 11
|
||||
#define LED_DIVIDER_6_7 13
|
||||
#define LED_DIVIDER_7_8 15
|
||||
#define LED_DIVIDER_8_9 17
|
||||
#define LED_DIVIDER_9_10 19
|
||||
#define LED_DIVIDER_10_11 21
|
||||
#define LED_DIVIDER_11_12 23
|
||||
#define LED_DIVIDER_12_13 25
|
||||
#define LED_DIVIDER_13_14 27
|
||||
#define LED_DIVIDER_14_15 29
|
||||
|
||||
typedef struct {
|
||||
uint16_t u16H;
|
||||
uint8_t u8S;
|
||||
uint8_t u8V;
|
||||
} hsv_t;
|
||||
// Internal LED control, from the settings UI (gets priority)
|
||||
extern hsv_t gaControlledIntLedData[LED_NUM_GROUND];
|
||||
extern uint8_t gbLedDataIsControlledInt;
|
||||
// External LED control, from the game
|
||||
extern uint8_t gu8aControlledExtLedData[32 * 3];
|
||||
extern uint8_t gbLedDataIsControlledExt;
|
||||
|
||||
void LED_I2C1_Init(void);
|
||||
void LED_WriteBasicGrounds(void);
|
||||
void LED_WriteRGB(void);
|
138
src/main.c
Normal file
138
src/main.c
Normal file
@ -0,0 +1,138 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
uint8_t volatile gu8HIDIO4Ready = 0;
|
||||
uint8_t volatile gu8HIDMiscReady = 0;
|
||||
|
||||
#define DEBOUNCE_COUNT 8
|
||||
uint8_t TickDebouncer(uint8_t u8Buttons) {
|
||||
static uint8_t u8Counters[8] = { 0 };
|
||||
uint8_t debounced = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (u8Buttons & (1 << i))
|
||||
u8Counters[i] = 0;
|
||||
else if (u8Counters[i] < DEBOUNCE_COUNT)
|
||||
u8Counters[i]++;
|
||||
|
||||
if (u8Counters[i] < DEBOUNCE_COUNT) debounced |= (1 << i);
|
||||
}
|
||||
return debounced;
|
||||
}
|
||||
|
||||
uint8_t gu8DigitalButtons;
|
||||
#define DELAY_FN 2
|
||||
#define DELAY_AIR 2
|
||||
void Digital_TickInputs() {
|
||||
uint8_t u8Buttons = 0;
|
||||
|
||||
GPIO_SetMode(_PIN_FN1, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_FN);
|
||||
GPIO_SetMode(_PIN_FN1, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_FN1 ? 0 : DIGITAL_FN1_Msk;
|
||||
|
||||
GPIO_SetMode(_PIN_FN2, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_FN);
|
||||
GPIO_SetMode(_PIN_FN2, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_FN2 ? 0 : DIGITAL_FN2_Msk;
|
||||
|
||||
GPIO_SetMode(_PIN_AIR1, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_AIR);
|
||||
GPIO_SetMode(_PIN_AIR1, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_AIR1 ? DIGITAL_AIR1_Msk : 0;
|
||||
|
||||
GPIO_SetMode(_PIN_AIR2, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_AIR);
|
||||
GPIO_SetMode(_PIN_AIR2, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_AIR2 ? DIGITAL_AIR2_Msk : 0;
|
||||
|
||||
GPIO_SetMode(_PIN_AIR3, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_AIR);
|
||||
GPIO_SetMode(_PIN_AIR3, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_AIR3 ? DIGITAL_AIR3_Msk : 0;
|
||||
|
||||
GPIO_SetMode(_PIN_AIR4, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_AIR);
|
||||
GPIO_SetMode(_PIN_AIR4, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_AIR4 ? DIGITAL_AIR4_Msk : 0;
|
||||
|
||||
GPIO_SetMode(_PIN_AIR5, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_AIR);
|
||||
GPIO_SetMode(_PIN_AIR5, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_AIR5 ? DIGITAL_AIR5_Msk : 0;
|
||||
|
||||
GPIO_SetMode(_PIN_AIR6, GPIO_PMD_INPUT);
|
||||
DelayCycles_Small(DELAY_AIR);
|
||||
GPIO_SetMode(_PIN_AIR6, GPIO_PMD_QUASI);
|
||||
u8Buttons |= PIN_AIR6 ? DIGITAL_AIR6_Msk : 0;
|
||||
|
||||
gu8DigitalButtons = TickDebouncer(u8Buttons);
|
||||
}
|
||||
|
||||
int _entry(void) {
|
||||
SYS_UnlockReg();
|
||||
SYS_Init();
|
||||
#ifdef ENABLE_BOOTLOADER_CHECK
|
||||
SYS_Bootloader_Check();
|
||||
#endif
|
||||
SYS_ModuleInit();
|
||||
|
||||
FMC_EEPROM_Load();
|
||||
|
||||
gu8VcomReady = 1;
|
||||
gu8HIDIO4Ready = 1;
|
||||
gu8HIDMiscReady = 1;
|
||||
|
||||
/**
|
||||
* Unfortunately, everything related to this seems to be a bit broken at the moment
|
||||
* For some reason, this code gets into infinite loops on cold boots, even with 5 seconds of
|
||||
* delay added first.
|
||||
* To make matters worse, if we ever actually call PSoCSetFingerCapacitance it ends up with
|
||||
* huge asymmetry between the two PSoCs, which is just unworkable.
|
||||
*/
|
||||
// uint16_t u16InitialFingerCap = PSoCGetFingerCapacitance();
|
||||
// if (u16InitialFingerCap != gu16PSoCFingerCap) {
|
||||
// PSoCSetFingerCapacitance(gu16PSoCFingerCap);
|
||||
// }
|
||||
|
||||
static uint32_t su32NowMs = 0;
|
||||
su32NowMs++;
|
||||
while (1) {
|
||||
USB_VCOM_Tick();
|
||||
|
||||
if (bPSoCDirty) {
|
||||
bPSoCDirty = 0;
|
||||
PSoC_PostProcessing();
|
||||
}
|
||||
|
||||
Slider_TickSerial();
|
||||
USBD_HID_PrepareReport();
|
||||
|
||||
// Limit this to 250us so our debouncer has a chance to function
|
||||
// 250us is the resolution of our timer currently, though we could increase it if needed
|
||||
if (gu8Do250usTick) {
|
||||
Digital_TickInputs();
|
||||
}
|
||||
|
||||
if (gu8Do1msTick) {
|
||||
su32NowMs++;
|
||||
gu8Do1msTick = 0;
|
||||
|
||||
Slider_Tick1ms();
|
||||
|
||||
PSoC_DigitalCalc();
|
||||
UI_Tick();
|
||||
|
||||
// LED_WriteBasicGrounds();
|
||||
LED_WriteRGB();
|
||||
} /* else {
|
||||
DelayCycles(45);
|
||||
}*/
|
||||
|
||||
// Wait until we know both PSoC are awake and talking before we attempt configure them
|
||||
if (gu8PSoCSeenData == 0b011) {
|
||||
PSoC_SetFingerCapacitanceFromConfig();
|
||||
gu8PSoCSeenData |= 0b100;
|
||||
}
|
||||
|
||||
FMC_EEPROM_Store();
|
||||
}
|
||||
}
|
64
src/pins.h
Normal file
64
src/pins.h
Normal file
@ -0,0 +1,64 @@
|
||||
#define PIN_SDA PA10
|
||||
#define PIN_SCL PA11
|
||||
#define PIN_USB_MUX_EN PB1
|
||||
#define PIN_USB_MUX_SEL PB0
|
||||
#define PIN_FN1 PB7
|
||||
#define PIN_FN2 PB2
|
||||
#define PIN_EC1 PB3
|
||||
#define PIN_EC2 PC5
|
||||
#define PIN_EC3 PC4
|
||||
#define PIN_RX2 PD9
|
||||
#define PIN_RX3 PD10
|
||||
#define PIN_RX4 PD11
|
||||
#define PIN_LED_WING_PWR PB13
|
||||
#define PIN_LED_GROUND_PWR PC3
|
||||
|
||||
#define _PIN_SDA PA, BIT10
|
||||
#define _PIN_SCL PA, BIT11
|
||||
#define _PIN_USB_MUX_EN PB, BIT1
|
||||
#define _PIN_USB_MUX_SEL PB, BIT0
|
||||
#define _PIN_FN1 PB, BIT7
|
||||
#define _PIN_FN2 PB, BIT2
|
||||
#define _PIN_EC1 PB, BIT3
|
||||
#define _PIN_EC2 PC, BIT5
|
||||
#define _PIN_EC3 PC, BIT4
|
||||
#define _PIN_RX2 PD, BIT9
|
||||
#define _PIN_RX3 PD, BIT10
|
||||
#define _PIN_RX4 PD, BIT11
|
||||
#define _PIN_LED_WING_PWR PB, BIT13
|
||||
#define _PIN_LED_GROUND_PWR PC, BIT3
|
||||
|
||||
#define PIN_AIR1 PIN_RX2
|
||||
#define PIN_AIR2 PIN_EC1
|
||||
#define PIN_AIR3 PIN_RX3
|
||||
#define PIN_AIR4 PIN_EC2
|
||||
#define PIN_AIR5 PIN_RX4
|
||||
#define PIN_AIR6 PIN_EC3
|
||||
#define _PIN_AIR1 _PIN_RX2
|
||||
#define _PIN_AIR2 _PIN_EC1
|
||||
#define _PIN_AIR3 _PIN_RX3
|
||||
#define _PIN_AIR4 _PIN_EC2
|
||||
#define _PIN_AIR5 _PIN_RX4
|
||||
#define _PIN_AIR6 _PIN_EC3
|
||||
|
||||
#define USB_MUX_ENABLE 0
|
||||
#define USB_MUX_DISABLE 1
|
||||
#define USB_MUX_HOST 0
|
||||
#define USB_MUX_LEDS 1
|
||||
|
||||
#define DIGITAL_FN1_Pos 0
|
||||
#define DIGITAL_FN2_Pos 1
|
||||
#define DIGITAL_AIR1_Pos 2
|
||||
#define DIGITAL_AIR2_Pos 3
|
||||
#define DIGITAL_AIR3_Pos 4
|
||||
#define DIGITAL_AIR4_Pos 5
|
||||
#define DIGITAL_AIR5_Pos 6
|
||||
#define DIGITAL_AIR6_Pos 7
|
||||
#define DIGITAL_FN1_Msk (1 << DIGITAL_FN1_Pos)
|
||||
#define DIGITAL_FN2_Msk (1 << DIGITAL_FN2_Pos)
|
||||
#define DIGITAL_AIR1_Msk (1 << DIGITAL_AIR1_Pos)
|
||||
#define DIGITAL_AIR2_Msk (1 << DIGITAL_AIR2_Pos)
|
||||
#define DIGITAL_AIR3_Msk (1 << DIGITAL_AIR3_Pos)
|
||||
#define DIGITAL_AIR4_Msk (1 << DIGITAL_AIR4_Pos)
|
||||
#define DIGITAL_AIR5_Msk (1 << DIGITAL_AIR5_Pos)
|
||||
#define DIGITAL_AIR6_Msk (1 << DIGITAL_AIR6_Pos)
|
292
src/psoc.c
Normal file
292
src/psoc.c
Normal file
@ -0,0 +1,292 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
uint16_t gu16PSoCDiff[32] = { 0 };
|
||||
|
||||
uint32_t gu32PSoCDigital = 0;
|
||||
uint32_t gu32PSoCDigitalPos = 0;
|
||||
uint32_t gu32PSoCDigitalNeg = 0;
|
||||
uint32_t gu32PSoCDigitalTrig = 0;
|
||||
uint16_t gu16PSoCDigital = 0;
|
||||
uint16_t gu16PSoCDigitalPos = 0;
|
||||
uint16_t gu16PSoCDigitalNeg = 0;
|
||||
uint16_t gu16PSoCDigitalTrig = 0;
|
||||
|
||||
uint8_t gu8PSoCSeenData = 0;
|
||||
|
||||
volatile uint8_t bPSoCDirty = 0;
|
||||
|
||||
static void* pu8PsocRxDestination = NULL;
|
||||
static uint8_t pu8PsocRxDestinationLen = 0;
|
||||
static volatile uint8_t* pu8PsocGotData = NULL;
|
||||
static void PSoC_HandleRx(PSoC_CMD_RX eCmd, uint8_t u8Len, uint8_t* u8Data) {
|
||||
if (eCmd != PSoC_CMD_RX_SLAVE_DIFF && eCmd != PSoC_CMD_RX_MASTER_DIFF &&
|
||||
eCmd != PSoC_CMD_RX_CS_START) {
|
||||
static uint8_t debug = 0;
|
||||
debug++;
|
||||
}
|
||||
|
||||
uint8_t u8PsocDataOffset = 0;
|
||||
switch (eCmd) {
|
||||
case PSoC_CMD_RX_REQUEST_FINGER_CAP:
|
||||
PSoC_SetFingerCapacitanceFromConfig();
|
||||
return;
|
||||
|
||||
// We don't care about these
|
||||
case PSoC_CMD_RX_CS_START:
|
||||
case PSoC_CMD_RX_CS_END:
|
||||
return;
|
||||
|
||||
case PSoC_CMD_RX_SLAVE_DIFF:
|
||||
u8PsocDataOffset = 16;
|
||||
gu8PSoCSeenData |= 1;
|
||||
// Falls through
|
||||
case PSoC_CMD_RX_MASTER_DIFF:
|
||||
if (eCmd == PSoC_CMD_RX_MASTER_DIFF) gu8PSoCSeenData |= 2;
|
||||
if (u8Len != 32) return;
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
gu16PSoCDiff[u8PsocDataOffset + i] = u8Data[(i * 2)] << 8;
|
||||
gu16PSoCDiff[u8PsocDataOffset + i] |= u8Data[(i * 2) + 1];
|
||||
}
|
||||
bPSoCDirty = 1;
|
||||
return;
|
||||
|
||||
// Arbitrary data reception
|
||||
case PSoC_CMD_RX_MASTER_TOUCH_TH:
|
||||
case PSoC_CMD_RX_SLAVE_TOUCH_TH:
|
||||
case PSoC_CMD_RX_MASTER_FINGER_TH:
|
||||
case PSoC_CMD_RX_MASTER_HYSTERESIS:
|
||||
case PSoC_CMD_RX_SLAVE_FINGER_TH:
|
||||
case PSoC_CMD_RX_SLAVE_HYSTERESIS:
|
||||
case PSoC_CMD_RX_GET_FINGER_CAP:
|
||||
case PSoC_CMD_RX_SET_FINGER_CAP:
|
||||
if (pu8PsocRxDestination) {
|
||||
if (u8Len > pu8PsocRxDestinationLen) u8Len = pu8PsocRxDestinationLen;
|
||||
memcpy(pu8PsocRxDestination, u8Data, u8Len);
|
||||
// Make sure we don't go clobbering stuff later!
|
||||
pu8PsocRxDestination = NULL;
|
||||
}
|
||||
if (pu8PsocGotData) {
|
||||
*pu8PsocGotData = 1;
|
||||
// Make sure we don't go clobbering stuff later!
|
||||
pu8PsocGotData = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
void UART1_IRQHandler(void) {
|
||||
static uint8_t su8RxData[32] = { 0 };
|
||||
static uint8_t su8State = 0;
|
||||
static PSoC_CMD_RX eCmd = 0;
|
||||
static uint8_t su8Len = 0;
|
||||
static uint8_t su8Index = 0;
|
||||
static uint8_t su8Sum = 0;
|
||||
|
||||
// We only care about data interrupts
|
||||
if (!(UART1->ISR & (UART_ISR_RDA_INT_Msk | UART_ISR_TOUT_INT_Msk))) return;
|
||||
|
||||
uint8_t u8Data = UART_READ(UART1);
|
||||
|
||||
switch (su8State) {
|
||||
case 0:
|
||||
eCmd = u8Data; // For debugging
|
||||
switch (u8Data) {
|
||||
// Just go away
|
||||
case PSoC_CMD_RX_CS_START:
|
||||
case PSoC_CMD_RX_CS_END:
|
||||
return;
|
||||
// Commands with no payload
|
||||
case PSoC_CMD_RX_SET_FINGER_CAP:
|
||||
PSoC_HandleRx(u8Data, 0, NULL);
|
||||
return;
|
||||
|
||||
// Commands that have a payload we need to receive
|
||||
case PSoC_CMD_RX_REQUEST_FINGER_CAP:
|
||||
case PSoC_CMD_RX_MASTER_DIFF:
|
||||
case PSoC_CMD_RX_SLAVE_DIFF:
|
||||
case PSoC_CMD_RX_MASTER_TOUCH_TH:
|
||||
case PSoC_CMD_RX_SLAVE_TOUCH_TH:
|
||||
case PSoC_CMD_RX_MASTER_FINGER_TH:
|
||||
case PSoC_CMD_RX_MASTER_HYSTERESIS:
|
||||
case PSoC_CMD_RX_SLAVE_FINGER_TH:
|
||||
case PSoC_CMD_RX_SLAVE_HYSTERESIS:
|
||||
case PSoC_CMD_RX_GET_FINGER_CAP:
|
||||
eCmd = u8Data;
|
||||
su8Sum = u8Data;
|
||||
su8State++;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case 1:
|
||||
su8Len = u8Data;
|
||||
su8Index = 0;
|
||||
su8Sum += u8Data;
|
||||
su8State++;
|
||||
// If there's no payload to receive, skip that step
|
||||
if (!su8Len) su8State++;
|
||||
// Packets too large for reception need dropped
|
||||
if (su8Len > sizeof su8RxData) su8State = 0;
|
||||
return;
|
||||
case 2:
|
||||
su8Sum += u8Data;
|
||||
su8RxData[su8Index++] = u8Data;
|
||||
if (su8Index == su8Len) su8State++;
|
||||
return;
|
||||
case 3:
|
||||
// Only process packets with a valid checksum
|
||||
if (su8Sum == u8Data) PSoC_HandleRx(eCmd, su8Len, su8RxData);
|
||||
su8State = 0;
|
||||
return;
|
||||
|
||||
// If we somehow land in an invalid state (should be impossible), make sure we can recover
|
||||
default:
|
||||
su8State = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void PSoC_Cmd(PSoC_CMD_TX eCmd, uint8_t u8D0, uint8_t u8D1, uint8_t u8Blocking) {
|
||||
static uint8_t su8Ready = 0;
|
||||
if (u8Blocking) {
|
||||
su8Ready = 0;
|
||||
pu8PsocGotData = &su8Ready;
|
||||
}
|
||||
|
||||
static uint8_t u8Packet[5];
|
||||
u8Packet[0] = eCmd;
|
||||
u8Packet[1] = 2;
|
||||
u8Packet[2] = u8D0;
|
||||
u8Packet[3] = u8D1;
|
||||
u8Packet[4] = eCmd + 2 + u8D0 + u8D1;
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
while (UART_IS_TX_FULL(UART1))
|
||||
;
|
||||
UART_WRITE(UART1, u8Packet[i]);
|
||||
}
|
||||
|
||||
if (u8Blocking) {
|
||||
while (!su8Ready)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t PSoC_GetFingerCapacitance(void) {
|
||||
uint16_t u16FingerCap;
|
||||
|
||||
pu8PsocRxDestination = &u16FingerCap;
|
||||
pu8PsocRxDestinationLen = sizeof u16FingerCap;
|
||||
PSoC_Cmd(PSoC_CMD_TX_GET_FINGER_CAP, 0, 0, 1);
|
||||
|
||||
return u16FingerCap;
|
||||
// Swap endian
|
||||
// return (u16FingerCap >> 8) | ((u16FingerCap & 0xff) << 8);
|
||||
}
|
||||
void PSoC_GetDebug(PSoC_CMD_DEBUG u8Cmd, uint8_t* pu8Data, volatile uint8_t* pu8Ready) {
|
||||
pu8PsocGotData = pu8Ready;
|
||||
pu8PsocRxDestination = pu8Data;
|
||||
pu8PsocRxDestinationLen = 32;
|
||||
PSoC_Cmd(PSoC_CMD_TX_GET_DEBUG, 0, u8Cmd, 0);
|
||||
}
|
||||
void PSoC_SetFingerCapacitance(uint16_t u16FingerCap) {
|
||||
if (u16FingerCap > 1023) u16FingerCap = 1023;
|
||||
// PSoC_Cmd(PSoC_CMD_TX_SET_FINGER_CAP, u16FingerCap >> 8, u16FingerCap & 0xff, 1);
|
||||
PSoC_Cmd(PSoC_CMD_TX_SET_FINGER_CAP, u16FingerCap >> 8, u16FingerCap & 0xff, 1);
|
||||
}
|
||||
void PSoC_SetFingerCapacitanceFromConfig(void) {
|
||||
PSoC_SetFingerCapacitance(PSoC_FINGER_CAP_MIN + (16 - gConfig.u8Sens) * PSoC_FINGER_CAP_STEP);
|
||||
}
|
||||
void PSoC_EnableDebug(uint8_t u8D1, uint8_t u8D2) {
|
||||
// TODO: Finish figuring out what values these two bytes need
|
||||
PSoC_Cmd(PSoC_CMD_TX_ENABLE_DEBUG, u8D1, u8D2, 1);
|
||||
}
|
||||
|
||||
uint8_t gu8GroundData[32];
|
||||
|
||||
// These are used to uniformly narrow the min/max gap
|
||||
// #define SCALE_OFFSET_MIN 150
|
||||
// #define SCALE_OFFSET_MIN 100
|
||||
// #define SCALE_OFFSET_MAX 450
|
||||
|
||||
void PSoC_PostProcessing(void) {
|
||||
// Process the raw PSoC data to compute our external 0-255 values
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
uint8_t j = (15 - (i / 2)) * 2 + (i & 1);
|
||||
|
||||
const uint16_t u16Pad = gu16PSoCDiff[i];
|
||||
|
||||
const uint16_t u16Min = gConfig.u16PSoCScaleMin[i]; // + SCALE_OFFSET_MIN;
|
||||
const uint16_t u16Max = gConfig.u16PSoCScaleMax[i]; // - SCALE_OFFSET_MAX;
|
||||
|
||||
if (u16Pad < u16Min) {
|
||||
gu8GroundData[j] = 0;
|
||||
} else if (u16Pad > u16Max) {
|
||||
gu8GroundData[j] = 255;
|
||||
} else {
|
||||
// Multiply by 255 first to retain precision
|
||||
// This can overflow u16, hence the u32 cast pre-mult
|
||||
gu8GroundData[j] = ((uint32_t)(u16Pad - u16Min) * 255) / (u16Max - u16Min);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Calculate digital input data from PSoC values
|
||||
*
|
||||
* Must be called at exactly 1ms intervals
|
||||
*
|
||||
* Trigger will activate once, a 200ms delay, then again every 5ms.
|
||||
*/
|
||||
void PSoC_DigitalCalc(void) {
|
||||
// Calculate digital data for 32 pads
|
||||
uint32_t u32Previous = gu32PSoCDigital;
|
||||
gu32PSoCDigital = 0;
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
if (gu8GroundData[i] > PSoC_INTERNAL_DIGITAL_TH) {
|
||||
gu32PSoCDigital |= (1 << i);
|
||||
}
|
||||
}
|
||||
gu32PSoCDigitalPos = gu32PSoCDigital & ~u32Previous;
|
||||
gu32PSoCDigitalNeg = u32Previous & ~gu32PSoCDigital;
|
||||
gu32PSoCDigitalTrig = gu32PSoCDigitalPos;
|
||||
|
||||
// Calculate digital data for 16 cells
|
||||
uint16_t u16Previous = gu16PSoCDigital;
|
||||
gu16PSoCDigital = 0;
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (gu8GroundData[i * 2] > PSoC_INTERNAL_DIGITAL_TH ||
|
||||
gu8GroundData[i * 2 + 1] > PSoC_INTERNAL_DIGITAL_TH) {
|
||||
gu16PSoCDigital |= (1 << i);
|
||||
}
|
||||
}
|
||||
gu16PSoCDigitalPos = gu16PSoCDigital & ~u16Previous;
|
||||
gu16PSoCDigitalNeg = u16Previous & ~gu16PSoCDigital;
|
||||
gu16PSoCDigitalTrig = gu16PSoCDigitalPos;
|
||||
|
||||
static uint8_t u8TriggerCounter = 0;
|
||||
if (++u8TriggerCounter != 5) return;
|
||||
u8TriggerCounter = 0;
|
||||
|
||||
static uint8_t u8a16TriggerCounter[16] = { 0 };
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (!(gu16PSoCDigital & (1 << i))) {
|
||||
u8a16TriggerCounter[i] = 0;
|
||||
} else if (u8a16TriggerCounter[i] == 200 / 5) {
|
||||
// High-speed repeat
|
||||
gu16PSoCDigitalTrig |= (1 << i);
|
||||
} else {
|
||||
// Counter up to high-speed
|
||||
u8a16TriggerCounter[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t u8a32TriggerCounter[32] = { 0 };
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
if (!(gu32PSoCDigital & (1 << i))) {
|
||||
u8a32TriggerCounter[i] = 0;
|
||||
} else if (u8a32TriggerCounter[i] == 200 / 5) {
|
||||
// High-speed repeat
|
||||
gu32PSoCDigitalTrig |= (1 << i);
|
||||
} else {
|
||||
// Counter up to high-speed
|
||||
u8a32TriggerCounter[i]++;
|
||||
}
|
||||
}
|
||||
}
|
110
src/psoc.h
Normal file
110
src/psoc.h
Normal file
@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PSoC_DATA_SIZE 32
|
||||
#define PSoC_PACKET_SIZE (2 + PSoC_DATA_SIZE)
|
||||
|
||||
// Used for calculation of PSoC_FINGER_CAP_MIN
|
||||
// The difference between CAP and MIN must be divisible by 8
|
||||
#define PSoC_FINGER_CAP_MIN 20 // 0.2pF
|
||||
#define PSoC_DEFAULT_CAP 340 // 3.2pF
|
||||
// Maximum is CAP*2-MIN*2 ie 6.0pF
|
||||
|
||||
#define PSoC_FINGER_CAP_STEP ((PSoC_DEFAULT_CAP - PSoC_FINGER_CAP_MIN) / 8)
|
||||
|
||||
typedef enum {
|
||||
// Host -> PSoC
|
||||
PSoC_CMD_TX_GET_FINGER_CAP = 0xB5,
|
||||
PSoC_CMD_TX_GET_DEBUG = 0xB6,
|
||||
PSoC_CMD_TX_SET_FINGER_CAP = 0xBD,
|
||||
PSoC_CMD_TX_ENABLE_DEBUG = 0xDE,
|
||||
} PSoC_CMD_TX;
|
||||
typedef enum {
|
||||
// PSoC -> Host
|
||||
PSoC_CMD_RX_MASTER_DIFF = 0xAD,
|
||||
PSoC_CMD_RX_SLAVE_DIFF = 0xAF,
|
||||
PSoC_CMD_RX_REQUEST_FINGER_CAP = 0xC1,
|
||||
|
||||
// PSoC -> Host (Debug)
|
||||
PSoC_CMD_RX_MASTER_TOUCH_TH = 0xAA,
|
||||
PSoC_CMD_RX_SLAVE_TOUCH_TH = 0xAB,
|
||||
PSoC_CMD_RX_MASTER_FINGER_TH = 0xA0,
|
||||
PSoC_CMD_RX_MASTER_HYSTERESIS = 0xA1,
|
||||
PSoC_CMD_RX_SLAVE_FINGER_TH = 0xA2,
|
||||
PSoC_CMD_RX_SLAVE_HYSTERESIS = 0xA3,
|
||||
PSoC_CMD_RX_CS_START = 0x00,
|
||||
PSoC_CMD_RX_CS_END = 0xFF,
|
||||
|
||||
// Packets that get a direct response
|
||||
PSoC_CMD_RX_GET_FINGER_CAP = PSoC_CMD_TX_GET_FINGER_CAP,
|
||||
PSoC_CMD_RX_SET_FINGER_CAP = PSoC_CMD_TX_SET_FINGER_CAP,
|
||||
} PSoC_CMD_RX;
|
||||
typedef enum {
|
||||
PSoC_CMD_DEBUG_MASTER_TOUCH_TH = 0,
|
||||
PSoC_CMD_DEBUG_SLAVE_TOUCH_TH,
|
||||
PSoC_CMD_DEBUG_MASTER_FINGER_TH,
|
||||
PSoC_CMD_DEBUG_SLAVE_FINGER_TH,
|
||||
PSoC_CMD_DEBUG_MASTER_HYSTERESIS,
|
||||
PSoC_CMD_DEBUG_SLAVE_HYSTERESIS,
|
||||
} PSoC_CMD_DEBUG;
|
||||
|
||||
// Difference between the raw count value and the baseline, from SmartSense
|
||||
extern uint16_t gu16PSoCDiff[32];
|
||||
|
||||
// Has the difference data changed?
|
||||
extern volatile uint8_t bPSoCDirty;
|
||||
|
||||
// Used for producing gu32PSoCDigital and gu16PSoCDigital
|
||||
#define PSoC_INTERNAL_DIGITAL_TH 0
|
||||
|
||||
// PSoC data, re-interpreted as digital inputs
|
||||
extern uint32_t gu32PSoCDigital;
|
||||
extern uint32_t gu32PSoCDigitalPos;
|
||||
extern uint32_t gu32PSoCDigitalNeg;
|
||||
extern uint32_t gu32PSoCDigitalTrig;
|
||||
extern uint16_t gu16PSoCDigital;
|
||||
extern uint16_t gu16PSoCDigitalPos;
|
||||
extern uint16_t gu16PSoCDigitalNeg;
|
||||
extern uint16_t gu16PSoCDigitalTrig;
|
||||
|
||||
extern uint8_t gu8PSoCSeenData;
|
||||
|
||||
#define PSoC_RAW_T0 34
|
||||
#define PSoC_RAW_T1 91
|
||||
#define PSoC_RAW_T2 121
|
||||
#define PSoC_RAW_MIN 199
|
||||
#define PSoC_SCALE 5 // ie to scale from [0~4ff] to [0~ff]
|
||||
|
||||
#define PSoC_OUT_MIN 20
|
||||
#define PSoC_OUT_MAX 255
|
||||
|
||||
#define PSoC_SCALE_MIN (0 + 128)
|
||||
#define PSoC_SCALE_MAX (0x4ff - 128 - 256)
|
||||
#define PSoC_SCALE_RANGE (3) // ie to scale from [min~max] to [0~ff]
|
||||
|
||||
void PSoC_PostProcessing(void);
|
||||
void PSoC_DigitalCalc(void);
|
||||
|
||||
// General usage PSoC commands; return instantly
|
||||
void PSoC_SetFingerCapacitance(uint16_t u16FingerCap);
|
||||
void PSoC_SetFingerCapacitanceFromConfig(void);
|
||||
/**
|
||||
* @brief Get the finger capacitance value currently configured on the Master PSoC
|
||||
*
|
||||
* Warning! This function is BLOCKING. Calls are likely to take at least 15ms
|
||||
*/
|
||||
uint16_t PSoC_GetFingerCapacitance(void);
|
||||
/**
|
||||
* @brief Request a debug array from the PSoC pair
|
||||
*
|
||||
* This call is asynchronous. Use pu8Ready to ensure pu8Data is ready.
|
||||
* Only one call can be in-flight at once.
|
||||
* **DO NOT** call PSoCGetFingerCapacitance while waiting on this function.
|
||||
*
|
||||
* @param u8Cmd The specific debug array to request
|
||||
* @param pu8Data Pointer to array that will receive the data. Must be 32 bytes.
|
||||
* @param pu8Ready Optional uint8_t to signal the data is ready
|
||||
*/
|
||||
void PSoC_GetDebug(PSoC_CMD_DEBUG u8Cmd, uint8_t* pu8Data, volatile uint8_t* pu8Ready);
|
||||
void PSoC_EnableDebug(uint8_t u8D1, uint8_t u8D2);
|
177
src/slider.c
Normal file
177
src/slider.c
Normal file
@ -0,0 +1,177 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
#define SLIDER_SYNC 0xFF
|
||||
#define SLIDER_MARK 0xFD
|
||||
|
||||
static uint8_t su8AutoEnabled = 0;
|
||||
static uint8_t su8GotLedData = 0;
|
||||
static uint32_t su32SinceLastControlled = 0;
|
||||
|
||||
typedef enum {
|
||||
SLIDER_PARSE_SYNC_WAIT = 0,
|
||||
SLIDER_PARSE_CMD,
|
||||
SLIDER_PARSE_NDATA,
|
||||
SLIDER_PARSE_DATA,
|
||||
SLIDER_PARSE_CHECKSUM,
|
||||
} slider_parse_state;
|
||||
|
||||
typedef enum {
|
||||
SLIDER_CMD_AUTO = 0x01,
|
||||
SLIDER_CMD_SET_LED = 0x02,
|
||||
SLIDER_CMD_AUTO_START = 0x03,
|
||||
SLIDER_CMD_AUTO_STOP = 0x04,
|
||||
SLIDER_CMD_RESET = 0x10,
|
||||
SLIDER_CMD_GET_BOARD_INFO = 0xF0,
|
||||
} slider_cmd;
|
||||
|
||||
static const uint8_t su8SliderVersion[32] = {
|
||||
'1', '5', '3', '3', '0', ' ', ' ', ' ', 0xA0,
|
||||
|
||||
'0', '6', '7', '1', '2', 0xFF,
|
||||
|
||||
0x90,
|
||||
};
|
||||
|
||||
static inline void Slider_Write(uint8_t u8Byte) {
|
||||
if (u8Byte == SLIDER_SYNC || u8Byte == SLIDER_MARK) {
|
||||
USB_VCOM_Write(SLIDER_MARK);
|
||||
u8Byte--;
|
||||
}
|
||||
USB_VCOM_Write(u8Byte);
|
||||
}
|
||||
static void Slider_Respond(slider_cmd u8SliderCmd, const uint8_t* pu8Packet, uint8_t u8NPacket) {
|
||||
uint8_t u8Sum = SLIDER_SYNC + u8SliderCmd + u8NPacket;
|
||||
USB_VCOM_Write(SLIDER_SYNC); // We don't want to escape sync!
|
||||
Slider_Write(u8SliderCmd);
|
||||
Slider_Write(u8NPacket);
|
||||
|
||||
for (uint16_t i = 0; i < u8NPacket; i++) {
|
||||
u8Sum += pu8Packet[i];
|
||||
Slider_Write(pu8Packet[i]);
|
||||
}
|
||||
|
||||
Slider_Write(-u8Sum);
|
||||
}
|
||||
static void Slider_Process(slider_cmd u8SliderCmd, uint8_t* pu8Packet, uint8_t u8NPacket) {
|
||||
switch (u8SliderCmd) {
|
||||
case SLIDER_CMD_RESET:
|
||||
// Hmm? Do we not need to <su8AutoEnabled = 0;> here?
|
||||
Slider_Respond(SLIDER_CMD_RESET, NULL, 0);
|
||||
return;
|
||||
case SLIDER_CMD_GET_BOARD_INFO:
|
||||
Slider_Respond(SLIDER_CMD_GET_BOARD_INFO, su8SliderVersion, sizeof su8SliderVersion);
|
||||
return;
|
||||
|
||||
case SLIDER_CMD_SET_LED:
|
||||
// TODO: What is the first byte of data? (00h and 28h observed)
|
||||
// Why are there 32 triples?
|
||||
if (u8NPacket == 1 + 0x60) {
|
||||
gbLedDataIsControlledExt = 1;
|
||||
su32SinceLastControlled = 0;
|
||||
memcpy(gu8aControlledExtLedData, &pu8Packet[1], 3 * 32);
|
||||
}
|
||||
su8GotLedData = 1;
|
||||
// No response
|
||||
return;
|
||||
|
||||
case SLIDER_CMD_AUTO_START:
|
||||
su8AutoEnabled = 1;
|
||||
su8GotLedData = 1;
|
||||
// No response
|
||||
return;
|
||||
case SLIDER_CMD_AUTO_STOP:
|
||||
// Purge any Tx buffer from the auto sending
|
||||
if (su8AutoEnabled) USB_VCOM_PurgeTx();
|
||||
su8AutoEnabled = 0;
|
||||
Slider_Respond(SLIDER_CMD_AUTO_STOP, NULL, 0);
|
||||
return;
|
||||
|
||||
// This is an outbound-only command, so we should never see it here!
|
||||
case SLIDER_CMD_AUTO:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Slider_TickSerial(void) {
|
||||
/**
|
||||
* Byte 0: FF
|
||||
* Byte 1: Command
|
||||
* Byte 2: Length (n)
|
||||
* Byte [3~2+n]: Data
|
||||
* Byte [3+n]: Checksum
|
||||
*
|
||||
* Byte FD is escape; the next byte should +1'd
|
||||
*/
|
||||
|
||||
static slider_parse_state su8State = SLIDER_PARSE_SYNC_WAIT;
|
||||
static uint8_t u8Mark = 0;
|
||||
static uint8_t u8NPacket = 0;
|
||||
static uint8_t u8NRead = 0;
|
||||
static uint8_t u8Sum = 0;
|
||||
static uint8_t u8SliderCmd = 0;
|
||||
|
||||
static uint8_t u8Packet[0x61]; // The largest inbound packet expected is to set LEDs
|
||||
|
||||
// Make sure we flush the buffer!
|
||||
while (USB_VCOM_Available()) {
|
||||
uint8_t u8Byte = USB_VCOM_Read();
|
||||
if (u8Byte == SLIDER_MARK) {
|
||||
u8Mark = 1;
|
||||
continue;
|
||||
} else if (u8Mark) {
|
||||
u8Mark = 0;
|
||||
// TODO: If u8Byte is 0xFD we should technically give up here
|
||||
u8Byte++;
|
||||
}
|
||||
|
||||
u8Sum += u8Byte;
|
||||
switch (su8State) {
|
||||
case SLIDER_PARSE_SYNC_WAIT:
|
||||
u8Sum = 0xff;
|
||||
if (u8Byte == SLIDER_SYNC) su8State = SLIDER_PARSE_CMD;
|
||||
break;
|
||||
case SLIDER_PARSE_CMD:
|
||||
u8SliderCmd = u8Byte;
|
||||
su8State = SLIDER_PARSE_NDATA;
|
||||
break;
|
||||
case SLIDER_PARSE_NDATA:
|
||||
u8NPacket = u8Byte;
|
||||
u8NRead = 0;
|
||||
su8State = SLIDER_PARSE_DATA;
|
||||
|
||||
// If this is more data than we could handle, just give up
|
||||
if (u8NPacket > sizeof u8Packet) su8State = SLIDER_PARSE_SYNC_WAIT;
|
||||
// If there's nothing to do.. do nothing!
|
||||
if (u8NPacket == 0) su8State = SLIDER_PARSE_CHECKSUM;
|
||||
break;
|
||||
case SLIDER_PARSE_DATA:
|
||||
u8Packet[u8NRead++] = u8Byte;
|
||||
if (u8NRead == u8NPacket) su8State = SLIDER_PARSE_CHECKSUM;
|
||||
break;
|
||||
case SLIDER_PARSE_CHECKSUM:
|
||||
// Only handle the packet if the sum equaled out
|
||||
if (u8Sum == 0) Slider_Process(u8SliderCmd, u8Packet, u8NPacket);
|
||||
|
||||
su8State = SLIDER_PARSE_SYNC_WAIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Slider_Tick1ms() {
|
||||
if (gbLedDataIsControlledExt) {
|
||||
// If we haven't had an LED packet in 5 seconds, call it quits
|
||||
if (++su32SinceLastControlled == 5 * 1000) gbLedDataIsControlledExt = 0;
|
||||
}
|
||||
|
||||
if (su8AutoEnabled) {
|
||||
static uint8_t u8Counter = 0;
|
||||
// Only actually send an update every 8ms
|
||||
if (++u8Counter != 8) return;
|
||||
|
||||
u8Counter = 0;
|
||||
|
||||
Slider_Respond(SLIDER_CMD_AUTO, gu8GroundData, sizeof gu8GroundData);
|
||||
}
|
||||
}
|
53
src/slider.h
Normal file
53
src/slider.h
Normal file
@ -0,0 +1,53 @@
|
||||
// 16 cells (0-15)
|
||||
#define CELL_0_Msk BIT15
|
||||
#define CELL_1_Msk BIT14
|
||||
#define CELL_2_Msk BIT13
|
||||
#define CELL_3_Msk BIT12
|
||||
#define CELL_4_Msk BIT11
|
||||
#define CELL_5_Msk BIT10
|
||||
#define CELL_6_Msk BIT9
|
||||
#define CELL_7_Msk BIT8
|
||||
#define CELL_8_Msk BIT7
|
||||
#define CELL_9_Msk BIT6
|
||||
#define CELL_10_Msk BIT5
|
||||
#define CELL_11_Msk BIT4
|
||||
#define CELL_12_Msk BIT3
|
||||
#define CELL_13_Msk BIT2
|
||||
#define CELL_14_Msk BIT1
|
||||
#define CELL_15_Msk BIT0
|
||||
// 32 pads (1-32)
|
||||
#define PAD_1_Msk BIT30
|
||||
#define PAD_2_Msk BIT31
|
||||
#define PAD_3_Msk BIT28
|
||||
#define PAD_4_Msk BIT29
|
||||
#define PAD_5_Msk BIT26
|
||||
#define PAD_6_Msk BIT27
|
||||
#define PAD_7_Msk BIT24
|
||||
#define PAD_8_Msk BIT25
|
||||
#define PAD_9_Msk BIT22
|
||||
#define PAD_10_Msk BIT23
|
||||
#define PAD_11_Msk BIT20
|
||||
#define PAD_12_Msk BIT21
|
||||
#define PAD_13_Msk BIT18
|
||||
#define PAD_14_Msk BIT19
|
||||
#define PAD_15_Msk BIT16
|
||||
#define PAD_16_Msk BIT17
|
||||
#define PAD_17_Msk BIT14
|
||||
#define PAD_18_Msk BIT15
|
||||
#define PAD_19_Msk BIT12
|
||||
#define PAD_20_Msk BIT13
|
||||
#define PAD_21_Msk BIT10
|
||||
#define PAD_22_Msk BIT11
|
||||
#define PAD_23_Msk BIT8
|
||||
#define PAD_24_Msk BIT9
|
||||
#define PAD_25_Msk BIT6
|
||||
#define PAD_26_Msk BIT7
|
||||
#define PAD_27_Msk BIT4
|
||||
#define PAD_28_Msk BIT5
|
||||
#define PAD_29_Msk BIT2
|
||||
#define PAD_30_Msk BIT3
|
||||
#define PAD_31_Msk BIT0
|
||||
#define PAD_32_Msk BIT1
|
||||
|
||||
void Slider_TickSerial(void);
|
||||
void Slider_Tick1ms(void);
|
158
src/sys.c
Normal file
158
src/sys.c
Normal file
@ -0,0 +1,158 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
#ifdef stdout
|
||||
// Unnecessary for compilation, but clangd can get a bit confused
|
||||
#undef stdout
|
||||
#endif
|
||||
// For picolibc
|
||||
FILE *const stdout = NULL;
|
||||
|
||||
void SYS_ResetModule(uint32_t u32ModuleIndex) {
|
||||
// Generate reset signal to the corresponding module
|
||||
*(volatile uint32_t *)((uint32_t)&SYS->IPRSTC1 + (u32ModuleIndex >> 24)) |=
|
||||
1 << (u32ModuleIndex & 0x00ffffff);
|
||||
|
||||
// Release corresponding module from reset state
|
||||
*(volatile uint32_t *)((uint32_t)&SYS->IPRSTC1 + (u32ModuleIndex >> 24)) &=
|
||||
~(1 << (u32ModuleIndex & 0x00ffffff));
|
||||
}
|
||||
|
||||
void SYS_Init(void) {
|
||||
// Enable XT1_OUT (PF.0) and XT1_IN (PF.1)
|
||||
SYS->GPF_MFP &= ~(SYS_GPF_MFP_PF0_Msk | SYS_GPF_MFP_PF1_Msk);
|
||||
SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;
|
||||
|
||||
// Enable Internal RC 22.1184 MHz clock
|
||||
CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
|
||||
|
||||
// Switch HCLK clock source to Internal RC and HCLK source divide 1
|
||||
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
|
||||
|
||||
// Enable external XTAL 12 MHz clock
|
||||
CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);
|
||||
CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);
|
||||
|
||||
// Set core clock
|
||||
CLK_SetCoreClock(72000000);
|
||||
|
||||
// Enable module clocks
|
||||
CLK_EnableModuleClock(UART1_MODULE);
|
||||
CLK_EnableModuleClock(USBD_MODULE);
|
||||
CLK_EnableModuleClock(TMR0_MODULE);
|
||||
CLK_EnableModuleClock(I2C1_MODULE);
|
||||
// Select module clock sources
|
||||
CLK_SetModuleClock(UART1_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));
|
||||
CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV_USB(3));
|
||||
CLK_SetModuleClock(TMR0_MODULE, 0, 0);
|
||||
CLK_SetModuleClock(I2C1_MODULE, 0, 0);
|
||||
|
||||
// Set GPB multi-function pins for UART1 RXD(PB4) and TXD(PB5)
|
||||
SYS->GPB_MFP &= ~(SYS_GPB_MFP_PB4_Msk | SYS_GPB_MFP_PB5_Msk);
|
||||
SYS->GPB_MFP |= SYS_GPB_MFP_PB4_UART1_RXD | SYS_GPB_MFP_PB5_UART1_TXD;
|
||||
|
||||
GPIO_SetMode(_PIN_SDA, GPIO_PMD_OUTPUT);
|
||||
GPIO_SetMode(_PIN_SCL, GPIO_PMD_OUTPUT);
|
||||
PIN_SDA = 1;
|
||||
PIN_SCL = 1;
|
||||
|
||||
// Configure our GPIO pins
|
||||
GPIO_SetMode(_PIN_EC1, GPIO_PMD_INPUT);
|
||||
GPIO_SetMode(_PIN_RX2, GPIO_PMD_INPUT);
|
||||
GPIO_SetMode(_PIN_RX3, GPIO_PMD_INPUT);
|
||||
GPIO_SetMode(_PIN_RX4, GPIO_PMD_INPUT);
|
||||
GPIO_SetMode(_PIN_EC2, GPIO_PMD_INPUT);
|
||||
GPIO_SetMode(_PIN_EC3, GPIO_PMD_INPUT);
|
||||
GPIO_SetMode(_PIN_USB_MUX_SEL, GPIO_PMD_OUTPUT);
|
||||
GPIO_SetMode(_PIN_USB_MUX_EN, GPIO_PMD_OUTPUT);
|
||||
GPIO_SetMode(_PIN_LED_WING_PWR, GPIO_PMD_OUTPUT);
|
||||
GPIO_SetMode(_PIN_LED_GROUND_PWR, GPIO_PMD_OUTPUT);
|
||||
|
||||
PIN_LED_WING_PWR = 1;
|
||||
PIN_LED_GROUND_PWR = 1;
|
||||
|
||||
GPIO_SetMode(_PIN_FN2, GPIO_PMD_INPUT);
|
||||
// TODO:
|
||||
if (PIN_FN2 == 0) {
|
||||
PIN_USB_MUX_SEL = USB_MUX_LEDS;
|
||||
PIN_USB_MUX_EN = USB_MUX_ENABLE;
|
||||
GPIO_SetMode(_PIN_SDA, GPIO_PMD_OUTPUT);
|
||||
GPIO_SetMode(_PIN_SCL, GPIO_PMD_OUTPUT);
|
||||
PIN_SDA = 0;
|
||||
PIN_SCL = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set GPA multi-function pins for I2C1 SDA and SCL
|
||||
SYS->GPA_MFP &= ~(SYS_GPA_MFP_PA10_Msk | SYS_GPA_MFP_PA11_Msk);
|
||||
SYS->GPA_MFP |= (SYS_GPA_MFP_PA10_I2C1_SDA | SYS_GPA_MFP_PA11_I2C1_SCL);
|
||||
SYS->ALT_MFP &= ~(SYS_ALT_MFP_PA10_Msk | SYS_ALT_MFP_PA11_Msk);
|
||||
SYS->ALT_MFP |= (SYS_ALT_MFP_PA10_I2C1_SDA | SYS_ALT_MFP_PA11_I2C1_SCL);
|
||||
|
||||
PIN_USB_MUX_EN = USB_MUX_ENABLE;
|
||||
PIN_USB_MUX_SEL = USB_MUX_HOST;
|
||||
}
|
||||
|
||||
void SYS_ModuleInit(void) {
|
||||
// Setup UART1
|
||||
SYS_ResetModule(UART1_RST);
|
||||
UART_Open(UART1, 460800);
|
||||
/* Enable interrupts for:
|
||||
* - Receive data available
|
||||
* - Receive line status
|
||||
* - RX time-out
|
||||
*/
|
||||
UART1->IER = (UART_IER_RDA_IEN_Msk | UART_IER_RLS_IEN_Msk | UART_IER_RTO_IEN_Msk);
|
||||
NVIC_EnableIRQ(UART1_IRQn);
|
||||
|
||||
// Set NVIC priorities
|
||||
NVIC_SetPriority(USBD_IRQn, 1);
|
||||
NVIC_SetPriority(TMR0_IRQn, 2);
|
||||
NVIC_SetPriority(I2S_IRQn, 3);
|
||||
NVIC_SetPriority(I2C0_IRQn, 4);
|
||||
|
||||
CLK_SysTickDelay(10 ms);
|
||||
|
||||
// For communication with the LED MCU
|
||||
LED_I2C1_Init();
|
||||
|
||||
// Timer 0: Used for HID, PSoC processing and slider outbound
|
||||
// This timer runs at 4kHz, but only sets the 1ms flag every 4 calls
|
||||
TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 4 kHz);
|
||||
TIMER_EnableInt(TIMER0);
|
||||
NVIC_EnableIRQ(TMR0_IRQn);
|
||||
TIMER_Start(TIMER0);
|
||||
|
||||
// Setup our USB stack
|
||||
Tas_USBD_Open();
|
||||
Tas_USBD_Init();
|
||||
Tas_USBD_Start();
|
||||
NVIC_EnableIRQ(USBD_IRQn);
|
||||
}
|
||||
|
||||
// Define a dedicated symbol for this, so we can easily trap it with a debugger!
|
||||
void HardFault_Handler() {
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void SYS_Bootloader_Check() {
|
||||
FMC_Open();
|
||||
while (FMC_Read(BOOTLOADER_MAGIC_ADDR) != BOOTLOADER_MAGIC)
|
||||
;
|
||||
FMC_Close();
|
||||
}
|
||||
|
||||
volatile uint8_t gu8Do250usTick = 0;
|
||||
volatile uint8_t gu8Do1msTick = 0;
|
||||
void TMR0_IRQHandler(void) {
|
||||
static uint32_t su32Counter;
|
||||
if (TIMER_GetIntFlag(TIMER0)) {
|
||||
TIMER_ClearIntFlag(TIMER0);
|
||||
gu8Do250usTick = 1;
|
||||
if (++su32Counter == 4) {
|
||||
su32Counter = 0;
|
||||
gu8Do1msTick = 1;
|
||||
}
|
||||
}
|
||||
}
|
275
src/tasoller.h
Normal file
275
src/tasoller.h
Normal file
@ -0,0 +1,275 @@
|
||||
#pragma once
|
||||
#include <NUC123.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ms *1000
|
||||
#define kHz *1000
|
||||
|
||||
/* === LEDs === */
|
||||
#define LED_Tx_BUFFER 254
|
||||
// Defined as volatile due to the I2C interrupt reading at random times!
|
||||
extern volatile uint8_t gu8LEDTx[LED_Tx_BUFFER];
|
||||
|
||||
/* === DAO-DRM === */
|
||||
// * For now the bootloader check is being left enabled.
|
||||
// * It'll help catch if I break that in my bootloader :P
|
||||
#define ENABLE_BOOTLOADER_CHECK
|
||||
#define BOOTLOADER_MAGIC 0x5555A320
|
||||
#define BOOTLOADER_MAGIC_ADDR 0x100FF8
|
||||
|
||||
/* === USB definitions === */
|
||||
#include "usb_inc/hid.h"
|
||||
#include "usb_inc/keymap.h"
|
||||
#include "usb_inc/usb.h"
|
||||
|
||||
/* === Local files === */
|
||||
#include "fmc_user.h"
|
||||
#include "led.h"
|
||||
#include "pins.h"
|
||||
#include "psoc.h"
|
||||
#include "slider.h"
|
||||
|
||||
#define IO4_VENDOR "SEGA INTERACTIVE"
|
||||
// Product description
|
||||
#define _IO4_PRODUCT \
|
||||
"I/O CONTROL BD;" /* Board type */ \
|
||||
"15257 ;" /* Board number */ \
|
||||
"01;" /* Mode */ \
|
||||
"90;" /* Firmware revision */ \
|
||||
"1831;" /* Firmware checksum */ \
|
||||
"6679A;" /* Chip number */ \
|
||||
"00;" /* Config */
|
||||
// Functional description
|
||||
#define _IO4_FUNCTION \
|
||||
"GOUT=14_" /* General purpose output (20) */ \
|
||||
"ADIN=8,E_" /* ADC input (8) */ \
|
||||
"ROTIN=4_" /* Rotary input (4) */ \
|
||||
"COININ=2_" /* Coin input (2) */ \
|
||||
"SWIN=2,E_" /* Switch inputs (2) */ \
|
||||
"UQ1=41,6;" /* Unique function 1 (?) */
|
||||
#define IO4_PRODUCT _IO4_PRODUCT _IO4_FUNCTION
|
||||
#define IO4_VID 0x0CA3
|
||||
#define IO4_PID 0x0021
|
||||
|
||||
#define INCR(x, y) ((x) = (x) < (y) ? (x) + 1 : (y))
|
||||
#define DECR(x, y) ((x) = (x) > (y) ? (x) - 1 : (y))
|
||||
#define MOD_INCR(x, y) ((x) = (x) == ((y)-1) ? 0 : ((x) + 1))
|
||||
#define MOD_DECR(x, y) ((x) = (x) == 0 ? ((y)-1) : ((x)-1))
|
||||
#define INV(x) ((x) = 1 - (x))
|
||||
|
||||
extern volatile uint8_t gu8VcomReady;
|
||||
/**
|
||||
* WARNING: This is both used internally and sent verbatim over serial
|
||||
* It **MUST** be 32 bytes of ground data
|
||||
*/
|
||||
extern uint8_t gu8GroundData[32];
|
||||
|
||||
/* === For HID === */
|
||||
enum {
|
||||
HID_REPORT_ID_IO4 = 1,
|
||||
HID_REPORT_ID_KEYBOARD,
|
||||
HID_REPORT_ID_DEBUG_A,
|
||||
HID_REPORT_ID_DEBUG_B,
|
||||
HID_REPORT_ID_IO4_CMD = 16,
|
||||
};
|
||||
|
||||
#define NUM_FN 2
|
||||
#define NUM_AIR 6
|
||||
#define NUM_GROUND 32
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint8_t bKeyboard[NUM_FN + NUM_AIR + NUM_GROUND];
|
||||
} hid_report_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint16_t wADC[8];
|
||||
uint16_t wRotary[4];
|
||||
uint16_t wCoin[2];
|
||||
uint16_t wButtons[2];
|
||||
uint8_t bSystemStatus;
|
||||
uint8_t bUsbStatus;
|
||||
uint8_t bUnique[29];
|
||||
} io4_hid_in_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint8_t bCmd;
|
||||
uint8_t bData[62];
|
||||
} io4_hid_out_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint16_t wData[16];
|
||||
} debug_hid_report_t;
|
||||
|
||||
extern uint8_t gu8DigitalButtons;
|
||||
|
||||
// void HID_Tick();
|
||||
void USBD_HID_PrepareReport();
|
||||
uint8_t *USBD_HID_GetReport(uint8_t u8ReportId, uint32_t *pu32Size);
|
||||
void USBD_HID_SetReport(volatile uint8_t *pu8EpBuf, uint32_t u32Size);
|
||||
|
||||
// For CDC
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t u32DTERate; // Baud rate
|
||||
uint8_t u8CharFormat; // Stop bit
|
||||
uint8_t u8ParityType; // Parity
|
||||
uint8_t u8DataBits; // Data bits
|
||||
} STR_VCOM_LINE_CODING;
|
||||
extern volatile int8_t gi8BulkOutReady;
|
||||
extern STR_VCOM_LINE_CODING gLineCoding;
|
||||
extern uint16_t gCtrlSignal;
|
||||
extern volatile uint16_t comRbytes;
|
||||
extern volatile uint16_t comRhead;
|
||||
extern volatile uint16_t comRtail;
|
||||
extern volatile uint16_t comTbytes;
|
||||
extern volatile uint16_t comThead;
|
||||
extern volatile uint16_t comTtail;
|
||||
extern volatile uint8_t *gpu8RxBuf;
|
||||
extern volatile uint32_t gu32RxSize;
|
||||
extern volatile uint32_t gu32TxSize;
|
||||
// For HID
|
||||
extern uint8_t volatile gu8HIDIO4Ready;
|
||||
extern uint8_t volatile gu8HIDMiscReady;
|
||||
// General USB control
|
||||
extern uint8_t volatile g_u8Suspend;
|
||||
extern uint8_t g_u8Idle;
|
||||
extern uint8_t g_u8Protocol;
|
||||
|
||||
extern const char *gszVendorInitial;
|
||||
extern const char *gszVendor;
|
||||
extern const char *gszProduct;
|
||||
extern const usb_device_descr_t *gpDeviceDescriptor;
|
||||
extern const usb_desc_config_t *gpConfigDescriptor;
|
||||
extern const uint32_t gu32HidDescIO4Offset;
|
||||
extern const uint32_t gu32HidDescMiscOffset;
|
||||
extern const uint32_t gu32UsbHidIO4ReportLen;
|
||||
extern const uint32_t gu32UsbHidMiscReportLen;
|
||||
extern const uint8_t *gpu8UsbHidIO4Report;
|
||||
extern const uint8_t *gpu8UsbHidMiscReport;
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
// Interfaces
|
||||
enum {
|
||||
USBD_ITF_CDC_CMD,
|
||||
USBD_ITF_CDC_DAT,
|
||||
USBD_ITF_HID_IO4,
|
||||
USBD_ITF_HID_MISC,
|
||||
_USBD_ITF_MAX,
|
||||
};
|
||||
|
||||
// Endpoint number mapping
|
||||
#define EP_CTRL_IN EP0
|
||||
#define EP_CTRL_OUT EP1
|
||||
#define EP_CDC_IN EP2
|
||||
#define EP_CDC_OUT EP3
|
||||
#define EP_CDC_CMD EP4
|
||||
#define EP_HID_IO4_IN EP5
|
||||
#define EP_HID_MISC_IN EP6
|
||||
#define EP_HID_MISC_OUT EP7
|
||||
|
||||
#define _USBD_INTSTS(x) USBD_INTSTS_EP##x
|
||||
#define USBD_INTSTS(x) _USBD_INTSTS(x)
|
||||
|
||||
// Must match the above!!
|
||||
#define USBD_INTSTS_CTRL_IN USBD_INTSTS(EP_CTRL_IN)
|
||||
#define USBD_INTSTS_CTRL_OUT USBD_INTSTS(EP_CTRL_OUT)
|
||||
#define USBD_INTSTS_CDC_IN USBD_INTSTS(EP_CDC_IN)
|
||||
#define USBD_INTSTS_CDC_OUT USBD_INTSTS(EP_CDC_OUT)
|
||||
#define USBD_INTSTS_CDC_CMD USBD_INTSTS(EP_CDC_CMD)
|
||||
#define USBD_INTSTS_HID_IO4_IN USBD_INTSTS(EP_HID_IO4_IN)
|
||||
#define USBD_INTSTS_HID_MISC_IN USBD_INTSTS(EP_HID_MISC_IN)
|
||||
#define USBD_INTSTS_HID_MISC_OUT USBD_INTSTS(EP_HID_MISC_OUT)
|
||||
|
||||
#define USBD_CDC_EP_IN (1 | EP_INPUT)
|
||||
#define USBD_CDC_EP_OUT (2 | EP_OUTPUT)
|
||||
#define USBD_CDC_EP_CMD (3 | EP_INPUT)
|
||||
#define USBD_HID_IO4_EP_IN (4 | EP_INPUT)
|
||||
#define USBD_HID_MISC_EP_IN (5 | EP_INPUT)
|
||||
#define USBD_HID_MISC_EP_OUT (6 | EP_OUTPUT)
|
||||
|
||||
#define USBD_SETUP_BUF_LEN (8)
|
||||
#define USBD_CDC_CMD_MAX_SIZE (16)
|
||||
#define USBD_CDC_IN_MAX_SIZE (64) // Device -> Host
|
||||
#define USBD_CDC_OUT_MAX_SIZE (64) // Host -> Device
|
||||
#define USBD_HID_BUF_LEN (64)
|
||||
|
||||
// Endpoint packet max size (cannot total more than 512!)
|
||||
#define EP0_MAX_PKT_SIZE 64
|
||||
#define EP1_MAX_PKT_SIZE 64
|
||||
#define EP2_MAX_PKT_SIZE USBD_CDC_IN_MAX_SIZE
|
||||
#define EP3_MAX_PKT_SIZE USBD_CDC_OUT_MAX_SIZE
|
||||
#define EP4_MAX_PKT_SIZE USBD_CDC_CMD_MAX_SIZE
|
||||
#define EP5_MAX_PKT_SIZE USBD_HID_BUF_LEN
|
||||
#define EP6_MAX_PKT_SIZE USBD_HID_BUF_LEN
|
||||
#define EP7_MAX_PKT_SIZE USBD_HID_BUF_LEN
|
||||
|
||||
#define SETUP_BUF_BASE 0
|
||||
#define SETUP_BUF_LEN 8
|
||||
|
||||
#if (SETUP_BUF_LEN + EP0_MAX_PKT_SIZE + EP1_MAX_PKT_SIZE + EP2_MAX_PKT_SIZE + EP3_MAX_PKT_SIZE + \
|
||||
EP4_MAX_PKT_SIZE + EP5_MAX_PKT_SIZE + EP6_MAX_PKT_SIZE + EP7_MAX_PKT_SIZE) > 512
|
||||
#error USB endpoint packet sizes exceeds 512-byte maximum
|
||||
#endif
|
||||
|
||||
#define EP0_BUF_BASE (SETUP_BUF_BASE + SETUP_BUF_LEN)
|
||||
#define EP1_BUF_BASE (EP0_BUF_BASE + EP0_MAX_PKT_SIZE)
|
||||
#define EP2_BUF_BASE (EP1_BUF_BASE + EP1_MAX_PKT_SIZE)
|
||||
#define EP3_BUF_BASE (EP2_BUF_BASE + EP2_MAX_PKT_SIZE)
|
||||
#define EP4_BUF_BASE (EP3_BUF_BASE + EP3_MAX_PKT_SIZE)
|
||||
#define EP5_BUF_BASE (EP4_BUF_BASE + EP4_MAX_PKT_SIZE)
|
||||
#define EP6_BUF_BASE (EP5_BUF_BASE + EP5_MAX_PKT_SIZE)
|
||||
#define EP7_BUF_BASE (EP5_BUF_BASE + EP6_MAX_PKT_SIZE)
|
||||
|
||||
// Define Descriptor information
|
||||
#define HID_IO4_INT_IN_INTERVAL 8
|
||||
#define HID_DEFAULT_INT_IN_INTERVAL 1
|
||||
#define HID_DEFAULT_INT_OUT_INTERVAL 1
|
||||
#define USBD_SELF_POWERED 0
|
||||
#define USBD_REMOTE_WAKEUP 0
|
||||
#define USBD_MAX_POWER (500 / 2)
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
#define HEX_NIBBLE(x) ("0123456789ABCDEF"[(x)&0xf])
|
||||
|
||||
void SYS_Init(void);
|
||||
void SYS_Bootloader_Check(void);
|
||||
void SYS_ModuleInit(void);
|
||||
extern volatile uint8_t gu8Do250usTick;
|
||||
extern volatile uint8_t gu8Do1msTick;
|
||||
|
||||
void EP_CDC_CMD_Handler(void);
|
||||
void EP_CDC_OUT_Handler(void);
|
||||
void EP_CDC_IN_Handler(void);
|
||||
void EP_HID_IO4_IN_Handler(void);
|
||||
void EP_HID_MISC_IN_Handler(void);
|
||||
void EP_HID_MISC_OUT_Handler(void);
|
||||
|
||||
void USB_VCOM_Write(uint8_t u8Char);
|
||||
uint16_t USB_VCOM_Available(void);
|
||||
uint8_t USB_VCOM_Read(void);
|
||||
void USB_VCOM_Tick(void);
|
||||
void USB_VCOM_PurgeTx(void);
|
||||
|
||||
void UI_Tick(void);
|
||||
|
||||
void DelayCycles(uint32_t u32Cycles);
|
||||
#define DelayCycles_Small(x) \
|
||||
for (int i = 0; i < (x); i++) __asm__ volatile("" : "+g"(i) : :);
|
||||
|
||||
// Custom USBD implementation
|
||||
void Tas_USBD_Open(void);
|
||||
void Tas_USBD_Init(void);
|
||||
void Tas_USBD_Start(void);
|
||||
void Tas_USBD_ClassRequest(void);
|
||||
void Tas_USBD_GetSetupPacket(usb_setup_t *buf);
|
||||
void Tas_USBD_ProcessSetupPacket(void);
|
||||
void Tas_USBD_PrepareCtrlIn(void *pu8Buf, uint32_t u32Size);
|
||||
void Tas_USBD_CtrlIn(void);
|
||||
void Tas_USBD_PrepareCtrlOut(void *pu8Buf, uint32_t u32Size,
|
||||
void (*pCallback)(volatile uint8_t *, uint32_t));
|
||||
void Tas_USBD_CtrlOut(void);
|
||||
void Tas_USBD_SwReset(void);
|
||||
extern volatile uint8_t *g_usbd_CtrlInPointer;
|
||||
extern volatile uint32_t g_usbd_CtrlInSize;
|
249
src/ui.c
Normal file
249
src/ui.c
Normal file
@ -0,0 +1,249 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
#define FN2_HOLD_TIME 250 // ms of FN2 to enter config
|
||||
#define FN1_HOLD_TIME 2000 // ms of FN1 to enter calibration
|
||||
|
||||
// All three of these are scaled based on gConfig.u8Sens
|
||||
#define CALIB_HANDS_MIN 100 // If we read less than this, ignore it
|
||||
#define CALIB_HANDS_REQ 700 // All values are required to be greater than this
|
||||
#define CALIB_HANDS_MAX 1300 // Scale from orange to green between [req] and [max]
|
||||
|
||||
#define RED 0
|
||||
#define GREEN 120
|
||||
#define BLUE 240
|
||||
|
||||
static void UI_TickSensitivity(void) {
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
gaControlledIntLedData[i].u16H = 0;
|
||||
gaControlledIntLedData[i].u8S = (gConfig.u8Sens - 1) * 16;
|
||||
gaControlledIntLedData[i].u8V = 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < gConfig.u8Sens; i++) gaControlledIntLedData[i * 2].u8V = 255;
|
||||
|
||||
// Preferentially allow decreasing of sensitivity, in case it's been taken up too high
|
||||
if (gu32PSoCDigitalPos & PAD_26_Msk && gConfig.u8Sens > 1) {
|
||||
gConfig.u8Sens--;
|
||||
} else if (gu32PSoCDigitalPos & PAD_25_Msk && gConfig.u8Sens < 16) {
|
||||
gConfig.u8Sens++;
|
||||
}
|
||||
}
|
||||
|
||||
static void UI_TickSettings(void) {
|
||||
// If either of the sensitivity settings are being changed, just render that
|
||||
static uint8_t su8SensTimeout = 0;
|
||||
if (gu16PSoCDigital & CELL_12_Msk) {
|
||||
su8SensTimeout = 150;
|
||||
UI_TickSensitivity();
|
||||
return;
|
||||
} else if (su8SensTimeout) {
|
||||
su8SensTimeout--;
|
||||
UI_TickSensitivity();
|
||||
|
||||
// Save the sensitivity on exit
|
||||
if (su8SensTimeout == 0) PSoC_SetFingerCapacitanceFromConfig();
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
gaControlledIntLedData[i].u16H = 0;
|
||||
gaControlledIntLedData[i].u8S = 255;
|
||||
gaControlledIntLedData[i].u8V = 0;
|
||||
}
|
||||
|
||||
{ // LED colour control
|
||||
gaControlledIntLedData[LED_CELL_0].u16H = gConfig.u16HueWingLeft;
|
||||
gaControlledIntLedData[LED_CELL_0].u8V = 255;
|
||||
gaControlledIntLedData[LED_CELL_1].u16H = gConfig.u16HueGround;
|
||||
gaControlledIntLedData[LED_CELL_1].u8V = 255;
|
||||
gaControlledIntLedData[LED_DIVIDER_1_2].u16H = gConfig.u16HueGroundActive;
|
||||
gaControlledIntLedData[LED_DIVIDER_1_2].u8V = 255;
|
||||
gaControlledIntLedData[LED_CELL_2].u16H = gConfig.u16HueGround;
|
||||
gaControlledIntLedData[LED_CELL_2].u8V = 255;
|
||||
gaControlledIntLedData[LED_CELL_3].u16H = gConfig.u16HueWingRight;
|
||||
gaControlledIntLedData[LED_CELL_3].u8V = 255;
|
||||
|
||||
if (gu32PSoCDigitalTrig & PAD_1_Msk) MOD_INCR(gConfig.u16HueWingLeft, LED_HUE_MAX);
|
||||
if (gu32PSoCDigitalTrig & PAD_2_Msk) MOD_DECR(gConfig.u16HueWingLeft, LED_HUE_MAX);
|
||||
if (gu32PSoCDigitalTrig & PAD_3_Msk) MOD_INCR(gConfig.u16HueGround, LED_HUE_MAX);
|
||||
if (gu32PSoCDigitalTrig & PAD_4_Msk) MOD_DECR(gConfig.u16HueGround, LED_HUE_MAX);
|
||||
if (gu32PSoCDigitalTrig & PAD_5_Msk) MOD_INCR(gConfig.u16HueGroundActive, LED_HUE_MAX);
|
||||
if (gu32PSoCDigitalTrig & PAD_6_Msk) MOD_DECR(gConfig.u16HueGroundActive, LED_HUE_MAX);
|
||||
if (gu32PSoCDigitalTrig & PAD_7_Msk) MOD_INCR(gConfig.u16HueWingRight, LED_HUE_MAX);
|
||||
if (gu32PSoCDigitalTrig & PAD_8_Msk) MOD_DECR(gConfig.u16HueWingRight, LED_HUE_MAX);
|
||||
}
|
||||
// [Cell 4 no function]
|
||||
{ // Lighting toggles
|
||||
static uint16_t su16Hue = 0;
|
||||
MOD_INCR(su16Hue, LED_HUE_MAX * 5);
|
||||
if (gConfig.bEnableRainbow) {
|
||||
gaControlledIntLedData[LED_CELL_5].u16H = su16Hue / 5;
|
||||
gaControlledIntLedData[LED_CELL_5].u8V = 255;
|
||||
} else {
|
||||
gaControlledIntLedData[LED_CELL_5].u8S = 0;
|
||||
gaControlledIntLedData[LED_CELL_5].u8V = 255;
|
||||
}
|
||||
|
||||
if (gu16PSoCDigitalPos & CELL_5_Msk) INV(gConfig.bEnableRainbow);
|
||||
}
|
||||
{ // Brightness
|
||||
if (gConfig.u8LedGroundBrightness) {
|
||||
gaControlledIntLedData[LED_CELL_6].u8S = 0;
|
||||
gaControlledIntLedData[LED_CELL_6].u8V = gConfig.u8LedGroundBrightness;
|
||||
} else {
|
||||
gaControlledIntLedData[LED_CELL_6].u8V = 255;
|
||||
}
|
||||
if (gConfig.u8LedWingBrightness) {
|
||||
gaControlledIntLedData[LED_CELL_7].u8S = 0;
|
||||
gaControlledIntLedData[LED_CELL_7].u8V = gConfig.u8LedWingBrightness;
|
||||
} else {
|
||||
gaControlledIntLedData[LED_CELL_7].u8V = 255;
|
||||
}
|
||||
|
||||
if (gu32PSoCDigitalTrig & PAD_13_Msk) INCR(gConfig.u8LedGroundBrightness, 255);
|
||||
if (gu32PSoCDigitalTrig & PAD_14_Msk) DECR(gConfig.u8LedGroundBrightness, 0);
|
||||
if (gu32PSoCDigitalTrig & PAD_15_Msk) INCR(gConfig.u8LedWingBrightness, 255);
|
||||
if (gu32PSoCDigitalTrig & PAD_16_Msk) DECR(gConfig.u8LedWingBrightness, 0);
|
||||
}
|
||||
// [Cell 8,9,10,11 no function]
|
||||
{ // Sensitivity control (handled in dedicated function)
|
||||
gaControlledIntLedData[LED_CELL_12].u8S = (gConfig.u8Sens - 1) * 16;
|
||||
gaControlledIntLedData[LED_CELL_12].u8V = 255;
|
||||
}
|
||||
// [Cell 13 no function]
|
||||
{ // Mode switching
|
||||
gaControlledIntLedData[LED_CELL_14].u16H = gConfig.bEnableKeyboard ? GREEN : RED;
|
||||
gaControlledIntLedData[LED_CELL_14].u8V = 255;
|
||||
gaControlledIntLedData[LED_CELL_15].u16H = gConfig.bEnableIO4 ? GREEN : RED;
|
||||
gaControlledIntLedData[LED_CELL_15].u8V = 255;
|
||||
|
||||
if (gu16PSoCDigitalPos & CELL_14_Msk) INV(gConfig.bEnableKeyboard);
|
||||
if (gu16PSoCDigitalPos & CELL_15_Msk) INV(gConfig.bEnableIO4);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _FillControlled(uint16_t u16H, uint8_t u8Fill) {
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
gaControlledIntLedData[i].u16H = u16H;
|
||||
gaControlledIntLedData[i].u8S = 255;
|
||||
gaControlledIntLedData[i].u8V = i < u8Fill ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t bCalibrationActive = 0;
|
||||
static void UI_TickCalibration(void) {
|
||||
static uint16_t u16Timer = 0;
|
||||
static uint16_t su16MaxNoHands[32] = { 0 };
|
||||
static uint16_t su16MaxHands[32] = { 0 };
|
||||
|
||||
if (!bCalibrationActive) {
|
||||
// Calibration start
|
||||
u16Timer = 0;
|
||||
bCalibrationActive = 1;
|
||||
memset(su16MaxNoHands, 0, sizeof su16MaxNoHands);
|
||||
memset(su16MaxHands, 0, sizeof su16MaxHands);
|
||||
}
|
||||
// Only tick the timer when we're using it, to avoid overflow
|
||||
if (u16Timer < 5000) u16Timer++;
|
||||
|
||||
if (u16Timer < 3000) {
|
||||
// Flash red for the first 3 seconds
|
||||
_FillControlled(RED, ((u16Timer / 250) & 1) ? 0 : LED_NUM_GROUND);
|
||||
} else if (u16Timer < 4000) {
|
||||
// Fill up the cells with blue
|
||||
_FillControlled(BLUE, (u16Timer - 3000) / (1000 / LED_NUM_GROUND));
|
||||
for (uint8_t i; i < 32; i++) {
|
||||
su16MaxNoHands[i] = Maximum(su16MaxNoHands[i], gu16PSoCDiff[i]);
|
||||
}
|
||||
} else if (u16Timer < 5000) {
|
||||
// Flash green for the next second
|
||||
_FillControlled(GREEN, ((u16Timer / 250) & 1) ? 0 : LED_NUM_GROUND);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
// As well as the raw minimum, force a small constant threshold minimum too
|
||||
su16MaxHands[i] = Maximum(su16MaxHands[i], gu16PSoCDiff[i] + (gConfig.u8Sens * 5));
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
gaControlledIntLedData[i].u8S = 255;
|
||||
gaControlledIntLedData[i].u8V = 255;
|
||||
}
|
||||
|
||||
uint16_t u16CalibMin = CALIB_HANDS_MIN + (gConfig.u8Sens * 50);
|
||||
uint16_t u16CalibReq = CALIB_HANDS_REQ + (gConfig.u8Sens * 50);
|
||||
uint16_t u16CalibMax = CALIB_HANDS_MAX + (gConfig.u8Sens * 50);
|
||||
|
||||
uint8_t bOk = 1;
|
||||
// Iterate over the cells
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (su16MaxHands[i * 2] < u16CalibMin || su16MaxHands[i * 2 + 1] < u16CalibMin ||
|
||||
su16MaxHands[i * 2] < su16MaxNoHands[i * 2] ||
|
||||
su16MaxHands[i * 2 + 1] < su16MaxNoHands[i * 2 + 1]) {
|
||||
// Not enough data
|
||||
gaControlledIntLedData[i * 2].u8V = 0;
|
||||
bOk = 0;
|
||||
} else if (su16MaxHands[i * 2] < u16CalibReq || su16MaxHands[i * 2 + 1] < u16CalibReq) {
|
||||
// Data is too low
|
||||
gaControlledIntLedData[i * 2].u16H = RED;
|
||||
bOk = 0;
|
||||
} else if (su16MaxHands[i * 2] < u16CalibMax || su16MaxHands[i * 2 + 1] < u16CalibMax) {
|
||||
// We've got enough, but it could be better
|
||||
uint16_t u16Min = Minimum(su16MaxHands[i * 2], su16MaxHands[i * 2 + 1]);
|
||||
gaControlledIntLedData[i * 2].u16H =
|
||||
((u16Min - u16CalibReq) * GREEN) / (u16CalibMax - u16CalibReq);
|
||||
} else {
|
||||
// More than enough data
|
||||
gaControlledIntLedData[i * 2].u16H = GREEN;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < LED_NUM_GROUND; i++) {
|
||||
if (i % 2 == 1) {
|
||||
gaControlledIntLedData[i].u16H = bOk ? GREEN : RED;
|
||||
}
|
||||
}
|
||||
|
||||
// Calibration complete
|
||||
if (gu8DigitalButtons & DIGITAL_FN1_Msk) {
|
||||
bCalibrationActive = 0;
|
||||
|
||||
if (bOk) {
|
||||
memcpy(gConfig.u16PSoCScaleMin, su16MaxNoHands, sizeof su16MaxNoHands);
|
||||
memcpy(gConfig.u16PSoCScaleMax, su16MaxHands, sizeof su16MaxHands);
|
||||
bConfigDirty = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UI_Tick(void) {
|
||||
static uint8_t u8Fn2Held = 0;
|
||||
if (gu8DigitalButtons & DIGITAL_FN2_Msk) {
|
||||
if (u8Fn2Held < FN2_HOLD_TIME) u8Fn2Held++;
|
||||
} else {
|
||||
// We released the button after holding it for long enough to be in the configuration UI, so
|
||||
// assume something changed
|
||||
if (u8Fn2Held >= FN2_HOLD_TIME) {
|
||||
bConfigDirty = 1;
|
||||
}
|
||||
|
||||
u8Fn2Held = 0;
|
||||
}
|
||||
|
||||
static uint16_t u16Fn1Held = 0;
|
||||
if (gu8DigitalButtons & DIGITAL_FN1_Msk) {
|
||||
if (u16Fn1Held < FN1_HOLD_TIME) u16Fn1Held++;
|
||||
} else {
|
||||
u16Fn1Held = 0;
|
||||
}
|
||||
|
||||
if (bCalibrationActive || u16Fn1Held >= FN1_HOLD_TIME) {
|
||||
gbLedDataIsControlledInt = 1;
|
||||
UI_TickCalibration();
|
||||
} else if (u8Fn2Held >= FN2_HOLD_TIME) {
|
||||
gbLedDataIsControlledInt = 1;
|
||||
UI_TickSettings();
|
||||
} else {
|
||||
gbLedDataIsControlledInt = 0;
|
||||
}
|
||||
}
|
1654
src/usb_inc/hid.h
Normal file
1654
src/usb_inc/hid.h
Normal file
File diff suppressed because it is too large
Load Diff
69
src/usb_inc/hid_macro.h
Normal file
69
src/usb_inc/hid_macro.h
Normal file
@ -0,0 +1,69 @@
|
||||
// https://github.com/katyo/hid_def
|
||||
|
||||
#pragma once
|
||||
|
||||
#define _NONE(...)
|
||||
|
||||
#define _UNWR_(...) __VA_ARGS__
|
||||
#define _UNWR(a) _UNWR_ a
|
||||
|
||||
#define _CAT2_(a, b) a##b
|
||||
#define _CAT2(a, b) _CAT2_(a, b)
|
||||
|
||||
#define _CAT3_(a, b, c) a##b##c
|
||||
#define _CAT3(a, b, c) _CAT3_(a, b, c)
|
||||
|
||||
#define _CAT4_(a, b, c, d) a##b##c##d
|
||||
#define _CAT4(a, b, c, d) _CAT4_(a, b, c, d)
|
||||
|
||||
#define _CAT5_(a, b, c, d, e) a##b##c##d##e
|
||||
#define _CAT5(a, b, c, d, e) _CAT5_(a, b, c, d, e)
|
||||
|
||||
#define _NTH0_(a, ...) a
|
||||
#define _NTH0(...) _NTH0_(__VA_ARGS__)
|
||||
|
||||
#define _NTH1_(a, b, ...) b
|
||||
#define _NTH1(...) _NTH1_(__VA_ARGS__)
|
||||
|
||||
#define _NTH2_(a, b, c, ...) c
|
||||
#define _NTH2(...) _NTH2_(__VA_ARGS__)
|
||||
|
||||
#define _NTH3_(a, b, c, d, ...) d
|
||||
#define _NTH3(...) _NTH3_(__VA_ARGS__)
|
||||
|
||||
#define _NTH4_(a, b, c, d, e, ...) e
|
||||
#define _NTH4(...) _NTH4_(__VA_ARGS__)
|
||||
|
||||
#define _MAX2(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define _MIN2(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define _CALL_(f, ...) f(__VA_ARGS__)
|
||||
#define _CALL(f, ...) _CALL_(f, ##__VA_ARGS__)
|
||||
|
||||
#define _EVAL0(...) __VA_ARGS__
|
||||
#define _EVAL1(...) _EVAL0(_EVAL0(_EVAL0(__VA_ARGS__)))
|
||||
#define _EVAL2(...) _EVAL1(_EVAL1(_EVAL1(__VA_ARGS__)))
|
||||
#define _EVAL3(...) _EVAL2(_EVAL2(_EVAL2(__VA_ARGS__)))
|
||||
#define _EVAL4(...) _EVAL3(_EVAL3(_EVAL3(__VA_ARGS__)))
|
||||
#define _EVAL(...) _EVAL4(_EVAL4(_EVAL4(__VA_ARGS__)))
|
||||
|
||||
#define _MAP_END(...)
|
||||
#define _MAP_OUT
|
||||
#define _MAP_COMMA ,
|
||||
|
||||
#define _MAP_GET_END2() 0, _MAP_END
|
||||
#define _MAP_GET_END1(...) _MAP_GET_END2
|
||||
#define _MAP_GET_END(...) _MAP_GET_END1
|
||||
#define _MAP_NEXT0(test, next, ...) next _MAP_OUT
|
||||
#define _MAP_NEXT1(test, next) _MAP_NEXT0(test, next, 0)
|
||||
#define _MAP_NEXT(test, next) _MAP_NEXT1(_MAP_GET_END test, next)
|
||||
|
||||
#define _MAP0(f, x, peek, ...) f(x) _MAP_NEXT(peek, _MAP1)(f, peek, __VA_ARGS__)
|
||||
#define _MAP1(f, x, peek, ...) f(x) _MAP_NEXT(peek, _MAP0)(f, peek, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Applies the function macro `f` to each of the remaining parameters.
|
||||
*/
|
||||
#define _MAP(f, ...) _EVAL(_MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||
|
||||
#define _ASSERT(x) ((1/(!!(x))) ? (x) : (x))
|
769
src/usb_inc/keymap.h
Normal file
769
src/usb_inc/keymap.h
Normal file
@ -0,0 +1,769 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Keyboard Modifiers
|
||||
enum KeyboardMods {
|
||||
MOD_LEFT_CTRL = (1 << 8),
|
||||
MOD_LEFT_SHIFT = (1 << 9),
|
||||
MOD_LEFT_ALT = (1 << 10),
|
||||
MOD_LEFT_GUI = (1 << 11),
|
||||
MOD_RIGHT_CTRL = (1 << 12),
|
||||
MOD_RIGHT_SHIFT = (1 << 13),
|
||||
MOD_RIGHT_ALT = (1 << 14),
|
||||
MOD_RIGHT_GUI = (uint16_t)(1 << 15),
|
||||
};
|
||||
|
||||
// Keyboard Leds
|
||||
enum KeyboardLeds {
|
||||
LED_NUM_LOCK = (1 << 0),
|
||||
LED_CAPS_LOCK = (1 << 1),
|
||||
LED_SCROLL_LOCK = (1 << 2),
|
||||
LED_COMPOSE = (1 << 3),
|
||||
LED_KANA = (1 << 4),
|
||||
LED_POWER = (1 << 5),
|
||||
LED_SHIFT = (1 << 6),
|
||||
LED_DO_NOT_DISTURB = (1 << 7),
|
||||
};
|
||||
|
||||
enum KeyboardKeycode {
|
||||
KEY_RESERVED = 0,
|
||||
KEY_ERROR_ROLLOVER = 1,
|
||||
KEY_POST_FAIL = 2,
|
||||
KEY_ERROR_UNDEFINED = 3,
|
||||
KEY_A = 4,
|
||||
KEY_B = 5,
|
||||
KEY_C = 6,
|
||||
KEY_D = 7,
|
||||
KEY_E = 8,
|
||||
KEY_F = 9,
|
||||
KEY_G = 10,
|
||||
KEY_H = 11,
|
||||
KEY_I = 12,
|
||||
KEY_J = 13,
|
||||
KEY_K = 14,
|
||||
KEY_L = 15,
|
||||
KEY_M = 16,
|
||||
KEY_N = 17,
|
||||
KEY_O = 18,
|
||||
KEY_P = 19,
|
||||
KEY_Q = 20,
|
||||
KEY_R = 21,
|
||||
KEY_S = 22,
|
||||
KEY_T = 23,
|
||||
KEY_U = 24,
|
||||
KEY_V = 25,
|
||||
KEY_W = 26,
|
||||
KEY_X = 27,
|
||||
KEY_Y = 28,
|
||||
KEY_Z = 29,
|
||||
KEY_1 = 30,
|
||||
KEY_2 = 31,
|
||||
KEY_3 = 32,
|
||||
KEY_4 = 33,
|
||||
KEY_5 = 34,
|
||||
KEY_6 = 35,
|
||||
KEY_7 = 36,
|
||||
KEY_8 = 37,
|
||||
KEY_9 = 38,
|
||||
KEY_0 = 39,
|
||||
KEY_ENTER = 40,
|
||||
KEY_RETURN = 40, // Alias
|
||||
KEY_ESC = 41,
|
||||
KEY_BACKSPACE = 42,
|
||||
KEY_TAB = 43,
|
||||
KEY_SPACE = 44,
|
||||
KEY_MINUS = 45,
|
||||
KEY_EQUAL = 46,
|
||||
KEY_LEFT_BRACE = 47,
|
||||
KEY_RIGHT_BRACE = 48,
|
||||
KEY_BACKSLASH = 49,
|
||||
KEY_NON_US_NUM = 50,
|
||||
KEY_SEMICOLON = 51,
|
||||
KEY_QUOTE = 52,
|
||||
KEY_TILDE = 53,
|
||||
KEY_COMMA = 54,
|
||||
KEY_PERIOD = 55,
|
||||
KEY_SLASH = 56,
|
||||
KEY_CAPS_LOCK = 0x39,
|
||||
KEY_F1 = 0x3A,
|
||||
KEY_F2 = 0x3B,
|
||||
KEY_F3 = 0x3C,
|
||||
KEY_F4 = 0x3D,
|
||||
KEY_F5 = 0x3E,
|
||||
KEY_F6 = 0x3F,
|
||||
KEY_F7 = 0x40,
|
||||
KEY_F8 = 0x41,
|
||||
KEY_F9 = 0x42,
|
||||
KEY_F10 = 0x43,
|
||||
KEY_F11 = 0x44,
|
||||
KEY_F12 = 0x45,
|
||||
KEY_PRINT = 0x46,
|
||||
KEY_PRINTSCREEN = 0x46, // Alias
|
||||
KEY_SCROLL_LOCK = 0x47,
|
||||
KEY_PAUSE = 0x48,
|
||||
KEY_INSERT = 0x49,
|
||||
KEY_HOME = 0x4A,
|
||||
KEY_PAGE_UP = 0x4B,
|
||||
KEY_DELETE = 0x4C,
|
||||
KEY_END = 0x4D,
|
||||
KEY_PAGE_DOWN = 0x4E,
|
||||
KEY_RIGHT_ARROW = 0x4F,
|
||||
KEY_LEFT_ARROW = 0x50,
|
||||
KEY_DOWN_ARROW = 0x51,
|
||||
KEY_UP_ARROW = 0x52,
|
||||
KEY_RIGHT = 0x4F, // Alias
|
||||
KEY_LEFT = 0x50, // Alias
|
||||
KEY_DOWN = 0x51, // Alias
|
||||
KEY_UP = 0x52, // Alias
|
||||
KEY_NUM_LOCK = 0x53,
|
||||
KEYPAD_DIVIDE = 0x54,
|
||||
KEYPAD_MULTIPLY = 0x55,
|
||||
KEYPAD_SUBTRACT = 0x56,
|
||||
KEYPAD_ADD = 0x57,
|
||||
KEYPAD_ENTER = 0x58,
|
||||
KEYPAD_1 = 0x59,
|
||||
KEYPAD_2 = 0x5A,
|
||||
KEYPAD_3 = 0x5B,
|
||||
KEYPAD_4 = 0x5C,
|
||||
KEYPAD_5 = 0x5D,
|
||||
KEYPAD_6 = 0x5E,
|
||||
KEYPAD_7 = 0x5F,
|
||||
KEYPAD_8 = 0x60,
|
||||
KEYPAD_9 = 0x61,
|
||||
KEYPAD_0 = 0x62,
|
||||
KEYPAD_DOT = 0x63,
|
||||
KEY_NON_US = 0x64,
|
||||
KEY_APPLICATION = 0x65, // Context menu/right click
|
||||
KEY_MENU = 0x65, // Alias
|
||||
|
||||
// Most of the following keys will only work with Linux or not at all.
|
||||
// F13+ keys are mostly used for laptop functions like ECO key.
|
||||
KEY_POWER = 0x66, // PowerOff (Ubuntu)
|
||||
KEY_PAD_EQUALS = 0x67, // Dont confuse with KEYPAD_EQUAL_SIGN
|
||||
KEY_F13 = 0x68, // Tools (Ubunutu)
|
||||
KEY_F14 = 0x69, // Launch5 (Ubuntu)
|
||||
KEY_F15 = 0x6A, // Launch6 (Ubuntu)
|
||||
KEY_F16 = 0x6B, // Launch7 (Ubuntu)
|
||||
KEY_F17 = 0x6C, // Launch8 (Ubuntu)
|
||||
KEY_F18 = 0x6D, // Launch9 (Ubuntu)
|
||||
KEY_F19 = 0x6E, // Disabled (Ubuntu)
|
||||
KEY_F20 = 0x6F, // AudioMicMute (Ubuntu)
|
||||
KEY_F21 = 0x70, // Touchpad toggle (Ubuntu)
|
||||
KEY_F22 = 0x71, // TouchpadOn (Ubuntu)
|
||||
KEY_F23 = 0x72, // TouchpadOff Ubuntu)
|
||||
KEY_F24 = 0x73, // Disabled (Ubuntu)
|
||||
KEY_EXECUTE = 0x74, // Open (Ubuntu)
|
||||
KEY_HELP = 0x75, // Help (Ubuntu)
|
||||
KEY_MENU2 = 0x76, // Disabled (Ubuntu)
|
||||
KEY_SELECT = 0x77, // Disabled (Ubuntu)
|
||||
KEY_STOP = 0x78, // Cancel (Ubuntu)
|
||||
KEY_AGAIN = 0x79, // Redo (Ubuntu)
|
||||
KEY_UNDO = 0x7A, // Undo (Ubuntu)
|
||||
KEY_CUT = 0x7B, // Cut (Ubuntu)
|
||||
KEY_COPY = 0x7C, // Copy (Ubuntu)
|
||||
KEY_PASTE = 0x7D, // Paste (Ubuntu)
|
||||
KEY_FIND = 0x7E, // Find (Ubuntu)
|
||||
KEY_MUTE = 0x7F,
|
||||
KEY_VOLUME_MUTE = 0x7F, // Alias
|
||||
KEY_VOLUME_UP = 0x80,
|
||||
KEY_VOLUME_DOWN = 0x81,
|
||||
KEY_LOCKING_CAPS_LOCK = 0x82, // Disabled (Ubuntu)
|
||||
KEY_LOCKING_NUM_LOCK = 0x83, // Disabled (Ubuntu)
|
||||
KEY_LOCKING_SCROLL_LOCK = 0x84, // Disabled (Ubuntu)
|
||||
KEYPAD_COMMA = 0x85, // .
|
||||
KEYPAD_EQUAL_SIGN = 0x86, // Disabled (Ubuntu), Dont confuse with KEYPAD_EQUAL
|
||||
KEY_INTERNATIONAL1 = 0x87, // Disabled (Ubuntu)
|
||||
KEY_INTERNATIONAL2 = 0x88, // Hiragana Katakana (Ubuntu)
|
||||
KEY_INTERNATIONAL3 = 0x89, // Disabled (Ubuntu)
|
||||
KEY_INTERNATIONAL4 = 0x8A, // Henkan (Ubuntu)
|
||||
KEY_INTERNATIONAL5 = 0x8B, // Muhenkan (Ubuntu)
|
||||
KEY_INTERNATIONAL6 = 0x8C, // Disabled (Ubuntu)
|
||||
KEY_INTERNATIONAL7 = 0x8D, // Disabled (Ubuntu)
|
||||
KEY_INTERNATIONAL8 = 0x8E, // Disabled (Ubuntu)
|
||||
KEY_INTERNATIONAL9 = 0x8F, // Disabled (Ubuntu)
|
||||
KEY_LANG1 = 0x90, // Disabled (Ubuntu)
|
||||
KEY_LANG2 = 0x91, // Disabled (Ubuntu)
|
||||
KEY_LANG3 = 0x92, // Katana (Ubuntu)
|
||||
KEY_LANG4 = 0x93, // Hiragana (Ubuntu)
|
||||
KEY_LANG5 = 0x94, // Disabled (Ubuntu)
|
||||
KEY_LANG6 = 0x95, // Disabled (Ubuntu)
|
||||
KEY_LANG7 = 0x96, // Disabled (Ubuntu)
|
||||
KEY_LANG8 = 0x97, // Disabled (Ubuntu)
|
||||
KEY_LANG9 = 0x98, // Disabled (Ubuntu)
|
||||
KEY_ALTERNATE_ERASE = 0x99, // Disabled (Ubuntu)
|
||||
KEY_SYSREQ_ATTENTION = 0x9A, // Disabled (Ubuntu)
|
||||
KEY_CANCEL = 0x9B, // Disabled (Ubuntu)
|
||||
KEY_CLEAR = 0x9C, // Delete (Ubuntu)
|
||||
KEY_PRIOR = 0x9D, // Disabled (Ubuntu)
|
||||
KEY_RETURN2 = 0x9E, // Disabled (Ubuntu), Do not confuse this with KEY_ENTER
|
||||
KEY_SEPARATOR = 0x9F, // Disabled (Ubuntu)
|
||||
KEY_OUT = 0xA0, // Disabled (Ubuntu)
|
||||
KEY_OPER = 0xA1, // Disabled (Ubuntu)
|
||||
KEY_CLEAR_AGAIN = 0xA2, // Disabled (Ubuntu)
|
||||
KEY_CRSEL_PROPS = 0xA3, // Disabled (Ubuntu)
|
||||
KEY_EXSEL = 0xA4, // Disabled (Ubuntu)
|
||||
|
||||
KEY_PAD_00 = 0xB0, // Disabled (Ubuntu)
|
||||
KEY_PAD_000 = 0xB1, // Disabled (Ubuntu)
|
||||
KEY_THOUSANDS_SEPARATOR = 0xB2, // Disabled (Ubuntu)
|
||||
KEY_DECIMAL_SEPARATOR = 0xB3, // Disabled (Ubuntu)
|
||||
KEY_CURRENCY_UNIT = 0xB4, // Disabled (Ubuntu)
|
||||
KEY_CURRENCY_SUB_UNIT = 0xB5, // Disabled (Ubuntu)
|
||||
KEYPAD_LEFT_BRACE = 0xB6, // (
|
||||
KEYPAD_RIGHT_BRACE = 0xB7, // )
|
||||
KEYPAD_LEFT_CURLY_BRACE = 0xB8, // Disabled (Ubuntu)
|
||||
KEYPAD_RIGHT_CURLY_BRACE = 0xB9, // Disabled (Ubuntu)
|
||||
KEYPAD_TAB = 0xBA, // Disabled (Ubuntu)
|
||||
KEYPAD_BACKSPACE = 0xBB, // Disabled (Ubuntu)
|
||||
KEYPAD_A = 0xBC, // Disabled (Ubuntu)
|
||||
KEYPAD_B = 0xBD, // Disabled (Ubuntu)
|
||||
KEYPAD_C = 0xBE, // Disabled (Ubuntu)
|
||||
KEYPAD_D = 0xBF, // Disabled (Ubuntu)
|
||||
KEYPAD_E = 0xC0, // Disabled (Ubuntu)
|
||||
KEYPAD_F = 0xC1, // Disabled (Ubuntu)
|
||||
KEYPAD_XOR = 0xC2, // Disabled (Ubuntu)
|
||||
KEYPAD_CARET = 0xC3, // Disabled (Ubuntu)
|
||||
KEYPAD_PERCENT = 0xC4, // Disabled (Ubuntu)
|
||||
KEYPAD_LESS_THAN = 0xC5, // Disabled (Ubuntu)
|
||||
KEYPAD_GREATER_THAN = 0xC6, // Disabled (Ubuntu)
|
||||
KEYPAD_AMPERSAND = 0xC7, // Disabled (Ubuntu)
|
||||
KEYPAD_DOUBLEAMPERSAND = 0xC8, // Disabled (Ubuntu)
|
||||
KEYPAD_PIPE = 0xC9, // Disabled (Ubuntu)
|
||||
KEYPAD_DOUBLEPIPE = 0xCA, // Disabled (Ubuntu)
|
||||
KEYPAD_COLON = 0xCB, // Disabled (Ubuntu)
|
||||
KEYPAD_POUND_SIGN = 0xCC, // Disabled (Ubuntu)
|
||||
KEYPAD_SPACE = 0xCD, // Disabled (Ubuntu)
|
||||
KEYPAD_AT_SIGN = 0xCE, // Disabled (Ubuntu)
|
||||
KEYPAD_EXCLAMATION_POINT = 0xCF, // Disabled (Ubuntu)
|
||||
KEYPAD_MEMORY_STORE = 0xD0, // Disabled (Ubuntu)
|
||||
KEYPAD_MEMORY_RECALL = 0xD1, // Disabled (Ubuntu)
|
||||
KEYPAD_MEMORY_CLEAR = 0xD2, // Disabled (Ubuntu)
|
||||
KEYPAD_MEMORY_ADD = 0xD3, // Disabled (Ubuntu)
|
||||
KEYPAD_MEMORY_SUBTRACT = 0xD4, // Disabled (Ubuntu)
|
||||
KEYPAD_MEMORY_MULTIPLY = 0xD5, // Disabled (Ubuntu)
|
||||
KEYPAD_MEMORY_DIVIDE = 0xD6, // Disabled (Ubuntu)
|
||||
KEYPAD_PLUS_MINUS = 0xD7, // Disabled (Ubuntu)
|
||||
KEYPAD_CLEAR = 0xD8, // Delete (Ubuntu)
|
||||
KEYPAD_CLEAR_ENTRY = 0xD9, // Disabled (Ubuntu)
|
||||
KEYPAD_BINARY = 0xDA, // Disabled (Ubuntu)
|
||||
KEYPAD_OCTAL = 0xDB, // Disabled (Ubuntu)
|
||||
KEYPAD_DECIMAL = 0xDC, // Disabled (Ubuntu)
|
||||
KEYPAD_HEXADECIMAL = 0xDD, // Disabled (Ubuntu)
|
||||
|
||||
KEY_LEFT_CTRL = 0xE0,
|
||||
KEY_LEFT_SHIFT = 0xE1,
|
||||
KEY_LEFT_ALT = 0xE2,
|
||||
KEY_LEFT_GUI = 0xE3,
|
||||
KEY_LEFT_WINDOWS = 0xE3, // Alias
|
||||
KEY_RIGHT_CTRL = 0xE4,
|
||||
KEY_RIGHT_SHIFT = 0xE5,
|
||||
KEY_RIGHT_ALT = 0xE6,
|
||||
KEY_RIGHT_GUI = 0xE7,
|
||||
KEY_RIGHT_WINDOWS = 0xE7, // Alias
|
||||
|
||||
// Keyboard HID mappings
|
||||
|
||||
// Reserved (no_event_indicated)
|
||||
HID_KEYBOARD_ERROR_ROLLOVER = 0x01,
|
||||
HID_KEYBOARD_POST_FAIL = 0x02,
|
||||
HID_KEYBOARD_ERROR_UNDEFINED = 0x03,
|
||||
HID_KEYBOARD_A_AND_A = 0x04,
|
||||
HID_KEYBOARD_B_AND_B = 0x05,
|
||||
HID_KEYBOARD_C_AND_C = 0x06,
|
||||
HID_KEYBOARD_D_AND_D = 0x07,
|
||||
HID_KEYBOARD_E_AND_E = 0x08,
|
||||
HID_KEYBOARD_F_AND_F = 0x09,
|
||||
HID_KEYBOARD_G_AND_G = 0x0A,
|
||||
HID_KEYBOARD_H_AND_H = 0x0B,
|
||||
HID_KEYBOARD_I_AND_I = 0x0C,
|
||||
HID_KEYBOARD_J_AND_J = 0x0D,
|
||||
HID_KEYBOARD_K_AND_K = 0x0E,
|
||||
HID_KEYBOARD_L_AND_L = 0x0F,
|
||||
HID_KEYBOARD_M_AND_M = 0x10,
|
||||
HID_KEYBOARD_N_AND_N = 0x11,
|
||||
HID_KEYBOARD_O_AND_O = 0x12,
|
||||
HID_KEYBOARD_P_AND_P = 0x13,
|
||||
HID_KEYBOARD_Q_AND_Q = 0x14,
|
||||
HID_KEYBOARD_R_AND_R = 0x15,
|
||||
HID_KEYBOARD_S_AND_S = 0x16,
|
||||
HID_KEYBOARD_T_AND_T = 0x17,
|
||||
HID_KEYBOARD_U_AND_U = 0x18,
|
||||
HID_KEYBOARD_V_AND_V = 0x19,
|
||||
HID_KEYBOARD_W_AND_W = 0x1A,
|
||||
HID_KEYBOARD_X_AND_X = 0x1B,
|
||||
HID_KEYBOARD_Y_AND_Y = 0x1C,
|
||||
HID_KEYBOARD_Z_AND_Z = 0x1D,
|
||||
HID_KEYBOARD_1_AND_EXCLAMATION_POINT = 0x1E,
|
||||
HID_KEYBOARD_2_AND_AT = 0x1F,
|
||||
HID_KEYBOARD_3_AND_POUND = 0x20,
|
||||
HID_KEYBOARD_4_AND_DOLLAR = 0x21,
|
||||
HID_KEYBOARD_5_AND_PERCENT = 0x22,
|
||||
HID_KEYBOARD_6_AND_CARAT = 0x23,
|
||||
HID_KEYBOARD_7_AND_AMPERSAND = 0x24,
|
||||
HID_KEYBOARD_8_AND_ASTERISK = 0x25,
|
||||
HID_KEYBOARD_9_AND_LEFT_PAREN = 0x26,
|
||||
HID_KEYBOARD_0_AND_RIGHT_PAREN = 0x27,
|
||||
HID_KEYBOARD_ENTER = 0x28, // (MARKED AS ENTER_SLASH_RETURN)
|
||||
HID_KEYBOARD_ESCAPE = 0x29,
|
||||
HID_KEYBOARD_DELETE = 0x2A, // (BACKSPACE)
|
||||
HID_KEYBOARD_TAB = 0x2B,
|
||||
HID_KEYBOARD_SPACEBAR = 0x2C,
|
||||
HID_KEYBOARD_MINUS_AND_UNDERSCORE = 0x2D, // (UNDERSCORE)
|
||||
HID_KEYBOARD_EQUALS_AND_PLUS = 0x2E,
|
||||
HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE = 0x2F,
|
||||
HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE = 0x30,
|
||||
HID_KEYBOARD_BACKSLASH_AND_PIPE = 0x31,
|
||||
HID_KEYBOARD_NON_US_POUND_AND_TILDE = 0x32,
|
||||
HID_KEYBOARD_SEMICOLON_AND_COLON = 0x33,
|
||||
HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE = 0x34,
|
||||
HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE = 0x35,
|
||||
HID_KEYBOARD_COMMA_AND_LESS_THAN = 0x36,
|
||||
HID_KEYBOARD_PERIOD_AND_GREATER_THAN = 0x37,
|
||||
HID_KEYBOARD_SLASH_AND_QUESTION_MARK = 0x38,
|
||||
HID_KEYBOARD_CAPS_LOCK = 0x39,
|
||||
HID_KEYBOARD_F1 = 0x3A,
|
||||
HID_KEYBOARD_F2 = 0x3B,
|
||||
HID_KEYBOARD_F3 = 0x3C,
|
||||
HID_KEYBOARD_F4 = 0x3D,
|
||||
HID_KEYBOARD_F5 = 0x3E,
|
||||
HID_KEYBOARD_F6 = 0x3F,
|
||||
HID_KEYBOARD_F7 = 0x40,
|
||||
HID_KEYBOARD_F8 = 0x41,
|
||||
HID_KEYBOARD_F9 = 0x42,
|
||||
HID_KEYBOARD_F10 = 0x43,
|
||||
HID_KEYBOARD_F11 = 0x44,
|
||||
HID_KEYBOARD_F12 = 0x45,
|
||||
HID_KEYBOARD_PRINTSCREEN = 0x46,
|
||||
HID_KEYBOARD_SCROLL_LOCK = 0x47,
|
||||
HID_KEYBOARD_PAUSE = 0x48,
|
||||
HID_KEYBOARD_INSERT = 0x49,
|
||||
HID_KEYBOARD_HOME = 0x4A,
|
||||
HID_KEYBOARD_PAGE_UP = 0x4B,
|
||||
HID_KEYBOARD_DELETE_FORWARD = 0x4C,
|
||||
HID_KEYBOARD_END = 0x4D,
|
||||
HID_KEYBOARD_PAGE_DOWN = 0x4E,
|
||||
HID_KEYBOARD_RIGHTARROW = 0x4F,
|
||||
HID_KEYBOARD_LEFTARROW = 0x50,
|
||||
HID_KEYBOARD_DOWNARROW = 0x51,
|
||||
HID_KEYBOARD_UPARROW = 0x52,
|
||||
HID_KEYPAD_NUM_LOCK_AND_CLEAR = 0x53,
|
||||
HID_KEYPAD_DIVIDE = 0x54,
|
||||
HID_KEYPAD_MULTIPLY = 0x55,
|
||||
HID_KEYPAD_SUBTRACT = 0x56,
|
||||
HID_KEYPAD_ADD = 0x57,
|
||||
HID_KEYPAD_ENTER = 0x58,
|
||||
HID_KEYPAD_1_AND_END = 0x59,
|
||||
HID_KEYPAD_2_AND_DOWN_ARROW = 0x5A,
|
||||
HID_KEYPAD_3_AND_PAGE_DOWN = 0x5B,
|
||||
HID_KEYPAD_4_AND_LEFT_ARROW = 0x5C,
|
||||
HID_KEYPAD_5 = 0x5D,
|
||||
HID_KEYPAD_6_AND_RIGHT_ARROW = 0x5E,
|
||||
HID_KEYPAD_7_AND_HOME = 0x5F,
|
||||
HID_KEYPAD_8_AND_UP_ARROW = 0x60,
|
||||
HID_KEYPAD_9_AND_PAGE_UP = 0x61,
|
||||
HID_KEYPAD_0_AND_INSERT = 0x62,
|
||||
HID_KEYPAD_PERIOD_AND_DELETE = 0x63,
|
||||
HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE = 0x64,
|
||||
HID_KEYBOARD_APPLICATION = 0x65,
|
||||
HID_KEYBOARD_POWER = 0x66,
|
||||
HID_KEYPAD_EQUALS = 0x67,
|
||||
HID_KEYBOARD_F13 = 0x68,
|
||||
HID_KEYBOARD_F14 = 0x69,
|
||||
HID_KEYBOARD_F15 = 0x6A,
|
||||
HID_KEYBOARD_F16 = 0x6B,
|
||||
HID_KEYBOARD_F17 = 0x6C,
|
||||
HID_KEYBOARD_F18 = 0x6D,
|
||||
HID_KEYBOARD_F19 = 0x6E,
|
||||
HID_KEYBOARD_F20 = 0x6F,
|
||||
HID_KEYBOARD_F21 = 0x70,
|
||||
HID_KEYBOARD_F22 = 0x71,
|
||||
HID_KEYBOARD_F23 = 0x72,
|
||||
HID_KEYBOARD_F24 = 0x73,
|
||||
HID_KEYBOARD_EXECUTE = 0x74,
|
||||
HID_KEYBOARD_HELP = 0x75,
|
||||
HID_KEYBOARD_MENU = 0x76,
|
||||
HID_KEYBOARD_SELECT = 0x77,
|
||||
HID_KEYBOARD_STOP = 0x78,
|
||||
HID_KEYBOARD_AGAIN = 0x79,
|
||||
HID_KEYBOARD_UNDO = 0x7A,
|
||||
HID_KEYBOARD_CUT = 0x7B,
|
||||
HID_KEYBOARD_COPY = 0x7C,
|
||||
HID_KEYBOARD_PASTE = 0x7D,
|
||||
HID_KEYBOARD_FIND = 0x7E,
|
||||
HID_KEYBOARD_MUTE = 0x7F,
|
||||
HID_KEYBOARD_VOLUME_UP = 0x80,
|
||||
HID_KEYBOARD_VOLUME_DOWN = 0x81,
|
||||
HID_KEYBOARD_LOCKING_CAPS_LOCK = 0x82,
|
||||
HID_KEYBOARD_LOCKING_NUM_LOCK = 0x83,
|
||||
HID_KEYBOARD_LOCKING_SCROLL_LOCK = 0x84,
|
||||
HID_KEYPAD_COMMA = 0x85,
|
||||
HID_KEYPAD_EQUAL_SIGN = 0x86,
|
||||
HID_KEYBOARD_INTERNATIONAL1 = 0x87,
|
||||
HID_KEYBOARD_INTERNATIONAL2 = 0x88,
|
||||
HID_KEYBOARD_INTERNATIONAL3 = 0x89,
|
||||
HID_KEYBOARD_INTERNATIONAL4 = 0x8A,
|
||||
HID_KEYBOARD_INTERNATIONAL5 = 0x8B,
|
||||
HID_KEYBOARD_INTERNATIONAL6 = 0x8C,
|
||||
HID_KEYBOARD_INTERNATIONAL7 = 0x8D,
|
||||
HID_KEYBOARD_INTERNATIONAL8 = 0x8E,
|
||||
HID_KEYBOARD_INTERNATIONAL9 = 0x8F,
|
||||
HID_KEYBOARD_LANG1 = 0x90,
|
||||
HID_KEYBOARD_LANG2 = 0x91,
|
||||
HID_KEYBOARD_LANG3 = 0x92,
|
||||
HID_KEYBOARD_LANG4 = 0x93,
|
||||
HID_KEYBOARD_LANG5 = 0x94,
|
||||
HID_KEYBOARD_LANG6 = 0x95,
|
||||
HID_KEYBOARD_LANG7 = 0x96,
|
||||
HID_KEYBOARD_LANG8 = 0x97,
|
||||
HID_KEYBOARD_LANG9 = 0x98,
|
||||
HID_KEYBOARD_ALTERNATE_ERASE = 0x99,
|
||||
HID_KEYBOARD_SYSREQ_SLASH_ATTENTION = 0x9A,
|
||||
HID_KEYBOARD_CANCEL = 0x9B,
|
||||
HID_KEYBOARD_CLEAR = 0x9C,
|
||||
HID_KEYBOARD_PRIOR = 0x9D,
|
||||
HID_KEYBOARD_RETURN = 0x9E,
|
||||
HID_KEYBOARD_SEPARATOR = 0x9F,
|
||||
HID_KEYBOARD_OUT = 0xA0,
|
||||
HID_KEYBOARD_OPER = 0xA1,
|
||||
HID_KEYBOARD_CLEAR_SLASH_AGAIN = 0xA2,
|
||||
HID_KEYBOARD_CRSEL_SLASH_PROPS = 0xA3,
|
||||
HID_KEYBOARD_EXSEL = 0xA4,
|
||||
// Reserved 0xA5-AF
|
||||
HID_KEYPAD_00 = 0xB0,
|
||||
HID_KEYPAD_000 = 0xB1,
|
||||
HID_THOUSANDS_SEPARATOR = 0xB2,
|
||||
HID_DECIMAL_SEPARATOR = 0xB3,
|
||||
HID_CURRENCY_UNIT = 0xB4,
|
||||
HID_CURRENCY_SUBUNIT = 0xB5,
|
||||
HID_KEYPAD_LEFT_PAREN = 0xB6,
|
||||
HID_KEYPAD_RIGHT_PAREN = 0xB7,
|
||||
HID_KEYPAD_LEFT_CURLY_BRACE = 0xB8,
|
||||
HID_KEYPAD_RIGHT_CURLY_BRACE = 0xB9,
|
||||
HID_KEYPAD_TAB = 0xBA,
|
||||
HID_KEYPAD_BACKSPACE = 0xBB,
|
||||
HID_KEYPAD_A = 0xBC,
|
||||
HID_KEYPAD_B = 0xBD,
|
||||
HID_KEYPAD_C = 0xBE,
|
||||
HID_KEYPAD_D = 0xBF,
|
||||
HID_KEYPAD_E = 0xC0,
|
||||
HID_KEYPAD_F = 0xC1,
|
||||
HID_KEYPAD_XOR = 0xC2,
|
||||
HID_KEYPAD_CARAT = 0xC3,
|
||||
HID_KEYPAD_PERCENT = 0xC4,
|
||||
HID_KEYPAD_LESS_THAN = 0xC5,
|
||||
HID_KEYPAD_GREATER_THAN = 0xC6,
|
||||
HID_KEYPAD_AMPERSAND = 0xC7,
|
||||
HID_KEYPAD_DOUBLEAMPERSAND = 0xC8,
|
||||
HID_KEYPAD_PIPE = 0xC9,
|
||||
HID_KEYPAD_DOUBLEPIPE = 0xCA,
|
||||
HID_KEYPAD_COLON = 0xCB,
|
||||
HID_KEYPAD_POUND_SIGN = 0xCC,
|
||||
HID_KEYPAD_SPACE = 0xCD,
|
||||
HID_KEYPAD_AT_SIGN = 0xCE,
|
||||
HID_KEYPAD_EXCLAMATION_POINT = 0xCF,
|
||||
HID_KEYPAD_MEMORY_STORE = 0xD0,
|
||||
HID_KEYPAD_MEMORY_RECALL = 0xD1,
|
||||
HID_KEYPAD_MEMORY_CLEAR = 0xD2,
|
||||
HID_KEYPAD_MEMORY_ADD = 0xD3,
|
||||
HID_KEYPAD_MEMORY_SUBTRACT = 0xD4,
|
||||
HID_KEYPAD_MEMORY_MULTIPLY = 0xD5,
|
||||
HID_KEYPAD_MEMORY_DIVIDE = 0xD6,
|
||||
HID_KEYPAD_PLUS_SLASH_MINUS = 0xD7,
|
||||
HID_KEYPAD_CLEAR = 0xD8,
|
||||
HID_KEYPAD_CLEAR_ENTRY = 0xD9,
|
||||
HID_KEYPAD_BINARY = 0xDA,
|
||||
HID_KEYPAD_OCTAL = 0xDB,
|
||||
HID_KEYPAD_DECIMAL = 0xDC,
|
||||
HID_KEYPAD_HEXADECIMAL = 0xDD,
|
||||
|
||||
// 0xDE-0xDF - RESERVED
|
||||
HID_KEYBOARD_LEFT_CONTROL = 0xE0,
|
||||
HID_KEYBOARD_LEFT_SHIFT = 0xE1,
|
||||
HID_KEYBOARD_LEFT_ALT = 0xE2,
|
||||
HID_KEYBOARD_LEFT_GUI = 0xE3,
|
||||
HID_KEYBOARD_RIGHT_CONTROL = 0xE4,
|
||||
HID_KEYBOARD_RIGHT_SHIFT = 0xE5,
|
||||
HID_KEYBOARD_RIGHT_ALT = 0xE6,
|
||||
HID_KEYBOARD_RIGHT_GUI = 0xE7,
|
||||
};
|
||||
|
||||
static const uint16_t _asciimap[] = {
|
||||
KEY_RESERVED, // NUL
|
||||
KEY_RESERVED, // SOH
|
||||
KEY_RESERVED, // STX
|
||||
KEY_RESERVED, // ETX
|
||||
KEY_RESERVED, // EOT
|
||||
KEY_RESERVED, // ENQ
|
||||
KEY_RESERVED, // ACK
|
||||
KEY_RESERVED, // BEL
|
||||
KEY_BACKSPACE, // BS Backspace
|
||||
KEY_TAB, // TAB Tab
|
||||
KEY_ENTER, // LF Enter
|
||||
KEY_RESERVED, // VT
|
||||
KEY_RESERVED, // FF
|
||||
KEY_RESERVED, // CR
|
||||
KEY_RESERVED, // SO
|
||||
KEY_RESERVED, // SI
|
||||
KEY_RESERVED, // DEL
|
||||
KEY_RESERVED, // DC1
|
||||
KEY_RESERVED, // DC2
|
||||
KEY_RESERVED, // DC3
|
||||
KEY_RESERVED, // DC4
|
||||
KEY_RESERVED, // NAK
|
||||
KEY_RESERVED, // SYN
|
||||
KEY_RESERVED, // ETB
|
||||
KEY_RESERVED, // CAN
|
||||
KEY_RESERVED, // EM
|
||||
KEY_RESERVED, // SUB
|
||||
KEY_RESERVED, // ESC
|
||||
KEY_RESERVED, // FS
|
||||
KEY_RESERVED, // GS
|
||||
KEY_RESERVED, // RS
|
||||
KEY_RESERVED, // US
|
||||
|
||||
KEY_SPACE, // ' ' Space
|
||||
KEY_1 | MOD_LEFT_SHIFT, // !
|
||||
KEY_QUOTE | MOD_LEFT_SHIFT, // "
|
||||
KEY_3 | MOD_LEFT_SHIFT, // #
|
||||
KEY_4 | MOD_LEFT_SHIFT, // $
|
||||
KEY_5 | MOD_LEFT_SHIFT, // %
|
||||
KEY_7 | MOD_LEFT_SHIFT, // &
|
||||
KEY_QUOTE, // '
|
||||
KEY_9 | MOD_LEFT_SHIFT, // (
|
||||
KEY_0 | MOD_LEFT_SHIFT, // )
|
||||
KEY_8 | MOD_LEFT_SHIFT, // *
|
||||
KEY_EQUAL | MOD_LEFT_SHIFT, // +
|
||||
KEY_COMMA, // ,
|
||||
KEY_MINUS, // -
|
||||
KEY_PERIOD, // .
|
||||
KEY_SLASH, // /
|
||||
KEY_0, // 0
|
||||
KEY_1, // 1
|
||||
KEY_2, // 2
|
||||
KEY_3, // 3
|
||||
KEY_4, // 4
|
||||
KEY_5, // 5
|
||||
KEY_6, // 6
|
||||
KEY_7, // 7
|
||||
KEY_8, // 8
|
||||
KEY_9, // 9
|
||||
KEY_SEMICOLON | MOD_LEFT_SHIFT, // :
|
||||
KEY_SEMICOLON, // ;
|
||||
KEY_COMMA | MOD_LEFT_SHIFT, // <
|
||||
KEY_EQUAL, // =
|
||||
KEY_PERIOD | MOD_LEFT_SHIFT, // >
|
||||
KEY_SLASH | MOD_LEFT_SHIFT, // ?
|
||||
KEY_2 | MOD_LEFT_SHIFT, // @
|
||||
KEY_A | MOD_LEFT_SHIFT, // A
|
||||
KEY_B | MOD_LEFT_SHIFT, // B
|
||||
KEY_C | MOD_LEFT_SHIFT, // C
|
||||
KEY_D | MOD_LEFT_SHIFT, // D
|
||||
KEY_E | MOD_LEFT_SHIFT, // E
|
||||
KEY_F | MOD_LEFT_SHIFT, // F
|
||||
KEY_G | MOD_LEFT_SHIFT, // G
|
||||
KEY_H | MOD_LEFT_SHIFT, // H
|
||||
KEY_I | MOD_LEFT_SHIFT, // I
|
||||
KEY_J | MOD_LEFT_SHIFT, // J
|
||||
KEY_K | MOD_LEFT_SHIFT, // K
|
||||
KEY_L | MOD_LEFT_SHIFT, // L
|
||||
KEY_M | MOD_LEFT_SHIFT, // M
|
||||
KEY_N | MOD_LEFT_SHIFT, // N
|
||||
KEY_O | MOD_LEFT_SHIFT, // O
|
||||
KEY_P | MOD_LEFT_SHIFT, // P
|
||||
KEY_Q | MOD_LEFT_SHIFT, // Q
|
||||
KEY_R | MOD_LEFT_SHIFT, // R
|
||||
KEY_S | MOD_LEFT_SHIFT, // S
|
||||
KEY_T | MOD_LEFT_SHIFT, // T
|
||||
KEY_U | MOD_LEFT_SHIFT, // U
|
||||
KEY_V | MOD_LEFT_SHIFT, // V
|
||||
KEY_W | MOD_LEFT_SHIFT, // W
|
||||
KEY_X | MOD_LEFT_SHIFT, // X
|
||||
KEY_Y | MOD_LEFT_SHIFT, // Y
|
||||
KEY_Z | MOD_LEFT_SHIFT, // Z
|
||||
KEY_LEFT_BRACE, // [
|
||||
KEY_BACKSLASH, // bslash
|
||||
KEY_RIGHT_BRACE, // ]
|
||||
KEY_6 | MOD_LEFT_SHIFT, // ^
|
||||
KEY_MINUS | MOD_LEFT_SHIFT, // _
|
||||
KEY_TILDE, // `
|
||||
KEY_A, // a
|
||||
KEY_B, // b
|
||||
KEY_C, // c
|
||||
KEY_D, // d
|
||||
KEY_E, // e
|
||||
KEY_F, // f
|
||||
KEY_G, // g
|
||||
KEY_H, // h
|
||||
KEY_I, // i
|
||||
KEY_J, // j
|
||||
KEY_K, // k
|
||||
KEY_L, // l
|
||||
KEY_M, // m
|
||||
KEY_N, // n
|
||||
KEY_O, // o
|
||||
KEY_P, // p
|
||||
KEY_Q, // q
|
||||
KEY_R, // r
|
||||
KEY_S, // s
|
||||
KEY_T, // t
|
||||
KEY_U, // u
|
||||
KEY_V, // v
|
||||
KEY_W, // w
|
||||
KEY_X, // x
|
||||
KEY_Y, // y
|
||||
KEY_Z, // z
|
||||
KEY_LEFT_BRACE | MOD_LEFT_SHIFT, // {
|
||||
KEY_BACKSLASH | MOD_LEFT_SHIFT, // |
|
||||
KEY_RIGHT_BRACE | MOD_LEFT_SHIFT, // }
|
||||
KEY_TILDE | MOD_LEFT_SHIFT, // ~
|
||||
KEY_RESERVED, // DEL
|
||||
// 7-bit ASCII codes end here
|
||||
|
||||
// The following characters belong to ISO-8859-15
|
||||
// ! The first 16 values here are used for the numpad
|
||||
KEYPAD_0,
|
||||
KEYPAD_1,
|
||||
KEYPAD_2,
|
||||
KEYPAD_3,
|
||||
KEYPAD_4,
|
||||
KEYPAD_5,
|
||||
KEYPAD_6,
|
||||
KEYPAD_7,
|
||||
KEYPAD_8,
|
||||
KEYPAD_9,
|
||||
KEYPAD_ADD,
|
||||
KEYPAD_SUBTRACT,
|
||||
KEYPAD_MULTIPLY,
|
||||
KEYPAD_DIVIDE,
|
||||
KEYPAD_ENTER,
|
||||
KEYPAD_DOT,
|
||||
// KEY_RESERVED, // 128 - Unused
|
||||
// KEY_RESERVED, // 129 - Unused
|
||||
// KEY_RESERVED, // 130 - Unused
|
||||
// KEY_RESERVED, // 131 - Unused
|
||||
// KEY_RESERVED, // 132 - Unused
|
||||
// KEY_RESERVED, // 133 - Unused
|
||||
// KEY_RESERVED, // 134 - Unused
|
||||
// KEY_RESERVED, // 135 - Unused
|
||||
// KEY_RESERVED, // 136 - Unused
|
||||
// KEY_RESERVED, // 137 - Unused
|
||||
// KEY_RESERVED, // 138 - Unused
|
||||
// KEY_RESERVED, // 139 - Unused
|
||||
// KEY_RESERVED, // 140 - Unused
|
||||
// KEY_RESERVED, // 141 - Unused
|
||||
// KEY_RESERVED, // 142 - Unused
|
||||
// KEY_RESERVED, // 143 - Unused
|
||||
KEY_RESERVED, // 144 - Unused
|
||||
KEY_RESERVED, // 145 - Unused
|
||||
KEY_RESERVED, // 146 - Unused
|
||||
KEY_RESERVED, // 147 - Unused
|
||||
KEY_RESERVED, // 148 - Unused
|
||||
KEY_RESERVED, // 149 - Unused
|
||||
KEY_RESERVED, // 150 - Unused
|
||||
KEY_RESERVED, // 151 - Unused
|
||||
KEY_RESERVED, // 152 - Unused
|
||||
KEY_RESERVED, // 153 - Unused
|
||||
KEY_RESERVED, // 154 - Unused
|
||||
KEY_RESERVED, // 155 - Unused
|
||||
KEY_RESERVED, // 156 - Unused
|
||||
KEY_RESERVED, // 157 - Unused
|
||||
KEY_RESERVED, // 158 - Unused
|
||||
KEY_RESERVED, // 159 - Unused
|
||||
KEY_RESERVED, // 160 - Non-breaking Space
|
||||
KEY_RESERVED, // 161 - Inverted Exclamation Mark
|
||||
KEY_RESERVED, // 162 - Cent
|
||||
KEY_RESERVED, // 163 - British Pound Sign
|
||||
KEY_RESERVED, // 164 - Euro Sign
|
||||
KEY_RESERVED, // 165 - Yen
|
||||
KEY_RESERVED, // 166 - Capital 's' Inverted Circumflex
|
||||
KEY_RESERVED, // 167 - Section Sign
|
||||
KEY_RESERVED, // 168 - 's' Inverted Circumflex
|
||||
KEY_RESERVED, // 169 - Copyright Sign
|
||||
KEY_RESERVED, // 170 - Superscript 'a'
|
||||
KEY_RESERVED, // 171 - Open Guillemet
|
||||
KEY_RESERVED, // 172 - Logic Negation
|
||||
KEY_RESERVED, // 173 - Soft Hypen
|
||||
KEY_RESERVED, // 174 - Registered Trademark
|
||||
KEY_RESERVED, // 175 - Macron
|
||||
KEY_RESERVED, // 176 - Degree Symbol
|
||||
KEY_RESERVED, // 177 - Plus-Minus
|
||||
KEY_RESERVED, // 178 - Superscript '2'
|
||||
KEY_RESERVED, // 179 - Superscript '3'
|
||||
KEY_RESERVED, // 180 - Capital 'z' Inverted Circumflex
|
||||
KEY_RESERVED, // 181 - Micro Symbol
|
||||
KEY_RESERVED, // 182 - Paragraph Mark
|
||||
KEY_RESERVED, // 183 - Interpunct
|
||||
KEY_RESERVED, // 184 - 'z' Inverted Circumflex
|
||||
KEY_RESERVED, // 185 - Superscript '1'
|
||||
KEY_RESERVED, // 186 - Ordinal Indicator
|
||||
KEY_RESERVED, // 187 - Closed Guillemet
|
||||
KEY_RESERVED, // 188 - Capital 'oe'
|
||||
KEY_RESERVED, // 189 - 'oe'
|
||||
KEY_RESERVED, // 190 - Capital 'y' Umlaut
|
||||
KEY_RESERVED, // 191 - Inverted Question Mark
|
||||
KEY_RESERVED, // 192 - Capital 'a' Grave
|
||||
KEY_RESERVED, // 193 - Capital 'a' Acute
|
||||
KEY_RESERVED, // 194 - Capital 'a' Circumflex
|
||||
KEY_RESERVED, // 195 - Capital 'a' Tilde
|
||||
KEY_RESERVED, // 196 - Capital 'a' Umlaut
|
||||
KEY_RESERVED, // 197 - Capital 'a' Circle
|
||||
KEY_RESERVED, // 198 - Capital 'ae'
|
||||
KEY_RESERVED, // 199 - Capital 'c' Cedilla
|
||||
KEY_RESERVED, // 200 - Capital 'e' Grave
|
||||
KEY_RESERVED, // 201 - Capital 'e' Acute
|
||||
KEY_RESERVED, // 202 - Capital 'e' Circumflex
|
||||
KEY_RESERVED, // 203 - Capital 'e' Umlaut
|
||||
KEY_RESERVED, // 204 - Capital 'i' Grave
|
||||
KEY_RESERVED, // 205 - Capital 'i' Acute
|
||||
KEY_RESERVED, // 206 - Capital 'i' Circumflex
|
||||
KEY_RESERVED, // 207 - Capital 'i' Umlaut
|
||||
KEY_RESERVED, // 208 - Capital Eth
|
||||
KEY_RESERVED, // 207 - Capital 'n' Tilde
|
||||
KEY_RESERVED, // 210 - Capital 'o' Grave
|
||||
KEY_RESERVED, // 211 - Capital 'o' Acute
|
||||
KEY_RESERVED, // 212 - Capital 'o' Circumflex
|
||||
KEY_RESERVED, // 213 - Capital 'o' Tilde
|
||||
KEY_RESERVED, // 214 - Capital 'o' Umlaut
|
||||
KEY_RESERVED, // 215 - Multiplication Sign
|
||||
KEY_RESERVED, // 216 - Capital 'o' Barred
|
||||
KEY_RESERVED, // 217 - Capital 'u' Grave
|
||||
KEY_RESERVED, // 218 - Capital 'u' Acute
|
||||
KEY_RESERVED, // 219 - Capital 'u' Circumflex
|
||||
KEY_RESERVED, // 220 - Capital 'u' Umlaut
|
||||
KEY_RESERVED, // 221 - Capital 'y' Acute
|
||||
KEY_RESERVED, // 222 - Capital Thorn
|
||||
KEY_RESERVED, // 223 - Eszett
|
||||
KEY_RESERVED, // 224 - 'a' Grave
|
||||
KEY_RESERVED, // 225 - 'a' Acute
|
||||
KEY_RESERVED, // 226 - 'a' Circumflex
|
||||
KEY_RESERVED, // 227 - 'a' Tilde
|
||||
KEY_RESERVED, // 228 - 'a' Umlaut
|
||||
KEY_RESERVED, // 229 - 'a' Circle
|
||||
KEY_RESERVED, // 230 - 'ae'
|
||||
KEY_RESERVED, // 231 - 'c' Cedilla
|
||||
KEY_RESERVED, // 232 - 'e' Grave
|
||||
KEY_RESERVED, // 233 - 'e' Acute
|
||||
KEY_RESERVED, // 234 - 'e' Circumflex
|
||||
KEY_RESERVED, // 235 - 'e' Umlaut
|
||||
KEY_RESERVED, // 236 - 'i' Grave
|
||||
KEY_RESERVED, // 237 - 'i' Acute
|
||||
KEY_RESERVED, // 238 - 'i' Circumflex
|
||||
KEY_RESERVED, // 239 - 'i' Umlaut
|
||||
KEY_RESERVED, // 240 - Eth
|
||||
KEY_RESERVED, // 241 - 'n' Tilde
|
||||
KEY_RESERVED, // 242 - 'o' Grave
|
||||
KEY_RESERVED, // 243 - 'o' Acute
|
||||
KEY_RESERVED, // 244 - 'o' Circumflex
|
||||
KEY_RESERVED, // 245 - 'o' Tilde
|
||||
KEY_RESERVED, // 246 - 'o' Umlaut
|
||||
KEY_RESERVED, // 247 - Multiplication Sign
|
||||
KEY_RESERVED, // 248 - 'o' Barred
|
||||
KEY_RESERVED, // 249 - 'u' Grave
|
||||
KEY_RESERVED, // 250 - 'u' Acute
|
||||
KEY_RESERVED, // 251 - 'u' Circumflex
|
||||
KEY_RESERVED, // 252 - 'u' Umlaut
|
||||
KEY_RESERVED, // 253 - 'y' Acute
|
||||
KEY_RESERVED, // 254 - Thorn
|
||||
KEY_RESERVED, // 255 - 'y' Umlaut
|
||||
};
|
316
src/usb_inc/usb.h
Normal file
316
src/usb_inc/usb.h
Normal file
@ -0,0 +1,316 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
// USB U16 helpers
|
||||
#define U16(_high, _low) ((uint16_t)(((_high) << 8) | (_low)))
|
||||
#define U16_HIGH(_u16) ((uint8_t)(((_u16) >> 8) & 0x00ff))
|
||||
#define U16_LOW(_u16) ((uint8_t)((_u16)&0x00ff))
|
||||
#define U16_TO_U8S_BE(_u16) U16_HIGH(_u16), U16_LOW(_u16)
|
||||
#define U16_TO_U8S_LE(_u16) U16_LOW(_u16), U16_HIGH(_u16)
|
||||
#define U16_TO_U8S_BE_A(_u16) \
|
||||
{ U16_TO_U8S_BE(_u16) }
|
||||
#define U16_TO_U8S_LE_A(_u16) \
|
||||
{ U16_TO_U8S_LE(_u16) }
|
||||
|
||||
// USB String helpers
|
||||
enum {
|
||||
USB_STRING_LANG = 0,
|
||||
USB_STRING_VENDOR,
|
||||
USB_STRING_PRODUCT,
|
||||
USB_STRING_SERIAL,
|
||||
USB_STRING_CDC,
|
||||
USB_STRING_HID_IO4,
|
||||
USB_STRING_HID_MISC,
|
||||
};
|
||||
|
||||
// USB Spec definitions
|
||||
#define DESC_IAD 0x0B
|
||||
#define DESC_CS_DEVICE 0x21
|
||||
#define DESC_CS_CONFIGURATION 0x22
|
||||
#define DESC_CS_STRING 0x23
|
||||
#define DESC_CS_INTERFACE 0x24
|
||||
#define DESC_CS_ENDPOINT 0x25
|
||||
|
||||
#define USB_CLASS_UNSPECIFIED 0
|
||||
#define USB_CLASS_AUDIO 1
|
||||
#define USB_CLASS_CDC 2
|
||||
#define USB_CLASS_HID 3
|
||||
#define USB_CLASS_RESERVED_4 4
|
||||
#define USB_CLASS_PHYSICAL 5
|
||||
#define USB_CLASS_IMAGE 6
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MSC 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_CDC_DATA 10
|
||||
#define USB_CLASS_SMART_CARD 11
|
||||
#define USB_CLASS_RESERVED_12 12
|
||||
#define USB_CLASS_CONTENT_SECURITY 13
|
||||
#define USB_CLASS_VIDEO 14
|
||||
#define USB_CLASS_PERSONAL_HEALTHCARE 15
|
||||
#define USB_CLASS_AUDIO_VIDEO 16
|
||||
|
||||
#define USB_CLASS_DIAGNOSTIC 0xDC
|
||||
#define USB_CLASS_WIRELESS_CONTROLLER 0xE0
|
||||
#define USB_CLASS_MISC 0xEF
|
||||
#define USB_CLASS_APPLICATION_SPECIFIC 0xFE
|
||||
#define USB_CLASS_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
#define CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL 0x01
|
||||
#define CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL 0x02
|
||||
#define CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL 0x03
|
||||
#define CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL 0x04
|
||||
#define CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL 0x05
|
||||
#define CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL 0x06
|
||||
#define CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL 0x07
|
||||
#define CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL0x08
|
||||
#define CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT 0x09
|
||||
#define CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL 0x0A
|
||||
#define CDC_COMM_SUBCLASS_OBEX 0x0B
|
||||
#define CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL 0x0C
|
||||
#define CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL 0x0D
|
||||
|
||||
#define CDC_COMM_PROTOCOL_NONE 0x00
|
||||
#define CDC_COMM_PROTOCOL_ATCOMMAND 0x01
|
||||
#define CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 0x02
|
||||
#define CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO0x03
|
||||
#define CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 0x04
|
||||
#define CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 0x05
|
||||
#define CDC_COMM_PROTOCOL_ATCOMMAND_CDMA 0x06
|
||||
#define CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL 0x07
|
||||
|
||||
#define CDC_FUNC_DESC_HEADER 0x00
|
||||
#define CDC_FUNC_DESC_CALL_MANAGEMENT 0x01
|
||||
#define CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT 0x02
|
||||
#define CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT 0x03
|
||||
#define CDC_FUNC_DESC_TELEPHONE_RINGER 0x04
|
||||
#define CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY0x05
|
||||
#define CDC_FUNC_DESC_UNION 0x06
|
||||
#define CDC_FUNC_DESC_COUNTRY_SELECTION 0x07
|
||||
#define CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES 0x08
|
||||
#define CDC_FUNC_DESC_USB_TERMINAL 0x09
|
||||
#define CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL 0x0A
|
||||
#define CDC_FUNC_DESC_PROTOCOL_UNIT 0x0B
|
||||
#define CDC_FUNC_DESC_EXTENSION_UNIT 0x0C
|
||||
#define CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT 0x0D
|
||||
#define CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT 0x0E
|
||||
#define CDC_FUNC_DESC_ETHERNET_NETWORKING 0x0F
|
||||
#define CDC_FUNC_DESC_ATM_NETWORKING 0x10
|
||||
#define CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL 0x11
|
||||
#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL 0x12
|
||||
#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL 0x13
|
||||
#define CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL 0x14
|
||||
#define CDC_FUNC_DESC_OBEX 0x15
|
||||
#define CDC_FUNC_DESC_COMMAND_SET 0x16
|
||||
#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
|
||||
#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
|
||||
#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
|
||||
#define CDC_FUNC_DESC_NCM 0x1A
|
||||
|
||||
#define SET_LINE_CODING 0x20
|
||||
#define GET_LINE_CODING 0x21
|
||||
#define SET_CONTROL_LINE_STATE 0x22
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
union {
|
||||
uint8_t wBytes[6];
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
};
|
||||
|
||||
// Core setup packet types
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t bIndex;
|
||||
uint8_t bType;
|
||||
uint16_t wLanguageId;
|
||||
uint16_t wDescriptorLength;
|
||||
} getDescriptor;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wFeature;
|
||||
uint16_t wEp;
|
||||
} clearFeature;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wAddress;
|
||||
} setAddress;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wConfiguration;
|
||||
} setConfiguration;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wFeature;
|
||||
uint16_t wEp;
|
||||
} setFeature;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wAlternate;
|
||||
uint16_t wInterface;
|
||||
} setInterface;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wValue;
|
||||
uint16_t wInterface;
|
||||
} getStatus;
|
||||
|
||||
// USB HID
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t bIndex;
|
||||
uint8_t bType;
|
||||
uint16_t wInterfaceNum;
|
||||
uint16_t wDescriptorLength;
|
||||
} hidGetDescriptor;
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint8_t bReportType;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} hidGetReport;
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint8_t bReportType;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} hidSetReport;
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint8_t bPad;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} hidGetIdle;
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t bReportId;
|
||||
uint8_t bDuration;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} hidSetIdle;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wPad;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} hidGetProtocol;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wProtocol;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} hidSetProtocol;
|
||||
|
||||
// USB CDC
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wValue;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} getLineCoding;
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t wValue;
|
||||
uint16_t wInterface;
|
||||
uint16_t wLength;
|
||||
} setLineCoding;
|
||||
};
|
||||
} usb_setup_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
uint8_t iManufacture;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} usb_device_descr_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bFirstInterface;
|
||||
uint8_t bInterfaceCount;
|
||||
uint8_t bFunctionClass;
|
||||
uint8_t bFunctionSubClass;
|
||||
uint8_t bFunctionProtocol;
|
||||
uint8_t iFunction;
|
||||
} usb_desc_iad_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wTotalLength;
|
||||
uint8_t bNumInterfaces;
|
||||
uint8_t bConfigurationValue;
|
||||
uint8_t iConfiguration;
|
||||
uint8_t bmAttributes;
|
||||
uint8_t MaxPower;
|
||||
} usb_desc_config_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bAlternateSetting;
|
||||
uint8_t bNumEndpoints;
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
uint8_t iInterface;
|
||||
} usb_desc_interface_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bReportDescriptorType;
|
||||
uint16_t wDescriptorLength;
|
||||
} usb_desc_hid_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmAttributes;
|
||||
uint16_t wMaxPacketSize;
|
||||
uint8_t bInterval;
|
||||
} usb_desc_endpoint_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint16_t bcdCDC;
|
||||
} usb_desc_cdc_header_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bControlInterface;
|
||||
uint8_t bSubordinateInterface0;
|
||||
} usb_desc_cdc_union_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bmCapabilities;
|
||||
uint8_t bDataInterface;
|
||||
} usb_desc_cdc_call_t;
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bmCapabilities;
|
||||
} usb_desc_cdc_acm_t;
|
||||
|
||||
// HID definitions
|
||||
#define GET_REPORT 0x01
|
||||
#define GET_IDLE 0x02
|
||||
#define GET_PROTOCOL 0x03
|
||||
#define SET_REPORT 0x09
|
||||
#define SET_IDLE 0x0A
|
||||
#define SET_PROTOCOL 0x0B
|
||||
|
||||
#define HID_NONE 0x00
|
||||
#define HID_KEYBOARD 0x01
|
||||
#define HID_MOUSE 0x02
|
||||
|
||||
#define HID_RPT_TYPE_INPUT 0x01
|
||||
#define HID_RPT_TYPE_OUTPUT 0x02
|
||||
#define HID_RPT_TYPE_FEATURE 0x03
|
551
src/usbd_driver.c
Normal file
551
src/usbd_driver.c
Normal file
@ -0,0 +1,551 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
usb_setup_t g_usbd_SetupPacket;
|
||||
// uint8_t g_usbd_SetupPacket[8] = { 0 };
|
||||
// static const usb_setup_t* p_usbd_SetupPacket = (usb_setup_t*)&g_usbd_SetupPacket;
|
||||
volatile uint8_t g_usbd_RemoteWakeupEn = 0;
|
||||
|
||||
volatile uint8_t *g_usbd_CtrlInPointer = 0;
|
||||
volatile uint32_t g_usbd_CtrlInSize = 0;
|
||||
static volatile uint8_t *g_usbd_CtrlOutPointer = 0;
|
||||
static volatile uint32_t g_usbd_CtrlOutSize = 0;
|
||||
static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0;
|
||||
static volatile uint32_t g_usbd_UsbAddr = 0;
|
||||
static volatile uint32_t g_usbd_UsbConfig = 0;
|
||||
static volatile uint32_t g_usbd_CtrlMaxPktSize = 8;
|
||||
static volatile uint32_t g_usbd_UsbAltInterface = 0;
|
||||
static volatile uint32_t g_usbd_CtrlOutToggle = 0;
|
||||
static volatile uint8_t g_usbd_CtrlInZeroFlag = 0;
|
||||
static void (*g_usbd_CtrlOutCallback)(volatile uint8_t *, uint32_t);
|
||||
|
||||
uint32_t g_u32EpStallLock = 0;
|
||||
|
||||
static inline void Tas_USBD_GetDescriptor(void);
|
||||
static inline void Tas_USBD_StandardRequest(void);
|
||||
|
||||
static uint8_t su8VendorCount = 0;
|
||||
|
||||
void Tas_USBD_Open(void) {
|
||||
g_usbd_CtrlMaxPktSize = gpDeviceDescriptor->bMaxPacketSize0;
|
||||
USBD->ATTR = 0x650; // Disable D+ and USB controller
|
||||
CLK_SysTickLongDelay(3000 ms);
|
||||
USBD->ATTR = 0x7D0;
|
||||
USBD_SET_SE0();
|
||||
}
|
||||
void Tas_USBD_Init(void) {
|
||||
// Buffer range for setup packet -> [0~7]
|
||||
USBD->STBUFSEG = SETUP_BUF_BASE;
|
||||
|
||||
// USB control IN/OUT on EP_CTRL_IN/EP_CTRL_OUT (addr 0)
|
||||
USBD_CONFIG_EP(EP_CTRL_IN, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | 0);
|
||||
USBD_SET_EP_BUF_ADDR(EP_CTRL_IN, EP0_BUF_BASE);
|
||||
USBD_CONFIG_EP(EP_CTRL_OUT, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | 0);
|
||||
USBD_SET_EP_BUF_ADDR(EP_CTRL_OUT, EP1_BUF_BASE);
|
||||
|
||||
// CDC data IN/OUT on EP2/EP3
|
||||
USBD_CONFIG_EP(EP_CDC_IN, USBD_CFG_EPMODE_IN | 1);
|
||||
USBD_SET_EP_BUF_ADDR(EP_CDC_IN, EP2_BUF_BASE);
|
||||
USBD_CONFIG_EP(EP_CDC_OUT, USBD_CFG_EPMODE_OUT | 2);
|
||||
USBD_SET_EP_BUF_ADDR(EP_CDC_OUT, EP3_BUF_BASE);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CDC_OUT, USBD_CDC_OUT_MAX_SIZE);
|
||||
|
||||
// CDC command IN on EP4
|
||||
USBD_CONFIG_EP(EP_CDC_CMD, USBD_CFG_EPMODE_IN | 3);
|
||||
USBD_SET_EP_BUF_ADDR(EP_CDC_CMD, EP4_BUF_BASE);
|
||||
|
||||
// IO4 HID IN on EP5
|
||||
USBD_CONFIG_EP(EP_HID_IO4_IN, USBD_CFG_EPMODE_IN | 4);
|
||||
USBD_SET_EP_BUF_ADDR(EP_HID_IO4_IN, EP5_BUF_BASE);
|
||||
|
||||
// Misc HID IN/OUT on EP6/EP6
|
||||
USBD_CONFIG_EP(EP_HID_MISC_IN, USBD_CFG_EPMODE_IN | 5);
|
||||
USBD_SET_EP_BUF_ADDR(EP_HID_MISC_IN, EP6_BUF_BASE);
|
||||
USBD_CONFIG_EP(EP_HID_MISC_OUT, USBD_CFG_EPMODE_OUT | 6);
|
||||
USBD_SET_EP_BUF_ADDR(EP_HID_MISC_OUT, EP7_BUF_BASE);
|
||||
USBD_SET_PAYLOAD_LEN(EP_HID_MISC_OUT, USBD_HID_BUF_LEN);
|
||||
}
|
||||
void Tas_USBD_Start(void) {
|
||||
// 100ms delay required as part of spec
|
||||
CLK_SysTickDelay(100 ms);
|
||||
|
||||
USBD_CLR_SE0(); // Disable software-disconnect function
|
||||
|
||||
// Clear USB-related interrupts before enable interrupt
|
||||
USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
|
||||
// Enable USB-related interrupts.
|
||||
USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
|
||||
}
|
||||
|
||||
void Tas_USBD_GetSetupPacket(usb_setup_t *buf) {
|
||||
memcpy(buf, &g_usbd_SetupPacket, sizeof g_usbd_SetupPacket);
|
||||
}
|
||||
|
||||
// <static inline> as unused for now
|
||||
static inline void Tas_USBD_VendorRequest(void) { return; }
|
||||
|
||||
void Tas_USBD_ProcessSetupPacket(void) {
|
||||
g_usbd_CtrlOutToggle = 0;
|
||||
// Get SETUP packet from USB buffer
|
||||
USBD_MemCopy((uint8_t *)&g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8);
|
||||
|
||||
// Check the request type
|
||||
switch (g_usbd_SetupPacket.bmRequestType & 0x60) {
|
||||
case REQ_STANDARD:
|
||||
Tas_USBD_StandardRequest();
|
||||
break;
|
||||
case REQ_CLASS:
|
||||
Tas_USBD_ClassRequest();
|
||||
break;
|
||||
case REQ_VENDOR:
|
||||
Tas_USBD_VendorRequest();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Setup error, stall the device
|
||||
USBD_SET_EP_STALL(EP_CTRL_IN);
|
||||
USBD_SET_EP_STALL(EP_CTRL_OUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Tas_USBD_GetDescriptor(void) {
|
||||
uint16_t u16Len;
|
||||
|
||||
g_usbd_CtrlInZeroFlag = 0;
|
||||
u16Len = g_usbd_SetupPacket.wLength;
|
||||
|
||||
switch (g_usbd_SetupPacket.getDescriptor.bType) {
|
||||
// Get Device Descriptor
|
||||
case DESC_DEVICE:
|
||||
su8VendorCount = 0;
|
||||
|
||||
u16Len = Minimum(u16Len, LEN_DEVICE);
|
||||
Tas_USBD_PrepareCtrlIn((uint8_t *)gpDeviceDescriptor, u16Len);
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
// Get Configuration Descriptor
|
||||
case DESC_CONFIG: {
|
||||
uint32_t u32TotalLen = gpConfigDescriptor->wTotalLength;
|
||||
if (u16Len > u32TotalLen) {
|
||||
u16Len = u32TotalLen;
|
||||
if ((u16Len % g_usbd_CtrlMaxPktSize) == 0) g_usbd_CtrlInZeroFlag = 1;
|
||||
}
|
||||
Tas_USBD_PrepareCtrlIn((uint8_t *)gpConfigDescriptor, u16Len);
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
}
|
||||
// Get HID Descriptor
|
||||
case DESC_HID:
|
||||
/* CV3.0 HID Class Descriptor Test,
|
||||
Need to indicate index of the HID Descriptor within gConfigDescriptor, specifically
|
||||
HID Composite device. */
|
||||
uint32_t u32ConfigDescOffset = 0; // u32ConfigDescOffset is configuration descriptor
|
||||
// offset (HID descriptor start index)
|
||||
u16Len = Minimum(u16Len, LEN_HID);
|
||||
|
||||
if (g_usbd_SetupPacket.hidGetDescriptor.wInterfaceNum == USBD_ITF_HID_IO4)
|
||||
u32ConfigDescOffset = gu32HidDescIO4Offset;
|
||||
else if (g_usbd_SetupPacket.hidGetDescriptor.wInterfaceNum == USBD_ITF_HID_MISC)
|
||||
u32ConfigDescOffset = gu32HidDescMiscOffset;
|
||||
Tas_USBD_PrepareCtrlIn(((uint8_t *)gpConfigDescriptor) + u32ConfigDescOffset, u16Len);
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
// Get Report Descriptor
|
||||
case DESC_HID_RPT:
|
||||
if (g_usbd_SetupPacket.hidGetDescriptor.wInterfaceNum == USBD_ITF_HID_IO4) {
|
||||
if (u16Len > gu32UsbHidIO4ReportLen) {
|
||||
u16Len = gu32UsbHidIO4ReportLen;
|
||||
if ((u16Len % g_usbd_CtrlMaxPktSize) == 0) g_usbd_CtrlInZeroFlag = 1;
|
||||
}
|
||||
Tas_USBD_PrepareCtrlIn((uint8_t *)gpu8UsbHidIO4Report, u16Len);
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
} else if (g_usbd_SetupPacket.hidGetDescriptor.wInterfaceNum == USBD_ITF_HID_MISC) {
|
||||
if (u16Len > gu32UsbHidMiscReportLen) {
|
||||
u16Len = gu32UsbHidMiscReportLen;
|
||||
if ((u16Len % g_usbd_CtrlMaxPktSize) == 0) g_usbd_CtrlInZeroFlag = 1;
|
||||
}
|
||||
Tas_USBD_PrepareCtrlIn((uint8_t *)gpu8UsbHidMiscReport, u16Len);
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
} else {
|
||||
Tas_USBD_PrepareCtrlIn(NULL, u16Len);
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Get String Descriptor
|
||||
case DESC_STRING: {
|
||||
uint8_t iString = g_usbd_SetupPacket.getDescriptor.bIndex;
|
||||
static uint8_t u8Str[256]; // IO4 needs at least 2+(2*96)=194
|
||||
|
||||
memset(u8Str, 0, sizeof u8Str);
|
||||
u8Str[1] = DESC_STRING;
|
||||
|
||||
switch (iString) {
|
||||
case USB_STRING_LANG:
|
||||
u8Str[0] = 2 + (2 * 2);
|
||||
u8Str[2] = 0x09;
|
||||
u8Str[3] = 0x04;
|
||||
break;
|
||||
|
||||
case USB_STRING_VENDOR: {
|
||||
const char *szVendor;
|
||||
if (su8VendorCount < 2) {
|
||||
szVendor = gszVendorInitial;
|
||||
su8VendorCount++;
|
||||
} else {
|
||||
szVendor = gszVendor;
|
||||
}
|
||||
|
||||
uint8_t u8Len = strlen(szVendor);
|
||||
u8Str[0] = 2 + u8Len * 2;
|
||||
for (uint8_t i = 0; i < u8Len; i++) {
|
||||
u8Str[2 + i * 2] = szVendor[i];
|
||||
u8Str[2 + i * 2 + 1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USB_STRING_PRODUCT: {
|
||||
uint8_t u8Len = strlen(gszProduct);
|
||||
u8Str[0] = 2 + u8Len * 2;
|
||||
for (uint8_t i = 0; i < u8Len; i++) {
|
||||
u8Str[2 + i * 2] = gszProduct[i];
|
||||
u8Str[2 + i * 2 + 1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USB_STRING_SERIAL: {
|
||||
// TODO: I think it might be a u16 then two u8s?
|
||||
// Need to check the TRM
|
||||
uint32_t u32serial;
|
||||
|
||||
FMC_Open();
|
||||
u8Str[0] = 2 + (2 * 24);
|
||||
|
||||
u32serial = FMC_ReadUID(0);
|
||||
for (int i = 0; i < 8; i++)
|
||||
u8Str[2 + i * 2] = HEX_NIBBLE((u32serial >> (i * 4)));
|
||||
u32serial = FMC_ReadUID(1);
|
||||
for (int i = 0; i < 8; i++)
|
||||
u8Str[2 + (8 * 2) + i * 2] = HEX_NIBBLE((u32serial >> (i * 4)));
|
||||
u32serial = FMC_ReadUID(2);
|
||||
for (int i = 0; i < 8; i++)
|
||||
u8Str[2 + (16 * 2) + i * 2] = HEX_NIBBLE((u32serial >> (i * 4)));
|
||||
|
||||
FMC_Close();
|
||||
break;
|
||||
}
|
||||
case USB_STRING_CDC: {
|
||||
const char *szCdc = "TASOLLER Slider Serial (COM1)";
|
||||
uint8_t u8Len = strlen(szCdc);
|
||||
u8Str[0] = 2 + u8Len * 2;
|
||||
for (uint8_t i = 0; i < u8Len; i++) {
|
||||
u8Str[2 + i * 2] = szCdc[i];
|
||||
u8Str[2 + i * 2 + 1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USB_STRING_HID_IO4: {
|
||||
const char *szCdc = IO4_PRODUCT;
|
||||
uint8_t u8Len = strlen(szCdc);
|
||||
u8Str[0] = 2 + u8Len * 2;
|
||||
for (uint8_t i = 0; i < u8Len; i++) {
|
||||
u8Str[2 + i * 2] = szCdc[i];
|
||||
u8Str[2 + i * 2 + 1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USB_STRING_HID_MISC: {
|
||||
const char *szCdc = "TASOLLER HID";
|
||||
uint8_t u8Len = strlen(szCdc);
|
||||
u8Str[0] = 2 + u8Len * 2;
|
||||
for (uint8_t i = 0; i < u8Len; i++) {
|
||||
u8Str[2 + i * 2] = szCdc[i];
|
||||
u8Str[2 + i * 2 + 1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Not support. Reply STALL.
|
||||
USBD_SET_EP_STALL(EP_CTRL_IN);
|
||||
USBD_SET_EP_STALL(EP_CTRL_OUT);
|
||||
break;
|
||||
}
|
||||
|
||||
if (u8Str[0] != 0) {
|
||||
if (u16Len > u8Str[0]) u16Len = u8Str[0];
|
||||
if ((u16Len % g_usbd_CtrlMaxPktSize) == 0) g_usbd_CtrlInZeroFlag = 1;
|
||||
Tas_USBD_PrepareCtrlIn(u8Str, u16Len);
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Not support. Reply STALL.
|
||||
USBD_SET_EP_STALL(EP_CTRL_IN);
|
||||
USBD_SET_EP_STALL(EP_CTRL_OUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Tas_USBD_StandardRequest(void) {
|
||||
// Clear global variables for new request
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
|
||||
// Switch on request data transfer direction
|
||||
if (g_usbd_SetupPacket.bmRequestType & 0x80) {
|
||||
// Device to host
|
||||
switch (g_usbd_SetupPacket.bRequest) {
|
||||
case GET_CONFIGURATION:
|
||||
// Return current configuration setting
|
||||
/* Data stage */
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN)) = g_usbd_UsbConfig;
|
||||
USBD_SET_DATA1(EP_CTRL_OUT);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_OUT, 0);
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 1);
|
||||
/* Status stage */
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
case GET_DESCRIPTOR:
|
||||
Tas_USBD_GetDescriptor();
|
||||
/* Status stage */
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
case GET_INTERFACE:
|
||||
// Return current interface setting
|
||||
// Data stage
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN)) = g_usbd_UsbAltInterface;
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 1);
|
||||
// Status stage
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
case GET_STATUS:
|
||||
// Device
|
||||
if (g_usbd_SetupPacket.bmRequestType == 0x80) {
|
||||
uint8_t u8Tmp;
|
||||
|
||||
u8Tmp = 0;
|
||||
if (gpConfigDescriptor->bmAttributes & 0x40)
|
||||
u8Tmp |= 1; // Self-Powered/Bus-Powered.
|
||||
if (gpConfigDescriptor->bmAttributes & 0x20)
|
||||
u8Tmp |= (g_usbd_RemoteWakeupEn << 1); // Remote wake up
|
||||
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN)) = u8Tmp;
|
||||
}
|
||||
// Interface
|
||||
else if (g_usbd_SetupPacket.bmRequestType == 0x81)
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN)) = 0;
|
||||
// Endpoint
|
||||
else if (g_usbd_SetupPacket.bmRequestType == 0x82) {
|
||||
uint8_t ep = g_usbd_SetupPacket.getStatus.wInterface & 0xF;
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN)) =
|
||||
USBD_GetStall(ep) ? 1 : 0;
|
||||
}
|
||||
|
||||
M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN) + 1) = 0;
|
||||
// Data stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 2);
|
||||
// Status stage
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Setup error, stall the device
|
||||
USBD_SET_EP_STALL(EP_CTRL_IN);
|
||||
USBD_SET_EP_STALL(EP_CTRL_OUT);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Host to device
|
||||
switch (g_usbd_SetupPacket.bRequest) {
|
||||
case CLEAR_FEATURE:
|
||||
if (g_usbd_SetupPacket.clearFeature.wFeature == FEATURE_ENDPOINT_HALT) {
|
||||
int32_t epNum, i;
|
||||
|
||||
/* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
|
||||
a flag: g_u32EpStallLock is added to support it */
|
||||
epNum = g_usbd_SetupPacket.clearFeature.wEp & 0xF;
|
||||
for (i = 0; i < USBD_MAX_EP; i++) {
|
||||
if (((USBD->EP[i].CFG & 0xF) == epNum) &&
|
||||
((g_u32EpStallLock & (1 << i)) == 0)) {
|
||||
USBD->EP[i].CFGP &= ~USBD_CFGP_SSTALL_Msk;
|
||||
USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
|
||||
}
|
||||
}
|
||||
} else if (g_usbd_SetupPacket.clearFeature.wFeature == FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||
g_usbd_RemoteWakeupEn = 0;
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_ADDRESS:
|
||||
g_usbd_UsbAddr = g_usbd_SetupPacket.setAddress.wAddress;
|
||||
|
||||
// DATA IN for end of setup
|
||||
// Status Stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_CONFIGURATION:
|
||||
g_usbd_UsbConfig = g_usbd_SetupPacket.setConfiguration.wConfiguration;
|
||||
|
||||
// Callback would be here if we wanted to have one :)
|
||||
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_FEATURE:
|
||||
if (g_usbd_SetupPacket.setFeature.wFeature == FEATURE_ENDPOINT_HALT) {
|
||||
USBD_SetStall(g_usbd_SetupPacket.setFeature.wEp & 0xF);
|
||||
} else if (g_usbd_SetupPacket.setFeature.wFeature == FEATURE_DEVICE_REMOTE_WAKEUP) {
|
||||
g_usbd_RemoteWakeupEn = 1;
|
||||
}
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_INTERFACE:
|
||||
g_usbd_UsbAltInterface = g_usbd_SetupPacket.setInterface.wAlternate;
|
||||
// Callback would be here if wanted to have one :)
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Setup error, stall the device
|
||||
USBD_SET_EP_STALL(EP_CTRL_IN);
|
||||
USBD_SET_EP_STALL(EP_CTRL_OUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tas_USBD_PrepareCtrlIn(void *pu8Buf, uint32_t u32Size) {
|
||||
if (u32Size > g_usbd_CtrlMaxPktSize) {
|
||||
// Data size > MXPLD
|
||||
g_usbd_CtrlInPointer = (uint8_t *)pu8Buf + g_usbd_CtrlMaxPktSize;
|
||||
g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize;
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN), (uint8_t *)pu8Buf,
|
||||
g_usbd_CtrlMaxPktSize);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, g_usbd_CtrlMaxPktSize);
|
||||
} else {
|
||||
// Data size <= MXPLD
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN), (uint8_t *)pu8Buf,
|
||||
u32Size);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, u32Size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Repeat Control IN pipe
|
||||
* @details This function processes the remained data of Control IN transfer.
|
||||
*/
|
||||
void Tas_USBD_CtrlIn(void) {
|
||||
if (g_usbd_CtrlInSize) {
|
||||
// Process remained data
|
||||
if (g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize) {
|
||||
// Data size > MXPLD
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN),
|
||||
(uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, g_usbd_CtrlMaxPktSize);
|
||||
g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize;
|
||||
g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
|
||||
} else {
|
||||
// Data size <= MXPLD
|
||||
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN),
|
||||
(uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, g_usbd_CtrlInSize);
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
}
|
||||
} else { // No more data for IN token
|
||||
// In ACK for Set address
|
||||
if ((g_usbd_SetupPacket.bmRequestType == REQ_STANDARD) &&
|
||||
(g_usbd_SetupPacket.bRequest == SET_ADDRESS)) {
|
||||
if ((USBD_GET_ADDR() != g_usbd_UsbAddr) && (USBD_GET_ADDR() == 0)) {
|
||||
USBD_SET_ADDR(g_usbd_UsbAddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* For the case of data size is integral times maximum packet size */
|
||||
if (g_usbd_CtrlInZeroFlag) {
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
g_usbd_CtrlInZeroFlag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tas_USBD_PrepareCtrlOut(void *pu8Buf, uint32_t u32Size,
|
||||
void (*pCallback)(volatile uint8_t *, uint32_t)) {
|
||||
g_usbd_CtrlOutPointer = pu8Buf;
|
||||
g_usbd_CtrlOutSize = 0;
|
||||
g_usbd_CtrlOutSizeLimit = u32Size;
|
||||
g_usbd_CtrlOutCallback = pCallback;
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_OUT, g_usbd_CtrlMaxPktSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Repeat Control OUT pipe
|
||||
* @details This function processes the successive Control OUT transfer.
|
||||
*/
|
||||
void Tas_USBD_CtrlOut(void) {
|
||||
uint32_t u32Size;
|
||||
|
||||
if (g_usbd_CtrlOutToggle != (USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk)) {
|
||||
g_usbd_CtrlOutToggle = USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk;
|
||||
if (g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit) {
|
||||
u32Size = USBD_GET_PAYLOAD_LEN(EP_CTRL_OUT);
|
||||
USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer,
|
||||
(uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_OUT), u32Size);
|
||||
g_usbd_CtrlOutPointer += u32Size;
|
||||
g_usbd_CtrlOutSize += u32Size;
|
||||
|
||||
if (g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_OUT, g_usbd_CtrlMaxPktSize);
|
||||
}
|
||||
|
||||
if (g_usbd_CtrlOutSize >= g_usbd_CtrlOutSizeLimit && g_usbd_CtrlOutCallback) {
|
||||
g_usbd_CtrlOutCallback(g_usbd_CtrlOutPointer - g_usbd_CtrlOutSize, g_usbd_CtrlOutSize);
|
||||
}
|
||||
} else {
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_OUT, g_usbd_CtrlMaxPktSize);
|
||||
}
|
||||
}
|
||||
|
||||
void Tas_USBD_SwReset(void) {
|
||||
// Reset all variables for protocol
|
||||
g_usbd_CtrlInPointer = 0;
|
||||
g_usbd_CtrlInSize = 0;
|
||||
g_usbd_CtrlOutPointer = 0;
|
||||
g_usbd_CtrlOutSize = 0;
|
||||
g_usbd_CtrlOutSizeLimit = 0;
|
||||
g_u32EpStallLock = 0;
|
||||
memset(&g_usbd_SetupPacket, 0, 8);
|
||||
|
||||
// Reset PID DATA0
|
||||
for (int i = 0; i < USBD_MAX_EP; i++) USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
|
||||
|
||||
// Reset USB device address
|
||||
USBD_SET_ADDR(0);
|
||||
}
|
245
src/usbd_user.c
Normal file
245
src/usbd_user.c
Normal file
@ -0,0 +1,245 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
uint8_t volatile g_u8Suspend = 0;
|
||||
uint8_t g_u8Idle = 0;
|
||||
uint8_t g_u8Protocol = 0;
|
||||
|
||||
uint8_t gHidSetReport[64];
|
||||
|
||||
STR_VCOM_LINE_CODING gLineCoding = { 0, 0, 0, 0 };
|
||||
uint16_t gCtrlSignal;
|
||||
|
||||
uint32_t volatile g_u32OutToggle = 0;
|
||||
|
||||
void USBD_IRQHandler(void) {
|
||||
uint32_t u32IntSts = USBD_GET_INT_FLAG();
|
||||
uint32_t u32State = USBD_GET_BUS_STATE();
|
||||
|
||||
if (u32IntSts & USBD_INTSTS_FLDET) {
|
||||
// Floating detect
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_FLDET);
|
||||
|
||||
if (USBD_IS_ATTACHED()) {
|
||||
USBD_ENABLE_USB();
|
||||
} else {
|
||||
USBD_DISABLE_USB();
|
||||
}
|
||||
}
|
||||
|
||||
if (u32IntSts & USBD_INTSTS_WAKEUP) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_WAKEUP);
|
||||
}
|
||||
|
||||
if (u32IntSts & USBD_INTSTS_BUS) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_BUS);
|
||||
|
||||
if (u32State & USBD_STATE_USBRST) {
|
||||
// Bus reset
|
||||
USBD_ENABLE_USB();
|
||||
Tas_USBD_SwReset();
|
||||
g_u32OutToggle = 0;
|
||||
g_u8Suspend = 0;
|
||||
}
|
||||
if (u32State & USBD_STATE_SUSPEND) {
|
||||
// Enter power down to wait USB attached; enable USB but disable PHY
|
||||
g_u8Suspend = 1;
|
||||
USBD_DISABLE_PHY();
|
||||
}
|
||||
if (u32State & USBD_STATE_RESUME) {
|
||||
// Enable USB and enable PHY
|
||||
USBD_ENABLE_USB();
|
||||
g_u8Suspend = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (u32IntSts & USBD_INTSTS_USB) {
|
||||
// USB event
|
||||
if (u32IntSts & USBD_INTSTS_SETUP) { // Setup packet
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP);
|
||||
|
||||
// Clear the data IN/OUT ready flag of control end-points
|
||||
USBD_STOP_TRANSACTION(EP_CTRL_IN);
|
||||
USBD_STOP_TRANSACTION(EP_CTRL_OUT);
|
||||
|
||||
Tas_USBD_ProcessSetupPacket();
|
||||
}
|
||||
|
||||
// Control endpoints
|
||||
if (u32IntSts & USBD_INTSTS_CTRL_IN) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_CTRL_IN);
|
||||
Tas_USBD_CtrlIn();
|
||||
}
|
||||
if (u32IntSts & USBD_INTSTS_CTRL_OUT) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_CTRL_OUT);
|
||||
Tas_USBD_CtrlOut();
|
||||
}
|
||||
|
||||
// CDC endpoints
|
||||
if (u32IntSts & USBD_INTSTS_CDC_IN) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_CDC_IN);
|
||||
EP_CDC_IN_Handler();
|
||||
}
|
||||
if (u32IntSts & USBD_INTSTS_CDC_OUT) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_CDC_OUT);
|
||||
EP_CDC_OUT_Handler();
|
||||
}
|
||||
if (u32IntSts & USBD_INTSTS_CDC_CMD) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_CDC_CMD);
|
||||
// TODO: ACM packets have connect/disconnect?
|
||||
}
|
||||
|
||||
// IO4 HID endpoints
|
||||
if (u32IntSts & USBD_INTSTS_HID_IO4_IN) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_HID_IO4_IN);
|
||||
EP_HID_IO4_IN_Handler();
|
||||
}
|
||||
|
||||
// IO4 Misc endpoints
|
||||
if (u32IntSts & USBD_INTSTS_HID_MISC_IN) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_HID_MISC_IN);
|
||||
EP_HID_MISC_IN_Handler();
|
||||
}
|
||||
if (u32IntSts & USBD_INTSTS_HID_MISC_OUT) {
|
||||
USBD_CLR_INT_FLAG(USBD_INTSTS_HID_MISC_OUT);
|
||||
EP_HID_MISC_OUT_Handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EP_HID_IO4_IN_Handler(void) { gu8HIDIO4Ready = 1; }
|
||||
void EP_HID_MISC_IN_Handler(void) { gu8HIDMiscReady = 1; }
|
||||
void EP_HID_MISC_OUT_Handler(void) {
|
||||
// TODO: Handle anything we need to here
|
||||
}
|
||||
void EP_CDC_OUT_Handler(void) {
|
||||
// Bulk OUT
|
||||
if (g_u32OutToggle == (USBD->EPSTS & USBD_EPSTS_EPSTS3_Msk)) {
|
||||
USBD_SET_PAYLOAD_LEN(EP_CDC_OUT, USBD_CDC_OUT_MAX_SIZE);
|
||||
} else {
|
||||
gu32RxSize = USBD_GET_PAYLOAD_LEN(EP_CDC_OUT);
|
||||
gpu8RxBuf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CDC_OUT));
|
||||
|
||||
g_u32OutToggle = USBD->EPSTS & USBD_EPSTS_EPSTS3_Msk;
|
||||
// Set a flag to indicate bulk out ready
|
||||
gi8BulkOutReady = 1;
|
||||
}
|
||||
}
|
||||
void EP_CDC_IN_Handler(void) { gu32TxSize = 0; }
|
||||
|
||||
void Tas_USBD_ClassRequest(void) {
|
||||
usb_setup_t setup;
|
||||
Tas_USBD_GetSetupPacket(&setup);
|
||||
|
||||
if (setup.bmRequestType & 0x80) {
|
||||
// Device to host
|
||||
switch (setup.bRequest) {
|
||||
case GET_LINE_CODING:
|
||||
if (setup.getLineCoding.wInterface == USBD_ITF_CDC_CMD)
|
||||
USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_IN)),
|
||||
(uint8_t *)&gLineCoding, setup.getLineCoding.wLength);
|
||||
|
||||
// Data stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, setup.getLineCoding.wLength);
|
||||
// Status stage
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
case GET_REPORT: {
|
||||
uint32_t u32Size = 0;
|
||||
uint8_t *pu8Data = NULL;
|
||||
pu8Data = USBD_HID_GetReport(setup.hidGetReport.bReportId, &u32Size);
|
||||
|
||||
Tas_USBD_PrepareCtrlIn(pu8Data, u32Size);
|
||||
// Status stage
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
case GET_IDLE:
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_OUT, setup.hidGetIdle.wLength);
|
||||
// Data stage
|
||||
Tas_USBD_PrepareCtrlIn(&g_u8Idle, setup.hidGetIdle.wLength);
|
||||
// Status stage
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
case GET_PROTOCOL:
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_OUT, setup.hidGetProtocol.wLength);
|
||||
// Data stage
|
||||
Tas_USBD_PrepareCtrlIn(&g_u8Protocol, setup.hidGetProtocol.wLength);
|
||||
// Status stage
|
||||
Tas_USBD_PrepareCtrlOut(NULL, 0, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Setup error, stall the device
|
||||
USBD_SetStall(EP_CTRL_IN);
|
||||
USBD_SetStall(EP_CTRL_OUT);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Host to device
|
||||
switch (setup.bRequest) {
|
||||
case SET_CONTROL_LINE_STATE:
|
||||
// TODO: Use bit[0] (DTR) to identify connection state
|
||||
// Is RTS worth using?
|
||||
if (setup.wIndex == USBD_ITF_CDC_CMD) gCtrlSignal = setup.wValue;
|
||||
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_LINE_CODING:
|
||||
if (setup.setLineCoding.wInterface == USBD_ITF_CDC_CMD)
|
||||
Tas_USBD_PrepareCtrlOut(&gLineCoding, sizeof gLineCoding, NULL);
|
||||
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_REPORT:
|
||||
// Report Type = Output
|
||||
if (setup.hidSetReport.bReportType == 2) {
|
||||
Tas_USBD_PrepareCtrlOut(&gHidSetReport, sizeof gHidSetReport,
|
||||
USBD_HID_SetReport);
|
||||
|
||||
// USBD_SET_DATA1(EP_CTRL_OUT);
|
||||
// USBD_SET_PAYLOAD_LEN(EP_CTRL_OUT, setup.wLength);
|
||||
|
||||
// USBD_HID_RecvData(
|
||||
// setup.hidSetReport.bReportId,
|
||||
// (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CTRL_OUT)),
|
||||
// setup.hidSetReport.wLength);
|
||||
|
||||
// // Status stage
|
||||
// Tas_USBD_PrepareCtrlIn(NULL, 0);
|
||||
}
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_IDLE:
|
||||
g_u8Idle = setup.hidSetIdle.bDuration;
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
case SET_PROTOCOL:
|
||||
g_u8Protocol = setup.hidSetProtocol.wProtocol;
|
||||
// Status stage
|
||||
USBD_SET_DATA1(EP_CTRL_IN);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CTRL_IN, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Setup error, stall the device
|
||||
USBD_SetStall(EP_CTRL_IN);
|
||||
USBD_SetStall(EP_CTRL_OUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
102
src/vcom.c
Normal file
102
src/vcom.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include "tasoller.h"
|
||||
|
||||
#define BUF_SIZE_RX 512
|
||||
#define BUF_SIZE_TX 512
|
||||
|
||||
volatile uint8_t gu8VcomReady = 0;
|
||||
|
||||
static volatile uint8_t gau8ComRbuf[BUF_SIZE_RX];
|
||||
static volatile uint16_t gu16ComRbytes = 0;
|
||||
static volatile uint16_t gu16ComRhead = 0;
|
||||
static volatile uint16_t gu16ComRtail = 0;
|
||||
|
||||
static volatile uint8_t gau8ComTbuf[BUF_SIZE_TX];
|
||||
static volatile uint16_t gu16ComTbytes = 0;
|
||||
static volatile uint16_t gu16ComThead = 0;
|
||||
static volatile uint16_t gu16ComTtail = 0;
|
||||
|
||||
uint8_t gau8RxBuf[64] = { 0 };
|
||||
volatile uint8_t *gpu8RxBuf = 0;
|
||||
volatile uint32_t gu32RxSize = 0;
|
||||
volatile uint32_t gu32TxSize = 0;
|
||||
|
||||
volatile int8_t gi8BulkOutReady = 0;
|
||||
|
||||
void _USB_VCOM_Tick_Tx(void) {
|
||||
uint32_t u32Len;
|
||||
if (gu32TxSize != 0) return;
|
||||
|
||||
// Check wether we have new COM Rx data to send to USB or not
|
||||
if (!gu16ComRbytes) {
|
||||
// Prepare a zero packet if previous packet size is USBD_CDC_IN_MAX_SIZE and
|
||||
// no more data to send at this moment to note Host the transfer has been done
|
||||
u32Len = USBD_GET_PAYLOAD_LEN(EP_CDC_IN);
|
||||
if (u32Len == USBD_CDC_IN_MAX_SIZE) USBD_SET_PAYLOAD_LEN(EP_CDC_IN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
u32Len = gu16ComRbytes;
|
||||
if (u32Len > USBD_CDC_IN_MAX_SIZE) u32Len = USBD_CDC_IN_MAX_SIZE;
|
||||
|
||||
for (uint32_t i = 0; i < u32Len; i++) {
|
||||
if (gu16ComRhead >= BUF_SIZE_RX) gu16ComRhead = 0;
|
||||
gau8RxBuf[i] = gau8ComRbuf[gu16ComRhead++];
|
||||
}
|
||||
|
||||
// __set_PRIMASK(1);
|
||||
gu16ComRbytes -= u32Len;
|
||||
// __set_PRIMASK(0);
|
||||
|
||||
gu32TxSize = u32Len;
|
||||
USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP_CDC_IN)), (uint8_t *)gau8RxBuf,
|
||||
u32Len);
|
||||
USBD_SET_PAYLOAD_LEN(EP_CDC_IN, u32Len);
|
||||
}
|
||||
void _USB_VCOM_Tick_Rx(void) {
|
||||
// Process the Bulk out data when bulk out data is ready.
|
||||
if (!gi8BulkOutReady) return;
|
||||
if (gu32RxSize > BUF_SIZE_TX - gu16ComTbytes) return;
|
||||
|
||||
for (uint32_t i = 0; i < gu32RxSize; i++) {
|
||||
gau8ComTbuf[gu16ComTtail++] = gpu8RxBuf[i];
|
||||
if (gu16ComTtail >= BUF_SIZE_TX) gu16ComTtail = 0;
|
||||
}
|
||||
|
||||
// __set_PRIMASK(1);
|
||||
gu16ComTbytes += gu32RxSize;
|
||||
// __set_PRIMASK(0);
|
||||
|
||||
gu32RxSize = 0;
|
||||
gi8BulkOutReady = 0; // Clear bulk out ready flag
|
||||
|
||||
// Ready to get next BULK out
|
||||
USBD_SET_PAYLOAD_LEN(EP_CDC_OUT, USBD_CDC_OUT_MAX_SIZE);
|
||||
}
|
||||
void USB_VCOM_Tick(void) {
|
||||
_USB_VCOM_Tick_Tx();
|
||||
_USB_VCOM_Tick_Rx();
|
||||
}
|
||||
|
||||
uint8_t USB_VCOM_Read() {
|
||||
if (!gu16ComTbytes) return 0xff;
|
||||
gu16ComTbytes--;
|
||||
if (gu16ComThead >= BUF_SIZE_TX) gu16ComThead = 0;
|
||||
return gau8ComTbuf[gu16ComThead++];
|
||||
}
|
||||
void USB_VCOM_Write(uint8_t u8Data) {
|
||||
if (gu16ComRbytes < BUF_SIZE_RX) {
|
||||
// Enqueue the character
|
||||
gau8ComRbuf[gu16ComRtail++] = u8Data;
|
||||
if (gu16ComRtail >= BUF_SIZE_RX) gu16ComRtail = 0;
|
||||
gu16ComRbytes++;
|
||||
} else {
|
||||
// FIFO over run
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t USB_VCOM_Available(void) { return gu16ComTbytes; }
|
||||
void USB_VCOM_PurgeTx(void) {
|
||||
gu16ComRbytes = 0;
|
||||
gu16ComRhead = 0;
|
||||
gu16ComRtail = 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user