/* Include Files */
#include "KTag.h"

TaskHandle_t Tag_Sensors_Task_Handle;

//#define DEBUG_TAG_SENSORS

#define MAX_RX_PULSES (2 * MAX_PULSES)

typedef enum
{
    FALLING_EDGE,
    RISING_EDGE
} EdgeDirection_T;

static volatile uint32_t LocalIncomingPulseDurations[MAX_RX_PULSES];
static volatile uint32_t RemoteIncomingPulseDurations[MAX_RX_PULSES];
static volatile uint16_t LocalPulseIndex = 0;
static volatile uint16_t RemotePulseIndex = 0;
static volatile uint16_t NumberOfLocalIncomingPulses = 0;
static volatile uint16_t NumberOfRemoteIncomingPulses = 0;
static volatile TagSensorLocation_T LocalActiveSensor = TAG_SENSOR_NONE;
static uint32_t LocalProcessingPulseDurations[MAX_RX_PULSES];
static uint32_t RemoteProcessingPulseDurations[MAX_RX_PULSES];
static uint16_t NumberOfLocalProcessingPulses = 0;
static uint16_t NumberOfRemoteProcessingPulses = 0;
static TimedPulseTrain_T LocalProcessingPulses;
static TimedPulseTrain_T RemoteProcessingPulses;
static TagSensorLocation_T LocalProcessingSensor = TAG_SENSOR_NONE;
static volatile EdgeDirection_T LocalExpectedEdgeDirection = FALLING_EDGE;
static volatile EdgeDirection_T RemoteExpectedEdgeDirection = FALLING_EDGE;


void On_Forward_Tag_Sensor_Rising_Edge();
void On_Forward_Tag_Sensor_Falling_Edge();
void On_Left_Tag_Sensor_Rising_Edge();
void On_Left_Tag_Sensor_Falling_Edge();
void On_Right_Tag_Sensor_Rising_Edge();
void On_Right_Tag_Sensor_Falling_Edge();
void On_Remote_Tag_Sensor_Rising_Edge();
void On_Remote_Tag_Sensor_Falling_Edge();
void On_Local_Tag_Sensor_Bit_Stream_Timer();
void On_Remote_Tag_Sensor_Bit_Stream_Timer();

QueueHandle_t xQueueTagSensors;

#ifdef DEBUG_TAG_SENSORS
static char8 buffer[30];
#endif // DEBUG_TAG_SENSORS

inline static void AppendLocalPulse(uint32_t duration)
{
    LocalIncomingPulseDurations[LocalPulseIndex] = duration;
    
    if (LocalPulseIndex < (MAX_RX_PULSES - 1))
    {
        LocalPulseIndex++;
    }
}

inline static void AppendRemotePulse(uint32_t duration)
{
    RemoteIncomingPulseDurations[RemotePulseIndex] = duration;
    
    if (RemotePulseIndex < (MAX_RX_PULSES - 1))
    {
        RemotePulseIndex++;
    }
}

inline static void EnableAllLocalEdgeISRs(void)
{   
    NVIC_EnableIRQ(Forward_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_EnableIRQ(Forward_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
    NVIC_EnableIRQ(Left_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_EnableIRQ(Left_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
    NVIC_EnableIRQ(Right_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_EnableIRQ(Right_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
}

inline static void EnableAllRemoteEdgeISRs(void)
{
    NVIC_EnableIRQ(Remote_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_EnableIRQ(Remote_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
}

inline static void DisableAllLocalRisingEdgeISRs(void)
{
    NVIC_DisableIRQ(Forward_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_DisableIRQ(Left_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_DisableIRQ(Right_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
}

inline static void DisableAllRemoteRisingEdgeISRs(void)
{
    NVIC_DisableIRQ(Remote_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
}

inline static void DisableAllLocalFallingEdgeISRs(void)
{
    NVIC_DisableIRQ(Forward_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
    NVIC_DisableIRQ(Left_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
    NVIC_DisableIRQ(Right_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
}

inline static void DisableAllRemoteFallingEdgeISRs(void)
{
    NVIC_DisableIRQ(Remote_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
}

inline static void DisableAllLocalEdgeISRs(void)
{
    DisableAllLocalRisingEdgeISRs();
    DisableAllLocalFallingEdgeISRs();
}

inline static void DisableAllRemoteEdgeISRs(void)
{
    DisableAllRemoteRisingEdgeISRs();
    DisableAllRemoteFallingEdgeISRs();
}

inline static void ClearAllPendingLocalEdgeISRs(void)
{
    NVIC_ClearPendingIRQ(Forward_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_ClearPendingIRQ(Forward_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
    NVIC_ClearPendingIRQ(Left_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_ClearPendingIRQ(Left_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
    NVIC_ClearPendingIRQ(Right_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_ClearPendingIRQ(Right_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
}

inline static void ClearAllPendingRemoteEdgeISRs(void)
{
    NVIC_ClearPendingIRQ(Remote_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
    NVIC_ClearPendingIRQ(Remote_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
}

void Tag_Sensors_Init(void)
{
    // Register the Local ISRs.
    Cy_SysInt_Init(&Forward_Tag_Sensor_Rising_Edge_ISR_cfg, On_Forward_Tag_Sensor_Rising_Edge);
    Cy_SysInt_Init(&Forward_Tag_Sensor_Falling_Edge_ISR_cfg, On_Forward_Tag_Sensor_Falling_Edge);
    Cy_SysInt_Init(&Left_Tag_Sensor_Rising_Edge_ISR_cfg, On_Left_Tag_Sensor_Rising_Edge);
    Cy_SysInt_Init(&Left_Tag_Sensor_Falling_Edge_ISR_cfg, On_Left_Tag_Sensor_Falling_Edge);
    Cy_SysInt_Init(&Right_Tag_Sensor_Rising_Edge_ISR_cfg, On_Right_Tag_Sensor_Rising_Edge);
    Cy_SysInt_Init(&Right_Tag_Sensor_Falling_Edge_ISR_cfg, On_Right_Tag_Sensor_Falling_Edge);
    Cy_SysInt_Init(&Local_Tag_Sensor_Bit_Stream_Timer_Interrupt_cfg, On_Local_Tag_Sensor_Bit_Stream_Timer);
    
    // Register the Remote ISRs.
    Cy_SysInt_Init(&Remote_Tag_Sensor_Rising_Edge_ISR_cfg, On_Remote_Tag_Sensor_Rising_Edge);
    Cy_SysInt_Init(&Remote_Tag_Sensor_Falling_Edge_ISR_cfg, On_Remote_Tag_Sensor_Falling_Edge);
    Cy_SysInt_Init(&Remote_Tag_Sensor_Bit_Stream_Timer_Interrupt_cfg, On_Remote_Tag_Sensor_Bit_Stream_Timer);
    
    // Enable the forward, left, right, and remote sensors.
    Tag_Sensor_Register_Write(0xFF - 0x0F);
    
    xQueueTagSensors = xQueueCreate(5, sizeof(TagSensorsAction_T));
    
    // Enable the timers.
    NVIC_EnableIRQ(Local_Tag_Sensor_Bit_Stream_Timer_Interrupt_cfg.intrSrc);
    NVIC_EnableIRQ(Remote_Tag_Sensor_Bit_Stream_Timer_Interrupt_cfg.intrSrc);
    
    // Enable the sensors.
    EnableAllLocalEdgeISRs();
    EnableAllRemoteEdgeISRs();
    
}

void Tag_Sensors_Task(void * pvParameters)
{
    portBASE_TYPE xStatus;
    
    while (true)
    {
        TagSensorsAction_T action;
        
        xStatus = xQueueReceive(xQueueTagSensors, &action, 0);
        
        if (xStatus == pdPASS)
        {
            switch (action)
            {
                case TAG_SENSOR_PROCESS_LOCAL_BUFFER:
                    {                        
                        for (uint8_t i = 0; i < NumberOfLocalIncomingPulses; i++)
                        {
                            LocalProcessingPulseDurations[i] = LocalIncomingPulseDurations[i];
                        }
                        NumberOfLocalProcessingPulses = NumberOfLocalIncomingPulses;
                        NumberOfLocalIncomingPulses = 0;
                        LocalProcessingSensor = LocalActiveSensor;
                        LocalActiveSensor = TAG_SENSOR_NONE;
                        EnableAllLocalEdgeISRs();
                        
#ifdef DEBUG_TAG_SENSORS         
                        COMM_Console_Print_String("\n");
                        
                        switch (LocalProcessingSensor)
                        {
                            case TAG_SENSOR_FORWARD:
                                COMM_Console_Print_String("Tag Rx'd FORWARD\n");
                                vTaskDelay(pdMS_TO_TICKS(10));
                                break;
                                
                            case TAG_SENSOR_LEFT:
                                COMM_Console_Print_String("Tag Rx'd LEFT\n");
                                vTaskDelay(pdMS_TO_TICKS(10));
                                break;
                                
                            case TAG_SENSOR_RIGHT:
                                COMM_Console_Print_String("Tag Rx'd RIGHT\n");
                                vTaskDelay(pdMS_TO_TICKS(10));
                                break;
                                
                            default:
                            case TAG_SENSOR_REMOTE:
                            case TAG_SENSOR_NONE:
                                break;
                        }
                    
                        for (uint_fast16_t i = 0; i < NumberOfLocalProcessingPulses; i++)
                        {
                            // Even pulses are marks; odd pulses are spaces.
                            if ((i % 2) == 0)
                            {
                                COMM_Console_Print_String("{.symbol = MARK,  .time = ");
                                sprintf(buffer, "%lu},  // %d\n", LocalProcessingPulseDurations[i], i);
                                COMM_Console_Print_String(buffer);
                                vTaskDelay(pdMS_TO_TICKS(10));
                            }
                            // A falling edge is the end of space.
                            else
                            {
                                COMM_Console_Print_String("{.symbol = SPACE, .time = ");
                                sprintf(buffer, "%lu},  // %d\n", LocalProcessingPulseDurations[i], i);
                                COMM_Console_Print_String(buffer);
                                vTaskDelay(pdMS_TO_TICKS(10));
                            }
                        }
#endif // DEBUG_TAG_SENSORS
                        
                        LocalProcessingPulses.count = NumberOfLocalProcessingPulses;
                        for (uint_fast16_t i = 0; (i < NumberOfLocalProcessingPulses) && (i < MAX_RX_PULSES); i++)
                        {
                            if ((i % 2) == 0)
                            {
                                LocalProcessingPulses.bitstream[i].symbol = MARK;
                            }
                            else
                            {
                                 LocalProcessingPulses.bitstream[i].symbol = SPACE;
                            }
                            LocalProcessingPulses.bitstream[i].duration = LocalProcessingPulseDurations[i];
                        }
                        LocalProcessingPulses.bitstream[NumberOfLocalProcessingPulses].duration = LAST_PULSE;
                        LocalProcessingPulses.receiver = LocalProcessingSensor;
                        
                        DecodedPacket_T * result = PROTOCOLS_MaybeDecodePacket(&LocalProcessingPulses);
                        
                        if (result != NULL)
                        {
                            if (result->Generic.type == DECODED_PACKET_TYPE_TAG_RECEIVED)
                            {
                                KEvent_T tag_received_event = {.ID = KEVENT_TAG_RECEIVED, .Data = result};
                                Post_KEvent(&tag_received_event);
                            }
                            else if (result->Generic.type == DECODED_PACKET_TYPE_COMMAND_RECEIVED)
                            {
                                KEvent_T command_received_event = {.ID = KEVENT_COMMAND_RECEIVED, .Data = result};
                                Post_KEvent(&command_received_event);
                            }
                        }
                        else
                        {
                            KEvent_T near_miss_event = {.ID = KEVENT_NEAR_MISS, .Data = NULL};
                            Post_KEvent(&near_miss_event);
                        }
                    }
                    break;
                    
                case TAG_SENSOR_PROCESS_REMOTE_BUFFER:
                    {                        
                        for (uint8_t i = 0; i < NumberOfRemoteIncomingPulses; i++)
                        {
                            RemoteProcessingPulseDurations[i] = RemoteIncomingPulseDurations[i];
                        }
                        NumberOfRemoteProcessingPulses = NumberOfRemoteIncomingPulses;
                        NumberOfRemoteIncomingPulses = 0;
                        EnableAllRemoteEdgeISRs();
                        
#ifdef DEBUG_TAG_SENSORS         
                        COMM_Console_Print_String("\n");
                        
                        COMM_Console_Print_String("Tag Rx'd REMOTE\n");
                        vTaskDelay(pdMS_TO_TICKS(10));
                    
                        for (uint_fast16_t i = 0; i < NumberOfRemoteProcessingPulses; i++)
                        {
                            // Even pulses are marks; odd pulses are spaces.
                            if ((i % 2) == 0)
                            {
                                COMM_Console_Print_String("{.symbol = MARK,  .time = ");
                                sprintf(buffer, "%lu},  // %d\n", RemoteProcessingPulseDurations[i], i);
                                COMM_Console_Print_String(buffer);
                                vTaskDelay(pdMS_TO_TICKS(10));
                            }
                            // A falling edge is the end of space.
                            else
                            {
                                COMM_Console_Print_String("{.symbol = SPACE, .time = ");
                                sprintf(buffer, "%lu},  // %d\n", RemoteProcessingPulseDurations[i], i);
                                COMM_Console_Print_String(buffer);
                                vTaskDelay(pdMS_TO_TICKS(10));
                            }
                        }
#endif // DEBUG_TAG_SENSORS
                        RemoteProcessingPulses.count = NumberOfRemoteProcessingPulses;
                        for (uint_fast16_t i = 0; (i < NumberOfRemoteProcessingPulses) && (i < MAX_RX_PULSES); i++)
                        {
                            if ((i % 2) == 0)
                            {
                                RemoteProcessingPulses.bitstream[i].symbol = MARK;
                            }
                            else
                            {
                                 RemoteProcessingPulses.bitstream[i].symbol = SPACE;
                            }
                            RemoteProcessingPulses.bitstream[i].duration = RemoteProcessingPulseDurations[i];
                        }
                        RemoteProcessingPulses.bitstream[NumberOfRemoteProcessingPulses].duration = LAST_PULSE;
                        RemoteProcessingPulses.receiver = TAG_SENSOR_REMOTE;
                        
                        DecodedPacket_T * result = PROTOCOLS_MaybeDecodePacket(&RemoteProcessingPulses);
                        
                        if (result != NULL)
                        {
                            if (result->Generic.type == DECODED_PACKET_TYPE_TAG_RECEIVED)
                            {
                                KEvent_T tag_received_event = {.ID = KEVENT_TAG_RECEIVED, .Data = result};
                                Post_KEvent(&tag_received_event);
                            }
                            else if (result->Generic.type == DECODED_PACKET_TYPE_COMMAND_RECEIVED)
                            {
                                KEvent_T command_received_event = {.ID = KEVENT_COMMAND_RECEIVED, .Data = result};
                                Post_KEvent(&command_received_event);
                            }
                        }
                        else
                        {
                            KEvent_T near_miss_event = {.ID = KEVENT_NEAR_MISS, .Data = NULL};
                            Post_KEvent(&near_miss_event);
                        }
                    }
                    break;
                    
                default:
                    break;
            }
        }
        
    vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

// A rising edge means the IR carrier frequency is no longer detected.
void On_Forward_Tag_Sensor_Rising_Edge()
{
    uint32_t counter = Local_Tag_Sensor_Bit_Stream_Timer_GetCounter();

    if (LocalActiveSensor == TAG_SENSOR_FORWARD)
    {
        if (LocalExpectedEdgeDirection == RISING_EDGE)
        {
            Local_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
            NVIC_ClearPendingIRQ(Forward_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
            
            AppendLocalPulse(counter);
            LocalExpectedEdgeDirection = FALLING_EDGE;
        }
    }
}

// A falling edge means the IR carrier frequency has been detected.
void On_Forward_Tag_Sensor_Falling_Edge()
{
    uint32_t counter = Local_Tag_Sensor_Bit_Stream_Timer_GetCounter();
    
    if ((LocalActiveSensor == TAG_SENSOR_FORWARD) || (LocalActiveSensor == TAG_SENSOR_NONE))
    {
        if (LocalExpectedEdgeDirection == FALLING_EDGE)
        {
            Local_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
            NVIC_ClearPendingIRQ(Forward_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
            
            if (LocalPulseIndex == 0)
            {
                Local_Tag_Sensor_Bit_Stream_Timer_Start();
                LocalActiveSensor = TAG_SENSOR_FORWARD;
            }
            else
            {
                AppendLocalPulse(counter);
            }
            LocalExpectedEdgeDirection = RISING_EDGE;
        }
    }
}

// A rising edge means the IR carrier frequency is no longer detected.
void On_Left_Tag_Sensor_Rising_Edge()
{
    uint32_t counter = Local_Tag_Sensor_Bit_Stream_Timer_GetCounter();
    
    if (LocalActiveSensor == TAG_SENSOR_LEFT)
    {
        if (LocalExpectedEdgeDirection == RISING_EDGE)
        {
            Local_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
            NVIC_ClearPendingIRQ(Left_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
            
            AppendLocalPulse(counter);
            LocalExpectedEdgeDirection = FALLING_EDGE;
        }
    }
}

// A falling edge means the IR carrier frequency has been detected.
void On_Left_Tag_Sensor_Falling_Edge()
{
    uint32_t counter = Local_Tag_Sensor_Bit_Stream_Timer_GetCounter();
    
    if ((LocalActiveSensor == TAG_SENSOR_LEFT) || (LocalActiveSensor == TAG_SENSOR_NONE))
    {
        if (LocalExpectedEdgeDirection == FALLING_EDGE)
        {
            Local_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
            NVIC_ClearPendingIRQ(Left_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
            
            if (LocalPulseIndex == 0)
            {
                Local_Tag_Sensor_Bit_Stream_Timer_Start();
                LocalActiveSensor = TAG_SENSOR_LEFT;
            }
            else
            {
                AppendLocalPulse(counter);
            }
            LocalExpectedEdgeDirection = RISING_EDGE;
        }
    }
}

// A rising edge means the IR carrier frequency is no longer detected.
void On_Right_Tag_Sensor_Rising_Edge()
{
    uint32_t counter = Local_Tag_Sensor_Bit_Stream_Timer_GetCounter();
    
    if (LocalActiveSensor == TAG_SENSOR_RIGHT)
    {
        if (LocalExpectedEdgeDirection == RISING_EDGE)
        {
            Local_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
            NVIC_ClearPendingIRQ(Right_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
            
            AppendLocalPulse(counter);
            LocalExpectedEdgeDirection = FALLING_EDGE;
        }
    }
}

// A falling edge means the IR carrier frequency has been detected.
void On_Right_Tag_Sensor_Falling_Edge()
{
    uint32_t counter = Local_Tag_Sensor_Bit_Stream_Timer_GetCounter();
    
    if ((LocalActiveSensor == TAG_SENSOR_RIGHT) || (LocalActiveSensor == TAG_SENSOR_NONE))
    {
        if (LocalExpectedEdgeDirection == FALLING_EDGE)
        {
            Local_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
            NVIC_ClearPendingIRQ(Left_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
            
            if (LocalPulseIndex == 0)
            {
                Local_Tag_Sensor_Bit_Stream_Timer_Start();
                LocalActiveSensor = TAG_SENSOR_RIGHT;
            }
            else
            {
                AppendLocalPulse(counter);
            }
            LocalExpectedEdgeDirection = RISING_EDGE;
        }
    }
}

// A rising edge means the IR carrier frequency is no longer detected.
void On_Remote_Tag_Sensor_Rising_Edge()
{
    uint32_t counter = Remote_Tag_Sensor_Bit_Stream_Timer_GetCounter();

    if (RemoteExpectedEdgeDirection == RISING_EDGE)
    {
        Remote_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
        NVIC_ClearPendingIRQ(Remote_Tag_Sensor_Rising_Edge_ISR_cfg.intrSrc);
        
        AppendRemotePulse(counter);
        RemoteExpectedEdgeDirection = FALLING_EDGE;
    }
}

// A falling edge means the IR carrier frequency has been detected.
void On_Remote_Tag_Sensor_Falling_Edge()
{
    uint32_t counter = Remote_Tag_Sensor_Bit_Stream_Timer_GetCounter();
    
    if (RemoteExpectedEdgeDirection == FALLING_EDGE)
    {
        Remote_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
        NVIC_ClearPendingIRQ(Remote_Tag_Sensor_Falling_Edge_ISR_cfg.intrSrc);
        
        if (RemotePulseIndex == 0)
        {
            Remote_Tag_Sensor_Bit_Stream_Timer_Start();
        }
        else
        {
            AppendRemotePulse(counter);
        }
        RemoteExpectedEdgeDirection = RISING_EDGE;
    }
}

void On_Local_Tag_Sensor_Bit_Stream_Timer()
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    
    //	Read and clear the interrupt status.
    uint32_t status = Local_Tag_Sensor_Bit_Stream_Timer_GetInterruptStatus();
    Local_Tag_Sensor_Bit_Stream_Timer_ClearInterrupt(CY_TCPWM_INT_ON_TC);
    
    if (status & CY_TCPWM_INT_ON_TC)
    {
        // The timer expired.
        Local_Tag_Sensor_Bit_Stream_Timer_TriggerStop();
        Local_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
        NumberOfLocalIncomingPulses = LocalPulseIndex;
        LocalPulseIndex = 0;
        DisableAllLocalEdgeISRs();
        LocalExpectedEdgeDirection = FALLING_EDGE;
        const TagSensorsAction_T action = TAG_SENSOR_PROCESS_LOCAL_BUFFER;
        xQueueSendFromISR(xQueueTagSensors, &action, &xHigherPriorityTaskWoken);
    }
    
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void On_Remote_Tag_Sensor_Bit_Stream_Timer()
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    
    //	Read and clear the interrupt status.
    uint32_t status = Remote_Tag_Sensor_Bit_Stream_Timer_GetInterruptStatus();
    Remote_Tag_Sensor_Bit_Stream_Timer_ClearInterrupt(CY_TCPWM_INT_ON_TC);
   
    if (status & CY_TCPWM_INT_ON_TC)
    {
        // The timer expired.
        Remote_Tag_Sensor_Bit_Stream_Timer_TriggerStop();
        Remote_Tag_Sensor_Bit_Stream_Timer_SetCounter(0);
        NumberOfRemoteIncomingPulses = RemotePulseIndex;
        RemotePulseIndex = 0;
        DisableAllRemoteEdgeISRs();
        RemoteExpectedEdgeDirection = FALLING_EDGE;
        const TagSensorsAction_T action = TAG_SENSOR_PROCESS_REMOTE_BUFFER;
        xQueueSendFromISR(xQueueTagSensors, &action, &xHigherPriorityTaskWoken);
    }
    
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

