feat: initial
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
.DS_Store
 | 
			
		||||
							
								
								
									
										90
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								README.md
									
									
									
									
									
								
							@@ -1,3 +1,89 @@
 | 
			
		||||
# zh_avr_encoder
 | 
			
		||||
# FreeRTOS based AVR library for rotary encoder
 | 
			
		||||
 | 
			
		||||
FreeRTOS based AVR library for rotary encoder.
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
1. Support some encoders on one device.
 | 
			
		||||
 | 
			
		||||
## Using
 | 
			
		||||
 | 
			
		||||
In an existing project, run the following command to install the components:
 | 
			
		||||
 | 
			
		||||
```text
 | 
			
		||||
cd ../your_project/lib
 | 
			
		||||
git clone http://git.zh.com.ru/avr_libraries/zh_avr_free_rtos
 | 
			
		||||
git clone http://git.zh.com.ru/avr_libraries/zh_avr_common
 | 
			
		||||
git clone http://git.zh.com.ru/avr_libraries/zh_avr_encoder
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In the application, add the component:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
#include "zh_avr_encoder.h"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
 | 
			
		||||
One encoder on device:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
#include "avr/io.h"
 | 
			
		||||
#include "stdio.h"
 | 
			
		||||
#include "zh_avr_encoder.h"
 | 
			
		||||
 | 
			
		||||
#define BAUD_RATE 9600
 | 
			
		||||
#define BAUD_PRESCALE (F_CPU / 16 / BAUD_RATE - 1)
 | 
			
		||||
 | 
			
		||||
int usart(char byte, FILE *stream)
 | 
			
		||||
{
 | 
			
		||||
    while ((UCSR0A & (1 << UDRE0)) == 0)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    UDR0 = byte;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
FILE uart = FDEV_SETUP_STREAM(usart, NULL, _FDEV_SETUP_WRITE);
 | 
			
		||||
 | 
			
		||||
zh_avr_encoder_handle_t encoder_handle = {0};
 | 
			
		||||
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
    UBRR0H = (BAUD_PRESCALE >> 8);
 | 
			
		||||
    UBRR0L = BAUD_PRESCALE;
 | 
			
		||||
    UCSR0B = (1 << RXEN0) | (1 << TXEN0);
 | 
			
		||||
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
 | 
			
		||||
    stdout = &uart;
 | 
			
		||||
    zh_avr_encoder_init_config_t encoder_init_config = ZH_AVR_ENCODER_INIT_CONFIG_DEFAULT();
 | 
			
		||||
    encoder_init_config.gpio_port = AVR_PORTD;
 | 
			
		||||
    encoder_init_config.a_gpio_number = PORTD5;
 | 
			
		||||
    encoder_init_config.b_gpio_number = PORTD6;
 | 
			
		||||
    encoder_init_config.pullup = true;
 | 
			
		||||
    encoder_init_config.encoder_min_value = -10;
 | 
			
		||||
    encoder_init_config.encoder_max_value = 20;
 | 
			
		||||
    encoder_init_config.encoder_step = 1;
 | 
			
		||||
    encoder_init_config.encoder_number = 1;
 | 
			
		||||
    zh_avr_encoder_init(&encoder_init_config, &encoder_handle);
 | 
			
		||||
    double position = 0;
 | 
			
		||||
    zh_avr_encoder_get(&encoder_handle, &position);
 | 
			
		||||
    printf("Encoder position %d.\n", (int)position);
 | 
			
		||||
    zh_avr_encoder_set(&encoder_handle, 5);
 | 
			
		||||
    zh_avr_encoder_reset(&encoder_handle);
 | 
			
		||||
    vTaskStartScheduler();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void zh_avr_encoder_event_handler(zh_avr_encoder_event_on_isr_t *event) // Do not delete!
 | 
			
		||||
{
 | 
			
		||||
    printf("Encoder number %d position %d.\n", event->encoder_number, (int)event->encoder_position);
 | 
			
		||||
    printf("Interrupt Task Remaining Stack Size %d.\n", uxTaskGetStackHighWaterMark(NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ISR(PCINT0_vect) // For AVR_PORTB.
 | 
			
		||||
// ISR(PCINT1_vect) // For AVR_PORTC.
 | 
			
		||||
ISR(PCINT2_vect) // For AVR_PORTD.
 | 
			
		||||
{
 | 
			
		||||
    if (zh_avr_encoder_isr_handler(&encoder_handle) == pdTRUE)
 | 
			
		||||
    {
 | 
			
		||||
        portYIELD();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										119
									
								
								include/zh_avr_encoder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								include/zh_avr_encoder.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "semphr.h"
 | 
			
		||||
#include "avr_err.h"
 | 
			
		||||
#include "avr_port.h"
 | 
			
		||||
#include "stdbool.h"
 | 
			
		||||
#include "avr/interrupt.h"
 | 
			
		||||
#include "avr/pgmspace.h"
 | 
			
		||||
 | 
			
		||||
#define ZH_AVR_ENCODER_INIT_CONFIG_DEFAULT()   \
 | 
			
		||||
    {                                          \
 | 
			
		||||
        .task_priority = configMAX_PRIORITIES, \
 | 
			
		||||
        .stack_size = 124,                     \
 | 
			
		||||
        .queue_size = 1,                       \
 | 
			
		||||
        .gpio_port = 0,                        \
 | 
			
		||||
        .a_gpio_number = 0,                    \
 | 
			
		||||
        .b_gpio_number = 0,                    \
 | 
			
		||||
        .pullup = false,                       \
 | 
			
		||||
        .encoder_min_value = -100,             \
 | 
			
		||||
        .encoder_max_value = 100,              \
 | 
			
		||||
        .encoder_step = 1,                     \
 | 
			
		||||
        .encoder_number = 0}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    typedef struct // Structure for initial initialization of encoder.
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t task_priority;     // Task priority for the encoder isr processing. @note It is not recommended to set a value less than configMAX_PRIORITIES.
 | 
			
		||||
        uint16_t stack_size;       // Stack size for task for the encoder isr processing processing. @note The minimum size is 124 bytes.
 | 
			
		||||
        uint8_t queue_size;        // Queue size for task for the encoder processing. Depends on the number of encoders.
 | 
			
		||||
        uint8_t gpio_port;         // Encoder GPIO port. @note Must be same for A and B GPIO.
 | 
			
		||||
        uint8_t a_gpio_number;     // Encoder A GPIO number.
 | 
			
		||||
        uint8_t b_gpio_number;     // Encoder B GPIO number.
 | 
			
		||||
        bool pullup;               // Using internal pullup resistors.
 | 
			
		||||
        int32_t encoder_min_value; // Encoder min value. @note Must be less than encoder_max_value.
 | 
			
		||||
        int32_t encoder_max_value; // Encoder max value. @note Must be greater than encoder_min_value.
 | 
			
		||||
        double encoder_step;       // Encoder step. @note Must be greater than 0.
 | 
			
		||||
        uint8_t encoder_number;    // Unique encoder number.
 | 
			
		||||
    } zh_avr_encoder_init_config_t;
 | 
			
		||||
 | 
			
		||||
    typedef struct // Encoder handle.
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t gpio_port;         // Encoder GPIO port.
 | 
			
		||||
        uint8_t a_gpio_number;     // Encoder A GPIO number.
 | 
			
		||||
        uint8_t b_gpio_number;     // Encoder B GPIO number.
 | 
			
		||||
        int32_t encoder_min_value; // Encoder min value.
 | 
			
		||||
        int32_t encoder_max_value; // Encoder max value.
 | 
			
		||||
        double encoder_step;       // Encoder step.
 | 
			
		||||
        double encoder_position;   // Encoder position.
 | 
			
		||||
        uint8_t encoder_number;    // Encoder unique number.
 | 
			
		||||
        uint8_t encoder_state;     // Encoder internal state.
 | 
			
		||||
        bool is_initialized;       // Encoder initialization flag.
 | 
			
		||||
    } zh_avr_encoder_handle_t;
 | 
			
		||||
 | 
			
		||||
    typedef struct // Structure for sending data to the event handler when cause an interrupt. @note Should be used with zh_avr_encoder event base.
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t encoder_number;  // Encoder unique number.
 | 
			
		||||
        double encoder_position; // Encoder current position.
 | 
			
		||||
    } zh_avr_encoder_event_on_isr_t;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Initialize encoder.
 | 
			
		||||
     *
 | 
			
		||||
     * @note The encoder will be set to the position (encoder_min_value + encoder_max_value)/2.
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in] config Pointer to encoder initialized configuration structure. Can point to a temporary variable.
 | 
			
		||||
     * @param[out] handle Pointer to unique encoder handle.
 | 
			
		||||
     *
 | 
			
		||||
     * @note Before initialize the encoder recommend initialize zh_avr_encoder_init_config_t structure with default values.
 | 
			
		||||
     *
 | 
			
		||||
     * @code zh_avr_encoder_init_config_t config = ZH_AVR_ENCODER_INIT_CONFIG_DEFAULT() @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * @return AVR_OK if success or an error code otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    avr_err_t zh_avr_encoder_init(const zh_avr_encoder_init_config_t *config, zh_avr_encoder_handle_t *handle);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Set encoder position.
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in, out] handle Pointer to unique encoder handle.
 | 
			
		||||
     * @param[in] position Encoder position (must be between encoder_min_value and encoder_max_value).
 | 
			
		||||
     *
 | 
			
		||||
     * @return AVR_OK if success or an error code otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    avr_err_t zh_avr_encoder_set(zh_avr_encoder_handle_t *handle, double position);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Get encoder position.
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in] handle Pointer to unique encoder handle.
 | 
			
		||||
     * @param[out] position Encoder position.
 | 
			
		||||
     *
 | 
			
		||||
     * @return AVR_OK if success or an error code otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    avr_err_t zh_avr_encoder_get(const zh_avr_encoder_handle_t *handle, double *position);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Reset encoder position.
 | 
			
		||||
     *
 | 
			
		||||
     * @note The encoder will be set to the position (encoder_min_value + encoder_max_value)/2.
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in, out] handle Pointer to unique encoder handle.
 | 
			
		||||
     *
 | 
			
		||||
     * @return AVR_OK if success or an error code otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    avr_err_t zh_avr_encoder_reset(zh_avr_encoder_handle_t *handle);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Encoder ISR handler.
 | 
			
		||||
     */
 | 
			
		||||
    BaseType_t zh_avr_encoder_isr_handler(zh_avr_encoder_handle_t *handle);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1
									
								
								version.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								version.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
1.0.0
 | 
			
		||||
							
								
								
									
										191
									
								
								zh_avr_encoder.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								zh_avr_encoder.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
#include "zh_avr_encoder.h"
 | 
			
		||||
 | 
			
		||||
#define ENCODER_DIRECTION_CW 0x10
 | 
			
		||||
#define ENCODER_DIRECTION_CCW 0x20
 | 
			
		||||
 | 
			
		||||
static const uint8_t _encoder_matrix[7][4] PROGMEM = {
 | 
			
		||||
    {0x03, 0x02, 0x01, 0x00},
 | 
			
		||||
    {0x23, 0x00, 0x01, 0x00},
 | 
			
		||||
    {0x13, 0x02, 0x00, 0x00},
 | 
			
		||||
    {0x03, 0x05, 0x04, 0x00},
 | 
			
		||||
    {0x03, 0x03, 0x04, 0x00},
 | 
			
		||||
    {0x03, 0x05, 0x03, 0x00},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TaskHandle_t zh_avr_encoder = NULL;
 | 
			
		||||
static QueueHandle_t _queue_handle = NULL;
 | 
			
		||||
static bool _is_initialized = false;
 | 
			
		||||
 | 
			
		||||
static avr_err_t _zh_avr_encoder_validate_config(const zh_avr_encoder_init_config_t *config);
 | 
			
		||||
static avr_err_t _zh_avr_encoder_configure_interrupts(const zh_avr_encoder_init_config_t *config, zh_avr_encoder_handle_t *handle);
 | 
			
		||||
static void _zh_avr_encoder_isr_processing_task(void *pvParameter);
 | 
			
		||||
 | 
			
		||||
avr_err_t zh_avr_encoder_init(const zh_avr_encoder_init_config_t *config, zh_avr_encoder_handle_t *handle)
 | 
			
		||||
{
 | 
			
		||||
    avr_err_t err = _zh_avr_encoder_validate_config(config);
 | 
			
		||||
    ZH_ERROR_CHECK(err == AVR_OK, err);
 | 
			
		||||
    handle->encoder_number = config->encoder_number;
 | 
			
		||||
    handle->encoder_min_value = config->encoder_min_value;
 | 
			
		||||
    handle->encoder_max_value = config->encoder_max_value;
 | 
			
		||||
    handle->encoder_step = config->encoder_step;
 | 
			
		||||
    handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2;
 | 
			
		||||
    handle->gpio_port = config->gpio_port;
 | 
			
		||||
    handle->a_gpio_number = config->a_gpio_number;
 | 
			
		||||
    handle->b_gpio_number = config->b_gpio_number;
 | 
			
		||||
    err = _zh_avr_encoder_configure_interrupts(config, handle);
 | 
			
		||||
    ZH_ERROR_CHECK(err == AVR_OK, err);
 | 
			
		||||
    handle->is_initialized = true;
 | 
			
		||||
    _is_initialized = true;
 | 
			
		||||
    return AVR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
avr_err_t zh_avr_encoder_set(zh_avr_encoder_handle_t *handle, double position)
 | 
			
		||||
{
 | 
			
		||||
    ZH_ERROR_CHECK(handle->is_initialized == true, AVR_FAIL);
 | 
			
		||||
    ZH_ERROR_CHECK(position <= handle->encoder_max_value && position >= handle->encoder_min_value, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    handle->encoder_position = position;
 | 
			
		||||
    return AVR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
avr_err_t zh_avr_encoder_get(const zh_avr_encoder_handle_t *handle, double *position)
 | 
			
		||||
{
 | 
			
		||||
    ZH_ERROR_CHECK(handle->is_initialized == true, AVR_FAIL);
 | 
			
		||||
    *position = handle->encoder_position;
 | 
			
		||||
    return AVR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
avr_err_t zh_avr_encoder_reset(zh_avr_encoder_handle_t *handle)
 | 
			
		||||
{
 | 
			
		||||
    ZH_ERROR_CHECK(handle->is_initialized == true, AVR_FAIL);
 | 
			
		||||
    handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2;
 | 
			
		||||
    return AVR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static avr_err_t _zh_avr_encoder_validate_config(const zh_avr_encoder_init_config_t *config)
 | 
			
		||||
{
 | 
			
		||||
    ZH_ERROR_CHECK(config != NULL, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->task_priority > tskIDLE_PRIORITY && config->stack_size >= 124, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->queue_size > 0, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->encoder_max_value > config->encoder_min_value, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->encoder_step > 0, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->gpio_port >= AVR_PORTB && config->gpio_port <= AVR_PORTD, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->a_gpio_number >= 0 && config->a_gpio_number <= 7, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->b_gpio_number >= 0 && config->b_gpio_number <= 7, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    ZH_ERROR_CHECK(config->a_gpio_number != config->b_gpio_number, AVR_ERR_INVALID_ARG);
 | 
			
		||||
    return AVR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static avr_err_t _zh_avr_encoder_configure_interrupts(const zh_avr_encoder_init_config_t *config, zh_avr_encoder_handle_t *handle)
 | 
			
		||||
{
 | 
			
		||||
    switch (config->gpio_port)
 | 
			
		||||
    {
 | 
			
		||||
    case AVR_PORTB:
 | 
			
		||||
        DDRB &= ~((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        if (config->pullup == true)
 | 
			
		||||
        {
 | 
			
		||||
            PORTB |= ((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        }
 | 
			
		||||
        PCICR |= (1 << PCIE0);
 | 
			
		||||
        PCMSK0 |= ((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        break;
 | 
			
		||||
    case AVR_PORTC:
 | 
			
		||||
        DDRC &= ~((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        if (config->pullup == true)
 | 
			
		||||
        {
 | 
			
		||||
            PORTC |= ((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        }
 | 
			
		||||
        PCICR |= (1 << PCIE1);
 | 
			
		||||
        PCMSK1 |= ((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        break;
 | 
			
		||||
    case AVR_PORTD:
 | 
			
		||||
        DDRD &= ~((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        if (config->pullup == true)
 | 
			
		||||
        {
 | 
			
		||||
            PORTD |= ((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        }
 | 
			
		||||
        PCICR |= (1 << PCIE2);
 | 
			
		||||
        PCMSK2 |= ((1 << config->a_gpio_number) | (1 << config->b_gpio_number));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        return AVR_ERR_INVALID_ARG;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    if (_is_initialized == false)
 | 
			
		||||
    {
 | 
			
		||||
        _queue_handle = xQueueCreate(config->queue_size, sizeof(zh_avr_encoder_handle_t));
 | 
			
		||||
        ZH_ERROR_CHECK(_queue_handle != NULL, AVR_ERR_NO_MEM);
 | 
			
		||||
        BaseType_t x_err = xTaskCreate(_zh_avr_encoder_isr_processing_task, "zh_avr_encoder", config->stack_size, NULL, config->task_priority, &zh_avr_encoder);
 | 
			
		||||
        if (x_err != pdPASS)
 | 
			
		||||
        {
 | 
			
		||||
            vQueueDelete(_queue_handle);
 | 
			
		||||
            return AVR_FAIL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return AVR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BaseType_t zh_avr_encoder_isr_handler(zh_avr_encoder_handle_t *handle)
 | 
			
		||||
{
 | 
			
		||||
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 | 
			
		||||
    uint8_t temp = 0;
 | 
			
		||||
    switch (handle->gpio_port)
 | 
			
		||||
    {
 | 
			
		||||
    case AVR_PORTB:
 | 
			
		||||
        temp = pgm_read_byte(&_encoder_matrix[handle->encoder_state & 0x0F][(((PINB & (1 << handle->b_gpio_number)) == 0 ? 0 : 1) << 1) | ((PINB & (1 << handle->a_gpio_number)) == 0 ? 0 : 1)]);
 | 
			
		||||
        break;
 | 
			
		||||
    case AVR_PORTC:
 | 
			
		||||
        temp = pgm_read_byte(&_encoder_matrix[handle->encoder_state & 0x0F][(((PINC & (1 << handle->b_gpio_number)) == 0 ? 0 : 1) << 1) | ((PINC & (1 << handle->a_gpio_number)) == 0 ? 0 : 1)]);
 | 
			
		||||
        break;
 | 
			
		||||
    case AVR_PORTD:
 | 
			
		||||
        temp = pgm_read_byte(&_encoder_matrix[handle->encoder_state & 0x0F][(((PIND & (1 << handle->b_gpio_number)) == 0 ? 0 : 1) << 1) | ((PIND & (1 << handle->a_gpio_number)) == 0 ? 0 : 1)]);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    if (temp != handle->encoder_state)
 | 
			
		||||
    {
 | 
			
		||||
        handle->encoder_state = temp;
 | 
			
		||||
        switch (handle->encoder_state & 0x30)
 | 
			
		||||
        {
 | 
			
		||||
        case ENCODER_DIRECTION_CW:
 | 
			
		||||
            if (handle->encoder_position < handle->encoder_max_value)
 | 
			
		||||
            {
 | 
			
		||||
                handle->encoder_position = handle->encoder_position + handle->encoder_step;
 | 
			
		||||
                if (handle->encoder_position > handle->encoder_max_value)
 | 
			
		||||
                {
 | 
			
		||||
                    handle->encoder_position = handle->encoder_max_value;
 | 
			
		||||
                }
 | 
			
		||||
                xQueueSendFromISR(_queue_handle, handle, &xHigherPriorityTaskWoken);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case ENCODER_DIRECTION_CCW:
 | 
			
		||||
            if (handle->encoder_position > handle->encoder_min_value)
 | 
			
		||||
            {
 | 
			
		||||
                handle->encoder_position = handle->encoder_position - handle->encoder_step;
 | 
			
		||||
                if (handle->encoder_position < handle->encoder_min_value)
 | 
			
		||||
                {
 | 
			
		||||
                    handle->encoder_position = handle->encoder_min_value;
 | 
			
		||||
                }
 | 
			
		||||
                xQueueSendFromISR(_queue_handle, handle, &xHigherPriorityTaskWoken);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return xHigherPriorityTaskWoken;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _zh_avr_encoder_isr_processing_task(void *pvParameter)
 | 
			
		||||
{
 | 
			
		||||
    zh_avr_encoder_handle_t queue = {0};
 | 
			
		||||
    zh_avr_encoder_event_on_isr_t event = {0};
 | 
			
		||||
    while (xQueueReceive(_queue_handle, &queue, portMAX_DELAY) == pdTRUE)
 | 
			
		||||
    {
 | 
			
		||||
        event.encoder_number = queue.encoder_number;
 | 
			
		||||
        event.encoder_position = queue.encoder_position;
 | 
			
		||||
        extern void zh_avr_encoder_event_handler(zh_avr_encoder_event_on_isr_t * event);
 | 
			
		||||
        zh_avr_encoder_event_handler(&event);
 | 
			
		||||
    }
 | 
			
		||||
    vTaskDelete(NULL);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user