加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
wiegand.c 5.33 KB
一键复制 编辑 原始数据 按行查看 历史
callful 提交于 2019-01-03 15:39 . the wiegand driver source
#include <drivers/pin.h>
#include <rtthread.h>
#include <rtconfig.h>
#include <rtdevice.h>
#include <wiegand.h>
#include <pin.h>
#if defined(RT_USING_ULOG)
#define LOG_TAG LOG_TAG_WIEGAND
#define LOG_LVL LOG_LVL_ERROR
#include <ulog.h>
#else
#define LOG_I()
#define LOG_D()
#define LOG_W()
#define LOG_E rt_kprintf
#endif
rt_err_t wiegand_data_check(const rt_uint8_t *data,rt_uint8_t databits,
rt_uint8_t head,rt_uint8_t tail)
{
/* head对应偶数个1,tail对应奇数个1 */
rt_uint8_t i=0,j=0,onebits=0;
rt_uint8_t tmp;
rt_uint8_t half;
RT_ASSERT(RT_NULL!=data);
half=(databits-2)/2;
/* 前半部分的数据bit */
for(i=0;i<half/8;i++)
{
tmp=data[i];
for(j=0;j<8;j++)
{
if(tmp&0x80)
{
onebits++;
tmp <<= 1;
}
}
}
/* 类似26-bit的数据bit分成两半会剩余不足8位的 */
if(half%8)
{
tmp=data[i];
for(j=0;j<(half%8);j++)
{
if(tmp&0x80)
{
onebits++;
tmp <<= 1;
}
}
}
if((onebits%2)==head)
{
return -RT_EIO;
}
/* 后半部分的数据bit */
onebits=0;
if(half%8)
{
tmp=data[i]<<((half%8));
for(j=(half%8);j<8;j++)
{
if(tmp&0x80)
{
onebits++;
tmp <<= 1;
}
}
}
for(i=0;i<half/8;i++)
{
tmp=data[i+half/8];
for(j=0;j<8;j++)
{
if(tmp&0x80)
{
onebits++;
tmp <<= 1;
}
}
}
if((onebits%2)!=tail)
{
return -RT_EIO;
}
return RT_EOK;
}
void wiegand_irq_isr(wiegand_package *wiegand)
{
rt_uint16_t bits,offset;
rt_uint8_t data;
RT_ASSERT(RT_NULL!=wiegand);
if(RT_NULL==wiegand->dev.rx_indicate)
{
/* 没有设置数据接收函数则直接退出 */
return;
}
data=rt_pin_read(wiegand->data0pin);
LOG_D("data0=%d",data);
if(wiegand_idle==wiegand->stat)
{
wiegand->head=data;
wiegand->stat=wiegand_receiving;
rt_memset(wiegand->data,0,wiegand->databits);
wiegand->index=1;
rt_timer_start(wiegand->timer);
return;
}
else if(wiegand->index<wiegand->databits)
{
bits=(wiegand->databits-1)/8;
offset=(wiegand->databits-1)%8;
wiegand->data[bits] <<= 1;
wiegand->data[bits] |= data;
wiegand->index++;
}
if(wiegand->index>=wiegand->databits)
{
rt_timer_stop(wiegand->timer);
wiegand->tail=data;
wiegand_data_check(wiegand->data,wiegand->databits,
wiegand->head,wiegand->tail);
wiegand->stat=wiegand_idle;
wiegand->index=0;
wiegand->dev.rx_indicate(wiegand->data,wiegand->databits/8);
}
}
void wiegand_timeout(void *para)
{
wiegand_package *wiegand=(wiegand_package*)para;
rt_err_t ret;
RT_ASSERT(RT_NULL!=wiegand);
if(wiegand_idle==wiegand->stat)
{
/* */
LOG_D("wiegand(%s) timerout in idle stat",wiegand->dev->parent.name);
return;
}
if(RT_NULL==wiegand->dev.rx_indicate)
{
/* 没有设置数据接收函数则直接退出 */
goto wg_exit;
}
if(26>wiegand->index)
{
goto wg_exit;
}
if((2==(wiegand->index%8)))
{
ret=wiegand_data_check(wiegand->data,wiegand->databits,
wiegand->head,wiegand->tail);
/* 在接收到全部数据bit之前发生时间中断则也发送数据帧 */
if(RT_EOK==ret)
{
wiegand->dev.rx_indicate(wiegand->data,wiegand->databits/8);
goto wg_exit;
}
LOG_D("wiegand(%s) data check error",wiegand->dev->parent.name);
}
wg_exit:
wiegand->stat=wiegand_idle;
wiegand->index=0;
return;
}
#define WIEGAND_BIT_DELAY(bits) (1+5*(bits)*RT_TICK_PER_SECOND/2000)
rt_err_t wiegand_device_init(char *devname,rt_uint16_t bits,rt_base_t data0pin)
{
wiegand_package *wiegand=RT_NULL;
rt_device_t dev=RT_NULL;
rt_uint32_t delay;
rt_err_t ret;
RT_ASSERT(RT_NULL!=devname);
if(bits<26 || bits>98)
{
LOG_E("error wiegand data bits");
return -RT_EINVAL;
}
/* 先初始化device的数据结构 */
dev=rt_malloc(sizeof(struct rt_device));
if(RT_NULL==dev)
{
LOG_E("malloc for device wiegand fail");
return -RT_ENOMEM;
}
rt_memset(dev,0,sizeof(struct rt_device));
#ifdef RT_USING_DEVICE_OPS
dev->ops = RT_NULL;
#else
dev->init = RT_NULL;
dev->open = RT_NULL;
dev->close = RT_NULL;
dev->read = RT_NULL;
dev->write = RT_NULL;
dev->control = RT_NULL;
#endif
dev->type = RT_Device_Class_Miscellaneous;
dev->rx_indicate = RT_NULL;
dev->tx_complete = RT_NULL;
dev->user_data = RT_NULL;
/* */
wiegand=rt_malloc(sizeof(wiegand_package));
if(RT_NULL==wiegand)
{
LOG_E("malloc wiegand fail");
return -RT_ENOMEM;
}
rt_memset(wiegand,0,sizeof(wiegand_package));
delay=WIEGAND_BIT_DELAY(bits);
wiegand->timer=rt_timer_create(devname,wiegand_timeout,
wiegand,delay,RT_TIMER_FLAG_ONE_SHOT);
if(RT_NULL!=wiegand->timer)
{
LOG_E("malloc timer fail");
return -RT_ENOMEM;
}
wiegand->data=rt_malloc(bits/8);
if(RT_NULL!=wiegand->data)
{
LOG_E("malloc for data fail");
return -RT_ENOMEM;
}
rt_memset(wiegand->data,0,bits/8);
wiegand->stat=wiegand_idle;
wiegand->data0pin=data0pin;
wiegand->head=0;
wiegand->tail=0;
wiegand->index=0;
wiegand->databits=bits;
/* 由外部调用函数直接设定数据引脚DATA0的输入方式 */
//rt_pin_mode(data0pin,PIN_MODE_INPUT);
dev->user_data=wiegand;
wiegand->dev=dev;
ret=rt_device_register(dev,devname,RT_DEVICE_FLAG_RDONLY|RT_DEVICE_FLAG_INT_RX);
return ret;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化