PIO-based glitch controller, untested
This commit is contained in:
parent
f28889a77a
commit
d3654f1762
|
@ -84,6 +84,7 @@ if(FAMILY STREQUAL "rp2040")
|
||||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/sbw.pio)
|
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/sbw.pio)
|
||||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/swim/swim.pio)
|
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/swim/swim.pio)
|
||||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78.pio)
|
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78.pio)
|
||||||
|
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/glitch/trigctl.pio)
|
||||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/test/test.pio)
|
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/test/test.pio)
|
||||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/test/delay.pio)
|
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/test/delay.pio)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <RP2040.h>
|
#include <RP2040.h>
|
||||||
#include <system_RP2040.h>
|
#include <system_RP2040.h>
|
||||||
#include <core_cm0plus.h>
|
#include <core_cm0plus.h>
|
||||||
|
|
||||||
#include <hardware/structs/iobank0.h>
|
#include <hardware/structs/iobank0.h>
|
||||||
#include <hardware/adc.h>
|
#include <hardware/adc.h>
|
||||||
#include <hardware/clocks.h>
|
#include <hardware/clocks.h>
|
||||||
|
@ -20,6 +21,8 @@
|
||||||
|
|
||||||
#include "glitch.h"
|
#include "glitch.h"
|
||||||
|
|
||||||
|
#include "trigctl.pio.h"
|
||||||
|
|
||||||
#define __STRINGIFY(f) #f
|
#define __STRINGIFY(f) #f
|
||||||
#define STRINGIFY(f) __STRINGIFY(f)
|
#define STRINGIFY(f) __STRINGIFY(f)
|
||||||
#define CORE0_FUNC(f) __scratch_x(STRINGIFY(f)) f
|
#define CORE0_FUNC(f) __scratch_x(STRINGIFY(f)) f
|
||||||
|
@ -33,6 +36,50 @@ volatile struct glitch_params glitch_param_cur = {0};
|
||||||
#define PCG_MULTIPLIER 6364136223846793005uLL
|
#define PCG_MULTIPLIER 6364136223846793005uLL
|
||||||
static uint64_t mcg_state = 0xcafef00dd15ea5e5uLL; // Must be odd
|
static uint64_t mcg_state = 0xcafef00dd15ea5e5uLL; // Must be odd
|
||||||
|
|
||||||
|
static PIO trigctl_pio = NULL;
|
||||||
|
static uint trigctl_sm, trigctl_off;
|
||||||
|
|
||||||
|
static int trigctl_pio_can_init(void) {
|
||||||
|
if (pio_can_add_program(pio0, &trigctl_program)) {
|
||||||
|
int r = pio_claim_unused_sm(pio0, false);
|
||||||
|
if (r >= 0) return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pio_can_add_program(pio1, &trigctl_program)) {
|
||||||
|
int r = pio_claim_unused_sm(pio1, false);
|
||||||
|
if (r >= 0) return r + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static void trigctl_pio_alloc_init(int piosm) {
|
||||||
|
trigctl_pio = (piosm & 4) ? pio1 : pio0;
|
||||||
|
trigctl_sm = piosm & 3;
|
||||||
|
|
||||||
|
trigctl_off = pio_add_program(trigctl_pio, &trigctl_program);
|
||||||
|
|
||||||
|
enum trigctl_source src = (param_cur.trigger_in_pin < 0)
|
||||||
|
? trig_source_irq : trig_source_pin;
|
||||||
|
trigctl_pio_init(trigctl_pio, trigctl_sm, trigctl_off,
|
||||||
|
src, param_cur.glitch_out_pin, param_cur.trigger_in_pin,
|
||||||
|
//param_cur.trigger_in_polarity, param_cur.glitch_out_polarity
|
||||||
|
false // disabled by default; needs to be armed
|
||||||
|
);
|
||||||
|
|
||||||
|
param_cur.trigctl_pio = trigctl_pio;
|
||||||
|
param_cur.trigctl_sm = trigctl_sm;
|
||||||
|
}
|
||||||
|
static void trigctl_pio_deinit(void) {
|
||||||
|
if (trigctl_pio) {
|
||||||
|
pio_sm_set_enabled(trigctl_pio, trigctl_sm, false);
|
||||||
|
pio_sm_unclaim(trigctl_pio, trigctl_sm);
|
||||||
|
pio_remove_program(trigctl_pio, &trigctl_program, trigctl_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
trigctl_pio = NULL;
|
||||||
|
trigctl_off = trigctl_sm = ~(uint32_t)0;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t CORE1_FUNC(pcg32_fast)(void) {
|
static uint32_t CORE1_FUNC(pcg32_fast)(void) {
|
||||||
uint64_t x = mcg_state;
|
uint64_t x = mcg_state;
|
||||||
unsigned count = (unsigned)(x >> 61); // 61 = 64 - 3
|
unsigned count = (unsigned)(x >> 61); // 61 = 64 - 3
|
||||||
|
@ -76,98 +123,124 @@ static void CORE1_FUNC(pcg32_fast_init)(uint64_t seed) {
|
||||||
param_cur.length_cur = len; \
|
param_cur.length_cur = len; \
|
||||||
} while (0) \
|
} while (0) \
|
||||||
|
|
||||||
|
__attribute__((__noreturn__))
|
||||||
|
static void CORE1_FUNC(glitch_core1_thread_core1_fifoirq)(void) {
|
||||||
|
int32_t len_prev = param_cur.length_min_us - 1;
|
||||||
|
|
||||||
|
SCB->SCR &= ~SCB_SCR_SEVONPEND_Msk; // don't resume WFE on interrupt
|
||||||
|
|
||||||
|
const int irq = SIO_IRQ_PROC1;
|
||||||
|
|
||||||
|
irq_set_enabled(irq, false);
|
||||||
|
multicore_fifo_clear_irq();
|
||||||
|
irq_set_priority(irq, PICO_HIGHEST_IRQ_PRIORITY);
|
||||||
|
//delayt1_irq_enable(pio0);
|
||||||
|
//irq_set_exclusive_handler(irq, core1_irq);
|
||||||
|
__disable_irq();
|
||||||
|
irq_set_enabled(irq, true);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
CORE1_PRE_CALC();
|
||||||
|
bool arm = *(volatile bool*)¶m_cur.armed;
|
||||||
|
|
||||||
|
__WFI();
|
||||||
|
irq_set_enabled(irq, false);
|
||||||
|
if (!arm) goto continue_;
|
||||||
|
arm = *(volatile bool*)¶m_cur.armed;
|
||||||
|
if (!arm) goto continue_;
|
||||||
|
|
||||||
|
CORE1_DO_GLITCH();
|
||||||
|
multicore_fifo_drain();
|
||||||
|
multicore_fifo_clear_irq();
|
||||||
|
continue_:
|
||||||
|
irq_set_enabled(irq, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__attribute__((__noreturn__))
|
||||||
|
static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) {
|
||||||
|
int32_t len_prev = param_cur.length_min_us - 1;
|
||||||
|
|
||||||
|
// init gpio irq
|
||||||
|
const int gpio = param_cur.trigger_in_pin;
|
||||||
|
const int irq = IO_IRQ_BANK0;
|
||||||
|
// always rising edge: already using input direction override in case
|
||||||
|
// of negative trigger input polarity
|
||||||
|
const int event = /*(param_cur.trigger_in_polarity == glitch_positive)
|
||||||
|
?*/ GPIO_IRQ_EDGE_RISE /*: GPIO_IRQ_EDGE_FALL*/;
|
||||||
|
irq_set_enabled(irq, false);
|
||||||
|
iobank0_hw->intr[gpio>>3] = event << 4*(gpio&7); // acknowledge irq
|
||||||
|
irq_set_priority(irq, PICO_HIGHEST_IRQ_PRIORITY);
|
||||||
|
hw_set_bits(&iobank0_hw->proc1_irq_ctrl.inte[gpio>>3], event << 4*(gpio&7));
|
||||||
|
irq_set_enabled(irq, true);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
CORE1_PRE_CALC();
|
||||||
|
|
||||||
|
__WFI();
|
||||||
|
iobank0_hw->intr[gpio>>3] = event << 4*(gpio&7); // acknowledge irq
|
||||||
|
bool arm = *(volatile bool*)¶m_cur.armed;
|
||||||
|
if (!arm) continue;
|
||||||
|
|
||||||
|
irq_set_enabled(irq, false);
|
||||||
|
//CORE1_DO_GLITCH();
|
||||||
|
busy_wait_us_32(off);
|
||||||
|
if (!(sio_hw->gpio_in & (1u<<gpio))) goto cont;
|
||||||
|
param_cur.offset_cur = off;
|
||||||
|
param_cur.length_cur = len;
|
||||||
|
sio_hw->gpio_set = iom;
|
||||||
|
asm volatile(
|
||||||
|
"1: sub %[counter], #1\n"
|
||||||
|
"cmp %[counter], #0\n"
|
||||||
|
"bne 1b\n"
|
||||||
|
:[counter]"+r"(len)
|
||||||
|
::
|
||||||
|
);
|
||||||
|
//busy_wait_us_32(len);
|
||||||
|
sio_hw->gpio_clr = iom;
|
||||||
|
|
||||||
|
cont:
|
||||||
|
irq_set_enabled(irq, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__attribute__((__noreturn__))
|
||||||
|
static void CORE1_FUNC(glitch_core1_thread_pio)(void) {
|
||||||
|
int32_t len_prev = param_cur.length_min_us - 1;
|
||||||
|
|
||||||
|
const int irq = (trigctl_pio == pio0) ? PIO0_IRQ_1 : PIO1_IRQ_1;
|
||||||
|
irq_set_enabled(irq, false);
|
||||||
|
trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm);
|
||||||
|
trigctl_set_glitch_irq_enabled(trigctl_pio, trigctl_sm, 1, true);
|
||||||
|
irq_set_priority(irq, PICO_HIGHEST_IRQ_PRIORITY);
|
||||||
|
irq_set_enabled(irq, true);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
CORE1_PRE_CALC();
|
||||||
|
(void)iom;
|
||||||
|
trigctl_push_off_len(trigctl_pio, trigctl_sm, off, len);
|
||||||
|
|
||||||
|
trigctl_wait_glitch_irq(trigctl_pio, trigctl_sm, true);
|
||||||
|
trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((__noreturn__))
|
||||||
static void CORE1_FUNC(glitch_core1_thread)(void) {
|
static void CORE1_FUNC(glitch_core1_thread)(void) {
|
||||||
// use stdlib randomness only for the seed, but use a custom rng sitting in
|
// use stdlib randomness only for the seed, but use a custom rng sitting in
|
||||||
// SRAM 5 to avoid bus contention
|
// SRAM 5 to avoid bus contention
|
||||||
pcg32_fast_init(random());
|
pcg32_fast_init(random());
|
||||||
|
|
||||||
int32_t len_prev = param_cur.length_min_us - 1;
|
|
||||||
|
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
|
|
||||||
if (param_cur.trigger_in_pin < 0) {
|
if (param_cur.impl == glitch_impl_pio) {
|
||||||
SCB->SCR &= ~SCB_SCR_SEVONPEND_Msk; // don't resume WFE on interrupt
|
glitch_core1_thread_pio();
|
||||||
|
} else if (param_cur.impl == glitch_impl_core1) {
|
||||||
const int irq = SIO_IRQ_PROC1;
|
if (param_cur.trigger_in_pin < 0) {
|
||||||
|
glitch_core1_thread_core1_fifoirq();
|
||||||
irq_set_enabled(irq, false);
|
} else {
|
||||||
multicore_fifo_clear_irq();
|
glitch_core1_thread_core1_gpio();
|
||||||
irq_set_priority(irq, PICO_HIGHEST_IRQ_PRIORITY);
|
|
||||||
//delayt1_irq_enable(pio0);
|
|
||||||
//irq_set_exclusive_handler(irq, core1_irq);
|
|
||||||
__disable_irq();
|
|
||||||
irq_set_enabled(irq, true);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
CORE1_PRE_CALC();
|
|
||||||
bool arm = *(volatile bool*)¶m_cur.armed;
|
|
||||||
|
|
||||||
__WFI();
|
|
||||||
irq_set_enabled(irq, false);
|
|
||||||
if (!arm) goto continue_;
|
|
||||||
arm = *(volatile bool*)¶m_cur.armed;
|
|
||||||
if (!arm) goto continue_;
|
|
||||||
|
|
||||||
CORE1_DO_GLITCH();
|
|
||||||
multicore_fifo_drain();
|
|
||||||
multicore_fifo_clear_irq();
|
|
||||||
continue_:
|
|
||||||
irq_set_enabled(irq, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*while (true) {
|
|
||||||
CORE1_PRE_CALC();
|
|
||||||
bool arm = *(volatile bool*)¶m_cur.armed;
|
|
||||||
|
|
||||||
__WFE();
|
|
||||||
if (!arm) continue;
|
|
||||||
arm = *(volatile bool*)¶m_cur.armed;
|
|
||||||
if (!arm) continue;
|
|
||||||
|
|
||||||
CORE1_DO_GLITCH();
|
|
||||||
}*/
|
|
||||||
} else {
|
|
||||||
// init gpio irq
|
|
||||||
const int gpio = param_cur.trigger_in_pin;
|
|
||||||
const int irq = IO_IRQ_BANK0;
|
|
||||||
const int event = GPIO_IRQ_EDGE_RISE;
|
|
||||||
irq_set_enabled(irq, false);
|
|
||||||
iobank0_hw->intr[gpio>>3] = event << 4*(gpio&7); // acknowledge irq
|
|
||||||
irq_set_priority(irq, PICO_HIGHEST_IRQ_PRIORITY);
|
|
||||||
hw_set_bits(&iobank0_hw->proc1_irq_ctrl.inte[gpio>>3], event << 4*(gpio&7));
|
|
||||||
irq_set_enabled(irq, true);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
CORE1_PRE_CALC();
|
|
||||||
|
|
||||||
__WFI();
|
|
||||||
iobank0_hw->intr[gpio>>3] = event << 4*(gpio&7); // acknowledge irq
|
|
||||||
bool arm = *(volatile bool*)¶m_cur.armed;
|
|
||||||
if (!arm) continue;
|
|
||||||
|
|
||||||
irq_set_enabled(irq, false);
|
|
||||||
//CORE1_DO_GLITCH();
|
|
||||||
busy_wait_us_32(off);
|
|
||||||
if (!(sio_hw->gpio_in & (1u<<gpio))) goto cont;
|
|
||||||
param_cur.offset_cur = off;
|
|
||||||
param_cur.length_cur = len;
|
|
||||||
sio_hw->gpio_set = iom;
|
|
||||||
asm volatile(
|
|
||||||
"1: sub %[counter], #1\n"
|
|
||||||
"cmp %[counter], #0\n"
|
|
||||||
"bne 1b\n"
|
|
||||||
:[counter]"+r"(len)
|
|
||||||
::
|
|
||||||
);
|
|
||||||
//busy_wait_us_32(len);
|
|
||||||
sio_hw->gpio_clr = iom;
|
|
||||||
|
|
||||||
cont:
|
|
||||||
irq_set_enabled(irq, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: PIO variant?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CORE1_DO_GLITCH
|
#undef CORE1_DO_GLITCH
|
||||||
|
@ -178,7 +251,7 @@ static void CORE0_FUNC(glitch_stop_no_clock_chg)(void) {
|
||||||
|
|
||||||
if (param_cur.impl != glitch_impl__none) {
|
if (param_cur.impl != glitch_impl__none) {
|
||||||
if (param_cur.impl == glitch_impl_pio) {
|
if (param_cur.impl == glitch_impl_pio) {
|
||||||
// TODO: deinit PIO when implemented
|
trigctl_pio_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// deinit GPIO
|
// deinit GPIO
|
||||||
|
@ -234,6 +307,12 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) {
|
||||||
if (params->impl != glitch_impl_core1 && params->impl != glitch_impl_pio)
|
if (params->impl != glitch_impl_core1 && params->impl != glitch_impl_pio)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
int r = 0x99990;
|
||||||
|
if (params->impl == glitch_impl_pio) {
|
||||||
|
r = trigctl_pio_can_init();
|
||||||
|
if (r < 0) return false;
|
||||||
|
}
|
||||||
|
|
||||||
glitch_stop();
|
glitch_stop();
|
||||||
memcpy(¶m_cur, params, sizeof param_cur); // apply new params
|
memcpy(¶m_cur, params, sizeof param_cur); // apply new params
|
||||||
|
|
||||||
|
@ -248,9 +327,15 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) {
|
||||||
vreg_set_voltage(VREG_VOLTAGE_1_15);
|
vreg_set_voltage(VREG_VOLTAGE_1_15);
|
||||||
set_sys_clock_khz(200*1000, true);
|
set_sys_clock_khz(200*1000, true);
|
||||||
|
|
||||||
uint func = GPIO_FUNC_SIO; // TODO: PIO when implemented
|
uint func = GPIO_FUNC_SIO;
|
||||||
|
if (params->impl == glitch_impl_pio) {
|
||||||
|
trigctl_pio_alloc_init(r);
|
||||||
|
func = (trigctl_pio == pio0) ? GPIO_FUNC_PIO0 : GPIO_FUNC_PIO1;
|
||||||
|
}
|
||||||
|
|
||||||
if (params->length_min_us < 0) {
|
if (params->length_min_us < 0) {
|
||||||
|
// FIXME: use a more generic approach (using dragonzap adc)
|
||||||
|
|
||||||
// ADC1: ADC mode
|
// ADC1: ADC mode
|
||||||
adc_init();
|
adc_init();
|
||||||
adc_gpio_init(27);
|
adc_gpio_init(27);
|
||||||
|
@ -287,7 +372,7 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//gpio_put(params->glitch_out_pin, false);
|
//gpio_put(params->glitch_out_pin, false);
|
||||||
// TODO: gpio_set_drive_strength(PIN_PULSE, GPIO_DRIVE_STRENGTH_12MA);
|
//gpio_set_drive_strength(PIN_PULSE, GPIO_DRIVE_STRENGTH_12MA);
|
||||||
//gpio_set_slew_rate(params->glitch_out_pin, GPIO_SLEW_RATE_FAST);
|
//gpio_set_slew_rate(params->glitch_out_pin, GPIO_SLEW_RATE_FAST);
|
||||||
//gpio_set_dir(params->glitch_out_pin, GPIO_OUT);
|
//gpio_set_dir(params->glitch_out_pin, GPIO_OUT);
|
||||||
//gpio_set_outover(params->glitch_out_pin,
|
//gpio_set_outover(params->glitch_out_pin,
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <hardware/pio.h>
|
||||||
|
|
||||||
enum glitch_polarity {
|
enum glitch_polarity {
|
||||||
glitch_positive,
|
glitch_positive,
|
||||||
glitch_negative,
|
glitch_negative,
|
||||||
|
@ -19,6 +21,8 @@ enum glitch_impl {
|
||||||
struct glitch_params {
|
struct glitch_params {
|
||||||
uint32_t offset_min_us;
|
uint32_t offset_min_us;
|
||||||
uint32_t offset_max_us;
|
uint32_t offset_max_us;
|
||||||
|
// FIXME: use a more generic approach (using dragonzap adc)
|
||||||
|
// for using user-tunable lengths (with physical knobs)
|
||||||
int32_t length_min_us;
|
int32_t length_min_us;
|
||||||
int32_t length_max_us;
|
int32_t length_max_us;
|
||||||
int trigger_in_pin; // use -1 for a signal coming from core 0
|
int trigger_in_pin; // use -1 for a signal coming from core 0
|
||||||
|
@ -27,6 +31,8 @@ struct glitch_params {
|
||||||
enum glitch_polarity glitch_out_polarity;
|
enum glitch_polarity glitch_out_polarity;
|
||||||
enum glitch_impl impl;
|
enum glitch_impl impl;
|
||||||
uint32_t offset_cur, length_cur;
|
uint32_t offset_cur, length_cur;
|
||||||
|
PIO trigctl_pio;
|
||||||
|
uint32_t trigctl_sm;
|
||||||
bool armed;
|
bool armed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,14 +47,25 @@ static inline void glitch_trigger_sw_core1(void) {
|
||||||
sio_hw->fifo_wr = 1;
|
sio_hw->fifo_wr = 1;
|
||||||
}
|
}
|
||||||
static inline void glitch_trigger_sw_pio(void) {
|
static inline void glitch_trigger_sw_pio(void) {
|
||||||
// TODO: implement
|
glitch_param_cur.trigctl_pio->irq_force =
|
||||||
|
1 << ((glitch_param_cur.trigctl_sm + 1) & 3);
|
||||||
|
/*trigctl_send_trig_irq(glitch_param_cur.trigctl_pio,
|
||||||
|
glitch_param_cur.trigctl_sm);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void glitch_arm(void) {
|
static inline void glitch_arm(void) {
|
||||||
glitch_param_cur.armed = true;
|
glitch_param_cur.armed = true;
|
||||||
|
if (glitch_param_cur.impl == glitch_impl_pio) {
|
||||||
|
pio_sm_set_enabled(glitch_param_cur.trigctl_pio,
|
||||||
|
glitch_param_cur.trigctl_sm, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static inline void glitch_disarm(void) {
|
static inline void glitch_disarm(void) {
|
||||||
glitch_param_cur.armed = false;
|
glitch_param_cur.armed = false;
|
||||||
|
if (glitch_param_cur.impl == glitch_impl_pio) {
|
||||||
|
pio_sm_set_enabled(glitch_param_cur.trigctl_pio,
|
||||||
|
glitch_param_cur.trigctl_sm, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
|
||||||
|
.program trigctl
|
||||||
|
|
||||||
|
; autopull should be on, depth 32
|
||||||
|
;
|
||||||
|
; input pin 0: trigger input
|
||||||
|
;
|
||||||
|
; set pin 0: glitch output
|
||||||
|
;
|
||||||
|
; irq 0 rel: PIO->CM0 "has glitched" signal
|
||||||
|
; irq 1 rel: CM0->PIO "do a glitch now" signal
|
||||||
|
|
||||||
|
public _start:
|
||||||
|
out x, 32 ; offset
|
||||||
|
out y, 32 ; length
|
||||||
|
|
||||||
|
irq clear 0 rel
|
||||||
|
|
||||||
|
public waitinsn:
|
||||||
|
wait 1 pin 0 ; or "wait irq 1 rel"
|
||||||
|
|
||||||
|
offloop:
|
||||||
|
jmp x-- offloop
|
||||||
|
|
||||||
|
set pins, 1
|
||||||
|
|
||||||
|
lenloop:
|
||||||
|
jmp y-- lenloop
|
||||||
|
|
||||||
|
set pins, 0
|
||||||
|
|
||||||
|
irq set 0 rel
|
||||||
|
|
||||||
|
% c-sdk {
|
||||||
|
|
||||||
|
enum trigctl_source {
|
||||||
|
trig_source_pin,
|
||||||
|
trig_source_irq
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void trigctl_pio_init(PIO pio, uint sm, uint prog_offs,
|
||||||
|
enum trigctl_source trigsrc, uint glitch_pin, uint trig_pin/*,
|
||||||
|
enum glitch_polarity trig_in_pol, enum glitch_polarity glitch_out_pol*/
|
||||||
|
, bool enable) {
|
||||||
|
pio_sm_set_enabled(pio, sm, false);
|
||||||
|
|
||||||
|
if (trigsrc == trig_source_irq) {
|
||||||
|
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
|
||||||
|
pio_encode_wait_irq(true, true, 1);
|
||||||
|
} else {
|
||||||
|
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
|
||||||
|
pio_encode_wait_pin(true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pio_sm_config c = trigctl_program_get_default_config(prog_offs);
|
||||||
|
sm_config_set_set_pins(&c, glitch_pin, 1);
|
||||||
|
sm_config_set_in_pins(&c, trig_pin/*, 1*/);
|
||||||
|
sm_config_set_out_shift(&c, false, true, 32);
|
||||||
|
sm_config_set_in_shift(&c, false, true, 32);
|
||||||
|
sm_config_set_clkdiv(&c, 1);
|
||||||
|
pio_sm_init(pio, sm, prog_offs, &c);
|
||||||
|
|
||||||
|
pio_sm_set_consecutive_pindirs(pio, sm, glitch_pin, 1, true );
|
||||||
|
pio_sm_set_consecutive_pindirs(pio, sm, trig_pin , 1, false);
|
||||||
|
pio_sm_set_pins_with_mask(pio, sm, 0, 1u << glitch_pin);
|
||||||
|
|
||||||
|
pio_sm_set_enabled(pio, sm, enable);
|
||||||
|
pio_gpio_init(pio, glitch_pin);
|
||||||
|
pio_gpio_init(pio, trig_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ony use "use_wfi" when the corresponding IRQ is enabled in the NVIC
|
||||||
|
static inline void trigctl_wait_glitch_irq(PIO pio, uint sm, bool use_wfi) {
|
||||||
|
uint mask = 1u << ((sm + 0) & 3);
|
||||||
|
if (use_wfi) {
|
||||||
|
while (!(pio->irq & mask)) __WFI();
|
||||||
|
} else {
|
||||||
|
while (!(pio->irq & mask)) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void trigctl_ack_glitch_irq(PIO pio, uint sm) {
|
||||||
|
hw_set_bits(&pio->irq, 1 << ((sm + 0) & 3));
|
||||||
|
}
|
||||||
|
// nvic_irqno: corresponding NVIC IRQ will be PIO${pio}_IRQ${nvic_irqno}
|
||||||
|
static inline void trigctl_set_glitch_irq_enabled(PIO pio, uint sm, uint nvic_irqno, bool en) {
|
||||||
|
pio_set_irqn_source_enabled(pio, nvic_irqno, (sm + 0) & 3, en);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static inline void trigctl_send_trig_irq(PIO pio, uint sm) {
|
||||||
|
pio->irq_force = 1 << ((sm + 1) & 3);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
static inline void trigctl_push_off_len(PIO pio, uint sm, uint32_t off, uint32_t len) {
|
||||||
|
while (pio_sm_is_tx_fifo_full(pio, sm)) ;
|
||||||
|
pio->txf[sm] = off;
|
||||||
|
while (pio_sm_is_tx_fifo_full(pio, sm)) ;
|
||||||
|
pio->txf[sm] = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
Loading…
Reference in New Issue