/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=895143]@version[/url] V1.00
* [url=home.php?mod=space&uid=247401]@brief[/url] Demonstrate how to use APIs of CIR to convert the output signal of an Infrared Receiver
*
* SPDX-License-Identifier: Apache-2.0
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2020 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "NuMicro.h"
#include "Queue.h"
uint32_t Queue[MAX_QUEUE];
/**
* Receive error int:
* The CIR_STATUS_RERRF_Msk will be raised if following reasons.
* 1. The coming pulse width does not meet the upper and lower bound of all patterns.
* 2. The first pulse width of coming pattern is not header pattern if pattern type is CIR_POSITIVE_EDGE or CIR_NEGATIVE_EDGE.
*
* Due to the repeat code appears alone and is not header patteren. It will cause the CIR_STATUS_RERRF_Msk flag to be raised.
* Programmer needs to judge if the error event caused by repeat code.
*/
void CIR_IRQHandler(void)
{
uint32_t status = CIR_GetIntFlag(CIR0) & CIR_GetEnabledIntMask(CIR0);
if(status & CIR_STATUS_RERRF_Msk)
{
uint32_t u32Hb, u32Lb;
/*
* Due to the special pattern (repeat code) out of header pattern and end pattern.
* It will generate a error event. As raised a error event,
* programmer needs to judge if the event caused by special pattern.
*/
CIR_GetPatternBoundary(CIR0, CIR_SPECIAL_PAT, &u32Hb, &u32Lb);
if((CIR_GetLatchedTimerValue(CIR0)< u32Hb) && (CIR_GetLatchedTimerValue(CIR0) > u32Lb))
Push(Queue, 0xFFFFFFFF); /* proprietary define repeat code to 0xFFFFFFFF */
CIR_ClearIntFlag(CIR0, CIR_STATUS_RERRF_Msk);
}
else if(status & CIR_STATUS_EPMF_Msk)
{
uint32_t u32Data0, u32Data1;
/* End Patter match int */
CIR_ClearIntFlag(CIR0, CIR_STATUS_EPMF_Msk);
CIR_GetData(CIR0, &u32Data0, &u32Data1);
Push(Queue, u32Data0);
/* Clear data fields and bit count for next receiving */
CIR_ClearDataFieldBitCount(CIR0);
}
}
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
/* Enable HXT clock */
CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);
/* Wait for HXT clock ready */
CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
/* Set core clock as 96MHz from PLL */
CLK_SetCoreClock(FREQ_96MHZ);
/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
/* Enable UART module clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Enable UART module clock */
CLK_EnableModuleClock(CIR0_MODULE);
/* Select UART module clock source as HXT and UART module clock divider as 1 */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HXT, CLK_CLKDIV0_UART0(1));
/* Select CIR module clock source as LIRC */
CLK_SetModuleClock(CIR0_MODULE, CLK_CLKSEL2_CIR0SEL_LIRC, (uint32_t)NULL);
/* Update System Core Clock */
SystemCoreClockUpdate();
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk);
SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
/* Set GPC14 multi-function pins for CIR */
SYS->GPC_MFPH = (SYS->GPC_MFPH & ~SYS_GPC_MFPH_PC14MFP_Msk) | SYS_GPC_MFPH_PC14MFP_CIR0_RXD;
CLK->PCLKDIV &= ~CLK_PCLKDIV_APB1DIV_Msk;
/* Lock protected registers */
SYS_LockReg();
}
void UART0_Init(void)
{
/* Configure UART0 and set UART0 baud rate */
UART_Open(UART0, 115200);
}
/**
* Use AI-26C generic remote controller by setting TV system to Panasonic:
* Pressed "Setup" up to 3 seconds, then pressed "0", "0", "1" to assign the remote controller to operate on Panasonic mode
*
* CIR Clock Source From LIRC. T = 30.5us
*
* unit: us
* Header 9100+4450
* Spec 9065+2282
* D0 576+557
* D1 576+1690
* Stop 542+17000
*/
void CIR_Init(void)
{
CIR_SetClockPrescaler(CIR0, CIR_PRESCALER_1);
CIR_SetPatternBoundary(CIR0, CIR_HEADER_PAT, ((9100+4450)/26)+15, ((9100+4450)/26)-15);
CIR_SetPatternBoundary(CIR0, CIR_DATA1_PAT, ((576+1690)/26)+15, ((576+1690)/26)-15);
CIR_SetPatternBoundary(CIR0, CIR_DATA0_PAT, ((576+557)/26)+15, ((576+557)/26)-15);
CIR_SetPatternBoundary(CIR0, CIR_SPECIAL_PAT, ((9065+2282)/26)+15, ((9065+2282)/26)-15);
CIR_SetPatternBoundary(CIR0, CIR_END_PAT, 0, (542+17000)/26);
CIR_EnableDataCmpWakeup(CIR0, 0x40, 7); /* Enable data compare if received data is 0x38 (8 bits) */
CIR_EnableRecvBitCountMatch(CIR0, 32); /* Enable bit count compare if bit count compare match with 32 bit */
CIR_EnableInt(CIR0, CIR_INTCTL_PERRIEN_Msk|CIR_INTCTL_EPMIEN_Msk);
CIR_SetInputType(CIR0, CIR_POSITIVE_EDGE, CIR_INVERSE);
NVIC_EnableIRQ(CIR_IRQn);
CIR_Open(CIR0);
}
typedef struct
{
char* KeyString;
uint32_t IrCode0;
uint32_t u32Len;
} IR_INFO;
const IR_INFO Array[] =
{
"POWER", 0xED12BF40, 32,
"IMAGE", 0xEB14BF40, 32,
"0", 0xFF00BF40, 32,
"1", 0xFE01BF40, 32,
"2", 0xFD02BF40, 32,
"3", 0xFC03BF40, 32,
"4", 0xFB04BF40, 32,
"5", 0xFA05BF40, 32,
"6", 0xF906BF40, 32,
"7", 0xF807BF40, 32,
"8", 0xF708BF40, 32,
"9", 0xF609BF40, 32,
"TV", 0xEC13BF40, 32,
"DISPLAY", 0xE916BF40, 32,
"CATV", 0xAE51BF40, 32,
"SLEEP", 0xE11EBF40, 32,
"RETURN", 0xF30CBF40, 32,
"INPUT", 0xF40BBF40, 32,
"SILENT", 0xEF10BF40, 32,
"VOL_UP", 0xE51ABF40, 32,
"VOL_DN", 0xE11EBF40, 32,
"VOL_SILENT", 0xE718BF40, 32,
"CHAN_UP", 0xE41BBF40, 32,
"CHAN_DN", 0xE01FBF40, 32,
"REPEAT", 0xFFFFFFFF, 32,
};
void CIR_Parsing(void)
{
uint32_t u32IrCode;
uint32_t i;
do
{
if(isEmpty() != 1)
{
u32IrCode = Pop(Queue);
if(u32IrCode != 0xFFFFFFFF)
{
for(i=0; i<sizeof(Array)/ sizeof(Array[0]); i=i+1)
{
if(u32IrCode == Array[i].IrCode0)
printf("%s Pressed\n", Array[i].KeyString);
}
}
else
{
printf("REPEAT\n");
}
}
}
while(1);
}
int main()
{
SYS_Init(); /* Init System, IP clock and multi-function I/O */
UART0_Init(); /* Initialize UART0 */
printf("\n");
printf("+------------------------------------------+\n");
printf("| M471 CIR Sample Code |\n");
printf("+------------------------------------------+\n");
CIR_Init(); /* Base on the remote control to set the timing */
CIR_Parsing();
printf("\nCIR Sample Code Completed.\n");
while (1);
}
/*** (C) COPYRIGHT 2020 Nuvoton Technology Corp. ***/