diff --git a/zynq_7010_code/CameraParams.h b/zynq_7010_code/CameraParams.h index e5f4ada..d6fd3c1 100644 --- a/zynq_7010_code/CameraParams.h +++ b/zynq_7010_code/CameraParams.h @@ -21,6 +21,15 @@ union CamZ_Reg_2char int value; }; +union test2 +{ + int value; + struct tests + { + uint8_t data1:8; + uint8_t data2:8; + }bit; +}; union CamZ_Reg_4 { int value; diff --git a/zynq_7010_code/CuoZhiMotor.cpp b/zynq_7010_code/CuoZhiMotor.cpp index e5eb71f..7ffd049 100644 --- a/zynq_7010_code/CuoZhiMotor.cpp +++ b/zynq_7010_code/CuoZhiMotor.cpp @@ -26,8 +26,8 @@ void CuoZhiMotor::pauseWaitForThread() if (thStart.joinable()) { thStart.join(); - } pause(); + } } void CuoZhiMotor::startAsyn() diff --git a/zynq_7010_code/FsmState.cpp b/zynq_7010_code/FsmState.cpp index 9f0477a..0f0c2bf 100644 --- a/zynq_7010_code/FsmState.cpp +++ b/zynq_7010_code/FsmState.cpp @@ -18,7 +18,7 @@ void FsmState::SetLedStatus(LedStatus s) } std::map> FsmStateManager::fsmStates; -void NoPaperState::initial() +void NoPaperState::initial(void *data) { printf("FSM: 扫描仪 无纸\n"); SetLedStatus(LedStatus::Ready); @@ -30,8 +30,7 @@ FsmState *NoPaperState::on_event(ScanEvent &event) return scanner->test(event); } - -void PaperReadyState::initial() +void PaperReadyState::initial(void *data) { if (scanner->getSensor().isPaperIn()) { @@ -46,7 +45,7 @@ FsmState *PaperReadyState::on_event(ScanEvent &event) return scanner->test(event); } -void CoverCloseState::initial() +void CoverCloseState::initial(void *data) { if (scanner->getSensor().isPaperIn()) { @@ -69,7 +68,7 @@ FsmState *CoverCloseState::on_event(ScanEvent &event) return scanner->test(event); } -void CoverOpenState::initial() +void CoverOpenState::initial(void *data) { printf("FSM: 扫描仪 开盖\n"); scanner->put(HG_EVT_STOP_SCAN_EMERGENCY); @@ -80,7 +79,7 @@ FsmState *CoverOpenState::on_event(ScanEvent &event) return scanner->test(event); } -void Boundary_Detection_State::initial() +void Boundary_Detection_State::initial(void *data) { printf("FSM: 扫描仪 纸张边界不平整 \n"); scanner->SetIOutBoundary(true); @@ -92,7 +91,7 @@ FsmState *Boundary_Detection_State::on_event(ScanEvent &event) return scanner->test(event); } -void InitState::initial() +void InitState::initial(void *data) { if (!(scanner->getSensor().isCoverClosed())) { @@ -116,7 +115,7 @@ FsmState *InitState::on_event(ScanEvent &event) return scanner->test(event); } -void ErrorJamState::initial() +void ErrorJamState::initial(void *data) { printf("FSM: 扫描仪 卡纸\n"); scanner->put(HG_EVT_STOP_SCAN_EMERGENCY); @@ -131,7 +130,7 @@ FsmState *ErrorJamState::on_event(ScanEvent &event) return scanner->test(event); } -void ErrorState::initial() +void ErrorState::initial(void *data) { printf("FSM: 扫描仪 搓纸失败\n"); scanner->put(HG_EVT_STOP_SCAN_EMERGENCY); @@ -140,53 +139,14 @@ void ErrorState::initial() FsmState *ErrorState::on_event(ScanEvent &event) { return scanner->test(event); - - if (event == HG_EVT_COVER_OPENED) - { - return FsmStateManagerEx::GetState(); - } - - if (scanner->getSensor().isCoverClosed() && !scanner->getSensor().isPaperStandby() && scanner->getSensor().isPaperIn()) - { - return FsmStateManagerEx::GetState(); - } - else if (event == HG_EVT_PAPER_STANDBY) - { - printf("ErrorState on_event HG_EVT_PAPER_STANDBY\n"); - if (scanner->getSensor().isPaperStandby()) //有纸 且没卡纸 - { - return FsmStateManagerEx::GetState(); - } - else - { - scanner->ResetJamIn(); - return FsmStateManagerEx::GetState(); - } - } - else if (event == HG_EVT_CLEAR_ERR) - { - if (!scanner->getSensor().isCoverClosed()) //没关盖 - { - return FsmStateManagerEx::GetState(); - } - else if (!scanner->GetIsJamIn()) - { - if (scanner->getSensor().isPaperStandby()) //有纸 且没卡纸 - { - if (!scanner->getSensor().isPaperIn()) - return FsmStateManagerEx::GetState(); - } - else - { - return FsmStateManagerEx::GetState(); - } - } - } - return this; } -void ScanningState::initial() +void ScanningState::initial(void *data) { + if (scanner->scanning) + { + return ; + } if (!scanner->getSensor().isCoverClosed()) { scanner->put(HG_EVT_COVER_OPENED); @@ -202,8 +162,10 @@ void ScanningState::initial() scanner->put(HG_EVT_JAM_OUT); return ; } + printf("FSM: 扫描仪 扫描中\n"); SetLedStatus(LedStatus::Scanning); + scanner->seria_is_wait_ = false; scanner->scanning = true; scanner->startScan(); } @@ -218,7 +180,7 @@ FsmState *ScanningState::on_event(ScanEvent &event) return scanner->test(event); } -void Double_Paper_State::initial() +void Double_Paper_State::initial(void *data) { printf("FSM: 扫描仪 双张 \n"); scanner->SetIsDoublePaper(true); @@ -230,7 +192,7 @@ FsmState *Double_Paper_State::on_event(ScanEvent &event) return scanner->test(event); } -void StopScanState::initial() +void StopScanState::initial(void *data) { printf("FSM: 扫描仪 停止扫描 \n"); scanner->stop_scan(); @@ -241,14 +203,13 @@ void StopScanState::initial() scanner->reset(); scanner->scanning = false; } - // scanner->put(HG_EVT_NORES); } FsmState *StopScanState::on_event(ScanEvent &event) { return scanner->test(event); } -void EmergencyStopScanState::initial() +void EmergencyStopScanState::initial(void *data) { printf("FSM: 扫描仪 紧急停止扫描 \n"); scanner->scanning = false; @@ -259,7 +220,7 @@ FsmState *EmergencyStopScanState::on_event(ScanEvent &event) { return scanner->test(event); } -void ScrewDetectionState::initial() +void ScrewDetectionState::initial(void *data) { printf("FSM: 扫描仪 纸张歪斜\n"); scanner->SetIScrewDetection(true); @@ -270,4 +231,85 @@ void ScrewDetectionState::initial() FsmState *ScrewDetectionState::on_event(ScanEvent &event) { return scanner->test(event); -} \ No newline at end of file +} + +void seria_stop::initial(void *data) +{ + seria_parse_.bit.event = HG_EVT_SERIA_STOP_FEEDING; + seria_parse_.bit.data = HG_SERIA_PROTOCOL_OK; + if (scanner->scanning) + { + scanner->seria_is_wait_ = true; + scanner->put(HG_EVT_START_SCAN); + } + scanner->seria_send((void *)&seria_parse_.valua,3); +} +FsmState *seria_stop::on_event(ScanEvent &event) +{ + return scanner->test(event); +} + +void seria_start::initial(void *data) +{ + seria_parse_.bit.event = HG_EVT_SERIA_START_FEEDING; + seria_parse_.bit.data = HG_SERIA_PROTOCOL_OK; + scanner->seria_cancel_wait(); + if (scanner->scanning) + { + scanner->put(HG_EVT_START_SCAN); + } + scanner->seria_send((void *)&seria_parse_.valua,3); +} +FsmState *seria_start::on_event(ScanEvent &event) +{ + return scanner->test(event); +} + +void seria_get_status::initial(void *data) +{ + seria_parse_.bit.event = HG_EVT_SERIA_GET_STATUS; + seria_parse_.bit.data = HG_SERIA_PROTOCOL_OK; + if (scanner->scanning) + { + seria_parse_.bit.data = HG_SERIA_IS_SCANNING; + } + else if (!scanner->getSensor().isCoverClosed()) + { + seria_parse_.bit.data = HG_SERIA_COVER_OPENED; + } + else if(!scanner->getSensor().isPaperStandby()) + { + seria_parse_.bit.data = HG_SERIA_NO_PAPERR; + } + else if(scanner->getSensor().isPaperIn()) + { + seria_parse_.bit.data = HG_SERIA_JAM_IN; + } + + printf("seria_parse_.bit.data:%d\r\n",seria_parse_.bit.data); + scanner->seria_send((void *)&seria_parse_.valua,3); +} +FsmState *seria_get_status::on_event(ScanEvent &event) +{ + return scanner->test(event); +} + +void seria_set_speed_mode::initial(void *data) +{ + if (!data) + { + return; + } + + int r = *((int *)data); + scanner->seria_set_speed(r); + printf("串口切换速度模式:%d\r\n",r); + seria_parse_data s; + s.bit.data = HG_SERIA_PROTOCOL_OK; + s.bit.event = HG_EVT_SERIA_SET_SPEED; + scanner->seria_send((void *)&s.valua,3); +} +FsmState *seria_set_speed_mode::on_event(ScanEvent &event) +{ + return scanner->test(event); +} diff --git a/zynq_7010_code/FsmState.h b/zynq_7010_code/FsmState.h index bacfed5..dd9c248 100644 --- a/zynq_7010_code/FsmState.h +++ b/zynq_7010_code/FsmState.h @@ -20,7 +20,7 @@ public: virtual ~FsmState(); virtual FsmState* on_event(ScanEvent &event) = 0; - virtual void initial() {} + virtual void initial(void *data) {} static void setScanner(Scanner* scan) { @@ -30,6 +30,7 @@ public: protected: static Scanner* scanner; void SetLedStatus(LedStatus s); + seria_parse_data seria_parse_; }; class FsmStateManager { @@ -40,7 +41,7 @@ template class FsmStateManagerEx : public FsmStateManager { public: - static FsmState* GetState() + static FsmState* GetState(void *data) { std::string type_name = typeid(T).name(); std::map>::iterator iter = fsmStates.find(type_name); @@ -48,7 +49,7 @@ public: { fsmStates.insert(std::pair>(type_name, std::shared_ptr(new T))); } - fsmStates[type_name]->initial(); + fsmStates[type_name]->initial(data); return fsmStates[type_name].get(); } }; @@ -56,17 +57,17 @@ public: class InitState :public FsmState { public: virtual FsmState* on_event(ScanEvent &event); - virtual void initial(); + virtual void initial(void *data); }; class NoPaperState :public FsmState { public: - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; class PaperReadyState : public FsmState { public: PaperReadyState() {} - virtual void initial(); + virtual void initial(void *data); FsmState* on_event(ScanEvent &event); }; @@ -75,31 +76,31 @@ class ScanningState : public FsmState { public: ScanningState() {} - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; class CoverOpenState : public FsmState { public: - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; class CoverCloseState : public FsmState { public: - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; class Double_Paper_State : public FsmState { public: - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; class Boundary_Detection_State : public FsmState { public: - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; @@ -108,7 +109,7 @@ class ErrorJamState : public FsmState { public: ErrorJamState() {} - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); void doPaper_pullout(); @@ -116,7 +117,7 @@ public: class ErrorState : public FsmState { public: ErrorState() {} - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; @@ -125,7 +126,7 @@ class EmergencyStopScanState : public FsmState { public: EmergencyStopScanState() {} - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; @@ -134,7 +135,7 @@ class StopScanState : public FsmState { public: StopScanState() {} - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; @@ -143,7 +144,52 @@ class ScrewDetectionState : public FsmState { public: ScrewDetectionState() {} - virtual void initial(); + virtual void initial(void *data); virtual FsmState* on_event(ScanEvent &event); }; + + + + + +class seria_stop : public FsmState { + +public: + seria_stop() {} + + virtual void initial(void *data); + + virtual FsmState* on_event(ScanEvent &event); +}; + +class seria_start : public FsmState { + +public: + seria_start() {} + + virtual void initial(void *data); + + virtual FsmState* on_event(ScanEvent &event); +}; + +class seria_get_status : public FsmState { + +public: + seria_get_status() {} + + virtual void initial(void *data); + + virtual FsmState* on_event(ScanEvent &event); +}; + +class seria_set_speed_mode : public FsmState { + +public: + seria_set_speed_mode() {} + + virtual void initial(void *data); + + virtual FsmState* on_event(ScanEvent &event); +}; + diff --git a/zynq_7010_code/HCamDevice.cpp b/zynq_7010_code/HCamDevice.cpp index 6e96613..5b1de1b 100644 --- a/zynq_7010_code/HCamDevice.cpp +++ b/zynq_7010_code/HCamDevice.cpp @@ -163,6 +163,8 @@ HCamDevice::HCamDevice() //camera_print("ADDR: 0x%x, Value: 0x%x\n", i, val); } + uint32_t q =0; + HtCamGetCisType(q); //HtCamSetScrewDidd(1); } @@ -869,20 +871,6 @@ void HCamDevice::HtCamChangeExposureValueB(uint32_t* value) rgb.NShort[1] = value[2]; //B 通道 HtCamWriteFpgaRegs(0x06,rgb.value); - - // pCamCtrlReg[5] = 0x00000000; - // pCamCtrlReg[6] = 0x00000000; - - // pCamCtrlReg[5] |= (uint32_t)(value[1]); // RED - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - // pCamCtrlReg[5] |= (uint32_t)(value[1] << 16); - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - // pCamCtrlReg[6] |= (uint32_t)(value[0]); // GREEN - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - // pCamCtrlReg[6] |= ((uint32_t)value[2] << 16); // BLUE - - - std::this_thread::sleep_for(std::chrono::milliseconds(5)); printf("曝光B R:%d G:%d B:%d \r\n",value[0],value[1],value[2]); } @@ -902,18 +890,6 @@ void HCamDevice::HtCamChangeExposureValueF(uint32_t* value) rgb.NShort[1] = value[2]; //B 通道 HtCamWriteFpgaRegs(0x0C,rgb.value); - // pCamCtrlReg[11] = 0x00000000; - // pCamCtrlReg[12] = 0x00000000; - - // pCamCtrlReg[11] |= (uint32_t)(value[1]); // RED - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - // pCamCtrlReg[11] |= (uint32_t)(value[1] << 16); - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - - // pCamCtrlReg[12] |= (uint32_t)(value[0]); // GREEN - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); - // pCamCtrlReg[12] |= ((uint32_t)value[2] << 16); // BLUE - std::this_thread::sleep_for(std::chrono::milliseconds(5)); printf("曝光F R:%d G:%d B:%d \r\n",value[0],value[1],value[2]); } @@ -930,7 +906,7 @@ void HCamDevice::HtCamWriteADCReg_ALL(bool is_gain,bool is_adc1,uint8_t addr, ui else addr += 0x0e; //偏移 - //printf("%s 地址 :%d 值%d \r\n",is_gain?"增益":"偏移",addr,data); + printf("%s 地址 :%d 值%d \r\n",is_gain?"增益":"偏移",addr,data); uint32_t *pCamCtrlReg = virBaseAddr; uint32_t AdcRegFrame = 0x0000; @@ -1072,14 +1048,17 @@ void HCamDevice::HtCamReadADCReg_ALL(uint8_t addr) // printf("pAdcRegFrame->value 2222:%0x\r\n",pAdcRegFrame.value); // printf("pAdcRegFrame->regData2222 :%d\r\n",pAdcRegFrame.bit.regData); + test2 t; + t.value = HtCamReadFpgaRegs(0x01); + printf("adc1 data:[%d] adc2 data:[%d]\r\n",t.bit.data1 , t.bit.data2); - CamZ_Reg_2Short rgb; - rgb.value = HtCamReadFpgaRegs(0x01); - CIS_ADC_NEW c ,b; - c.value = rgb.NShort[0]; - b.value = rgb.NShort[1]; + // CamZ_Reg_2Short rgb; + // rgb.value = HtCamReadFpgaRegs(0x01); + // CIS_ADC_NEW c ,b; + // c.value = rgb.NShort[0]; + // b.value = rgb.NShort[1]; - printf("adc1 data:[%d] adc2 data:[%d]\r\n",b.bit.regData , c.bit.regData); + //printf("adc1 data:[%d] adc2 data:[%d]\r\n",b.bit.regData , c.bit.regData); } void HCamDevice::HtCamReadADCReg(uint8_t addr, uint8_t *data) @@ -1354,8 +1333,8 @@ void HCamDevice::HtCamInitADCReg() { - pADCReg[0] = 0x07; - pADCReg[1] = 0x50;//0x50; + pADCReg[0] = 0x07; + pADCReg[1] = 0x50;//0x50; /* gain */ @@ -1405,15 +1384,15 @@ void HCamDevice::HtCamOverClockClear() } -void HCamDevice:: HtCamSetScrewDiv(double reg_value) +void HCamDevice::HtCamSetScrewDiv(double reg_value) { } -void HCamDevice:: HtCamSetScrewSamp(double reg_value) +void HCamDevice::HtCamSetScrewSamp(double reg_value) { } -void HCamDevice:: HtCamSetScrewDidd(double reg_value) +void HCamDevice::HtCamSetScrewDidd(double reg_value) { CamZ_Reg_11 reg ; double val = (reg_value + 1) * 100; @@ -1424,4 +1403,10 @@ void HCamDevice:: HtCamSetScrewDidd(double reg_value) reg.bit.low_reg = val; HtCamWriteFpgaRegs(0x16,reg.value); printf("reg.bit.low_reg:%d val:%f reg_value:%f\r\n",reg.bit.low_reg,val,reg_value); -} \ No newline at end of file +} + +void HCamDevice::HtCamGetCisType(uint32_t& value) +{ + value = (HtCamReadFpgaRegs(0x15)& 0xffff0000) >> 16; + printf("%x\r\n",value); +} diff --git a/zynq_7010_code/HCamDevice.h b/zynq_7010_code/HCamDevice.h index b71c75d..7e5ef94 100644 --- a/zynq_7010_code/HCamDevice.h +++ b/zynq_7010_code/HCamDevice.h @@ -79,6 +79,7 @@ public: void HtCamSetScrewDiv(double reg_value); void HtCamSetScrewSamp(double reg_value); void HtCamSetScrewDidd(double reg_value); + void HtCamGetCisType(uint32_t& value); ////////////////ADC 寄存器0x00 - 0x14/////////////////// /////////////// 0x00 - 0xdh暂时只需要写高位,低位不用写 diff --git a/zynq_7010_code/Scanner.cpp b/zynq_7010_code/Scanner.cpp index d156c4e..465e223 100644 --- a/zynq_7010_code/Scanner.cpp +++ b/zynq_7010_code/Scanner.cpp @@ -17,7 +17,8 @@ Scanner::Scanner(ScannerGlue glue) m_jamPaper(false),m_jamIn(false), m_correctting(false),waitpapertime(200), m_scansysinfo(nullptr),auto_size_(false), - m_iscrew(false),m_isoutBoundary(false) + m_iscrew(false),m_isoutBoundary(false), + seria_is_wait_(false) { frame_time_ = 3000; m_scaninfo = GetScanInfoFromJson(); @@ -62,7 +63,7 @@ Scanner::Scanner(ScannerGlue glue) } }; sensor = std::make_shared(sysEvent); - + seria_ = std::make_shared(sysEvent); m_keyboard.reset(new huagao::Keyboard(btnevent)); m_keyboard->init(); @@ -119,7 +120,7 @@ void Scanner::ConfigScanParam(HG_ScanConfiguration config) m_config.params.pageSize==(int)PaperSize::G400_MAXAUTO || m_config.params.pageSize==(int)PaperSize::G400_MAXSIZE; - updateSpeedMode(); + UpdateScanInfo(); capturer->UpdateScanParam(m_config); } void Scanner::UpdateScanInfo() @@ -171,7 +172,8 @@ void Scanner::runMessageLoop() { std::this_thread::sleep_for(std::chrono::milliseconds(200));//避免scanpin io 开始异常 GetSysInfo();//待fpga 重启完成 - FsmState *fsm = FsmStateManagerEx::GetState(); + void *data = NULL; + FsmState *fsm = FsmStateManagerEx::GetState(data); while (bMsgLoop) { ScanEvent evt = sysEvent.Take(); @@ -190,7 +192,9 @@ void Scanner::processevent(ScanEvent event) return; } //printf("插入事件 001 ID:%d\r\n",event); - m_glue.m_deviceevent(event_2_hg_map_[event], ""); + if (event_2_hg_map_.count(event) > 0) + + m_glue.m_deviceevent(event_2_hg_map_[event], ""); } void Scanner::runScan() { @@ -226,7 +230,16 @@ void Scanner::runScan() isScaning = false; break; } + if (seria_is_wait_) + { + seria_wait_notify(); + if (!sensor->isPaperStandby()) + { + break; + } + } + motorCuozhi.startAsyn(); if (!sensor->waitPaperIn(3000))// @@ -381,6 +394,7 @@ std::string Scanner::GetSysInfo() } void Scanner::emergency_stop(int id) { + seria_cancel_wait(); sensor->cancelWaitPaper(); sensor->enableDoubleSensor(false); sensor->width_detect_enable(false); @@ -397,6 +411,7 @@ void Scanner::emergency_stop(int id) } void Scanner::stop_scan() { + seria_cancel_wait(); sensor->cancelWaitPaper(); sensor->enableDoubleSensor(false); sensor->width_detect_enable(false); @@ -437,7 +452,25 @@ void Scanner::paper_pullout() motorZouzhi.speedRecover(); m_isPulling = false; } - +void Scanner::seria_wait_notify() +{ + std::unique_lock lock(seria_lock_); + wait_seria_.wait(lock); +} +void Scanner::seria_cancel_wait() +{ + wait_seria_.notify_all(); + seria_is_wait_ = false; +} +void Scanner::seria_send(void * data,int len) +{ + seria_->cc_seria_send(data,len); +} +void Scanner::seria_set_speed(int sp) +{ + m_scaninfo.SpeedMode = sp; + SaveScaninfo(m_scaninfo); +} void Scanner::status_change_init() { status_change_map_[HG_EVT_PAPER_NOT_STANDBY] = &Scanner::status_change_standby ; @@ -454,6 +487,16 @@ void Scanner::status_change_init() status_change_map_[HG_EVT_SCREW_DETECTION] = &Scanner::status_change_screw_detection; status_change_map_[HG_EVT_OUT_BOUNDS] = &Scanner::status_change_boundary_detection; + status_change_map_[HG_EVT_SERIA_STOP_FEEDING] = &Scanner::status_change_seria_stop; + status_change_map_[HG_EVT_SERIA_START_FEEDING] = &Scanner::status_change_seria_start; + status_change_map_[HG_EVT_SERIA_GET_STATUS] = &Scanner::status_change_seria_get_status; + status_change_map_[HG_EVT_SERIA_SPEED_MODE_1] = &Scanner::status_change_seria_set_speed_mode; + status_change_map_[HG_EVT_SERIA_SPEED_MODE_2] = &Scanner::status_change_seria_set_speed_mode; + status_change_map_[HG_EVT_SERIA_SPEED_MODE_3] = &Scanner::status_change_seria_set_speed_mode; + status_change_map_[HG_EVT_SERIA_SPEED_MODE_4] = &Scanner::status_change_seria_set_speed_mode; + status_change_map_[HG_EVT_SERIA_SPEED_MODE_5] = &Scanner::status_change_seria_set_speed_mode; + + event_2_hg_map_[HG_EVT_PAPER_NOT_STANDBY] = (int)HG_ScannerStatus::NO_FEED; event_2_hg_map_[HG_EVT_JAM_OUT] = (int)HG_ScannerStatus::PAPER_JAM; event_2_hg_map_[HG_EVT_JAM_IN] = (int)HG_ScannerStatus::FEED_IN_ERROR; @@ -463,71 +506,122 @@ void Scanner::status_change_init() event_2_hg_map_[HG_EVT_STOP_SCAN_EMERGENCY] = (int)HG_ScannerStatus::STOP_SCAN; event_2_hg_map_[HG_EVT_SCREW_DETECTION] = (int)HG_ScannerStatus::PAPER_SKEW; event_2_hg_map_[HG_EVT_OUT_BOUNDS] = (int)HG_ScannerStatus::BOUNDS_OUT_TEST; + } -FsmState* Scanner::status_change_standby() +FsmState* Scanner::status_change_standby(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState *Scanner::status_change_paper_ready() +FsmState *Scanner::status_change_paper_ready(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_scanning() +FsmState* Scanner::status_change_scanning(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_paperjam() +FsmState* Scanner::status_change_paperjam(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_feed_in_error() +FsmState* Scanner::status_change_feed_in_error(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_double_paper() +FsmState* Scanner::status_change_double_paper(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_open_cover() +FsmState* Scanner::status_change_open_cover(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_close_cover() +FsmState* Scanner::status_change_close_cover(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_stop_scan() +FsmState* Scanner::status_change_stop_scan(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_emergency_stop_scan() +FsmState* Scanner::status_change_emergency_stop_scan(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_screw_detection() +FsmState* Scanner::status_change_screw_detection(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_init_status() +FsmState* Scanner::status_change_init_status(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); +} +FsmState* Scanner::status_change_boundary_detection(void *data) +{ + return FsmStateManagerEx::GetState(data); } -FsmState* Scanner::status_change_boundary_detection() + +FsmState* Scanner::status_change_seria_stop(void *data) { - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); +} +FsmState* Scanner::status_change_seria_start(void *data) +{ + return FsmStateManagerEx::GetState(data); +} +FsmState* Scanner::status_change_seria_get_status(void *data) +{ + return FsmStateManagerEx::GetState(data); +} +FsmState* Scanner::status_change_seria_set_speed_mode(void *data) +{ + return FsmStateManagerEx::GetState(data); } FsmState *Scanner::test(ScanEvent e) { + void * data = NULL; + int r = 0; + if (e == HG_EVT_SERIA_SPEED_MODE_1 || e == HG_EVT_SERIA_SPEED_MODE_2 + ||e == HG_EVT_SERIA_SPEED_MODE_3 + ||e == HG_EVT_SERIA_SPEED_MODE_4 ||e == HG_EVT_SERIA_SPEED_MODE_5 ) + { + seria_protocol s = hgevt_2_seria(e); + r = (int)s; + } + + //printf("插入事件 000 ID:%d\r\n",e); + //data = &(hgevt_2_seria(e)); if (status_change_map_.count(e) > 0) { - FsmState *fsm = (this->*status_change_map_[e])(); + FsmState *fsm = (this->*status_change_map_[e])((void*)&r); //printf("当前状态事件:%s\r\n",typeid(*fsm).name()); return fsm; } - return FsmStateManagerEx::GetState(); + return FsmStateManagerEx::GetState(data); +} + +seria_protocol Scanner::hgevt_2_seria(ScanEvent p) +{ + switch (p) + { + case HG_EVT_SERIA_SPEED_MODE_1: + return HG_SERIA_SPEED_MODE_1 ; + + case HG_EVT_SERIA_SPEED_MODE_2: + return HG_SERIA_SPEED_MODE_2; + + case HG_EVT_SERIA_SPEED_MODE_3: + return HG_SERIA_SPEED_MODE_3; + + case HG_EVT_SERIA_SPEED_MODE_4: + return HG_SERIA_SPEED_MODE_4; + + case HG_EVT_SERIA_SPEED_MODE_5: + return HG_SERIA_SPEED_MODE_5; + } } \ No newline at end of file diff --git a/zynq_7010_code/Scanner.h b/zynq_7010_code/Scanner.h index 2ad078c..62319f4 100644 --- a/zynq_7010_code/Scanner.h +++ b/zynq_7010_code/Scanner.h @@ -17,6 +17,7 @@ #include "SysInforTool.h" #include "MotorConfig.h" #include "correct_ultis.h" +#include "seria_com.h" class ICapturer; class MemoryInfo; @@ -27,8 +28,18 @@ class Scanner std::mutex cb_lock_; std::condition_variable wait_cb_; + std::mutex seria_lock_; + std::condition_variable wait_seria_; +public: + void seria_cancel_wait(); + void seria_wait_notify(); + void seria_send(void * data,int len); + void seria_set_speed(int sp); + seria_protocol hgevt_2_seria(ScanEvent p); public: bool isScaning = false; + volatile bool seria_is_wait_; + public: Scanner(ScannerGlue glue); @@ -45,6 +56,7 @@ public: static void have_img_callback(int val); std::string GetSysInfo(); + public: Sensor &getSensor() { return *sensor.get(); } PanelLeds &getPanelLeds() { return panelLeds; } @@ -136,26 +148,34 @@ private: std::shared_ptr capturer; std::shared_ptr m_keyboard; std::shared_ptr sensor; - + std::shared_ptrseria_; public: bool scanning = true; std::map event_2_hg_map_; - std::map status_change_map_; + std::map status_change_map_; void status_change_init(); - FsmState* status_change_no_paper(); - FsmState *status_change_standby(); - FsmState *status_change_paper_ready(); - FsmState *status_change_scanning(); - FsmState *status_change_paperjam(); - FsmState *status_change_feed_in_error(); - FsmState *status_change_double_paper(); - FsmState *status_change_open_cover(); - FsmState *status_change_close_cover(); - FsmState *status_change_stop_scan(); - FsmState *status_change_emergency_stop_scan(); - FsmState *status_change_screw_detection(); - FsmState *status_change_init_status(); - FsmState *status_change_boundary_detection(); + FsmState* status_change_no_paper(void *data); + FsmState *status_change_standby(void *data); + FsmState *status_change_paper_ready(void *data); + FsmState *status_change_scanning(void *data); + FsmState *status_change_paperjam(void *data); + FsmState *status_change_feed_in_error(void *data); + FsmState *status_change_double_paper(void *data); + FsmState *status_change_open_cover(void *data); + FsmState *status_change_close_cover(void *data); + FsmState *status_change_stop_scan(void *data); + FsmState *status_change_emergency_stop_scan(void *data); + FsmState *status_change_screw_detection(void *data); + FsmState *status_change_init_status(void *data); + FsmState *status_change_boundary_detection(void *data); + + FsmState *status_change_seria_stop(void *data); + FsmState *status_change_seria_start(void *data); + FsmState *status_change_seria_get_status(void *data); + FsmState *status_change_seria_set_speed_mode(void *data); + + + FsmState *test(ScanEvent e); }; diff --git a/zynq_7010_code/regsctrl.cpp b/zynq_7010_code/regsctrl.cpp new file mode 100644 index 0000000..a7a341a --- /dev/null +++ b/zynq_7010_code/regsctrl.cpp @@ -0,0 +1,276 @@ +#include "regsctrl.h" +#include "unistd.h" +#include +#include +#include + +#define CIS0003 0x516 +#define CIS0006 0x515 +Regs::Regs() + : pregs(nullptr) +{ + if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) + return; + + pregs = (uint32_t *)mmap(NULL, range, PROT_READ | PROT_WRITE, MAP_SHARED, fd, base); +} + +Regs RegsBase::regs = Regs(); + +Regs::~Regs() +{ + if (pregs) + munmap(pregs, range); + + if (fd >= 0) + close(fd); +} +uint32_t *Regs::addr_base() +{ + return pregs; +} +CamRegsHg::CamRegsHg() +{ + regE = (PRegE)(regs.addr_base() + 0x0E); + regD = (PRegD)(regs.addr_base() + 0x0D); + regC = (PRegC)(regs.addr_base() + 0x0C); + regB = (PRegB)(regs.addr_base() + 0x0B); + regA = (PRegA)(regs.addr_base() + 0x0A); + + reg16 = (PReg16)(regs.addr_base() + 0x16); + reg15 = (PReg15)(regs.addr_base() + 0x15); + reg14 = (PReg14)(regs.addr_base() + 0x14); + reg13 = (PReg13)(regs.addr_base() + 0x13); + reg12 = (PReg12)(regs.addr_base() + 0x12); + reg11 = (PReg11)(regs.addr_base() + 0x11); + reg10 = (PReg10)(regs.addr_base() + 0x10); + + reg9 = (PReg9)(regs.addr_base() + 0x9); + reg8 = (PReg8)(regs.addr_base() + 0x8); + reg6 = (PReg6)(regs.addr_base() + 0x6); + reg5 = (PReg5)(regs.addr_base() + 0x5); + reg4 = (PReg4)(regs.addr_base() + 0x4); + reg3 = (PReg3)(regs.addr_base() + 0x3); + reg2 = (PReg2)(regs.addr_base() + 0x2); + + //reg7_6 = (PReg1_6)(regs.addr_base() + 0x07); + reg1_6 = (PReg1_6)(regs.addr_base() + 0x01); + reg0_6 = (PReg0_6)(regs.addr_base() + 0x00); + + reg17_3 = (PReg17_3)(regs.addr_base() + 0x17); ; + reg7_3 = (PReg7_3)(regs.addr_base() + 0x07); + reg1_3 = (PReg1_3)(regs.addr_base() + 0x01); + reg0_3 = (PReg0_3)(regs.addr_base() + 0x00); + + get_cis_model(); +} + +void CamRegsHg::set_adc(bool ix, int ixreg, uint16_t val) +{ + if (cis_type_ == CIS0006) + { + if (!ix) + { + reg0_6->rwbit1 = 0; + reg0_6->rwbit2 = 0; + reg0_6->addr1 = ixreg; + reg0_6->addr2 = ixreg; + reg0_6->data1 = val; + reg0_6->data2 = val; + + reg4->en_adc1_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc1_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + //printf("ix:%d ixreg:%d\r\n",ix,ixreg); + return ; + } + + reg7_6->rwbit1 = 0; + reg7_6->rwbit2 = 0; + reg7_6->addr1 = ixreg; + reg7_6->addr2 = ixreg; + reg7_6->data1 = val; + reg7_6->data2 = val; + + reg4->en_adc2_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc2_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + //printf("ix:%d ixreg:%d\r\n",ix,ixreg); + return ; + } + + if (!ix) + { + reg0_3->rwbit1 = 0; + reg0_3->rwbit2 = 0; + reg0_3->addr1 = ixreg; + reg0_3->addr2 = ixreg; + reg0_3->data1 = val; + reg0_3->data2 = val; + + reg4->en_adc1_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc1_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + //printf("ix:%d ixreg:%d\r\n",ix,ixreg); + return ; + } + + reg7_3->rwbit1 = 0; + reg7_3->rwbit2 = 0; + reg7_3->addr1 = ixreg; + reg7_3->addr2 = ixreg; + reg7_3->data1 = val; + reg7_3->data2 = val; + + reg4->en_adc2_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc2_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + //printf("ix:%d ixreg:%d\r\n",ix,ixreg); +} + + +uint16_t CamRegsHg::get_adc(int ix, int ixreg) +{ + if (cis_type_ == CIS0006) + { + if (!ix) + { + reg0_6->rwbit1 = 1; + reg0_6->rwbit2 = 1; + reg0_6->addr1 = ixreg; + reg0_6->addr2 = ixreg; + reg0_6->data1 = 0; + reg0_6->data2 = 0; + + reg4->en_adc1_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc1_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + } + else + { + reg7_6->rwbit1 = 1; + reg7_6->rwbit2 = 1; + reg7_6->addr1 = ixreg; + reg7_6->addr2 = ixreg; + reg7_6->data1 = 0; + reg7_6->data2 = 0; + + reg4->en_adc2_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc2_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + } + + //printf("ix:%d ixreg:%d\r\n",ix,ixreg); + //printf("adc1 data:[%d] adc2 data:[%d]\r\n",Reg1_6->adc1_data , Reg1_6->adc2_data); + return 0; + } + + if (!ix) + { + reg0_3->rwbit1 = 1; + reg0_3->rwbit2 = 1; + reg0_3->addr1 = ixreg; + reg0_3->addr2 = ixreg; + reg0_3->data1 = 0; + reg0_3->data2 = 0; + + reg4->en_adc1_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc1_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + + } + else + { + reg7_3->rwbit1 = 1; + reg7_3->rwbit2 = 1; + reg7_3->addr1 = ixreg; + reg7_3->addr2 = ixreg; + reg7_3->data1 = 0; + reg7_3->data2 = 0; + + reg4->en_adc2_cfg = 0; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + reg4->en_adc2_cfg = 1; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + } + + //printf("ix:%d ixreg:%d\r\n",ix,ixreg); + //printf("adc1 data:[%d] adc2 data:[%d]\r\n", reg1_3->adc1_data , reg17_3->adc2_data); +} + + +int CamRegsHg::get_cis_model() +{ + return cis_type_ = reg15->cis_model; +} + +std::vector CamRegsHg::get_expos() +{ + std::vector vals(6); + vals[0] = get_expo_r(0); + vals[1] = get_expo_g(0); + vals[2] = get_expo_b(0); + vals[3] = get_expo_r(1); + vals[4] = get_expo_g(1); + vals[5] = get_expo_b(1); + return vals; +} + +void CamRegsHg::set_expos(const std::vector& expos) +{ + if (expos.size() != 6) + return; + + set_expo_r(0, expos[0]); + set_expo_g(0, expos[1]); + set_expo_b(0, expos[2]); + set_expo_r(1, expos[3]); + set_expo_g(1, expos[4]); + set_expo_b(1, expos[5]); +} + +void CamRegsHg::set_expo_r(int ix, uint16_t val) +{ + if (!ix) + reg5->R1 = val; + else + regB->R2 = val; +} + +uint16_t CamRegsHg::get_expo_r(int ix) +{ + return !ix ? reg5->R1 : regB->R2; +} + +void CamRegsHg::set_expo_g(int ix, uint16_t val) +{ + if(!ix) + reg6->G1 = val; + else + regC->G2 = val; +} + +uint16_t CamRegsHg::get_expo_g(int ix) +{ + return !ix ? reg6->G1 : regC->G2; +} + +void CamRegsHg::set_expo_b(int ix, uint16_t val) +{ + if(!ix) + reg6->B1 = val; + else + regC->B2 = val; +} + +uint16_t CamRegsHg::get_expo_b(int ix) +{ + return !ix ? reg6->B1 : regC->B2; +} \ No newline at end of file diff --git a/zynq_7010_code/regsctrl.h b/zynq_7010_code/regsctrl.h new file mode 100644 index 0000000..ab4c0b3 --- /dev/null +++ b/zynq_7010_code/regsctrl.h @@ -0,0 +1,296 @@ +#pragma once +#include +#include + +//!< 0_6 and 7_6_ is cis6 , 0_3_ and 7_3_ is cis3 0x00 and 0x07 start >! +typedef struct _Reg0_6_ +{ + uint8_t data1; // 数据区 + uint32_t reserve : 2; + uint8_t addr1 : 5; // 寄存器地址 + uint8_t rwbit1 : 1; // 读写 1读 0写 + uint8_t data2 : 8; + uint32_t reserve1 : 2; + uint32_t addr2 : 5; + uint32_t rwbit2 : 1; +} Reg0_6, *PReg0_6; +typedef struct _Reg7_6_ +{ + uint8_t data1; + uint32_t reserve : 2; + uint8_t addr1 : 5; + uint8_t rwbit1 : 1; + uint8_t data2: 8; + uint32_t reserve1 : 2; + uint32_t addr2 : 5; + uint32_t rwbit2 : 1; +} Reg7_6, *PReg7_6; + +typedef struct _Reg0_3_ +{ + uint16_t data1: 9; + uint32_t reserve : 3; + uint8_t addr1 : 3; + uint8_t rwbit1 : 1; + uint8_t data2: 9; + uint32_t reserve1 : 3; + uint32_t addr2 : 3; + uint32_t rwbit2 : 1; +} Reg0_3, *PReg0_3; + +typedef struct _Reg7_3_ +{ + uint16_t data1: 9; + uint32_t reserve : 3; + uint8_t addr1 : 3; + uint8_t rwbit1 : 1; + uint8_t data2: 9; + uint32_t reserve1 : 3; + uint32_t addr2 : 3; + uint32_t rwbit2 : 1; +} Reg7_3, *PReg7_3; +//!< 0_6 and 7_6_ is cis6 , 0_3_ and 7_3_ is cis3 0x00 and 0x07 end >! + +//!< _Reg1_6_ get 6cis adc data start >! +typedef struct _Reg1_6_ +{ + uint16_t adc1_data; + uint16_t adc2_data; +} Reg1_6, *PReg1_6; +//!< _Reg1_6_ get 6cis adc data end >! + +//!< _Reg_1_3_ and _Reg17_3_ get 3cis adc1 and adc2 data start >! +typedef struct _Reg_1_3_ +{ + uint32_t adc1_data ; +} Reg1_3, *PReg1_3; + +typedef struct _Reg17_3_ +{ + uint32_t adc2_data ; +} Reg17_3, *PReg17_3; +//!< _Reg_1_3_ and _Reg17_3_ get 3cis adc1 and adc2 data end >! + +typedef struct _Reg2_ +{ + uint8_t button_start : 1; + uint8_t button : 1; + uint8_t start_stop_flag : 1; + uint8_t trigger_flag : 1; +} Reg2, *PReg2; + +typedef struct _Reg3_ +{ + uint16_t sp_inter; //!< 曝光间隔 默认 49 + uint16_t sp_line; //!< 灰度内触发间隔 +} Reg3, *PReg3; + +typedef struct _Reg4_ +{ + uint8_t reserve0 : 2; + uint8_t mode : 1; + uint8_t en_frameset : 1; + uint16_t reserve1 : 9; + uint8_t en_adc1_cfg : 1; + uint8_t en_adc2_cfg : 1; + uint8_t clr_exp : 1; + uint8_t soft_rst_n : 1; + uint8_t en_pattern : 1; + uint16_t en_line : 1; +} Reg4, *PReg4; + +typedef struct _Reg5_ +{ + uint16_t reserve0; + uint16_t R1; +} Reg5, *PReg5; + +typedef struct _Reg6_ +{ + uint16_t G1; + uint16_t B1; +} Reg6, *PReg6; + +typedef struct _Reg8_ +{ + uint8_t i_ctr1; + uint16_t i_devder; + uint8_t reserve; +} Reg8, *PReg8; + +typedef struct _Reg9_ +{ + uint8_t i_period; + uint16_t i_dc; +} Reg9, *PReg9; + +typedef struct _RegA_ +{ + uint8_t start : 1; + uint8_t stop : 1; + uint8_t reserve : 5; + uint8_t finished : 1; + uint8_t psen : 1; + uint8_t psincdec : 1; + uint8_t clr_psedon : 1; + uint8_t dpi : 1; //!< 1 : 300dpi , 0 : 600dpi + uint32_t reserve1 : 20; +} RegA, *PRegA; + +typedef struct _RegB_ +{ + uint16_t reserve; + uint16_t R2; +} RegB, *PRegB; + +typedef struct _RegC_ +{ + uint16_t G2; + uint16_t B2; +} RegC, *PRegC; + +typedef struct _RegD_ +{ + uint16_t line_cnt; + uint16_t mo; +} RegD, *PRegD; + +typedef struct _RegE_ +{ + uint16_t send_line_cnt; +} RegE, *PRegE; + +typedef struct _Reg10_ +{ + uint8_t vsnp1; + uint8_t vsnp2; + uint16_t reserve; +} Reg10, *PReg10; + +typedef struct _Reg11_ +{ + uint8_t dev_reg : 6; + uint16_t samp_reg : 10; + uint16_t low_reg : 10; + uint16_t reserve : 6; +} Reg11, *PReg11; + +typedef struct _Reg12_ +{ + uint32_t autogig_dly_time; +} Reg12, *PReg12; + +typedef struct _Reg13_ +{ + uint16_t sp_time2; //!< 彩色模式下的内触发间隔 + uint16_t reserve; +} Reg13, *PReg13; + +typedef struct _Reg14_ +{ + uint16_t frame_cnt; + uint16_t reserve; +} Reg14, *PReg14; + +typedef struct _Reg15_ +{ + uint16_t frame_tx; + uint16_t cis_model; +} Reg15, *PReg15; + +typedef struct _Reg16_ +{ + uint8_t dev_reg : 6; + uint16_t samp_reg : 10; + uint16_t diff_reg : 10; + uint16_t reserve : 6; +} Reg16, *PReg16; + + +class Regs +{ +private: + /* data */ +public: + Regs(/* args */); + ~Regs(); + int read(int ix); + void write(int ix , int val); + uint32_t* addr_base(); +private: + const int base = 0x40010000; + const int range = 0x100; + + int fd; + uint32_t* pregs; +}; + +class RegsBase +{ +protected: + static Regs regs; +}; + +class CamRegsHg : public RegsBase +{ +public: + CamRegsHg(); + +//!< 0x00 and 0x07 start + void set_adc(bool ix, int ixreg, uint16_t val); +//!< 0x00 and 0x07 end + +//!< 0x01 start + uint16_t get_adc(int ix, int ixreg); +//!< 0x01 end + + std::vector get_expos(); + void set_expos(const std::vector& expos); + + void set_expo_r(int ix, uint16_t val); + uint16_t get_expo_r(int ix); + void set_expo_g(int ix, uint16_t val); + uint16_t get_expo_g(int ix); + void set_expo_b(int ix, uint16_t val); + uint16_t get_expo_b(int ix); + + //!< 0x15 start + int get_cis_model(); + //!< 0x15 start + + int cis_type_; + +private: + const int dpi300 = 5184; + + PRegE regE; + PRegD regD; + PRegC regC; + PRegB regB; + PRegA regA; + PReg16 reg16; + PReg15 reg15; + PReg14 reg14; + PReg13 reg13; + PReg12 reg12; + PReg11 reg11; + PReg10 reg10; + PReg9 reg9; + PReg8 reg8; + PReg6 reg6; + PReg5 reg5; + PReg4 reg4; + PReg3 reg3; + PReg2 reg2; + +//!< adc read and write _3 is 3cis _6 is 6cis start >! + PReg17_3 reg17_3; + PReg7_3 reg7_3; + PReg1_3 reg1_3; + PReg0_3 reg0_3; + + PReg7_6 reg7_6; + PReg1_6 reg1_6; + PReg0_6 reg0_6; +//!< adc read and write _3 is 3cis _6 is 6cis end >! +}; \ No newline at end of file diff --git a/zynq_7010_code/scanservices_utils.h b/zynq_7010_code/scanservices_utils.h index c139a6c..b89210f 100644 --- a/zynq_7010_code/scanservices_utils.h +++ b/zynq_7010_code/scanservices_utils.h @@ -312,7 +312,6 @@ enum scanner_err SCANNER_ERR_UPDATE_UNZIP_FAIL, //设备更新:解压失败 }; - enum ScanEvent { HG_EVT_NORES = 0x00, HG_EVT_SCAN_FINISHED , @@ -343,10 +342,51 @@ enum ScanEvent { HG_EVT_PAPER_NOT_STANDBY, HG_EVT_PAPER_STANDBY, HG_EVT_SCREW_DETECTION, - HG_EVT_SCREW_NOT_DETECTION + HG_EVT_SCREW_NOT_DETECTION, + + + HG_EVT_SERIA_START_FEEDING = 0x1000, + HG_EVT_SERIA_STOP_FEEDING, + HG_EVT_SERIA_GET_STATUS, + HG_EVT_SERIA_SET_SPEED, + + HG_EVT_SERIA_SPEED_MODE_1, + HG_EVT_SERIA_SPEED_MODE_2, + HG_EVT_SERIA_SPEED_MODE_3, + HG_EVT_SERIA_SPEED_MODE_4, + HG_EVT_SERIA_SPEED_MODE_5, + HG_EVT_SERIA_PROTOCOL_ERROR = 0x1100, + HG_EVT_SERIA_RESERVED = 0x1100, }; +union seria_parse_data +{ + uint32_t valua; + struct + { + uint32_t data:5; + uint32_t event:13; + uint32_t reserved:14; + }bit; + +}; + +enum seria_protocol +{ + HG_SERIA_PROTOCOL_OK = 0X00, + HG_SERIA_SPEED_MODE_1, + HG_SERIA_SPEED_MODE_2, + HG_SERIA_SPEED_MODE_3, + HG_SERIA_SPEED_MODE_4, + HG_SERIA_SPEED_MODE_5, + HG_SERIA_COVER_OPENED, + HG_SERIA_NO_PAPERR, + HG_SERIA_JAM_IN , + HG_SERIA_IS_SCANNING, + HG_SERIA_PROTOCOL_ERROR = 0x1F, +}; + typedef struct { int Command; diff --git a/zynq_7010_code/seria_com.cpp b/zynq_7010_code/seria_com.cpp new file mode 100644 index 0000000..9ca071a --- /dev/null +++ b/zynq_7010_code/seria_com.cpp @@ -0,0 +1,111 @@ +#include +#define SERIAL_PORT "/dev/ttyPS1" +seria_com::seria_com(BlockingQueue& sysEvents):events(sysEvents) +{ + serialib_.reset(new serialib); + if (!serialib_.get()) + { + return; + } + + int ret = serialib_->openDevice(SERIAL_PORT,19200); + if(ret != 1) return ; + + printf("Ok To Open Port: %s \r\n", SERIAL_PORT); + thread_seria = std::thread(&seria_com::thread_seria_com,this); +} + +seria_com::~seria_com() +{ +} +void seria_com::thread_seria_com() +{ + std::vector buf; + while (serialib_.get()) + { + if (serialib_->waitAvailable(100) >= 0) + { + buf.resize(serialib_->available()); + serialib_->readBytes((void *)buf.data(), buf.size(), 0, 0); + parse_com_data(buf.data(),buf.size()); + } + } +} + +void seria_com::parse_com_data(uint8_t *buf,size_t len) +{ + std::vector vec; + vec.resize(len); + vec.push_back(HG_SERIA_PROTOCOL_ERROR); + if (len != 3 ) + { + printf("协议数量错误!!!\r\n"); + cc_seria_send(vec.data(),vec.size()); + return ; + } + + seria_parse_data parse; + + int c = buf[0] << 11 ; + int d = c | buf[1] ; + + printf("d :%d %x\r\n",d, d); + parse.valua = d << 5 | buf[2]; + + + ScanEvent e; + printf("parse.bit.event:%d data :%d\r\n",parse.bit.event,parse.bit.data); + switch (parse.bit.event) + { + case HG_EVT_SERIA_SET_SPEED: + + e = seria_to_hgevt((seria_protocol)parse.bit.data); + if (e == HG_EVT_SERIA_PROTOCOL_ERROR) + { + cc_seria_send(vec.data(),vec.size()); + break; + } + events.Put(e); + break; + case HG_EVT_SERIA_START_FEEDING: + case HG_EVT_SERIA_STOP_FEEDING: + case HG_EVT_SERIA_GET_STATUS: + if (parse.bit.data != HG_SERIA_PROTOCOL_OK) + { + cc_seria_send(vec.data(),vec.size()); + break; + } + events.Put((ScanEvent)parse.bit.event); + break; + + default: + cc_seria_send(vec.data(),vec.size()); + break; + } + + printf("协议 READ :%d %x\r\n",parse.valua,parse.valua); + +} + +void seria_com::cc_seria_send(void * data,int len) +{ + serialib_->writeBytes(data, len); +} +ScanEvent seria_com::seria_to_hgevt(seria_protocol p) +{ + switch (p) + { + case HG_SERIA_SPEED_MODE_1: + return HG_EVT_SERIA_SPEED_MODE_1; + case HG_SERIA_SPEED_MODE_2: + return HG_EVT_SERIA_SPEED_MODE_2; + case HG_SERIA_SPEED_MODE_3: + return HG_EVT_SERIA_SPEED_MODE_3; + case HG_SERIA_SPEED_MODE_4: + return HG_EVT_SERIA_SPEED_MODE_4; + case HG_SERIA_SPEED_MODE_5: + return HG_EVT_SERIA_SPEED_MODE_5; + default: + return HG_EVT_SERIA_PROTOCOL_ERROR; + } +} \ No newline at end of file diff --git a/zynq_7010_code/seria_com.h b/zynq_7010_code/seria_com.h new file mode 100644 index 0000000..5aa6000 --- /dev/null +++ b/zynq_7010_code/seria_com.h @@ -0,0 +1,27 @@ + + +#include +#include +#include +#include "BlockingQueue.h" +#include "scanservices_utils.h" +#include +#include + +class seria_com +{ +private: + BlockingQueue& events; + std::thread thread_seria; + void thread_seria_com(); + volatile bool bseria = true; + std::shared_ptr serialib_; + void parse_com_data(uint8_t *buf,size_t len); + ScanEvent seria_to_hgevt(seria_protocol p); +public: + seria_com(BlockingQueue& sysEvents); + ~seria_com(); + void cc_seria_send(void * data,int len); +}; + + diff --git a/zynq_7010_code/serialib.cpp b/zynq_7010_code/serialib.cpp new file mode 100644 index 0000000..dc2807c --- /dev/null +++ b/zynq_7010_code/serialib.cpp @@ -0,0 +1,1164 @@ +/*! + \file serialib.cpp + \brief Source file of the class serialib. This class is used for communication over a serial device. + \author Philippe Lucidarme (University of Angers) + \version 2.0 + \date december the 27th of 2019 + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +This is a licence-free software, it can be used by anyone who try to build a better world. + */ + +#include "serialib.h" + + + +//_____________________________________ +// ::: Constructors and destructors ::: + + +/*! + \brief Constructor of the class serialib. +*/ +serialib::serialib() +{ +#if defined (_WIN32) || defined( _WIN64) + // Set default value for RTS and DTR (Windows only) + currentStateRTS=true; + currentStateDTR=true; + hSerial = INVALID_HANDLE_VALUE; +#endif +#if defined (__linux__) || defined(__APPLE__) + fd = -1; +#endif +} + + +/*! + \brief Destructor of the class serialib. It close the connection +*/ +// Class desctructor +serialib::~serialib() +{ + closeDevice(); +} + + + +//_________________________________________ +// ::: Configuration and initialization ::: + + + +/*! + \brief Open the serial port + \param Device : Port name (COM1, COM2, ... for Windows ) or (/dev/ttyS0, /dev/ttyACM0, /dev/ttyUSB0 ... for linux) + \param Bauds : Baud rate of the serial port. + + \n Supported baud rate for Windows : + - 110 + - 300 + - 600 + - 1200 + - 2400 + - 4800 + - 9600 + - 14400 + - 19200 + - 38400 + - 56000 + - 57600 + - 115200 + - 128000 + - 256000 + + \n Supported baud rate for Linux :\n + - 110 + - 300 + - 600 + - 1200 + - 2400 + - 4800 + - 9600 + - 19200 + - 38400 + - 57600 + - 115200 + + \n Optionally supported baud rates, depending on Linux kernel:\n + - 230400 + - 460800 + - 500000 + - 576000 + - 921600 + - 1000000 + - 1152000 + - 1500000 + - 2000000 + - 2500000 + - 3000000 + - 3500000 + - 4000000 + + \param Databits : Number of data bits in one UART transmission. + + \n Supported values: \n + - SERIAL_DATABITS_5 (5) + - SERIAL_DATABITS_6 (6) + - SERIAL_DATABITS_7 (7) + - SERIAL_DATABITS_8 (8) + - SERIAL_DATABITS_16 (16) (not supported on Unix) + + \param Parity: Parity type + + \n Supported values: \n + - SERIAL_PARITY_NONE (N) + - SERIAL_PARITY_EVEN (E) + - SERIAL_PARITY_ODD (O) + - SERIAL_PARITY_MARK (MARK) (not supported on Unix) + - SERIAL_PARITY_SPACE (SPACE) (not supported on Unix) + \param Stopbit: Number of stop bits + + \n Supported values: + - SERIAL_STOPBITS_1 (1) + - SERIAL_STOPBITS_1_5 (1.5) (not supported on Unix) + - SERIAL_STOPBITS_2 (2) + + \return 1 success + \return -1 device not found + \return -2 error while opening the device + \return -3 error while getting port parameters + \return -4 Speed (Bauds) not recognized + \return -5 error while writing port parameters + \return -6 error while writing timeout parameters + \return -7 Databits not recognized + \return -8 Stopbits not recognized + \return -9 Parity not recognized + */ +char serialib::openDevice(const char *Device, const unsigned int Bauds, + SerialDataBits Databits, + SerialParity Parity, + SerialStopBits Stopbits) { +#if defined (_WIN32) || defined( _WIN64) + // Open serial port + hSerial = CreateFileA(Device,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,/*FILE_ATTRIBUTE_NORMAL*/0,0); + if(hSerial==INVALID_HANDLE_VALUE) { + if(GetLastError()==ERROR_FILE_NOT_FOUND) + return -1; // Device not found + + // Error while opening the device + return -2; + } + + // Set parameters + + // Structure for the port parameters + DCB dcbSerialParams; + dcbSerialParams.DCBlength=sizeof(dcbSerialParams); + + // Get the port parameters + if (!GetCommState(hSerial, &dcbSerialParams)) return -3; + + // Set the speed (Bauds) + switch (Bauds) + { + case 110 : dcbSerialParams.BaudRate=CBR_110; break; + case 300 : dcbSerialParams.BaudRate=CBR_300; break; + case 600 : dcbSerialParams.BaudRate=CBR_600; break; + case 1200 : dcbSerialParams.BaudRate=CBR_1200; break; + case 2400 : dcbSerialParams.BaudRate=CBR_2400; break; + case 4800 : dcbSerialParams.BaudRate=CBR_4800; break; + case 9600 : dcbSerialParams.BaudRate=CBR_9600; break; + case 14400 : dcbSerialParams.BaudRate=CBR_14400; break; + case 19200 : dcbSerialParams.BaudRate=CBR_19200; break; + case 38400 : dcbSerialParams.BaudRate=CBR_38400; break; + case 56000 : dcbSerialParams.BaudRate=CBR_56000; break; + case 57600 : dcbSerialParams.BaudRate=CBR_57600; break; + case 115200 : dcbSerialParams.BaudRate=CBR_115200; break; + case 128000 : dcbSerialParams.BaudRate=CBR_128000; break; + case 256000 : dcbSerialParams.BaudRate=CBR_256000; break; + default : return -4; + } + //select data size + BYTE bytesize = 0; + switch(Databits) { + case SERIAL_DATABITS_5: bytesize = 5; break; + case SERIAL_DATABITS_6: bytesize = 6; break; + case SERIAL_DATABITS_7: bytesize = 7; break; + case SERIAL_DATABITS_8: bytesize = 8; break; + case SERIAL_DATABITS_16: bytesize = 16; break; + default: return -7; + } + BYTE stopBits = 0; + switch(Stopbits) { + case SERIAL_STOPBITS_1: stopBits = ONESTOPBIT; break; + case SERIAL_STOPBITS_1_5: stopBits = ONE5STOPBITS; break; + case SERIAL_STOPBITS_2: stopBits = TWOSTOPBITS; break; + default: return -8; + } + BYTE parity = 0; + switch(Parity) { + case SERIAL_PARITY_NONE: parity = NOPARITY; break; + case SERIAL_PARITY_EVEN: parity = EVENPARITY; break; + case SERIAL_PARITY_ODD: parity = ODDPARITY; break; + case SERIAL_PARITY_MARK: parity = MARKPARITY; break; + case SERIAL_PARITY_SPACE: parity = SPACEPARITY; break; + default: return -9; + } + // configure byte size + dcbSerialParams.ByteSize = bytesize; + // configure stop bits + dcbSerialParams.StopBits = stopBits; + // configure parity + dcbSerialParams.Parity = parity; + + // Write the parameters + if(!SetCommState(hSerial, &dcbSerialParams)) return -5; + + // Set TimeOut + + // Set the Timeout parameters + timeouts.ReadIntervalTimeout=0; + // No TimeOut + timeouts.ReadTotalTimeoutConstant=MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier=0; + timeouts.WriteTotalTimeoutConstant=MAXDWORD; + timeouts.WriteTotalTimeoutMultiplier=0; + + // Write the parameters + if(!SetCommTimeouts(hSerial, &timeouts)) return -6; + + // Opening successfull + return 1; +#endif +#if defined (__linux__) || defined(__APPLE__) + // Structure with the device's options + struct termios options; + + + // Open device + fd = open(Device, O_RDWR | O_NOCTTY | O_NDELAY); + // If the device is not open, return -1 + if (fd == -1) return -2; + // Open the device in nonblocking mode + fcntl(fd, F_SETFL, FNDELAY); + + + // Get the current options of the port + tcgetattr(fd, &options); + // Clear all the options + bzero(&options, sizeof(options)); + + // Prepare speed (Bauds) + speed_t Speed; + switch (Bauds) + { + case 110 : Speed=B110; break; + case 300 : Speed=B300; break; + case 600 : Speed=B600; break; + case 1200 : Speed=B1200; break; + case 2400 : Speed=B2400; break; + case 4800 : Speed=B4800; break; + case 9600 : Speed=B9600; break; + case 19200 : Speed=B19200; break; + case 38400 : Speed=B38400; break; + case 57600 : Speed=B57600; break; + case 115200 : Speed=B115200; break; +#if defined (B230400) + case 230400 : Speed=B230400; break; +#endif +#if defined (B460800) + case 460800 : Speed=B460800; break; +#endif +#if defined (B500000) + case 500000 : Speed=B500000; break; +#endif +#if defined (B576000) + case 576000 : Speed=B576000; break; +#endif +#if defined (B921600) + case 921600 : Speed=B921600; break; +#endif +#if defined (B1000000) + case 1000000 : Speed=B1000000; break; +#endif +#if defined (B1152000) + case 1152000 : Speed=B1152000; break; +#endif +#if defined (B1500000) + case 1500000 : Speed=B1500000; break; +#endif +#if defined (B2000000) + case 2000000 : Speed=B2000000; break; +#endif +#if defined (B2500000) + case 2500000 : Speed=B2500000; break; +#endif +#if defined (B3000000) + case 3000000 : Speed=B3000000; break; +#endif +#if defined (B3500000) + case 3500000 : Speed=B3500000; break; +#endif +#if defined (B4000000) + case 4000000 : Speed=B4000000; break; +#endif + default : return -4; + } + int databits_flag = 0; + switch(Databits) { + case SERIAL_DATABITS_5: databits_flag = CS5; break; + case SERIAL_DATABITS_6: databits_flag = CS6; break; + case SERIAL_DATABITS_7: databits_flag = CS7; break; + case SERIAL_DATABITS_8: databits_flag = CS8; break; + //16 bits and everything else not supported + default: return -7; + } + int stopbits_flag = 0; + switch(Stopbits) { + case SERIAL_STOPBITS_1: stopbits_flag = 0; break; + case SERIAL_STOPBITS_2: stopbits_flag = CSTOPB; break; + //1.5 stopbits and everything else not supported + default: return -8; + } + int parity_flag = 0; + switch(Parity) { + case SERIAL_PARITY_NONE: parity_flag = 0; break; + case SERIAL_PARITY_EVEN: parity_flag = PARENB; break; + case SERIAL_PARITY_ODD: parity_flag = (PARENB | PARODD); break; + //mark and space parity not supported + default: return -9; + } + + // Set the baud rate + cfsetispeed(&options, Speed); + cfsetospeed(&options, Speed); + // Configure the device : data bits, stop bits, parity, no control flow + // Ignore modem control lines (CLOCAL) and Enable receiver (CREAD) + options.c_cflag |= ( CLOCAL | CREAD | databits_flag | parity_flag | stopbits_flag); + options.c_iflag |= ( IGNPAR | IGNBRK ); + // Timer unused + options.c_cc[VTIME]=0; + // At least on character before satisfy reading + options.c_cc[VMIN]=0; + // Activate the settings + tcsetattr(fd, TCSANOW, &options); + // Success + return (1); +#endif + +} + +bool serialib::isDeviceOpen() +{ +#if defined (_WIN32) || defined( _WIN64) + return hSerial != INVALID_HANDLE_VALUE; +#endif +#if defined (__linux__) || defined(__APPLE__) + return fd >= 0; +#endif +} + +/*! + \brief Close the connection with the current device +*/ +void serialib::closeDevice() +{ +#if defined (_WIN32) || defined( _WIN64) + CloseHandle(hSerial); + hSerial = INVALID_HANDLE_VALUE; +#endif +#if defined (__linux__) || defined(__APPLE__) + close (fd); + fd = -1; +#endif +} + + + + +//___________________________________________ +// ::: Read/Write operation on characters ::: + + + +/*! + \brief Write a char on the current serial port + \param Byte : char to send on the port (must be terminated by '\0') + \return 1 success + \return -1 error while writting data + */ +int serialib::writeChar(const char Byte) +{ +#if defined (_WIN32) || defined( _WIN64) + // Number of bytes written + DWORD dwBytesWritten; + // Write the char to the serial device + // Return -1 if an error occured + if(!WriteFile(hSerial,&Byte,1,&dwBytesWritten,NULL)) return -1; + // Write operation successfull + return 1; +#endif +#if defined (__linux__) || defined(__APPLE__) + // Write the char + if (write(fd,&Byte,1)!=1) return -1; + + // Write operation successfull + return 1; +#endif +} + + + +//________________________________________ +// ::: Read/Write operation on strings ::: + + +/*! + \brief Write a string on the current serial port + \param receivedString : string to send on the port (must be terminated by '\0') + \return 1 success + \return -1 error while writting data + */ +int serialib::writeString(const char *receivedString) +{ +#if defined (_WIN32) || defined( _WIN64) + // Number of bytes written + DWORD dwBytesWritten; + // Write the string + if(!WriteFile(hSerial,receivedString,strlen(receivedString),&dwBytesWritten,NULL)) + // Error while writing, return -1 + return -1; + // Write operation successfull + return 1; +#endif +#if defined (__linux__) || defined(__APPLE__) + // Lenght of the string + int Lenght=strlen(receivedString); + // Write the string + if (write(fd,receivedString,Lenght)!=Lenght) return -1; + // Write operation successfull + return 1; +#endif +} + +// _____________________________________ +// ::: Read/Write operation on bytes ::: + + + +/*! + \brief Write an array of data on the current serial port + \param Buffer : array of bytes to send on the port + \param NbBytes : number of byte to send + \return 1 success + \return -1 error while writting data + */ +int serialib::writeBytes(const void *Buffer, unsigned int NbBytes) +{ +#if defined (_WIN32) || defined( _WIN64) + // Number of bytes written + DWORD dwBytesWritten; + // Write data + if(!WriteFile(hSerial, Buffer, NbBytes, &dwBytesWritten, NULL)) + // Error while writing, return -1 + return -1; + // Write operation successfull + return 1; +#endif +#if defined (__linux__) || defined(__APPLE__) + // Write data + ssize_t writting = 0; + while(NbBytes) + { + writting = write(fd, Buffer, NbBytes); + if(writting >= 0) + { + NbBytes -= writting; + Buffer += writting; + }else { + usleep(5000); + } + } + // Write operation successfull + return 1; +#endif +} + + + +/*! + \brief Wait for a byte from the serial device and return the data read + \param pByte : data read on the serial device + \param timeOut_ms : delay of timeout before giving up the reading + If set to zero, timeout is disable (Optional) + \return 1 success + \return 0 Timeout reached + \return -1 error while setting the Timeout + \return -2 error while reading the byte + */ +int serialib::readChar(char *pByte,unsigned int timeOut_ms) +{ +#if defined (_WIN32) || defined(_WIN64) + // Number of bytes read + DWORD dwBytesRead = 0; + + // Set the TimeOut + timeouts.ReadTotalTimeoutConstant=timeOut_ms; + + // Write the parameters, return -1 if an error occured + if(!SetCommTimeouts(hSerial, &timeouts)) return -1; + + // Read the byte, return -2 if an error occured + if(!ReadFile(hSerial,pByte, 1, &dwBytesRead, NULL)) return -2; + + // Return 0 if the timeout is reached + if (dwBytesRead==0) return 0; + + // The byte is read + return 1; +#endif +#if defined (__linux__) || defined(__APPLE__) + // Timer used for timeout + timeOut timer; + // Initialise the timer + timer.initTimer(); + // While Timeout is not reached + while (timer.elapsedTime_ms()0 success, return the number of bytes read + \return -1 error while setting the Timeout + \return -2 error while reading the byte + \return -3 MaxNbBytes is reached + */ +int serialib::readStringNoTimeOut(char *receivedString,char finalChar,unsigned int maxNbBytes) +{ + // Number of characters read + unsigned int NbBytes=0; + // Returned value from Read + char charRead; + + // While the buffer is not full + while (NbBytes0 success, return the number of bytes read (including the null character) + \return 0 timeout is reached + \return -1 error while setting the Timeout + \return -2 error while reading the character + \return -3 MaxNbBytes is reached + */ +int serialib::readString(char *receivedString,char finalChar,unsigned int maxNbBytes,unsigned int timeOut_ms) +{ + // Check if timeout is requested + if (timeOut_ms==0) return readStringNoTimeOut(receivedString,finalChar,maxNbBytes); + + // Number of bytes read + unsigned int nbBytes=0; + // Character read on serial device + char charRead; + // Timer used for timeout + timeOut timer; + long int timeOutParam; + + // Initialize the timer (for timeout) + timer.initTimer(); + + // While the buffer is not full + while (nbBytes0) + { + // Wait for a byte on the serial link with the remaining time as timeout + charRead=readChar(&receivedString[nbBytes],timeOutParam); + + // If a byte has been received + if (charRead==1) + { + // Check if the character received is the final one + if (receivedString[nbBytes]==finalChar) + { + // Final character: add the end character 0 + receivedString [++nbBytes]=0; + // Return the number of bytes read + return nbBytes; + } + // This is not the final character, just increase the number of bytes read + nbBytes++; + } + // Check if an error occured during reading char + // If an error occurend, return the error number + if (charRead<0) return charRead; + } + // Check if timeout is reached + if (timer.elapsedTime_ms()>timeOut_ms) + { + // Add the end caracter + receivedString[nbBytes]=0; + // Return 0 (timeout reached) + return 0; + } + } + + // Buffer is full : return -3 + return -3; +} + + +/*! + \brief Read an array of bytes from the serial device (with timeout) + \param buffer : array of bytes read from the serial device + \param maxNbBytes : maximum allowed number of bytes read + \param timeOut_ms : delay of timeout before giving up the reading + \param sleepDuration_us : delay of CPU relaxing in microseconds (Linux only) + In the reading loop, a sleep can be performed after each reading + This allows CPU to perform other tasks + \return >=0 return the number of bytes read before timeout or + requested data is completed + \return -1 error while setting the Timeout + \return -2 error while reading the byte + */ +int serialib::readBytes (void *buffer,unsigned int maxNbBytes,unsigned int timeOut_ms, unsigned int sleepDuration_us) +{ +#if defined (_WIN32) || defined(_WIN64) + // Avoid warning while compiling + UNUSED(sleepDuration_us); + + // Number of bytes read + DWORD dwBytesRead = 0; + + // Set the TimeOut + timeouts.ReadTotalTimeoutConstant=(DWORD)timeOut_ms; + + // Write the parameters and return -1 if an error occrured + if(!SetCommTimeouts(hSerial, &timeouts)) return -1; + + + // Read the bytes from the serial device, return -2 if an error occured + if(!ReadFile(hSerial,buffer,(DWORD)maxNbBytes,&dwBytesRead, NULL)) return -2; + + // Return the byte read + return dwBytesRead; +#endif +#if defined (__linux__) || defined(__APPLE__) + // Timer used for timeout + timeOut timer; + // Initialise the timer + timer.initTimer(); + unsigned int NbByteRead=0; + // While Timeout is not reached + while (timer.elapsedTime_ms()0) + { + // Increase the number of read bytes + NbByteRead+=Ret; + // Success : bytes has been read + if (NbByteRead>=maxNbBytes) + return NbByteRead; + } + // Suspend the loop to avoid charging the CPU + usleep (sleepDuration_us); + } + // Timeout reached, return the number of bytes read + return NbByteRead; +#endif +} + + + + +// _________________________ +// ::: Special operation ::: + + + +/*! + \brief Empty receiver buffer + Note that when using serial over USB on Unix systems, a delay of 20ms may be necessary before calling the flushReceiver function + \return If the function succeeds, the return value is nonzero. + If the function fails, the return value is zero. +*/ +char serialib::flushReceiver() +{ +#if defined (_WIN32) || defined(_WIN64) + // Purge receiver + return PurgeComm (hSerial, PURGE_RXCLEAR); +#endif +#if defined (__linux__) || defined(__APPLE__) + // Purge receiver + tcflush(fd,TCIFLUSH); + return true; +#endif +} + + + +/*! + \brief Return the number of bytes in the received buffer (UNIX only) + \return The number of bytes received by the serial provider but not yet read. +*/ +int serialib::available() +{ +#if defined (_WIN32) || defined(_WIN64) + // Device errors + DWORD commErrors; + // Device status + COMSTAT commStatus; + // Read status + ClearCommError(hSerial, &commErrors, &commStatus); + // Return the number of pending bytes + return commStatus.cbInQue; +#endif +#if defined (__linux__) || defined(__APPLE__) + int nBytes=0; + // Return number of pending bytes in the receiver + ioctl(fd, FIONREAD, &nBytes); + return nBytes; +#endif + +} + +int serialib::waitAvailable(int timeOut) +{ + #if defined (_WIN32) || defined(_WIN64) + + return 0; +#endif + #if defined (__linux__) || defined(__APPLE__) + pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN | POLLRDNORM; + if (poll(&pfd, 1, timeOut) > 0) + { + return pfd.revents; + }else{ + return -1; + } +#endif +} + + + +// __________________ +// ::: I/O Access ::: + +/*! + \brief Set or unset the bit DTR (pin 4) + DTR stands for Data Terminal Ready + Convenience method :This method calls setDTR and clearDTR + \param status = true set DTR + status = false unset DTR + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::DTR(bool status) +{ + if (status) + // Set DTR + return this->setDTR(); + else + // Unset DTR + return this->clearDTR(); +} + + +/*! + \brief Set the bit DTR (pin 4) + DTR stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::setDTR() +{ +#if defined (_WIN32) || defined(_WIN64) + // Set DTR + currentStateDTR=true; + return EscapeCommFunction(hSerial,SETDTR); +#endif +#if defined (__linux__) || defined(__APPLE__) + // Set DTR + int status_DTR=0; + ioctl(fd, TIOCMGET, &status_DTR); + status_DTR |= TIOCM_DTR; + ioctl(fd, TIOCMSET, &status_DTR); + return true; +#endif +} + +/*! + \brief Clear the bit DTR (pin 4) + DTR stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::clearDTR() +{ +#if defined (_WIN32) || defined(_WIN64) + // Clear DTR + currentStateDTR=true; + return EscapeCommFunction(hSerial,CLRDTR); +#endif +#if defined (__linux__) || defined(__APPLE__) + // Clear DTR + int status_DTR=0; + ioctl(fd, TIOCMGET, &status_DTR); + status_DTR &= ~TIOCM_DTR; + ioctl(fd, TIOCMSET, &status_DTR); + return true; +#endif +} + + + +/*! + \brief Set or unset the bit RTS (pin 7) + RTS stands for Data Termina Ready + Convenience method :This method calls setDTR and clearDTR + \param status = true set DTR + status = false unset DTR + \return false if the function fails + \return true if the function succeeds +*/ +bool serialib::RTS(bool status) +{ + if (status) + // Set RTS + return this->setRTS(); + else + // Unset RTS + return this->clearRTS(); +} + + +/*! + \brief Set the bit RTS (pin 7) + RTS stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::setRTS() +{ +#if defined (_WIN32) || defined(_WIN64) + // Set RTS + currentStateRTS=false; + return EscapeCommFunction(hSerial,SETRTS); +#endif +#if defined (__linux__) || defined(__APPLE__) + // Set RTS + int status_RTS=0; + ioctl(fd, TIOCMGET, &status_RTS); + status_RTS |= TIOCM_RTS; + ioctl(fd, TIOCMSET, &status_RTS); + return true; +#endif +} + + + +/*! + \brief Clear the bit RTS (pin 7) + RTS stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::clearRTS() +{ +#if defined (_WIN32) || defined(_WIN64) + // Clear RTS + currentStateRTS=false; + return EscapeCommFunction(hSerial,CLRRTS); +#endif +#if defined (__linux__) || defined(__APPLE__) + // Clear RTS + int status_RTS=0; + ioctl(fd, TIOCMGET, &status_RTS); + status_RTS &= ~TIOCM_RTS; + ioctl(fd, TIOCMSET, &status_RTS); + return true; +#endif +} + + + + +/*! + \brief Get the CTS's status (pin 8) + CTS stands for Clear To Send + \return Return true if CTS is set otherwise false + */ +bool serialib::isCTS() +{ +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_CTS_ON; +#endif +#if defined (__linux__) || defined(__APPLE__) + int status=0; + //Get the current status of the CTS bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_CTS; +#endif +} + + + +/*! + \brief Get the DSR's status (pin 6) + DSR stands for Data Set Ready + \return Return true if DTR is set otherwise false + */ +bool serialib::isDSR() +{ +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_DSR_ON; +#endif +#if defined (__linux__) || defined(__APPLE__) + int status=0; + //Get the current status of the DSR bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_DSR; +#endif +} + + + + + + +/*! + \brief Get the DCD's status (pin 1) + CDC stands for Data Carrier Detect + \return true if DCD is set + \return false otherwise + */ +bool serialib::isDCD() +{ +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_RLSD_ON; +#endif +#if defined (__linux__) || defined(__APPLE__) + int status=0; + //Get the current status of the DCD bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_CAR; +#endif +} + + +/*! + \brief Get the RING's status (pin 9) + Ring Indicator + \return Return true if RING is set otherwise false + */ +bool serialib::isRI() +{ +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_RING_ON; +#endif +#if defined (__linux__) || defined(__APPLE__) + int status=0; + //Get the current status of the RING bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_RNG; +#endif +} + + +/*! + \brief Get the DTR's status (pin 4) + DTR stands for Data Terminal Ready + May behave abnormally on Windows + \return Return true if CTS is set otherwise false + */ +bool serialib::isDTR() +{ +#if defined (_WIN32) || defined( _WIN64) + return currentStateDTR; +#endif +#if defined (__linux__) || defined(__APPLE__) + int status=0; + //Get the current status of the DTR bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_DTR ; +#endif +} + + + +/*! + \brief Get the RTS's status (pin 7) + RTS stands for Request To Send + May behave abnormally on Windows + \return Return true if RTS is set otherwise false + */ +bool serialib::isRTS() +{ +#if defined (_WIN32) || defined(_WIN64) + return currentStateRTS; +#endif +#if defined (__linux__) || defined(__APPLE__) + int status=0; + //Get the current status of the CTS bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_RTS; +#endif +} + + + + + + +// ****************************************** +// Class timeOut +// ****************************************** + + +/*! + \brief Constructor of the class timeOut. +*/ +// Constructor +timeOut::timeOut() +{} + + +/*! + \brief Initialise the timer. It writes the current time of the day in the structure PreviousTime. +*/ +//Initialize the timer +void timeOut::initTimer() +{ +#if defined (NO_POSIX_TIME) + LARGE_INTEGER tmp; + QueryPerformanceFrequency(&tmp); + counterFrequency = tmp.QuadPart; + // Used to store the previous time (for computing timeout) + QueryPerformanceCounter(&tmp); + previousTime = tmp.QuadPart; +#else + gettimeofday(&previousTime, NULL); +#endif +} + +/*! + \brief Returns the time elapsed since initialization. It write the current time of the day in the structure CurrentTime. + Then it returns the difference between CurrentTime and PreviousTime. + \return The number of microseconds elapsed since the functions InitTimer was called. + */ +//Return the elapsed time since initialization +unsigned long int timeOut::elapsedTime_ms() +{ +#if defined (NO_POSIX_TIME) + // Current time + LARGE_INTEGER CurrentTime; + // Number of ticks since last call + int sec; + + // Get current time + QueryPerformanceCounter(&CurrentTime); + + // Compute the number of ticks elapsed since last call + sec=CurrentTime.QuadPart-previousTime; + + // Return the elapsed time in milliseconds + return sec/(counterFrequency/1000); +#else + // Current time + struct timeval CurrentTime; + // Number of seconds and microseconds since last call + int sec,usec; + + // Get current time + gettimeofday(&CurrentTime, NULL); + + // Compute the number of seconds and microseconds elapsed since last call + sec=CurrentTime.tv_sec-previousTime.tv_sec; + usec=CurrentTime.tv_usec-previousTime.tv_usec; + + // If the previous usec is higher than the current one + if (usec<0) + { + // Recompute the microseonds and substract one second + usec=1000000-previousTime.tv_usec+CurrentTime.tv_usec; + sec--; + } + + // Return the elapsed time in milliseconds + return sec*1000+usec/1000; +#endif +} diff --git a/zynq_7010_code/serialib.h b/zynq_7010_code/serialib.h new file mode 100644 index 0000000..4b56838 --- /dev/null +++ b/zynq_7010_code/serialib.h @@ -0,0 +1,270 @@ +/*! +\file serialib.h +\brief Header file of the class serialib. This class is used for communication over a serial device. +\author Philippe Lucidarme (University of Angers) +\version 2.0 +\date december the 27th of 2019 +This Serial library is used to communicate through serial port. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +This is a licence-free software, it can be used by anyone who try to build a better world. +*/ + + +#ifndef SERIALIB_H +#define SERIALIB_H + +#if defined(__CYGWIN__) + // This is Cygwin special case + #include +#endif + +// Include for windows +#if defined (_WIN32) || defined (_WIN64) +#if defined(__GNUC__) + // This is MinGW special case + #include +#else + // sys/time.h does not exist on "actual" Windows + #define NO_POSIX_TIME +#endif + // Accessing to the serial port under Windows + #include +#endif + +// Include for Linux +#if defined (__linux__) || defined(__APPLE__) + #include + #include + #include + #include + #include + #include + #include + // File control definitions + #include + #include + #include + #include +#endif + +/*! To avoid unused parameters */ +#define UNUSED(x) (void)(x) + +/** + * number of serial data bits + */ +enum SerialDataBits { + SERIAL_DATABITS_5, /**< 5 databits */ + SERIAL_DATABITS_6, /**< 6 databits */ + SERIAL_DATABITS_7, /**< 7 databits */ + SERIAL_DATABITS_8, /**< 8 databits */ + SERIAL_DATABITS_16, /**< 16 databits */ +}; + +/** + * number of serial stop bits + */ +enum SerialStopBits { + SERIAL_STOPBITS_1, /**< 1 stop bit */ + SERIAL_STOPBITS_1_5, /**< 1.5 stop bits */ + SERIAL_STOPBITS_2, /**< 2 stop bits */ +}; + +/** + * type of serial parity bits + */ +enum SerialParity { + SERIAL_PARITY_NONE, /**< no parity bit */ + SERIAL_PARITY_EVEN, /**< even parity bit */ + SERIAL_PARITY_ODD, /**< odd parity bit */ + SERIAL_PARITY_MARK, /**< mark parity */ + SERIAL_PARITY_SPACE /**< space bit */ +}; + +/*! \class serialib + \brief This class is used for communication over a serial device. +*/ +class serialib +{ +public: + + //_____________________________________ + // ::: Constructors and destructors ::: + + + + // Constructor of the class + serialib (); + + // Destructor + ~serialib (); + + + + //_________________________________________ + // ::: Configuration and initialization ::: + + + // Open a device + char openDevice(const char *Device, const unsigned int Bauds, + SerialDataBits Databits = SERIAL_DATABITS_8, + SerialParity Parity = SERIAL_PARITY_NONE, + SerialStopBits Stopbits = SERIAL_STOPBITS_1); + + // Check device opening state + bool isDeviceOpen(); + + // Close the current device + void closeDevice(); + + + + + //___________________________________________ + // ::: Read/Write operation on characters ::: + + + // Write a char + int writeChar (char); + + // Read a char (with timeout) + int readChar (char *pByte,const unsigned int timeOut_ms=0); + + + + + //________________________________________ + // ::: Read/Write operation on strings ::: + + + // Write a string + int writeString (const char *String); + + // Read a string (with timeout) + int readString ( char *receivedString, + char finalChar, + unsigned int maxNbBytes, + const unsigned int timeOut_ms=0); + + + + // _____________________________________ + // ::: Read/Write operation on bytes ::: + + + // Write an array of bytes + int writeBytes (const void *Buffer, unsigned int NbBytes); + + // Read an array of byte (with timeout) + int readBytes (void *buffer,unsigned int maxNbBytes,const unsigned int timeOut_ms=0, unsigned int sleepDuration_us=100); + + + + + // _________________________ + // ::: Special operation ::: + + + // Empty the received buffer + char flushReceiver(); + + // Return the number of bytes in the received buffer + int available(); + + + int waitAvailable(int timeOut); + + // _________________________ + // ::: Access to IO bits ::: + + + // Set CTR status (Data Terminal Ready, pin 4) + bool DTR(bool status); + bool setDTR(); + bool clearDTR(); + + // Set RTS status (Request To Send, pin 7) + bool RTS(bool status); + bool setRTS(); + bool clearRTS(); + + // Get RI status (Ring Indicator, pin 9) + bool isRI(); + + // Get DCD status (Data Carrier Detect, pin 1) + bool isDCD(); + + // Get CTS status (Clear To Send, pin 8) + bool isCTS(); + + // Get DSR status (Data Set Ready, pin 9) + bool isDSR(); + + // Get RTS status (Request To Send, pin 7) + bool isRTS(); + + // Get CTR status (Data Terminal Ready, pin 4) + bool isDTR(); + + +private: + // Read a string (no timeout) + int readStringNoTimeOut (char *String,char FinalChar,unsigned int MaxNbBytes); + + // Current DTR and RTS state (can't be read on WIndows) + bool currentStateRTS; + bool currentStateDTR; + + + + + +#if defined (_WIN32) || defined( _WIN64) + // Handle on serial device + HANDLE hSerial; + // For setting serial port timeouts + COMMTIMEOUTS timeouts; +#endif +#if defined (__linux__) || defined(__APPLE__) + int fd; +#endif + +}; + + + +/*! \class timeOut + \brief This class can manage a timer which is used as a timeout. + */ +// Class timeOut +class timeOut +{ +public: + + // Constructor + timeOut(); + + // Init the timer + void initTimer(); + + // Return the elapsed time since initialization + unsigned long int elapsedTime_ms(); + +private: +#if defined (NO_POSIX_TIME) + // Used to store the previous time (for computing timeout) + LONGLONG counterFrequency; + LONGLONG previousTime; +#else + // Used to store the previous time (for computing timeout) + struct timeval previousTime; +#endif +}; + +#endif // serialib_H