├── make ├── .gitignore └── Makefile ├── doc ├── frontend.jpg ├── prog_cable.jpg ├── prog_conn.jpg ├── prog_usb_conn.jpg ├── prog_conn_pinout.jpg ├── Programming.md └── Hardware.md ├── include ├── cmsis_version.h ├── cmsis_compiler.h └── mpu_armv7.h ├── flash.h ├── scope.h ├── battery.h ├── buffer.h ├── timer.h ├── trigger.h ├── fonts.h ├── linker └── gd32f407ve.ld ├── images.h ├── buttons.h ├── capture.h ├── lcd.h ├── config.h ├── common.h ├── flash.c ├── utils.h ├── timer.c ├── buttons.c ├── hal_gpio.h ├── utils.c ├── README.md ├── battery.c ├── main.c ├── images.c ├── config.c ├── lcd.c ├── startup_gd32f4.c ├── buffer.c └── fonts.c /make/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /doc/frontend.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ataradov/open-5012h/HEAD/doc/frontend.jpg -------------------------------------------------------------------------------- /doc/prog_cable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ataradov/open-5012h/HEAD/doc/prog_cable.jpg -------------------------------------------------------------------------------- /doc/prog_conn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ataradov/open-5012h/HEAD/doc/prog_conn.jpg -------------------------------------------------------------------------------- /doc/prog_usb_conn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ataradov/open-5012h/HEAD/doc/prog_usb_conn.jpg -------------------------------------------------------------------------------- /doc/prog_conn_pinout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ataradov/open-5012h/HEAD/doc/prog_conn_pinout.jpg -------------------------------------------------------------------------------- /include/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.4 5 | * @date 23. July 2019 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2019 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /flash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _FLASH_H_ 30 | #define _FLASH_H_ 31 | 32 | /*- Prototypes --------------------------------------------------------------*/ 33 | void flash_init(void); 34 | 35 | #endif // _FLASH_H_ 36 | 37 | -------------------------------------------------------------------------------- /scope.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _SCOPE_H_ 30 | #define _SCOPE_H_ 31 | 32 | /*- Prototypes --------------------------------------------------------------*/ 33 | void scope_init(bool calibration_mode); 34 | void scope_buttons_handler(int buttons); 35 | void scope_task(void); 36 | 37 | #endif // _SCOPE_H_ 38 | 39 | -------------------------------------------------------------------------------- /battery.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _BATTERY_H_ 30 | #define _BATTERY_H_ 31 | 32 | /*- Prototypes --------------------------------------------------------------*/ 33 | void battery_init(void); 34 | int battery_voltage(void); 35 | void battery_task(void); 36 | 37 | void battery_low_handler(void); 38 | 39 | #endif // _BATTERY_H_ 40 | 41 | 42 | -------------------------------------------------------------------------------- /buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _BUFFER_H_ 30 | #define _BUFFER_H_ 31 | 32 | /*- Prototypes --------------------------------------------------------------*/ 33 | void buffer_decimate(uint32_t dst, uint32_t src, uint32_t count, uint32_t offset); 34 | void buffer_decimate_reverse(uint32_t dst, uint32_t src, uint32_t count, uint32_t offset); 35 | void buffer_reverse(uint32_t buf, uint32_t count); 36 | 37 | #endif // _BUFFER_H_ 38 | 39 | -------------------------------------------------------------------------------- /timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _TIMER_H_ 30 | #define _TIMER_H_ 31 | 32 | /*- Definitions -------------------------------------------------------------*/ 33 | #define TIMER_DISABLE -1 34 | 35 | /*- Prototypes --------------------------------------------------------------*/ 36 | void timer_init(void); 37 | void timer_add(int *timer); 38 | void timer_remove(int *timer); 39 | int timer_get_max_delta(void); 40 | void timer_task(void); 41 | 42 | #endif // _TIMER_H_ 43 | 44 | -------------------------------------------------------------------------------- /trigger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _TRIGGER_H_ 30 | #define _TRIGGER_H_ 31 | 32 | /*- Prototypes --------------------------------------------------------------*/ 33 | void trigger_set_levels(int level); 34 | int trigger_find_rise_single(uint32_t buf, uint32_t count); 35 | int trigger_find_fall_single(uint32_t buf, uint32_t count); 36 | int trigger_find_both_single(uint32_t buf, uint32_t count); 37 | int trigger_find_rise_dual(uint32_t buf, uint32_t count); 38 | int trigger_find_fall_dual(uint32_t buf, uint32_t count); 39 | int trigger_find_both_dual(uint32_t buf, uint32_t count); 40 | 41 | #endif // _TRIGGER_H_ 42 | 43 | 44 | -------------------------------------------------------------------------------- /make/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | BUILD = build 3 | BIN = open-5012h 4 | 5 | ############################################################################## 6 | .PHONY: all directory clean size 7 | 8 | CC = arm-none-eabi-gcc 9 | OBJCOPY = arm-none-eabi-objcopy 10 | SIZE = arm-none-eabi-size 11 | 12 | ifeq ($(OS), Windows_NT) 13 | MKDIR = gmkdir 14 | else 15 | MKDIR = mkdir 16 | endif 17 | 18 | CFLAGS += -W -Wall --std=gnu11 -O3 19 | CFLAGS += -fno-diagnostics-show-caret 20 | CFLAGS += -fdata-sections -ffunction-sections 21 | CFLAGS += -funsigned-char -funsigned-bitfields 22 | CFLAGS += -mcpu=cortex-m4 -mthumb 23 | CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 24 | CFLAGS += -MD -MP -MT $(BUILD)/$(*F).o -MF $(BUILD)/$(@F).d 25 | #CFLAGS += -save-temps 26 | 27 | LDFLAGS += -mcpu=cortex-m4 -mthumb 28 | LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 29 | LDFLAGS += -Wl,--gc-sections 30 | LDFLAGS += -Wl,--script=../linker/gd32f407ve.ld 31 | 32 | INCLUDES += \ 33 | -I../include \ 34 | -I.. \ 35 | 36 | SRCS += \ 37 | ../main.c \ 38 | ../lcd.c \ 39 | ../flash.c \ 40 | ../timer.c \ 41 | ../config.c \ 42 | ../buttons.c \ 43 | ../battery.c \ 44 | ../capture.c \ 45 | ../trigger.c \ 46 | ../buffer.c \ 47 | ../scope.c \ 48 | ../utils.c \ 49 | ../fonts.c \ 50 | ../images.c \ 51 | ../startup_gd32f4.c \ 52 | 53 | DEFINES += \ 54 | -D__GD32F407VE__ \ 55 | -DF_CPU=250000000 \ 56 | 57 | CFLAGS += $(INCLUDES) $(DEFINES) 58 | 59 | OBJS = $(addprefix $(BUILD)/, $(notdir %/$(subst .c,.o, $(SRCS)))) 60 | 61 | all: directory $(BUILD)/$(BIN).elf $(BUILD)/$(BIN).hex $(BUILD)/$(BIN).bin size 62 | 63 | $(BUILD)/$(BIN).elf: $(OBJS) 64 | @echo LD $@ 65 | @$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ 66 | 67 | $(BUILD)/$(BIN).hex: $(BUILD)/$(BIN).elf 68 | @echo OBJCOPY $@ 69 | @$(OBJCOPY) -O ihex $^ $@ 70 | 71 | $(BUILD)/$(BIN).bin: $(BUILD)/$(BIN).elf 72 | @echo OBJCOPY $@ 73 | @$(OBJCOPY) -O binary $^ $@ 74 | 75 | %.o: 76 | @echo CC $@ 77 | @$(CC) $(CFLAGS) $(filter %/$(subst .o,.c,$(notdir $@)), $(SRCS)) -c -o $@ 78 | 79 | directory: 80 | @$(MKDIR) -p $(BUILD) 81 | 82 | size: $(BUILD)/$(BIN).elf 83 | @echo size: 84 | @$(SIZE) -t $^ 85 | 86 | clean: 87 | @echo clean 88 | @-rm -rf $(BUILD) 89 | 90 | prog: 91 | @edbg -b -c 3000 -t gd32f4xx -pv -f $(BUILD)/$(BIN).bin 92 | 93 | -include $(wildcard $(BUILD)/*.d) 94 | 95 | -------------------------------------------------------------------------------- /fonts.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _FONTS_H_ 30 | #define _FONTS_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | 35 | /*- Definitions -------------------------------------------------------------*/ 36 | #define FONT_FIRST_CHAR ' ' 37 | #define FONT_LAST_CHAR '~' 38 | #define FONT_HALF_SPACE '\x01' 39 | 40 | #define FONT_SMALL &font_6x8 41 | #define FONT_LARGE &terminus_8x16 42 | 43 | /*- Types -------------------------------------------------------------------*/ 44 | typedef struct 45 | { 46 | int width; 47 | int height; 48 | int pitch; 49 | uint8_t data[]; 50 | } Font; 51 | 52 | /*- Constants ---------------------------------------------------------------*/ 53 | extern const Font font_6x8; 54 | extern const Font terminus_8x16; 55 | 56 | #endif // _FONTS_H_ 57 | 58 | -------------------------------------------------------------------------------- /linker/gd32f407ve.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | MEMORY 30 | { 31 | flash (rx) : ORIGIN = 0x08000000, LENGTH = 512K 32 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 33 | tcm (rwx) : ORIGIN = 0x10000000, LENGTH = 64K 34 | } 35 | 36 | __top_flash = ORIGIN(flash) + LENGTH(flash); 37 | __top_tcm = ORIGIN(tcm) + LENGTH(tcm); 38 | 39 | ENTRY(irq_handler_reset) 40 | 41 | SECTIONS 42 | { 43 | .text : ALIGN(4) 44 | { 45 | FILL(0xff) 46 | KEEP(*(.vectors)) 47 | *(.text*) 48 | *(.rodata) 49 | *(.rodata.*) 50 | . = ALIGN(4); 51 | } > flash 52 | 53 | . = ALIGN(4); 54 | _etext = .; 55 | 56 | .uninit_RESERVED : ALIGN(4) 57 | { 58 | KEEP(*(.bss.$RESERVED*)) 59 | } > tcm 60 | 61 | .data : ALIGN(4) 62 | { 63 | FILL(0xff) 64 | _data = .; 65 | *(vtable) 66 | *(.data*) 67 | . = ALIGN(4); 68 | _edata = .; 69 | } > tcm AT > flash 70 | 71 | .bss : ALIGN(4) 72 | { 73 | _bss = .; 74 | *(.bss*) 75 | *(COMMON) 76 | . = ALIGN(4); 77 | _ebss = .; 78 | PROVIDE(_end = .); 79 | } > tcm 80 | 81 | PROVIDE(_stack_top = __top_tcm); 82 | } 83 | 84 | -------------------------------------------------------------------------------- /images.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _IMAGES_H_ 30 | #define _IMAGES_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | #include 35 | 36 | /*- Types -------------------------------------------------------------------*/ 37 | typedef struct 38 | { 39 | int width; 40 | int height; 41 | int ox; 42 | int oy; 43 | uint16_t data[]; 44 | } Image; 45 | 46 | /*- Comstants ---------------------------------------------------------------*/ 47 | extern const Image image_ac; 48 | extern const Image image_dc; 49 | 50 | extern const Image image_trigger_edge_rise; 51 | extern const Image image_trigger_edge_fall; 52 | extern const Image image_trigger_edge_both; 53 | 54 | extern const Image image_trigger_level; 55 | extern const Image image_trigger_offset; 56 | extern const Image image_trigger_offset_left; 57 | extern const Image image_trigger_offset_right; 58 | extern const Image image_trigger_mv; 59 | 60 | extern const Image image_reference_level; 61 | extern const Image image_reference_level_up; 62 | extern const Image image_reference_level_down; 63 | 64 | #endif // _IMAGES_H_ 65 | 66 | -------------------------------------------------------------------------------- /buttons.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _BUTTONS_H_ 30 | #define _BUTTONS_H_ 31 | 32 | /*- Definitions -------------------------------------------------------------*/ 33 | enum 34 | { 35 | BTN_STOP = (1 << 0), 36 | BTN_UP = (1 << 1), 37 | BTN_EDGE = (1 << 2), 38 | BTN_MODE = (1 << 3), 39 | BTN_F1 = (1 << 4), 40 | BTN_RIGHT = (1 << 5), 41 | BTN_AC_DC = (1 << 6), 42 | BTN_AUTO = (1 << 7), 43 | 44 | BTN_50P = (1 << 8), 45 | BTN_MENU = (1 << 9), 46 | BTN_TRIG_UP = (1 << 10), 47 | BTN_LEFT = (1 << 11), 48 | BTN_TRIG_DOWN = (1 << 12), 49 | BTN_SAVE = (1 << 13), 50 | BTN_TRIG = (1 << 14), 51 | BTN_DOWN = (1 << 15), 52 | 53 | BTN_F2 = (1 << 16), 54 | BTN_1X_10X = (1 << 17), 55 | BTN_SHIFT = (1 << 17), 56 | 57 | BTN_REPEAT = (1 << 18), 58 | }; 59 | 60 | /*- Prototypes --------------------------------------------------------------*/ 61 | void buttons_init(void); 62 | int buttons_read(void); 63 | int buttons_state(void); 64 | void buttons_task(void); 65 | 66 | void buttons_handler(int buttons); 67 | 68 | #endif // _BUTTONS_H_ 69 | 70 | 71 | -------------------------------------------------------------------------------- /doc/Programming.md: -------------------------------------------------------------------------------- 1 | # Programming 2 | 3 | ## Electrical Connections 4 | 5 | USB connector of the FNIRSI-5012H has standard ARM SWD programming pins exposed on 6 | the data lines. The pinout of the connector is shown below. 7 | 8 | ![FNIRSI-5012H USB Connector Pinout](prog_usb_conn.jpg) 9 | 10 | I used a Micro-USB connector like this: 11 | 12 | ![Micro-USB Connector](prog_conn.jpg) 13 | 14 | Search eBay for "Micro USB 5 Pins Male Connector Port Solder Plug" to get a lot 15 | of offers. They all are essentially the same, pick whichever is cheaper. 16 | 17 | You can also use a cut off Micro-USB cable. But keep in mind that USB connector 18 | on the FNIRSI-5012H is recessed, so normal USB cables may not fully insert. 19 | In this case you can remove some of the plastic of the casing. 20 | 21 | The connector mentioned above is long enough and does not need any modifications. 22 | Pinout of this connector is as follows: 23 | 24 | ![USB Connector Pinout](prog_conn_pinout.jpg) 25 | 26 | Here are some pictures of the cable I'm using: 27 | 28 | ![Programming Cable](prog_cable.jpg) 29 | 30 | Keep the cable length from the USB connector to the debugger short. 31 | Ideally it should be under 5". Don't use the full length of the USB cable 32 | if you go that route. 33 | 34 | ## Entering Programming Mode 35 | 36 | Without a reset connection, SWD interface on this device is a bit temperamental, 37 | especially is ADC is running. To overcome this, there is a programming 38 | mode, which makes sure that device does not initialize any of the fast running 39 | clocks. 40 | 41 | To enter the programming mode, hold F2 button while powering on the device. 42 | Display will remain dark and device will not show that it is powered in any way. 43 | This is normal and expected. 44 | 45 | Current version of the firmware will also stop the clocks if you press F2 while 46 | device is running. This is done for easy programming while debugging and 47 | because F2 is not used at this time. 48 | You can disable this behaviour in the buttons_handler() function in the main.c file. 49 | 50 | ## Programmer Hardware 51 | 52 | You will need any SWD-capable programmer. I sell one [here](https://www.tindie.com/products/ataradov/cmsis-dap-compliant-swd-debugger/), 53 | but there are many options out there, pick one that works for you. 54 | 55 | It is important to keep in mind that programmers supporting multiple target 56 | voltages often use level shifters powered by the reference voltage provided 57 | by the target board. In this case there is no reference voltage, so you 58 | would need to provide that voltage (+3.3V) externally. 59 | 60 | ## Programmer Software 61 | 62 | Use whatever software works with your programmer and supports GD32F407VET6. 63 | 64 | Open-OCD will probably work, so will [edbg](https://github.com/ataradov/edbg) 65 | if you are using CMSIS-DAP-compliant programmer. 66 | 67 | 68 | -------------------------------------------------------------------------------- /capture.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _CAPTURE_H_ 30 | #define _CAPTURE_H_ 31 | 32 | /*- Definitions -------------------------------------------------------------*/ 33 | #define BASE_SAMPLE_RATE 125e6 34 | #define BASE_SAMPLE_PERIOD (1e9 / BASE_SAMPLE_RATE) 35 | #define CAPTURE_BUFFER_SIZE (128 * 1024) 36 | #define TRIGGER_MARGIN_SAMPLES 1024 37 | #define DATA_BUFFER_SIZE 300 38 | 39 | /*- Types -------------------------------------------------------------------*/ 40 | typedef struct 41 | { 42 | int size; 43 | int min_value; 44 | int max_value; 45 | int vertical_position; 46 | int frequency; 47 | int min[DATA_BUFFER_SIZE]; 48 | int max[DATA_BUFFER_SIZE]; 49 | uint8_t flags[DATA_BUFFER_SIZE]; 50 | } DataBuffer; 51 | 52 | /*- Prototypes --------------------------------------------------------------*/ 53 | void capture_init(void); 54 | void capture_disable_clock(void); 55 | void capture_start(void); 56 | void capture_stop(void); 57 | void capture_set_vertical_parameters(void); 58 | void capture_set_horizontal_parameters(int sr_divider, int trigger_offset); 59 | void capture_set_trigger_level(int level); 60 | void capture_set_trigger_edge(int edge); 61 | void capture_set_trigger_mode(int mode); 62 | int capture_get_state(void); 63 | bool capture_buffer_updated(void); 64 | void capture_get_data(DataBuffer *db); 65 | void capture_get_raw_data(int *raw, int size); 66 | 67 | #endif // _CAPTURE_H_ 68 | 69 | 70 | -------------------------------------------------------------------------------- /lcd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _LCD_H_ 30 | #define _LCD_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | #include 35 | #include "fonts.h" 36 | #include "images.h" 37 | 38 | /*- Definitions -------------------------------------------------------------*/ 39 | #define LCD_WIDTH 320 40 | #define LCD_HEIGHT 240 41 | 42 | #define LCD_COLOR(r, g, b) \ 43 | ((((r) << 8) & 0xf800) | (((g) << 3) & 0x07e0) | (((b) >> 3) & 0x001f)) 44 | 45 | #define LCD_BLACK_COLOR LCD_COLOR(0, 0, 0) 46 | #define LCD_WHITE_COLOR LCD_COLOR(255, 255, 255) 47 | #define LCD_RED_COLOR LCD_COLOR(255, 0, 0) 48 | #define LCD_GREEN_COLOR LCD_COLOR(0, 255, 0) 49 | #define LCD_BLUE_COLOR LCD_COLOR(0, 0, 255) 50 | 51 | /*- Prototypes --------------------------------------------------------------*/ 52 | void lcd_init(void); 53 | void lcd_set_backlight_level(int level); 54 | void lcd_draw_pixel(int x, int y, int color); 55 | void lcd_draw_buf(int x, int y, int w, int h, const uint16_t *buf); 56 | void lcd_draw_image(int x, int y, const Image *image); 57 | void lcd_draw_rect(int x, int y, int w, int h, int color); 58 | void lcd_fill_rect(int x, int y, int w, int h, int color); 59 | void lcd_hline(int x0, int x1, int y, int color); 60 | void lcd_vline(int x, int y0, int y1, int color); 61 | void lcd_set_font(const Font *font); 62 | void lcd_set_color(int bg, int fg); 63 | void lcd_putc(int x, int y, char ch); 64 | void lcd_puts(int x, int y, const char *str); 65 | 66 | #endif // _LCD_H_ 67 | 68 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _CONFIG_H_ 30 | #define _CONFIG_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | #include 35 | #include "common.h" 36 | 37 | /*- Definitions -------------------------------------------------------------*/ 38 | #define CALIB_MULTIPLIER 1024 39 | 40 | /*- Types -------------------------------------------------------------------*/ 41 | typedef struct 42 | { 43 | uint32_t magic; 44 | int size; 45 | int version; 46 | int count; 47 | 48 | int power_cycles; 49 | int charge_cycles; 50 | 51 | int lcd_bl_level; 52 | 53 | bool ac_coupling; 54 | bool x10; 55 | 56 | int trigger_mode; 57 | int trigger_edge; 58 | int trigger_level; 59 | int trigger_level_mv; 60 | 61 | int horizontal_scale; 62 | int64_t horizontal_position; 63 | int horizontal_position_px; 64 | int horizontal_period; 65 | 66 | int vertical_scale; 67 | int vertical_position; 68 | int vertical_position_mv; 69 | int vertical_mult; 70 | 71 | int sample_rate_limit; 72 | 73 | bool measure_display; 74 | 75 | uint32_t padding[31]; 76 | 77 | int calib_channel_delta; 78 | int calib_dac_zero; 79 | int calib_dac_mult[VS_COUNT]; 80 | int calib_vs_mult[VS_COUNT]; 81 | 82 | uint32_t crc; 83 | } Config; 84 | 85 | /*- Variables ---------------------------------------------------------------*/ 86 | extern Config config; 87 | 88 | /*- Prototypes --------------------------------------------------------------*/ 89 | void config_init(void); 90 | void config_reset(void); 91 | void config_task(void); 92 | 93 | #endif // _CONFIG_H_ 94 | 95 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _COMMON_H_ 30 | #define _COMMON_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | #include 35 | 36 | /*- Definitions -------------------------------------------------------------*/ 37 | enum // Horizontal Scale 38 | { 39 | HS_50_ns, 40 | HS_100_ns, 41 | HS_200_ns, 42 | HS_500_ns, 43 | 44 | HS_1_us, 45 | HS_2_us, 46 | HS_5_us, 47 | HS_10_us, 48 | HS_20_us, 49 | HS_50_us, 50 | HS_100_us, 51 | HS_200_us, 52 | HS_500_us, 53 | 54 | HS_1_ms, 55 | HS_2_ms, 56 | HS_5_ms, 57 | HS_10_ms, 58 | HS_20_ms, 59 | HS_50_ms, 60 | HS_100_ms, 61 | HS_200_ms, 62 | HS_500_ms, 63 | 64 | HS_LAST = HS_500_ms, 65 | HS_COUNT, 66 | }; 67 | 68 | enum // Vertical Scale 69 | { 70 | VS_50_mV, 71 | VS_100_mV, 72 | VS_200_mV, 73 | VS_500_mV, 74 | VS_1_V, 75 | VS_2_V, 76 | VS_5_V, 77 | VS_10_V, 78 | 79 | VS_LAST = VS_10_V, 80 | VS_COUNT, 81 | }; 82 | 83 | enum 84 | { 85 | TRIGGER_EDGE_RISE, 86 | TRIGGER_EDGE_FALL, 87 | TRIGGER_EDGE_BOTH, 88 | }; 89 | 90 | enum 91 | { 92 | TRIGGER_MODE_AUTO, 93 | TRIGGER_MODE_NORMAL, 94 | TRIGGER_MODE_SINGLE, 95 | }; 96 | 97 | enum 98 | { 99 | CAPTURE_STATE_STOP, 100 | CAPTURE_STATE_WAIT, 101 | CAPTURE_STATE_TRIG, 102 | }; 103 | 104 | enum 105 | { 106 | SAMPLE_FLAG_NONE = 0, 107 | SAMPLE_FLAG_VALID = (1 << 0), 108 | SAMPLE_FLAG_FILLED = (1 << 1), 109 | SAMPLE_FLAG_CLIP_L = (1 << 2), 110 | SAMPLE_FLAG_CLIP_H = (1 << 3), 111 | }; 112 | 113 | /*- Prototypes -------------------------------------------------------------*/ 114 | void error(char *text); 115 | 116 | #endif // _COMMON_H_ 117 | 118 | 119 | -------------------------------------------------------------------------------- /flash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include "gd32f4xx.h" 33 | #include "hal_gpio.h" 34 | #include "common.h" 35 | #include "utils.h" 36 | #include "flash.h" 37 | 38 | /*- Definitions -------------------------------------------------------------*/ 39 | HAL_GPIO_PIN(CS, A, 3) 40 | HAL_GPIO_PIN(CLK, A, 5) 41 | HAL_GPIO_PIN(MISO, A, 6) 42 | HAL_GPIO_PIN(MOSI, A, 7) 43 | 44 | enum 45 | { 46 | CMD_READ_JEDEC_ID = 0x9f, 47 | }; 48 | 49 | /*- Implementations ---------------------------------------------------------*/ 50 | 51 | //----------------------------------------------------------------------------- 52 | static int spi_write(int value) 53 | { 54 | SPI0->DATA = value; 55 | while (0 == SPI0->STAT_b.RBNE); 56 | return SPI0->DATA; 57 | } 58 | 59 | //----------------------------------------------------------------------------- 60 | static bool flash_test(void) 61 | { 62 | int id0, id1, id2; 63 | 64 | HAL_GPIO_CS_clr(); 65 | spi_write(CMD_READ_JEDEC_ID); 66 | id0 = spi_write(0); 67 | id1 = spi_write(0); 68 | id2 = spi_write(0); 69 | HAL_GPIO_CS_set(); 70 | 71 | return (id0 == 0xef && id1 == 0x40 && id2 == 0x17); 72 | } 73 | 74 | //----------------------------------------------------------------------------- 75 | void flash_init(void) 76 | { 77 | HAL_GPIO_CS_out(); 78 | HAL_GPIO_CS_set(); 79 | HAL_GPIO_CLK_alt(5); 80 | HAL_GPIO_MISO_alt(5); 81 | HAL_GPIO_MOSI_alt(5); 82 | 83 | RCU->APB2EN_b.SPI0EN = 1; 84 | 85 | SPI0->CTL0 = SPI0_CTL0_SPIEN_Msk | SPI0_CTL0_MSTMOD_Msk | (1/*PCLK/4*/ << SPI0_CTL0_PSC_Pos) | 86 | SPI0_CTL0_CKPH_Msk | SPI0_CTL0_CKPL_Msk | SPI0_CTL0_SWNSSEN_Msk | SPI0_CTL0_SWNSS_Msk; 87 | 88 | delay_cycles(100); 89 | 90 | if (!flash_test()) 91 | error("Flash error"); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _UTILS_H_ 30 | #define _UTILS_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | #include 35 | 36 | /*- Definitions -------------------------------------------------------------*/ 37 | #define ARRAY_SIZE(x) ((int)(sizeof(x) / sizeof(0[x]))) 38 | 39 | /*- Prototypes --------------------------------------------------------------*/ 40 | void crc32_init(void); 41 | uint32_t crc32_calc(uint32_t *data, int size); 42 | char *format_time(int64_t value, bool show_plus_sign); 43 | char *format_voltage(int value, bool show_plus_sign); 44 | char *format_divisions(int value, bool show_plus_sign); 45 | char *format_frequency(int value); 46 | char *format_raw_data(int *data, int size); 47 | char *format_sps(int value); 48 | 49 | uint64_t round_divide(int64_t dividend, int64_t divisor); 50 | 51 | /*- Implementations ---------------------------------------------------------*/ 52 | 53 | //----------------------------------------------------------------------------- 54 | static inline void delay_ms(int ms) 55 | { 56 | uint32_t cycles = ms * F_CPU / 4 / 1000; 57 | 58 | asm volatile (R"asm( 59 | 1: subs %[cycles], %[cycles], #1 60 | nop 61 | bne 1b 62 | )asm" 63 | : [cycles] "+r"(cycles) 64 | ); 65 | } 66 | 67 | //----------------------------------------------------------------------------- 68 | static inline void delay_cycles(int cycles) 69 | { 70 | cycles /= 4; 71 | 72 | asm volatile (R"asm( 73 | 1: subs %[cycles], %[cycles], #1 74 | nop 75 | bne 1b 76 | )asm" 77 | : [cycles] "+r"(cycles) 78 | ); 79 | } 80 | 81 | //----------------------------------------------------------------------------- 82 | static inline int rbit8(int value) 83 | { 84 | return __RBIT(value) >> 24; 85 | } 86 | 87 | #endif // _UTILS_H_ 88 | 89 | -------------------------------------------------------------------------------- /timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include "gd32f4xx.h" 33 | #include "common.h" 34 | #include "timer.h" 35 | 36 | /*- Definitions -------------------------------------------------------------*/ 37 | #define MAX_TIMERS 16 38 | #define MS (F_CPU / 8 / 1000) 39 | 40 | /*- Variables ---------------------------------------------------------------*/ 41 | static int *g_timer_list[MAX_TIMERS]; 42 | static int g_timer_count = 0; 43 | static int g_timer_max_delta = 0; 44 | static int g_timer_prev_value = 0; 45 | 46 | /*- Implementations ---------------------------------------------------------*/ 47 | 48 | //----------------------------------------------------------------------------- 49 | static void timer_restart(void) 50 | { 51 | SysTick->CTRL = 0; 52 | SysTick->VAL = 0; 53 | SysTick->LOAD = 0xffffff; 54 | SysTick->CTRL = SysTick_CTRL_ENABLE_Msk; 55 | } 56 | 57 | //----------------------------------------------------------------------------- 58 | void timer_init(void) 59 | { 60 | g_timer_count = 0; 61 | g_timer_max_delta = 0; 62 | g_timer_prev_value = 0xffffff; 63 | timer_restart(); 64 | } 65 | 66 | //----------------------------------------------------------------------------- 67 | void timer_add(int *timer) 68 | { 69 | for (int i = 0; i < g_timer_count; i++) 70 | { 71 | if (g_timer_list[i] == timer) 72 | return; 73 | } 74 | 75 | if (g_timer_count == MAX_TIMERS) 76 | while (1); 77 | 78 | g_timer_list[g_timer_count++] = timer; 79 | } 80 | 81 | //----------------------------------------------------------------------------- 82 | void timer_remove(int *timer) 83 | { 84 | for (int i = 0; i < g_timer_count; i++) 85 | { 86 | if (g_timer_list[i] == timer) 87 | { 88 | g_timer_list[i] = g_timer_list[g_timer_count-1]; 89 | g_timer_count--; 90 | return; 91 | } 92 | } 93 | } 94 | 95 | //----------------------------------------------------------------------------- 96 | int timer_get_max_delta(void) 97 | { 98 | int res = g_timer_max_delta; 99 | g_timer_max_delta = 0; 100 | return res; 101 | } 102 | 103 | //----------------------------------------------------------------------------- 104 | void timer_task(void) 105 | { 106 | int value = SysTick->VAL; 107 | int delta = g_timer_prev_value - value; 108 | 109 | if (delta > MS) 110 | { 111 | int ms = delta / MS; 112 | int rem = delta % MS; 113 | 114 | for (int i = 0; i < g_timer_count; i++) 115 | { 116 | if (*g_timer_list[i] > ms) 117 | *g_timer_list[i] -= ms; 118 | else if (*g_timer_list[i] > 0) 119 | *g_timer_list[i] = 0; 120 | } 121 | 122 | g_timer_prev_value = value - rem; 123 | 124 | if (ms > g_timer_max_delta) 125 | g_timer_max_delta = ms; 126 | } 127 | 128 | if (value < 0x7fffff) 129 | { 130 | g_timer_prev_value += 0x7fffff; 131 | SysTick->LOAD = SysTick->VAL + 0x7fffff; 132 | SysTick->VAL = 0; 133 | } 134 | 135 | if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) 136 | error("Timer overflow"); 137 | } 138 | 139 | 140 | -------------------------------------------------------------------------------- /buttons.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include "gd32f4xx.h" 33 | #include "hal_gpio.h" 34 | #include "utils.h" 35 | #include "timer.h" 36 | #include "buttons.h" 37 | 38 | /* 39 | Button mapping: 40 | PE13 - PE0.A0 41 | PB14 - PE0.A1 42 | PB13 - PE0.A2 43 | PE14 - PE0.GS 44 | PE15 - PE1.A0 45 | PB12 - PE1.A1 46 | PB11 - PE1.A2 47 | PB10 - PE1.GS 48 | PE12 - BTN_1X10X 49 | PE11 - BTN_F2 50 | */ 51 | 52 | /*- Definitions -------------------------------------------------------------*/ 53 | #define DEBOUNCE_TIMEOUT 20 54 | #define REPEAT_DELAY 250 55 | #define REPEAT_INTERVAL_MAX 50 56 | #define REPEAT_INTERVAL_MIN 10 57 | 58 | /*- Variables ---------------------------------------------------------------*/ 59 | static int g_next_state = 0; 60 | static int g_buttons_state = 0; 61 | static int g_debounce_timer = TIMER_DISABLE; 62 | static int g_repeat_timer = TIMER_DISABLE; 63 | static int g_repeat_interval = 0; 64 | 65 | /*- Implementations ---------------------------------------------------------*/ 66 | 67 | //----------------------------------------------------------------------------- 68 | int buttons_read(void) 69 | { 70 | int pb = ~GPIOB->ISTAT; 71 | int pe = ~GPIOE->ISTAT; 72 | int state = 0; 73 | 74 | if (pe & (1 << 11)) 75 | state |= BTN_F2; 76 | 77 | if (pe & (1 << 12)) 78 | state |= BTN_1X_10X; 79 | 80 | if (pe & (1 << 14)) 81 | { 82 | int idx = ((pb >> 13) & 0x3) | ((pe >> 11) & 0x4); 83 | state |= (1 << idx); 84 | } 85 | 86 | if (pb & (1 << 10)) 87 | { 88 | int idx = ((pb >> 11) & 0x3) | ((pe >> 13) & 0x4); 89 | state |= (0x100 << idx); 90 | } 91 | 92 | return state; 93 | } 94 | 95 | //----------------------------------------------------------------------------- 96 | void buttons_init(void) 97 | { 98 | g_next_state = buttons_read(); 99 | g_buttons_state = g_next_state; 100 | 101 | timer_add(&g_debounce_timer); 102 | timer_add(&g_repeat_timer); 103 | } 104 | 105 | //----------------------------------------------------------------------------- 106 | int buttons_state(void) 107 | { 108 | return g_buttons_state; 109 | } 110 | 111 | //----------------------------------------------------------------------------- 112 | void buttons_task(void) 113 | { 114 | int state = buttons_read(); 115 | 116 | if (state != g_next_state) 117 | { 118 | g_next_state = state; 119 | g_debounce_timer = DEBOUNCE_TIMEOUT; 120 | } 121 | 122 | if (0 == g_repeat_timer && g_buttons_state) 123 | { 124 | g_repeat_timer = g_repeat_interval; 125 | 126 | if (g_repeat_interval > REPEAT_INTERVAL_MIN) 127 | g_repeat_interval--; 128 | 129 | buttons_handler(g_buttons_state | BTN_REPEAT); 130 | } 131 | 132 | if (0 == g_debounce_timer && g_next_state != g_buttons_state) 133 | { 134 | g_repeat_timer = g_next_state ? REPEAT_DELAY : TIMER_DISABLE; 135 | g_repeat_interval = REPEAT_INTERVAL_MAX; 136 | g_debounce_timer = TIMER_DISABLE; 137 | g_buttons_state = g_next_state; 138 | buttons_handler(g_buttons_state); 139 | } 140 | } 141 | 142 | -------------------------------------------------------------------------------- /hal_gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _HAL_GPIO_H_ 30 | #define _HAL_GPIO_H_ 31 | 32 | /*- Definitions -------------------------------------------------------------*/ 33 | #define HAL_GPIO_PIN(name, port, pin) \ 34 | static inline void HAL_GPIO_##name##_set(void) \ 35 | { \ 36 | GPIO##port->BOP = (1 << pin); \ 37 | (void)HAL_GPIO_##name##_set; \ 38 | } \ 39 | \ 40 | static inline void HAL_GPIO_##name##_clr(void) \ 41 | { \ 42 | GPIO##port->BC = (1 << pin); \ 43 | (void)HAL_GPIO_##name##_clr; \ 44 | } \ 45 | \ 46 | static inline void HAL_GPIO_##name##_toggle(void) \ 47 | { \ 48 | GPIO##port->TG = (1 << pin); \ 49 | (void)HAL_GPIO_##name##_toggle; \ 50 | } \ 51 | \ 52 | static inline void HAL_GPIO_##name##_write(int value) \ 53 | { \ 54 | if (value) \ 55 | GPIO##port->BOP = (1 << pin); \ 56 | else \ 57 | GPIO##port->BC = (1 << pin); \ 58 | (void)HAL_GPIO_##name##_write; \ 59 | } \ 60 | \ 61 | static inline void HAL_GPIO_##name##_in(void) \ 62 | { \ 63 | GPIO##port->CTL_b.CTL##pin = 0; \ 64 | (void)HAL_GPIO_##name##_in; \ 65 | } \ 66 | \ 67 | static inline void HAL_GPIO_##name##_out(void) \ 68 | { \ 69 | GPIO##port->CTL_b.CTL##pin = 1; \ 70 | (void)HAL_GPIO_##name##_out; \ 71 | } \ 72 | \ 73 | static inline void HAL_GPIO_##name##_alt(int v) \ 74 | { \ 75 | int bi = (pin % 8) * 4; \ 76 | if (pin & 0x8) \ 77 | GPIO##port->AFSEL1 = (GPIO##port->AFSEL1 & ~(0xf << bi)) | (v << bi); \ 78 | else \ 79 | GPIO##port->AFSEL0 = (GPIO##port->AFSEL0 & ~(0xf << bi)) | (v << bi); \ 80 | GPIO##port->CTL_b.CTL##pin = 2; \ 81 | (void)HAL_GPIO_##name##_alt; \ 82 | } \ 83 | \ 84 | static inline void HAL_GPIO_##name##_analog(void) \ 85 | { \ 86 | GPIO##port->CTL_b.CTL##pin = 3; \ 87 | (void)HAL_GPIO_##name##_analog; \ 88 | } \ 89 | \ 90 | static inline void HAL_GPIO_##name##_pullup(void) \ 91 | { \ 92 | GPIO##port->PUD_b.PUD##pin = 1; \ 93 | (void)HAL_GPIO_##name##_pullup; \ 94 | } \ 95 | \ 96 | static inline void HAL_GPIO_##name##_pulldown(void) \ 97 | { \ 98 | GPIO##port->PUD_b.PUD##pin = 2; \ 99 | (void)HAL_GPIO_##name##_pulldown; \ 100 | } \ 101 | \ 102 | static inline void HAL_GPIO_##name##_pulldis(void) \ 103 | { \ 104 | GPIO##port->PUD_b.PUD##pin = 0; \ 105 | (void)HAL_GPIO_##name##_pulldis; \ 106 | } \ 107 | \ 108 | static inline int HAL_GPIO_##name##_read(void) \ 109 | { \ 110 | return GPIO##port->ISTAT_b.ISTAT##pin; \ 111 | (void)HAL_GPIO_##name##_read; \ 112 | } \ 113 | \ 114 | static inline int HAL_GPIO_##name##_state(void) \ 115 | { \ 116 | return GPIO##port->CTL_b.CTL##pin; \ 117 | (void)HAL_GPIO_##name##_state; \ 118 | } \ 119 | \ 120 | static inline void HAL_GPIO_##name##_speed(int s) \ 121 | { \ 122 | GPIO##port->OSPD_b.OSPD##pin = s; \ 123 | (void)HAL_GPIO_##name##_speed; \ 124 | } \ 125 | \ 126 | static inline void HAL_GPIO_##name##_open_drain(void) \ 127 | { \ 128 | GPIO##port->OMODE_b.OM##pin = 1; \ 129 | (void)HAL_GPIO_##name##_open_drain; \ 130 | } \ 131 | \ 132 | static inline void HAL_GPIO_##name##_push_pull(void) \ 133 | { \ 134 | GPIO##port->OMODE_b.OM##pin = 0; \ 135 | (void)HAL_GPIO_##name##_push_pull; \ 136 | } \ 137 | 138 | #endif // _HAL_GPIO_H_ 139 | 140 | -------------------------------------------------------------------------------- /doc/Hardware.md: -------------------------------------------------------------------------------- 1 | # FNIRSI-5012H Hardware 2 | 3 | There are two models of the PCB. The first revision has 4 mechanical relays. 4 | The second revision has only one mechanical relay. The text below only applies 5 | to the second revision. 6 | 7 | ## Main components on the board 8 | 9 | * GD32F407VET6 - MCU (Cortex-M4, 512 KB Flash, 192 KB SRAM) 10 | * AD9288 (most likely a clone, no markings) - ADC 11 | * TP4056 - Li-lon Battery Charger 12 | * TLV70033DDCR - 3.3 V LDO 13 | * PC817 - Photocoupler 14 | * CPC1002N - Optically coupled solid state relay 15 | * SN74HC148 - 8-line to 3-line priority encoder 16 | * SS8550 - PNP transistor 17 | * HFD4 - Mechanical relay 18 | * OPA356 - 200 MHz, CMOS OpAmp 19 | * W25Q64JV - 64 Mbit SPI Flash 20 | * TFT Display - Based on ST7789S 21 | 22 | ## ADC 23 | 24 | The ADC is pin-compatible with AD9288, but there are a couple of pins in 25 | the original that are marked NC, but bypassed to ground with capacitors 26 | in this design. It also has a hemispherical dimple for the first pin marker. 27 | The original has a flat bottom dimple. So it is most likely a clone, 28 | but fully pin-compatible. It might be MXT2088. 29 | 30 | ## Power System 31 | 32 | There are two LDOs in the system. One is the main LDO powering all the components. 33 | The other one is dedicated to the LCD backlight. The brightness is controlled by 34 | PWMing the enable signal. 35 | 36 | The LDO inputs are always supplied by the battery and he power switch 37 | controls enable pin of the main LDO. 38 | 39 | ## USB 40 | 41 | The USB connector has programming pins (SWDIO/SWCLK) on the data pins, 42 | so this connector is used for initial programming during the manufacturing process. 43 | 44 | As a result there is no way to get USB working without hardware modification. 45 | Modification would be relatively easy to do. USB FS data pins are located right 46 | next to the programming pins. But I'm not sure there is any value to having USB on 47 | this device. 48 | 49 | ## Buttons 50 | 51 | SN74HC148 are used to read the keyboard. Each IC handles 8 buttons and two buttons 52 | are connected directly to the MCU pins (for a total of 18 buttons). 53 | 54 | Allocation of keys to priority encoders (PE): 55 | 56 | | Channel | PE0 | PE1 | 57 | |:-------:|:------|:----------| 58 | | 0 | STOP | 50% | 59 | | 1 | F1 | TRIG DOWN | 60 | | 2 | EDGE | TRIG UP | 61 | | 3 | AC/DC | TRIG | 62 | | 4 | UP | MENU | 63 | | 5 | RIGHT | SAVE | 64 | | 6 | MODE | LEFT | 65 | | 7 | AUTO | DOWN | 66 | 67 | F2 and 1X10X are connected directly to the MCU pins. 68 | 69 | It is an interesting way to reduce the number of pins required for 70 | the keyboard, but obviously only one key from the group can be detected 71 | at a time, even if multiple keys are pressed. 72 | 73 | ## Other Hardware 74 | 75 | * CPC1002N is used for shorting the AC/DC capacitor. 76 | * SS8550 are used to control PC817s and a mechanical relay. 77 | * OPA356 is a buffer right before the ADC. 78 | * W25Q64JV is used for waveform storage (and possibly settings, but not the firmware). 79 | 80 | ## Attenuation (Vertical Scale Control) 81 | 82 | Attenuation is set though the 7 transistors (controlling optocouplers and a relay). 83 | I number the transistors Q0-Q6 starting from the one closest to the BNC connector. 84 | Each volts/div setting enables one transistor: 85 | * 10 V/div - Q4 86 | * 5 V/div - Q5 87 | * 2 V/div - Q6 88 | * 1 V/div - Q1 89 | * 500 mV/div - Q0 90 | * 200 mV/div - Q2 91 | * 100 mV/div and 50 mV/div - Q3 92 | 93 | 50 and 100 mV/div are not different on the hardware level, so the amplitude 94 | is just changed in the software. This is also the only range that is controlled 95 | using a mechanical relay. 96 | 97 | ## Front-end 98 | 99 | Here is a schematic of the front-end of this oscilloscope. None of the capacitor values are known. 100 | 101 | Transistors are part of the optocouplers. The paired transistors are the same optocouplers, 102 | but they are driven at the same time (LEDs on the other side are in series). 103 | 104 | ![FNIRSI-5012H Front-end](frontend.jpg) 105 | 106 | ## GD32F407VET6 Pinout 107 | 108 | And finally, the full pinout of the MCU. 109 | 110 | ADC 111 | 112 | | Pin | Function | 113 | |:----:|:-----------| 114 | | PD0  | ADC B D0 | 115 | | PD1  | ADC B D1 | 116 | | PD2  | ADC B D2 | 117 | | PD3  | ADC B D3 | 118 | | PD4  | ADC B D4 | 119 | | PD5  | ADC B D5 | 120 | | PD6  | ADC B D6 | 121 | | PD7  | ADC B D7 | 122 | | PD8  | ADC A D7 | 123 | | PD9  | ADC A D6 | 124 | | PD10 | ADC A D5 | 125 | | PD11 | ADC A D4 | 126 | | PD12 | ADC A D3 | 127 | | PD13 | ADC A D2 | 128 | | PD14 | ADC A D1 | 129 | | PD15 | ADC A D0 | 130 | | PA8  | ADC A CLK | 131 | | PA9  | ADC B CLK | 132 | 133 | LCD 134 | 135 | | Pin | Function | 136 | |:----:|:-----------| 137 | | PC6  | LCD_RESET | 138 | | PB3  | LCD_RD | 139 | | PB4  | LCD_WR | 140 | | PB5  | LCD_RS | 141 | | PB6  | LCD_CS | 142 | | PE0  | LCD_D0 | 143 | | PE1  | LCD_D1 | 144 | | PE2  | LCD_D2 | 145 | | PE3  | LCD_D3 | 146 | | PE4  | LCD_D4 | 147 | | PE5  | LCD_D5 | 148 | | PE6  | LCD_D6 | 149 | | PE7  | LCD_D7 | 150 | | PB0  | LCD_BL_EN | 151 | 152 | Vertical Controls 153 | 154 | | Pin | Function | 155 | |:----:|:-----------| 156 | | PB9  | Q0 | 157 | | PB8  | Q1 | 158 | | PB7  | Q2 | 159 | | PC12 | Q3 | 160 | | PC11 | Q4 | 161 | | PC10 | Q5 | 162 | | PA15 | Q6 | 163 | | PC15 | AC/DC | 164 | | PA4  | Offset (DAC output) | 165 | 166 | Keyboard 167 | 168 | | Pin | Function | 169 | |:----:|:-----------| 170 | | PE13 | PE0.A0 | 171 | | PB14 | PE0.A1 | 172 | | PB13 | PE0.A2 | 173 | | PE14 | PE0.GS | 174 | | PE15 | PE1.A0 | 175 | | PB12 | PE1.A1 | 176 | | PB11 | PE1.A2 | 177 | | PB10 | PE1.GS | 178 | | PE12 | BTN_1X10X | 179 | | PE11 | BTN_F2 | 180 | 181 | Flash 182 | 183 | | Pin | Function | 184 | |:----:|:-----------| 185 | | PA3  | FLASH_CS | 186 | | PA5  | FLASH_CLK | 187 | | PA6  | FLASH_MISO | 188 | | PA7  | FLASH_MOSI | 189 | 190 | Miscellaneous 191 | 192 | | Pin | Function | 193 | |:----:|:-----------| 194 | | PB15 | CHARGE | 195 | | PB1  | VBAT_SENSE (Vbat / 2) | 196 | | PHx | 20 MHz Crystal | 197 | | PA13 | SWDIO | 198 | | PA14 | SWCLK | 199 | 200 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include "gd32f4xx.h" 33 | #include "utils.h" 34 | 35 | /*- Definitions -------------------------------------------------------------*/ 36 | #define SPACE "\x01" 37 | 38 | /*- Variables ---------------------------------------------------------------*/ 39 | static char g_buf[64]; 40 | 41 | /*- Implementations ---------------------------------------------------------*/ 42 | 43 | //----------------------------------------------------------------------------- 44 | void crc32_init(void) 45 | { 46 | RCU->AHB1EN_b.CRCEN = 1; 47 | } 48 | 49 | //----------------------------------------------------------------------------- 50 | uint32_t crc32_calc(uint32_t *data, int size) 51 | { 52 | size /= sizeof(uint32_t); 53 | 54 | CRC->CTL = CRC_CTL_RST_Msk; 55 | while (CRC->CTL); 56 | 57 | for (int i = 0; i < size; i++) 58 | CRC->DATA = data[i]; 59 | 60 | return CRC->DATA; 61 | } 62 | 63 | //----------------------------------------------------------------------------- 64 | static char *format_number(int64_t value, int sign, int prec, int width, char *unit) 65 | { 66 | char *start = g_buf + sizeof(g_buf) - 8; // Maximum length of a unit string is 7 67 | char *ptr = start; 68 | 69 | while (*unit) 70 | *ptr++ = *unit++; 71 | 72 | *ptr = 0; 73 | ptr = start; 74 | 75 | do 76 | { 77 | *(--ptr) = '0' + (value % 10); 78 | value /= 10; 79 | if (--prec == 0) 80 | *(--ptr) = '.'; 81 | } while (value > 0 || prec >= 0); 82 | 83 | if (sign < 0) 84 | *(--ptr) = '-'; 85 | else if (sign > 0) 86 | *(--ptr) = '+'; 87 | 88 | while ((start - ptr) < width) 89 | *(--ptr) = ' '; 90 | 91 | return ptr; 92 | } 93 | 94 | //----------------------------------------------------------------------------- 95 | char *format_time(int64_t value, bool show_plus_sign) 96 | { 97 | int sign = (value < 0) ? -1 : (show_plus_sign ? 1 : 0); 98 | 99 | if (value < 0) 100 | value = -value; 101 | 102 | if (value < 1000) 103 | return format_number(value * 100, sign, 2, 7, SPACE"ns"); 104 | else if (value < 1000000) 105 | return format_number(value / 10, sign, 2, 7, SPACE"us"); 106 | else if (value < 1000000000) 107 | return format_number(value / 10000, sign, 2, 7, SPACE"ms"); 108 | else 109 | return format_number(value / 10000000, sign, 2, 7, SPACE"s "); 110 | } 111 | 112 | //----------------------------------------------------------------------------- 113 | char *format_voltage(int value, bool show_plus_sign) 114 | { 115 | int sign = (value < 0) ? -1 : (show_plus_sign ? 1 : 0); 116 | 117 | if (value < 0) 118 | value = -value; 119 | 120 | if (value < 1000) 121 | return format_number(value * 100, sign, 2, 7, SPACE"mV"); 122 | else 123 | return format_number(value / 10, sign, 2, 7, SPACE"V "); 124 | } 125 | 126 | //----------------------------------------------------------------------------- 127 | char *format_divisions(int value, bool show_plus_sign) 128 | { 129 | int sign = (value < 0) ? -1 : (show_plus_sign ? 1 : 0); 130 | 131 | if (value < 0) 132 | value = -value; 133 | 134 | return format_number(value, sign, 2, 6, SPACE"div"); 135 | } 136 | 137 | //----------------------------------------------------------------------------- 138 | char *format_frequency(int value) 139 | { 140 | if (value < 1000) 141 | return format_number(value * 100, 0, 2, 6, SPACE"Hz "); 142 | else if (value < 1000000) 143 | return format_number(value / 10, 0, 2, 6, SPACE"kHz"); 144 | else 145 | return format_number(value / 10000, 0, 2, 6, SPACE"MHz"); 146 | } 147 | 148 | //----------------------------------------------------------------------------- 149 | char *format_sps(int value) 150 | { 151 | if (value < 1000) 152 | return format_number(value, 0, 0, 3, SPACE" "); 153 | else if (value < 1000000) 154 | return format_number(value / 1000, 0, 0, 3, SPACE"K"); 155 | else 156 | return format_number(value / 1000000, 0, 0, 3, SPACE"M"); 157 | } 158 | 159 | //----------------------------------------------------------------------------- 160 | char *format_raw_data(int *data, int size) 161 | { 162 | static const char hex[] = "0123456789ABCDEF"; 163 | char *ptr = g_buf;; 164 | 165 | for (int i = 0; i < size; i++) 166 | { 167 | ptr[0] = hex[(data[i] >> 4) & 0xf]; 168 | ptr[1] = hex[data[i] & 0xf]; 169 | ptr[2] = ' '; 170 | ptr += 3; 171 | } 172 | 173 | ptr[size ? -1 : 0] = 0; 174 | 175 | return g_buf; 176 | } 177 | 178 | //----------------------------------------------------------------------------- 179 | uint64_t round_divide(int64_t dividend, int64_t divisor) 180 | { 181 | return (dividend + (divisor / 2)) / divisor; 182 | } 183 | 184 | 185 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open-5012h - Open Source Firmware for the FNIRSI-5012H Oscilloscope 2 | 3 | This is an open source firmware for the FNIRSI-5012H oscilloscope. 4 | 5 | The project is in the Alpha stage. The firmware is usable, but was not well tested. 6 | Use at your own risk. 7 | 8 | There are two models of the FNIRSI-5012H PCB. The first revision has 4 mechanical 9 | relays. The second revision has only one mechanical relay. This project is created 10 | for the more recent board with a single relay. I'm not sure how different the boards 11 | actually are, I don't have the old hardware. 12 | 13 | FNIRSI-5012H hardware is described in details [here](doc/Hardware.md). 14 | 15 | ## Installation 16 | 17 | The MCU (GigaDevice GD32F407VET6) is locked and can't be erased or reused. 18 | Swapping the chip is the only way to run this firmware. 19 | 20 | New GD32F407VET6 are available for $5 from LCSC. 21 | 22 | ## Programming 23 | 24 | Programming pins are available on the USB connector. There are no other dedicated 25 | test points or connectors on the board, so making an adapter is the best way to go. 26 | 27 | Details of the programmer connections are [here](doc/Programming.md). 28 | 29 | ## Keyboard 30 | 31 | Some buttons have multiple functions assigned to them. **1X10X** button is used 32 | as a **SHIFT** and marked as such in the text below. 1X/10X state can be selected 33 | through the menu. 34 | 35 | In the oscilloscope mode the buttons have the following functions: 36 | 37 | | Button | Function | 38 | |:---:|:---| 39 | | **AC/DC** | Select AC or DC Coupling | 40 | | **MODE** | Select Measurement or Trigger Parameters Display Mode | 41 | | **STOP** | Start, Stop or Retrigger Capture | 42 | | **EDGE** | Select Trigger Edge | 43 | | **TRIG** | Select Trigger Mode (Normal, Auto, Single) | 44 | | **TRIG UP** / **TRIG DOWN** | Change Trigger Level | 45 | | **SHIFT** + **TRIG UP** / **TRIG DOWN** | Change Sample Rate Limit | 46 | | **UP** / **DOWN** | Change Vertical Position | 47 | | **SHIFT** + **UP** / **DOWN** | Change Vertical Scale | 48 | | **UP** + **DOWN** | Set Vertical Position to 0 | 49 | | **LEFT** / **RIGHT** | Change Horizontal Position | 50 | | **SHIFT** + **LEFT** / **RIGHT** | Change Horizontal Scale | 51 | | **LEFT** + **RIGHT** | Set Horizontal Position to 0 | 52 | 53 | ## Calibration 54 | 55 | Your hardware will require calibration. The default calibration values are 56 | the values from my development device, so they will definitely not work for 57 | any other device. 58 | 59 | The calibration mode is entered by holding **SHIFT** + **MODE** while powering on 60 | the device, 61 | 62 | The calibration should be performed with a fully charged battery and 63 | the charger disconnected. It is better to have LCD backlight level set to 100%. 64 | 65 | The calibration should be performed with a direct connection to the device or 66 | a probe in 1X mode. 67 | 68 | In the calibration mode trigger controls are fixed to the auto mode with 69 | the rising edge and the level set to 0. 70 | 71 | The trigger control buttons change their functions: 72 | 73 | | Button | Function | 74 | |:---:|:---| 75 | | **TRIG UP** / **TRIG DOWN** | Change Calibration Value | 76 | | **SHIFT** + **TRIG UP** / **TRIG DOWN** | Change Calibration Parameter | 77 | 78 | In the calibration mode trigger parameters in the status line are replaced 79 | with the calibration data. 80 | 81 | There are 4 calibration parameters: 82 | 1. Zero -- Zero offset 83 | 2. Delta -- Delta between the channels in a dual channel mode 84 | 3. Scale -- Voltage Scale 85 | 4. Offset -- Voltage Offset 86 | 87 | Zero and Delta are common to all vertical scales, but Scale and Offset 88 | have to be adjusted for each vertical scale individually. 89 | 90 | In the Zero and Delta modes status line shows raw ADC readings and 91 | the screen is split into two halves. On the left trace shows raw ADC 92 | readings and the right side shows magnified view of the same trace. 93 | 94 | In the Scale and Offset modes status line shows minimum and maximum voltage 95 | values. All the calibration procedures are performed with the constant (DC) 96 | voltages, so the minimum and maximum voltages will be close, but they will 97 | be slightly different due to noise. 98 | 99 | The calibration procedure consists of a few steps. 100 | 101 | ### Zero 102 | 103 | This step must be performed in a single channel mode (sample rate is 62 MSPS or below). 104 | 105 | For this test the input must be shorted (or at least disconnected). 106 | 107 | The goal is to adjust the trace positions so it is exactly in the middle of the screen. 108 | 109 | Middle of the screen corresponds to 0 V, which is the raw ADC reading of 0x80. 110 | 111 | ### Delta 112 | 113 | This step must be performed in a dual channel mode (sample rate is 125 MSPS). 114 | 115 | For this test the input must be shorted (or at least disconnected). 116 | 117 | The goal is to adjust the trace so that even and odd samples (coming from the ADC 118 | channels A and B) have the same value. 119 | 120 | ### Scale 121 | 122 | This must be performed in a single channel mode (sample rate is 62 MSPS or below). 123 | The vertical offset must be set to 0 V. 124 | 125 | The input must be connected to the source of the variable voltage. 126 | 127 | The voltage must be set so that ADC readings are close to the full scale, 128 | but not clipping. 129 | 130 | Zero or Delta mode raw readings can be used to select appropriate voltage. 131 | Ideally the raw ADC data should be in the range 0xd0 - 0xf0. 132 | 133 | The exact voltage does not matter as long as it can be measured independently 134 | (for example using multimeter). 135 | 136 | The calibration value must be adjusted until the minimum and maximum values 137 | in the status bar match the measured value. 138 | 139 | The calibration value for the negative voltage may be slightly different. 140 | It is recommended to perform this procedure for the negative voltage as well 141 | and adjust the calibration until symmetrical results are reached. 142 | 143 | This step must be performed for all vertical scale settings separately. 144 | 145 | ### Offset 146 | 147 | This must be performed in a single channel mode (sample rate is 62 MSPS or below). 148 | 149 | The input must be connected to the source of the variable voltage. 150 | 151 | Set the vertical offset close to the edge of the grid (+4 or -4 divisions). 152 | 153 | Adjust calibration value until the displayed minimum and maximum voltages 154 | match the actually measures voltage. 155 | 156 | Perform this procedure for both positive and negative vertical position settings. 157 | 158 | This step must be performed for all vertical scale settings separately. 159 | 160 | 161 | -------------------------------------------------------------------------------- /battery.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include "gd32f4xx.h" 33 | #include "hal_gpio.h" 34 | #include "config.h" 35 | #include "utils.h" 36 | #include "timer.h" 37 | #include "lcd.h" 38 | #include "battery.h" 39 | 40 | /*- Definitions -------------------------------------------------------------*/ 41 | #define BATTERY_X 289 42 | #define BATTERY_Y 4 43 | #define BATTERY_THRESHOLDS_SIZE 8 44 | #define BATTERY_REF_VOLTAGE 6600 45 | #define BATTERY_LOW_VOLTAGE 3500 46 | #define BATTERY_FULL_VOLTAGE 4150 47 | #define BATTERY_BLINK_INTERVAL 500 48 | #define BATTERY_UPDATE_INTERVAL 5000 49 | 50 | HAL_GPIO_PIN(VBAT, B, 1) 51 | HAL_GPIO_PIN(CHARGING, B, 15) 52 | 53 | /*- Constants ---------------------------------------------------------------*/ 54 | static const int battery_thresholds[BATTERY_THRESHOLDS_SIZE] = 55 | { 56 | BATTERY_LOW_VOLTAGE, 3600, 3650, 3700, 3750, 3800, 3850, 3900, 57 | }; 58 | 59 | static const int battery_thresholds_charging[BATTERY_THRESHOLDS_SIZE] = 60 | { 61 | 3800, 3850, 3900, 3920, 3960, 4000, 4040, 4070, 62 | }; 63 | 64 | /*- Variables ---------------------------------------------------------------*/ 65 | static int g_battery_blink_timer = TIMER_DISABLE; 66 | static int g_battery_update_timer = TIMER_DISABLE; 67 | static int g_battery_voltage = 0; 68 | static bool g_battery_blink_state = true; 69 | 70 | /*- Implementations ---------------------------------------------------------*/ 71 | 72 | //----------------------------------------------------------------------------- 73 | static bool battery_charging(void) 74 | { 75 | if (HAL_GPIO_CHARGING_read() || (g_battery_voltage > BATTERY_FULL_VOLTAGE)) 76 | return false; 77 | else 78 | return true; 79 | } 80 | 81 | //----------------------------------------------------------------------------- 82 | static int read_battery_voltage(void) 83 | { 84 | return (ADC0->RDATA * BATTERY_REF_VOLTAGE) / 4096; 85 | } 86 | 87 | //----------------------------------------------------------------------------- 88 | static void battery_draw_frame(void) 89 | { 90 | lcd_fill_rect(BATTERY_X, BATTERY_Y, 20, 10, LCD_WHITE_COLOR); 91 | lcd_fill_rect(BATTERY_X+1, BATTERY_Y+1, 18, 8, LCD_BLACK_COLOR); 92 | lcd_fill_rect(BATTERY_X+20, BATTERY_Y+3, 2, 4, LCD_WHITE_COLOR); 93 | } 94 | 95 | //----------------------------------------------------------------------------- 96 | static void battery_draw_level(void) 97 | { 98 | const int *thresholds = HAL_GPIO_CHARGING_read() ? battery_thresholds : battery_thresholds_charging; 99 | int bars, color; 100 | 101 | for (bars = 0; bars < BATTERY_THRESHOLDS_SIZE; bars++) 102 | { 103 | if (g_battery_voltage < thresholds[bars]) 104 | break; 105 | } 106 | 107 | if (bars < 2) 108 | color = LCD_RED_COLOR; 109 | else if (bars < 4) 110 | color = LCD_COLOR(255, 200, 0); 111 | else 112 | color = LCD_GREEN_COLOR; 113 | 114 | if (bars > 0 && !g_battery_blink_state) 115 | bars--; 116 | 117 | if (bars > 0) 118 | lcd_fill_rect(BATTERY_X+2, BATTERY_Y+2, bars * 2, 6, color); 119 | 120 | if (bars < BATTERY_THRESHOLDS_SIZE) 121 | { 122 | lcd_fill_rect(BATTERY_X+2 + bars * 2, BATTERY_Y+2, 123 | (BATTERY_THRESHOLDS_SIZE-bars) * 2, 6, LCD_BLACK_COLOR); 124 | } 125 | } 126 | 127 | //----------------------------------------------------------------------------- 128 | void battery_init(void) 129 | { 130 | HAL_GPIO_CHARGING_in(); 131 | HAL_GPIO_CHARGING_pullup(); 132 | 133 | HAL_GPIO_VBAT_analog(); 134 | 135 | RCU->APB2EN_b.ADC0EN = 1; 136 | 137 | ADC_Common->SYNCCTL_b.ADCCK = 7; // HCLK / 20 138 | 139 | ADC0->OVSAMPCTL = ADC0_OVSAMPCTL_OVSEN_Msk | (7/*256x*/ << ADC0_OVSAMPCTL_OVSR_Pos) | 140 | (8/*Shift 8-bits*/ << ADC0_OVSAMPCTL_OVSS_Pos); 141 | 142 | ADC0->CTL1_b.ADCON = 1; 143 | delay_ms(1); 144 | 145 | ADC0->CTL1_b.RSTCLB = 1; 146 | while (ADC0->CTL1_b.RSTCLB); 147 | 148 | ADC0->CTL1_b.CLB = 1; 149 | while (ADC0->CTL1_b.CLB); 150 | 151 | ADC0->RSQ2_b.RSQ0 = 9; 152 | ADC0->SAMPT1_b.SPT0 = 7; // 480 cycles 153 | 154 | ADC0->CTL1_b.CTN = 1; 155 | 156 | ADC0->CTL1_b.SWRCST = 1; 157 | while (0 == ADC0->STAT_b.EOC); 158 | 159 | g_battery_voltage = read_battery_voltage(); 160 | 161 | timer_add(&g_battery_update_timer); 162 | timer_add(&g_battery_blink_timer); 163 | 164 | g_battery_update_timer = 0; 165 | 166 | battery_draw_frame(); 167 | battery_draw_level(); 168 | } 169 | 170 | //----------------------------------------------------------------------------- 171 | int battery_voltage(void) 172 | { 173 | return g_battery_voltage; 174 | } 175 | 176 | //----------------------------------------------------------------------------- 177 | void battery_task(void) 178 | { 179 | if (0 == g_battery_update_timer) 180 | { 181 | int voltage = read_battery_voltage(); 182 | 183 | if (voltage < BATTERY_LOW_VOLTAGE) 184 | battery_low_handler(); 185 | 186 | if (voltage != g_battery_voltage) 187 | { 188 | g_battery_voltage = voltage; 189 | battery_draw_level(); 190 | } 191 | 192 | g_battery_update_timer = BATTERY_UPDATE_INTERVAL; 193 | } 194 | 195 | if (0 == g_battery_blink_timer) 196 | { 197 | g_battery_voltage = read_battery_voltage(); 198 | 199 | if (battery_charging()) 200 | { 201 | g_battery_blink_timer = BATTERY_BLINK_INTERVAL; 202 | g_battery_blink_state = !g_battery_blink_state; 203 | } 204 | else 205 | { 206 | g_battery_blink_timer = TIMER_DISABLE; 207 | g_battery_blink_state = true; 208 | } 209 | 210 | battery_draw_level(); 211 | } 212 | 213 | if (TIMER_DISABLE == g_battery_blink_timer && battery_charging()) 214 | { 215 | config.charge_cycles++; 216 | g_battery_blink_timer = BATTERY_BLINK_INTERVAL; 217 | } 218 | } 219 | 220 | 221 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "gd32f4xx.h" 37 | #include "hal_gpio.h" 38 | #include "lcd.h" 39 | #include "utils.h" 40 | #include "flash.h" 41 | #include "timer.h" 42 | #include "config.h" 43 | #include "buttons.h" 44 | #include "battery.h" 45 | #include "capture.h" 46 | #include "scope.h" 47 | 48 | /*- Definitions -------------------------------------------------------------*/ 49 | #define RESET_TO_DEFAULT (BTN_SHIFT | BTN_SAVE) 50 | #define CALIBRATION_MODE (BTN_SHIFT | BTN_MODE) 51 | 52 | /*- Variables ---------------------------------------------------------------*/ 53 | 54 | /*- Implementations ---------------------------------------------------------*/ 55 | 56 | //----------------------------------------------------------------------------- 57 | static void sys_init(void) 58 | { 59 | RCU->AHB1EN |= RCU_AHB1EN_PAEN_Msk | RCU_AHB1EN_PBEN_Msk | RCU_AHB1EN_PCEN_Msk | 60 | RCU_AHB1EN_PDEN_Msk | RCU_AHB1EN_PEEN_Msk | RCU_AHB1EN_PFEN_Msk | 61 | RCU_AHB1EN_PGEN_Msk | RCU_AHB1EN_PHEN_Msk | RCU_AHB1EN_PIEN_Msk; 62 | 63 | // Stop execution of the program before it has a chance to configure high speed 64 | // clocks. This helps with programming. 65 | if (buttons_read() & BTN_F2) 66 | while (1); 67 | 68 | RCU->CTL_b.HXTALEN = 1; 69 | while (0 == RCU->CTL_b.HXTALSTB); 70 | 71 | RCU->PLL = RCU_PLL_PLLSEL_Msk | (20 << RCU_PLL_PLLPSC_Pos) | (500 << RCU_PLL_PLLN_Pos) | 72 | (0 << RCU_PLL_PLLP_Pos) | (15 << RCU_PLL_PLLQ_Pos); 73 | 74 | RCU->CTL_b.PLLEN = 1; 75 | while (0 == RCU->CTL_b.PLLSTB); 76 | 77 | RCU->CFG0 = (2/*CK_PLLP*/ << RCU_CFG0_SCS_Pos) | (0/*CK_SYS*/ << RCU_CFG0_AHBPSC_Pos) | 78 | (5/*DIV 4*/ << RCU_CFG0_APB1PSC_Pos) | (4/*DIV 2*/ << RCU_CFG0_APB2PSC_Pos) | 79 | (0 << RCU_CFG0_RTCDIV_Pos); 80 | while (RCU->CFG0_b.SCSS != 2); 81 | } 82 | 83 | //----------------------------------------------------------------------------- 84 | static void print_value(int x, int y, char *name, uint32_t value) 85 | { 86 | static const char hex[] = "0123456789abcdef"; 87 | char str[9]; 88 | 89 | for (int i = 0; i < 8; i++) 90 | str[i] = hex[(value >> ((7-i)*4)) & 0xf]; 91 | 92 | str[8] = 0; 93 | 94 | lcd_puts((x+1)*8, 2 + y*16, name); 95 | lcd_puts((x+6)*8, 2 + y*16, "= 0x"); 96 | lcd_puts((x+10)*8, 2 + y*16, str); 97 | } 98 | 99 | //----------------------------------------------------------------------------- 100 | void irq_handler_hard_fault_c(uint32_t lr, uint32_t msp, uint32_t psp) 101 | { 102 | uint32_t s_r0, s_r1, s_r2, s_r3, s_r12, s_lr, s_pc, s_psr; 103 | uint32_t r_CFSR, r_HFSR, r_DFSR, r_AFSR, r_BFAR, r_MMAR; 104 | uint32_t *sp = (uint32_t *)((lr & 4) ? psp : msp); 105 | 106 | s_r0 = sp[0]; 107 | s_r1 = sp[1]; 108 | s_r2 = sp[2]; 109 | s_r3 = sp[3]; 110 | s_r12 = sp[4]; 111 | s_lr = sp[5]; 112 | s_pc = sp[6]; 113 | s_psr = sp[7]; 114 | 115 | r_CFSR = SCB->CFSR; // Configurable Fault Status Register (MMSR, BFSR and UFSR) 116 | r_HFSR = SCB->HFSR; // Hard Fault Status Register 117 | r_DFSR = SCB->DFSR; // Debug Fault Status Register 118 | r_MMAR = SCB->MMFAR; // MemManage Fault Address Register 119 | r_BFAR = SCB->BFAR; // Bus Fault Address Register 120 | r_AFSR = SCB->AFSR; // Auxiliary Fault Status Register 121 | 122 | asm("nop"); // Setup breakpoint here 123 | 124 | lcd_fill_rect(0, 0, LCD_WIDTH, LCD_HEIGHT, LCD_BLACK_COLOR); 125 | lcd_set_color(LCD_BLACK_COLOR, LCD_WHITE_COLOR); 126 | lcd_set_font(FONT_LARGE); 127 | lcd_puts(120, 2, "HARD FAULT"); 128 | 129 | print_value(0, 2, "R0", s_r0); 130 | print_value(0, 3, "R1", s_r1); 131 | print_value(0, 4, "R2", s_r2); 132 | print_value(0, 5, "R3", s_r3); 133 | print_value(0, 6, "R12", s_r12); 134 | print_value(0, 7, "LR", s_lr); 135 | print_value(0, 8, "PC", s_pc); 136 | print_value(0, 9, "PSR", s_psr); 137 | print_value(0, 10, "SP", (lr & 4) ? psp : msp); 138 | print_value(0, 11, "MSP", msp); 139 | print_value(0, 12, "PSP", psp); 140 | 141 | print_value(20, 2, "CFSR", r_CFSR); 142 | print_value(20, 3, "HFSR", r_HFSR); 143 | print_value(20, 4, "DFSR", r_DFSR); 144 | print_value(20, 5, "MMAR", r_MMAR); 145 | print_value(20, 6, "BFAR", r_BFAR); 146 | print_value(20, 7, "AFSR", r_AFSR); 147 | 148 | while (1); 149 | } 150 | 151 | //----------------------------------------------------------------------------- 152 | __attribute__((naked)) void irq_handler_hard_fault(void) 153 | { 154 | asm volatile (R"asm( 155 | mov r0, lr 156 | mrs r1, msp 157 | mrs r2, psp 158 | b irq_handler_hard_fault_c 159 | )asm" 160 | ); 161 | } 162 | 163 | //----------------------------------------------------------------------------- 164 | void error(char *text) 165 | { 166 | int len; 167 | 168 | __disable_irq(); 169 | 170 | capture_stop(); 171 | capture_disable_clock(); 172 | lcd_set_backlight_level(50); 173 | 174 | lcd_set_font(FONT_LARGE); 175 | lcd_set_color(LCD_WHITE_COLOR, LCD_RED_COLOR); 176 | lcd_fill_rect(0, 0, LCD_WIDTH, LCD_HEIGHT, LCD_WHITE_COLOR); 177 | 178 | for (len = 0; text[len]; len++); 179 | 180 | lcd_puts(LCD_WIDTH/2 - len*4, 112, text); 181 | 182 | while (1); 183 | } 184 | 185 | //----------------------------------------------------------------------------- 186 | void battery_low_handler(void) 187 | { 188 | error("BATTERY LOW"); 189 | } 190 | 191 | //----------------------------------------------------------------------------- 192 | void buttons_handler(int buttons) 193 | { 194 | scope_buttons_handler(buttons); 195 | 196 | #if 1 // Debug only, makes it easier to program things 197 | if (buttons & BTN_F2) 198 | { 199 | capture_disable_clock(); 200 | while (1); 201 | } 202 | #endif 203 | } 204 | 205 | //----------------------------------------------------------------------------- 206 | int main(void) 207 | { 208 | int buttons; 209 | 210 | sys_init(); 211 | timer_init(); 212 | lcd_init(); 213 | crc32_init(); 214 | //flash_init(); 215 | config_init(); 216 | buttons_init(); 217 | battery_init(); 218 | capture_init(); 219 | 220 | lcd_set_font(FONT_LARGE); 221 | lcd_set_color(LCD_BLACK_COLOR, LCD_WHITE_COLOR); 222 | lcd_set_backlight_level(config.lcd_bl_level); 223 | 224 | buttons = buttons_state(); 225 | 226 | if ((buttons & RESET_TO_DEFAULT) == RESET_TO_DEFAULT) 227 | config_reset(); 228 | 229 | scope_init((buttons & CALIBRATION_MODE) == CALIBRATION_MODE); 230 | 231 | while (1) 232 | { 233 | timer_task(); 234 | scope_task(); 235 | battery_task(); 236 | buttons_task(); 237 | config_task(); 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | -------------------------------------------------------------------------------- /images.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include "images.h" 33 | #include "lcd.h" 34 | 35 | /*- Constants ---------------------------------------------------------------*/ 36 | #define __ LCD_COLOR(0, 0, 0) // Background 37 | #define WT LCD_COLOR(255, 255, 255) // White 38 | #define OR LCD_COLOR(255, 180, 50) // Orange 39 | #define YL LCD_COLOR(255, 255, 0) // Yellow 40 | #define CY LCD_COLOR(50, 255, 255) // Cyan-ish 41 | 42 | const Image image_ac = 43 | { 44 | .width = 8, 45 | .height = 16, 46 | .ox = 0, 47 | .oy = 0, 48 | .data = { 49 | __, __, __, __, __, __, __, __, 50 | __, __, __, __, __, __, __, __, 51 | __, __, YL, YL, __, __, __, __, 52 | __, YL, __, __, YL, __, __, YL, 53 | __, __, __, __, __, YL, YL, __, 54 | __, __, __, __, __, __, __, __, 55 | __, __, YL, __, __, __, YL, __, 56 | __, YL, __, YL, __, YL, __, YL, 57 | __, YL, __, YL, __, YL, __, __, 58 | __, YL, YL, YL, __, YL, __, __, 59 | __, YL, __, YL, __, YL, __, YL, 60 | __, YL, __, YL, __, __, YL, __, 61 | __, __, __, __, __, __, __, __, 62 | __, __, __, __, __, __, __, __, 63 | __, __, __, __, __, __, __, __, 64 | __, __, __, __, __, __, __, __, 65 | } 66 | }; 67 | 68 | const Image image_dc = 69 | { 70 | .width = 8, 71 | .height = 16, 72 | .ox = 0, 73 | .oy = 0, 74 | .data = { 75 | __, __, __, __, __, __, __, __, 76 | __, __, __, __, __, __, __, __, 77 | __, YL, __, YL, __, YL, __, YL, 78 | __, __, __, __, __, __, __, __, 79 | __, YL, YL, YL, YL, YL, YL, YL, 80 | __, __, __, __, __, __, __, __, 81 | __, YL, YL, __, __, __, YL, __, 82 | __, YL, __, YL, __, YL, __, YL, 83 | __, YL, __, YL, __, YL, __, __, 84 | __, YL, __, YL, __, YL, __, __, 85 | __, YL, __, YL, __, YL, __, YL, 86 | __, YL, YL, __, __, __, YL, __, 87 | __, __, __, __, __, __, __, __, 88 | __, __, __, __, __, __, __, __, 89 | __, __, __, __, __, __, __, __, 90 | __, __, __, __, __, __, __, __, 91 | } 92 | }; 93 | 94 | const Image image_trigger_edge_rise = 95 | { 96 | .width = 8, 97 | .height = 16, 98 | .ox = 0, 99 | .oy = 0, 100 | .data = { 101 | __, __, __, __, __, __, __, __, 102 | __, __, __, __, __, __, __, __, 103 | __, __, __, __, __, CY, CY, CY, 104 | __, __, __, __, __, CY, __, __, 105 | __, __, __, __, __, CY, __, __, 106 | __, __, __, __, __, CY, __, __, 107 | __, __, __, __, CY, __, __, __, 108 | __, __, __, __, CY, __, __, __, 109 | __, __, __, __, CY, __, __, __, 110 | __, __, __, CY, __, __, __, __, 111 | __, __, __, CY, __, __, __, __, 112 | __, __, __, CY, __, __, __, __, 113 | __, CY, CY, CY, __, __, __, __, 114 | __, __, __, __, __, __, __, __, 115 | __, __, __, __, __, __, __, __, 116 | __, __, __, __, __, __, __, __, 117 | } 118 | }; 119 | 120 | const Image image_trigger_edge_fall = 121 | { 122 | .width = 8, 123 | .height = 16, 124 | .ox = 0, 125 | .oy = 0, 126 | .data = { 127 | __, __, __, __, __, __, __, __, 128 | __, __, __, __, __, __, __, __, 129 | __, CY, CY, CY, __, __, __, __, 130 | __, __, __, CY, __, __, __, __, 131 | __, __, __, CY, __, __, __, __, 132 | __, __, __, CY, __, __, __, __, 133 | __, __, __, __, CY, __, __, __, 134 | __, __, __, __, CY, __, __, __, 135 | __, __, __, __, CY, __, __, __, 136 | __, __, __, __, __, CY, __, __, 137 | __, __, __, __, __, CY, __, __, 138 | __, __, __, __, __, CY, __, __, 139 | __, __, __, __, __, CY, CY, CY, 140 | __, __, __, __, __, __, __, __, 141 | __, __, __, __, __, __, __, __, 142 | __, __, __, __, __, __, __, __, 143 | } 144 | }; 145 | 146 | const Image image_trigger_edge_both = 147 | { 148 | .width = 8, 149 | .height = 16, 150 | .ox = 0, 151 | .oy = 0, 152 | .data = { 153 | __, __, __, __, __, __, __, __, 154 | __, __, __, __, __, __, __, __, 155 | __, CY, CY, CY, __, CY, CY, CY, 156 | __, __, __, CY, __, CY, __, __, 157 | __, __, __, CY, __, CY, __, __, 158 | __, __, __, CY, __, CY, __, __, 159 | __, __, __, __, CY, __, __, __, 160 | __, __, __, __, CY, __, __, __, 161 | __, __, __, __, CY, __, __, __, 162 | __, __, __, CY, __, CY, __, __, 163 | __, __, __, CY, __, CY, __, __, 164 | __, __, __, CY, __, CY, __, __, 165 | __, CY, CY, CY, __, CY, CY, CY, 166 | __, __, __, __, __, __, __, __, 167 | __, __, __, __, __, __, __, __, 168 | __, __, __, __, __, __, __, __, 169 | } 170 | }; 171 | 172 | const Image image_trigger_level = 173 | { 174 | .width = 8, 175 | .height = 7, 176 | .ox = 0, 177 | .oy = 3, 178 | .data = { 179 | __, __, __, OR, OR, OR, OR, OR, 180 | __, __, OR, OR, OR, OR, OR, OR, 181 | __, OR, OR, OR, OR, OR, OR, OR, 182 | OR, OR, OR, OR, OR, OR, OR, OR, 183 | __, OR, OR, OR, OR, OR, OR, OR, 184 | __, __, OR, OR, OR, OR, OR, OR, 185 | __, __, __, OR, OR, OR, OR, OR, 186 | } 187 | }; 188 | 189 | const Image image_trigger_offset = 190 | { 191 | .width = 7, 192 | .height = 7, 193 | .ox = 3, 194 | .oy = 0, 195 | .data = { 196 | __, __, __, WT, __, __, __, 197 | __, __, __, WT, __, __, __, 198 | __, __, __, WT, __, __, __, 199 | WT, WT, WT, WT, WT, WT, WT, 200 | __, WT, WT, WT, WT, WT, __, 201 | __, __, WT, WT, WT, __, __, 202 | __, __, __, WT, __, __, __, 203 | } 204 | }; 205 | 206 | const Image image_trigger_offset_left = 207 | { 208 | .width = 7, 209 | .height = 7, 210 | .ox = 0, 211 | .oy = 0, 212 | .data = { 213 | __, __, __, WT, __, __, __, 214 | __, __, WT, WT, __, __, __, 215 | __, WT, WT, WT, __, __, __, 216 | WT, WT, WT, WT, WT, WT, WT, 217 | __, WT, WT, WT, __, __, __, 218 | __, __, WT, WT, __, __, __, 219 | __, __, __, WT, __, __, __, 220 | } 221 | }; 222 | 223 | const Image image_trigger_offset_right = 224 | { 225 | .width = 7, 226 | .height = 7, 227 | .ox = 6, 228 | .oy = 0, 229 | .data = { 230 | __, __, __, WT, __, __, __, 231 | __, __, __, WT, WT, __, __, 232 | __, __, __, WT, WT, WT, __, 233 | WT, WT, WT, WT, WT, WT, WT, 234 | __, __, __, WT, WT, WT, __, 235 | __, __, __, WT, WT, __, __, 236 | __, __, __, WT, __, __, __, 237 | } 238 | }; 239 | 240 | const Image image_trigger_mv = 241 | { 242 | .width = 5, 243 | .height = 5, 244 | .ox = 2, 245 | .oy = 4, 246 | .data = { 247 | OR, OR, OR, OR, OR, 248 | OR, OR, OR, OR, OR, 249 | OR, OR, OR, OR, OR, 250 | __, OR, OR, OR, __, 251 | __, __, OR, __, __, 252 | } 253 | }; 254 | 255 | const Image image_reference_level = 256 | { 257 | .width = 8, 258 | .height = 7, 259 | .ox = 7, 260 | .oy = 3, 261 | .data = { 262 | YL, YL, YL, YL, YL, __, __, __, 263 | YL, YL, YL, YL, YL, YL, __, __, 264 | YL, YL, YL, YL, YL, YL, YL, __, 265 | YL, YL, YL, YL, YL, YL, YL, YL, 266 | YL, YL, YL, YL, YL, YL, YL, __, 267 | YL, YL, YL, YL, YL, YL, __, __, 268 | YL, YL, YL, YL, YL, __, __, __, 269 | } 270 | }; 271 | 272 | const Image image_reference_level_up = 273 | { 274 | .width = 7, 275 | .height = 4, 276 | .ox = 3, 277 | .oy = 0, 278 | .data = { 279 | __, __, __, YL, __, __, __, 280 | __, __, YL, YL, YL, __, __, 281 | __, YL, YL, YL, YL, YL, __, 282 | YL, YL, YL, YL, YL, YL, YL, 283 | } 284 | }; 285 | 286 | const Image image_reference_level_down = 287 | { 288 | .width = 7, 289 | .height = 4, 290 | .ox = 3, 291 | .oy = 3, 292 | .data = { 293 | YL, YL, YL, YL, YL, YL, YL, 294 | __, YL, YL, YL, YL, YL, __, 295 | __, __, YL, YL, YL, __, __, 296 | __, __, __, YL, __, __, __, 297 | } 298 | }; 299 | 300 | 301 | -------------------------------------------------------------------------------- /include/cmsis_compiler.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_compiler.h 3 | * @brief CMSIS compiler generic header file 4 | * @version V5.1.0 5 | * @date 09. October 2018 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2018 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #ifndef __CMSIS_COMPILER_H 26 | #define __CMSIS_COMPILER_H 27 | 28 | #include 29 | 30 | /* 31 | * Arm Compiler 4/5 32 | */ 33 | #if defined ( __CC_ARM ) 34 | #include "cmsis_armcc.h" 35 | 36 | 37 | /* 38 | * Arm Compiler 6.6 LTM (armclang) 39 | */ 40 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) 41 | #include "cmsis_armclang_ltm.h" 42 | 43 | /* 44 | * Arm Compiler above 6.10.1 (armclang) 45 | */ 46 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) 47 | #include "cmsis_armclang.h" 48 | 49 | 50 | /* 51 | * GNU Compiler 52 | */ 53 | #elif defined ( __GNUC__ ) 54 | #include "cmsis_gcc.h" 55 | 56 | 57 | /* 58 | * IAR Compiler 59 | */ 60 | #elif defined ( __ICCARM__ ) 61 | #include 62 | 63 | 64 | /* 65 | * TI Arm Compiler 66 | */ 67 | #elif defined ( __TI_ARM__ ) 68 | #include 69 | 70 | #ifndef __ASM 71 | #define __ASM __asm 72 | #endif 73 | #ifndef __INLINE 74 | #define __INLINE inline 75 | #endif 76 | #ifndef __STATIC_INLINE 77 | #define __STATIC_INLINE static inline 78 | #endif 79 | #ifndef __STATIC_FORCEINLINE 80 | #define __STATIC_FORCEINLINE __STATIC_INLINE 81 | #endif 82 | #ifndef __NO_RETURN 83 | #define __NO_RETURN __attribute__((noreturn)) 84 | #endif 85 | #ifndef __USED 86 | #define __USED __attribute__((used)) 87 | #endif 88 | #ifndef __WEAK 89 | #define __WEAK __attribute__((weak)) 90 | #endif 91 | #ifndef __PACKED 92 | #define __PACKED __attribute__((packed)) 93 | #endif 94 | #ifndef __PACKED_STRUCT 95 | #define __PACKED_STRUCT struct __attribute__((packed)) 96 | #endif 97 | #ifndef __PACKED_UNION 98 | #define __PACKED_UNION union __attribute__((packed)) 99 | #endif 100 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 101 | struct __attribute__((packed)) T_UINT32 { uint32_t v; }; 102 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 103 | #endif 104 | #ifndef __UNALIGNED_UINT16_WRITE 105 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 106 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) 107 | #endif 108 | #ifndef __UNALIGNED_UINT16_READ 109 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 110 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 111 | #endif 112 | #ifndef __UNALIGNED_UINT32_WRITE 113 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 114 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 115 | #endif 116 | #ifndef __UNALIGNED_UINT32_READ 117 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 118 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 119 | #endif 120 | #ifndef __ALIGNED 121 | #define __ALIGNED(x) __attribute__((aligned(x))) 122 | #endif 123 | #ifndef __RESTRICT 124 | #define __RESTRICT __restrict 125 | #endif 126 | #ifndef __COMPILER_BARRIER 127 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 128 | #define __COMPILER_BARRIER() (void)0 129 | #endif 130 | 131 | 132 | /* 133 | * TASKING Compiler 134 | */ 135 | #elif defined ( __TASKING__ ) 136 | /* 137 | * The CMSIS functions have been implemented as intrinsics in the compiler. 138 | * Please use "carm -?i" to get an up to date list of all intrinsics, 139 | * Including the CMSIS ones. 140 | */ 141 | 142 | #ifndef __ASM 143 | #define __ASM __asm 144 | #endif 145 | #ifndef __INLINE 146 | #define __INLINE inline 147 | #endif 148 | #ifndef __STATIC_INLINE 149 | #define __STATIC_INLINE static inline 150 | #endif 151 | #ifndef __STATIC_FORCEINLINE 152 | #define __STATIC_FORCEINLINE __STATIC_INLINE 153 | #endif 154 | #ifndef __NO_RETURN 155 | #define __NO_RETURN __attribute__((noreturn)) 156 | #endif 157 | #ifndef __USED 158 | #define __USED __attribute__((used)) 159 | #endif 160 | #ifndef __WEAK 161 | #define __WEAK __attribute__((weak)) 162 | #endif 163 | #ifndef __PACKED 164 | #define __PACKED __packed__ 165 | #endif 166 | #ifndef __PACKED_STRUCT 167 | #define __PACKED_STRUCT struct __packed__ 168 | #endif 169 | #ifndef __PACKED_UNION 170 | #define __PACKED_UNION union __packed__ 171 | #endif 172 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 173 | struct __packed__ T_UINT32 { uint32_t v; }; 174 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 175 | #endif 176 | #ifndef __UNALIGNED_UINT16_WRITE 177 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 178 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 179 | #endif 180 | #ifndef __UNALIGNED_UINT16_READ 181 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 182 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 183 | #endif 184 | #ifndef __UNALIGNED_UINT32_WRITE 185 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 186 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 187 | #endif 188 | #ifndef __UNALIGNED_UINT32_READ 189 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 190 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 191 | #endif 192 | #ifndef __ALIGNED 193 | #define __ALIGNED(x) __align(x) 194 | #endif 195 | #ifndef __RESTRICT 196 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 197 | #define __RESTRICT 198 | #endif 199 | #ifndef __COMPILER_BARRIER 200 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 201 | #define __COMPILER_BARRIER() (void)0 202 | #endif 203 | 204 | 205 | /* 206 | * COSMIC Compiler 207 | */ 208 | #elif defined ( __CSMC__ ) 209 | #include 210 | 211 | #ifndef __ASM 212 | #define __ASM _asm 213 | #endif 214 | #ifndef __INLINE 215 | #define __INLINE inline 216 | #endif 217 | #ifndef __STATIC_INLINE 218 | #define __STATIC_INLINE static inline 219 | #endif 220 | #ifndef __STATIC_FORCEINLINE 221 | #define __STATIC_FORCEINLINE __STATIC_INLINE 222 | #endif 223 | #ifndef __NO_RETURN 224 | // NO RETURN is automatically detected hence no warning here 225 | #define __NO_RETURN 226 | #endif 227 | #ifndef __USED 228 | #warning No compiler specific solution for __USED. __USED is ignored. 229 | #define __USED 230 | #endif 231 | #ifndef __WEAK 232 | #define __WEAK __weak 233 | #endif 234 | #ifndef __PACKED 235 | #define __PACKED @packed 236 | #endif 237 | #ifndef __PACKED_STRUCT 238 | #define __PACKED_STRUCT @packed struct 239 | #endif 240 | #ifndef __PACKED_UNION 241 | #define __PACKED_UNION @packed union 242 | #endif 243 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 244 | @packed struct T_UINT32 { uint32_t v; }; 245 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 246 | #endif 247 | #ifndef __UNALIGNED_UINT16_WRITE 248 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 249 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 250 | #endif 251 | #ifndef __UNALIGNED_UINT16_READ 252 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 253 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 254 | #endif 255 | #ifndef __UNALIGNED_UINT32_WRITE 256 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 257 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 258 | #endif 259 | #ifndef __UNALIGNED_UINT32_READ 260 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 261 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 262 | #endif 263 | #ifndef __ALIGNED 264 | #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. 265 | #define __ALIGNED(x) 266 | #endif 267 | #ifndef __RESTRICT 268 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 269 | #define __RESTRICT 270 | #endif 271 | #ifndef __COMPILER_BARRIER 272 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 273 | #define __COMPILER_BARRIER() (void)0 274 | #endif 275 | 276 | 277 | #else 278 | #error Unknown compiler. 279 | #endif 280 | 281 | 282 | #endif /* __CMSIS_COMPILER_H */ 283 | 284 | -------------------------------------------------------------------------------- /config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include "gd32f4xx.h" 33 | #include "timer.h" 34 | #include "utils.h" 35 | #include "common.h" 36 | #include "config.h" 37 | 38 | /*- Definitions -------------------------------------------------------------*/ 39 | #define MAGIC 0x78656c41 40 | #define VERSION 1 41 | 42 | #define FLASH_START 0x08000000 43 | #define ENTRY_SIZE (1024) 44 | #define STORAGE_SIZE (256*1024) 45 | #define STORAGE_OFFSET (256*1024) 46 | #define STORAGE_START (FLASH_START + STORAGE_OFFSET) 47 | #define ENTRIES_COUNT (STORAGE_SIZE / ENTRY_SIZE) 48 | 49 | #define SECTOR_0_INDEX (6) 50 | #define SECTOR_0_OFFSET (0) 51 | #define SECTOR_1_INDEX (7) 52 | #define SECTOR_1_OFFSET (128*1024) 53 | 54 | #define TIMER_INTERVAL 1000 55 | 56 | #define FMC_KEY_KEY1 0x45670123 57 | #define FMC_KEY_KEY2 0xcdef89ab 58 | 59 | #define FMC_STAT_ALL_ERRORS (FMC_STAT_OPERR_Msk | FMC_STAT_WPERR_Msk | \ 60 | FMC_STAT_PGMERR_Msk | FMC_STAT_PGSERR_Msk | FMC_STAT_RDDERR_Msk) 61 | 62 | /*- Variables ---------------------------------------------------------------*/ 63 | Config config; 64 | static int g_config_timer = 0; 65 | static int g_entry_offset; 66 | static Config g_config_copy; 67 | static bool g_flash_erase_busy = false; 68 | static bool g_flash_write_busy = false; 69 | static uint32_t *g_flash_write_addr = 0; 70 | static uint32_t *g_flash_write_data = 0; 71 | static uint32_t g_flash_write_size = 0; 72 | 73 | /*- Implementations ---------------------------------------------------------*/ 74 | 75 | //----------------------------------------------------------------------------- 76 | static inline Config *get_entry(int index) 77 | { 78 | return (Config *)(STORAGE_START + index * ENTRY_SIZE); 79 | } 80 | 81 | //----------------------------------------------------------------------------- 82 | static void flash_unlock(void) 83 | { 84 | FMC->KEY = FMC_KEY_KEY1; 85 | FMC->KEY = FMC_KEY_KEY2; 86 | FMC->CTL = 0; 87 | 88 | if (FMC->CTL & FMC_CTL_LK_Msk) 89 | error("Flash unlock error"); 90 | } 91 | 92 | //----------------------------------------------------------------------------- 93 | static void flash_erase(int index) 94 | { 95 | uint32_t cmd = FMC_CTL_SER_Msk | (index << FMC_CTL_SN_Pos); 96 | 97 | FMC->CTL = cmd; 98 | FMC->CTL = cmd | FMC_CTL_START_Msk; 99 | 100 | g_flash_erase_busy = true; 101 | } 102 | 103 | //----------------------------------------------------------------------------- 104 | static bool flash_erase_task(void) 105 | { 106 | if (!g_flash_erase_busy) 107 | return false; 108 | 109 | if (FMC->STAT & FMC_STAT_BUSY_Msk) 110 | return true; 111 | 112 | if (FMC->STAT & FMC_STAT_ALL_ERRORS) 113 | error("Flash erase error"); 114 | 115 | FMC->CTL = 0; 116 | 117 | g_flash_erase_busy = false; 118 | 119 | return false; 120 | } 121 | 122 | //----------------------------------------------------------------------------- 123 | static void flash_write(uint32_t *addr, uint32_t *data, int size) 124 | { 125 | g_flash_write_addr = addr; 126 | g_flash_write_data = data; 127 | g_flash_write_size = size; 128 | g_flash_write_busy = true; 129 | } 130 | 131 | //----------------------------------------------------------------------------- 132 | static bool flash_write_task(void) 133 | { 134 | if (!g_flash_write_busy) 135 | return false; 136 | 137 | if (FMC->STAT & FMC_STAT_BUSY_Msk) 138 | return true; 139 | 140 | if (FMC->STAT & FMC_STAT_ALL_ERRORS) 141 | error("Flash write error"); 142 | 143 | if (g_flash_write_size > 0) 144 | { 145 | FMC->CTL = (2/*WORD*/ << FMC_CTL_PSZ_Pos) | FMC_CTL_PG_Msk; 146 | 147 | *g_flash_write_addr = *g_flash_write_data; 148 | g_flash_write_addr++; 149 | g_flash_write_data++; 150 | g_flash_write_size -= sizeof(uint32_t); 151 | return true; 152 | } 153 | else 154 | { 155 | FMC->CTL = 0; 156 | g_flash_write_busy = false; 157 | } 158 | 159 | return false; 160 | } 161 | 162 | //----------------------------------------------------------------------------- 163 | static bool is_entry_valid(Config *entry) 164 | { 165 | if (entry->magic != MAGIC) 166 | return false; 167 | 168 | if (entry->version != VERSION) 169 | return false; 170 | 171 | if (entry->size != sizeof(Config)) 172 | return false; 173 | 174 | if (crc32_calc((uint32_t *)entry, sizeof(Config) - sizeof(uint32_t)) != entry->crc) 175 | return false; 176 | 177 | return true; 178 | } 179 | 180 | //----------------------------------------------------------------------------- 181 | static int find_last_entry(void) 182 | { 183 | int max_count = -1; 184 | int index = -1; 185 | 186 | for (int i = 0; i < ENTRIES_COUNT; i++) 187 | { 188 | Config *entry = get_entry(i); 189 | 190 | if (!is_entry_valid(entry)) 191 | continue; 192 | 193 | if (entry->count > max_count) 194 | { 195 | index = i; 196 | max_count = entry->count; 197 | } 198 | } 199 | 200 | return index; 201 | } 202 | 203 | //----------------------------------------------------------------------------- 204 | static bool config_changed(void) 205 | { 206 | return crc32_calc((uint32_t *)&config, sizeof(Config) - sizeof(uint32_t)) != config.crc; 207 | } 208 | 209 | //----------------------------------------------------------------------------- 210 | static void config_save(void) 211 | { 212 | g_entry_offset = (g_entry_offset + ENTRY_SIZE) % STORAGE_SIZE; 213 | 214 | if (g_entry_offset == SECTOR_0_OFFSET) 215 | flash_erase(SECTOR_0_INDEX); 216 | else if (g_entry_offset == SECTOR_1_OFFSET) 217 | flash_erase(SECTOR_1_INDEX); 218 | 219 | config.count++; 220 | config.crc = crc32_calc((uint32_t *)&config, sizeof(Config) - sizeof(uint32_t)); 221 | 222 | g_config_copy = config; 223 | 224 | flash_write((uint32_t *)(STORAGE_START + g_entry_offset), 225 | (uint32_t *)&g_config_copy, sizeof(Config)); 226 | } 227 | 228 | //----------------------------------------------------------------------------- 229 | void config_init(void) 230 | { 231 | int index = find_last_entry(); 232 | 233 | flash_unlock(); 234 | 235 | if (index == -1) 236 | { 237 | flash_erase(SECTOR_0_INDEX); 238 | 239 | config_reset(); 240 | 241 | config.count = 0; 242 | config.power_cycles = 0; 243 | config.charge_cycles = 0; 244 | 245 | g_entry_offset = 0; 246 | } 247 | else 248 | { 249 | Config *entry = get_entry(index); 250 | config = *entry; 251 | g_entry_offset = index * ENTRY_SIZE; 252 | } 253 | 254 | config.power_cycles++; 255 | 256 | timer_add(&g_config_timer); 257 | } 258 | 259 | //----------------------------------------------------------------------------- 260 | void config_reset(void) 261 | { 262 | config.magic = MAGIC; 263 | config.size = sizeof(Config); 264 | config.version = VERSION; 265 | 266 | // Keep config.count 267 | // Keep config.power_cycles 268 | // Keep config.charge_cycles 269 | 270 | config.lcd_bl_level = 100; 271 | 272 | config.ac_coupling = false; 273 | config.x10 = false; 274 | 275 | config.trigger_mode = TRIGGER_MODE_AUTO; 276 | config.trigger_edge = TRIGGER_EDGE_RISE; 277 | config.trigger_level = 0; 278 | config.trigger_level_mv = 0; 279 | 280 | config.horizontal_scale = HS_100_us; 281 | config.horizontal_position = 0; 282 | config.horizontal_position_px = 0; 283 | config.horizontal_period = 1; // Dummy value 284 | 285 | config.vertical_scale = VS_200_mV; 286 | config.vertical_position = 0; 287 | config.vertical_position_mv = 0; 288 | config.vertical_mult = 1; // Dummy value 289 | 290 | config.sample_rate_limit = 0; 291 | 292 | config.measure_display = false; 293 | 294 | for (int i = 0; i < ARRAY_SIZE(config.padding); i++) 295 | config.padding[i] = 0; 296 | 297 | config.calib_channel_delta = -5; 298 | config.calib_dac_zero = 2010; 299 | 300 | config.calib_dac_mult[VS_50_mV] = 2308; 301 | config.calib_dac_mult[VS_100_mV] = 4548; 302 | config.calib_dac_mult[VS_200_mV] = 5277; 303 | config.calib_dac_mult[VS_500_mV] = 5384; 304 | config.calib_dac_mult[VS_1_V] = 5160; 305 | config.calib_dac_mult[VS_2_V] = 5082; 306 | config.calib_dac_mult[VS_5_V] = 5542; 307 | config.calib_dac_mult[VS_10_V] = 5630; 308 | 309 | config.calib_vs_mult[VS_50_mV] = 4941; 310 | config.calib_vs_mult[VS_100_mV] = 4808; 311 | config.calib_vs_mult[VS_200_mV] = 8343; 312 | config.calib_vs_mult[VS_500_mV] = 20449; 313 | config.calib_vs_mult[VS_1_V] = 42447; 314 | config.calib_vs_mult[VS_2_V] = 86232; 315 | config.calib_vs_mult[VS_5_V] = 196726; 316 | config.calib_vs_mult[VS_10_V] = 386029; 317 | } 318 | 319 | //----------------------------------------------------------------------------- 320 | void config_task(void) 321 | { 322 | if (flash_erase_task()) 323 | return; 324 | 325 | if (flash_write_task()) 326 | return; 327 | 328 | if (g_config_timer == 0) 329 | { 330 | if (config_changed()) 331 | config_save(); 332 | 333 | g_config_timer = TIMER_INTERVAL; 334 | } 335 | } 336 | 337 | 338 | -------------------------------------------------------------------------------- /include/mpu_armv7.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file mpu_armv7.h 3 | * @brief CMSIS MPU API for Armv7-M MPU 4 | * @version V5.1.0 5 | * @date 08. March 2019 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2017-2019 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef ARM_MPU_ARMV7_H 32 | #define ARM_MPU_ARMV7_H 33 | 34 | #define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes 35 | #define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes 36 | #define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes 37 | #define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes 38 | #define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes 39 | #define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte 40 | #define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes 41 | #define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes 42 | #define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes 43 | #define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes 44 | #define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes 45 | #define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes 46 | #define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes 47 | #define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes 48 | #define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes 49 | #define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte 50 | #define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes 51 | #define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes 52 | #define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes 53 | #define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes 54 | #define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes 55 | #define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes 56 | #define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes 57 | #define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes 58 | #define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes 59 | #define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte 60 | #define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes 61 | #define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes 62 | 63 | #define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access 64 | #define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only 65 | #define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only 66 | #define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access 67 | #define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only 68 | #define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access 69 | 70 | /** MPU Region Base Address Register Value 71 | * 72 | * \param Region The region to be configured, number 0 to 15. 73 | * \param BaseAddress The base address for the region. 74 | */ 75 | #define ARM_MPU_RBAR(Region, BaseAddress) \ 76 | (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ 77 | ((Region) & MPU_RBAR_REGION_Msk) | \ 78 | (MPU_RBAR_VALID_Msk)) 79 | 80 | /** 81 | * MPU Memory Access Attributes 82 | * 83 | * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. 84 | * \param IsShareable Region is shareable between multiple bus masters. 85 | * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. 86 | * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. 87 | */ 88 | #define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ 89 | ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ 90 | (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ 91 | (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ 92 | (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) 93 | 94 | /** 95 | * MPU Region Attribute and Size Register Value 96 | * 97 | * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. 98 | * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. 99 | * \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. 100 | * \param SubRegionDisable Sub-region disable field. 101 | * \param Size Region size of the region to be configured, for example 4K, 8K. 102 | */ 103 | #define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ 104 | ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ 105 | (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ 106 | (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ 107 | (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ 108 | (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ 109 | (((MPU_RASR_ENABLE_Msk)))) 110 | 111 | /** 112 | * MPU Region Attribute and Size Register Value 113 | * 114 | * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. 115 | * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. 116 | * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. 117 | * \param IsShareable Region is shareable between multiple bus masters. 118 | * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. 119 | * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. 120 | * \param SubRegionDisable Sub-region disable field. 121 | * \param Size Region size of the region to be configured, for example 4K, 8K. 122 | */ 123 | #define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ 124 | ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) 125 | 126 | /** 127 | * MPU Memory Access Attribute for strongly ordered memory. 128 | * - TEX: 000b 129 | * - Shareable 130 | * - Non-cacheable 131 | * - Non-bufferable 132 | */ 133 | #define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) 134 | 135 | /** 136 | * MPU Memory Access Attribute for device memory. 137 | * - TEX: 000b (if shareable) or 010b (if non-shareable) 138 | * - Shareable or non-shareable 139 | * - Non-cacheable 140 | * - Bufferable (if shareable) or non-bufferable (if non-shareable) 141 | * 142 | * \param IsShareable Configures the device memory as shareable or non-shareable. 143 | */ 144 | #define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) 145 | 146 | /** 147 | * MPU Memory Access Attribute for normal memory. 148 | * - TEX: 1BBb (reflecting outer cacheability rules) 149 | * - Shareable or non-shareable 150 | * - Cacheable or non-cacheable (reflecting inner cacheability rules) 151 | * - Bufferable or non-bufferable (reflecting inner cacheability rules) 152 | * 153 | * \param OuterCp Configures the outer cache policy. 154 | * \param InnerCp Configures the inner cache policy. 155 | * \param IsShareable Configures the memory as shareable or non-shareable. 156 | */ 157 | #define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U)) 158 | 159 | /** 160 | * MPU Memory Access Attribute non-cacheable policy. 161 | */ 162 | #define ARM_MPU_CACHEP_NOCACHE 0U 163 | 164 | /** 165 | * MPU Memory Access Attribute write-back, write and read allocate policy. 166 | */ 167 | #define ARM_MPU_CACHEP_WB_WRA 1U 168 | 169 | /** 170 | * MPU Memory Access Attribute write-through, no write allocate policy. 171 | */ 172 | #define ARM_MPU_CACHEP_WT_NWA 2U 173 | 174 | /** 175 | * MPU Memory Access Attribute write-back, no write allocate policy. 176 | */ 177 | #define ARM_MPU_CACHEP_WB_NWA 3U 178 | 179 | 180 | /** 181 | * Struct for a single MPU Region 182 | */ 183 | typedef struct { 184 | uint32_t RBAR; //!< The region base address register value (RBAR) 185 | uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR 186 | } ARM_MPU_Region_t; 187 | 188 | /** Enable the MPU. 189 | * \param MPU_Control Default access permissions for unconfigured regions. 190 | */ 191 | __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) 192 | { 193 | MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; 194 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 195 | SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 196 | #endif 197 | __DSB(); 198 | __ISB(); 199 | } 200 | 201 | /** Disable the MPU. 202 | */ 203 | __STATIC_INLINE void ARM_MPU_Disable(void) 204 | { 205 | __DMB(); 206 | #ifdef SCB_SHCSR_MEMFAULTENA_Msk 207 | SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; 208 | #endif 209 | MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; 210 | } 211 | 212 | /** Clear and disable the given MPU region. 213 | * \param rnr Region number to be cleared. 214 | */ 215 | __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) 216 | { 217 | MPU->RNR = rnr; 218 | MPU->RASR = 0U; 219 | } 220 | 221 | /** Configure an MPU region. 222 | * \param rbar Value for RBAR register. 223 | * \param rsar Value for RSAR register. 224 | */ 225 | __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) 226 | { 227 | MPU->RBAR = rbar; 228 | MPU->RASR = rasr; 229 | } 230 | 231 | /** Configure the given MPU region. 232 | * \param rnr Region number to be configured. 233 | * \param rbar Value for RBAR register. 234 | * \param rsar Value for RSAR register. 235 | */ 236 | __STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) 237 | { 238 | MPU->RNR = rnr; 239 | MPU->RBAR = rbar; 240 | MPU->RASR = rasr; 241 | } 242 | 243 | /** Memcopy with strictly ordered memory access, e.g. for register targets. 244 | * \param dst Destination data is copied to. 245 | * \param src Source data is copied from. 246 | * \param len Amount of data words to be copied. 247 | */ 248 | __STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) 249 | { 250 | uint32_t i; 251 | for (i = 0U; i < len; ++i) 252 | { 253 | dst[i] = src[i]; 254 | } 255 | } 256 | 257 | /** Load the given number of MPU regions from a table. 258 | * \param table Pointer to the MPU configuration table. 259 | * \param cnt Amount of regions to be configured. 260 | */ 261 | __STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) 262 | { 263 | const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; 264 | while (cnt > MPU_TYPE_RALIASES) { 265 | ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); 266 | table += MPU_TYPE_RALIASES; 267 | cnt -= MPU_TYPE_RALIASES; 268 | } 269 | ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); 270 | } 271 | 272 | #endif 273 | -------------------------------------------------------------------------------- /lcd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "gd32f4xx.h" 36 | #include "hal_gpio.h" 37 | #include "utils.h" 38 | #include "fonts.h" 39 | #include "lcd.h" 40 | 41 | /*- Definitions -------------------------------------------------------------*/ 42 | HAL_GPIO_PIN(LCD_RST, C, 6) 43 | HAL_GPIO_PIN(LCD_RD, B, 3) 44 | HAL_GPIO_PIN(LCD_WR, B, 4) 45 | HAL_GPIO_PIN(LCD_RS, B, 5) 46 | HAL_GPIO_PIN(LCD_CS, B, 6) 47 | HAL_GPIO_PIN(LCD_BL, B, 0) 48 | // LCD_D[7:0] - PE[7:0] 49 | 50 | // Note: Not all commands are enumerated. here. Read the display datasheet 51 | // for a full list of supported commands. 52 | enum 53 | { 54 | ST7789_NOP = 0x00, 55 | ST7789_SWRESET = 0x01, 56 | ST7789_RDDID = 0x04, 57 | ST7789_RDDST = 0x09, 58 | ST7789_SLPIN = 0x10, 59 | ST7789_SLPOUT = 0x11, 60 | ST7789_DISPOFF = 0x28, 61 | ST7789_DISPON = 0x29, 62 | ST7789_CASET = 0x2a, 63 | ST7789_RASET = 0x2b, 64 | ST7789_RAMWR = 0x2c, 65 | ST7789_RAMRD = 0x2e, 66 | ST7789_MADCTL = 0x36, 67 | ST7789_COLMOD = 0x3a, 68 | ST7789_PORCTRL = 0xb2, 69 | ST7789_GCTRL = 0xb7, 70 | ST7789_VCOMS = 0xbb, 71 | ST7789_PWCTR1 = 0xc0, 72 | ST7789_PWCTR2 = 0xc1, 73 | ST7789_PWCTR3 = 0xc2, 74 | ST7789_PWCTR4 = 0xc3, 75 | ST7789_PWCTR5 = 0xc4, 76 | ST7789_VMCTR1 = 0xc5, 77 | ST7789_FRCTR2 = 0xc6, 78 | ST7789_PWCTRL1 = 0xd0, 79 | }; 80 | 81 | /*- Variables ---------------------------------------------------------------*/ 82 | static const Font *lcd_font = NULL; 83 | static int bg_color[2]; 84 | static int fg_color[2]; 85 | 86 | /*- Implementations ---------------------------------------------------------*/ 87 | 88 | //----------------------------------------------------------------------------- 89 | static inline void lcd_data_set_in(void) 90 | { 91 | GPIOE->CTL &= ~0xffff; 92 | } 93 | 94 | //----------------------------------------------------------------------------- 95 | static inline void lcd_data_set_out(void) 96 | { 97 | GPIOE->CTL |= 0x5555; 98 | } 99 | 100 | //----------------------------------------------------------------------------- 101 | static inline void lcd_data_write(uint8_t value) 102 | { 103 | GPIOE->BOP = (~value << 16) | value; 104 | asm("nop"); 105 | asm("nop"); 106 | asm("nop"); 107 | HAL_GPIO_LCD_WR_clr(); 108 | asm("nop"); 109 | asm("nop"); 110 | asm("nop"); 111 | asm("nop"); 112 | asm("nop"); 113 | asm("nop"); 114 | HAL_GPIO_LCD_WR_set(); 115 | asm("nop"); 116 | asm("nop"); 117 | asm("nop"); 118 | } 119 | 120 | //----------------------------------------------------------------------------- 121 | static inline void lcd_command_write(uint8_t cmd) 122 | { 123 | HAL_GPIO_LCD_RS_clr(); 124 | lcd_data_write(cmd); 125 | HAL_GPIO_LCD_RS_set(); 126 | } 127 | 128 | //----------------------------------------------------------------------------- 129 | static void lcd_cmd(int cmd, int size, uint8_t *data) 130 | { 131 | HAL_GPIO_LCD_CS_clr(); 132 | lcd_command_write(cmd); 133 | 134 | for (int i = 0; i < size; i++) 135 | lcd_data_write(data[i]); 136 | 137 | HAL_GPIO_LCD_CS_set(); 138 | } 139 | 140 | //----------------------------------------------------------------------------- 141 | static void lcd_set_rect(int x, int y, int w, int h) 142 | { 143 | int xe = x + w - 1; 144 | int ye = y + h - 1; 145 | uint8_t buf[4]; 146 | 147 | buf[0] = x >> 8; 148 | buf[1] = x; 149 | buf[2] = xe >> 8; 150 | buf[3] = xe; 151 | lcd_cmd(ST7789_CASET, 4, buf); 152 | 153 | buf[0] = y >> 8; 154 | buf[1] = y; 155 | buf[2] = ye >> 8; 156 | buf[3] = ye; 157 | lcd_cmd(ST7789_RASET, 4, buf); 158 | } 159 | 160 | //----------------------------------------------------------------------------- 161 | void lcd_init(void) 162 | { 163 | HAL_GPIO_LCD_RST_out(); 164 | HAL_GPIO_LCD_RST_set(); 165 | 166 | HAL_GPIO_LCD_CS_out(); 167 | HAL_GPIO_LCD_CS_set(); 168 | 169 | HAL_GPIO_LCD_RD_out(); 170 | HAL_GPIO_LCD_RD_set(); 171 | 172 | HAL_GPIO_LCD_WR_out(); 173 | HAL_GPIO_LCD_WR_set(); 174 | 175 | HAL_GPIO_LCD_RS_out(); 176 | HAL_GPIO_LCD_RS_set(); 177 | 178 | lcd_data_set_in(); 179 | lcd_data_set_out(); 180 | 181 | HAL_GPIO_LCD_RST_clr(); 182 | delay_ms(10); 183 | HAL_GPIO_LCD_RST_set(); 184 | delay_ms(5); 185 | 186 | lcd_cmd(ST7789_DISPOFF, 0, NULL); 187 | lcd_cmd(ST7789_SLPOUT, 0, NULL); 188 | lcd_cmd(ST7789_MADCTL, 1, (uint8_t[]){ 0x60 }); 189 | lcd_cmd(ST7789_COLMOD, 1, (uint8_t[]){ 0x55 }); 190 | lcd_cmd(ST7789_PORCTRL, 5, (uint8_t[]){ 0x08, 0x08, 0x00, 0x22, 0x22 }); 191 | lcd_cmd(ST7789_GCTRL, 1, (uint8_t[]){ 0x35 }); 192 | lcd_cmd(ST7789_VCOMS, 1, (uint8_t[]){ 0x2b }); 193 | lcd_cmd(ST7789_PWCTR1, 1, (uint8_t[]){ 0x2c }); 194 | lcd_cmd(ST7789_PWCTR3, 2, (uint8_t[]){ 0x01, 0xff }); 195 | lcd_cmd(ST7789_PWCTR4, 1, (uint8_t[]){ 0x11 }); 196 | lcd_cmd(ST7789_PWCTR5, 1, (uint8_t[]){ 0x20 }); 197 | lcd_cmd(ST7789_FRCTR2, 1, (uint8_t[]){ 0x0f }); 198 | lcd_cmd(ST7789_PWCTRL1, 2, (uint8_t[]){ 0xa4, 0xa1 }); 199 | lcd_cmd(ST7789_DISPON, 0, NULL); 200 | 201 | lcd_fill_rect(0, 0, LCD_WIDTH, LCD_HEIGHT, 0); 202 | 203 | lcd_set_backlight_level(100); 204 | } 205 | 206 | //----------------------------------------------------------------------------- 207 | static void pwm_start(int level) 208 | { 209 | RCU->APB1EN_b.TIMER2EN = 1; 210 | 211 | TIMER2->CTL0 = 0; 212 | TIMER2->CNT = 0; 213 | TIMER2->PSC = 20; 214 | TIMER2->CAR = 51200; 215 | TIMER2->CH2CV = level * 512; 216 | TIMER2->CHCTL1_Output = (6 << TIMER2_CHCTL1_Output_CH2COMCTL_Pos); 217 | TIMER2->CHCTL2 = TIMER2_CHCTL2_CH2EN_Msk; 218 | TIMER2->CTL0 = TIMER2_CTL0_CEN_Msk; 219 | } 220 | 221 | //----------------------------------------------------------------------------- 222 | static void pwm_stop(void) 223 | { 224 | TIMER2->CTL0 = 0; 225 | } 226 | 227 | //----------------------------------------------------------------------------- 228 | void lcd_set_backlight_level(int level) 229 | { 230 | if (level < 0) 231 | level = 0; 232 | else if (level > 100) 233 | level = 100; 234 | 235 | if (level == 0) 236 | { 237 | HAL_GPIO_LCD_BL_out(); 238 | HAL_GPIO_LCD_BL_clr(); 239 | pwm_stop(); 240 | } 241 | else if (level == 100) 242 | { 243 | HAL_GPIO_LCD_BL_out(); 244 | HAL_GPIO_LCD_BL_set(); 245 | pwm_stop(); 246 | } 247 | else 248 | { 249 | HAL_GPIO_LCD_BL_alt(2); 250 | pwm_start(level); 251 | } 252 | } 253 | 254 | //----------------------------------------------------------------------------- 255 | void lcd_draw_pixel(int x, int y, int color) 256 | { 257 | lcd_set_rect(x, y, 1, 1); 258 | 259 | HAL_GPIO_LCD_CS_clr(); 260 | lcd_command_write(ST7789_RAMWR); 261 | lcd_data_write((color >> 8) & 0xff); 262 | lcd_data_write(color & 0xff); 263 | HAL_GPIO_LCD_CS_set(); 264 | } 265 | 266 | //----------------------------------------------------------------------------- 267 | void lcd_draw_buf(int x, int y, int w, int h, const uint16_t *buf) 268 | { 269 | int size = w * h; 270 | 271 | lcd_set_rect(x, y, w, h); 272 | 273 | HAL_GPIO_LCD_CS_clr(); 274 | lcd_command_write(ST7789_RAMWR); 275 | 276 | for (int i = 0; i < size; i++) 277 | { 278 | lcd_data_write(buf[i] >> 8); 279 | lcd_data_write(buf[i]); 280 | } 281 | 282 | HAL_GPIO_LCD_CS_set(); 283 | } 284 | 285 | //----------------------------------------------------------------------------- 286 | void lcd_draw_image(int x, int y, const Image *image) 287 | { 288 | int size = image->width * image->height; 289 | 290 | lcd_set_rect(x - image->ox, y - image->oy, image->width, image->height); 291 | 292 | HAL_GPIO_LCD_CS_clr(); 293 | lcd_command_write(ST7789_RAMWR); 294 | 295 | for (int i = 0; i < size; i++) 296 | { 297 | lcd_data_write(image->data[i] >> 8); 298 | lcd_data_write(image->data[i]); 299 | } 300 | 301 | HAL_GPIO_LCD_CS_set(); 302 | } 303 | 304 | //----------------------------------------------------------------------------- 305 | void lcd_draw_rect(int x, int y, int w, int h, int color) 306 | { 307 | w -= 1; 308 | h -= 1; 309 | lcd_vline(x, y, y+h, color); 310 | lcd_vline(x+w, y, y+h, color); 311 | lcd_hline(x, x+w, y, color); 312 | lcd_hline(x, x+w, y+h, color); 313 | } 314 | 315 | //----------------------------------------------------------------------------- 316 | void lcd_fill_rect(int x, int y, int w, int h, int color) 317 | { 318 | int size = w * h; 319 | int c0 = (color >> 8) & 0xff; 320 | int c1 = color & 0xff; 321 | 322 | lcd_set_rect(x, y, w, h); 323 | 324 | HAL_GPIO_LCD_CS_clr(); 325 | lcd_command_write(ST7789_RAMWR); 326 | 327 | for (int i = 0; i < size; i++) 328 | { 329 | lcd_data_write(c0); 330 | lcd_data_write(c1); 331 | } 332 | 333 | HAL_GPIO_LCD_CS_set(); 334 | } 335 | 336 | //----------------------------------------------------------------------------- 337 | void lcd_hline(int x0, int x1, int y, int color) 338 | { 339 | lcd_fill_rect(x0, y, x1 - x0 + 1, 1, color); 340 | } 341 | 342 | //----------------------------------------------------------------------------- 343 | void lcd_vline(int x, int y0, int y1, int color) 344 | { 345 | lcd_fill_rect(x, y0, 1, y1 - y0 + 1, color); 346 | } 347 | 348 | //----------------------------------------------------------------------------- 349 | void lcd_set_font(const Font *font) 350 | { 351 | lcd_font = font; 352 | } 353 | 354 | //----------------------------------------------------------------------------- 355 | void lcd_set_color(int bg, int fg) 356 | { 357 | bg_color[0] = (bg >> 8) & 0xff; 358 | bg_color[1] = bg & 0xff; 359 | 360 | fg_color[0] = (fg >> 8) & 0xff; 361 | fg_color[1] = fg & 0xff; 362 | } 363 | 364 | //----------------------------------------------------------------------------- 365 | void lcd_putc(int x, int y, char ch) 366 | { 367 | int size = lcd_font->width * lcd_font->height; 368 | const uint8_t *bitmap; 369 | 370 | lcd_set_rect(x, y, lcd_font->width, lcd_font->height); 371 | 372 | HAL_GPIO_LCD_CS_clr(); 373 | lcd_command_write(ST7789_RAMWR); 374 | 375 | if (ch < FONT_FIRST_CHAR || ch > FONT_LAST_CHAR) 376 | ch = '?'; 377 | 378 | bitmap = lcd_font->data + (ch - FONT_FIRST_CHAR) * lcd_font->pitch; 379 | 380 | for (int i = 0; i < size; i++) 381 | { 382 | int byte = bitmap[i / 8]; 383 | int pixel = (byte >> (i % 8)) & 1; 384 | 385 | if (pixel) 386 | { 387 | lcd_data_write(fg_color[0]); 388 | lcd_data_write(fg_color[1]); 389 | } 390 | else 391 | { 392 | lcd_data_write(bg_color[0]); 393 | lcd_data_write(bg_color[1]); 394 | } 395 | } 396 | 397 | HAL_GPIO_LCD_CS_set(); 398 | } 399 | 400 | //----------------------------------------------------------------------------- 401 | void lcd_puts(int x, int y, const char *str) 402 | { 403 | while (*str) 404 | { 405 | if (FONT_HALF_SPACE == *str) 406 | { 407 | int color = (bg_color[0] << 8) | bg_color[1]; 408 | lcd_fill_rect(x, y, lcd_font->width / 2, lcd_font->height, color); 409 | x += lcd_font->width / 2; 410 | } 411 | else 412 | { 413 | lcd_putc(x, y, *str); 414 | x += lcd_font->width; 415 | } 416 | 417 | str++; 418 | } 419 | } 420 | 421 | 422 | -------------------------------------------------------------------------------- /startup_gd32f4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include "gd32f4xx.h" 31 | 32 | /*- Definitions -------------------------------------------------------------*/ 33 | #define DUMMY __attribute__ ((weak, alias ("irq_handler_dummy"))) 34 | 35 | /*- Prototypes --------------------------------------------------------------*/ 36 | void irq_handler_reset(void); 37 | DUMMY void irq_handler_nmi(void); 38 | DUMMY void irq_handler_hard_fault(void); 39 | DUMMY void irq_handler_mm_fault(void); 40 | DUMMY void irq_handler_bus_fault(void); 41 | DUMMY void irq_handler_usage_fault(void); 42 | DUMMY void irq_handler_sv_call(void); 43 | DUMMY void irq_handler_debug_mon(void); 44 | DUMMY void irq_handler_pend_sv(void); 45 | DUMMY void irq_handler_sys_tick(void); 46 | 47 | DUMMY void irq_handler_wwdgt(void); 48 | DUMMY void irq_handler_lvd(void); 49 | DUMMY void irq_handler_tamper_stamp(void); 50 | DUMMY void irq_handler_rtc_wkup(void); 51 | DUMMY void irq_handler_fmc(void); 52 | DUMMY void irq_handler_rcu_ctc(void); 53 | DUMMY void irq_handler_exti0(void); 54 | DUMMY void irq_handler_exti1(void); 55 | DUMMY void irq_handler_exti2(void); 56 | DUMMY void irq_handler_exti3(void); 57 | DUMMY void irq_handler_exti4(void); 58 | DUMMY void irq_handler_dma0_channel0(void); 59 | DUMMY void irq_handler_dma0_channel1(void); 60 | DUMMY void irq_handler_dma0_channel2(void); 61 | DUMMY void irq_handler_dma0_channel3(void); 62 | DUMMY void irq_handler_dma0_channel4(void); 63 | DUMMY void irq_handler_dma0_channel5(void); 64 | DUMMY void irq_handler_dma0_channel6(void); 65 | DUMMY void irq_handler_adc(void); 66 | DUMMY void irq_handler_can0_tx(void); 67 | DUMMY void irq_handler_can0_rx0(void); 68 | DUMMY void irq_handler_can0_rx1(void); 69 | DUMMY void irq_handler_can0_ewmc(void); 70 | DUMMY void irq_handler_exti9_5(void); 71 | DUMMY void irq_handler_timer0_brk_timer8(void); 72 | DUMMY void irq_handler_timer0_up_timer9(void); 73 | DUMMY void irq_handler_timer0_trg_cmt_timer10(void); 74 | DUMMY void irq_handler_timer0_cc(void); 75 | DUMMY void irq_handler_timer1(void); 76 | DUMMY void irq_handler_timer2(void); 77 | DUMMY void irq_handler_timer3(void); 78 | DUMMY void irq_handler_i2c0_ev(void); 79 | DUMMY void irq_handler_i2c0_er(void); 80 | DUMMY void irq_handler_i2c1_ev(void); 81 | DUMMY void irq_handler_i2c1_er(void); 82 | DUMMY void irq_handler_spi0(void); 83 | DUMMY void irq_handler_spi1(void); 84 | DUMMY void irq_handler_usart0(void); 85 | DUMMY void irq_handler_usart1(void); 86 | DUMMY void irq_handler_usart2(void); 87 | DUMMY void irq_handler_exti15_10(void); 88 | DUMMY void irq_handler_rtc_alarm(void); 89 | DUMMY void irq_handler_otg_fs_wkup(void); 90 | DUMMY void irq_handler_timer7_brk_timer11(void); 91 | DUMMY void irq_handler_timer7_up_timer12(void); 92 | DUMMY void irq_handler_timer7_trg_cmt_timer13(void); 93 | DUMMY void irq_handler_timer7_cc(void); 94 | DUMMY void irq_handler_dma0_channel7(void); 95 | DUMMY void irq_handler_exmc(void); 96 | DUMMY void irq_handler_sdio(void); 97 | DUMMY void irq_handler_timer4(void); 98 | DUMMY void irq_handler_spi2(void); 99 | DUMMY void irq_handler_uart3(void); 100 | DUMMY void irq_handler_uart4(void); 101 | DUMMY void irq_handler_timer5_dac(void); 102 | DUMMY void irq_handler_timer6(void); 103 | DUMMY void irq_handler_dma1_channel0(void); 104 | DUMMY void irq_handler_dma1_channel1(void); 105 | DUMMY void irq_handler_dma1_channel2(void); 106 | DUMMY void irq_handler_dma1_channel3(void); 107 | DUMMY void irq_handler_dma1_channel4(void); 108 | DUMMY void irq_handler_enet(void); 109 | DUMMY void irq_handler_enet_wkup(void); 110 | DUMMY void irq_handler_can1_tx(void); 111 | DUMMY void irq_handler_can1_rx0(void); 112 | DUMMY void irq_handler_can1_rx1(void); 113 | DUMMY void irq_handler_can1_ewmc(void); 114 | DUMMY void irq_handler_otg_fs(void); 115 | DUMMY void irq_handler_dma1_channel5(void); 116 | DUMMY void irq_handler_dma1_channel6(void); 117 | DUMMY void irq_handler_dma1_channel7(void); 118 | DUMMY void irq_handler_usart5(void); 119 | DUMMY void irq_handler_i2c2_ev(void); 120 | DUMMY void irq_handler_i2c2_er(void); 121 | DUMMY void irq_handler_usbhs_ep1_out(void); 122 | DUMMY void irq_handler_usbhs_ep1_in(void); 123 | DUMMY void irq_handler_usbhs_wkup(void); 124 | DUMMY void irq_handler_usbhs(void); 125 | DUMMY void irq_handler_dci(void); 126 | DUMMY void irq_handler_trng(void); 127 | DUMMY void irq_handler_fpu(void); 128 | DUMMY void irq_handler_uart6(void); 129 | DUMMY void irq_handler_uart7(void); 130 | DUMMY void irq_handler_spi3(void); 131 | DUMMY void irq_handler_spi4(void); 132 | DUMMY void irq_handler_spi5(void); 133 | DUMMY void irq_handler_tli(void); 134 | DUMMY void irq_handler_tli_er(void); 135 | DUMMY void irq_handler_ipa(void); 136 | 137 | int main(void); 138 | 139 | extern void _stack_top(void); 140 | extern unsigned int _etext; 141 | extern unsigned int _data; 142 | extern unsigned int _edata; 143 | extern unsigned int _bss; 144 | extern unsigned int _ebss; 145 | 146 | /*- Variables ---------------------------------------------------------------*/ 147 | 148 | //----------------------------------------------------------------------------- 149 | __attribute__ ((used, section(".vectors"))) 150 | void (* const vectors[])(void) = 151 | { 152 | &_stack_top, // 0 - Initial Stack Pointer Value 153 | 154 | // Cortex-M4 handlers 155 | irq_handler_reset, // 1 - Reset 156 | irq_handler_nmi, // 2 - NMI 157 | irq_handler_hard_fault, // 3 - Hard Fault 158 | irq_handler_mm_fault, // 4 - MM Fault 159 | irq_handler_bus_fault, // 5 - Bus Fault 160 | irq_handler_usage_fault, // 6 - Usage Fault 161 | 0, // 7 - Reserved 162 | 0, // 8 - Reserved 163 | 0, // 9 - Reserved 164 | 0, // 10 - Reserved 165 | irq_handler_sv_call, // 11 - SVCall 166 | irq_handler_debug_mon, // 12 - Debug 167 | 0, // 13 - Reserved 168 | irq_handler_pend_sv, // 14 - PendSV 169 | irq_handler_sys_tick, // 15 - SysTick 170 | 171 | // Peripheral handlers 172 | irq_handler_wwdgt, // 0 - Window Watchdog Timer 173 | irq_handler_lvd, // 1 - LVD from EXTI 174 | irq_handler_tamper_stamp, // 2 - RTC Tamper and TimeStamp from EXTI 175 | irq_handler_rtc_wkup, // 3 - RTC Wakeup from EXTI 176 | irq_handler_fmc, // 4 - FMC 177 | irq_handler_rcu_ctc, // 5 - RCU and CTC 178 | irq_handler_exti0, // 6 - EXTI Line 0 179 | irq_handler_exti1, // 7 - EXTI Line 1 180 | irq_handler_exti2, // 8 - EXTI Line 2 181 | irq_handler_exti3, // 9 - EXTI Line 3 182 | irq_handler_exti4, // 10 - EXTI Line 4 183 | irq_handler_dma0_channel0, // 11 - DMA0 Channel 0 184 | irq_handler_dma0_channel1, // 12 - DMA0 Channel 1 185 | irq_handler_dma0_channel2, // 13 - DMA0 Channel 2 186 | irq_handler_dma0_channel3, // 14 - DMA0 Channel 3 187 | irq_handler_dma0_channel4, // 15 - DMA0 Channel 4 188 | irq_handler_dma0_channel5, // 16 - DMA0 Channel 5 189 | irq_handler_dma0_channel6, // 17 - DMA0 Channel 6 190 | irq_handler_adc, // 18 - ADC 191 | irq_handler_can0_tx, // 19 - CAN0 TX 192 | irq_handler_can0_rx0, // 20 - CAN0 RX0 193 | irq_handler_can0_rx1, // 21 - CAN0 RX1 194 | irq_handler_can0_ewmc, // 22 - CAN0 EWMC 195 | irq_handler_exti9_5, // 23 - EXTI Line [9:5] 196 | irq_handler_timer0_brk_timer8, // 24 - TIMER0 Break and TIMER8 197 | irq_handler_timer0_up_timer9, // 25 - TIMER0 Update and TIMER9 198 | irq_handler_timer0_trg_cmt_timer10, // 26 - TIMER0 Trigger and Channel Commutation and TIMER10 199 | irq_handler_timer0_cc, // 27 - TIMER0 Capture Compare 200 | irq_handler_timer1, // 28 - TIMER1 201 | irq_handler_timer2, // 29 - TIMER2 202 | irq_handler_timer3, // 30 - TIMER3 203 | irq_handler_i2c0_ev, // 31 - I2C0 Event 204 | irq_handler_i2c0_er, // 32 - I2C0 Error 205 | irq_handler_i2c1_ev, // 33 - I2C1 Event 206 | irq_handler_i2c1_er, // 34 - I2C1 Error 207 | irq_handler_spi0, // 35 - SPI0 208 | irq_handler_spi1, // 36 - SPI1 209 | irq_handler_usart0, // 37 - USART0 210 | irq_handler_usart1, // 38 - USART1 211 | irq_handler_usart2, // 39 - USART2 212 | irq_handler_exti15_10, // 40 - EXTI Line [15:10] 213 | irq_handler_rtc_alarm, // 41 - RTC Alarm from EXTI 214 | irq_handler_otg_fs_wkup, // 42 - USBFS Wakeup from EXTI 215 | irq_handler_timer7_brk_timer11, // 43 - TIMER7 Break and TIMER11 216 | irq_handler_timer7_up_timer12, // 44 - TIMER7 Update and TIMER12 217 | irq_handler_timer7_trg_cmt_timer13, // 45 - TIMER7 Trigger and Channel Commutation and TIMER13 218 | irq_handler_timer7_cc, // 46 - TIMER7 Capture Compare 219 | irq_handler_dma0_channel7, // 47 - DMA0 Channel 7 220 | irq_handler_exmc, // 48 - EXMC 221 | irq_handler_sdio, // 49 - SDIO 222 | irq_handler_timer4, // 50 - TIMER4 223 | irq_handler_spi2, // 51 - SPI2 224 | irq_handler_uart3, // 52 - UART3 225 | irq_handler_uart4, // 53 - UART4 226 | irq_handler_timer5_dac, // 54 - TIMER5, DAC0, DAC1 Underrun Error 227 | irq_handler_timer6, // 55 - TIMER6 228 | irq_handler_dma1_channel0, // 56 - DMA1 Channel 0 229 | irq_handler_dma1_channel1, // 57 - DMA1 Channel 1 230 | irq_handler_dma1_channel2, // 58 - DMA1 Channel 2 231 | irq_handler_dma1_channel3, // 59 - DMA1 Channel 3 232 | irq_handler_dma1_channel4, // 60 - DMA1 Channel 4 233 | irq_handler_enet, // 61 - Ethernet 234 | irq_handler_enet_wkup, // 62 - Ethernet Wakeup from EXTI 235 | irq_handler_can1_tx, // 63 - CAN1 TX 236 | irq_handler_can1_rx0, // 64 - CAN1 RX0 237 | irq_handler_can1_rx1, // 65 - CAN1 RX1 238 | irq_handler_can1_ewmc, // 66 - CAN1 EWMC 239 | irq_handler_otg_fs, // 67 - USBFS 240 | irq_handler_dma1_channel5, // 68 - DMA1 Channel 5 241 | irq_handler_dma1_channel6, // 69 - DMA1 Channel 6 242 | irq_handler_dma1_channel7, // 70 - DMA1 Channel 7 243 | irq_handler_usart5, // 71 - USART5 244 | irq_handler_i2c2_ev, // 72 - I2C2 Event 245 | irq_handler_i2c2_er, // 73 - I2C2 Error 246 | irq_handler_usbhs_ep1_out, // 74 - USBHS Endpoint 1 Out 247 | irq_handler_usbhs_ep1_in, // 75 - USBHS Endpoint 1 In 248 | irq_handler_usbhs_wkup, // 76 - USBHS Wakeup from EXTI 249 | irq_handler_usbhs, // 77 - USBHS 250 | irq_handler_dci, // 78 - DCI 251 | 0, // 79 - Reserved 252 | irq_handler_trng, // 80 - TRNG 253 | irq_handler_fpu, // 81 - FPU 254 | irq_handler_uart6, // 82 - UART6 255 | irq_handler_uart7, // 83 - UART7 256 | irq_handler_spi3, // 84 - SPI3 257 | irq_handler_spi4, // 85 - SPI4 258 | irq_handler_spi5, // 86 - SPI5 259 | 0, // 87 - Reserved 260 | irq_handler_tli, // 88 - TLI 261 | irq_handler_tli_er, // 89 - TLI Error 262 | irq_handler_ipa, // 90 - IPA 263 | }; 264 | 265 | /*- Implementations ---------------------------------------------------------*/ 266 | 267 | //----------------------------------------------------------------------------- 268 | void irq_handler_reset(void) 269 | { 270 | unsigned int *src, *dst; 271 | 272 | src = &_etext; 273 | dst = &_data; 274 | while (dst < &_edata) 275 | *dst++ = *src++; 276 | 277 | dst = &_bss; 278 | while (dst < &_ebss) 279 | *dst++ = 0; 280 | 281 | // Enable FPU 282 | SCB->CPACR |= (0xf << 20); 283 | __DSB(); 284 | __ISB(); 285 | 286 | SCB->VTOR = (uint32_t)vectors; 287 | 288 | main(); 289 | 290 | while (1); 291 | } 292 | 293 | //----------------------------------------------------------------------------- 294 | void irq_handler_dummy(void) 295 | { 296 | while (1); 297 | } 298 | 299 | -------------------------------------------------------------------------------- /buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include "config.h" 32 | #include "buffer.h" 33 | 34 | /*- Implementations ---------------------------------------------------------*/ 35 | 36 | //----------------------------------------------------------------------------- 37 | void buffer_decimate(uint32_t dst, uint32_t src, uint32_t count, uint32_t offset) 38 | { 39 | asm volatile (R"asm( 40 | b0 .req r5 41 | b1 .req r6 42 | b2 .req r7 43 | b3 .req r8 44 | b4 .req r9 45 | b5 .req r10 46 | b6 .req r11 47 | b7 .req r12 48 | 49 | cmp %[offset], #1 50 | beq 8f 51 | cmp %[offset], #2 52 | beq 16f 53 | cmp %[offset], #3 54 | beq 24f 55 | 56 | 0: 57 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 58 | ubfx b1, b1, #0, #8 59 | bfi b0, b1, #8, #8 60 | ubfx b2, b2, #0, #8 61 | bfi b0, b2, #16, #8 62 | ubfx b3, b3, #0, #8 63 | bfi b0, b3, #24, #8 64 | ubfx b5, b5, #0, #8 65 | bfi b4, b5, #8, #8 66 | ubfx b6, b6, #0, #8 67 | bfi b4, b6, #16, #8 68 | ubfx b7, b7, #0, #8 69 | bfi b4, b7, #24, #8 70 | stm %[dst]!, { b0, b4 } 71 | subs %[count], #32 72 | bne 0b 73 | b 99f 74 | 75 | 8: 76 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 77 | ubfx b0, b0, #8, #8 78 | bfi b1, b0, #0, #8 79 | ubfx b2, b2, #8, #8 80 | bfi b1, b2, #16, #8 81 | ubfx b3, b3, #8, #8 82 | bfi b1, b3, #24, #8 83 | ubfx b4, b4, #8, #8 84 | bfi b5, b4, #0, #8 85 | ubfx b6, b6, #8, #8 86 | bfi b5, b6, #16, #8 87 | ubfx b7, b7, #8, #8 88 | bfi b5, b7, #24, #8 89 | stm %[dst]!, { b1, b5 } 90 | subs %[count], #32 91 | bne 8b 92 | b 99f 93 | 94 | 16: 95 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 96 | ubfx b0, b0, #16, #8 97 | bfi b2, b0, #0, #8 98 | ubfx b1, b1, #16, #8 99 | bfi b2, b1, #8, #8 100 | ubfx b3, b3, #16, #8 101 | bfi b2, b3, #24, #8 102 | ubfx b4, b4, #16, #8 103 | bfi b6, b4, #0, #8 104 | ubfx b5, b5, #16, #8 105 | bfi b6, b5, #8, #8 106 | ubfx b7, b7, #16, #8 107 | bfi b6, b7, #24, #8 108 | stm %[dst]!, { b2, b6 } 109 | subs %[count], #32 110 | bne 16b 111 | b 99f 112 | 113 | 24: 114 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 115 | ubfx b0, b0, #24, #8 116 | bfi b3, b0, #0, #8 117 | ubfx b1, b1, #24, #8 118 | bfi b3, b1, #8, #8 119 | ubfx b2, b2, #24, #8 120 | bfi b3, b2, #16, #8 121 | ubfx b4, b4, #24, #8 122 | bfi b7, b4, #0, #8 123 | ubfx b5, b5, #24, #8 124 | bfi b7, b5, #8, #8 125 | ubfx b6, b6, #24, #8 126 | bfi b7, b6, #16, #8 127 | stm %[dst]!, { b3, b7 } 128 | subs %[count], #32 129 | bne 24b 130 | 131 | 99: 132 | .unreq b0 133 | .unreq b1 134 | .unreq b2 135 | .unreq b3 136 | .unreq b4 137 | .unreq b5 138 | .unreq b6 139 | .unreq b7 140 | )asm" 141 | : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count) 142 | : [offset] "r" (offset) 143 | : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" 144 | ); 145 | } 146 | 147 | //----------------------------------------------------------------------------- 148 | static void buffer_reverse_add(uint32_t buf, uint32_t count, uint32_t delta) 149 | { 150 | asm volatile (R"asm( 151 | t .req r4 152 | b0 .req r5 153 | b1 .req r6 154 | b2 .req r7 155 | b3 .req r8 156 | b4 .req r9 157 | b5 .req r10 158 | b6 .req r11 159 | b7 .req r12 160 | 161 | // Generate APSR.GE bits for select operation 162 | mov b0, #0 163 | mov b1, #0xff00ff00 164 | sadd8 b0, b0, b1 165 | 166 | 0: 167 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 168 | 169 | rbit t, b0 170 | ror t, #8 171 | sel b0, b0, t 172 | uqadd8 b0, b0, %[delta] 173 | 174 | rbit t, b1 175 | ror t, #8 176 | sel b1, b1, t 177 | uqadd8 b1, b1, %[delta] 178 | 179 | rbit t, b2 180 | ror t, #8 181 | sel b2, b2, t 182 | uqadd8 b2, b2, %[delta] 183 | 184 | rbit t, b3 185 | ror t, #8 186 | sel b3, b3, t 187 | uqadd8 b3, b3, %[delta] 188 | 189 | rbit t, b4 190 | ror t, #8 191 | sel b4, b4, t 192 | uqadd8 b4, b4, %[delta] 193 | 194 | rbit t, b5 195 | ror t, #8 196 | sel b5, b5, t 197 | uqadd8 b5, b5, %[delta] 198 | 199 | rbit t, b6 200 | ror t, #8 201 | sel b6, b6, t 202 | uqadd8 b6, b6, %[delta] 203 | 204 | rbit t, b7 205 | ror t, #8 206 | sel b7, b7, t 207 | uqadd8 b7, b7, %[delta] 208 | 209 | stm %[dst]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 210 | subs %[count], #32 211 | bne 0b 212 | 213 | .unreq t 214 | .unreq b0 215 | .unreq b1 216 | .unreq b2 217 | .unreq b3 218 | .unreq b4 219 | .unreq b5 220 | .unreq b6 221 | .unreq b7 222 | )asm" 223 | : [src] "+r" (buf), [dst] "+r" (buf), [count] "+r" (count) 224 | : [delta] "r" (delta) 225 | : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" 226 | ); 227 | } 228 | 229 | //----------------------------------------------------------------------------- 230 | static void buffer_reverse_sub(uint32_t buf, uint32_t count, uint32_t delta) 231 | { 232 | asm volatile (R"asm( 233 | t .req r4 234 | b0 .req r5 235 | b1 .req r6 236 | b2 .req r7 237 | b3 .req r8 238 | b4 .req r9 239 | b5 .req r10 240 | b6 .req r11 241 | b7 .req r12 242 | 243 | // Generate APSR.GE bits for select operation 244 | mov b0, #0 245 | mov b1, #0xff00ff00 246 | sadd8 b0, b0, b1 247 | 248 | 0: 249 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 250 | 251 | rbit t, b0 252 | ror t, #8 253 | sel b0, b0, t 254 | uqsub8 b0, b0, %[delta] 255 | 256 | rbit t, b1 257 | ror t, #8 258 | sel b1, b1, t 259 | uqsub8 b1, b1, %[delta] 260 | 261 | rbit t, b2 262 | ror t, #8 263 | sel b2, b2, t 264 | uqsub8 b2, b2, %[delta] 265 | 266 | rbit t, b3 267 | ror t, #8 268 | sel b3, b3, t 269 | uqsub8 b3, b3, %[delta] 270 | 271 | rbit t, b4 272 | ror t, #8 273 | sel b4, b4, t 274 | uqsub8 b4, b4, %[delta] 275 | 276 | rbit t, b5 277 | ror t, #8 278 | sel b5, b5, t 279 | uqsub8 b5, b5, %[delta] 280 | 281 | rbit t, b6 282 | ror t, #8 283 | sel b6, b6, t 284 | uqsub8 b6, b6, %[delta] 285 | 286 | rbit t, b7 287 | ror t, #8 288 | sel b7, b7, t 289 | uqsub8 b7, b7, %[delta] 290 | 291 | stm %[dst]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 292 | subs %[count], #32 293 | bne 0b 294 | 295 | .unreq t 296 | .unreq b0 297 | .unreq b1 298 | .unreq b2 299 | .unreq b3 300 | .unreq b4 301 | .unreq b5 302 | .unreq b6 303 | .unreq b7 304 | )asm" 305 | : [src] "+r" (buf), [dst] "+r" (buf), [count] "+r" (count) 306 | : [delta] "r" (delta) 307 | : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" 308 | ); 309 | } 310 | 311 | 312 | //----------------------------------------------------------------------------- 313 | void buffer_reverse(uint32_t buf, uint32_t count) 314 | { 315 | uint32_t delta; 316 | 317 | if (config.calib_channel_delta < 0) 318 | { 319 | delta = -config.calib_channel_delta; 320 | delta = (delta << 24) | (delta << 8); 321 | buffer_reverse_sub(buf, count, delta); 322 | } 323 | else 324 | { 325 | delta = config.calib_channel_delta; 326 | delta = (delta << 24) | (delta << 8); 327 | buffer_reverse_add(buf, count, delta); 328 | } 329 | } 330 | 331 | //----------------------------------------------------------------------------- 332 | static void buffer_decimate_reverse_add(uint32_t dst, uint32_t src, uint32_t count, uint32_t offset, uint32_t delta) 333 | { 334 | asm volatile (R"asm( 335 | b0 .req r5 336 | b1 .req r6 337 | b2 .req r7 338 | b3 .req r8 339 | b4 .req r9 340 | b5 .req r10 341 | b6 .req r11 342 | b7 .req r12 343 | 344 | cmp %[offset], #3 345 | beq 16f 346 | 347 | 8: 348 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 349 | rbit b0, b0 350 | rbit b1, b1 351 | rbit b2, b2 352 | rbit b3, b3 353 | rbit b4, b4 354 | rbit b5, b5 355 | rbit b6, b6 356 | rbit b7, b7 357 | ubfx b0, b0, #16, #8 358 | bfi b2, b0, #0, #8 359 | ubfx b1, b1, #16, #8 360 | bfi b2, b1, #8, #8 361 | ubfx b3, b3, #16, #8 362 | bfi b2, b3, #24, #8 363 | ubfx b4, b4, #16, #8 364 | bfi b6, b4, #0, #8 365 | ubfx b5, b5, #16, #8 366 | bfi b6, b5, #8, #8 367 | ubfx b7, b7, #16, #8 368 | bfi b6, b7, #24, #8 369 | uqadd8 b2, b2, %[delta] 370 | uqadd8 b6, b6, %[delta] 371 | stm %[dst]!, { b2, b6 } 372 | subs %[count], #32 373 | bne 8b 374 | b 99f 375 | 376 | 16: 377 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 378 | rbit b0, b0 379 | rbit b1, b1 380 | rbit b2, b2 381 | rbit b3, b3 382 | rbit b4, b4 383 | rbit b5, b5 384 | rbit b6, b6 385 | rbit b7, b7 386 | ubfx b1, b1, #0, #8 387 | bfi b0, b1, #8, #8 388 | ubfx b2, b2, #0, #8 389 | bfi b0, b2, #16, #8 390 | ubfx b3, b3, #0, #8 391 | bfi b0, b3, #24, #8 392 | ubfx b5, b5, #0, #8 393 | bfi b4, b5, #8, #8 394 | ubfx b6, b6, #0, #8 395 | bfi b4, b6, #16, #8 396 | ubfx b7, b7, #0, #8 397 | bfi b4, b7, #24, #8 398 | uqadd8 b0, b0, %[delta] 399 | uqadd8 b4, b4, %[delta] 400 | stm %[dst]!, { b0, b4 } 401 | subs %[count], #32 402 | bne 16b 403 | 404 | 99: 405 | .unreq b0 406 | .unreq b1 407 | .unreq b2 408 | .unreq b3 409 | .unreq b4 410 | .unreq b5 411 | .unreq b6 412 | .unreq b7 413 | )asm" 414 | : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count) 415 | : [offset] "r" (offset), [delta] "r" (delta) 416 | : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" 417 | ); 418 | } 419 | 420 | //----------------------------------------------------------------------------- 421 | static void buffer_decimate_reverse_sub(uint32_t dst, uint32_t src, uint32_t count, uint32_t offset, uint32_t delta) 422 | { 423 | asm volatile (R"asm( 424 | b0 .req r5 425 | b1 .req r6 426 | b2 .req r7 427 | b3 .req r8 428 | b4 .req r9 429 | b5 .req r10 430 | b6 .req r11 431 | b7 .req r12 432 | 433 | cmp %[offset], #3 434 | beq 16f 435 | 436 | 8: 437 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 438 | rbit b0, b0 439 | rbit b1, b1 440 | rbit b2, b2 441 | rbit b3, b3 442 | rbit b4, b4 443 | rbit b5, b5 444 | rbit b6, b6 445 | rbit b7, b7 446 | ubfx b0, b0, #16, #8 447 | bfi b2, b0, #0, #8 448 | ubfx b1, b1, #16, #8 449 | bfi b2, b1, #8, #8 450 | ubfx b3, b3, #16, #8 451 | bfi b2, b3, #24, #8 452 | ubfx b4, b4, #16, #8 453 | bfi b6, b4, #0, #8 454 | ubfx b5, b5, #16, #8 455 | bfi b6, b5, #8, #8 456 | ubfx b7, b7, #16, #8 457 | bfi b6, b7, #24, #8 458 | uqsub8 b2, b2, %[delta] 459 | uqsub8 b6, b6, %[delta] 460 | stm %[dst]!, { b2, b6 } 461 | subs %[count], #32 462 | bne 8b 463 | b 99f 464 | 465 | 16: 466 | ldm %[src]!, { b0, b1, b2, b3, b4, b5, b6, b7 } 467 | rbit b0, b0 468 | rbit b1, b1 469 | rbit b2, b2 470 | rbit b3, b3 471 | rbit b4, b4 472 | rbit b5, b5 473 | rbit b6, b6 474 | rbit b7, b7 475 | ubfx b1, b1, #0, #8 476 | bfi b0, b1, #8, #8 477 | ubfx b2, b2, #0, #8 478 | bfi b0, b2, #16, #8 479 | ubfx b3, b3, #0, #8 480 | bfi b0, b3, #24, #8 481 | ubfx b5, b5, #0, #8 482 | bfi b4, b5, #8, #8 483 | ubfx b6, b6, #0, #8 484 | bfi b4, b6, #16, #8 485 | ubfx b7, b7, #0, #8 486 | bfi b4, b7, #24, #8 487 | uqsub8 b0, b0, %[delta] 488 | uqsub8 b4, b4, %[delta] 489 | stm %[dst]!, { b0, b4 } 490 | subs %[count], #32 491 | bne 16b 492 | 493 | 99: 494 | .unreq b0 495 | .unreq b1 496 | .unreq b2 497 | .unreq b3 498 | .unreq b4 499 | .unreq b5 500 | .unreq b6 501 | .unreq b7 502 | )asm" 503 | : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count) 504 | : [offset] "r" (offset), [delta] "r" (delta) 505 | : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" 506 | ); 507 | } 508 | 509 | //----------------------------------------------------------------------------- 510 | void buffer_decimate_reverse(uint32_t dst, uint32_t src, uint32_t count, uint32_t offset) 511 | { 512 | uint32_t delta; 513 | 514 | if (config.calib_channel_delta < 0) 515 | { 516 | delta = -config.calib_channel_delta; 517 | delta = (delta << 24) | (delta << 16) | (delta << 8) | delta; 518 | buffer_decimate_reverse_sub(dst, src, count, offset, delta); 519 | } 520 | else 521 | { 522 | delta = config.calib_channel_delta; 523 | delta = (delta << 24) | (delta << 16) | (delta << 8) | delta; 524 | buffer_decimate_reverse_add(dst, src, count, offset, delta); 525 | } 526 | } 527 | 528 | -------------------------------------------------------------------------------- /fonts.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include "fonts.h" 31 | 32 | /*- Constants ---------------------------------------------------------------*/ 33 | 34 | // --- 6x8 --- 35 | const Font font_6x8 = 36 | { 37 | .width = 6, 38 | .height = 8, 39 | .pitch = 6, 40 | .data = { 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " " 42 | 0x04, 0x41, 0x10, 0x04, 0x40, 0x00, // "!" 43 | 0x8a, 0xa2, 0x00, 0x00, 0x00, 0x00, // """ 44 | 0x8a, 0xf2, 0x29, 0x9f, 0xa2, 0x00, // "#" 45 | 0x84, 0x57, 0x38, 0xd4, 0x43, 0x00, // "$" 46 | 0xc3, 0x84, 0x10, 0x42, 0x86, 0x01, // "%" 47 | 0x46, 0x52, 0x08, 0x55, 0x62, 0x01, // "&" 48 | 0x06, 0x21, 0x00, 0x00, 0x00, 0x00, // "'" 49 | 0x08, 0x21, 0x08, 0x02, 0x81, 0x00, // "(" 50 | 0x02, 0x81, 0x20, 0x08, 0x21, 0x00, // ")" 51 | 0x80, 0x42, 0x7c, 0x84, 0x02, 0x00, // "*" 52 | 0x00, 0x41, 0x7c, 0x04, 0x01, 0x00, // "+" 53 | 0x00, 0x00, 0x00, 0x06, 0x21, 0x00, // "," 54 | 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, // "-" 55 | 0x00, 0x00, 0x00, 0x80, 0x61, 0x00, // "." 56 | 0x00, 0x84, 0x10, 0x42, 0x00, 0x00, // "/" 57 | 0x4e, 0x94, 0x55, 0x53, 0xe4, 0x00, // "0" 58 | 0x84, 0x41, 0x10, 0x04, 0xe1, 0x00, // "1" 59 | 0x4e, 0x04, 0x21, 0x84, 0xf0, 0x01, // "2" 60 | 0x1f, 0x42, 0x20, 0x50, 0xe4, 0x00, // "3" 61 | 0x08, 0xa3, 0x24, 0x1f, 0x82, 0x00, // "4" 62 | 0x5f, 0xf0, 0x40, 0x50, 0xe4, 0x00, // "5" 63 | 0x8c, 0x10, 0x3c, 0x51, 0xe4, 0x00, // "6" 64 | 0x1f, 0x84, 0x10, 0x82, 0x20, 0x00, // "7" 65 | 0x4e, 0x14, 0x39, 0x51, 0xe4, 0x00, // "8" 66 | 0x4e, 0x14, 0x79, 0x10, 0x62, 0x00, // "9" 67 | 0x80, 0x61, 0x00, 0x86, 0x01, 0x00, // ":" 68 | 0x80, 0x61, 0x00, 0x06, 0x21, 0x00, // ";" 69 | 0x10, 0x42, 0x08, 0x04, 0x02, 0x01, // "<" 70 | 0x00, 0xf0, 0x01, 0x1f, 0x00, 0x00, // "=" 71 | 0x81, 0x40, 0x20, 0x84, 0x10, 0x00, // ">" 72 | 0x4e, 0x04, 0x21, 0x04, 0x40, 0x00, // "?" 73 | 0x4e, 0x04, 0x59, 0x55, 0xe5, 0x00, // "@" 74 | 0x4e, 0x14, 0x45, 0x5f, 0x14, 0x01, // "A" 75 | 0x4f, 0x14, 0x3d, 0x51, 0xf4, 0x00, // "B" 76 | 0x4e, 0x14, 0x04, 0x41, 0xe4, 0x00, // "C" 77 | 0x47, 0x12, 0x45, 0x51, 0x72, 0x00, // "D" 78 | 0x5f, 0x10, 0x3c, 0x41, 0xf0, 0x01, // "E" 79 | 0x5f, 0x10, 0x1c, 0x41, 0x10, 0x00, // "F" 80 | 0x4e, 0x14, 0x04, 0x59, 0xe4, 0x00, // "G" 81 | 0x51, 0x14, 0x7d, 0x51, 0x14, 0x01, // "H" 82 | 0x0e, 0x41, 0x10, 0x04, 0xe1, 0x00, // "I" 83 | 0x1c, 0x82, 0x20, 0x48, 0x62, 0x00, // "J" 84 | 0x51, 0x52, 0x0c, 0x45, 0x12, 0x01, // "K" 85 | 0x41, 0x10, 0x04, 0x41, 0xf0, 0x01, // "L" 86 | 0xd1, 0x56, 0x45, 0x51, 0x14, 0x01, // "M" 87 | 0x51, 0x34, 0x55, 0x59, 0x14, 0x01, // "N" 88 | 0x4e, 0x14, 0x45, 0x51, 0xe4, 0x00, // "O" 89 | 0x4f, 0x14, 0x3d, 0x41, 0x10, 0x00, // "P" 90 | 0x4e, 0x14, 0x45, 0x55, 0x62, 0x01, // "Q" 91 | 0x4f, 0x14, 0x3d, 0x45, 0x12, 0x01, // "R" 92 | 0x5e, 0x10, 0x38, 0x10, 0xf4, 0x00, // "S" 93 | 0x1f, 0x41, 0x10, 0x04, 0x41, 0x00, // "T" 94 | 0x51, 0x14, 0x45, 0x51, 0xe4, 0x00, // "U" 95 | 0x51, 0x14, 0x45, 0x91, 0x42, 0x00, // "V" 96 | 0x51, 0x14, 0x55, 0xd5, 0x16, 0x01, // "W" 97 | 0x51, 0xa4, 0x10, 0x4a, 0x14, 0x01, // "X" 98 | 0x51, 0xa4, 0x10, 0x04, 0x41, 0x00, // "Y" 99 | 0x1f, 0x84, 0x10, 0x42, 0xf0, 0x01, // "Z" 100 | 0x1c, 0x41, 0x10, 0x04, 0xc1, 0x01, // "[" 101 | 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, // "\" 102 | 0x07, 0x41, 0x10, 0x04, 0x71, 0x00, // "]" 103 | 0x84, 0x12, 0x01, 0x00, 0x00, 0x00, // "^" 104 | 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, // "_" 105 | 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, // "`" 106 | 0x00, 0xe0, 0x40, 0x5e, 0xe4, 0x01, // "a" 107 | 0x41, 0xd0, 0x4c, 0x51, 0xf4, 0x00, // "b" 108 | 0x00, 0xe0, 0x04, 0x41, 0xe4, 0x00, // "c" 109 | 0x10, 0x64, 0x65, 0x51, 0xe4, 0x01, // "d" 110 | 0x00, 0xe0, 0x44, 0x5f, 0xe0, 0x00, // "e" 111 | 0x8c, 0x24, 0x1c, 0x82, 0x20, 0x00, // "f" 112 | 0x00, 0xe0, 0x45, 0x1e, 0xc4, 0x00, // "g" 113 | 0x41, 0xd0, 0x4c, 0x51, 0x14, 0x01, // "h" 114 | 0x04, 0x60, 0x10, 0x04, 0xe1, 0x00, // "i" 115 | 0x08, 0xc0, 0x20, 0x48, 0x62, 0x00, // "j" 116 | 0x82, 0x20, 0x29, 0x86, 0x22, 0x01, // "k" 117 | 0x06, 0x41, 0x10, 0x04, 0xe1, 0x00, // "l" 118 | 0x00, 0xb0, 0x54, 0x55, 0x14, 0x01, // "m" 119 | 0x00, 0xd0, 0x4c, 0x51, 0x14, 0x01, // "n" 120 | 0x00, 0xe0, 0x44, 0x51, 0xe4, 0x00, // "o" 121 | 0x00, 0xf0, 0x44, 0x4f, 0x10, 0x00, // "p" 122 | 0x00, 0x60, 0x65, 0x1e, 0x04, 0x01, // "q" 123 | 0x00, 0xd0, 0x4c, 0x41, 0x10, 0x00, // "r" 124 | 0x00, 0xe0, 0x04, 0x0e, 0xf4, 0x00, // "s" 125 | 0x82, 0x70, 0x08, 0x82, 0xc4, 0x00, // "t" 126 | 0x00, 0x10, 0x45, 0x51, 0x66, 0x01, // "u" 127 | 0x00, 0x10, 0x45, 0x91, 0x42, 0x00, // "v" 128 | 0x00, 0x10, 0x45, 0x55, 0xa5, 0x00, // "w" 129 | 0x00, 0x10, 0x29, 0x84, 0x12, 0x01, // "x" 130 | 0x00, 0x10, 0x45, 0x1e, 0xe4, 0x00, // "y" 131 | 0x00, 0xf0, 0x21, 0x84, 0xf0, 0x01, // "z" 132 | 0x08, 0x41, 0x08, 0x04, 0x81, 0x00, // "{" 133 | 0x04, 0x41, 0x10, 0x04, 0x41, 0x00, // "|" 134 | 0x02, 0x41, 0x20, 0x04, 0x21, 0x00, // "}" 135 | 0x00, 0x40, 0xa8, 0x10, 0x00, 0x00, // "~" 136 | } 137 | }; 138 | 139 | // --- 8x16 (Terminus) --- 140 | const Font terminus_8x16 = 141 | { 142 | .width = 8, 143 | .height = 16, 144 | .pitch = 16, 145 | .data = { 146 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " " 147 | 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // "!" 148 | 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // """ 149 | 0x00, 0x00, 0x36, 0x36, 0x36, 0x7f, 0x36, 0x36, 0x7f, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, // "#" 150 | 0x00, 0x08, 0x08, 0x3e, 0x6b, 0x0b, 0x0b, 0x3e, 0x68, 0x68, 0x6b, 0x3e, 0x08, 0x08, 0x00, 0x00, // "$" 151 | 0x00, 0x00, 0x66, 0x6b, 0x36, 0x30, 0x18, 0x18, 0x0c, 0x6c, 0xd6, 0x66, 0x00, 0x00, 0x00, 0x00, // "%" 152 | 0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x6e, 0x3b, 0x33, 0x33, 0x3b, 0x6e, 0x00, 0x00, 0x00, 0x00, // "&" 153 | 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "'" 154 | 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // "(" 155 | 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, // ")" 156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x1c, 0x7f, 0x1c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "*" 157 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "+" 158 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, // "," 159 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "-" 160 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // "." 161 | 0x00, 0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, // "/" 162 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x73, 0x7b, 0x6f, 0x67, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "0" 163 | 0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, // "1" 164 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, // "2" 165 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x60, 0x3c, 0x60, 0x60, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "3" 166 | 0x00, 0x00, 0x60, 0x70, 0x78, 0x6c, 0x66, 0x63, 0x7f, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, // "4" 167 | 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x60, 0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "5" 168 | 0x00, 0x00, 0x3c, 0x06, 0x03, 0x03, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "6" 169 | 0x00, 0x00, 0x7f, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, // "7" 170 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "8" 171 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00, // "9" 172 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // ":" 173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, // ";" 174 | 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, // "<" 175 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "=" 176 | 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, // ">" 177 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x30, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // "?" 178 | 0x00, 0x00, 0x3e, 0x63, 0x73, 0x6b, 0x6b, 0x6b, 0x6b, 0x73, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, // "@" 179 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "A" 180 | 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3f, 0x00, 0x00, 0x00, 0x00, // "B" 181 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x03, 0x03, 0x03, 0x03, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "C" 182 | 0x00, 0x00, 0x1f, 0x33, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x33, 0x1f, 0x00, 0x00, 0x00, 0x00, // "D" 183 | 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x1f, 0x03, 0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, // "E" 184 | 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x1f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, // "F" 185 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x03, 0x03, 0x7b, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "G" 186 | 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "H" 187 | 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // "I" 188 | 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00, // "J" 189 | 0x00, 0x00, 0x63, 0x63, 0x33, 0x1b, 0x0f, 0x0f, 0x1b, 0x33, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "K" 190 | 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, // "L" 191 | 0x00, 0x00, 0x41, 0x63, 0x77, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "M" 192 | 0x00, 0x00, 0x63, 0x63, 0x63, 0x67, 0x6f, 0x7b, 0x73, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "N" 193 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "O" 194 | 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, // "P" 195 | 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7b, 0x3e, 0x60, 0x00, 0x00, 0x00, // "Q" 196 | 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3f, 0x0f, 0x1b, 0x33, 0x63, 0x00, 0x00, 0x00, 0x00, // "R" 197 | 0x00, 0x00, 0x3e, 0x63, 0x03, 0x03, 0x3e, 0x60, 0x60, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "S" 198 | 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // "T" 199 | 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "U" 200 | 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, // "V" 201 | 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, // "W" 202 | 0x00, 0x00, 0x63, 0x63, 0x36, 0x36, 0x1c, 0x1c, 0x36, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "X" 203 | 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // "Y" 204 | 0x00, 0x00, 0x7f, 0x60, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, // "Z" 205 | 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, // "[" 206 | 0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, // "\" 207 | 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, // "]" 208 | 0x00, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "^" 209 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, // "_" 210 | 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "`" 211 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x60, 0x7e, 0x63, 0x63, 0x63, 0x7e, 0x00, 0x00, 0x00, 0x00, // "a" 212 | 0x00, 0x00, 0x03, 0x03, 0x03, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3f, 0x00, 0x00, 0x00, 0x00, // "b" 213 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "c" 214 | 0x00, 0x00, 0x60, 0x60, 0x60, 0x7e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x00, 0x00, 0x00, 0x00, // "d" 215 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x7f, 0x03, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x00, // "e" 216 | 0x00, 0x00, 0x78, 0x0c, 0x0c, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, // "f" 217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x3e, 0x00, 0x00, // "g" 218 | 0x00, 0x00, 0x03, 0x03, 0x03, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "h" 219 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // "i" 220 | 0x00, 0x00, 0x60, 0x60, 0x00, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00, 0x00, // "j" 221 | 0x00, 0x00, 0x03, 0x03, 0x03, 0x63, 0x33, 0x1b, 0x0f, 0x1b, 0x33, 0x63, 0x00, 0x00, 0x00, 0x00, // "k" 222 | 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, // "l" 223 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00, // "m" 224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "n" 225 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, // "o" 226 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3f, 0x03, 0x03, 0x00, 0x00, // "p" 227 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x00, 0x00, // "q" 228 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x0f, 0x07, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, // "r" 229 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x03, 0x03, 0x3e, 0x60, 0x60, 0x3f, 0x00, 0x00, 0x00, 0x00, // "s" 230 | 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, // "t" 231 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x00, 0x00, 0x00, 0x00, // "u" 232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x36, 0x36, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, // "v" 233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x6b, 0x6b, 0x6b, 0x6b, 0x3e, 0x00, 0x00, 0x00, 0x00, // "w" 234 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x36, 0x1c, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, // "x" 235 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x3e, 0x00, 0x00, // "y" 236 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, // "z" 237 | 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00, // "{" 238 | 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // "|" 239 | 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x30, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, // "}" 240 | 0x00, 0xce, 0xdb, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "~" 241 | } 242 | }; 243 | 244 | 245 | --------------------------------------------------------------------------------