burst 주파수 옵션 추가: 1.8 MHz ~ 2.3 MHz

This commit is contained in:
2026-07-09 12:17:36 +09:00
parent 7cba63c143
commit 8c0a5d1f49
5 changed files with 247 additions and 103 deletions
+181 -61
View File
@@ -7,6 +7,7 @@
#include <zephyr/drivers/gpio.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/util.h>
#include <hal/nrf_gpiote.h>
#include <hal/nrf_gpio.h>
#include <errno.h>
@@ -23,7 +24,7 @@
#define MUX_SEL0_NODE DT_NODELABEL(mux_sel0)
#define MUX_SEL1_NODE DT_NODELABEL(mux_sel1)
/* 피에조 전원/구동 GPIO */
/* Piezo 전원/구동 GPIO */
static const struct gpio_dt_spec piezo_pwr = GPIO_DT_SPEC_GET(PIEZO_PWR_NODE, gpios);
static const struct gpio_dt_spec piezo_pe = GPIO_DT_SPEC_GET(PIEZO_PE_NODE, gpios);
static const struct gpio_dt_spec piezo_p_out = GPIO_DT_SPEC_GET(PIEZO_P_OUT_NODE, gpios);
@@ -36,7 +37,7 @@ static const struct gpio_dt_spec mux_en_b = GPIO_DT_SPEC_GET(MUX_EN_B_NODE, g
static const struct gpio_dt_spec mux_sel0 = GPIO_DT_SPEC_GET(MUX_SEL0_NODE, gpios);
static const struct gpio_dt_spec mux_sel1 = GPIO_DT_SPEC_GET(MUX_SEL1_NODE, gpios);
/* MUX 제어 상태 */
/* MUX 제어 */
struct mux_state {
uint8_t en_a;
uint8_t en_b;
@@ -44,7 +45,7 @@ struct mux_state {
uint8_t sel1;
};
/* 채널별 MUX EN/SEL 조합 */
/* MUX EN/SEL 조합 */
static const struct mux_state mux_map[PIEZO_NUM_CHANNELS] = {
{1, 0, 0, 0},
{1, 0, 1, 0},
@@ -56,58 +57,32 @@ static const struct mux_state mux_map[PIEZO_NUM_CHANNELS] = {
static bool piezo_initialized;
/* 빠른 GPIO 제어용 절대 핀 */
/* 빠른 GPIO ?어???? ??*/
static uint32_t piezo_pe_abs;
static uint32_t piezo_p_out_abs;
static uint32_t piezo_n_out_abs;
static uint32_t piezo_dmp_abs;
/* 포트 OUT 직접 갱신용 비트 마스크 */
/* PE, P OUT, N OUT, DMP 비트 마스크 */
static uint32_t piezo_pe_mask;
static uint32_t piezo_p_out_mask;
static uint32_t piezo_n_out_mask;
static uint32_t piezo_dmp_mask;
/* 포트 포함 절대 핀 번호 */
/* GPIO 포트 포함한 nRF 절대 핀 번호 계산 */
static uint32_t gpio_abs_pin(const struct gpio_dt_spec *spec)
{
uint32_t port = (spec->port == DEVICE_DT_GET(DT_NODELABEL(gpio1))) ? 1U : 0U;
return NRF_GPIO_PIN_MAP(port, spec->pin);
}
/* 버스트 타이밍용 1사이클 지연 */
/* BURST 타이밍용 1 사이클 지연(1 burst_nop = 15.625 ns) */
static inline void burst_nop(void)
{
__asm__ volatile("nop");
}
/* 짧은 반주기 보정 지연 */
static inline void nop_delay_9(void)
{
burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop();
}
/* 긴 반주기 보정 지연 */
static inline void nop_delay_14(void)
{
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop();
}
/* 댐핑 펄스 폭 지연 */
static inline void nop_delay_32(void)
{
for (int i = 0; i < 32; i++)
{
burst_nop();
}
}
/* 출력/MUX 안전 대기 상태 */
/* 출력/MUX 핀 초기 상태 */
static void piezo_drive_idle(void)
{
nrf_gpio_pin_clear(piezo_pe_abs);
@@ -123,7 +98,6 @@ static void piezo_drive_idle(void)
int piezo_init(void)
{
// 중복 초기화 방지
if (piezo_initialized)
{
return 0;
@@ -138,7 +112,6 @@ int piezo_init(void)
for (size_t i = 0; i < ARRAY_SIZE(pins); i++)
{
// GPIO 포트 준비 확인
if (!device_is_ready(pins[i]->port))
{
DBG_PRINTF("[PIEZO] GPIO device not ready (%d)\r\n", (int)i);
@@ -154,7 +127,6 @@ int piezo_init(void)
}
}
// 직접 제어용 핀/마스크 캐시
piezo_pe_abs = gpio_abs_pin(&piezo_pe);
piezo_p_out_abs = gpio_abs_pin(&piezo_p_out);
piezo_n_out_abs = gpio_abs_pin(&piezo_n_out);
@@ -172,25 +144,21 @@ int piezo_init(void)
void piezo_power_on(void)
{
// 필요 시 자동 초기화
if (!piezo_initialized && piezo_init() != 0)
{
return;
}
// 피에조 전원 인가
gpio_pin_set_dt(&piezo_pwr, 1);
}
void piezo_power_off(void)
{
// 필요 시 자동 초기화
if (!piezo_initialized && piezo_init() != 0)
{
return;
}
// 출력 정지 후 전원 차단
piezo_drive_idle();
gpio_pin_set_dt(&piezo_pwr, 0);
}
@@ -198,7 +166,6 @@ void piezo_power_off(void)
/* Piezo 채널 선택 */
int piezo_select_channel(uint8_t channel)
{
// 필요 시 자동 초기화
if (!piezo_initialized)
{
int err = piezo_init();
@@ -220,24 +187,24 @@ int piezo_select_channel(uint8_t channel)
gpio_pin_set_dt(&mux_sel0, mux_map[channel].sel0);
gpio_pin_set_dt(&mux_sel1, mux_map[channel].sel1);
// MUX 안정화 대기
// MUX 안정화 딜레이
k_busy_wait(PIEZO_MUX_SETTLE_US);
return 0;
}
/* Piezo Burst Switching : 현재는 2.1MHz 고정, 1.8~2.2MHz 추가 예정 */
void piezo_burst_sw(uint8_t cycles)
/* Piezo Burst Switching : 1.8~2.3MHz */
void piezo_burst_sw_freq(uint8_t freq, uint8_t cycles)
{
// 초기화/횟수 검사
// 초기 상태 검사
if (!piezo_initialized || cycles == 0U)
{
return;
}
// 타이밍 흔들림 방지
// 인터럽트 lock
unsigned int key = irq_lock();
// P1 비제어 핀 상태 보존
// P1 상태 설정
uint32_t saved_p1_out = NRF_P1->OUT;
uint32_t p1_ctrl_mask = piezo_p_out_mask | piezo_n_out_mask | piezo_dmp_mask;
uint32_t p1_all_low = saved_p1_out & ~p1_ctrl_mask;
@@ -245,27 +212,180 @@ void piezo_burst_sw(uint8_t cycles)
uint32_t p1_p_low_n_high = p1_all_low | piezo_n_out_mask;
uint32_t p1_dmp_high = p1_all_low | piezo_dmp_mask;
// 구동 Enable 전 초기 Low 정렬
// 초기 상태 all Low
NRF_P0->OUTCLR = piezo_pe_mask;
NRF_P1->OUT = p1_all_low;
NRF_P0->OUTSET = piezo_pe_mask; // PE High
for (uint8_t i = 0; i < cycles; i++)
{
// P High / N Low
NRF_P1->OUT = p1_p_high_n_low;
nop_delay_14();
// PE High ~ P High 사이 딜레이(첫 TX pulse 밀림 방지, 약 1.5 us)
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
// P Low / N High
NRF_P1->OUT = p1_p_low_n_high;
nop_delay_9();
// 주파수별 분기(P, N)
switch (freq)
{
case PIEZO_FREQ_1_8MHZ: // 1.8 MHz
for (uint8_t i = 0U; i < cycles; i++)
{
// P High / N Low = 17
NRF_P1->OUT = p1_p_high_n_low;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop();
// P Low / N High = 12
NRF_P1->OUT = p1_p_low_n_high;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
}
break;
case PIEZO_FREQ_1_9MHZ: // 1.9 MHz
for (uint8_t i = 0U; i < cycles; i++)
{
// P High / N Low = 16
NRF_P1->OUT = p1_p_high_n_low;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
// P Low / N High = 11
NRF_P1->OUT = p1_p_low_n_high;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop();
}
break;
case PIEZO_FREQ_2_0MHZ: // 2.0 MHz
for (uint8_t i = 0U; i < cycles; i++)
{
// P High / N Low = 16
NRF_P1->OUT = p1_p_high_n_low;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
// P Low / N High = 10
NRF_P1->OUT = p1_p_low_n_high;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop();
}
break;
case PIEZO_FREQ_2_1MHZ: // 2.1 MHz
for (uint8_t i = 0U; i < cycles; i++)
{
// P High / N Low = 14
NRF_P1->OUT = p1_p_high_n_low;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop();
// P Low / N High =9
NRF_P1->OUT = p1_p_low_n_high;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop();
}
break;
case PIEZO_FREQ_2_2MHZ: // 2.2 MHz
for (uint8_t i = 0U; i < cycles; i++)
{
// P High / N Low = 13
NRF_P1->OUT = p1_p_high_n_low;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop();
// P Low / N High = 8
NRF_P1->OUT = p1_p_low_n_high;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
}
break;
default: // 2.3 MHz
for (uint8_t i = 0U; i < cycles; i++)
{
// P High / N Low = 12
NRF_P1->OUT = p1_p_high_n_low;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
// P Low / N High = 7
NRF_P1->OUT = p1_p_low_n_high;
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop();
}
break;
}
// 잔류 전하 방전
NRF_P1->OUT = p1_dmp_high;
nop_delay_32(); // DMP High 폭
NRF_P1->OUT = p1_all_low;
// dmp - 잔류 전하 방전(약 2 us)
NRF_P1->OUT = p1_dmp_high; // DMP High
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
burst_nop(); burst_nop(); burst_nop(); burst_nop();
// 출력 Low 복귀
NRF_P1->OUT = p1_all_low;
NRF_P0->OUTCLR = piezo_pe_mask; // PE Low
irq_unlock(key);
+8 -1
View File
@@ -14,10 +14,17 @@
#define PIEZO_POWER_STABILIZE_MS 3
#define PIEZO_BURST_TO_ADC_DELAY_US 10
#define PIEZO_FREQ_1_8MHZ 0U
#define PIEZO_FREQ_1_9MHZ 1U
#define PIEZO_FREQ_2_0MHZ 2U
#define PIEZO_FREQ_2_1MHZ 3U
#define PIEZO_FREQ_2_2MHZ 4U
#define PIEZO_FREQ_2_3MHZ 5U
int piezo_init(void);
void piezo_power_on(void);
void piezo_power_off(void);
int piezo_select_channel(uint8_t channel);
void piezo_burst_sw(uint8_t cycles);
void piezo_burst_sw_freq(uint8_t freq, uint8_t cycles);
#endif /* PIEZO_H__ */