2018-06-06 19:56:43 +08:00
/**
* this case is used for test PCNT
* prepare job for test environment UT_T1_PCNT:
2019-12-02 16:34:59 +08:00
* We use internal signals instead of external wiring, but please keep the following IO connections, or connect nothing to prevent the signal from being disturbed.
2018-06-06 19:56:43 +08:00
* 1. prepare one ESP-WROOM-32 board and connect it to PC.
2019-12-02 16:34:59 +08:00
* 2. connect GPIO21 with GPIO4
2018-06-06 19:56:43 +08:00
* 3. GPIO5 connect to 3.3v
* 4. GPIO19 connect to GND
* 5. logic analyzer will help too if possible
*
* the GPIO18 is the pulse producer, the GPIO4 is the input GPIO
*/
# include <stdio.h>
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# include "freertos/queue.h"
2020-10-12 14:23:49 +08:00
# include "soc/soc_caps.h"
# if SOC_PCNT_SUPPORTED
2018-06-06 19:56:43 +08:00
# include "driver/periph_ctrl.h"
# include "driver/gpio.h"
# include "driver/pcnt.h"
# include "driver/ledc.h"
# include "esp_attr.h"
# include "esp_log.h"
2019-05-13 18:02:45 +08:00
# include "soc/gpio_periph.h"
2018-06-06 19:56:43 +08:00
# include "unity.h"
2020-06-19 12:00:58 +08:00
# include "esp_rom_gpio.h"
2018-06-06 19:56:43 +08:00
2019-12-02 16:34:59 +08:00
# define PULSE_IO 21
2018-06-06 19:56:43 +08:00
# define PCNT_INPUT_IO 4
2019-12-02 16:34:59 +08:00
# define PCNT_CTRL_VCC_IO 5
2018-06-06 19:56:43 +08:00
# define PCNT_CTRL_GND_IO 19
# define HIGHEST_LIMIT 10
# define LOWEST_LIMIT 0
# define MAX_THRESHOLD 5
# define MIN_THRESHOLD 0
2019-12-02 16:34:59 +08:00
# define PCNT_CTRL_HIGH_LEVEL 1
# define PCNT_CTRL_LOW_LEVEL 0
2018-06-06 19:56:43 +08:00
2019-12-02 16:34:59 +08:00
static xQueueHandle pcnt_evt_queue = NULL ;
2018-06-06 19:56:43 +08:00
typedef struct {
int zero_times ;
int h_limit ;
int l_limit ;
int h_threshold ;
int l_threshold ;
int filter_time ;
} event_times ;
2019-12-02 16:34:59 +08:00
static void pcnt_test_io_config ( int ctrl_level )
{
// Connect internal signals using IO matrix.
gpio_set_direction ( PULSE_IO , GPIO_MODE_INPUT_OUTPUT ) ;
2020-06-19 12:00:58 +08:00
esp_rom_gpio_connect_out_signal ( PULSE_IO , LEDC_LS_SIG_OUT1_IDX , 0 , 0 ) ; // LEDC_TIMER_1, LEDC_LOW_SPEED_MODE
esp_rom_gpio_connect_in_signal ( PULSE_IO , PCNT_SIG_CH0_IN0_IDX , 0 ) ; // PCNT_UNIT_0, PCNT_CHANNEL_0
esp_rom_gpio_connect_in_signal ( ctrl_level ? GPIO_MATRIX_CONST_ONE_INPUT : GPIO_MATRIX_CONST_ZERO_INPUT , PCNT_CTRL_CH0_IN0_IDX , 0 ) ; // PCNT_UNIT_0, PCNT_CHANNEL_0
2019-12-02 16:34:59 +08:00
}
2018-06-06 19:56:43 +08:00
/* use LEDC to produce pulse for PCNT
* the frequency of LEDC is 1000, so every second will get 1000 count values
* the PCNT count the LEDC pulse
* */
static void produce_pulse ( void )
{
ledc_timer_config_t ledc_timer = {
2019-12-02 16:34:59 +08:00
. speed_mode = LEDC_LOW_SPEED_MODE ,
2018-06-06 19:56:43 +08:00
. timer_num = LEDC_TIMER_1 ,
. duty_resolution = LEDC_TIMER_10_BIT ,
. freq_hz = 1 ,
2018-11-01 12:23:11 +08:00
. clk_cfg = LEDC_AUTO_CLK ,
2018-06-06 19:56:43 +08:00
} ;
2019-08-11 15:48:17 +10:00
ESP_ERROR_CHECK ( ledc_timer_config ( & ledc_timer ) ) ;
2018-06-06 19:56:43 +08:00
ledc_channel_config_t ledc_channel = {
2019-12-02 16:34:59 +08:00
. speed_mode = LEDC_LOW_SPEED_MODE ,
2018-06-06 19:56:43 +08:00
. channel = LEDC_CHANNEL_1 ,
. timer_sel = LEDC_TIMER_1 ,
. intr_type = LEDC_INTR_DISABLE ,
. gpio_num = PULSE_IO ,
. duty = 100 ,
. hpoint = 0 ,
} ;
2019-08-11 15:48:17 +10:00
ESP_ERROR_CHECK ( ledc_channel_config ( & ledc_channel ) ) ;
2018-06-06 19:56:43 +08:00
}
static void IRAM_ATTR pcnt_intr_handler ( void * arg )
{
uint32_t intr_status = PCNT . int_st . val ;
int i ;
uint32_t status ;
BaseType_t port_status = pdFALSE ;
for ( i = 0 ; i < PCNT_UNIT_MAX ; i + + ) {
if ( intr_status & ( BIT ( i ) ) ) {
status = PCNT . status_unit [ i ] . val ;
PCNT . int_clr . val = BIT ( i ) ;
xQueueSendFromISR ( pcnt_evt_queue , & status , & port_status ) ;
if ( port_status = = pdTRUE ) {
portYIELD_FROM_ISR ( ) ;
}
}
}
}
static void event_calculate ( event_times * event )
{
int16_t test_counter = 0 ;
int times = 0 ;
BaseType_t port_status ;
uint32_t status = 0 ;
while ( times < 10 ) {
port_status = xQueueReceive ( pcnt_evt_queue , & status , 1000 / portTICK_PERIOD_MS ) ;
if ( port_status = = pdTRUE ) {
event - > filter_time + + ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " Current counter value :%d \n " , test_counter ) ;
2019-12-02 16:34:59 +08:00
if ( status & PCNT_EVT_THRES_1 ) {
2018-06-06 19:56:43 +08:00
printf ( " THRES1 EVT \n " ) ;
event - > h_threshold + + ;
}
2019-12-02 16:34:59 +08:00
if ( status & PCNT_EVT_THRES_0 ) {
2018-06-06 19:56:43 +08:00
printf ( " THRES0 EVT \n " ) ;
event - > l_threshold + + ;
}
2019-12-02 16:34:59 +08:00
if ( status & PCNT_EVT_L_LIM ) {
2018-06-06 19:56:43 +08:00
printf ( " L_LIM EVT \n " ) ;
event - > l_limit + + ;
}
2019-12-02 16:34:59 +08:00
if ( status & PCNT_EVT_H_LIM ) {
2018-06-06 19:56:43 +08:00
printf ( " H_LIM EVT \n " ) ;
event - > h_limit + + ;
}
2019-12-02 16:34:59 +08:00
if ( status & PCNT_EVT_ZERO ) {
2018-06-06 19:56:43 +08:00
printf ( " ZERO EVT \n " ) ;
event - > zero_times + + ;
}
} else {
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " Current counter value :%d \n " , test_counter ) ;
}
times + + ;
}
printf ( " %d, %d, %d, %d, %d, %d \n " , event - > h_threshold , event - > l_threshold ,
event - > l_limit , event - > h_limit , event - > zero_times , event - > filter_time ) ;
}
/*
* There exist 2 kind of counting methods: positive and negative counting method
* 1. when control IO is high level, PCNT is positive counting mode
* 2. when control IO is low level, PCNT is positive negative mode
* the positive method standard is as below:
* ----------------------------------------------------------------------------------
* POS_ MODE | LCTRL_ MODE | HCTRL_ MODE | sig l→h when ctrl=0 | sig l→h when ctrl=1
* NEG_ MODE | | | |
* ===================================================================================
* 1 (inc) | 0 (-) | 0 (-) | Inc ctr | Inc ctr
* 2 (dec) | 0 (-) | 0 (-) | Dec ctr | Dec ctr
* 0 (-) | x | x | No action | No action
* 1 (inc) | 0 (-) | 1 (inv) | Inc ctr | Dec ctr
* 1 (inc) | 1 (inv) | 0 (-) | Dec ctr | Inc ctr
* 2 (dec) | 0 (-) | 1 (inv) | Dec ctr | Inc ctr
* 1 (inc) | 0 (-) | 2 (dis) | Inc ctr | No action
* 1 (inc) | 2 (dis) | 0 (-) | No action | Inc ctr
* -----------------------------------------------------------------------------------
* */
static void count_mode_test ( gpio_num_t ctl_io )
{
int16_t test_counter ;
//produce pulse, 100HZ
ledc_timer_config_t ledc_timer = {
2019-12-02 16:34:59 +08:00
. speed_mode = LEDC_LOW_SPEED_MODE ,
2018-06-06 19:56:43 +08:00
. timer_num = LEDC_TIMER_1 ,
. duty_resolution = LEDC_TIMER_10_BIT ,
. freq_hz = 100 ,
2018-11-01 12:23:11 +08:00
. clk_cfg = LEDC_AUTO_CLK ,
2018-06-06 19:56:43 +08:00
} ;
ledc_timer_config ( & ledc_timer ) ;
ledc_channel_config_t ledc_channel = {
2019-12-02 16:34:59 +08:00
. speed_mode = LEDC_LOW_SPEED_MODE ,
2018-06-06 19:56:43 +08:00
. channel = LEDC_CHANNEL_1 ,
. timer_sel = LEDC_TIMER_1 ,
. intr_type = LEDC_INTR_DISABLE ,
. gpio_num = PULSE_IO ,
. duty = 100 ,
. hpoint = 0 ,
} ;
ledc_channel_config ( & ledc_channel ) ;
pcnt_config_t pcnt_config = {
. pulse_gpio_num = PCNT_INPUT_IO ,
. ctrl_gpio_num = ctl_io ,
. channel = PCNT_CHANNEL_0 ,
. unit = PCNT_UNIT_0 ,
. pos_mode = PCNT_COUNT_INC ,
. neg_mode = PCNT_COUNT_DIS ,
. lctrl_mode = PCNT_MODE_REVERSE ,
. hctrl_mode = PCNT_MODE_KEEP ,
. counter_h_lim = 101 ,
. counter_l_lim = - 101 ,
} ;
TEST_ESP_OK ( pcnt_unit_config ( & pcnt_config ) ) ;
2019-12-02 16:34:59 +08:00
pcnt_test_io_config ( ( ctl_io = = PCNT_CTRL_VCC_IO ) ? PCNT_CTRL_HIGH_LEVEL : PCNT_CTRL_LOW_LEVEL ) ;
2018-06-06 19:56:43 +08:00
int16_t result1 [ 8 ] = { 100 , - 100 , 0 , - 100 , 100 , 100 , 0 , 100 } ;
int16_t result2 [ 8 ] = { 100 , - 100 , 0 , 100 , - 100 , - 100 , 100 , 0 } ;
int16_t * result ;
2019-12-02 16:34:59 +08:00
if ( ctl_io = = PCNT_CTRL_VCC_IO ) {
2018-06-06 19:56:43 +08:00
result = result1 ;
} else {
result = result2 ;
}
// 1, 0, 0, 0
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_INC , PCNT_COUNT_DIS ,
PCNT_MODE_KEEP , PCNT_MODE_KEEP ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 0 ] ) ;
//2, 0, 0, 0
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_DEC , PCNT_COUNT_DIS ,
PCNT_MODE_KEEP , PCNT_MODE_KEEP ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 1 ] ) ;
//0,0,0,0
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_DIS , PCNT_COUNT_DIS ,
PCNT_MODE_KEEP , PCNT_MODE_KEEP ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 2 ] ) ;
//1,0,1,0
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_INC , PCNT_COUNT_DIS ,
PCNT_MODE_REVERSE , PCNT_MODE_KEEP ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 3 ] ) ;
//1,0,0,1
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_INC , PCNT_COUNT_DIS ,
PCNT_MODE_KEEP , PCNT_MODE_REVERSE ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 4 ] ) ;
//2,0,0,1
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_DEC , PCNT_COUNT_DIS ,
PCNT_MODE_REVERSE , PCNT_MODE_KEEP ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 5 ] ) ;
//1,0,2,0
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_INC , PCNT_COUNT_DIS ,
PCNT_MODE_DISABLE , PCNT_MODE_KEEP ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 6 ] ) ;
//1,0,0,2
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_mode ( PCNT_UNIT_0 , PCNT_CHANNEL_0 ,
PCNT_COUNT_INC , PCNT_COUNT_DIS ,
PCNT_MODE_KEEP , PCNT_MODE_DISABLE ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " value: %d \n " , test_counter ) ;
TEST_ASSERT_INT16_WITHIN ( 1 , test_counter , result [ 7 ] ) ;
}
// test PCNT basic configuration
2019-12-02 16:34:59 +08:00
TEST_CASE ( " PCNT test config " , " [pcnt] " )
2018-06-06 19:56:43 +08:00
{
pcnt_config_t pcnt_config = {
. pulse_gpio_num = PCNT_INPUT_IO ,
2019-12-02 16:34:59 +08:00
. ctrl_gpio_num = PCNT_CTRL_VCC_IO ,
2018-06-06 19:56:43 +08:00
. channel = PCNT_CHANNEL_0 ,
. unit = PCNT_UNIT_0 ,
. pos_mode = PCNT_COUNT_INC ,
. neg_mode = PCNT_COUNT_DIS ,
. lctrl_mode = PCNT_MODE_REVERSE ,
. hctrl_mode = PCNT_MODE_KEEP ,
. counter_h_lim = 100 ,
. counter_l_lim = 0 ,
} ;
// basic configuration
pcnt_config_t temp_pcnt_config = pcnt_config ;
TEST_ESP_OK ( pcnt_unit_config ( & pcnt_config ) ) ;
2019-12-02 16:34:59 +08:00
// test PCNT_UNIT_MAX units, from 0-(PCNT_UNIT_MAX-1)
2018-06-06 19:56:43 +08:00
pcnt_config = temp_pcnt_config ;
pcnt_config . unit = PCNT_UNIT_MAX ;
TEST_ASSERT_NOT_NULL ( ( void * ) pcnt_unit_config ( & pcnt_config ) ) ;
2019-12-02 16:34:59 +08:00
for ( int i = 0 ; i < PCNT_UNIT_MAX ; i + + ) {
2018-06-06 19:56:43 +08:00
pcnt_config . unit = i ;
TEST_ESP_OK ( pcnt_unit_config ( & pcnt_config ) ) ;
}
// test channels
pcnt_config = temp_pcnt_config ;
pcnt_config . channel = PCNT_CHANNEL_MAX ;
TEST_ASSERT_NOT_NULL ( ( void * ) pcnt_unit_config ( & pcnt_config ) ) ;
pcnt_config = temp_pcnt_config ;
pcnt_config . pulse_gpio_num = - 1 ;
TEST_ESP_OK ( pcnt_unit_config ( & pcnt_config ) ) ;
pcnt_config = temp_pcnt_config ;
2019-12-02 16:34:59 +08:00
pcnt_config . pulse_gpio_num = GPIO_NUM_MAX + 1 ;
2018-06-06 19:56:43 +08:00
TEST_ASSERT_NOT_NULL ( ( void * ) pcnt_unit_config ( & pcnt_config ) ) ;
// test pulse_gpio_num and ctrl_gpio_num is the same
pcnt_config = temp_pcnt_config ;
pcnt_config . pulse_gpio_num = PCNT_INPUT_IO ;
pcnt_config . ctrl_gpio_num = PCNT_INPUT_IO ;
TEST_ASSERT_NOT_NULL ( ( void * ) pcnt_unit_config ( & pcnt_config ) ) ;
pcnt_config = temp_pcnt_config ;
pcnt_config . pos_mode = PCNT_COUNT_MAX ;
TEST_ASSERT_NOT_NULL ( ( void * ) pcnt_unit_config ( & pcnt_config ) ) ;
pcnt_config = temp_pcnt_config ;
pcnt_config . hctrl_mode = PCNT_MODE_MAX ;
TEST_ASSERT_NOT_NULL ( ( void * ) pcnt_unit_config ( & pcnt_config ) ) ;
pcnt_config = temp_pcnt_config ;
pcnt_config . lctrl_mode = PCNT_MODE_MAX ;
TEST_ASSERT_NOT_NULL ( ( void * ) pcnt_unit_config ( & pcnt_config ) ) ;
}
/* PCNT basic property:
* 1. pause counter
* 2. resume counter
* 3. clear counter
* 4. check the counter value*/
2019-12-02 16:34:59 +08:00
TEST_CASE ( " PCNT basic function test " , " [pcnt] " )
2018-06-06 19:56:43 +08:00
{
int16_t test_counter ;
int16_t time = 0 ;
int clear_count = 0 ;
int resume_count = 0 ;
int temp_value = 0 ;
pcnt_config_t pcnt_config = {
. pulse_gpio_num = PCNT_INPUT_IO ,
2019-12-02 16:34:59 +08:00
. ctrl_gpio_num = PCNT_CTRL_VCC_IO ,
2018-06-06 19:56:43 +08:00
. channel = PCNT_CHANNEL_0 ,
. unit = PCNT_UNIT_0 ,
. pos_mode = PCNT_COUNT_INC ,
. neg_mode = PCNT_COUNT_DIS ,
. lctrl_mode = PCNT_MODE_REVERSE ,
. hctrl_mode = PCNT_MODE_KEEP ,
. counter_h_lim = 10 ,
. counter_l_lim = - 10 ,
} ;
TEST_ESP_OK ( pcnt_unit_config ( & pcnt_config ) ) ;
// use LEDC to produce the pulse, then the PCNT to count it
produce_pulse ( ) ;
2019-12-02 16:34:59 +08:00
pcnt_test_io_config ( PCNT_CTRL_HIGH_LEVEL ) ;
2018-06-06 19:56:43 +08:00
// initialize first, the initail value should be 0
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
TEST_ASSERT_EQUAL_INT16 ( test_counter , 0 ) ;
// resume the PCNT
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
TEST_ASSERT_EQUAL_INT16 ( test_counter , 0 ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
TEST_ASSERT_EQUAL_INT16 ( test_counter , 0 ) ;
//count now
while ( time ! = 10 ) {
vTaskDelay ( 1001 / portTICK_RATE_MS ) ; // in case of can't wait to get counter(edge effect)
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " COUNT: %d \n " , test_counter ) ;
TEST_ASSERT_NOT_EQUAL ( test_counter , temp_value ) ;
temp_value = test_counter ;
if ( test_counter = = 5 | | test_counter = = - 5 ) {
//test clear
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
TEST_ASSERT_EQUAL_INT16 ( test_counter , 0 ) ;
clear_count + + ;
}
if ( test_counter = = 0 ) {
//test pause
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " PAUSE: %d \n " , test_counter ) ;
TEST_ASSERT_EQUAL_INT16 ( test_counter , 0 ) ;
// test resume
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
vTaskDelay ( 1000 / portTICK_RATE_MS ) ;
TEST_ESP_OK ( pcnt_get_counter_value ( PCNT_UNIT_0 , & test_counter ) ) ;
printf ( " RESUME: %d \n " , test_counter ) ;
2019-12-02 16:34:59 +08:00
TEST_ASSERT_EQUAL_INT16 ( test_counter , 1 ) ;
2018-06-06 19:56:43 +08:00
resume_count + + ;
}
time + + ;
}
TEST_ASSERT_EQUAL_INT16 ( clear_count , 2 ) ;
TEST_ASSERT_EQUAL_INT16 ( resume_count , 2 ) ;
}
/**
* there are 4 situations will be tested:
* 1. set event to interrupt triggered
* 2. disable interrupt to stop triggering interrupt
* 3. enable interrupt to interrupt triggered again
* 4. disable event to stop triggering interrupt
*
* PCNT interrupt type:
* 1. PCNT_EVT_THRES_1
* 2. PCNT_EVT_THRES_0
* 3. PCNT_EVT_ZERO
* 4. PCNT_EVT_H_LIM
* 5. PCNT_EVT_L_LIM
* */
2019-12-02 16:34:59 +08:00
TEST_CASE ( " PCNT interrupt method test(control IO is high) " , " [pcnt][timeout=120] " )
2018-06-06 19:56:43 +08:00
{
pcnt_config_t config = {
. pulse_gpio_num = PCNT_INPUT_IO ,
2019-12-02 16:34:59 +08:00
. ctrl_gpio_num = PCNT_CTRL_VCC_IO ,
2018-06-06 19:56:43 +08:00
. channel = PCNT_CHANNEL_0 ,
. unit = PCNT_UNIT_0 ,
. pos_mode = PCNT_COUNT_INC ,
. neg_mode = PCNT_COUNT_DIS ,
. lctrl_mode = PCNT_MODE_REVERSE ,
. hctrl_mode = PCNT_MODE_KEEP ,
. counter_h_lim = 5 ,
. counter_l_lim = 0 ,
} ;
TEST_ESP_OK ( pcnt_unit_config ( & config ) ) ;
produce_pulse ( ) ;
2019-12-02 16:34:59 +08:00
pcnt_test_io_config ( PCNT_CTRL_HIGH_LEVEL ) ;
2018-06-06 19:56:43 +08:00
event_times event = {
. zero_times = 0 ,
. h_limit = 0 ,
. l_limit = 0 ,
. h_threshold = 0 ,
. l_threshold = 0 ,
. filter_time = 0 ,
} ;
//interrupt set
TEST_ESP_OK ( pcnt_set_filter_value ( PCNT_UNIT_0 , 2 ) ) ;
TEST_ESP_OK ( pcnt_filter_enable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_event_value ( PCNT_UNIT_0 , PCNT_EVT_THRES_1 , 4 ) ) ; // when arrive to max threshold trigger
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_THRES_1 ) ) ;
TEST_ESP_OK ( pcnt_set_event_value ( PCNT_UNIT_0 , PCNT_EVT_THRES_0 , 1 ) ) ; // when arrive to minimum threshold trigger
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_THRES_0 ) ) ;
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_ZERO ) ) ;
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_H_LIM ) ) ; // when arrive to max limit trigger
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_L_LIM ) ) ; // when arrive to minimum limit trigger
2019-12-02 16:34:59 +08:00
// initialize first, the initail value should be 0
2018-06-06 19:56:43 +08:00
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
2019-12-02 16:34:59 +08:00
pcnt_evt_queue = xQueueCreate ( 10 , sizeof ( uint32_t ) ) ;
pcnt_isr_handle_t pcnt_isr_service ;
TEST_ESP_OK ( pcnt_isr_register ( pcnt_intr_handler , NULL , 0 , & pcnt_isr_service ) ) ;
2018-06-06 19:56:43 +08:00
TEST_ESP_OK ( pcnt_intr_enable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
// test event
event_calculate ( & event ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 2 ) ;
2018-06-06 19:56:43 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 2 ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT ( event . l_limit = = 0 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_limit , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 3 , event . filter_time , 4 ) ;
2018-06-06 19:56:43 +08:00
// test interrupt disable
TEST_ESP_OK ( pcnt_intr_disable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
// for the original control io disable interrupt status
event_calculate ( & event ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 2 ) ;
2018-06-06 19:56:43 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 2 ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT ( event . l_limit = = 0 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_limit , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 3 , event . filter_time , 4 ) ;
2018-06-06 19:56:43 +08:00
// enable the intr
TEST_ESP_OK ( pcnt_intr_enable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
event_calculate ( & event ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 4 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 4 ) ;
TEST_ASSERT ( event . l_limit = = 0 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_limit , 4 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 4 ) ;
TEST_ASSERT_INT_WITHIN ( 3 , event . filter_time , 10 ) ;
2018-06-06 19:56:43 +08:00
// disable part of events
TEST_ESP_OK ( pcnt_event_disable ( PCNT_UNIT_0 , PCNT_EVT_ZERO ) ) ;
TEST_ESP_OK ( pcnt_event_disable ( PCNT_UNIT_0 , PCNT_EVT_L_LIM ) ) ;
TEST_ESP_OK ( pcnt_event_disable ( PCNT_UNIT_0 , PCNT_EVT_THRES_0 ) ) ;
event_calculate ( & event ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 5 ) ;
2018-06-06 19:56:43 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 4 ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT ( event . l_limit = = 0 ) ;
2019-12-02 16:34:59 +08:00
TEST_ASSERT_INT_WITHIN ( 3 , event . h_limit , 6 ) ;
2018-06-26 09:07:51 +08:00
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 4 ) ;
TEST_ASSERT_INT_WITHIN ( 3 , event . filter_time , 14 ) ;
2018-06-06 19:56:43 +08:00
2019-12-02 16:34:59 +08:00
// Because this test uses its own ISR, we need to release it with `pcnt_isr_unregister` instead of `pcnt_isr_service_uninstall`
TEST_ESP_OK ( pcnt_isr_unregister ( pcnt_isr_service ) ) ;
vQueueDelete ( pcnt_evt_queue ) ;
2018-06-06 19:56:43 +08:00
}
2019-12-02 16:34:59 +08:00
TEST_CASE ( " PCNT interrupt method test(control IO is low) " , " [pcnt][timeout=120] " )
2018-06-06 19:56:43 +08:00
{
pcnt_config_t config = {
. pulse_gpio_num = PCNT_INPUT_IO ,
. ctrl_gpio_num = PCNT_CTRL_GND_IO ,
. channel = PCNT_CHANNEL_0 ,
. unit = PCNT_UNIT_0 ,
. pos_mode = PCNT_COUNT_INC ,
. neg_mode = PCNT_COUNT_DIS ,
. lctrl_mode = PCNT_MODE_REVERSE ,
. hctrl_mode = PCNT_MODE_KEEP ,
. counter_h_lim = 0 ,
. counter_l_lim = - 5 ,
} ;
TEST_ESP_OK ( pcnt_unit_config ( & config ) ) ;
produce_pulse ( ) ;
2019-12-02 16:34:59 +08:00
pcnt_test_io_config ( PCNT_CTRL_LOW_LEVEL ) ;
2018-06-06 19:56:43 +08:00
event_times event = {
. zero_times = 0 ,
. h_limit = 0 ,
. l_limit = 0 ,
. h_threshold = 0 ,
. l_threshold = 0 ,
. filter_time = 0 ,
} ;
//interrupt set
TEST_ESP_OK ( pcnt_set_filter_value ( PCNT_UNIT_0 , 2 ) ) ;
TEST_ESP_OK ( pcnt_filter_enable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_set_event_value ( PCNT_UNIT_0 , PCNT_EVT_THRES_1 , - 4 ) ) ; // when arrive to max threshold trigger
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_THRES_1 ) ) ;
TEST_ESP_OK ( pcnt_set_event_value ( PCNT_UNIT_0 , PCNT_EVT_THRES_0 , 0 ) ) ; // when arrive to minimum threshold trigger
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_THRES_0 ) ) ;
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_ZERO ) ) ;
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_H_LIM ) ) ; // when arrive to max limit trigger
TEST_ESP_OK ( pcnt_event_enable ( PCNT_UNIT_0 , PCNT_EVT_L_LIM ) ) ; // when arrive to minimum limit trigger
// to initialize for PCNT
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
2019-12-02 16:34:59 +08:00
pcnt_evt_queue = xQueueCreate ( 10 , sizeof ( uint32_t ) ) ;
2020-09-10 10:37:58 +08:00
2019-12-02 16:34:59 +08:00
pcnt_isr_handle_t pcnt_isr_service ;
TEST_ESP_OK ( pcnt_isr_register ( pcnt_intr_handler , NULL , 0 , & pcnt_isr_service ) ) ;
2018-06-06 19:56:43 +08:00
TEST_ESP_OK ( pcnt_intr_enable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
// test event
event_calculate ( & event ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_limit , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_limit , 0 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . filter_time , 2 ) ;
// test interrupt disable
TEST_ESP_OK ( pcnt_intr_disable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
// for the original control io disable interrupt status
event_calculate ( & event ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_limit , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_limit , 0 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 1 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . filter_time , 2 ) ;
// enable the intr
pcnt_unit_config ( & config ) ;
2019-12-02 16:34:59 +08:00
pcnt_test_io_config ( PCNT_CTRL_LOW_LEVEL ) ;
2018-06-06 19:56:43 +08:00
TEST_ESP_OK ( pcnt_intr_enable ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_pause ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_clear ( PCNT_UNIT_0 ) ) ;
TEST_ESP_OK ( pcnt_counter_resume ( PCNT_UNIT_0 ) ) ;
event_calculate ( & event ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 3 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_limit , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_limit , 0 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . filter_time , 6 ) ;
// disable part of events
TEST_ESP_OK ( pcnt_event_disable ( PCNT_UNIT_0 , PCNT_EVT_ZERO ) ) ;
TEST_ESP_OK ( pcnt_event_disable ( PCNT_UNIT_0 , PCNT_EVT_L_LIM ) ) ;
TEST_ESP_OK ( pcnt_event_disable ( PCNT_UNIT_0 , PCNT_EVT_THRES_0 ) ) ;
event_calculate ( & event ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_threshold , 4 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_threshold , 3 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . l_limit , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . h_limit , 0 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . zero_times , 2 ) ;
TEST_ASSERT_INT_WITHIN ( 2 , event . filter_time , 8 ) ;
2019-12-02 16:34:59 +08:00
// Because this test uses its own ISR, we need to release it with `pcnt_isr_unregister` instead of `pcnt_isr_service_uninstall`
TEST_ESP_OK ( pcnt_isr_unregister ( pcnt_isr_service ) ) ;
vQueueDelete ( pcnt_evt_queue ) ;
2018-06-06 19:56:43 +08:00
}
2019-12-02 16:34:59 +08:00
TEST_CASE ( " PCNT counting mode test " , " [pcnt] " )
2018-06-06 19:56:43 +08:00
{
printf ( " PCNT mode test for positive count \n " ) ;
2019-12-02 16:34:59 +08:00
count_mode_test ( PCNT_CTRL_VCC_IO ) ;
2018-06-06 19:56:43 +08:00
printf ( " PCNT mode test for negative count \n " ) ;
count_mode_test ( PCNT_CTRL_GND_IO ) ;
2020-08-20 12:22:36 +08:00
}
2020-10-12 14:23:49 +08:00
# endif // #if SOC_PCNT_SUPPORTED