From c82a54b06c057bfafab5dff57c981e99ae98a09f Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sun, 19 May 2024 21:31:47 +0200 Subject: [PATCH] sseg: add support for PWM per segment --- src/main.c | 16 ++++++++++++++++ src/sseg.c | 21 ++++++++++++++++----- src/sseg.h | 3 +++ src/sseg.pio | 12 +++++++++--- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/main.c b/src/main.c index 259e6b7..7ebcfa9 100644 --- a/src/main.c +++ b/src/main.c @@ -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: diff --git a/src/sseg.c b/src/sseg.c index 837de28..8eb5296 100644 --- a/src/sseg.c +++ b/src/sseg.c @@ -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); } diff --git a/src/sseg.h b/src/sseg.h index 56edfcf..5ad1d22 100644 --- a/src/sseg.h +++ b/src/sseg.h @@ -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 diff --git a/src/sseg.pio b/src/sseg.pio index bc2a66e..8a318ff 100644 --- a/src/sseg.pio +++ b/src/sseg.pio @@ -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