sseg: add support for PWM per segment

This commit is contained in:
Thomas Kolb 2024-05-19 21:31:47 +02:00
parent 455118882b
commit c82a54b06c
4 changed files with 44 additions and 8 deletions

View file

@ -132,6 +132,18 @@ static void update_countdown_fsm(uint32_t time_ms)
sseg_set_char(2, 'f', false);
}
{ // animation block
uint32_t modtime = time_in_state % 3000;
if(modtime < 500) {
sseg_set_pwm_percent(0, 100 - 75 * modtime / 500);
} else if(modtime < 1000) {
sseg_set_pwm_percent(1, 100 - 75 * (modtime - 500) / 500);
} else if(modtime < 1500) {
sseg_set_pwm_percent(2, 100 - 75 * (modtime - 1000) / 500);
}
}
if(buttons_get_events(BTN_ON) & BTN_EVENT_PRESSED) {
m_countdown_state = COUNTDOWN_STARTING;
}
@ -148,6 +160,10 @@ static void update_countdown_fsm(uint32_t time_ms)
sseg_set_char(0, '|', false);
sseg_set_char(1, ' ', false);
sseg_set_char(2, ' ', false);
sseg_set_pwm_percent(0, 100);
sseg_set_pwm_percent(1, 100);
sseg_set_pwm_percent(2, 100);
break;
case 500:

View file

@ -23,10 +23,11 @@
#define SSEG_START_PIN 0
static volatile uint32_t m_dma_buffer[4] __attribute__((aligned(4*sizeof(uint32_t *)))) = {
0x0000013D, // segment 0 = 'Z' = '2'
0x00000277, // segment 1 = A
0x00000476, // segment 2 = M
0x00000000, // dummy entry
//AABBDDCC; DD = segment code; CC = PWM off time; BB = multiplexer pins; AA = PWM on time
0xFF013D00, // segment 0 = 'Z' = '2'
0xFF027700, // segment 1 = A
0xFF047600, // segment 2 = M
0x00000000, // dummy entry (all off, for the shortest possible time)
};
static PIO m_pio;
@ -173,5 +174,15 @@ void sseg_loop(void)
void sseg_set_char(uint8_t seg, char c, bool with_dot)
{
uint dot_bit = with_dot ? 0x80 : 0x00;
m_dma_buffer[seg] = (m_dma_buffer[seg] & 0xFFFFFF00) | dot_bit | ascii_to_sseg(c);
m_dma_buffer[seg] = (m_dma_buffer[seg] & 0xFFFF00FF) | ((dot_bit | ascii_to_sseg(c)) << 8);
}
void sseg_set_pwm_times(uint8_t seg, uint8_t on_time, uint8_t off_time)
{
m_dma_buffer[seg] = (m_dma_buffer[seg] & 0x00FFFF00) | ((uint32_t)on_time << 24) | (uint32_t)off_time;
}
void sseg_set_pwm_percent(uint8_t seg, uint8_t on_percent)
{
sseg_set_pwm_times(seg, on_percent, 100-on_percent);
}

View file

@ -9,4 +9,7 @@ void sseg_loop(void);
void sseg_set_char(uint8_t seg, char c, bool with_dot);
void sseg_set_pwm_times(uint8_t seg, uint8_t on_time, uint8_t off_time);
void sseg_set_pwm_percent(uint8_t seg, uint8_t on_percent);
#endif // SSEG_H

View file

@ -3,8 +3,14 @@
; Repeatedly get one word of data from the TX FIFO, stalling when the FIFO is
; empty. Write the least significant bit to the OUT pin group.
loop:
next_digit:
set pins, 0x00 ; set MUX pins to 0
pull
out pins, 11 [31] ; write the data from the FIFO to the outputs and wait some time
jmp loop [31] ; repeat and wait some extra time
out x, 8 ; load "pwm on" cycle count into the scratch register
off_loop:
jmp x--, off_loop
out pins, 16 ; set the segment pins (only the lower 11 bits are used)
out x, 8 ; load "pwm on" cycle count into the scratch register
on_loop:
jmp x--, on_loop
jmp next_digit ; repeat the whole process