got LEDs working, ribbon trail program initially implemented

- fixed soft I2C master set hi/lo routines
- fixed bug in matrix_send not setting all LEDs from map
- fix AWU interrupt not firing; requires EXTI line to be configured too even if unused
- fixed wrong dividers used in system clock set function
This commit is contained in:
true 2026-05-08 16:12:18 -07:00
parent d95af918fa
commit abd985e3a1
10 changed files with 117 additions and 56 deletions

View File

@ -91,7 +91,7 @@
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting.1983282875" name="Create extended listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize.1000761142" name="Print size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform.1944008784" isAbstract="false" osList="all" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform"/>
<builder buildPath="${workspace_loc:/firmware/obj" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.1421508906" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" stopOnErr="true" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>
<builder buildPath="${workspace_loc:/hsc26_art2/obj" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.1421508906" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" stopOnErr="true" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.1244756189" name="GNU RISC-V Cross Assembler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor.1692176068" name="Use preprocessor" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.nostdinc.821897907" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.nostdinc" useByScannerDiscovery="true" value="false" valueType="boolean"/>
@ -230,7 +230,7 @@
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.1801165667" name="GNU RISC-V Cross Create Flash Image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.textsection.1097396305" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.textsection" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.datasection.2034511797" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.datasection" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.1726268709" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice" useByScannerDiscovery="false" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.ihex" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.1726268709" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice" useByScannerDiscovery="false" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.ihexAndbinary" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.othersection.1890795928" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.othersection" useByScannerDiscovery="false" valueType="stringList"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.other.788974495" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.other" useByScannerDiscovery="false" value="" valueType="string"/>
</tool>

View File

@ -10,10 +10,10 @@ PeripheralVersion=1.9
Description=Website: https://www.wch.cn/products/CH32X035.html?\nROM(byte): 62K, SRAM(byte): 20K, CHIP PINS: 28, GPIO PORTS: 27.\nWCH CH32X035 series of mainstream MCUs covers the needs of a large variety of applications in the industrial,medical and consumer markets. High performance with first-class peripherals and low-power,low-voltage operation is paired with a high level of integration at accessible prices with a simple architecture and easy-to-use tools.
Mcu Type=CH32X035
Address=0x08000000
Target Path=obj/CH32X035G8U6.hex
Target Path=obj\hsc26_art2.hex
Exe Path=
Exe Arguments=
CLKSpeed=1
CLKSpeed=2
DebugInterfaceMode=0
Erase All=true
Program=true

View File

@ -46,27 +46,31 @@
#define SDA_PIN 9
#define SDA_BIT (1 << SDA_PIN)
#define SDA_CONFOFF ((SDA_PIN % 8) * 4)
#define SDA_CONFOFFS ((SDA_PIN % 8) * 4)
#define SDA_GPIO GPIOB
#define SDA_CFGR GPIOB->CFGHR
#define SDA_CFGR SDA_GPIO->CFGHR
#define SCL_PIN 8
#define SCL_BIT (1 << SCL_PIN)
#define SCL_CONFOFF ((SCL_PIN % 8) * 4)
#define SCL_CONFOFFS ((SCL_PIN % 8) * 4)
#define SCL_GPIO GPIOB
#define SCL_CFGR GPIOB->CFGHR
#define SCL_CFGR SCL_GPIO->CFGHR
#define GPIO_CFG_LO 0x1
#define GPIO_CFG_HI 0x8
#define GPIO_CFG_HI 0x4
#define SDA_IN_HI() { SDA_CFGR &= ~(0xf << SDA_CONFOFF); SDA_CFGR |= (GPIO_CFG_HI << SDA_CONFOFF); }
#define SDA_OUTLO() { SDA_CFGR &= ~(0xf << SDA_CONFOFF); SDA_CFGR |= (GPIO_CFG_LO << SDA_CONFOFF); }
#define SDA_IN_HI() { uint32_t sda = SDA_CFGR & ~(0xf << SDA_CONFOFFS); \
sda |= (GPIO_CFG_HI << SDA_CONFOFFS); SDA_CFGR = sda; }
#define SDA_OUTLO() { uint32_t sda = SDA_CFGR & ~(0xf << SDA_CONFOFFS); \
sda |= (GPIO_CFG_LO << SDA_CONFOFFS); SDA_CFGR = sda; }
#define SDA_SET_LO() SDA_GPIO->BCR = SDA_BIT
#define SDA_GET() ( SDA_GPIO->INDR & SDA_BIT )
#define SCL_IN_HI() { SCL_CFGR &= ~(0xf << SCL_CONFOFF); SCL_CFGR |= (GPIO_CFG_HI << SCL_CONFOFF); }
#define SCL_OUTLO() { SCL_CFGR &= ~(0xf << SCL_CONFOFF); SCL_CFGR |= (GPIO_CFG_LO << SCL_CONFOFF); }
#define SCL_IN_HI() { uint32_t scl = SCL_CFGR & ~(0xf << SCL_CONFOFFS); \
scl |= (GPIO_CFG_HI << SCL_CONFOFFS); SCL_CFGR = scl; }
#define SCL_OUTLO() { uint32_t scl = SCL_CFGR & ~(0xf << SCL_CONFOFFS); \
scl |= (GPIO_CFG_LO << SCL_CONFOFFS); SCL_CFGR = scl; }
#define SCL_SET_LO() SCL_GPIO->BCR = SCL_BIT
#define SCL_GET() ( SCL_GPIO->INDR & SCL_BIT )

View File

@ -55,16 +55,16 @@ void lp_ribbon_upward(uint16_t wait, uint16_t rate, uint8_t fade)
x = s[2]++;
// are we done?
if (x > sizeof(led_set.ribbon)) {
if (x >= sizeof(led_set.ribbon)) {
s[0] = 0;
s[1] = wait;
break;
}
// fade in and up
led_set.ribbon[x] = 0x40;
if (x) led_set.ribbon[x - 1] = 0x70;
if (x > 1) led_set.ribbon[x - 2] = 0xff;
led_set.ribbon[x] = 0x20;
if (x) led_set.ribbon[x - 1] = 0x66;
if (x > 1) led_set.ribbon[x - 2] = 0xd0;
}
}
@ -73,7 +73,7 @@ void lp_ribbon_upward(uint16_t wait, uint16_t rate, uint8_t fade)
if (led_set.ribbon[i] >= fade) {
led_set.ribbon[i] -= fade;
} else {
led_set.ribbon[i] = 0;
led_set.ribbon[i] >>= 1;
}
}

View File

@ -13,7 +13,7 @@
#define AW20X_DIM 31 // initial global current setting
#define AW20X_DIM 28 // initial global current setting
#define AW20X_COLS 6
#define AW20X_ROWS 12
@ -24,17 +24,16 @@
AW20x awled;
static uint8_t awled_fade[AW20X_FADE_COUNT];
uint8_t awled_fade[AW20X_FADE_COUNT];
static uint8_t led_matrix_needs_update = 0;
uint16_t led_map_size;
const LedMap led_map = {
// map is 1-based to match part numbers on the board
{ // ribbon
1, 25, 13, 49,
.ribbon = { // ribbon
13, 25, 1, 49,
37, 14,
28, 2, 38,
26, 2, 38,
50, 3,
27, 15,
39, 51,
@ -54,19 +53,20 @@ const LedMap led_map = {
55, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
8, 20, 32,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
8, 0, 0, 20, 0, 0, 32,
0, 0
},
{ // "A"
.a = { // "A"
9, 21, 33, 0, 0, 0, 45, 57, 10,
22,
34, 46, 58, 11, 23, 35, 47, 59, 12
},
{ // "//" left one
.ii_lf = { // "//" left one
61, 62, 63, 64, 44
},
{ // "//" right one
.ii_rt = { // "//" right one
60, 48, 36, 24, 56
}
};
@ -95,8 +95,6 @@ void matrix_init()
aw20x_set_dim_global(&awled, AW20X_DIM);
aw20x_set_fade(&awled);
aw20x_led_enable_range(&awled, 0, (AW20X_COLS * AW20X_MAX_ROWS) - 1);
led_map_size = sizeof(led_map.ribbon) + sizeof(led_map.a) + sizeof(led_map.ii_lf) + sizeof(led_map.ii_rt);
}
void matrix_flag_update()
@ -104,9 +102,14 @@ void matrix_flag_update()
led_matrix_needs_update = 1;
}
/*
static uint8_t delay = 0;
static uint8_t work = 0;
*/
void matrix_send()
{
int8_t i;
uint32_t i;
uint8_t *fade = awled_fade;
uint8_t *map = (uint8_t *)&led_map;
uint8_t *set = (uint8_t *)&led_set;
@ -115,14 +118,35 @@ void matrix_send()
led_matrix_needs_update = 0;
// remap data for sending
for (i = 0; i < led_map_size; i++) {
if ((*map) & (*map <= AW20X_FADE_COUNT)) {
fade[*map - 1] = *set;
for (i = 0; i < sizeof(led_map); i++) {
if ((*map) && ((*map) <= AW20X_FADE_COUNT)) {
fade[(*map) - 1] = *set;
}
map++;
set++;
map++; set++;
}
/* testing
if (delay) {
delay--;
} else {
delay = 20;
for (int i = 0; i < sizeof(led_map.ribbon); i++) {
if (led_map.ribbon[i]) {
awled_fade[led_map.ribbon[i] - 1] = 0;
}
}
if (led_map.ribbon[work]) {
awled_fade[led_map.ribbon[work] - 1] = 0xff;
}
work++;
if (work >= sizeof(led_map.ribbon)) work = 0;
matrix_flag_update();
}
*/
aw20x_set_fade(&awled);
}
}

View File

@ -13,7 +13,7 @@
// 0 index = bottom.
// 0 value = no LED here.
typedef struct LedMap {
uint8_t ribbon[80]; // a "linear" bottom to top map, with gaps for the spacing.
uint8_t ribbon[88]; // a "linear" bottom to top map, with gaps for the spacing.
uint8_t a[20]; // left to right, bottom to apex to bottom.
uint8_t ii_lf[5]; // top to bottom.
uint8_t ii_rt[5]; // top to bottom.
@ -22,6 +22,7 @@ typedef struct LedMap {
extern LedMap led_set;
extern uint8_t awled_fade[6*12];

View File

@ -47,10 +47,15 @@ void clk_init()
void periphclk_init()
{
// needed for GPIO, remap, ADC, SPI
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO |
RCC_APB2Periph_ADC1 | RCC_APB2Periph_SPI1, ENABLE);
// may be needed for AWU
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
// needed for DMA, USBPD
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_USBPD, ENABLE);
}
@ -100,6 +105,31 @@ void gpio_init()
// todo later
}
void awu_init()
{
NVIC_InitTypeDef nvic;
EXTI_InitTypeDef exti = {0};
// configure AWU
AWU_SetPrescaler(AWU_Prescaler_1);
AWU_SetWindowValue(0x2f);
AutoWakeUpCmd(ENABLE);
// configure EXTI line
exti.EXTI_Line = EXTI_Line27;
exti.EXTI_Mode = EXTI_Mode_Interrupt;
exti.EXTI_Trigger = EXTI_Trigger_Rising;
exti.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti);
// configure PFIC interrupt
nvic.NVIC_IRQChannel = AWU_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority = 0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
}
/*********************************************************************
@ -130,22 +160,20 @@ int main(void)
// set up accelerometer
spim_init();
// configure AWU to provide ~1440Hz wakeup interrupt for main program
// configure AWU to provide ~997Hz wakeup interrupt for main program
// TODO: confirm if the counter is reset / preloaded
AWU_SetPrescaler(AWU_Prescaler_32);
AWU_SetWindowValue(0x3e);
AutoWakeUpCmd(ENABLE);
awu_init();
while (1) {
// low-priority tasks like
// rendering next LED program output frame
if (lp_render) {
lp_render = 0;
lp_ribbon_upward(800, 3, 2);
lp_ribbon_upward(200, 3, 4);
}
// stay a while
// __WFI();
__WFI();
}
}
@ -154,13 +182,13 @@ void AWU_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void AWU_IRQHandler(void)
{
cnt++;
if (cnt >= 1440) {
if (cnt >= 1000) {
cnt = 0;
wake_uptime++;
}
// handle render new frame at 90Hz
if ((cnt & 0xf) == 0) {
// handle render new frame at ~100Hz
if ((cnt % 10) == 0) {
lp_render = 1;
}
@ -172,4 +200,7 @@ void AWU_IRQHandler(void)
// handle buttons
// do we sleep?
// clear interrupt
EXTI_ClearFlag(EXTI_Line27);
}

View File

@ -10,6 +10,7 @@
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "ch32x035.h"
#include "system_ch32x035.h"
/*
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
@ -90,10 +91,10 @@ void SetSysClock_HSI(uint32_t divider)
// set wait states depending on speed
if (divider > RCC_HPRE_DIV1) { // 48MHz is already set to 2 cycles
if (divider >= RCC_HPRE_DIV1) { // 24MHz is 1 cycle
actlr |= (uint32_t)FLASH_ACTLR_LATENCY_0;
} else { // all others are 0 cycle
if (divider == RCC_HPRE_DIV2) { // 24MHz is 1 cycle
actlr |= (uint32_t)FLASH_ACTLR_LATENCY_1;
} else { // all others are 0 cycle
actlr |= (uint32_t)FLASH_ACTLR_LATENCY_0;
}
FLASH->ACTLR = actlr;

View File

@ -40,8 +40,8 @@
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="handle_reset"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
<stringAttribute key="com.mounriver.debug.gdbjtag.svdPath" value="${eclipse_home}template/wizard/WCH/RISC-V/CH32X035/NoneOS/CH32X035xx.svd"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="obj/CH32X035G8U6.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="CH32X035G8U6"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="obj/hsc26_art2.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="hsc26_art2"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="GNU MCU OpenOCD"/>
<stringAttribute key="com.mounriver.debug.gdbjtag.openocd.gdbServerConnectionAddress" value=""/>
@ -54,7 +54,7 @@
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="CH32X035G8U6"/>
<listEntry value="hsc26_art2"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>

View File

@ -259,7 +259,7 @@
},
"createFlash": {
"enabled": true,
"outputFileFormat": "ihex",
"outputFileFormat": "ihexAndbinary",
"copy_only_section_text": false,
"copy_only_section_data": false,
"copy_only_sections": [],
@ -313,8 +313,8 @@
"flashConfig": {
"mcutype": "CH32X035",
"address": "0x08000000",
"target_path": "obj/hsc26_art2.hex",
"clkSpeed": "High",
"target_path": "obj\\hsc26_art2.hex",
"clkSpeed": "Middle",
"debug_interface_mode": "1-wire serial",
"erase": true,
"program": true,