diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..bed1a7c --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +# -*- mode: yaml -*- + +BasedOnStyle: LLVM +IndentWidth: 4 +ColumnLimit: 100 +BreakBeforeBraces: WebKit # Only break at start of functions diff --git a/CMakeLists.txt b/CMakeLists.txt index ab951a2..2fbfda9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,9 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) set(HAL_DEFINES - PY32F002Ax5 + # PY32F002Ax5 + PY32F003x6 + # USE_FULL_LL_DRIVER ) set(HAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/py32f0-sdk) @@ -49,7 +51,8 @@ target_sources(py32-hal PRIVATE ${HAL_DIR}/Libraries/PY32F0xx_LL_BSP/Src/py32f0xx_bsp_printf.c # Startup code ${HAL_DIR}/Libraries/CMSIS/Device/PY32F0xx/Source/system_py32f0xx.c - ${HAL_DIR}/Libraries/CMSIS/Device/PY32F0xx/Source/gcc/startup_py32f002a.s + #${HAL_DIR}/Libraries/CMSIS/Device/PY32F0xx/Source/gcc/startup_py32f002a.s + ${HAL_DIR}/Libraries/CMSIS/Device/PY32F0xx/Source/gcc/startup_py32f003.s ) # Set up target executable @@ -61,8 +64,21 @@ target_link_libraries(puya32-playground target_sources(puya32-playground PRIVATE src/main.c + src/neopixel.c ) +# # example +# add_executable(ll_tim1_dma) + +# target_link_libraries(ll_tim1_dma +# PRIVATE py32-hal +# ) + +# target_sources(ll_tim1_dma PRIVATE +# py32f0-sdk/Examples/PY32F0xx/LL/TIM/TIM1_DMA/main.c +# py32f0-sdk/Examples/PY32F0xx/LL/TIM/TIM1_DMA/py32f0xx_it.c +# ) + # clang-format add_custom_target(check-format find include/ src/ -iname '*.[ch]' -exec clang-format -Werror --dry-run {} + diff --git a/cmake/gcc-arm-none-eabi.cmake b/cmake/gcc-arm-none-eabi.cmake index e4dc447..d70505d 100644 --- a/cmake/gcc-arm-none-eabi.cmake +++ b/cmake/gcc-arm-none-eabi.cmake @@ -28,15 +28,16 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}") set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fdata-sections -ffunction-sections") -set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") +set(CMAKE_C_FLAGS_DEBUG "-Og -g3") set(CMAKE_C_FLAGS_RELEASE "-Os -g0") -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") +set(CMAKE_CXX_FLAGS_DEBUG "-Og -g3") set(CMAKE_CXX_FLAGS_RELEASE "-Os -g0") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") set(CMAKE_EXE_LINKER_FLAGS "${TARGET_FLAGS}") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${CMAKE_SOURCE_DIR}/py32f0-sdk/Libraries/LDScripts/py32f002ax5.ld\"") +#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${CMAKE_SOURCE_DIR}/py32f0-sdk/Libraries/LDScripts/py32f002ax5.ld\"") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${CMAKE_SOURCE_DIR}/py32f0-sdk/Libraries/LDScripts/py32f003x6.ld\"") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nano.specs --specs=nosys.specs") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage") diff --git a/src/main.c b/src/main.c index 12f3cae..14d283f 100644 --- a/src/main.c +++ b/src/main.c @@ -1,75 +1,95 @@ +#include "neopixel.h" + +#include +#include #include #include #include -#include #include +#include + #define LED_PIN LL_GPIO_PIN_0 static void init(void) { - /* LL_RCC_HSI_Enable(); */ - /* while(LL_RCC_HSI_IsReady() != 1); */ + BSP_RCC_HSI_24MConfig(); - /* LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); */ - /* LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSISYS); */ - /* while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSISYS); */ - - /* LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); */ - /* LL_Init1msTick(8000000); */ - /* LL_SetSystemCoreClock(8000000); */ - LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); + LL_GPIO_SetPinMode(GPIOA, LED_PIN, LL_GPIO_MODE_OUTPUT); + neopixel_init(); + BSP_USART_Config(115200); - - LL_Init1msTick(8000000); - LL_SetSystemCoreClock(8000000); } -int main(void) { - init(); +static const uint8_t sintbl[] = {0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, + 40, 43, 46, 49, 51, 54, 57, 60, 63, 65, 68, 71, 73, + 76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 100, 102, + 104, 106, 107, 109, 111, 112, 113, 115, 116, 117, 118, 120, 121, + 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127}; - printf("Hello, PY32F002A!\r\n"); - - while(1) { - LL_GPIO_TogglePin(GPIOA, LED_PIN); - LL_mDelay(1000); +static uint8_t sin_(uint8_t pos) { + if (pos <= 63) { + return 128 + sintbl[pos]; + } else if (pos <= 127) { + return 128 + sintbl[63 - (pos - 64)]; + } else if (pos <= 191) { + return 128 - sintbl[pos - 128]; + } else { + return 128 - sintbl[63 - (pos - 192)]; } } -void NMI_Handler(void) +int main(void) { + init(); + + printf("Hello, PY32F002A!\r\n"); + + unsigned i = 0; + unsigned val[8]; + while (true) { + for (int p = 0;p < 4;++p) { + val[p] = neopixel_build_val(sin_(i+p*32), sin_(i+p*32+85), sin_(i+p*32+2*85)); + } + //neopixel_set_all(sin_(i), sin_(i+85), sin_(i+2*85), 8); + neopixel_set_raw(val, 4); + LL_mDelay(1); + ++i; + /* for (int c = 0; c < 3; ++c) { */ + /* for (int i = 0; i < 256; ++i) { */ + /* /\* neopixel_set_raw(val); *\/ */ + /* neopixel_set_all(c == 0 ? i : 0, c == 1 ? i : 0, c == 2 ? i : 0, 8); */ + /* LL_mDelay(10); */ + /* } */ + /* } */ + } } +void NMI_Handler(void) {} + /** - * @brief This function handles Hard fault interrupt. - */ + * @brief This function handles Hard fault interrupt. + */ void HardFault_Handler(void) { - while (1) - { - } + while (1) { + } } /** - * @brief This function handles System service call via SWI instruction. - */ -void SVC_Handler(void) -{ -} + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) {} /** - * @brief This function handles Pendable request for system service. - */ -void PendSV_Handler(void) -{ -} + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) {} /** - * @brief This function handles System tick timer. - */ -void SysTick_Handler(void) -{ -} + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) {} diff --git a/src/neopixel.c b/src/neopixel.c new file mode 100644 index 0000000..d655fcc --- /dev/null +++ b/src/neopixel.c @@ -0,0 +1,116 @@ +#include "neopixel.h" + +#include +#include +#include +#include +#include +#include + +void neopixel_init(void) +{ +#ifdef NEOPIXEL_USE_DMA + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); + LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG | LL_APB1_GRP2_PERIPH_TIM1); +#else + LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM1); +#endif + + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_1, LL_GPIO_MODE_ALTERNATE); + LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_1, LL_GPIO_AF_13); // TIM1_CH4 on PA1 + + LL_TIM_EnableCounter(TIM1); + LL_TIM_EnableUpdateEvent(TIM1); + LL_TIM_EnableARRPreload(TIM1); + LL_TIM_SetPrescaler(TIM1, __LL_TIM_CALC_PSC(SystemCoreClock, 8000000)); + LL_TIM_SetAutoReload(TIM1, 10); + LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH4); + LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH4); + LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH4, LL_TIM_OCMODE_PWM1); + LL_TIM_OC_ConfigOutput(TIM1, LL_TIM_CHANNEL_CH4, LL_TIM_OCPOLARITY_HIGH); + LL_TIM_OC_SetCompareCH4(TIM1, 0); + LL_TIM_EnableAllOutputs(TIM1); + +#ifdef NEOPIXEL_USE_DMA + LL_DMA_ConfigTransfer(DMA1, LL_DMA_CHANNEL_1, + LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_NORMAL | + LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | + LL_DMA_PDATAALIGN_HALFWORD | LL_DMA_MDATAALIGN_HALFWORD | + LL_DMA_PRIORITY_VERYHIGH); + LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, (uintptr_t)&(TIM1->CCR4)); + LL_TIM_EnableDMAReq_UPDATE(TIM1); + LL_SYSCFG_SetDMARemap_CH1(LL_SYSCFG_DMA_MAP_TIM1_UP); +#endif +} + +static const uint8_t gammatbl[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, + 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, + 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, + 29, 30, 30, 31, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, 41, 42, 43, + 43, 44, 45, 46, 47, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 81, + 82, 83, 84, 85, 87, 88, 89, 90, 91, 93, 94, 95, 97, 98, 99, 100, 102, 103, 105, + 106, 107, 109, 110, 111, 113, 114, 116, 117, 119, 120, 121, 123, 124, 126, 127, 129, 130, 132, + 133, 135, 137, 138, 140, 141, 143, 145, 146, 148, 149, 151, 153, 154, 156, 158, 159, 161, 163, + 165, 166, 168, 170, 172, 173, 175, 177, 179, 181, 182, 184, 186, 188, 190, 192, 194, 196, 197, + 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 234, 236, + 238, 240, 242, 244, 246, 248, 251, 253, 255}; + +#ifdef NEOPIXEL_USE_DMA +static uint16_t buf[NEOPIXEL_MAX_LEN*24+1] = {0}; + +void neopixel_set_raw(const unsigned *val, unsigned count) +{ + if (LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_1)) { + while (!LL_DMA_IsActiveFlag_TC1(DMA1)) { + } + LL_DMA_ClearFlag_TC1(DMA1); + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); + } + for (int pix = 0;pix < count;++pix) { + unsigned tmp = val[pix]; + for (int i = 0; i < 24; ++i) { + buf[i+pix*24] = (tmp & 0x800000) ? 6 : 3; + tmp <<= 1; + } + } + buf[count*24] = 0; + LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uintptr_t)buf); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, count*24+1); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); +} +#else +void neopixel_set_raw(unsigned val) +{ + LL_TIM_ClearFlag_UPDATE(TIM1); + while (!LL_TIM_IsActiveFlag_UPDATE(TIM1)) { + } + LL_TIM_ClearFlag_UPDATE(TIM1); + unsigned tmp = val; + for (int i = 0; i < 24; ++i) { + LL_TIM_OC_SetCompareCH4(TIM1, (tmp & 0x800000) ? 6 : 3); + while (!LL_TIM_IsActiveFlag_UPDATE(TIM1)) { + } + LL_TIM_ClearFlag_UPDATE(TIM1); + tmp <<= 1; + } + LL_TIM_OC_SetCompareCH4(TIM1, 0); +} +#endif + +void neopixel_set_all(uint8_t r, uint8_t g, uint8_t b, unsigned count) +{ + unsigned val[NEOPIXEL_MAX_LEN]; + const unsigned raw = neopixel_build_val(r, g, b); + for (int i = 0; i < count; ++i) + val[i] = raw; + neopixel_set_raw(val, count); +} + +unsigned neopixel_build_val(uint8_t r, uint8_t g, uint8_t b) +{ + return (gammatbl[g] << 16) | (gammatbl[r] << 8) | gammatbl[b]; +} diff --git a/src/neopixel.h b/src/neopixel.h new file mode 100644 index 0000000..8135d03 --- /dev/null +++ b/src/neopixel.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#define NEOPIXEL_USE_DMA +#define NEOPIXEL_MAX_LEN 8 + +void neopixel_init(void); +void neopixel_set_raw(const unsigned *val, unsigned count); +void neopixel_set_all(uint8_t r, uint8_t g, uint8_t b, unsigned count); +unsigned neopixel_build_val(uint8_t r, uint8_t g, uint8_t b);