led: add basic Charlieplexing scan
This commit is contained in:
parent
7d7389cac5
commit
90cdb61063
3
Makefile
3
Makefile
@ -49,7 +49,8 @@ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2dev.c \
|
||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostBase.c \
|
||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi1.c \
|
||||
CH5xx_ble_firmware_library/RVMSIS/core_riscv.c \
|
||||
src/main.c
|
||||
src/main.c \
|
||||
src/leddrv.c
|
||||
|
||||
|
||||
# ASM sources
|
||||
|
||||
150
src/leddrv.c
Normal file
150
src/leddrv.c
Normal file
@ -0,0 +1,150 @@
|
||||
#include "leddrv.h"
|
||||
|
||||
#define LED_DRIVE_STRENTH 0
|
||||
#define LED_PINCOUNT (23)
|
||||
typedef enum {
|
||||
FLOATING,
|
||||
LOW,
|
||||
HIGH,
|
||||
} tristate_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t *port_buf;
|
||||
uint32_t *cfg_buf;
|
||||
uint32_t pin;
|
||||
} pinctrl_t;
|
||||
|
||||
static void gpio_buf_set(pinctrl_t pinctl, tristate_t state)
|
||||
{
|
||||
if (state == FLOATING) {
|
||||
*(pinctl.cfg_buf) &= ~pinctl.pin;
|
||||
} else {
|
||||
if (state == HIGH)
|
||||
*(pinctl.port_buf) |= pinctl.pin;
|
||||
else
|
||||
*(pinctl.port_buf) &= ~pinctl.pin;
|
||||
|
||||
*(pinctl.cfg_buf) |= pinctl.pin;
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_buf_apply(
|
||||
volatile uint8_t *gpio_base,
|
||||
uint32_t *port, uint32_t *cfg,
|
||||
uint32_t *mask)
|
||||
{
|
||||
#if LED_DRIVE_STRENTH != 0
|
||||
uint32_t *drv = (uint32_t *)(gpio_base + GPIO_PD_DRV);
|
||||
*drv = (*drv & ~*mask) | (*cfg & *mask);
|
||||
#endif
|
||||
uint32_t *dir = (uint32_t *)(gpio_base + GPIO_DIR);
|
||||
*dir = (*dir & ~*mask) | (*cfg & *mask);
|
||||
|
||||
uint32_t *out = (uint32_t *)(gpio_base + GPIO_OUT);
|
||||
*out = (*out & ~*mask) | (*port & *mask);
|
||||
}
|
||||
|
||||
static uint32_t PA_buf;
|
||||
static uint32_t PB_buf;
|
||||
static uint32_t PAcfg_buf;
|
||||
static uint32_t PBcfg_buf;
|
||||
static uint32_t PA_mask;
|
||||
static uint32_t PB_mask;
|
||||
|
||||
#define GPIO_APPLY_ALL() \
|
||||
gpio_buf_apply(BA_PA, &PA_buf, &PAcfg_buf, &PA_mask); \
|
||||
gpio_buf_apply(BA_PB, &PB_buf, &PBcfg_buf, &PB_mask)
|
||||
|
||||
#define PINCTRL(x, pin) { \
|
||||
&P##x##_buf, \
|
||||
&P##x##cfg_buf, \
|
||||
GPIO_Pin_##pin \
|
||||
}
|
||||
|
||||
static const pinctrl_t led_pins[LED_PINCOUNT] = {
|
||||
PINCTRL(A, 15), // A
|
||||
PINCTRL(B, 18), // B
|
||||
PINCTRL(B, 0), // C
|
||||
PINCTRL(B, 7), // D
|
||||
PINCTRL(A, 12), // E
|
||||
PINCTRL(A, 10), // F
|
||||
PINCTRL(A, 11), // G
|
||||
PINCTRL(B, 9), // H
|
||||
PINCTRL(B, 8), // I
|
||||
PINCTRL(B, 15), // J
|
||||
PINCTRL(B, 14), // K
|
||||
PINCTRL(B, 13), // L
|
||||
PINCTRL(B, 12), // M
|
||||
PINCTRL(B, 5), // N
|
||||
PINCTRL(A, 4), // O
|
||||
PINCTRL(B, 3), // P
|
||||
PINCTRL(B, 4), // Q
|
||||
PINCTRL(B, 2), // R
|
||||
PINCTRL(B, 1), // S
|
||||
PINCTRL(B, 23), // T
|
||||
PINCTRL(B, 21), // U
|
||||
PINCTRL(B, 20), // V
|
||||
PINCTRL(B, 19), // W
|
||||
};
|
||||
|
||||
void led_init()
|
||||
{
|
||||
for (int i=0; i<LED_PINCOUNT; i++) {
|
||||
if (led_pins[i].port_buf == &PA_buf)
|
||||
PA_mask |= led_pins[i].pin;
|
||||
else
|
||||
PB_mask |= led_pins[i].pin;
|
||||
}
|
||||
}
|
||||
|
||||
void leds_releaseall() {
|
||||
for (int i=0; i<LED_PINCOUNT; i++)
|
||||
gpio_buf_set(led_pins[i], FLOATING);
|
||||
GPIO_APPLY_ALL();
|
||||
}
|
||||
|
||||
static void led_write2dcol_raw(int dcol, uint32_t val)
|
||||
{
|
||||
// TODO: assert params
|
||||
gpio_buf_set(led_pins[dcol], HIGH);
|
||||
for (int i=0; i<LED_PINCOUNT; i++) {
|
||||
if (i == dcol) continue;
|
||||
gpio_buf_set(led_pins[i], (val & 0x01) ? LOW : FLOATING); // danger: floating=0 (led off) or low=1 (led on)
|
||||
val >>= 1;
|
||||
}
|
||||
GPIO_APPLY_ALL();
|
||||
}
|
||||
|
||||
static uint32_t combine_cols(uint16_t col1_val, uint16_t col2_val)
|
||||
{
|
||||
uint32_t dval = 0;
|
||||
dval |= ((col1_val & 0x01) << (LED_ROWS*2));
|
||||
dval |= ((col2_val & 0x01) << (LED_ROWS*2+1));
|
||||
for (int i=0; i<LED_ROWS; i++) {
|
||||
col1_val >>= 1;
|
||||
col2_val >>= 1;
|
||||
|
||||
dval >>= 2;
|
||||
dval |= ((col1_val & 0x01) << (LED_ROWS*2));
|
||||
dval |= ((col2_val & 0x01) << (LED_ROWS*2+1));
|
||||
}
|
||||
return dval;
|
||||
}
|
||||
|
||||
void led_write2dcol(int dcol, uint16_t col1_val, uint16_t col2_val)
|
||||
{
|
||||
led_write2dcol_raw(dcol, combine_cols(col1_val, col2_val));
|
||||
}
|
||||
|
||||
void led_write2row_raw(int row, int which_half, uint32_t val)
|
||||
{
|
||||
row = row*2 + (which_half != 0);
|
||||
|
||||
gpio_buf_set(led_pins[row], LOW);
|
||||
for (int i=0; i<LED_PINCOUNT; i++) {
|
||||
if (i == row) continue;
|
||||
gpio_buf_set(led_pins[i], (val & 0x01) ? HIGH : FLOATING);
|
||||
val >>= 1;
|
||||
}
|
||||
GPIO_APPLY_ALL();
|
||||
}
|
||||
14
src/leddrv.h
Normal file
14
src/leddrv.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __LEDDRV_H__
|
||||
#define __LEDDRV_H__
|
||||
|
||||
#include "CH58x_common.h"
|
||||
|
||||
#define LED_COLS 44
|
||||
#define LED_ROWS 11
|
||||
|
||||
void led_init();
|
||||
void leds_releaseall();
|
||||
void led_write2dcol(int dcol, uint16_t col1_val, uint16_t col2_val);
|
||||
void led_write2row_raw(int row, int which_half, uint32_t val);
|
||||
|
||||
#endif /* __LEDDRV_H__ */
|
||||
86
src/main.c
86
src/main.c
@ -1,30 +1,88 @@
|
||||
#include "CH58x_common.h"
|
||||
#include "CH58x_sys.h"
|
||||
#include "leddrv.h"
|
||||
|
||||
void led_init(void)
|
||||
#define FB_WIDTH LED_COLS*4
|
||||
#define SCROLL_IRATIO 3
|
||||
|
||||
uint16_t fb[2][FB_WIDTH];
|
||||
|
||||
uint8_t test_font[][11] = {
|
||||
0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xF0, 0x00, // F
|
||||
0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, // O
|
||||
0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0xC6, 0x7C, 0x00, // S
|
||||
0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0xC6, 0x7C, 0x00, // S
|
||||
0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, // A
|
||||
0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0xC6, 0x7C, 0x00, // S
|
||||
0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // I
|
||||
0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, // A
|
||||
};
|
||||
|
||||
void draw2fb(uint16_t *fb, int c, int col)
|
||||
{
|
||||
GPIOA_SetBits(GPIO_Pin_10);
|
||||
GPIOA_ResetBits(GPIO_Pin_12);
|
||||
GPIOA_ModeCfg(GPIO_Pin_10, GPIO_ModeOut_PP_5mA);
|
||||
GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeOut_PP_5mA);
|
||||
uint16_t tmpfb[8] = {0};
|
||||
for (int i=0; i<8; i++) {
|
||||
for (int j=0; j<11; j++) {
|
||||
tmpfb[i] |= ((test_font[c][j] >> (8-i)) & 0x01) << j;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<8; i++) {
|
||||
fb[col+i] = tmpfb[i];
|
||||
}
|
||||
}
|
||||
|
||||
void led_toggle(void)
|
||||
{
|
||||
GPIOA_InverseBits(GPIO_Pin_10);
|
||||
GPIOA_InverseBits(GPIO_Pin_12);
|
||||
}
|
||||
volatile int fb_sel = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
SetSysClock(CLK_SOURCE_PLL_60MHz);
|
||||
|
||||
led_init();
|
||||
draw2fb(fb[0], 0, 8*5);
|
||||
draw2fb(fb[0], 1, 8*6);
|
||||
draw2fb(fb[0], 2, 8*7);
|
||||
draw2fb(fb[0], 3, 8*8);
|
||||
draw2fb(fb[0], 4, 8*9);
|
||||
draw2fb(fb[0], 5, 8*10);
|
||||
draw2fb(fb[0], 6, 8*11);
|
||||
draw2fb(fb[0], 7, 8*12);
|
||||
|
||||
while(1)
|
||||
{
|
||||
mDelaymS(100);
|
||||
led_toggle();
|
||||
draw2fb(fb[1], 4, 8*5);
|
||||
draw2fb(fb[1], 5, 8*6);
|
||||
draw2fb(fb[1], 6, 8*7);
|
||||
draw2fb(fb[1], 7, 8*8);
|
||||
draw2fb(fb[1], 0, 8*9);
|
||||
draw2fb(fb[1], 1, 8*10);
|
||||
draw2fb(fb[1], 2, 8*11);
|
||||
draw2fb(fb[1], 3, 8*12);
|
||||
|
||||
TMR0_TimerInit(1500);
|
||||
TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END);
|
||||
PFIC_EnableIRQ(TMR0_IRQn);
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((interrupt))
|
||||
void TMR0_IRQHandler(void)
|
||||
{
|
||||
static int i, scroll;
|
||||
|
||||
if (TMR0_GetITFlag(TMR0_3_IT_CYC_END)) {
|
||||
|
||||
i += 2;
|
||||
if (i >= LED_COLS) {
|
||||
i = 0;
|
||||
scroll++;
|
||||
if (scroll >= (FB_WIDTH-LED_COLS)*SCROLL_IRATIO) {
|
||||
scroll = 0;
|
||||
fb_sel = fb_sel == 0;
|
||||
}
|
||||
}
|
||||
// This is a mess
|
||||
led_write2dcol(i/2, fb[fb_sel][i+scroll/SCROLL_IRATIO], fb[fb_sel][i+scroll/SCROLL_IRATIO+1]);
|
||||
|
||||
TMR0_ClearITFlag(TMR0_3_IT_CYC_END);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user