/**
  *****************************************************************************************************
  * @file    kpm32xx_it.c
  * @author  Kiwi Software Team
  * @brief   This file provides routines for all CPU exceptions handler and
  *          external peripherals interrupt service.
  *
  * Copyright (c) 2024, Kiwi Instruments Co,. Ltd.
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *
  *   3. Neither the name of the copyright holder nor the names of its contributors
  *      may be used to endorse or promote products derived from this software without
  *      specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************************************
  */

#include "main.h"


/**
  * @brief This function handles Non-Maskable interrupt.
  */
void NMI_Handler(void)
{

}


/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
	while (1)
	{

	}
}


/**
  * @brief This function handles System service call via SWI instruction.
  */
void SVC_Handler(void)
{

}


/**
  * @brief This function handles Pendable request for system service.
  */
void PendSV_Handler(void)
{

}


/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
    DDL_IncTick();
}


#if defined(DDL_SPI_MODULE_ENABLED)
extern volatile uint32_t remainSendCnt;
extern volatile uint32_t remainReceiveCnt;
extern volatile uint8_t spiTxCmplt;
extern volatile uint8_t spiRxCmplt;
extern uint8_t *pTxBuffPtr;
extern uint8_t *pRxBuffPtr;


void SPI_IRQHandler(void)
{
	uint32_t tx_cnt = 0;
	uint32_t rx_cnt  = __DDL_SPI_GET_FIFORXLVL(SPI);
	uint32_t rx_thrshld = 0;

	if ((SPI->INTR & SPI_INTR_TXFFTHRWRN) && (SPI->INTST & SPI_INTST_TXFFTHRWRN))
	{
		tx_cnt = MIN(remainSendCnt, __SPI_FIFOTX_THRESHOLD__);
		__DDL_SPI_CLEAR_RXFIFO(SPI);
		while (tx_cnt)
		{
			SPI->DR = (uint8_t)(*pTxBuffPtr);
			pTxBuffPtr++;
			remainSendCnt--;
			tx_cnt--;
		}
		if (remainSendCnt == 0)
		{
			__DDL_SPI_DISABLE_IT(SPI, SPI_INTR_TXFFTHRWRN);
		}
		__DDL_SPI_CLEAR_INTRFLAG(SPI, SPI_INTST_TXFFTHRWRN);
	}

	if ((SPI->INTR & SPI_INTR_SNDCMPLT) && (SPI->INTST & SPI_INTST_SNDCMPLT))
	{
		/* Clear all interrupt flags */
		WRITE_REG(SPI->INTST, 0xFFFFFFF);
		__DDL_SPI_DISABLE_IT(SPI, SPI_INTR_SNDCMPLT);
		spiTxCmplt = 1;
	}

	if ((SPI->INTR & SPI_INTR_RXFFTHRWRN) && (SPI->INTST & SPI_INTST_RXFFTHRWRN))
	{
		/* read out all data resided in RX FIFO */
		while (rx_cnt)
		{
			*pRxBuffPtr = (uint8_t)(SPI->DR);
			pRxBuffPtr++;
			rx_cnt--;
			remainReceiveCnt--;
		}
		__DDL_SPI_CLEAR_INTRFLAG(SPI, SPI_INTST_RXFFTHRWRN);

		if (remainReceiveCnt == 0)
		{
			/* Clear all interrupt flags */
			WRITE_REG(SPI->INTST, 0xFFFFFFF);
			__DDL_SPI_DISABLE_IT(SPI, SPI_INTR_RXFFTHRWRN);
			spiRxCmplt = 1;
		}
		else
		{
			/* rejust the RX Threshold, in case that the count of remained data decreases blow the previous threshold */
			rx_thrshld = MIN(remainReceiveCnt, __SPI_FIFORX_THRESHOLD__);
			__DDL_SPI_RXTHRD_CONFIG(SPI, rx_thrshld);
			while (rx_thrshld)
			{
				SPI->DR = (uint8_t)__SPI_08BIT_DUMMY_DATA__;
				rx_thrshld--;
			}
		}
	}
}
#endif /*DDL_SPI_MODULE_ENABLED*/

