424 lines
14 KiB
C
424 lines
14 KiB
C
#include "elite_board.h"
|
|
|
|
#include "nrf_gpio.h"
|
|
#include "nrf_gpiote.h"
|
|
|
|
#include "nrf_spim.h"
|
|
#include "nrf_timer.h"
|
|
|
|
#include "FreeRTOS.h"
|
|
#include "semphr.h"
|
|
#include "task.h"
|
|
|
|
#include "SEGGER_RTT.h"
|
|
|
|
#if (DEF_ELITE_MODEL == DEF_ELITE_PEL_V2_0)
|
|
|
|
pel_hw_t pel_hw = {
|
|
.pulse_tmr = NRF_TIMER3,
|
|
.pulse_irq_n = TIMER3_IRQn,
|
|
.pulse_cnt = 0,
|
|
.adc.channels = {
|
|
[OUTPUT_R1_IDX] = OUTPUT_R1_CHANNEL,
|
|
[OUTPUT_R2_IDX] = OUTPUT_R2_CHANNEL,
|
|
[OUTPUT_VO_IDX] = OUTPUT_VO_CHANNEL,
|
|
[OUTPUT_VC_IDX] = OUTPUT_VC_CHANNEL,
|
|
[OUTPUT_VE_IDX] = OUTPUT_VE_CHANNEL},
|
|
.adc.gain = NRF_SAADC_GAIN1_6,
|
|
.adc.smaple_time = NRF_SAADC_ACQTIME_3US
|
|
};
|
|
|
|
void spim_xfer(uint32_t cs_pin,
|
|
nrf_spim_mode_t spi_mode,
|
|
uint8_t *p_tx_buffer,
|
|
uint16_t tx_buffer_length,
|
|
uint8_t *p_rx_buf,
|
|
uint16_t rx_buffer_length)
|
|
{
|
|
__disable_irq();
|
|
|
|
NRF_SPIM3->ENABLE = SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos;
|
|
|
|
switch (spi_mode)
|
|
{
|
|
default:
|
|
case NRF_SPIM_MODE_0:
|
|
NRF_SPIM3->CONFIG = (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos) |
|
|
(SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos) |
|
|
(SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos);
|
|
break;
|
|
|
|
case NRF_SPIM_MODE_1:
|
|
NRF_SPIM3->CONFIG = (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos) |
|
|
(SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos) |
|
|
(SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos);
|
|
break;
|
|
|
|
case NRF_SPIM_MODE_2:
|
|
NRF_SPIM3->CONFIG = (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos) |
|
|
(SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos) |
|
|
(SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos);
|
|
break;
|
|
|
|
case NRF_SPIM_MODE_3:
|
|
NRF_SPIM3->CONFIG = (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos) |
|
|
(SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos) |
|
|
(SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos);
|
|
break;
|
|
}
|
|
|
|
NRF_SPIM3->ENABLE = SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos;
|
|
|
|
NRF_SPIM3->TXD.MAXCNT = tx_buffer_length;
|
|
NRF_SPIM3->TXD.PTR = (uint32_t)p_tx_buffer;
|
|
|
|
NRF_SPIM3->RXD.MAXCNT = rx_buffer_length;
|
|
NRF_SPIM3->RXD.PTR = (uint32_t)p_rx_buf;
|
|
|
|
nrf_gpio_pin_clear(cs_pin);
|
|
|
|
NRF_SPIM3->EVENTS_END = 0;
|
|
NRF_SPIM3->TASKS_START = 1;
|
|
do {
|
|
} while (NRF_SPIM3->EVENTS_END == 0);
|
|
|
|
nrf_gpio_pin_set(cs_pin);
|
|
|
|
__enable_irq();
|
|
}
|
|
|
|
#define MIN_PULSE_WIDTH 2
|
|
#define MIN_PULSE_IDLE 2
|
|
#define MAX_PULSE_WIDTH INT16_MAX
|
|
#define MAX_PULSE_IDLE INT16_MAX
|
|
|
|
void set_anode_cathode_to_default(void)
|
|
{
|
|
if (BOARD_IOPx == BOARD_IOPL)
|
|
{
|
|
nrf_gpio_pin_set(ANODE_PIN);
|
|
nrf_gpio_pin_clear(CATHODE_PIN);
|
|
nrf_gpio_pin_clear(SAMPLE_R_PIN);
|
|
nrf_gpio_pin_clear(SAMPLE_V_PIN);
|
|
nrf_gpio_pin_clear(TP1_PIN);
|
|
nrf_gpio_pin_clear(TP2_PIN);
|
|
nrf_gpio_pin_clear(RELAY1_PIN);
|
|
}
|
|
else if (BOARD_IOPx == BOARD_IOPH)
|
|
{
|
|
nrf_gpio_pin_clear(ANODE_PIN);
|
|
nrf_gpio_pin_set(CATHODE_PIN);
|
|
nrf_gpio_pin_clear(SAMPLE_R_PIN);
|
|
nrf_gpio_pin_clear(SAMPLE_V_PIN);
|
|
nrf_gpio_pin_clear(TP1_PIN);
|
|
nrf_gpio_pin_clear(TP2_PIN);
|
|
nrf_gpio_pin_clear(RELAY1_PIN);
|
|
}
|
|
}
|
|
|
|
static void pel_saadc_init(pel_adc_t *p_adc)
|
|
{
|
|
/* stop ssadc */
|
|
NRF_SAADC->EVENTS_STOPPED = 0;
|
|
NRF_SAADC->TASKS_STOP = 1;
|
|
do {
|
|
} while (NRF_SAADC->EVENTS_STOPPED == 0);
|
|
|
|
/* disable ssadc */
|
|
NRF_SAADC->ENABLE = 0;
|
|
|
|
/*
|
|
ref: p.381, nrf52840_PS_v1.1.pdf
|
|
Note: Oversampling should only be used when a single input channel is enabled, as averaging is
|
|
performed over all enabled channels.
|
|
*/
|
|
NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Bypass;
|
|
NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit;
|
|
/* config analog inputs */
|
|
for (uint32_t i = 0; i < COUNTOF(NRF_SAADC->CH); i++)
|
|
{
|
|
if (i < COUNTOF(p_adc->channels))
|
|
{
|
|
NRF_SAADC->CH[i].PSELP = NRF_SAADC_INPUT_AIN0 + p_adc->channels[i];
|
|
NRF_SAADC->CH[i].PSELN = NRF_SAADC_INPUT_DISABLED;
|
|
NRF_SAADC->CH[i].CONFIG =
|
|
(NRF_SAADC_RESISTOR_DISABLED << SAADC_CH_CONFIG_RESP_Pos) |
|
|
(NRF_SAADC_RESISTOR_DISABLED << SAADC_CH_CONFIG_RESN_Pos) |
|
|
(p_adc->gain << SAADC_CH_CONFIG_GAIN_Pos) |
|
|
(NRF_SAADC_REFERENCE_INTERNAL << SAADC_CH_CONFIG_REFSEL_Pos) |
|
|
(p_adc->smaple_time << SAADC_CH_CONFIG_TACQ_Pos) |
|
|
(NRF_SAADC_MODE_SINGLE_ENDED << SAADC_CH_CONFIG_MODE_Pos) |
|
|
(NRF_SAADC_BURST_DISABLED << SAADC_CH_CONFIG_BURST_Pos);
|
|
}
|
|
else
|
|
{
|
|
NRF_SAADC->CH[i].PSELP = NRF_SAADC_INPUT_DISABLED;
|
|
NRF_SAADC->CH[i].PSELN = NRF_SAADC_INPUT_DISABLED;
|
|
NRF_SAADC->CH[i].CONFIG = 0;
|
|
}
|
|
}
|
|
/* enable ssadc */
|
|
NRF_SAADC->INTENSET = NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END;
|
|
NRF_SAADC->ENABLE = 1;
|
|
NRF_SAADC->RESULT.PTR = (uint32_t)p_adc->results;
|
|
NRF_SAADC->RESULT.MAXCNT = COUNTOF(p_adc->results);
|
|
}
|
|
|
|
void TIMER3_IRQHandler(void)
|
|
{
|
|
if (pel_hw.pulse_tmr->EVENTS_COMPARE[0])
|
|
{
|
|
pel_hw.pulse_tmr->EVENTS_COMPARE[0] = 0;
|
|
|
|
pel_hw.pulse_is_running = 1;
|
|
|
|
if (pel_hw.pulse_cnt)
|
|
{
|
|
pel_hw.pulse_cnt--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SAADC_IRQHandler(void)
|
|
{
|
|
if (NRF_SAADC->EVENTS_STARTED)
|
|
{
|
|
NRF_SAADC->EVENTS_STARTED = 0;
|
|
if (pel_hw.pulse_cnt == 0)
|
|
{
|
|
pel_hw.pulse_tmr->TASKS_STOP = 1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (NRF_SAADC->EVENTS_END)
|
|
{
|
|
NRF_SAADC->EVENTS_END = 0;
|
|
NRF_SAADC->RESULT.PTR = (uint32_t)pel_hw.adc.results;
|
|
NRF_SAADC->RESULT.MAXCNT = COUNTOF(pel_hw.adc.results);
|
|
pel_hw.pulse_is_running = 0;
|
|
if (pel_hw.adc.convt_new_arrival_cb)
|
|
{
|
|
pel_hw.adc.convt_new_arrival_cb();
|
|
}
|
|
}
|
|
}
|
|
|
|
void pel_pulse_gen_init(pel_config_t cfg)
|
|
{
|
|
pel_hw.pulse_tmr->TASKS_STOP = 1;
|
|
|
|
sd_nvic_DisableIRQ(pel_hw.pulse_irq_n);
|
|
sd_nvic_ClearPendingIRQ(pel_hw.pulse_irq_n);
|
|
|
|
sd_nvic_DisableIRQ(SAADC_IRQn);
|
|
sd_nvic_ClearPendingIRQ(SAADC_IRQn);
|
|
|
|
pel_hw.pulse_cnt = cfg.pulse_cnt;
|
|
pel_hw.adc.gain = cfg.gain;
|
|
pel_hw.adc.smaple_time = cfg.smaple_time;
|
|
pel_hw.adc.convt_new_arrival_cb = cfg.convt_new_arrival_cb;
|
|
|
|
pel_saadc_init(&pel_hw.adc);
|
|
|
|
// disable gpio task
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
nrf_gpiote_task_disable(i);
|
|
}
|
|
|
|
set_anode_cathode_to_default();
|
|
|
|
// config gpiote task
|
|
switch (cfg.mode)
|
|
{
|
|
default:
|
|
case 1:
|
|
nrf_gpiote_task_configure(0, cfg.anode_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
|
|
nrf_gpiote_task_configure(1, cfg.cathode_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
|
|
break;
|
|
case 0:
|
|
nrf_gpiote_task_configure(0, cfg.anode_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
|
|
nrf_gpiote_task_configure(1, cfg.cathode_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
|
|
break;
|
|
}
|
|
|
|
nrf_gpiote_task_configure(2, cfg.smaple_r_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
|
|
nrf_gpiote_task_configure(3, cfg.sample_v_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
|
|
|
|
if (cfg.test_pin != 0xFFFFFFFF)
|
|
{
|
|
nrf_gpiote_task_configure(4, cfg.test_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
|
|
}
|
|
|
|
// enable gpio task
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
nrf_gpiote_task_enable(i);
|
|
}
|
|
|
|
NRF_PPI->CH[0].EEP = (uint32_t)&pel_hw.pulse_tmr->EVENTS_COMPARE[0];
|
|
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
|
|
NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[1];
|
|
NRF_PPI->CHENSET = (1 << (0));
|
|
|
|
NRF_PPI->CH[1].EEP = (uint32_t)&pel_hw.pulse_tmr->EVENTS_COMPARE[1];
|
|
NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[2];
|
|
NRF_PPI->FORK[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[3];
|
|
NRF_PPI->CHENSET = (1 << (1));
|
|
|
|
NRF_PPI->CH[2].EEP = (uint32_t)&pel_hw.pulse_tmr->EVENTS_COMPARE[2];
|
|
NRF_PPI->CH[2].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[2];
|
|
NRF_PPI->FORK[2].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[3];
|
|
NRF_PPI->CHENSET = (1 << (2));
|
|
|
|
NRF_PPI->CH[3].EEP = (uint32_t)&pel_hw.pulse_tmr->EVENTS_COMPARE[3];
|
|
NRF_PPI->CH[3].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
|
|
NRF_PPI->FORK[3].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[1];
|
|
NRF_PPI->CHENSET = (1 << (3));
|
|
|
|
NRF_PPI->CH[4].EEP = (uint32_t)&pel_hw.pulse_tmr->EVENTS_COMPARE[4];
|
|
NRF_PPI->CH[4].TEP = (uint32_t)&NRF_SAADC->TASKS_START;
|
|
NRF_PPI->CHENSET = (1 << (4));
|
|
|
|
if (cfg.test_pin != 0xFFFFFFFF)
|
|
{
|
|
NRF_PPI->CH[6].EEP = (uint32_t)&NRF_SAADC->EVENTS_STARTED;
|
|
NRF_PPI->CH[6].TEP = (uint32_t)&NRF_SAADC->TASKS_SAMPLE;
|
|
NRF_PPI->FORK[6].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[4];
|
|
NRF_PPI->CHENSET = (1 << (6));
|
|
NRF_PPI->CH[7].EEP = (uint32_t)&NRF_SAADC->EVENTS_END;
|
|
NRF_PPI->CH[7].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[4];
|
|
NRF_PPI->CHENSET = (1 << (7));
|
|
}
|
|
|
|
pel_hw.pulse_tmr->PRESCALER = NRF_TIMER_FREQ_16MHz;
|
|
pel_hw.pulse_tmr->MODE = NRF_TIMER_MODE_TIMER;
|
|
pel_hw.pulse_tmr->BITMODE = NRF_TIMER_BIT_WIDTH_32;
|
|
pel_hw.pulse_tmr->CC[0] = cfg.point_us[0] * 16;
|
|
pel_hw.pulse_tmr->CC[1] = pel_hw.pulse_tmr->CC[0] + cfg.point_us[1] * 16;
|
|
pel_hw.pulse_tmr->CC[2] = pel_hw.pulse_tmr->CC[1] + cfg.point_us[2] * 16;
|
|
pel_hw.pulse_tmr->CC[3] = pel_hw.pulse_tmr->CC[2] + cfg.point_us[3] * 16;
|
|
pel_hw.pulse_tmr->CC[4] = pel_hw.pulse_tmr->CC[3] + cfg.point_us[4] * 16 + cfg.adc_timing_shift;
|
|
pel_hw.pulse_tmr->CC[5] = pel_hw.pulse_tmr->CC[4];
|
|
pel_hw.pulse_tmr->SHORTS = NRF_TIMER_SHORT_COMPARE5_CLEAR_MASK;
|
|
pel_hw.pulse_tmr->INTENSET = NRF_TIMER_INT_COMPARE0_MASK;
|
|
|
|
sd_nvic_SetPriority(SAADC_IRQn, _PRIO_APP_HIGH);
|
|
sd_nvic_EnableIRQ(SAADC_IRQn);
|
|
|
|
sd_nvic_SetPriority(pel_hw.pulse_irq_n, _PRIO_APP_HIGH);
|
|
sd_nvic_EnableIRQ(pel_hw.pulse_irq_n);
|
|
}
|
|
|
|
void pel_pulse_gen_start(void)
|
|
{
|
|
pel_hw.pulse_tmr->TASKS_START = 1;
|
|
}
|
|
|
|
void pel_pulse_gen_stop(void)
|
|
{
|
|
pel_hw.pulse_cnt = 0;
|
|
do {
|
|
} while (pel_hw.pulse_is_running == 1);
|
|
pel_hw.adc.convt_new_arrival_cb = NULL;
|
|
}
|
|
|
|
#if (DEF_ELITE_DEMO_W_SOFTDEVICE == 1) || (DEF_ELITE_DEMO_WO_SOFTDEVICE == 1)
|
|
static void pel_pulse_gen_demo_task(void *p_arg)
|
|
{
|
|
pel_config_t pel_cfg = {
|
|
.anode_pin = ANODE_PIN,
|
|
.cathode_pin = CATHODE_PIN,
|
|
.smaple_r_pin = SAMPLE_R_PIN,
|
|
.sample_v_pin = SAMPLE_V_PIN,
|
|
.test_pin = TP1_PIN,
|
|
.mode = BOARD_IOPx,
|
|
.point_us = {
|
|
10000,
|
|
3,
|
|
5,
|
|
2,
|
|
0,
|
|
},
|
|
.pulse_cnt = 0xFFFFFFFF,
|
|
.gain = NRF_SAADC_GAIN1_6,
|
|
.smaple_time = NRF_SAADC_ACQTIME_10US,
|
|
.adc_timing_shift = 0,
|
|
};
|
|
|
|
pel_pulse_gen_init(pel_cfg);
|
|
|
|
pel_pulse_gen_start();
|
|
|
|
for (;;)
|
|
{
|
|
static uint32_t i = 0;
|
|
vTaskDelay(pdMS_TO_TICKS(pel_cfg.point_us[0] / 1000));
|
|
SEGGER_RTT_printf(0, "%d, %d, %d, %d, %d, %d\r\n", i++, pel_hw.adc.results[0], pel_hw.adc.results[1], pel_hw.adc.results[2], pel_hw.adc.results[3], pel_hw.adc.results[4]);
|
|
}
|
|
}
|
|
|
|
void pel_pulse_gen_demo(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void pel20_io_init(void)
|
|
{
|
|
const uint32_t pel_pins_default_high[] = {
|
|
INPUT_1_PIN,
|
|
INPUT_2_PIN,
|
|
INPUT_3_PIN,
|
|
INPUT_4_PIN,
|
|
INPUT_5_PIN,
|
|
INPUT_6_PIN,
|
|
INPUT_7_PIN,
|
|
INPUT_8_PIN,
|
|
INPUT_9_PIN,
|
|
INPUT_10_PIN,
|
|
INPUT_11_PIN,
|
|
INPUT_12_PIN
|
|
};
|
|
|
|
for (int i = 0; i < COUNTOF(pel_pins_default_high); i++)
|
|
{
|
|
nrf_gpio_pin_set(pel_pins_default_high[i]);
|
|
nrf_gpio_cfg_output(pel_pins_default_high[i]);
|
|
}
|
|
|
|
set_anode_cathode_to_default();
|
|
nrf_gpio_cfg_output(ANODE_PIN);
|
|
nrf_gpio_cfg_output(CATHODE_PIN);
|
|
nrf_gpio_cfg_output(SAMPLE_R_PIN);
|
|
nrf_gpio_cfg_output(SAMPLE_V_PIN);
|
|
nrf_gpio_cfg_output(TP1_PIN);
|
|
nrf_gpio_cfg_output(TP2_PIN);
|
|
nrf_gpio_cfg_output(RELAY1_PIN);
|
|
|
|
// Config spi module
|
|
|
|
nrf_gpio_pin_set(WP_MEM_PIN);
|
|
nrf_gpio_cfg_output(WP_MEM_PIN);
|
|
nrf_gpio_pin_set(CS_MEM_PIN);
|
|
nrf_gpio_cfg_output(CS_MEM_PIN);
|
|
nrf_gpio_pin_clear(SPIM_MOSI_PIN);
|
|
nrf_gpio_cfg_output(SPIM_MOSI_PIN);
|
|
nrf_gpio_pin_clear(SPIM_CLK_PIN);
|
|
nrf_gpio_cfg_output(SPIM_CLK_PIN);
|
|
nrf_gpio_cfg_input(SPIM_MISO_PIN, NRF_GPIO_PIN_NOPULL);
|
|
|
|
NRF_SPIM3->ENABLE = SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos;
|
|
NRF_SPIM3->ORC = 0x00000000;
|
|
NRF_SPIM3->FREQUENCY = SPIM_FREQUENCY_FREQUENCY_M32;
|
|
NRF_SPIM3->CSNPOL = SPIM_CSNPOL_CSNPOL_LOW;
|
|
NRF_SPIM3->IFTIMING.CSNDUR = 8;
|
|
NRF_SPIM3->PSEL.CSN = CS_MEM_PIN;
|
|
NRF_SPIM3->PSEL.SCK = SPIM_CLK_PIN;
|
|
NRF_SPIM3->PSEL.MOSI = SPIM_MOSI_PIN;
|
|
NRF_SPIM3->PSEL.MISO = SPIM_MISO_PIN;
|
|
NRF_SPIM3->ENABLE = SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos;
|
|
}
|
|
|
|
#endif
|