/**
 * @file rtos_drv.h
 * @author June6 (https://github.com/Junedoubling6)
 * @brief
 * @version 0.2
 * @date 2023-03-03
 *
 * @copyright Copyright (c) 2022 - , All rights reserved.
 *
 */
#ifndef RTOS_DRV_H__
#define RTOS_DRV_H__

#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "err_code.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
/* 提供FreeRTOS定时器支持 */
#include "freertos/timers.h"
#include "param_drv.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 事件位 */
#define TASK_BIT_1 (0x01 << 0)
#define TASK_BIT_2 (0x01 << 1)
#define TASK_BIT_3 (0x01 << 2)
#define TASK_BIT_4 (0x01 << 3)
#define TASK_BIT_5 (0x01 << 4)
#define TASK_BIT_6 (0x01 << 5)
#define TASK_BIT_7 (0x01 << 6)
#define TASK_BIT_8 (0x01 << 7)
#define TASK_BIT_9 (0x01 << 8)
#define TASK_BIT_10 (0x01 << 9)
#define TASK_BIT_11 (0x01 << 10)
#define TASK_BIT_12 (0x01 << 11)
#define TASK_BIT_13 (0x01 << 12)
#define TASK_BIT_14 (0x01 << 13)
#define TASK_BIT_15 (0x01 << 14)
#define TASK_BIT_16 (0x01 << 15)
#define TASK_BIT_17 (0x01 << 16)
#define TASK_BIT_18 (0x01 << 17)
#define TASK_BIT_19 (0x01 << 18)
#define TASK_BIT_20 (0x01 << 19)
#define TASK_BIT_21 (0x01 << 20)
#define TASK_BIT_22 (0x01 << 21)
#define TASK_BIT_23 (0x01 << 22)
#define TASK_BIT_24 (0x01 << 23)
#define TASK_BIT_25 (0x01 << 24)
#define TASK_BIT_26 (0x01 << 25)
#define TASK_BIT_27 (0x01 << 26)
#define TASK_BIT_28 (0x01 << 27)
#define TASK_BIT_29 (0x01 << 28)
#define TASK_BIT_30 (0x01 << 29)
#define TASK_BIT_31 (0x01 << 30)
#define TASK_BIT_32 (0x01 << 31)
#define WDT_TASK_BIT_ALL ()

/* 定时器 */
#define ADC_TIMER ((const char *)"adc_timer")

/* 数据消息长度 */
#define DATA_MSG_NUM ((UBaseType_t)50)
#define DATASET_MSG_NUM ((UBaseType_t)50)

/* 任务 */
#define LCD_PANEL_UI_TASK ((const char *)"lcd_panel_ui_task")
#if CONFIG_LCD_CONTROLLER_SLEEP_WAKEUP
#define LCD_PANEL_RESTART_TASK ((const char *)"lcd_panel_restart_task")
#endif
#define UPDATE_SCREEN_CONTENT_TASK ((const char *)"update_screen_content_task")

/* 任务协议栈大小 */
/* NOTE: June6 如果UI事件执行过程中出现崩溃, 请考虑添加任务堆栈空间大小 */
#define LCD_PANEL_UI_STK_SIZE ((uint16_t)30 * 1024)
#if CONFIG_LCD_CONTROLLER_SLEEP_WAKEUP
#define LCD_PANEL_RESTART_STK_SIZE ((uint16_t)5 * 1024)
#endif
#define UPDATE_SCREEN_CONTENT_STK_SIZE ((uint16_t)4 * 1024)

/* 任务优先级 */
/* 值越小, 优先级越低 */
/* NOTE: June6 优先级为0-20的任务留给协议栈进行处理 */
#define LCD_PANEL_UI_TASK_PRIO ((UBaseType_t)configMAX_PRIORITIES-1)
#if CONFIG_LCD_CONTROLLER_SLEEP_WAKEUP
#define LCD_PANEL_RESTART_TASK_PRIO ((UBaseType_t)12)
#endif
#define UPDATE_SCREEN_CONTENT_TASK_PRIO ((UBaseType_t)13)

/* 任务执行周期 */
#define LCD_PANEL_UI_TASK_PERIOD_MS ((TickType_t)10)
#define LCD_PANEL_UI_TASK_MAX_PERIOD_MS ((TickType_t)500)
#define LCD_PANEL_UI_TASK_MIN_PERIOD_MS ((TickType_t)10)
#define UPDATE_SCREEN_CONTENT_TASK_PERIOD_MS ((TickType_t)1000)

#define SEMAPHORE_TAKE_WAIT_TICK ((TickType_t)0)
#define QUEUE_SEND_WAIT_TICK ((TickType_t)0)
/* NOTE: June6 一个任务中PEEK的多个队列不能有最长时间,
 * 否则将导致只接收其中一个队列 */
#define QUEUE_PEEK_WAIT_TICK ((TickType_t)0)
/* NOTE: June6 当同一队列为PEEK时, 需要将其设置为0 */
#define QUEUE_RECEIVE_WAIT_TICK ((TickType_t)0)

/* 信号量 */
extern SemaphoreHandle_t lvgl_mutex_semaphore_handler;

/* 队列句柄 */

/* 任务句柄 */
extern TaskHandle_t lcd_panel_ui_task_handler;
extern StackType_t lcd_panel_ui_task_stack_buffer[LCD_PANEL_UI_STK_SIZE];
extern StaticTask_t lcd_panel_ui_task_buffer;
#if CONFIG_LCD_CONTROLLER_SLEEP_WAKEUP
extern TaskHandle_t lcd_panel_restart_task_handler;
extern StaticTask_t lcd_panel_restart_task_buffer;
extern StackType_t
    lcd_panel_restart_task_stack_buffer[LCD_PANEL_RESTART_STK_SIZE];
#endif
extern TaskHandle_t update_screen_content_task_handler;
extern StackType_t
    update_screen_content_stack_task_buffer[UPDATE_SCREEN_CONTENT_STK_SIZE];
extern StaticTask_t update_screen_content_task_buffer;

/* 事件标志组句柄 */

/**
 * @brief Delete timer.
 *
 * @param timer_handle
 * @return ErrorStatus
 */
ErrorStatus timer_delete(TimerHandle_t timer_handle);

/**
 * @brief timer start.
 *
 * @param from_isr_flag
 * @param timer_handle
 * @param cmd
 * @param detecte_active_flag
 * @return ErrorStatus
 */
ErrorStatus timer_start(bool from_isr_flag, TimerHandle_t timer_handle,
                        bool cmd, bool detecte_active_flag);

/**
 * @brief Change timer period.
 *
 * @param from_isr_flag
 * @param timer_handle
 * @param period_ms
 * @return ErrorStatus
 */
ErrorStatus timer_period_change(bool from_isr_flag, TimerHandle_t timer_handle,
                                uint32_t period_ms);

/**
 * @brief Get timer period.
 *
 * @param handtimer_handleler
 * @return TickType_t
 */
TickType_t timer_period_get(TimerHandle_t timer_handle);

/**
 * @brief Get timer remaining time.
 *
 * @param from_isr_flag
 * @param timer_handle
 * @param timer_period_ms
 * @param get_remain_flag
 * @return TickType_t
 */
TickType_t timer_remaining_time_get(bool from_isr_flag,
                                    TimerHandle_t timer_handle,
                                    TickType_t timer_period_ms,
                                    bool get_remain_flag);

/**
 * @brief Task delay.
 *
 * @param tick
 */
void rtos_task_delay(TickType_t tick);

/**
 * @brief Send data byte queue.
 *
 * @param queue_handle
 * @param data
 * @return ErrorStatus
 */
ErrorStatus byte_queue_send(QueueHandle_t queue_handle, uint32_t data);

/**
 * @brief Send data server queue.
 *
 * @param from_isr_flag
 * @param queue_handle
 * @param data
 * @return ErrorStatus
 */
ErrorStatus server_queue_send(bool from_isr_flag, QueueHandle_t queue_handle,
                              ServerData_t *data);

/**
 * @brief Send dataset server queue.
 *
 * @param from_isr_flag
 * @param queue_handle
 * @param data
 * @return ErrorStatus
 */
ErrorStatus server_dataset_queue_send(bool from_isr_flag,
                                      QueueHandle_t queue_handle,
                                      ServerDataSet_t *data);

#ifdef __cplusplus
}
#endif

#endif  // RTOS_DRV_H__
