Add drivers for HW
This commit is contained in:
@@ -23,9 +23,15 @@ target_include_directories(rp2040_hid PRIVATE src)
|
|||||||
pico_add_extra_outputs(rp2040_hid)
|
pico_add_extra_outputs(rp2040_hid)
|
||||||
|
|
||||||
add_executable(ledtest
|
add_executable(ledtest
|
||||||
|
src/buttons.c
|
||||||
src/ledtest.c
|
src/ledtest.c
|
||||||
|
src/sevenseg.c
|
||||||
|
src/statusleds.c
|
||||||
|
src/rotary.c
|
||||||
)
|
)
|
||||||
|
|
||||||
pico_generate_pio_header(ledtest ${CMAKE_CURRENT_LIST_DIR}/src/ledtest.pio)
|
pico_generate_pio_header(ledtest ${CMAKE_CURRENT_LIST_DIR}/src/sevenseg.pio)
|
||||||
|
pico_generate_pio_header(ledtest ${CMAKE_CURRENT_LIST_DIR}/src/shift_in.pio)
|
||||||
|
pico_generate_pio_header(ledtest ${CMAKE_CURRENT_LIST_DIR}/src/statusleds.pio)
|
||||||
target_link_libraries(ledtest pico_stdlib hardware_pio)
|
target_link_libraries(ledtest pico_stdlib hardware_pio)
|
||||||
pico_add_extra_outputs(ledtest)
|
pico_add_extra_outputs(ledtest)
|
||||||
|
|||||||
52
src/buttons.c
Normal file
52
src/buttons.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "buttons.h"
|
||||||
|
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include <hardware/pio.h>
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
|
||||||
|
#include "shift_in.pio.h"
|
||||||
|
|
||||||
|
extern PIO pio;
|
||||||
|
static uint sm_but;
|
||||||
|
|
||||||
|
static volatile unsigned int button_val;
|
||||||
|
|
||||||
|
static void rxnempty_isr(void) {
|
||||||
|
if (pio_sm_is_rx_fifo_empty(pio, sm_but)) return;
|
||||||
|
|
||||||
|
static unsigned button_prev = 0;
|
||||||
|
unsigned button_new = button_prev;
|
||||||
|
while (!pio_sm_is_rx_fifo_empty(pio, sm_but)) {
|
||||||
|
button_prev = button_new;
|
||||||
|
button_new = (~pio_sm_get(pio, sm_but)) >> 4;
|
||||||
|
}
|
||||||
|
// debounce, only buttons where button_new and button_prev agree are stored to button_val
|
||||||
|
unsigned button_match = ~(button_new ^ button_prev);
|
||||||
|
button_val = (button_val & ~button_match) | (button_new & button_match);
|
||||||
|
button_prev = button_new;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned buttons_read(void)
|
||||||
|
{
|
||||||
|
return button_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buttons_init(void)
|
||||||
|
{
|
||||||
|
uint offset_but = pio_add_program(pio, &shiftin_program);
|
||||||
|
sm_but = pio_claim_unused_sm(pio, true);
|
||||||
|
pio_sm_config c_but = shiftin_program_get_default_config(offset_but);
|
||||||
|
sm_config_set_in_pins(&c_but, BUTTONS_SDI_PIN);
|
||||||
|
sm_config_set_sideset_pins(&c_but, BUTTONS_CLK_PIN);
|
||||||
|
sm_config_set_in_shift(&c_but, false, false, 24);
|
||||||
|
sm_config_set_clkdiv(&c_but, 2600); // 1 kHz sample rate
|
||||||
|
pio_sm_set_pindirs_with_mask(pio, sm_but, (1u << BUTTONS_CLK_PIN) | (1u << BUTTONS_PL_PIN),
|
||||||
|
(1u << BUTTONS_SDI_PIN) | (1u << BUTTONS_CLK_PIN) | (1u << BUTTONS_PL_PIN));
|
||||||
|
pio_gpio_init(pio, BUTTONS_SDI_PIN);
|
||||||
|
pio_gpio_init(pio, BUTTONS_CLK_PIN);
|
||||||
|
pio_gpio_init(pio, BUTTONS_PL_PIN);
|
||||||
|
pio_set_irq1_source_enabled(pio, PIO_INTR_SM0_RXNEMPTY_LSB+sm_but, true);
|
||||||
|
irq_add_shared_handler(PIO0_IRQ_1, &rxnempty_isr, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
|
||||||
|
pio_sm_init(pio, sm_but, offset_but, &c_but);
|
||||||
|
pio_sm_set_enabled(pio, sm_but, true);
|
||||||
|
}
|
||||||
5
src/buttons.h
Normal file
5
src/buttons.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
unsigned buttons_read(void);
|
||||||
|
|
||||||
|
void buttons_init(void);
|
||||||
126
src/ledtest.c
126
src/ledtest.c
@@ -1,101 +1,55 @@
|
|||||||
#include <stdio.h>
|
#include "buttons.h"
|
||||||
#include <pico/stdlib.h>
|
#include "pinmap.h"
|
||||||
|
#include "rotary.h"
|
||||||
|
#include "sevenseg.h"
|
||||||
|
#include "statusleds.h"
|
||||||
#include <hardware/pio.h>
|
#include <hardware/pio.h>
|
||||||
#include "ledtest.pio.h"
|
#include <pico/stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define SDO_PIN 21
|
PIO pio = pio0;
|
||||||
#define OE_PIN 20
|
|
||||||
#define FCLK_PIN 19
|
|
||||||
#define SCLK_PIN 18
|
|
||||||
|
|
||||||
#define LED1_GPIO 22
|
void rotary_event(int rot_ch, bool ccw) {
|
||||||
|
static int count[4] = { 0 };
|
||||||
static void output_byte_manual(uint8_t val)
|
if (ccw) {
|
||||||
{
|
++count[rot_ch];
|
||||||
gpio_put(FCLK_PIN, false);
|
} else {
|
||||||
gpio_put(SCLK_PIN, false);
|
count[rot_ch] = count[rot_ch] ? count[rot_ch] - 1 : 9;
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
sleep_us(1);
|
|
||||||
gpio_put(SCLK_PIN, false);
|
|
||||||
gpio_put(SDO_PIN, val & 0x1);
|
|
||||||
sleep_us(1);
|
|
||||||
gpio_put(SCLK_PIN, true);
|
|
||||||
val >>= 1;
|
|
||||||
}
|
}
|
||||||
sleep_us(1);
|
sevenseg_set_digit(rot_ch+12, count[rot_ch] % 10);
|
||||||
gpio_put(SCLK_PIN, false);
|
|
||||||
gpio_put(FCLK_PIN, true);
|
|
||||||
sleep_us(1);
|
|
||||||
gpio_put(FCLK_PIN, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PIO pio = pio0;
|
int main(void)
|
||||||
static uint sm;
|
|
||||||
|
|
||||||
static void output_pio(uint32_t val)
|
|
||||||
{
|
{
|
||||||
*(volatile uint32_t*)&pio->txf[sm] = val;
|
setup_default_uart();
|
||||||
}
|
|
||||||
|
|
||||||
void isr_pio0_0(void)
|
rotary_init();
|
||||||
{
|
sevenseg_init();
|
||||||
gpio_put(OE_PIN, false);
|
buttons_init();
|
||||||
// only need to enable outputs after first output
|
statusleds_init();
|
||||||
pio_set_irq0_source_enabled(pio, PIO_INTR_SM0_LSB, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t pattern[] = {
|
irq_set_enabled(PIO0_IRQ_1, true);
|
||||||
0x8001,
|
|
||||||
0x4002,
|
|
||||||
0x2004,
|
|
||||||
0x1008,
|
|
||||||
0x0810,
|
|
||||||
0x0420,
|
|
||||||
0x0240,
|
|
||||||
0x0180,
|
|
||||||
};
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
gpio_init(LED1_GPIO);
|
|
||||||
gpio_set_dir(LED1_GPIO, GPIO_OUT);
|
|
||||||
gpio_put(LED1_GPIO, false);
|
|
||||||
|
|
||||||
gpio_init(SDO_PIN);
|
printf("ledtest.c\n");
|
||||||
gpio_set_dir(SDO_PIN, GPIO_OUT);
|
|
||||||
gpio_put(SDO_PIN, false);
|
|
||||||
gpio_init(OE_PIN);
|
|
||||||
gpio_set_dir(OE_PIN, GPIO_OUT);
|
|
||||||
gpio_put(OE_PIN, true);
|
|
||||||
gpio_init(FCLK_PIN);
|
|
||||||
gpio_set_dir(FCLK_PIN, GPIO_OUT);
|
|
||||||
gpio_put(FCLK_PIN, false);
|
|
||||||
gpio_init(SCLK_PIN);
|
|
||||||
gpio_set_dir(SCLK_PIN, GPIO_OUT);
|
|
||||||
gpio_put(SCLK_PIN, false);
|
|
||||||
|
|
||||||
uint offset = pio_add_program(pio, &ledtest_program);
|
for (int i = 0; i < 4; ++i)
|
||||||
sm = pio_claim_unused_sm(pio, true);
|
sevenseg_set_digit(i + 12, 0);
|
||||||
pio_sm_config c = ledtest_program_get_default_config(offset);
|
|
||||||
sm_config_set_out_pins(&c, SDO_PIN, 1);
|
|
||||||
sm_config_set_sideset_pins(&c, SCLK_PIN);
|
|
||||||
sm_config_set_out_shift(&c, false, false, 16);
|
|
||||||
sm_config_set_clkdiv(&c, 13); // 130 / 13 / 2 = 5 MHz
|
|
||||||
pio_sm_set_pindirs_with_mask(pio, sm, (1u << SDO_PIN) | (1u << SCLK_PIN) | (1u << FCLK_PIN),
|
|
||||||
(1u << SDO_PIN) | (1u << SCLK_PIN) | (1u << FCLK_PIN));
|
|
||||||
pio_gpio_init(pio, SDO_PIN);
|
|
||||||
pio_gpio_init(pio, SCLK_PIN);
|
|
||||||
pio_gpio_init(pio, FCLK_PIN);
|
|
||||||
pio_set_irq0_source_enabled(pio, PIO_INTR_SM0_LSB, true);
|
|
||||||
irq_set_enabled(PIO0_IRQ_0, true);
|
|
||||||
pio_sm_init(pio, sm, offset, &c);
|
|
||||||
pio_sm_set_enabled(pio, sm, true);
|
|
||||||
|
|
||||||
int pos = 0;
|
for (int i = 0; i < 5; ++i)
|
||||||
|
sevenseg_set_digit(i + 3, 0xf);
|
||||||
|
|
||||||
|
int led_time = time_us_32();
|
||||||
|
int led_ctr = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
output_pio(pattern[pos++]<<16);
|
unsigned buttons = buttons_read();
|
||||||
if (pos >= (sizeof(pattern) / sizeof(pattern[0])))
|
for (int i = 0; i < 5; ++i) {
|
||||||
pos = 0;
|
sevenseg_set_digit(i + 3, buttons >> (i * 4) & 0xf);
|
||||||
sleep_ms(100);
|
}
|
||||||
|
if (time_us_32() - led_time >= 1000000) {
|
||||||
|
statusleds_set(1<<led_ctr);
|
||||||
|
led_ctr = led_ctr >= 12 ? 0 : led_ctr+1;
|
||||||
|
led_time = time_us_32();
|
||||||
|
}
|
||||||
|
sleep_ms(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/pinmap.h
Normal file
19
src/pinmap.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define SEVENSEG_SDO_PIN 21
|
||||||
|
#define SEVENSEG_OE_PIN 20
|
||||||
|
#define SEVENSEG_FCLK_PIN 19
|
||||||
|
#define SEVENSEG_SCLK_PIN 18
|
||||||
|
|
||||||
|
#define LED1_GPIO 22
|
||||||
|
|
||||||
|
#define ROTARY_FIRST_GPIO 2
|
||||||
|
|
||||||
|
#define BUTTONS_SDI_PIN 11
|
||||||
|
#define BUTTONS_CLK_PIN 12
|
||||||
|
#define BUTTONS_PL_PIN 13
|
||||||
|
|
||||||
|
#define LEDS_SDO_PIN 17
|
||||||
|
#define LEDS_OE_PIN 16
|
||||||
|
#define LEDS_FCLK_PIN 15
|
||||||
|
#define LEDS_SCLK_PIN 14
|
||||||
71
src/rotary.c
Normal file
71
src/rotary.c
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include "rotary.h"
|
||||||
|
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
|
||||||
|
static int rotary_alarm;
|
||||||
|
static uint64_t rotary_timer_next;
|
||||||
|
|
||||||
|
#define ROTARY_INTERVAL 500
|
||||||
|
|
||||||
|
enum rotary_states {
|
||||||
|
rotary_state_idle = 0,
|
||||||
|
rotary_state_B,
|
||||||
|
rotary_state_A,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void rotary_timer_event(uint alarm_num)
|
||||||
|
{
|
||||||
|
rotary_timer_next += ROTARY_INTERVAL;
|
||||||
|
hardware_alarm_set_target(alarm_num, rotary_timer_next);
|
||||||
|
|
||||||
|
static enum rotary_states state[4] = { rotary_state_idle };
|
||||||
|
static int count[4] = { 0 };
|
||||||
|
bool rot_gpio[8];
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
rot_gpio[i] = gpio_get(ROTARY_FIRST_GPIO + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
switch (state[i]) {
|
||||||
|
case rotary_state_idle:
|
||||||
|
if (!rot_gpio[i * 2] && rot_gpio[i * 2 + 1])
|
||||||
|
state[i] = rotary_state_B;
|
||||||
|
if (rot_gpio[i * 2] && !rot_gpio[i * 2 + 1])
|
||||||
|
state[i] = rotary_state_A;
|
||||||
|
break;
|
||||||
|
case rotary_state_B:
|
||||||
|
if (rot_gpio[i * 2] && rot_gpio[i * 2 + 1])
|
||||||
|
state[i] = rotary_state_idle;
|
||||||
|
if (rot_gpio[i * 2] && !rot_gpio[i * 2 + 1]) {
|
||||||
|
state[i] = rotary_state_A;
|
||||||
|
rotary_event(i, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case rotary_state_A:
|
||||||
|
if (rot_gpio[i * 2] && rot_gpio[i * 2 + 1])
|
||||||
|
state[i] = rotary_state_idle;
|
||||||
|
if (!rot_gpio[i * 2] && rot_gpio[i * 2 + 1]) {
|
||||||
|
state[i] = rotary_state_B;
|
||||||
|
rotary_event(i, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotary_init(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
gpio_init(ROTARY_FIRST_GPIO + i);
|
||||||
|
gpio_set_dir(ROTARY_FIRST_GPIO + i, GPIO_IN);
|
||||||
|
gpio_pull_up(ROTARY_FIRST_GPIO + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotary_alarm = hardware_alarm_claim_unused(true);
|
||||||
|
hardware_alarm_set_callback(rotary_alarm, &rotary_timer_event);
|
||||||
|
rotary_timer_next = time_us_64() + ROTARY_INTERVAL;
|
||||||
|
hardware_alarm_set_target(rotary_alarm, rotary_timer_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
7
src/rotary.h
Normal file
7
src/rotary.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
extern void rotary_event(int rot_ch, bool ccw);
|
||||||
|
|
||||||
|
void rotary_init(void);
|
||||||
73
src/sevenseg.c
Normal file
73
src/sevenseg.c
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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_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);
|
||||||
|
}
|
||||||
28
src/sevenseg.h
Normal file
28
src/sevenseg.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum sevenseg_digits {
|
||||||
|
LED_ZERO = 0,
|
||||||
|
LED_ONE,
|
||||||
|
LED_TWO,
|
||||||
|
LED_THREE,
|
||||||
|
LED_FOUR,
|
||||||
|
LED_FIVE,
|
||||||
|
LED_SIX,
|
||||||
|
LED_SEVEN,
|
||||||
|
LED_EIGHT,
|
||||||
|
LED_NINE,
|
||||||
|
LED_A,
|
||||||
|
LED_B,
|
||||||
|
LED_C,
|
||||||
|
LED_D,
|
||||||
|
LED_E,
|
||||||
|
LED_F,
|
||||||
|
LED_BLANK,
|
||||||
|
LED_MINUS,
|
||||||
|
NUM_DIGITS,
|
||||||
|
LED_DECIMAL = 0x100,
|
||||||
|
};
|
||||||
|
|
||||||
|
void sevenseg_set_digit(int index, enum sevenseg_digits digit);
|
||||||
|
|
||||||
|
void sevenseg_init(void);
|
||||||
12
src/sevenseg.pio
Normal file
12
src/sevenseg.pio
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.program sevenseg
|
||||||
|
.side_set 3
|
||||||
|
|
||||||
|
set x,0 side 0
|
||||||
|
.wrap_target
|
||||||
|
pull noblock side 0
|
||||||
|
loop:
|
||||||
|
out pins, 1 side 0
|
||||||
|
jmp !OSRE loop side 1
|
||||||
|
nop side 6 [2]
|
||||||
|
nop side 4
|
||||||
|
.wrap
|
||||||
10
src/shift_in.pio
Normal file
10
src/shift_in.pio
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.program shiftin
|
||||||
|
.side_set 2
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
set x, 23 side 1 ;; load, clk high
|
||||||
|
loop:
|
||||||
|
in pins, 1 side 2 ;; shift, clk low
|
||||||
|
jmp x-- loop side 3 ;; shift, clk high
|
||||||
|
push side 3 ;; shift, clk high
|
||||||
|
.wrap
|
||||||
55
src/statusleds.c
Normal file
55
src/statusleds.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include "statusleds.h"
|
||||||
|
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include <hardware/pio.h>
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
|
||||||
|
#include "statusleds.pio.h"
|
||||||
|
|
||||||
|
extern PIO pio;
|
||||||
|
static uint sm_leds;
|
||||||
|
|
||||||
|
static const int led_dim = (1 << 2);
|
||||||
|
static uint16_t led_val = 0xffff;
|
||||||
|
|
||||||
|
static void txnfull_isr(void)
|
||||||
|
{
|
||||||
|
static int dim_ctr = 0;
|
||||||
|
while (!pio_sm_is_tx_fifo_full(pio, sm_leds)) {
|
||||||
|
if (dim_ctr == led_dim)
|
||||||
|
pio_sm_put(pio, sm_leds, ((uint32_t)led_val)<<16);
|
||||||
|
else
|
||||||
|
pio_sm_put(pio, sm_leds, 0);
|
||||||
|
dim_ctr = dim_ctr >= led_dim ? 0 : dim_ctr + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void statusleds_set(uint16_t val)
|
||||||
|
{
|
||||||
|
led_val = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void statusleds_init(void)
|
||||||
|
{
|
||||||
|
uint offset_leds = pio_add_program(pio, &statusleds_program);
|
||||||
|
sm_leds = pio_claim_unused_sm(pio, true);
|
||||||
|
pio_sm_config c_leds = statusleds_program_get_default_config(offset_leds);
|
||||||
|
sm_config_set_out_pins(&c_leds, LEDS_SDO_PIN, 1);
|
||||||
|
sm_config_set_sideset_pins(&c_leds, LEDS_SCLK_PIN);
|
||||||
|
sm_config_set_out_shift(&c_leds, false, false, 16);
|
||||||
|
sm_config_set_clkdiv(&c_leds, 394); // 10 kHz refresh cycle, 33 pio instrs/cycle
|
||||||
|
pio_sm_set_pindirs_with_mask(pio, sm_leds, (1u << LEDS_SDO_PIN) | (1u << LEDS_SCLK_PIN) | (1u << LEDS_FCLK_PIN),
|
||||||
|
(1u << LEDS_SDO_PIN) | (1u << LEDS_SCLK_PIN) | (1u << LEDS_FCLK_PIN));
|
||||||
|
pio_gpio_init(pio, LEDS_SDO_PIN);
|
||||||
|
pio_gpio_init(pio, LEDS_SCLK_PIN);
|
||||||
|
pio_gpio_init(pio, LEDS_FCLK_PIN);
|
||||||
|
pio_set_irq1_source_enabled(pio, PIO_INTR_SM0_TXNFULL_LSB+sm_leds, true);
|
||||||
|
irq_add_shared_handler(PIO0_IRQ_1, &txnfull_isr, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
|
||||||
|
pio_sm_init(pio, sm_leds, offset_leds, &c_leds);
|
||||||
|
pio_sm_set_enabled(pio, sm_leds, true);
|
||||||
|
pio_sm_put(pio, sm_leds, 0);
|
||||||
|
|
||||||
|
gpio_init(LEDS_OE_PIN);
|
||||||
|
gpio_set_dir(LEDS_OE_PIN, GPIO_OUT);
|
||||||
|
gpio_put(LEDS_OE_PIN, false);
|
||||||
|
}
|
||||||
7
src/statusleds.h
Normal file
7
src/statusleds.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void statusleds_set(uint16_t val);
|
||||||
|
|
||||||
|
void statusleds_init(void);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
.program ledtest
|
.program statusleds
|
||||||
.side_set 2
|
.side_set 2
|
||||||
|
|
||||||
.wrap_target
|
.wrap_target
|
||||||
@@ -6,5 +6,5 @@ pull side 0
|
|||||||
loop:
|
loop:
|
||||||
out pins, 1 side 0
|
out pins, 1 side 0
|
||||||
jmp !OSRE loop side 1
|
jmp !OSRE loop side 1
|
||||||
irq 0 side 2
|
nop side 2
|
||||||
.wrap
|
.wrap
|
||||||
Reference in New Issue
Block a user