Files
microchip-application-bmd38…/cpg11_io.c
T
Roy_01 8db81a445c fix: 1. upon startup, the state of all electrodes is highZ (the control of GPIOs follows a specific order)
2. the state is idle before starting and after finishing the pulse generation
2024-08-29 09:56:08 +08:00

409 lines
13 KiB
C

#include "elite_board.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "nrf_log.h"
#include "nrf_spim.h"
#include "nrf_timer.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#pragma GCC optimize("O2")
#if (DEF_ELITE_MODEL == DEF_CURRENT_PULSE_GANERATOR_11)
typedef struct
{
const uint32_t gpiote_idx[4];
NRF_TIMER_Type *TMR_A;
NRF_TIMER_Type *TMR_B;
uint32_t IRQn;
pusle_gen_t *p_pusle_gen;
uint32_t pusle_gen_len;
uint32_t pusle_gen_sel;
} pusle_gen_hw_t;
pusle_gen_hw_t pusle_gen_hw[] = {
{{ 0, 1, 2, 3 },
NRF_TIMER1,
NRF_TIMER3,
TIMER3_IRQn,
NULL,
0,
0},
{{ 4, 5, 6, 7 },
NRF_TIMER2,
NRF_TIMER4,
TIMER4_IRQn,
NULL,
0,
0},
};
__STATIC_INLINE void cpg11_tmr_cb(uint32_t hw_idx)
{
if (pusle_gen_hw[hw_idx].TMR_B->EVENTS_COMPARE[4])
{
pusle_gen_hw[hw_idx].TMR_B->EVENTS_COMPARE[4] = 0;
uint32_t sel = pusle_gen_hw[hw_idx].pusle_gen_sel;
if (pusle_gen_hw[hw_idx].p_pusle_gen[sel].pulse_cnt > 0)
{
pusle_gen_hw[hw_idx].p_pusle_gen[sel].pulse_cnt--;
}
for (uint32_t i = 0; i < pusle_gen_hw[hw_idx].pusle_gen_len; i++)
{
sel = (sel + 1) % pusle_gen_hw[hw_idx].pusle_gen_len;
if (pusle_gen_hw[hw_idx].p_pusle_gen[sel].pulse_cnt > 0)
{
pusle_gen_hw[hw_idx].pusle_gen_sel = sel;
cpg11_pulse_start(hw_idx, &pusle_gen_hw[hw_idx].p_pusle_gen[sel]);
return;
}
}
}
}
void TIMER3_IRQHandler(void)
{
cpg11_tmr_cb(0);
}
void TIMER4_IRQHandler(void)
{
cpg11_tmr_cb(1);
}
void cpg11_pulse_stop_by_pulse_id(uint32_t pulse_id)
{
for (uint32_t i = 0; i < COUNTOF(pusle_gen_hw); i++)
{
for (uint32_t j = 0; j < pusle_gen_hw[i].pusle_gen_len; j++)
{
if (pusle_gen_hw[i].p_pusle_gen[j].pulse_id == pulse_id)
{
taskENTER_CRITICAL();
pusle_gen_hw[i].p_pusle_gen[j].VAxH = 0xFFFFFFFF;
pusle_gen_hw[i].p_pusle_gen[j].VBxH = 0xFFFFFFFF;
pusle_gen_hw[i].p_pusle_gen[j].VAxL = 0xFFFFFFFF;
pusle_gen_hw[i].p_pusle_gen[j].VBxL = 0xFFFFFFFF;
taskEXIT_CRITICAL();
}
}
}
}
void cpg11_pulse_start(uint32_t hw_idx, pusle_gen_t *p_pusle_gen)
{
pusle_gen_hw[hw_idx].TMR_B->TASKS_STOP = 1;
pusle_gen_hw[hw_idx].TMR_A->TASKS_STOP = 1;
sd_nvic_DisableIRQ(pusle_gen_hw[hw_idx].IRQn);
sd_nvic_ClearPendingIRQ(pusle_gen_hw[hw_idx].IRQn);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[0]);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[1]);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[2]);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[3]);
nrf_gpiote_task_configure(pusle_gen_hw[hw_idx].gpiote_idx[0], p_pusle_gen->VBxH, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(pusle_gen_hw[hw_idx].gpiote_idx[1], p_pusle_gen->VBxL, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_configure(pusle_gen_hw[hw_idx].gpiote_idx[2], p_pusle_gen->VAxH, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(pusle_gen_hw[hw_idx].gpiote_idx[3], p_pusle_gen->VAxL, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(pusle_gen_hw[hw_idx].gpiote_idx[0]);
nrf_gpiote_task_enable(pusle_gen_hw[hw_idx].gpiote_idx[1]);
nrf_gpiote_task_enable(pusle_gen_hw[hw_idx].gpiote_idx[2]);
nrf_gpiote_task_enable(pusle_gen_hw[hw_idx].gpiote_idx[3]);
uint32_t offs = 8 * hw_idx;
NRF_PPI->CH[offs + 0].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_A->EVENTS_COMPARE[0];
NRF_PPI->CH[offs + 0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[0]];
NRF_PPI->CHENSET = (1 << (offs + 0));
NRF_PPI->CH[offs + 1].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_A->EVENTS_COMPARE[1];
NRF_PPI->CH[offs + 1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[1]];
NRF_PPI->CHENSET = (1 << (offs + 1));
NRF_PPI->CH[offs + 2].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_A->EVENTS_COMPARE[2];
NRF_PPI->CH[offs + 2].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[1]];
NRF_PPI->CHENSET = (1 << (offs + 2));
NRF_PPI->CH[offs + 3].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_A->EVENTS_COMPARE[3];
NRF_PPI->CH[offs + 3].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[0]];
NRF_PPI->FORK[offs + 3].TEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_B->TASKS_START;
NRF_PPI->CHENSET = (1 << (offs + 3));
NRF_PPI->CH[offs + 4].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_B->EVENTS_COMPARE[0];
NRF_PPI->CH[offs + 4].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[2]];
NRF_PPI->CHENSET = (1 << (offs + 4));
NRF_PPI->CH[offs + 5].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_B->EVENTS_COMPARE[1];
NRF_PPI->CH[offs + 5].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[3]];
NRF_PPI->CHENSET = (1 << (offs + 5));
NRF_PPI->CH[offs + 6].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_B->EVENTS_COMPARE[2];
NRF_PPI->CH[offs + 6].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[3]];
NRF_PPI->CHENSET = (1 << (offs + 6));
NRF_PPI->CH[offs + 7].EEP = (uint32_t)&pusle_gen_hw[hw_idx].TMR_B->EVENTS_COMPARE[3];
NRF_PPI->CH[offs + 7].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pusle_gen_hw[hw_idx].gpiote_idx[2]];
NRF_PPI->CHENSET = (1 << (offs + 7));
pusle_gen_hw[hw_idx].TMR_B->TASKS_CLEAR = 1;
pusle_gen_hw[hw_idx].TMR_A->TASKS_CLEAR = 1;
pusle_gen_hw[hw_idx].TMR_B->CC[0] = 1 + p_pusle_gen->point_us[3] * 16;
pusle_gen_hw[hw_idx].TMR_B->CC[1] = pusle_gen_hw[hw_idx].TMR_B->CC[0] + p_pusle_gen->point_us[4] * 16;
pusle_gen_hw[hw_idx].TMR_B->CC[2] = pusle_gen_hw[hw_idx].TMR_B->CC[1] + p_pusle_gen->point_us[5] * 16;
pusle_gen_hw[hw_idx].TMR_B->CC[3] = pusle_gen_hw[hw_idx].TMR_B->CC[2] + p_pusle_gen->point_us[6] * 16;
pusle_gen_hw[hw_idx].TMR_B->CC[4] = pusle_gen_hw[hw_idx].TMR_B->CC[3] + p_pusle_gen->idle_us * 16;
pusle_gen_hw[hw_idx].TMR_B->SHORTS = NRF_TIMER_SHORT_COMPARE4_STOP_MASK | NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK;
pusle_gen_hw[hw_idx].TMR_B->INTENSET = NRF_TIMER_INT_COMPARE4_MASK;
pusle_gen_hw[hw_idx].TMR_A->CC[0] = 1;
pusle_gen_hw[hw_idx].TMR_A->CC[1] = pusle_gen_hw[hw_idx].TMR_A->CC[0] + p_pusle_gen->point_us[0] * 16;
pusle_gen_hw[hw_idx].TMR_A->CC[2] = pusle_gen_hw[hw_idx].TMR_A->CC[1] + p_pusle_gen->point_us[1] * 16;
pusle_gen_hw[hw_idx].TMR_A->CC[3] = pusle_gen_hw[hw_idx].TMR_A->CC[2] + p_pusle_gen->point_us[2] * 16;
pusle_gen_hw[hw_idx].TMR_A->SHORTS = NRF_TIMER_SHORT_COMPARE3_STOP_MASK | NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK;
sd_nvic_EnableIRQ(pusle_gen_hw[hw_idx].IRQn);
pusle_gen_hw[hw_idx].TMR_A->TASKS_START = 1;
}
void cpg11_pulse_init(uint32_t hw_idx, pusle_gen_t *p_pusle_gen, uint32_t len)
{
taskENTER_CRITICAL();
if (pusle_gen_hw[hw_idx].p_pusle_gen)
{
pusle_gen_hw[hw_idx].TMR_B->TASKS_STOP = 1;
pusle_gen_hw[hw_idx].TMR_A->TASKS_STOP = 1;
sd_nvic_DisableIRQ(pusle_gen_hw[hw_idx].IRQn);
sd_nvic_ClearPendingIRQ(pusle_gen_hw[hw_idx].IRQn);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[0]);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[1]);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[2]);
nrf_gpiote_task_disable(pusle_gen_hw[hw_idx].gpiote_idx[3]);
}
pusle_gen_hw[hw_idx].p_pusle_gen = p_pusle_gen;
pusle_gen_hw[hw_idx].pusle_gen_len = len;
pusle_gen_hw[hw_idx].pusle_gen_sel = 0;
for (uint32_t i = 0; i < len; i++)
{
nrf_gpio_pin_clear(p_pusle_gen[i].VBxL);
nrf_gpio_pin_set(p_pusle_gen[i].VBxH);
nrf_gpio_pin_clear(p_pusle_gen[i].VAxL);
nrf_gpio_pin_set(p_pusle_gen[i].VAxH);
}
taskEXIT_CRITICAL();
};
void cpg_pulse_default_demo_ext(void)
{
uint32_t pusle_gen_numb = 2;
pusle_gen_t *p_pusle_genA = pvPortMalloc(sizeof(pusle_gen_t) * pusle_gen_numb);
pusle_gen_t *p_pusle_genB = pvPortMalloc(sizeof(pusle_gen_t) * pusle_gen_numb);
memset(p_pusle_genA, 0x00, sizeof(pusle_gen_t) * pusle_gen_numb);
memset(p_pusle_genB, 0x00, sizeof(pusle_gen_t) * pusle_gen_numb);
if (pusle_gen_numb > 0)
{
p_pusle_genA[0] = (pusle_gen_t) {
.VBxH = VB1H_PIN,
.VBxL = VB1L_PIN,
.VAxH = VA1H_PIN,
.VAxL = VA1L_PIN,
.point_us[0] = 1,
.point_us[1] = 50,
.point_us[2] = 1,
.point_us[3] = 0,
.point_us[4] = 1,
.point_us[5] = 50,
.point_us[6] = 1,
.idle_us = 1000,
.pulse_cnt = UINT32_MAX,
.pulse_id = 0,
};
}
if (pusle_gen_numb > 1)
{
p_pusle_genA[1] = (pusle_gen_t) {
.VBxH = VB2H_PIN,
.VBxL = VB2L_PIN,
.VAxH = VA2H_PIN,
.VAxL = VA2L_PIN,
.point_us[0] = 1,
.point_us[1] = 50,
.point_us[2] = 1,
.point_us[3] = 0,
.point_us[4] = 1,
.point_us[5] = 50,
.point_us[6] = 1,
.idle_us = 1000,
.pulse_cnt = UINT32_MAX,
.pulse_id = 1,
};
}
if (pusle_gen_numb > 0)
{
p_pusle_genB[0] = (pusle_gen_t) {
.VBxH = VB3H_PIN,
.VBxL = VB3L_PIN,
.VAxH = VA3H_PIN,
.VAxL = VA3L_PIN,
.point_us[0] = 1,
.point_us[1] = 50,
.point_us[2] = 1,
.point_us[3] = 0,
.point_us[4] = 1,
.point_us[5] = 50,
.point_us[6] = 1,
.idle_us = 1000,
.pulse_cnt = UINT32_MAX,
.pulse_id = 2,
};
}
if (pusle_gen_numb > 1)
{
p_pusle_genB[1] = (pusle_gen_t) {
.VBxH = VB4H_PIN,
.VBxL = VB4L_PIN,
.VAxH = VA4H_PIN,
.VAxL = VA4L_PIN,
.point_us[0] = 1,
.point_us[1] = 50,
.point_us[2] = 1,
.point_us[3] = 0,
.point_us[4] = 1,
.point_us[5] = 50,
.point_us[6] = 1,
.idle_us = 1000,
.pulse_cnt = UINT32_MAX,
.pulse_id = 3,
};
}
cpg11_pulse_init(0, p_pusle_genA, pusle_gen_numb);
cpg11_pulse_init(1, p_pusle_genB, pusle_gen_numb);
cpg11_pulse_start(0, p_pusle_genA);
cpg11_pulse_start(1, p_pusle_genB);
vTaskDelay(10);
// cpg11_pulse_stop_by_pulse_id(p_pusle_gen[0].pulse_id);
// cpg11_pulse_stop_by_pulse_id(p_pusle_gen[1].pulse_id);
// cpg11_pulse_stop_by_pulse_id(p_pusle_gen[2].pulse_id);
// cpg11_pulse_stop_by_pulse_id(p_pusle_gen[3].pulse_id);
// cpg11_pulse_stop_by_pulse_id(p_pusle_gen[4].pulse_id);
vPortFree(p_pusle_genA);
vPortFree(p_pusle_genB);
for (;;)
{
}
}
void cpg11_io_init(void)
{
const uint32_t pel_pins_default_high[] = {
LED_R_PIN,
LED_G_PIN,
LED_B_PIN,
CS_MEM_PIN
};
const uint32_t pel_pins_default_low[] = {
TW_SCKI_0_PIN,
TW_SCKI_1_PIN,
ADPT_CLK,
HV_EN_PIN,
SPIM_CLK_PIN,
SPIM_MOSI_PIN,
SPIM_MISO_PIN,
ADPT_LE_PIN,
ADPT_CLR_PIN,
ADPT0_S4_PIN,
ADPT0_S3_PIN,
ADPT0_S2_PIN,
ADPT0_S1_PIN,
ADPT1_S4_PIN,
ADPT1_S3_PIN,
ADPT1_S2_PIN,
ADPT1_S1_PIN,
VB1L_PIN,
VB1H_PIN,
VA1L_PIN,
VA1H_PIN,
VB2L_PIN,
VB2H_PIN,
VA2L_PIN,
VA2H_PIN,
VB3L_PIN,
VB3H_PIN,
VA3L_PIN,
VA3H_PIN,
VB4L_PIN,
VB4H_PIN,
VA4L_PIN,
VA4H_PIN,
};
for (int i = 0; i < COUNTOF(pel_pins_default_high); i++)
{
nrf_gpio_cfg_output(pel_pins_default_high[i]);
nrf_gpio_pin_set(pel_pins_default_high[i]);
}
for (int i = 0; i < COUNTOF(pel_pins_default_low); i++)
{
nrf_gpio_cfg_output(pel_pins_default_low[i]);
nrf_gpio_pin_clear(pel_pins_default_low[i]);
}
nrf_gpio_cfg_input(AIN0_PIN, NRF_GPIO_PIN_NOPULL);
nrf_gpio_cfg_input(AIN1_PIN, NRF_GPIO_PIN_NOPULL);
for (uint32_t i = 0; i < COUNTOF(pusle_gen_hw); i++)
{
pusle_gen_hw[i].TMR_B->PRESCALER = NRF_TIMER_FREQ_16MHz;
pusle_gen_hw[i].TMR_B->MODE = NRF_TIMER_MODE_TIMER;
pusle_gen_hw[i].TMR_B->BITMODE = NRF_TIMER_BIT_WIDTH_32;
pusle_gen_hw[i].TMR_A->PRESCALER = NRF_TIMER_FREQ_16MHz;
pusle_gen_hw[i].TMR_A->MODE = NRF_TIMER_MODE_TIMER;
pusle_gen_hw[i].TMR_A->BITMODE = NRF_TIMER_BIT_WIDTH_32;
sd_nvic_SetPriority(pusle_gen_hw[i].IRQn, _PRIO_APP_HIGH);
}
//cpg_pulse_default_demo_ext();
}
#endif