WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 03e8ecb

Browse files
authored
LED: Fix artefacts. (#61)
* LED: Fix artefacts. Basic idea to change the state of the Pins: 1) Tri-State all (will TURN OFF all LEDs) 2) Define correct High/Low value for Pins 3) Drive pins which need driving (will TURN ON correct LEDs) * leddrv: Different implementation. Fix artefacts when using high brightness. Highter drive strength if more than 5 LEDs need to be turned on. * Support 4 different brightness levels.
1 parent 9cda337 commit 03e8ecb

File tree

3 files changed

+148
-103
lines changed

3 files changed

+148
-103
lines changed

src/leddrv.c

Lines changed: 130 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,131 +2,167 @@
22

33
#define LED_PINCOUNT (23)
44

5-
volatile int drive_strength;
5+
static uint32_t g_pindrive_strong;
66

77
typedef enum {
88
FLOATING,
99
LOW,
1010
HIGH,
1111
} tristate_t;
1212

13-
typedef struct {
14-
uint32_t *port_buf;
15-
uint32_t *cfg_buf;
16-
uint32_t pin;
17-
} pinctrl_t;
13+
typedef struct pinbank {
14+
volatile uint8_t *base;
1815

19-
static void gpio_buf_set(pinctrl_t pinctl, tristate_t state)
16+
uint32_t bankpins_mask;
17+
18+
uint32_t out_val;
19+
uint32_t dir_val;
20+
uint32_t drv_val;
21+
} pinbank_t;
22+
23+
typedef struct pindesc {
24+
pinbank_t *bank;
25+
uint32_t pin_mask;
26+
} pindesc_t;
27+
28+
static struct pinbanks {
29+
pinbank_t A;
30+
pinbank_t B;
31+
} g_PinBanks;
32+
33+
34+
static void gpio_pin_set(const pindesc_t *desc, tristate_t state)
2035
{
21-
if (state == FLOATING) {
22-
*(pinctl.cfg_buf) &= ~pinctl.pin;
23-
} else {
24-
if (state == HIGH)
25-
*(pinctl.port_buf) |= pinctl.pin;
26-
else
27-
*(pinctl.port_buf) &= ~pinctl.pin;
28-
29-
*(pinctl.cfg_buf) |= pinctl.pin;
36+
switch(state) {
37+
case FLOATING:
38+
desc->bank->dir_val &= ~desc->pin_mask;
39+
break;
40+
case HIGH:
41+
desc->bank->dir_val |= desc->pin_mask;
42+
desc->bank->out_val |= desc->pin_mask;
43+
break;
44+
default:
45+
desc->bank->dir_val |= desc->pin_mask;
46+
desc->bank->out_val &= ~desc->pin_mask;
3047
}
3148
}
3249

33-
void led_setDriveStrength(int is_20mA)
50+
static void gpio_bank_tristate(pinbank_t *bank)
3451
{
35-
drive_strength = is_20mA;
52+
volatile uint32_t *out = (volatile uint32_t *)(bank->base + GPIO_OUT);
53+
volatile uint32_t *drv = (volatile uint32_t *)(bank->base + GPIO_PD_DRV);
54+
volatile uint32_t *dir = (volatile uint32_t *)(bank->base + GPIO_DIR);
55+
uint32_t bankpins_mask;
56+
57+
// Get state for pins we do NOT control
58+
bankpins_mask = bank->bankpins_mask;
59+
bank->out_val =
60+
(bank->out_val & bankpins_mask) | (*out & ~bankpins_mask);
61+
bank->dir_val =
62+
(bank->dir_val & bankpins_mask) | (*dir & ~bankpins_mask);
63+
bank->drv_val =
64+
(g_pindrive_strong & bank->dir_val & bankpins_mask) | (*drv & ~bankpins_mask);
65+
66+
// ... and tristate pins, we DO control
67+
*dir = (bank->dir_val & ~bankpins_mask);
3668
}
3769

38-
static void gpio_buf_apply(
39-
volatile uint8_t *gpio_base,
40-
uint32_t *port, uint32_t *cfg,
41-
uint32_t *mask)
70+
static void gpio_bank_apply(pinbank_t *bank)
4271
{
43-
if (drive_strength) {
44-
uint32_t *drv = (uint32_t *)(gpio_base + GPIO_PD_DRV);
45-
*drv = (*drv & ~*mask) | (*cfg & *mask);
46-
}
47-
uint32_t *dir = (uint32_t *)(gpio_base + GPIO_DIR);
48-
*dir = (*dir & ~*mask) | (*cfg & *mask);
72+
volatile uint32_t *out = (volatile uint32_t *)(bank->base + GPIO_OUT);
73+
volatile uint32_t *drv = (volatile uint32_t *)(bank->base + GPIO_PD_DRV);
74+
volatile uint32_t *dir = (volatile uint32_t *)(bank->base + GPIO_DIR);
4975

50-
uint32_t *out = (uint32_t *)(gpio_base + GPIO_OUT);
51-
*out = (*out & ~*mask) | (*port & *mask);
76+
*out = bank->out_val;
77+
*drv = bank->drv_val;
78+
*dir = bank->dir_val;
5279
}
5380

54-
static uint32_t PA_buf;
55-
static uint32_t PB_buf;
56-
static uint32_t PAcfg_buf;
57-
static uint32_t PBcfg_buf;
58-
static uint32_t PA_mask;
59-
static uint32_t PB_mask;
60-
61-
#define GPIO_APPLY_ALL() \
62-
gpio_buf_apply(BA_PA, &PA_buf, &PAcfg_buf, &PA_mask); \
63-
gpio_buf_apply(BA_PB, &PB_buf, &PBcfg_buf, &PB_mask)
64-
65-
#define PINCTRL(x, pin) { \
66-
&P##x##_buf, \
67-
&P##x##cfg_buf, \
68-
GPIO_Pin_##pin \
81+
#define GPIO_APPLY_ALL() do { \
82+
gpio_bank_tristate(&g_PinBanks.A); \
83+
gpio_bank_tristate(&g_PinBanks.B); \
84+
gpio_bank_apply(&g_PinBanks.A); \
85+
gpio_bank_apply(&g_PinBanks.B); \
86+
} while (0)
87+
88+
89+
#define PINDESC(bank_, pinnr_) { \
90+
&g_PinBanks.bank_ , \
91+
GPIO_Pin_##pinnr_ \
6992
}
7093

71-
static const pinctrl_t led_pins[LED_PINCOUNT] = {
72-
PINCTRL(A, 15), // A
73-
PINCTRL(B, 18), // B
74-
PINCTRL(B, 0), // C
75-
PINCTRL(B, 7), // D
76-
PINCTRL(A, 12), // E
77-
PINCTRL(A, 10), // F
78-
PINCTRL(A, 11), // G
79-
PINCTRL(B, 9), // H
80-
PINCTRL(B, 8), // I
81-
PINCTRL(B, 15), // J
82-
PINCTRL(B, 14), // K
83-
PINCTRL(B, 13), // L
84-
PINCTRL(B, 12), // M
85-
PINCTRL(B, 5), // N
86-
PINCTRL(A, 4), // O
87-
PINCTRL(B, 3), // P
88-
PINCTRL(B, 4), // Q
89-
PINCTRL(B, 2), // R
90-
PINCTRL(B, 1), // S
94+
static const pindesc_t led_pins[LED_PINCOUNT] = {
95+
PINDESC(A, 15), // A
96+
PINDESC(B, 18), // B
97+
PINDESC(B, 0), // C
98+
PINDESC(B, 7), // D
99+
PINDESC(A, 12), // E
100+
PINDESC(A, 10), // F
101+
PINDESC(A, 11), // G
102+
PINDESC(B, 9), // H
103+
PINDESC(B, 8), // I
104+
PINDESC(B, 15), // J
105+
PINDESC(B, 14), // K
106+
PINDESC(B, 13), // L
107+
PINDESC(B, 12), // M
108+
PINDESC(B, 5), // N
109+
PINDESC(A, 4), // O
110+
PINDESC(B, 3), // P
111+
PINDESC(B, 4), // Q
112+
PINDESC(B, 2), // R
113+
PINDESC(B, 1), // S
91114
#ifdef USBC_VERSION
92-
PINCTRL(B, 6), // T
115+
PINDESC(B, 6), // T
93116
#else
94-
PINCTRL(B, 23), // T
117+
PINDESC(B, 23), // T
95118
#endif
96-
PINCTRL(B, 21), // U
97-
PINCTRL(B, 20), // V
98-
PINCTRL(B, 19), // W
119+
PINDESC(B, 21), // U
120+
PINDESC(B, 20), // V
121+
PINDESC(B, 19), // W
99122
};
100123

101124
void led_init()
102125
{
103-
for (int i=0; i<LED_PINCOUNT; i++) {
104-
if (led_pins[i].port_buf == &PA_buf)
105-
PA_mask |= led_pins[i].pin;
106-
else
107-
PB_mask |= led_pins[i].pin;
126+
int i;
127+
128+
g_PinBanks.A.base = BA_PA;
129+
g_PinBanks.B.base = BA_PB;
130+
for (i = 0; i < LED_PINCOUNT; i++) {
131+
led_pins[i].bank->bankpins_mask |= led_pins[i].pin_mask;
108132
}
109133
}
110134

111135
void leds_releaseall() {
112136
for (int i=0; i<LED_PINCOUNT; i++)
113-
gpio_buf_set(led_pins[i], FLOATING);
137+
gpio_pin_set(led_pins + i, FLOATING);
138+
g_pindrive_strong = 0x00000000;
114139
GPIO_APPLY_ALL();
115140
}
116141

117142
static void led_write2dcol_raw(int dcol, uint32_t val)
118143
{
119-
// TODO: assert params
120-
gpio_buf_set(led_pins[dcol], HIGH);
144+
int on_count;
145+
int pin_value;
146+
147+
gpio_pin_set(led_pins + dcol, HIGH);
148+
on_count = 0;
121149
for (int i=0; i<LED_PINCOUNT; i++) {
122150
if (i == dcol) continue;
123-
gpio_buf_set(led_pins[i], (val & 0x01) ? LOW : FLOATING); // danger: floating=0 (led off) or low=1 (led on)
151+
pin_value = FLOATING;
152+
if (val & 0x01) {
153+
on_count++;
154+
pin_value = LOW; // pin LOW => LED on
155+
}
156+
gpio_pin_set(led_pins + i, pin_value);
124157
val >>= 1;
125158
}
159+
g_pindrive_strong = 0x00000000;
160+
if (on_count > 5)
161+
g_pindrive_strong = 0xFFFFFFFF;
126162
GPIO_APPLY_ALL();
127163
}
128164

129-
static uint32_t combine_cols(uint16_t col1_val, uint16_t col2_val)
165+
static uint32_t combine_cols(uint16_t col1_val, uint16_t col2_val)
130166
{
131167
uint32_t dval = 0;
132168
dval |= ((col1_val & 0x01) << (LED_ROWS*2));
@@ -156,13 +192,24 @@ void led_write2dcol(int dcol, uint16_t col1_val, uint16_t col2_val)
156192

157193
void led_write2row_raw(int row, int which_half, uint32_t val)
158194
{
159-
row = row*2 + (which_half != 0);
195+
int on_count;
196+
int pin_value;
160197

161-
gpio_buf_set(led_pins[row], LOW);
198+
row = row*2 + (which_half != 0);
199+
gpio_pin_set(led_pins + row, LOW);
200+
on_count = 0;
162201
for (int i=0; i<LED_PINCOUNT; i++) {
163202
if (i == row) continue;
164-
gpio_buf_set(led_pins[i], (val & 0x01) ? HIGH : FLOATING);
203+
pin_value = FLOATING;
204+
if (val & 0x01) {
205+
on_count++;
206+
pin_value = HIGH;
207+
}
208+
gpio_pin_set(led_pins + i, pin_value);
165209
val >>= 1;
166210
}
211+
g_pindrive_strong = 0x00000000;
212+
if (on_count > 5)
213+
g_pindrive_strong = 0xFFFFFFFF;
167214
GPIO_APPLY_ALL();
168215
}

src/leddrv.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@ void led_init();
1010
void leds_releaseall();
1111
void led_write2dcol(int dcol, uint16_t col1_val, uint16_t col2_val);
1212
void led_write2row_raw(int row, int which_half, uint32_t val);
13-
void led_setDriveStrength(int is_20mA);
1413

1514
#endif /* __LEDDRV_H__ */

src/main.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ __HIGH_CODE
6060
static void change_brightness()
6161
{
6262
NEXT_STATE(brightness, 0, BRIGHTNESS_LEVELS);
63-
led_setDriveStrength(brightness / 2);
6463
}
6564

6665
__HIGH_CODE
@@ -272,7 +271,7 @@ void spawn_tasks()
272271

273272
tmos_start_reload_task(common_taskid, ANI_MARQUE, ANI_MARQUE_SPEED_T / 625);
274273
tmos_start_reload_task(common_taskid, ANI_FLASH, ANI_FLASH_SPEED_T / 625);
275-
tmos_start_reload_task(common_taskid, SCAN_BOOTLD_BTN,
274+
tmos_start_reload_task(common_taskid, SCAN_BOOTLD_BTN,
276275
SCAN_BOOTLD_BTN_SPEED_T / 625);
277276
tmos_start_task(common_taskid, ANI_NEXT_STEP, 500000 / 625);
278277
}
@@ -300,20 +299,20 @@ void handle_mode_transition()
300299
// Disable bitmap transition while in download mode
301300
btn_onOnePress(KEY2, NULL);
302301

303-
// Take control of the current bitmap to display
302+
// Take control of the current bitmap to display
304303
// the Bluetooth animation
305304
ble_start();
306305
while (mode == DOWNLOAD) {
307306
TMOS_SystemProcess();
308307
}
309-
// If not being flashed, pressing KEY1 again will
308+
// If not being flashed, pressing KEY1 again will
310309
// make the badge goes off:
311-
310+
312311
// fallthrough
313312
case POWER_OFF:
314313
poweroff();
315314
break;
316-
315+
317316
default:
318317
break;
319318
}
@@ -402,7 +401,7 @@ static void fb_putchar(char c, int col, int row)
402401
{
403402
for (int i=0; i < 6; i++) {
404403
if (col + i >= LED_COLS) break;
405-
fb[col + i] = (fb[col + i] & ~(0x7f << row))
404+
fb[col + i] = (fb[col + i] & ~(0x7f << row))
406405
| (font5x7[c - ' '][i] << row);
407406
}
408407
}
@@ -450,7 +449,7 @@ int main()
450449
usb_start();
451450

452451
led_init();
453-
TMR0_TimerInit(SCAN_T / 2);
452+
TMR0_TimerInit(SCAN_T / 4);
454453
TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END);
455454
PFIC_EnableIRQ(TMR0_IRQn);
456455

@@ -462,7 +461,7 @@ int main()
462461
btn_onLongPress(KEY1, change_brightness);
463462

464463
disp_charging();
465-
464+
466465
play_splash(&splash, 0, 0);
467466

468467
load_bmlist();
@@ -483,19 +482,19 @@ __HIGH_CODE
483482
void TMR0_IRQHandler(void)
484483
{
485484
static int i;
485+
int state;
486486

487487
if (TMR0_GetITFlag(TMR0_3_IT_CYC_END)) {
488-
i += 1;
489-
if (i >= LED_COLS) {
490-
i = 0;
491-
}
492-
493-
if (i % 2) {
494-
if ((brightness + 1) % 2)
495-
leds_releaseall();
496-
} else {
497-
led_write2dcol(i/2, fb[i], fb[i + 1]);
488+
i++;
489+
state = i&3;
490+
491+
if (state == 0) {
492+
if ((i >> 1) >= LED_COLS)
493+
i = 0;
494+
led_write2dcol(i >> 2, fb[i >> 1], fb[(i >> 1) + 1]);
498495
}
496+
else if (state > (brightness&3))
497+
leds_releaseall();
499498

500499
TMR0_ClearITFlag(TMR0_3_IT_CYC_END);
501500
}

0 commit comments

Comments
 (0)