/** ****************************************************************************** * @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; }