/**
******************************************************************************
* @file scanmode.c
* @author TMC Scan Team
* @version V1.0.0
* @date 09/06/2019
* @brief This file provides the different modes of scanning.
******************************************************************************
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, TMC SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
© COPYRIGHT 2016 TMC
******************************************************************************
**/
#include "global.h"
uint8_t gAutoModeOverTimeFlag = TRUE; //连续模式下,同码延时和异码延时,第一次解码不需要延时;或者扫码一直不成功,定时器如果超时,解码也不需要延时
uint8_t gCmdStartFlag = FALSE; //命令模式下,开启扫码命令标记;FALSE表示禁止扫码,TRUE表示使能扫码
uint8_t gSensorChangeFlag = FALSE; //环境变化标记,FALSE表明环境无变化,TRUE表明环境有变化
ImageSizeType gLastPictureSize = DCMI_640_480; //感应模式下上一次采图标记,感知环境变化时由于RAM不足,需要采集小图;当进入解码状态时,采集图像尺寸恢复到640*480
uint32_t gCurrentPictureAddr = DCMIBUFADDR; //感应模式下,需要采集两张图像,标记当前采集图像的地址
uint8_t gPreImage[MAXCODELEN] = {0};
uint32_t gPrebarcodelen = 0;
int gPreCodeType = Communication_Id;
uint8_t gCmdModeTimeFlag = FALSE; //命令模式下,定时器开启标志,默认未开启
extern uint8_t gLicenseFlag;
extern uint32_t gFunTrace;
/**
* @function AppScanModeInit
* @brief 配置识读模块的初始条件
* @param[in] 无
* @return 无
*/
void AppScanModeInit(void)
{
switch(gConfgBuf.scanCodeMode)
{
case AUTOMODE:
gAutoModeOverTimeFlag = TRUE;
break;
case CMDMODE:
gCmdStartFlag = TRUE; //命令模式下,开启扫码命令标记;FALSE表示禁止扫码,TRUE表示使能扫码
break;
case CMDTIMEMODE:
gCmdStartFlag = FALSE; //命令模式下,开启扫码命令标记;FALSE表示禁止扫码,TRUE表示使能扫码
break;
case SENSORMODE:
gAutoModeOverTimeFlag = TRUE;
gSensorChangeFlag = FALSE; //环境变化标记,FALSE表明环境无变化,TRUE表明环境有变化
gLastPictureSize = DCMI_640_480;
gCurrentPictureAddr = DCMIBUFADDR;
break;
default:
break;
}
}
/**
* @function AutoScanMode
* @brief 连续模式,一直处于解码状态
* @param[in] BarData 结构体,存放解码数据
* @return 返回值为正,则为成功解码
*/
int AutoScanMode(BarData *pCode)
{
int result = 0;
//灯光控制
AppLEDControl(gConfgBuf.ledStatus);
//采集图像
if(!DCMI_CaptureOnePic(DCMIBUFADDR, DCMI_640_480))return FALSE;
//解码
result = TMC_Scan_Decode(pCode);
if(result > 0)
{
if(gPrebarcodelen && (gPrebarcodelen == pCode->datalen))
{
if(!memcmp(gPreImage, pCode->bardata, pCode->datalen))
{
//同码延时,定时器时间大于延时,输出;或者超时标记为真
if((gAutoModeOverTimeFlag == TRUE) || (TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.sameCodeInterval * CLK_BASE)))
{
gPrebarcodelen = pCode->datalen;
Memcpy(gPreImage, pCode->bardata, pCode->datalen);
gAutoModeOverTimeFlag = FALSE;
TimerHSIClockCount(TIM4, STOP_TIMER);
TimerHSIClockCount(TIM4, START_TIMER);
return TRUE;
}
else
{
return FALSE;
}
}
}
//异码延时,定时器时间大于延时,输出;或者超时标记为真
if((gAutoModeOverTimeFlag == TRUE) || (TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.differentCodeInterval * CLK_BASE)))
{
gPrebarcodelen = pCode->datalen;
Memcpy(gPreImage, pCode->bardata, pCode->datalen);
gAutoModeOverTimeFlag = FALSE;
TimerHSIClockCount(TIM4, STOP_TIMER);
TimerHSIClockCount(TIM4, START_TIMER);
return TRUE;
}
}
else
{
if((TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.sameCodeInterval * CLK_BASE))
&& (TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.differentCodeInterval * CLK_BASE)))
{
gAutoModeOverTimeFlag = TRUE;
}
}
return FALSE;
}
/**
* @function CmdScanMode
* @brief 命令模式,如果接收到开启扫码命令,才开始解码
* @param[in] BarData 结构体,存放解码数据
* @return 返回值为正,则为成功解码
*/
int CmdScanMode(BarData *pCode)
{
int result = 0;
//判断是否收到解码命令
if(gCmdStartFlag)
{
//灯光控制
AppLEDControl(gConfgBuf.ledStatus);
//采集图像
if(!DCMI_CaptureOnePic(DCMIBUFADDR, DCMI_640_480))return FALSE;
//解码
result = TMC_Scan_Decode(pCode);
//识读成功
if(result > 0)
{
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
//记录码制类型
gPreCodeType = pCode->bartype;
//清除命令标记
gCmdStartFlag = FALSE; //关闭扫码
TimerHSIClockCount(TIM5, STOP_TIMER);
return result;
}
}
else
{
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
}
return result;
}
/**
* @function CmdScanTimeMode
* @brief 命令超时模式,如果接收到开启扫码命令,才开始解码,如果超时则自动关闭扫码
* @param[in] BarData 结构体,存放解码数据
* @return 返回值为正,则为成功解码
*/
int CmdScanTimeMode(BarData *pCode)
{
int result = 0;
//判断是否收到解码命令
if(gCmdStartFlag)
{
//如果开启定时,并且时间未超时,则扫码
if(TimerHSIClockCount(TIM5, GET_TIMER) <= gConfgBuf.cmdModeTime * 12000)
{
//灯光控制
AppLEDControl(gConfgBuf.ledStatus);
//采集图像
if(!DCMI_CaptureOnePic(DCMIBUFADDR, DCMI_640_480))return FALSE;
//解码
result = TMC_Scan_Decode(pCode);
//识读成功
if(result > 0)
{
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
//记录码制类型
gPreCodeType = pCode->bartype;
//清除命令标记
gCmdStartFlag = FALSE; //关闭扫码
TimerHSIClockCount(TIM5, STOP_TIMER);
return result;
}
}
else
{
//超时则关闭扫码
gCmdStartFlag = FALSE;
TimerHSIClockCount(TIM5, STOP_TIMER);
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
}
}
else
{
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
}
return result;
}
#ifdef LIGHTING
/**
* @function SensorScanMode
* @brief 感应模式,如果感应环境有变化,再开启解码
* @param[in] BarData 结构体,存放解码数据
* @return 返回值为正,则为成功解码
*/
int SensorScanMode(BarData *pCode)
{
int result = 0;
//环境是否有变化,默认值是"无变化"
if(!gSensorChangeFlag) //环境无变化
{
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
//判断上一次采图尺寸是否为640*480,是的情况下需要采两张图
if(gLastPictureSize == DCMI_640_480)
{
TimerDelay(TIM2, gConfgBuf.stableTime);
gLastPictureSize = DCMI_320_240;
gCurrentPictureAddr = DCMIBUFADDR;
if(!DCMI_CaptureOnePic(gCurrentPictureAddr, gLastPictureSize))return FALSE;
gCurrentPictureAddr += HALF_BUF_SIZE;
}
if(!DCMI_CaptureOnePic(gCurrentPictureAddr, gLastPictureSize))return FALSE;
if(gCurrentPictureAddr == DCMIBUFADDR)
{
gCurrentPictureAddr += HALF_BUF_SIZE;
}
else
{
gCurrentPictureAddr = DCMIBUFADDR;
}
//图像差异明显?
if(DCMI_Differ(HALF_BUF_SIZE) == TMC_OK)
{
gSensorChangeFlag = TRUE;
gLastPictureSize = DCMI_640_480;
TimerHSIClockCount(TIM5, START_TIMER);
}
else
{
return result;
}
}
//环境有变化
//灯光控制
AppLEDControl(gConfgBuf.ledStatus);
//图像采集
if(!DCMI_CaptureOnePic(DCMIBUFADDR, gLastPictureSize))return FALSE;
//解码
result = TMC_Scan_Decode(pCode);
//识读成功 或 超时
if(result > 0)
{
if(gPrebarcodelen && (gPrebarcodelen == pCode->datalen))
{
if(!memcmp(gPreImage, pCode->bardata, pCode->datalen))
{
//同码延时,定时器时间大于延时,输出;或者超时标记为真
if((gAutoModeOverTimeFlag == TRUE) || (TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.sameCodeInterval * CLK_BASE)))
{
Memcpy(gPreImage, pCode->bardata, pCode->datalen);
gPrebarcodelen = pCode->datalen;
gAutoModeOverTimeFlag = FALSE;
TimerHSIClockCount(TIM4, STOP_TIMER);
TimerHSIClockCount(TIM4, START_TIMER);
TimerHSIClockCount(TIM5, STOP_TIMER);
gSensorChangeFlag = FALSE;
return TRUE;
}
return FALSE;
}
}
//异码延时,定时器时间大于延时,输出;或者超时标记为真
if((gAutoModeOverTimeFlag == TRUE) || (TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.differentCodeInterval * CLK_BASE)))
{
Memcpy(gPreImage, pCode->bardata, pCode->datalen);
gPrebarcodelen = pCode->datalen;
gAutoModeOverTimeFlag = FALSE;
TimerHSIClockCount(TIM4, STOP_TIMER);
TimerHSIClockCount(TIM4, START_TIMER);
TimerHSIClockCount(TIM5, STOP_TIMER);
gSensorChangeFlag = FALSE;
return TRUE;
}
return FALSE;
}
else
{
if((TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.sameCodeInterval * CLK_BASE)) && (TimerHSIClockCount(TIM4, GET_TIMER) >= (gConfgBuf.differentCodeInterval * CLK_BASE)))
{
gAutoModeOverTimeFlag = TRUE;
TimerHSIClockCount(TIM4, STOP_TIMER);
}
}
if ((TimerHSIClockCount(TIM5, GET_TIMER) >= SENSOR_TIME_OUT))
{
TimerHSIClockCount(TIM5, STOP_TIMER);
gSensorChangeFlag = FALSE;
}
return result;
}
#else
/**
* @function SensorScanMode
* @brief 感应模式,如果感应环境有变化,再开启解码
* @param[in] BarData 结构体,存放解码数据
* @return 返回值为正,则为成功解码
*/
int SensorScanMode(BarData *pCode)
{
int result = 0;
//环境是否有变化,默认值是"无变化"
if(!gSensorChangeFlag) //环境无变化
{
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
//判断上一次采图尺寸是否为640*480,是的情况下需要采两张图
if(gLastPictureSize == DCMI_640_480)
{
gLastPictureSize = DCMI_320_240;
gCurrentPictureAddr = DCMIBUFADDR;
if(!DCMI_CaptureOnePic(gCurrentPictureAddr, gLastPictureSize))return FALSE;
gCurrentPictureAddr += HALF_BUF_SIZE;
}
if(!DCMI_CaptureOnePic(gCurrentPictureAddr, gLastPictureSize))return FALSE;
if(gCurrentPictureAddr == DCMIBUFADDR)
{
gCurrentPictureAddr += HALF_BUF_SIZE;
}
else
{
gCurrentPictureAddr = DCMIBUFADDR;
}
//图像差异明显?
if(DCMI_Differ(HALF_BUF_SIZE) == TMC_OK)
{
gSensorChangeFlag = TRUE;
gLastPictureSize = DCMI_640_480;
TimerHSIClockCount(TIM4, START_TIMER);
memset(gPreImage, 0, MAXCODELEN);
}
else
{
return result;
}
}
//环境有变化
//灯光控制
AppLEDControl(gConfgBuf.ledStatus);
//图像采集
if(!DCMI_CaptureOnePic(DCMIBUFADDR, gLastPictureSize))return FALSE;
//解码
result = TMC_Scan_Decode(pCode);
//识读成功 或 超时
if(result > 0)
{
if(!memcmp(gPreImage, pCode->bardata, pCode->datalen)) //如果成功,相同条码延时
{
TimerHSIClockCount(TIM4, START_TIMER);
return FALSE;
}
else
{
Memcpy(gPreImage, pCode->bardata, pCode->datalen);
TimerHSIClockCount(TIM4, START_TIMER);
return TRUE;
}
}
if(TimerHSIClockCount(TIM4, GET_TIMER) >= TIME_OUT)
{
gSensorChangeFlag = FALSE;
//灯光控制
AppLEDControl(!gConfgBuf.ledStatus);
TimerHSIClockCount(TIM4, STOP_TIMER);
}
return result;
}
#endif
/**
* @function SingleMode
* @brief 扫码成功一次,移开,再移入才成功
* @param[in] BarData 结构体,存放解码数据
* @return 返回值为正,则为成功解码
*/
int SingleMode(BarData *pCode)
{
int result = 0;
//灯光控制
AppLEDControl(gConfgBuf.ledStatus);
//采集图像
if(!DCMI_CaptureOnePic(DCMIBUFADDR, DCMI_640_480))return FALSE;
//解码
result = TMC_Scan_Decode(pCode);
//识读成功
if(result > 0)
{
//长度相等
if(gPrebarcodelen && (gPrebarcodelen == pCode->datalen))
{
if(memcmp(pCode->bardata, gPreImage, gPrebarcodelen)) //码不同
{
gPrebarcodelen = pCode->datalen;
memcpy(gPreImage, pCode->bardata, gPrebarcodelen);
return TRUE;
}
}
else //长度不等,码不同
{
gPrebarcodelen = pCode->datalen;
memcpy(gPreImage, pCode->bardata, gPrebarcodelen);
return TRUE;
}
}
else
{
gPrebarcodelen = 0;
memset(gPreImage, 0, MAXCODELEN);
}
return FALSE;
}
/**
* @function ScanModeReceiveData
* @brief 扫码模块
* @param[in] BarData 结构体,存放解码数据
* @return TRUE 解码成功
* FALSE 解码失败
*/
uint8_t ScanModeReceiveData(BarData *bardata)
{
int ret = 0;
if(gLicenseFlag)
{
return FALSE;
}
gFunTrace = 36;
switch(gConfgBuf.scanCodeMode)
{
case AUTOMODE:
ret = AutoScanMode(bardata);
break;
case CMDMODE: //命令模式
ret = CmdScanMode(bardata);
break;
case CMDTIMEMODE: //命令时间模式
ret = CmdScanTimeMode(bardata);
break;
case SENSORMODE://感应模式
ret = SensorScanMode(bardata);
break;
case SINGLEMODE: //单次模式
ret = SingleMode(bardata);
break;
default:
ret = AutoScanMode(bardata);
break;
}
if(ret > 0)
{
return TRUE;
}
return FALSE;
}