Browse Source

add remote for stm32_netradio

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@363 bbd45198-f89e-11dd-88c7-29a3b14d5316
wuyangyong 15 years ago
parent
commit
7669398ee7
1 changed files with 474 additions and 0 deletions
  1. 474 0
      bsp/stm32_radio/remote.c

+ 474 - 0
bsp/stm32_radio/remote.c

@@ -0,0 +1,474 @@
+/*
++-----------------------
+|
+| 红外自学习遥控
+|
+| Chang Logs:
+| Date           Author       Notes
+| 2010-01-02     aozima       The bate version.
++----------------------------------------------------
+*/
+
+#include <rtthread.h>
+#include <dfs_posix.h>
+#include <stm32f10x.h>
+
+unsigned int rem_mode = 0;//红外模式 0:没启动,1:自学习,2:正常解码
+
+static unsigned int first_tick = 0;
+static unsigned int rx_count = 0;
+static unsigned short rm_code[100];
+
+struct rem_codes_typedef
+{
+    unsigned int len;
+    unsigned short rem_code[100];
+};
+struct rem_codes_typedef * p_rem_code_src = RT_NULL;
+
+static const char  str1[]="KEY_UP";     /* 上 */
+static const char  str2[]="KEY_DOWN";   /* 下 */
+static const char  str3[]="KEY_LEFT";   /* 左 */
+static const char  str4[]="KEY_RIGHT";  /* 右 */
+static const char  str5[]="KEY_ENTER";  /* 确认 */
+static const char  str6[]="KEY_RETURN"; /* 返回 */
+static const char * desc_key[6]= {str1,str2,str3,str4,str5,str6};
+#define wucha         15
+
+
+/* tim5 configure */
+static void TIM5_Configuration(void)
+{
+    /* 时钟及分频设置 */
+    {
+        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
+        /* Time Base configuration */
+        /* 72M/720 = 0.01ms */
+        TIM_TimeBaseStructure.TIM_Prescaler = 720-1;
+        //计数模式:向上计数
+        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
+        TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
+        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
+        //重新计数的起始值
+        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
+
+        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
+    }
+
+    /* 捕获设置 */
+    {
+        TIM_ICInitTypeDef  TIM_ICInitStructure;
+
+        TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;/* 每次检测到捕获输入就触发一次捕获 */
+        TIM_ICInitStructure.TIM_ICFilter    = 8;/* 滤波 */
+
+        TIM_ICInitStructure.TIM_Channel     = TIM_Channel_3;//选择通道3
+        TIM_ICInitStructure.TIM_ICPolarity  = TIM_ICPolarity_Falling;//下降沿
+        TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//通道方向选择
+        TIM_ICInit(TIM5, &TIM_ICInitStructure);
+
+        TIM_ICInitStructure.TIM_Channel     = TIM_Channel_4;//选择通道3
+        TIM_ICInitStructure.TIM_ICPolarity  = TIM_ICPolarity_Rising;//上升沿
+        TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;//通道方向选择
+        TIM_ICInit(TIM5, &TIM_ICInitStructure);
+    }
+
+    /* 输入触发源选择:外部输入触发 */
+    TIM_SelectInputTrigger(TIM5, TIM_TS_ETRF);//TIM_TS_ETRF 外部触发
+    /* 从模式-复位模式 */
+    /* TIM_SlaveMode_Reset 4:选中的触发输入(TRGI)的上升沿重新初始化计数器,并且产生一个更新寄存器的信号 */
+    TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset);
+    TIM_SelectMasterSlaveMode(TIM5, TIM_MasterSlaveMode_Enable);
+
+    /* TIM enable counter */
+    TIM_Cmd(TIM5, ENABLE);
+
+    /* Enable the CC3 and CC4 Interrupt Request */
+    TIM_ITConfig(TIM5, TIM_IT_CC3, ENABLE);
+    TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
+}
+
+static void NVIC_Configuration(void)
+{
+    NVIC_InitTypeDef NVIC_InitStructure;
+
+    /* Enable the TIM5 global Interrupt */
+    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+}
+
+static void RCC_Configuration(void)
+{
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
+
+    /* TIM5 clock enable */
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
+
+    /* clock enable */
+    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA ,ENABLE);
+}
+
+static void GPIO_Configuration(void)
+{
+    GPIO_InitTypeDef GPIO_InitStructure;
+
+    /* TIM5 channel 3 pin (PA.02) configuration */
+    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
+
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+}
+
+void rem_start(void)
+{
+    RCC_Configuration();
+    GPIO_Configuration();
+
+    /* configure TIM5 for remote and encoder */
+    NVIC_Configuration();
+    TIM5_Configuration();
+
+    p_rem_code_src = rt_malloc( 1500 );
+
+    /* 解读红外信息 */
+    {
+        int fd,size;
+        char buf[6];//文件读取临时缓存
+        unsigned int i;
+        unsigned short tmp;
+        unsigned int read_index = 0;
+        unsigned int EOF_flag = 1;
+
+        rt_kprintf("\r\n解读红外信息");
+        fd = open("/resource/remote.txt",O_RDONLY,0);
+        if( fd>0 )
+        {
+            rt_kprintf("\r/resource/remote.txt打开成功");
+            while( EOF_flag )
+            {
+                //读取长度
+                size = read(fd,buf,6);
+                if( (size == 6) && (buf[4]=='\r') && buf[5]=='\n' )
+                {
+                    //转换得到样本数据长度
+                    tmp =   (buf[0]-'0')*1000
+                            + (buf[1]-'0')*100
+                            + (buf[2]-'0')*10
+                            + (buf[3]-'0');
+                    if( tmp<100 )
+                    {
+                        unsigned int code_len = tmp;
+                        p_rem_code_src[read_index].len = code_len;
+                        //如果样本长度符合
+                        for(i=0; i<code_len; i++)
+                        {
+                            size = read(fd,buf,6);
+                            if( (size == 6) && (buf[4]=='\r') && buf[5]=='\n' )
+                            {
+                                tmp =   (buf[0]-'0')*1000
+                                        + (buf[1]-'0')*100
+                                        + (buf[2]-'0')*10
+                                        + (buf[3]-'0');
+                                p_rem_code_src[read_index].rem_code[i] = tmp;
+                            }
+                        }
+                        read_index++;
+                    }
+                }
+                else
+                {
+                    EOF_flag = 0;
+                }
+            }//while( EOF_flag )
+            //设置工作模式为正常识别模式
+            rem_mode = 2;
+            rt_kprintf("\r红外遥控编码文件解读完成,已打开红外遥控功能\r\n");
+        }
+        else
+        {
+            rt_kprintf("\r红外遥控编码文件 /resource/remote.txt 打开失败! fd:%d\r\n无法开启红外遥控功能.\r\n请执行rem_study()进行自动学习\r\n",fd);
+        }
+        close(fd);
+    }/* 解读红外信息 */
+}
+
+#include <rtgui/event.h>
+void rem_encoder(struct rtgui_event_kbd * p)
+{
+    struct rtgui_event_kbd * p_kbd_event = p;
+    /* 红外遥控匹配 */
+    if( (rem_mode==2) && (rt_tick_get()>first_tick+10) && (rx_count > 0) )
+    {
+        /* 手动清零第一个捕获结果 */
+        rm_code[0] = 0;
+        rx_count = 0;
+#if 0
+        {
+            unsigned int iii;
+            for(iii=0; iii<100; iii++)
+            {
+                rt_kprintf("\r\n%d",rm_code[iii]);
+            }
+        }
+#endif
+
+#if 1
+        {
+            unsigned int tmp;
+            unsigned int fflag = 0;
+            unsigned int rem_cmp_n = 6;
+
+            //循环匹配所有KEY
+            while( rem_cmp_n )
+            {
+                unsigned int tmp2 = p_rem_code_src[ 6-rem_cmp_n ].len;
+                //rt_kprintf("\r\nrem_cmp_n:%d  tmp2:%d",rem_cmp_n,tmp2);
+                if( tmp2 )
+                {
+
+                    for(tmp=0; tmp<tmp2; tmp++)
+                    {
+                        if( !( (rm_code[tmp] < p_rem_code_src[6-rem_cmp_n].rem_code[tmp]+wucha) && (rm_code[tmp] > p_rem_code_src[6-rem_cmp_n].rem_code[tmp]-wucha)) )
+                        {
+                            fflag = 1;
+                            //rt_kprintf("\r\nerr %d: rm_code[%d] p_rem_code_src[%d].rem_code[%d]",tmp,rm_code[tmp],6-rem_cmp_n,p_rem_code_src[ 6-rem_cmp_n].rem_code[tmp]);
+                        }
+                    }
+                }
+                else
+                {
+                    fflag = 1;
+                    rt_kprintf("\r\n解码失败");
+                }
+
+                if(fflag==0)
+                {
+                    //成功
+                    rt_kprintf("\r\n识别到遥控按键 %s",desc_key[6-rem_cmp_n]);
+                    switch( rem_cmp_n )
+                    {
+                    case 6:
+                        p_kbd_event->key  = RTGUIK_UP;
+                        break;
+                    case 5:
+                        p_kbd_event->key  = RTGUIK_DOWN;
+                        break;
+                    case 4:
+                        p_kbd_event->key  = RTGUIK_LEFT;
+                        break;
+                    case 3:
+                        p_kbd_event->key  = RTGUIK_RIGHT;
+                        break;
+                    case 2:
+                        p_kbd_event->key  = RTGUIK_RETURN;
+                        break;
+                    case 1:
+                        p_kbd_event->key  = RTGUIK_HOME;
+                        break;
+                    default:
+                        break;
+                    }
+                    rem_cmp_n = 0;
+                }
+                else
+                {
+                    //不成功
+                    fflag = 0;
+                    rem_cmp_n --;
+                }
+
+            }
+        }
+#endif
+    }//红外遥控匹配
+}
+
+/* remote isr */
+void remote_isr(void)
+{
+    static unsigned int clr_flag = 1;
+    unsigned int tick_now  = rt_tick_get();
+
+    /* 红外遥控下降沿 */
+    if(TIM_GetITStatus(TIM5, TIM_IT_CC3) == SET)
+    {
+        switch( rem_mode )
+        {
+        case 0://未启动
+            break;
+        case 1://自学习
+            if( (rx_count==0) || (rx_count>90) || (tick_now>first_tick+10) )
+            {
+                //需要清0
+                rx_count = 0;
+                clr_flag = 1;
+            }
+            if( rx_count<100 )
+            {
+                rm_code[rx_count++] = TIM_GetCapture3(TIM5);
+            }
+            break;
+        case 2://正常解码
+            if( (rx_count>90) || tick_now>first_tick+10 )
+            {
+                rx_count = 0;
+                clr_flag = 1;
+            }
+            if(rx_count<100 )
+            {
+                rm_code[rx_count++] = TIM_GetCapture3(TIM5);
+            }
+            break;
+        default:
+            rem_mode = 0;//设置模式为未启动
+            break;
+        }
+        TIM_ClearITPendingBit(TIM5, TIM_IT_CC3);
+    }
+
+    /* 红外遥控上升沿 */
+    if(TIM_GetITStatus(TIM5, TIM_IT_CC4) == SET)
+    {
+        switch( rem_mode )
+        {
+        case 0://未启动
+            break;
+        case 1://自学习
+            if( rx_count<100 )
+            {
+                rm_code[rx_count++] = TIM_GetCapture4(TIM5);
+            }
+            break;
+        case 2://正常解码
+            if( rx_count<100 )
+            {
+                rm_code[rx_count++] = TIM_GetCapture4(TIM5);
+            }
+            break;
+        default:
+            rem_mode = 0;//设置模式为未启动
+            break;
+        }
+        TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);
+    }
+
+    //更新时间戳
+    first_tick = tick_now;
+    //检测是否需要重置计数器
+    if( clr_flag )
+    {
+        //重置计数器
+        TIM_SetCounter(TIM5,0);
+        clr_flag = 0;
+    }
+}
+
+#include <finsh.h>
+/* 启动红外学习程序 */
+int rem_study(void)
+{
+    unsigned int i;
+
+    int fd,size;
+    unsigned char tmp_buf[606];
+
+    rem_mode = 1;
+    rx_count = 0;
+    rt_kprintf("\r\n红外遥控自学习功能启动");
+    fd = open("/resource/remote.txt",O_WRONLY | O_TRUNC,0);
+    if( !(fd<0) )
+    {
+        rt_kprintf("\r\n红外遥控编码文件 /resource/remote.txt 创建成功");
+    }
+    else
+    {
+        rt_kprintf("\r红外遥控编码文件 /resource/remote.txt 创建失败.\r\n学习程序中止.");
+        return -1;
+    }
+
+    //学习6个键盘
+    for( i=0; i<6; i++)
+    {
+        unsigned int is_ok = 1;
+        rt_kprintf("\r\npress key %s",desc_key[i]);
+        while( is_ok==1 )
+        {
+            if( (rem_mode==1) && (rt_tick_get()>first_tick+10) && (rx_count > 0) )
+            {
+                unsigned int a,b;
+                unsigned char * p = tmp_buf;
+
+                rt_kprintf("\r\n%s",desc_key[i]);
+
+                b = rx_count;
+                p_rem_code_src[i].len = rx_count;
+
+                /* TIM disable counter */
+                TIM_Cmd(TIM5, DISABLE);
+                /* disable the CC3 and CC4 Interrupt Request */
+                TIM_ITConfig(TIM5, TIM_IT_CC3, DISABLE);
+                TIM_ITConfig(TIM5, TIM_IT_CC4, DISABLE);
+
+                p[0] = rx_count / 1000 +'0';
+                rx_count = rx_count % 1000;
+                p[1] = rx_count / 100  +'0';
+                rx_count = rx_count % 100;
+                p[2] = rx_count / 10   +'0';
+                rx_count = rx_count % 10;
+                p[3] = rx_count        +'0';
+                rx_count = 0;
+                p[4] = '\r';
+                p[5] = '\n';
+                p += 6;
+
+                rm_code[0] = 0;
+
+                for( a=0; a<b; a++)
+                {
+                    p_rem_code_src[i].rem_code[a] = rm_code[a];
+                    p[0] = rm_code[a] / 1000 +'0';
+                    rm_code[a] = rm_code[a] % 1000;
+                    p[1] = rm_code[a] / 100  +'0';
+                    rm_code[a] = rm_code[a] % 100;
+                    p[2] = rm_code[a] / 10   +'0';
+                    rm_code[a] = rm_code[a] % 10;
+                    p[3] = rm_code[a]        +'0';
+                    p[4] = '\r';
+                    p[5] = '\n';
+                    p += 6;
+                }
+                size = write(fd,(char*)tmp_buf,(b+1)*6 );
+                if( size==((b+1)*6) )
+                {
+                    rt_kprintf("文件写入成功");
+                    is_ok++;
+                    rt_thread_delay( 2 );
+
+                    /* 重新打开 TIM5 进行捕获 */
+                    TIM_ClearITPendingBit(TIM5, TIM_IT_CC3);
+                    TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);
+                    /* TIM ENABLE counter */
+                    TIM_Cmd(TIM5, ENABLE);
+                    /* ENABLE the CC3 and CC4 Interrupt Request */
+                    TIM_ITConfig(TIM5, TIM_IT_CC3, ENABLE);
+                    TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
+                }
+                else
+                {
+                    rt_kprintf("文件写入失败\r\n红外学习程序退出");
+                    return -1;
+                }
+            }
+            rt_thread_delay(1);
+        }//while( is_ok==1 )
+    }//for( i=0; i<6; i++)
+    close(fd);
+    rt_kprintf("\r\n学习完成,现在进入正常识别模式\r\n");
+    rem_mode = 2;
+    return 0;
+}
+FINSH_FUNCTION_EXPORT(rem_study, rem_study);