Files
rp2040-hid/src/sevenseg.c

84 lines
2.6 KiB
C

#include "sevenseg.h"
#include <hardware/pio.h>
#include "pinmap.h"
#include "sevenseg.pio.h"
extern PIO pio;
static uint sm;
static uint16_t row_vals[8] = { 0 };
static const int dim = (1 << 3);
static void txnfull_isr(void)
{
static int line = 0;
static int dim_ctr = 0;
while (!pio_sm_is_tx_fifo_full(pio, sm)) {
if (dim_ctr == dim) {
pio_sm_put(pio, sm, (0x1000000lu << line) | (((uint32_t)row_vals[line]) << 8));
} else {
pio_sm_put(pio, sm, (0x1000000lu << line));
}
if (++line >= 8) {
if (dim_ctr++ >= dim)
dim_ctr = 0;
line = 0;
}
}
}
static const uint8_t digit_row_map[NUM_DIGITS] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,
0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71, 0x00, 0x40, 0x63 };
void sevenseg_set_digit(int index, enum sevenseg_digits digit)
{
int dig_idx = (int)digit & 0xff;
for (int i = 0; i < 7; ++i) {
if (digit_row_map[dig_idx] & (1 << i)) {
row_vals[i] |= (1 << index);
} else {
row_vals[i] &= ~(1 << index);
}
}
if (digit & LED_DECIMAL) {
row_vals[7] |= (1 << index);
} else {
row_vals[7] &= ~(1 << index);
}
}
void sevenseg_mod_digit(int index, enum sevenseg_digits digit)
{
if (digit & LED_DECIMAL) {
row_vals[7] |= (1 << index);
} else {
row_vals[7] &= ~(1 << index);
}
}
void sevenseg_init(void)
{
uint offset = pio_add_program(pio, &sevenseg_program);
sm = pio_claim_unused_sm(pio, true);
pio_sm_config c = sevenseg_program_get_default_config(offset);
sm_config_set_out_pins(&c, SEVENSEG_SDO_PIN, 1);
sm_config_set_sideset_pins(&c, SEVENSEG_SCLK_PIN);
sm_config_set_out_shift(&c, false, false, 24);
sm_config_set_clkdiv(&c, 245.28f); // 20 kHz refresh cycle, 53 pio instrs/cycle
pio_sm_set_pindirs_with_mask(
pio, sm,
(1u << SEVENSEG_SDO_PIN) | (1u << SEVENSEG_SCLK_PIN) | (1u << SEVENSEG_FCLK_PIN) | (1u << SEVENSEG_OE_PIN),
(1u << SEVENSEG_SDO_PIN) | (1u << SEVENSEG_SCLK_PIN) | (1u << SEVENSEG_FCLK_PIN) | (1u << SEVENSEG_OE_PIN));
pio_gpio_init(pio, SEVENSEG_SDO_PIN);
pio_gpio_init(pio, SEVENSEG_SCLK_PIN);
pio_gpio_init(pio, SEVENSEG_FCLK_PIN);
pio_gpio_init(pio, SEVENSEG_OE_PIN);
pio_set_irq0_source_enabled(pio, PIO_INTR_SM0_TXNFULL_LSB + sm, true);
irq_set_exclusive_handler(PIO0_IRQ_0, &txnfull_isr);
irq_set_enabled(PIO0_IRQ_0, true);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}