diff --git a/hardware/cis/FpgaComm.cpp b/hardware/cis/FpgaComm.cpp new file mode 100644 index 0000000..b61dde2 --- /dev/null +++ b/hardware/cis/FpgaComm.cpp @@ -0,0 +1,360 @@ +// +// Created by Nick on 2019/4/7. +// +#include "FpgaComm.h" + +#include +#include "../uart/uartregsaccess.h" +#include + +#define Reg(x) (fpgaParams.x) +#define RegIndex(x) (std::distance((unsigned int*)&fpgaParams, (unsigned int*)&fpgaParams.x)) +#define ReadReg(x) read(RegIndex(x), *((unsigned int*)&fpgaParams.x)) +#define WriteReg(x) write(RegIndex(x), *((unsigned int*)&fpgaParams.x)) +#define WR_Reg(x) (WriteReg(x),ReadReg(x)) + +#define CO(x) std::cout << #x << " : "<< RegIndex(x) << std::endl + +FpgaComm::FpgaComm(int bauds) : bauds_(bauds) +{ + m_regsAccess.reset(new UartRegsAccess(FPGA_UART, bauds_, 0x03, 0x83)); + update(); + + Reg(AledR).sample = 256; + WR_Reg(AledR); +} + +bool FpgaComm::read(unsigned int addr, unsigned int& val) { + return m_regsAccess->read(addr, val); +} + +bool FpgaComm::write(unsigned int addr, unsigned int val) { + return m_regsAccess->write(addr, val); +} + +void FpgaComm::regsAccess_reset(bool enable){ + if(enable) + { + if(!m_regsAccess.get()) + m_regsAccess.reset(new UartRegsAccess(FPGA_UART, bauds_, 0x03, 0x83)); + update(); + return; + } + if(m_regsAccess.get()) + m_regsAccess.reset(); +} + +void FpgaComm::setFrameHeight(int height){ + Reg(frame).height = height; + WR_Reg(frame); +} + +int FpgaComm::getFrameHeight() +{ + return Reg(frame).height; +} + +void FpgaComm::setFrameNum(int num){ + Reg(frame).num = num; + WR_Reg(frame); +} + +void FpgaComm::enableLed(bool bEnable) { + Reg(AledR).ledEnable = bEnable; + WR_Reg(AledR); +#ifdef HAS_UV + Reg(BledR).ledEnable = bEnable; + WR_Reg(BledR); +#else + Reg(BledR).ledEnable = bEnable; + WR_Reg(BledR); +#endif +} + +void FpgaComm::enableUV(bool enable){ +#ifdef HAS_UV + isUVEnable = enable; + Reg(BledR).ledEnable = isUVEnable; + WR_Reg(BledR); +#endif +} + +void FpgaComm::capture() { + Reg(cmd).cmd = 0; + WriteReg(cmd); + Reg(cmd).cmd = 1; + WriteReg(cmd); +} + +int FpgaComm::getRegs(int addr) { + return fpgaParams.regs[addr]; +} + +void FpgaComm::setRegs(int addr, int value) { + fpgaParams.regs[addr] = value; + write(addr, value); + read(addr, fpgaParams.regs[addr]); +} + +void FpgaComm::setAGain(int indexGain, int value) { + int index = indexGain; + int val;// = value + value>=511?val=511:val=value; + index++; + fpgaParams.Aad.ad0_addr = index*2; + fpgaParams.Aad.ad1_addr = fpgaParams.Aad.ad0_addr + 1; + fpgaParams.Aad.ad0_value = val; + fpgaParams.Aad.ad1_value = val>255?1:0; + fpgaParams.Aad.ad0_rw = 0; + fpgaParams.Aad.ad1_rw = 0; + write(0x04,*(int*)&fpgaParams.Aad); + Reg(mode).adcA = 1; + WriteReg(mode); + Reg(mode).adcA = 0; + WriteReg(mode); +} + +void FpgaComm::setBGain(int indexGain, int value) { + int index = indexGain; + int val;// = value + value>=511?val=511:val=value; + index++; + fpgaParams.Bad.ad0_addr = index*2; + fpgaParams.Bad.ad1_addr = index*2 + 1; + fpgaParams.Bad.ad0_value = val; + fpgaParams.Bad.ad1_value = val>255?1:0; + fpgaParams.Bad.ad0_rw = 0; + fpgaParams.Bad.ad1_rw = 0; + write(0x07,*(int*)&fpgaParams.Bad); + Reg(mode).adcB = 1; + WriteReg(mode); + Reg(mode).adcB = 0; + WriteReg(mode); +} + +void FpgaComm::setAOffset(int indexOffset, int value) { + Reg(Aad).ad0_rw = 0; + Reg(Aad).ad1_rw = 0; + Reg(Aad).ad0_addr = indexOffset + 0x0e; + Reg(Aad).ad1_addr = 0x14; + Reg(Aad).ad0_value = value; + WriteReg(Aad); + Reg(mode).adcA = 1; + WriteReg(mode); + Reg(mode).adcA = 0; + WriteReg(mode); +} + +void FpgaComm::setBOffset(int indexOffset, int value) { + Reg(Bad).ad0_rw = 0; + Reg(Bad).ad1_rw = 0; + Reg(Bad).ad0_addr = indexOffset + 0x0e; + Reg(Bad).ad1_addr = 0x14; + Reg(Bad).ad0_value = value; + WriteReg(Bad); + Reg(mode).adcB = 1; + WriteReg(mode); + Reg(mode).adcB = 0; + WriteReg(mode); +} + +void FpgaComm::setAExposureR(int value) { + Reg(AledR).ledR = value; + WR_Reg(AledR); +} + +void FpgaComm::setAExposureG(int value) { + Reg(AledGB).ledG = value; + WR_Reg(AledGB); +} + +void FpgaComm::setAExposureB(int value) { + Reg(AledGB).ledB = value; + WR_Reg(AledGB); +} + +void FpgaComm::setAExposureUV(int value){ +#ifdef HAS_UV + Reg(UVLed).ledASide = value; + WR_Reg(UVLed); +#endif +} + +void FpgaComm::setBExposureR(int value) { + Reg(BledR).ledR = value; + WR_Reg(BledR); +} + +void FpgaComm::setBExposureG(int value) { + Reg(BledGB).ledG = value; + WR_Reg(BledGB); +} + +void FpgaComm::setBExposureB(int value) { + Reg(BledGB).ledB = value; + WR_Reg(BledGB); +} + +void FpgaComm::setBExpousreUV(int value){ +#ifdef HAS_UV + Reg(UVLed).ledBSide = value; + WR_Reg(UVLed); +#endif +} + +void FpgaComm::setSp(int value) +{ + Reg(mode).sp = value; + WR_Reg(mode); +} + +int FpgaComm::getSp() +{ + return Reg(mode).sp; +} + +void FpgaComm::setColorMode(int mode) +{ + Reg(mode).colorMode = mode; + WR_Reg(mode); +} + +int FpgaComm::getColorMode() +{ + return Reg(mode).colorMode; +} + +void FpgaComm::setSample(int sample) +{ + Reg(mode).sample = sample; + WR_Reg(mode); + Reg(AledR).sample = sample; + WR_Reg(AledR); +} + + void FpgaComm::EnableTest(bool bTest) + { + Reg(mode).selftest = bTest; + WR_Reg(mode); + } + +int FpgaComm::IsTest() +{ + return Reg(mode).selftest; +} + +int FpgaComm::getSample() +{ + return Reg(mode).sample; +} + +void FpgaComm::setDpi(int dpi) +{ + Reg(mode).dpi = dpi; + WR_Reg(mode); +} + +int FpgaComm::getDpi() +{ + return Reg(mode).dpi; +} + +//20190626 YHP autoTrig function +void FpgaComm::setTrigMode(bool isArmMode) { + unsigned int tmp; + read(0x0b, tmp); + if(!isArmMode){ //default value+ ARM MODE,bit27 =0; + fpgaParams.TrigMode = tmp & 0XFBFFFFFF; + }else{ + fpgaParams.TrigMode = tmp |(1<<26); + } + WR_Reg(TrigMode); +} +void FpgaComm::setDelayTime(int value) { + Reg(DelayTime) = value; + WR_Reg(DelayTime); +} + +void FpgaComm::update() +{ + for(int i = 0; i < MAX_REGS; i++) + { + read(i, fpgaParams.regs[i]); + } +} + +void FpgaComm::enableJamCheck(bool b){ + //Reg(BledR).user_define.led_sample.jamEnable = b; + //WR_Regs(0x08); +} + +void FpgaComm::resetADC() { + + fpgaParams.Aad.ad0_rw = 0; + fpgaParams.Aad.ad0_addr = 0; + fpgaParams.Aad.ad0_value = 0; + fpgaParams.Aad.ad1_rw = 0; + fpgaParams.Aad.ad1_addr = 0; + fpgaParams.Aad.ad1_value = 0; + WR_Reg(Aad); + fpgaParams.mode.adcA = 1; + WR_Reg(mode); + fpgaParams.mode.adcA = 0; + WR_Reg(mode); + fpgaParams.Bad.ad0_rw = 0; + fpgaParams.Bad.ad0_addr = 0; + fpgaParams.Bad.ad0_value = 0; + fpgaParams.Bad.ad1_rw = 0; + fpgaParams.Bad.ad1_addr = 0; + fpgaParams.Bad.ad1_value = 0; + WR_Reg(Bad); + fpgaParams.mode.adcB = 1; + WR_Reg(mode); + fpgaParams.mode.adcB = 0; + WR_Reg(mode); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + fpgaParams.Aad.ad0_rw = 0; + fpgaParams.Aad.ad0_addr = 0; + fpgaParams.Aad.ad0_value = 7; + fpgaParams.Aad.ad1_rw = 0; + fpgaParams.Aad.ad1_addr = 0; + fpgaParams.Aad.ad1_value = 7; + WR_Reg(Aad); + fpgaParams.mode.adcA = 1; + WR_Reg(mode); + fpgaParams.mode.adcA = 0; + WR_Reg(mode); + fpgaParams.Bad.ad0_rw = 0; + fpgaParams.Bad.ad0_addr = 0; + fpgaParams.Bad.ad0_value = 7; + fpgaParams.Bad.ad1_rw = 0; + fpgaParams.Bad.ad1_addr = 0; + fpgaParams.Bad.ad1_value = 7; + WR_Reg(Bad); + fpgaParams.mode.adcB = 1; + WR_Reg(mode); + fpgaParams.mode.adcB = 0; + WR_Reg(mode); + fpgaParams.Aad.ad0_rw = 0; + fpgaParams.Aad.ad0_addr = 1; + fpgaParams.Aad.ad0_value = 0x50; + fpgaParams.Aad.ad1_rw = 0; + fpgaParams.Aad.ad1_addr = 1; + fpgaParams.Aad.ad1_value = 0x50; + WR_Reg(Aad); + fpgaParams.mode.adcA = 1; + WR_Reg(mode); + fpgaParams.mode.adcA = 0; + WR_Reg(mode); + fpgaParams.Bad.ad0_rw = 0; + fpgaParams.Bad.ad0_addr = 1; + fpgaParams.Bad.ad0_value = 0x50; + fpgaParams.Bad.ad1_rw = 0; + fpgaParams.Bad.ad1_addr = 1; + fpgaParams.Bad.ad1_value = 0x50; + WR_Reg(Bad); + fpgaParams.mode.adcB = 1; + WR_Reg(mode); + fpgaParams.mode.adcB = 0; + WR_Reg(mode); +} diff --git a/hardware/cis/FpgaComm.h b/hardware/cis/FpgaComm.h new file mode 100644 index 0000000..154d738 --- /dev/null +++ b/hardware/cis/FpgaComm.h @@ -0,0 +1,203 @@ +#pragma once +#include +#include +#include "../uart/regsaccess.h" + +#ifdef HAS_UV +#define MAX_REGS 0x0e +#else +#define MAX_REGS 0x0d +#endif + +typedef struct Frame_FPGA +{ + unsigned short int height; + unsigned short int num : 8; + unsigned short int reserved : 8; + +} FrameFpga; + +typedef struct Mode_FPGA +{ + unsigned short int colorMode : 1; + unsigned short int dpi : 2; + unsigned short int led : 1; + unsigned short sample : 9; + unsigned short int adcA : 1; + unsigned short int adcB : 1; + unsigned short int selftest : 1; + unsigned short int sp; +} ModeFpga; + +typedef struct CMD_FPGA +{ + unsigned int cmd : 1; //start : 1 , stop : 0 + unsigned int reserved : 31; +} CmdFpga; + +typedef struct STATUS_FPGA +{ + unsigned int status : 1; //start : 1 , stop : 0 + unsigned int reserved : 31; +} StatusFpga; + +typedef struct Ad_Gain +{ + unsigned short int gain_low8 : 8; + unsigned short int gain_hight : 1; + unsigned int reserved : 23; +} AdGain; + + +typedef struct CIS_AD_Gain +{ + unsigned short int ad0_value : 8; //!< 数据位 + unsigned short int ad0_reserved : 2; //!< 保留位 + unsigned short int ad0_addr : 5; //!< 寄存器地址 + unsigned short int ad0_rw : 1; //!< 读写位 1:读, 0:写 + unsigned short int ad1_value : 8; //!< 数据位 + unsigned short int ad1_reserved : 2; //!< 保留位 + unsigned short int ad1_addr : 5; //!< 寄存器地址 + unsigned short int ad1_rw : 1; //!< 读写位 1:读, 0:写; +} CisAdGain; + +typedef struct CIS_LED_RF +{ + unsigned short int ledEnable : 1; + unsigned short int fanMode : 2; + unsigned short int jamEnable : 1; + unsigned short int sample : 9; + unsigned short int reserved : 3; + unsigned short int ledR; +} CisLedRF; + +typedef struct CIS_LED_R +{ + unsigned short int ledEnable : 1; + unsigned short int sample : 9; + unsigned short int reserved : 6; + unsigned short int ledR; +} CisLedR; + +typedef struct CIS_LED_GB +{ + unsigned short int ledG; + unsigned short int ledB; +} CisLedGB; + +typedef struct CIS_LED_UV +{ + unsigned short int ledASide; + unsigned short int ledBSide; +} CisLedUv; + +typedef union Fpga_Params +{ + struct + { + FrameFpga frame; //0x00 + ModeFpga mode; //0x01 + CmdFpga cmd; //0x02 + StatusFpga status; //0x03 + CisAdGain Aad; //0x04 + CisLedR AledR; //0x05 + CisLedGB AledGB; //0x06 + CisAdGain Bad; //0x07 +#ifndef G300 + CisLedRF BledR; //0x08 +#else + CisLedR BledR; //0x08 +#endif + CisLedGB BledGB; //0x09 + unsigned int ExpIncr; //0x0a + unsigned int TrigMode; //0x0b + unsigned int DelayTime; //0x0c + CisLedUv UVLed; + }; + unsigned int regs[14]; +} FpgaParams; + +#define FPGA_UART "/dev/ttyUSB0" +#define MOTOR_UART "/dev/ttyS4" + +enum +{ + GRAY_MODE = 0, + COLOR_MODE, +}; +enum +{ + DPI_300 = 0, + DPI_200, +}; +enum +{ + CIS_GAIN_IND_COUNT = 6, +}; +enum +{ + CIS_OFFSET_IND_COUNT = 6, +}; + +class FpgaComm : public IRegsAccess +{ + int bauds_ = 921600; + +public: + FpgaComm(int bauds = 921600); + virtual ~FpgaComm(){} + + void reset(); + void regsAccess_reset(bool enable); + void setRegs(int addr, int value); + int getRegs(int addr); + void setFrameHeight(int height); + int getFrameHeight(); + void setFrameNum(int num); + void enableLed(bool bEnable); + void enableUV(bool enable); + void capture(); + void setAGain(int indexGain, int value); + void setBGain(int indexGain, int value); + void setAOffset(int indexOffset, int value); + void setBOffset(int indexOffset, int value); + + void setAExposureR(int value); + void setAExposureG(int value); + void setAExposureB(int value); + void setAExposureUV(int value); + + void setBExposureR(int value); + void setBExposureG(int value); + void setBExposureB(int value); + void setBExpousreUV(int value); + + void setSp(int value); + int getSp(); + + void EnableTest(bool bTest); + int IsTest(); + + void setColorMode(int mode); + int getColorMode(); + + void setDpi(int dpi); + int getDpi(); + + void setSample(int sample); + int getSample(); + + //20190626 YHP autoTrig function + void setDelayTime(int value); + void setTrigMode(bool isArmMode); + + void update(); + void enableJamCheck(bool b); + void resetADC(); + virtual bool write(unsigned int addr, unsigned int val); + virtual bool read(unsigned int addr, unsigned int& val); + +private: + FpgaParams fpgaParams; + std::shared_ptr m_regsAccess; +}; \ No newline at end of file diff --git a/hardware/hardware.cpp b/hardware/hardware.cpp new file mode 100644 index 0000000..95cdd6c --- /dev/null +++ b/hardware/hardware.cpp @@ -0,0 +1,198 @@ +#include "hardware.h" + +#include "./cis/FpgaComm.h" +#include +#include + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// scanner_hw +static std::string device_opt_json[] = { + "{\"mode\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u989c\\u8272\\u6a21\\u5f0f\",\"desc\":\"\\u9009\\u62e9\\u8272\\u5f69\\u6a21\\u5f0f\",\"type\":\"string\",\"fix-id\":34819,\"ui-pos\":10,\"auth\":0,\"size\":12,\"cur\":\"\\u5f69\\u8272\",\"default\":\"\\u5f69\\u8272\",\"range\":[\"\\u5f69\\u8272\",\"\\u7070\\u5ea6\"]},\"resolution\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5206\\u8fa8\\u7387\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u56fe\\u50cf\\u7684\\u5206\\u8fa8\\u7387\",\"type\":\"int\",\"fix-id\":34840,\"ui-pos\":11,\"auth\":0,\"size\":4,\"cur\":300,\"default\":300,\"range\":[200,300]},\"baud\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u6ce2\\u7279\\u7387\",\"desc\":\"CIS\\u63a7\\u5236\\u901a\\u4fe1\\u901f\\u7387\",\"type\":\"int\",\"ui-pos\":12,\"auth\":0,\"size\":4,\"cur\":921600,\"default\":921600,\"range\":[110,300,600,1200,2400,4800,9600,19200,38400,57600,115200,500000,921600,1500000]},\"act-after\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5ef6\\u8fdf\\u54cd\\u5e94\",\"desc\":\"\\u91c7\\u96c6\\u5934\\u63a5\\u53d7\\u547d\\u4ee4\\u540e\\u7684\\u52a8\\u4f5c\\u5ef6\\u8fdf\\u65f6\\u95f4\",\"type\":\"int\",\"ui-pos\":12,\"auth\":0,\"unit\":\"microsec\",\"size\":4,\"cur\":1000,\"default\":1000},\"fram-h\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u5e27\\u9ad8\\u5ea6\",\"desc\":\"\\u91c7\\u96c6\\u5934\\u6bcf\\u4e00\\u5e27\\u7684\\u91c7\\u96c6\\u9ad8\\u5ea6\",\"type\":\"int\",\"ui-pos\":13,\"auth\":0,\"size\":4,\"cur\":12,\"default\":12},\"sample\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u91c7\\u6837\\u9891\\u7387\",\"desc\":\"\\u91c7\\u6837\\u9891\\u7387\",\"type\":\"int\",\"ui-pos\":14,\"auth\":0,\"size\":4,\"cur\":256,\"default\":256},\"expo-fb\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u84dd\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u84dd\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":15,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-fg\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u7eff\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7eff\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":16,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-fr\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u6b63\\u9762\\u7ea2\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7ea2\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":17,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-bb\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u84dd\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u84dd\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":18,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-bg\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u7eff\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7eff\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":19,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"expo-br\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u66dd\\u5149\\u5ea6\\uff08\\u80cc\\u9762\\u7ea2\\u8272\\u901a\\u9053\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7ea2\\u8272\\u901a\\u9053\\u7684\\u66dd\\u5149\\u5f3a\\u5ea6\",\"type\":\"int\",\"ui-pos\":20,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"gain-f\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\uff08\\u6b63\\u9762\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7684\\u589e\\u76ca\\u91cf\",\"type\":\"int\",\"ui-pos\":21,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"gain-b\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u589e\\u76ca\\uff08\\u80cc\\u9762\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7684\\u589e\\u76ca\\u91cf\",\"type\":\"int\",\"ui-pos\":24,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":-1000,\"max\":1000,\"step\":1}},\"off-f\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u504f\\u79fb\\uff08\\u6b63\\u9762\\uff09\",\"desc\":\"\\u6b63\\u9762\\u7684\\u504f\\u79fb\\u91cf\",\"type\":\"int\",\"ui-pos\":27,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":0,\"max\":100,\"step\":1}},\"off-b\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"\\u504f\\u79fb\\uff08\\u80cc\\u9762\\uff09\",\"desc\":\"\\u80cc\\u9762\\u7684\\u504f\\u79fb\\u91cf\",\"type\":\"int\",\"ui-pos\":30,\"auth\":0,\"size\":4,\"cur\":0,\"default\":0,\"range\":{\"min\":0,\"max\":100,\"step\":1}}}" +}; + + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// scanner_hw +scanner_hw::scanner_hw() +{ + set_where("hardware"); + init(); +} +scanner_hw::~scanner_hw() +{ + close(); +} + +void scanner_hw::init(void) +{ + std::string text(""); + + for(auto& v: device_opt_json) + text += v; + + set_opt_json_text(&text[0]); + + auto m = [this](void* value) -> void + { + if(strcmp((char*)value, "\347\201\260\345\272\246") == 0) + mode_ = (char*)value; + else + mode_ = "\345\275\251\350\211\262"; + }; + auto r = [this](void* value) -> void + { + if(*(int*)value <= 200) + dpi_ = 200; + else + dpi_ = 300; + }; + auto b = [this](void* value) -> void + { + baud_ = *(int*)value; + }; + auto d = [this](void* value) -> void + { + delay_ = *(int*)value; + }; + auto f = [this](void* value) -> void + { + frame_h_ = *(int*)value; + }; + auto s = [this](void* value) -> void + { + sample_ = *(int*)value; + }; + + auto efb = [this](void* value) -> void + { + exposure_[SIDE_FRONT][COLOR_IND_BLUE] = *(int*)value; + }; + auto efg = [this](void* value) -> void + { + exposure_[SIDE_FRONT][COLOR_IND_GREEN] = *(int*)value; + }; + auto efr = [this](void* value) -> void + { + exposure_[SIDE_FRONT][COLOR_IND_RED] = *(int*)value; + }; + auto ebb = [this](void* value) -> void + { + exposure_[SIDE_BACK][COLOR_IND_BLUE] = *(int*)value; + }; + auto ebg = [this](void* value) -> void + { + exposure_[SIDE_BACK][COLOR_IND_GREEN] = *(int*)value; + }; + auto ebr = [this](void* value) -> void + { + exposure_[SIDE_BACK][COLOR_IND_RED] = *(int*)value; + }; + + auto gf = [this](void* value) -> void + { + gain_[SIDE_FRONT] = *(int*)value; + }; + auto gb = [this](void* value) -> void + { + gain_[SIDE_BACK] = *(int*)value; + }; + + auto of = [this](void* value) -> void + { + off_[SIDE_FRONT] = *(int*)value; + }; + auto ob = [this](void* value) -> void + { + off_[SIDE_BACK] = *(int*)value; + }; + + opt_handler_[SANE_FULL_NAME(COLOR_MODE)] = m; + opt_handler_[SANE_FULL_NAME(RESOLUTION)] = r; + opt_handler_[SANE_FULL_NAME(CIS_BAUD)] = b; + opt_handler_[SANE_FULL_NAME(CIS_DELAY)] = d; + opt_handler_[SANE_FULL_NAME(CIS_FRAME_H)] = f; + opt_handler_[SANE_FULL_NAME(CIS_SAMPLE)] = s; + + opt_handler_[SANE_FULL_NAME(CIS_EXPO_FB)] = efb; + opt_handler_[SANE_FULL_NAME(CIS_EXPO_FG)] = efg; + opt_handler_[SANE_FULL_NAME(CIS_EXPO_FR)] = efr; + opt_handler_[SANE_FULL_NAME(CIS_EXPO_BB)] = ebb; + opt_handler_[SANE_FULL_NAME(CIS_EXPO_BG)] = ebg; + opt_handler_[SANE_FULL_NAME(CIS_EXPO_BR)] = ebr; + + opt_handler_[SANE_FULL_NAME(CIS_GAIN_FRONT)] = gf; + opt_handler_[SANE_FULL_NAME(CIS_GAIN_BACK)] = gb; + + opt_handler_[SANE_FULL_NAME(CIS_OFFSET_FRONT)] = of; + opt_handler_[SANE_FULL_NAME(CIS_OFFSET_BACK)] = ob; +} + +// sane_opt_provider +char* scanner_hw::get_value(const char* name, void* value, size_t* size, int* err) +{ + char *ret = nullptr; + + return ret; +} +int scanner_hw::set_value(const char* name, void* val) +{ + if(opt_handler_.count(name)) + { + opt_handler_[name](val); + + return 0; + } + else + { + return SCANNER_ERR_DEVICE_NOT_SUPPORT; + } +} + +// operation ... +int scanner_hw::open(std::function image_handler) +{ + img_controller_.reset(new FpgaComm(baud_)); + + img_controller_->setColorMode(mode_ == "\345\275\251\350\211\262" ? COLOR_MODE : GRAY_MODE); + img_controller_->setDpi(dpi_ == 200 ? DPI_200 : DPI_300); + img_controller_->setFrameHeight(frame_h_); + img_controller_->setDelayTime(delay_); + img_controller_->setSample(sample_); + + void(FpgaComm::* exposure[])(int) = {&FpgaComm::setAExposureB, &FpgaComm::setAExposureG + , &FpgaComm::setAExposureR, &FpgaComm::setBExposureB, &FpgaComm::setBExposureG, &FpgaComm::setBExposureR}; + for(int i = 0; i < SIDE_COUNT; ++i) + { + for(int j = 0; j < COLOR_IND_COUNT; ++j) + (img_controller_.get()->*exposure[i * SIDE_COUNT + j])(exposure_[i][j]); + } + + for(int i = 0; i < CIS_GAIN_IND_COUNT; ++i) + img_controller_->setAGain(i, gain_[SIDE_FRONT]); + for(int i = 0; i < CIS_GAIN_IND_COUNT; ++i) + img_controller_->setBGain(i, gain_[SIDE_BACK]); + + for(int i = 0; i < CIS_OFFSET_IND_COUNT; ++i) + img_controller_->setAOffset(i, off_[SIDE_FRONT]); + for(int i = 0; i < CIS_OFFSET_IND_COUNT; ++i) + img_controller_->setBOffset(i, off_[SIDE_BACK]); + + return 0; +} +int scanner_hw::start_scan(void) +{ + return 0; +} +int scanner_hw::stop_scan(void) +{ + return 0; +} +int scanner_hw::close(void) +{ + if(img_controller_.get()) + { + img_controller_.reset(); + } + + return 0; +} diff --git a/hardware/hardware.h b/hardware/hardware.h new file mode 100644 index 0000000..a98461f --- /dev/null +++ b/hardware/hardware.h @@ -0,0 +1,326 @@ +// hardware drivers +// +// Contains: CIS, MotorBoard, ... +// +// Date: 2023-12-18 + +#include +#include +#include +#include +#include +#include + +// image handler callback proto +// +// dyn_mem_ptr: image data buffer, or be uint32_t if bool was false +// +// bool: true - image, dyn_mem_ptr is image data buffer; false - dyn_mem_ptr is an uint32_t code of hardware event +// +// LPPACKIMAGE: image information, ignored when bool is false +#define IMAGE_HANDLER_PROTO void(dyn_mem_ptr, bool, LPPACKIMAGE) + +class FpgaComm; + +class scanner_hw : public sane_opt_provider +{ + std::function img_handler_; + bool scanning_ = false; + bool auto_scan_ = false; + std::unique_ptr img_controller_; + + enum + { + SIDE_FRONT = 0, + SIDE_BACK, + SIDE_COUNT, + }; + enum + { + COLOR_IND_BLUE = 0, + COLOR_IND_GREEN, + COLOR_IND_RED, + COLOR_IND_COUNT, + }; + std::string mode_; + int dpi_ = 300; + int baud_ = 921600; + int delay_ = 1000; + int frame_h_ = 12; + int sample_ = 256; + int exposure_[SIDE_COUNT][COLOR_IND_COUNT]; + int gain_[SIDE_COUNT]; + int off_[SIDE_COUNT]; + std::map> opt_handler_; + + + void init(void); + +public: + scanner_hw(); +protected: + ~scanner_hw(); + + // sane_opt_provider +public: + // return malloc(), real data size stored in parameter 'size'. invoker should free() the returned value + virtual char* get_value(const char* name, void* value, size_t* size, int* err = nullptr) override; + virtual int set_value(const char* name, void* val) override; + + // operation ... +public: + int open(std::function image_handler); + int start_scan(void); + int stop_scan(void); + int close(void); +}; +// { +// "mode": { +// "cat": "none", +// "group": "CIS", +// "title": "颜色模式", +// "desc": "选择色彩模式", +// "type": "string", +// "fix-id": 34819, +// "ui-pos": 10, +// "auth": 0, +// "size": 12, +// "cur": "彩色", +// "default": "彩色", +// "range": ["彩色", "灰度"] +// }, +// "resolution": { +// "cat": "none", +// "group": "CIS", +// "title": "分辨率", +// "desc": "设置扫描图像的分辨率", +// "type": "int", +// "fix-id": 34840, +// "ui-pos": 11, +// "auth": 0, +// "size": 4, +// "cur": 300, +// "default": 300, +// "range": [200, 300] +// }, +// "baud": { +// "cat": "none", +// "group": "CIS", +// "title": "波特率", +// "desc": "CIS控制通信速率", +// "type": "int", +// "ui-pos": 12, +// "auth": 0, +// "size": 4, +// "cur": 921600, +// "default": 921600, +// "range": [110, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 500000, 921600, 1500000] +// }, +// "act-after": { +// "cat": "none", +// "group": "CIS", +// "title": "延迟响应", +// "desc": "采集头接受命令后的动作延迟时间", +// "type": "int", +// "ui-pos": 12, +// "auth": 0, +// "unit": "microsec", +// "size": 4, +// "cur": 1000, +// "default": 1000 +// }, +// "fram-h": { +// "cat": "none", +// "group": "CIS", +// "title": "帧高度", +// "desc": "采集头每一帧的采集高度", +// "type": "int", +// "ui-pos": 13, +// "auth": 0, +// "size": 4, +// "cur": 12, +// "default": 12 +// }, +// "sample": { +// "cat": "none", +// "group": "CIS", +// "title": "采样频率", +// "desc": "采样频率", +// "type": "int", +// "ui-pos": 14, +// "auth": 0, +// "size": 4, +// "cur": 256, +// "default": 256 +// }, +// "expo-fb": { +// "cat": "none", +// "group": "CIS", +// "title": "曝光度(正面蓝色通道)", +// "desc": "正面蓝色通道的曝光强度", +// "type": "int", +// "ui-pos": 15, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "expo-fg": { +// "cat": "none", +// "group": "CIS", +// "title": "曝光度(正面绿色通道)", +// "desc": "正面绿色通道的曝光强度", +// "type": "int", +// "ui-pos": 16, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "expo-fr": { +// "cat": "none", +// "group": "CIS", +// "title": "曝光度(正面红色通道)", +// "desc": "正面红色通道的曝光强度", +// "type": "int", +// "ui-pos": 17, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "expo-bb": { +// "cat": "none", +// "group": "CIS", +// "title": "曝光度(背面蓝色通道)", +// "desc": "背面蓝色通道的曝光强度", +// "type": "int", +// "ui-pos": 18, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "expo-bg": { +// "cat": "none", +// "group": "CIS", +// "title": "曝光度(背面绿色通道)", +// "desc": "背面绿色通道的曝光强度", +// "type": "int", +// "ui-pos": 19, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "expo-br": { +// "cat": "none", +// "group": "CIS", +// "title": "曝光度(背面红色通道)", +// "desc": "背面红色通道的曝光强度", +// "type": "int", +// "ui-pos": 20, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "gain-f": { +// "cat": "none", +// "group": "CIS", +// "title": "增益(正面)", +// "desc": "正面的增益量", +// "type": "int", +// "ui-pos": 21, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "gain-b": { +// "cat": "none", +// "group": "CIS", +// "title": "增益(背面)", +// "desc": "背面的增益量", +// "type": "int", +// "ui-pos": 24, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": -1000, +// "max": 1000, +// "step": 1 +// } +// }, +// "off-f": { +// "cat": "none", +// "group": "CIS", +// "title": "偏移(正面)", +// "desc": "正面的偏移量", +// "type": "int", +// "ui-pos": 27, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": 0, +// "max": 100, +// "step": 1 +// } +// }, +// "off-b": { +// "cat": "none", +// "group": "CIS", +// "title": "偏移(背面)", +// "desc": "背面的偏移量", +// "type": "int", +// "ui-pos": 30, +// "auth": 0, +// "size": 4, +// "cur": 0, +// "default": 0, +// "range": { +// "min": 0, +// "max": 100, +// "step": 1 +// } +// } +// } \ No newline at end of file diff --git a/hardware/uart/DevUtil.cpp b/hardware/uart/DevUtil.cpp new file mode 100644 index 0000000..2fce871 --- /dev/null +++ b/hardware/uart/DevUtil.cpp @@ -0,0 +1,31 @@ +#include "DevUtil.h" + +#include +#include + +#define IOEXPORTPATH "/sys/class/gpio/export" +#define PWMEXPORTPATH "/sys/class/pwm/pwmchip%d/export" +int read_dev_i(std::string path) { + int val = -1; + std::ifstream ifin(path.c_str()); + ifin >> val; + return val; +} + +std::string read_dev_s(std::string path) { + std::string val; + std::ifstream ifin(path.c_str()); + ifin >> val; + return val; +} + +DeviceExport::DeviceExport() +{ + int num = sizeof(ports) / sizeof(ports[0]); + for (int i = 0; i < num; i++) + write_dev(IOEXPORTPATH, ports[i]); + + num = sizeof(pwms) / sizeof(pwms[0]); + for (int i = 0; i < num; i++) + write_dev(utils::format_string(PWMEXPORTPATH, pwms[i]), 0); +} diff --git a/hardware/uart/DevUtil.h b/hardware/uart/DevUtil.h new file mode 100644 index 0000000..553f747 --- /dev/null +++ b/hardware/uart/DevUtil.h @@ -0,0 +1,94 @@ +#pragma once +#include +#include +#include + +#define G300 + +template +void write_dev(std::string path, T value) +{ + std::ofstream ofout(path); + ofout << value; +} + +extern int read_dev_i(std::string path); + +extern std::string read_dev_s(std::string path); + +enum PORTS +{ + Start = 171, + Stop = 49, + Power = 5, + Fpga_Load = 8, + +#ifndef G300 + Power_12v_Off = 12, +#endif + + MotorPower = 48, + CuoZhiMotor_Reset = 56, + CuoZhiMotor_Sleep = 57, + CuoZhiMotor_Enable = 58, + + CuoZhiMotor_Direction = 62, + CuoZhiMotor_Decay = 63, + CuoZhiMotor_Home = 184, + CuoZhiMotor_Fault = 185, + + CuoZhiMotor_Mode0 = 59, + CuoZhiMotor_Mode1 = 60, + CuoZhiMotor_Mode2 = 61, + Cover = 189, // 'GPIO6A5' opened:0 ; closed:1 + + Paper = 225, // 'GPIO7B1' has paper:0 ; no paper:1 + Scan = 226, // 'GPIO7B2' no paper:0 ; has paper:1 + PaperJam = 102, + Double_Paper = 219, // 'GPIO7A3' not doubled:0 ; doubled:1 + SW_NOR_FLASH = 221, + Double_Enable = 250, // 'GPIO8A2' off: 0 ; on: 1 + + ZouZhiMotor_Reset = 64, + ZouZhiMotor_Sleep = 65, + ZouZhiMotor_Enable = 66, + ZouZhiMotor_Direction = 70, + + ZouZhiMotor_Decay = 71, + ZouZhiMotor_Home = 187, + ZouZhiMotor_Fault = 188, + ZouZhiMotor_Mode0 = 67, + + ZouZhiMotor_Mode1 = 68, + ZouZhiMotor_Mode2 = 69, + CIS_3v3_Off = 96, + CIS_5v_En = 98, + + Fpga_InitDone = 99, + Image_In_Transfer = 101, + Fpga_Reset = 232 +}; + +class DeviceExport +{ +public: + DeviceExport(); + +private: +#ifndef G300 + const int ports[38] = {Start, Stop, Power, Fpga_Load, Power_12v_Off, MotorPower, CuoZhiMotor_Reset, CuoZhiMotor_Sleep, CuoZhiMotor_Enable, + CuoZhiMotor_Direction, CuoZhiMotor_Decay, CuoZhiMotor_Home, CuoZhiMotor_Fault, CuoZhiMotor_Mode0, + CuoZhiMotor_Mode1, CuoZhiMotor_Mode2, Cover, Paper, Scan, PaperJam, Double_Paper, Double_Enable, + ZouZhiMotor_Reset, ZouZhiMotor_Sleep, ZouZhiMotor_Enable, ZouZhiMotor_Direction, ZouZhiMotor_Decay, + ZouZhiMotor_Home, ZouZhiMotor_Fault, ZouZhiMotor_Mode0, ZouZhiMotor_Mode1, ZouZhiMotor_Mode2, + CIS_3v3_Off, CIS_5v_En, Fpga_InitDone, Image_In_Transfer, Fpga_Reset, SW_NOR_FLASH}; +#else + const int ports[36] = {Start, Stop, Power, Fpga_Load, MotorPower, CuoZhiMotor_Reset, CuoZhiMotor_Sleep, CuoZhiMotor_Enable, + CuoZhiMotor_Direction, CuoZhiMotor_Decay, CuoZhiMotor_Home, CuoZhiMotor_Fault, CuoZhiMotor_Mode0, + CuoZhiMotor_Mode1, CuoZhiMotor_Mode2, Cover, Paper, Scan, PaperJam, Double_Paper, Double_Enable, + ZouZhiMotor_Reset, ZouZhiMotor_Sleep, ZouZhiMotor_Enable, ZouZhiMotor_Direction, ZouZhiMotor_Decay, + ZouZhiMotor_Home, ZouZhiMotor_Fault, ZouZhiMotor_Mode0, ZouZhiMotor_Mode1, ZouZhiMotor_Mode2, + CIS_3v3_Off, CIS_5v_En, Fpga_InitDone, Image_In_Transfer, Fpga_Reset}; +#endif + const int pwms[2] = {2, 3}; +}; \ No newline at end of file diff --git a/hardware/uart/Gpio.cpp b/hardware/uart/Gpio.cpp new file mode 100644 index 0000000..b960c4a --- /dev/null +++ b/hardware/uart/Gpio.cpp @@ -0,0 +1,76 @@ +// +// Created by yingluo907 on 2019/4/11. +// +#include "Gpio.h" + +#include +#include "DevUtil.h" + +#define IOPATH "%s/gpio%d/%s" + +const std::string Gpio::falling = "falling"; +const std::string Gpio::rising = "rising"; +const std::string Gpio::both = "both"; +const std::string Gpio::none = "none"; + +const std::string Gpio::in = "in"; +const std::string Gpio::out = "out"; + +Gpio::Gpio(int port) +{ + this->port = port; + path_value = utils::format_string(IOPATH, path_gpiobase.c_str(), port, path_value.c_str()); + path_edge = utils::format_string(IOPATH, path_gpiobase.c_str(), port, path_edge.c_str()); + path_direction = utils::format_string(IOPATH, path_gpiobase.c_str(), port, path_direction.c_str()); + path_active_low = utils::format_string(IOPATH, path_gpiobase.c_str(), port, path_active_low.c_str()); +} + +int Gpio::getPort() +{ + return port; +} + +void Gpio::setValue(GpioLevel level) +{ + write_dev(path_value, level); +} + +Gpio::GpioLevel Gpio::getValue() { + return (Gpio::GpioLevel)read_dev_i(path_value); +} + +std::string Gpio::getDirection() +{ + return read_dev_s(path_direction); +} + +void Gpio::setDirection(std::string direction) +{ + write_dev(path_direction, direction); +} + +void Gpio::setActive(GpioLevel level) +{ + write_dev(path_active_low, level); +} + +Gpio::GpioLevel Gpio::getActive() +{ + return (GpioLevel)read_dev_i(path_active_low); +} + +void Gpio::setEdge(std::string edge) +{ + write_dev(path_edge, edge); +} + +std::string Gpio::getEdge() +{ + return read_dev_s(path_edge); +} + +GpioOut::GpioOut(int port) : + Gpio(port) +{ + setDirection(out); +} diff --git a/hardware/uart/Gpio.h b/hardware/uart/Gpio.h new file mode 100644 index 0000000..1ee375a --- /dev/null +++ b/hardware/uart/Gpio.h @@ -0,0 +1,50 @@ +#pragma once +#include + +class Gpio +{ +public: + enum GpioLevel + { + Low, + High + }; + + Gpio(int port); + int getPort(); + void setValue(GpioLevel level); + GpioLevel getValue(); + std::string getDirection(); + void setDirection(std::string direction); + void setActive(GpioLevel level); + GpioLevel getActive(); + void setEdge(std::string edge); + std::string getEdge(); + + std::string getValuePath() + { + return path_value; + } + + static const std::string falling; + static const std::string rising; + static const std::string both; + static const std::string none; + + static const std::string in; + static const std::string out; + +private: + int port; + const std::string path_gpiobase = "/sys/class/gpio"; + std::string path_value = "value"; + std::string path_edge = "edge"; + std::string path_direction = "direction"; + std::string path_active_low = "active_low"; +}; + +class GpioOut : public Gpio +{ +public: + GpioOut(int port); +}; diff --git a/hardware/uart/regsaccess.h b/hardware/uart/regsaccess.h new file mode 100644 index 0000000..3fadf8f --- /dev/null +++ b/hardware/uart/regsaccess.h @@ -0,0 +1,10 @@ +#pragma once + +class IRegsAccess +{ +public: + virtual ~IRegsAccess(){}; + + virtual bool read(unsigned int addr, unsigned int& val) = 0; + virtual bool write(unsigned int addr , const unsigned int val) = 0; +}; \ No newline at end of file diff --git a/hardware/uart/serialib.cpp b/hardware/uart/serialib.cpp new file mode 100644 index 0000000..0cb5aa9 --- /dev/null +++ b/hardware/uart/serialib.cpp @@ -0,0 +1,582 @@ +/*! + \file serialib.cpp + \brief Class to manage the serial port + \author Philippe Lucidarme (University of Angers) + \version 1.2 + \date 28 avril 2011 + +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" + + +#define FNDELAY O_NDELAY + + + +/*! + \brief Constructor of the class serialib. +*/ +// Class constructor +serialib::serialib() +{} + + +/*! + \brief Destructor of the class serialib. It close the connection +*/ +// Class desctructor +serialib::~serialib() +{ + Close(); +} + + + +//_________________________________________ +// ::: 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 + + \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 + */ +char serialib::Open(const char *Device,const unsigned int Bauds) +{ +#if defined(_WIN32) || defined(_WIN64) + + // Open serial port + hSerial = CreateFileA(Device, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hSerial == INVALID_HANDLE_VALUE) + { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + return -1; // Device not found + return -2; // Error while opening the device + } + + // Set parameters + DCB dcbSerialParams = {0}; // Structure for the port parameters + dcbSerialParams.DCBlength = sizeof(dcbSerialParams); + if (!GetCommState(hSerial, &dcbSerialParams)) // Get the port parameters + return -3; // Error while getting port parameters + switch (Bauds) // Set the speed (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; + } + dcbSerialParams.ByteSize = 8; // 8 bit data + dcbSerialParams.StopBits = ONESTOPBIT; // One stop bit + dcbSerialParams.Parity = NOPARITY; // No parity + if (!SetCommState(hSerial, &dcbSerialParams)) // Write the parameters + return -5; // Error while writing + + // Set TimeOut + timeouts.ReadIntervalTimeout = 0; // Set the Timeout parameters + timeouts.ReadTotalTimeoutConstant = MAXDWORD; // No TimeOut + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = MAXDWORD; + timeouts.WriteTotalTimeoutMultiplier = 0; + if (!SetCommTimeouts(hSerial, &timeouts)) // Write the parameters + return -6; // Error while writting the parameters + return 1; // Opening successfull + +#endif +#ifdef __linux__ + struct termios options; // Structure with the device's options + + // Open device + fd = open(Device, O_RDWR | O_NOCTTY | O_NDELAY); // Open port + if (fd == -1) + return -2; // If the device is not open, return -1 + fcntl(fd, F_SETFL, FNDELAY); // Open the device in nonblocking mode + + // Set parameters + tcgetattr(fd, &options); // Get the current options of the port + bzero(&options, sizeof(options)); // Clear all the options + speed_t Speed; + switch (Bauds) // Set the speed (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; + case 500000: + Speed = B500000; + break; + case 921600: + Speed = B921600; + break; + case 1500000: + Speed = B1500000; + break; + default: + return -4; + } + cfsetispeed(&options, Speed); // Set the baud rate at 115200 bauds + cfsetospeed(&options, Speed); + options.c_cflag |= (CLOCAL | CREAD | CS8); // Configure the device : 8 bits, no parity, no control + options.c_iflag |= (IGNPAR | IGNBRK); + options.c_cc[VTIME] = 0; // Timer unused + options.c_cc[VMIN] = 0; // At least on character before satisfy reading + tcsetattr(fd, TCSANOW, &options); // Activate the settings + return (1); // Success +#endif +} + +/*! + \brief Close the connection with the current device +*/ +void serialib::Close() +{ +#if defined (_WIN32) || defined( _WIN64) + CloseHandle(hSerial); +#endif +#ifdef __linux__ + close (fd); +#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 + */ +char serialib::WriteChar(const char Byte) +{ +#if defined (_WIN32) || defined( _WIN64) + DWORD dwBytesWritten; // Number of bytes written + if(!WriteFile(hSerial,&Byte,1,&dwBytesWritten,NULL)) // Write the char + return -1; // Error while writing + return 1; // Write operation successfull +#endif +#ifdef __linux__ + if (write(fd,&Byte,1)!=1) // Write the char + return -1; // Error while writting + return 1; // Write operation successfull +#endif +} + + + +//________________________________________ +// ::: Read/Write operation on strings ::: + + +/*! + \brief Write a string on the current serial port + \param String : string to send on the port (must be terminated by '\0') + \return 1 success + \return -1 error while writting data + */ +char serialib::WriteString(const char *String) +{ +#if defined (_WIN32) || defined( _WIN64) + DWORD dwBytesWritten; // Number of bytes written + if(!WriteFile(hSerial,String,strlen(String),&dwBytesWritten,NULL)) // Write the string + return -1; // Error while writing + return 1; // Write operation successfull +#endif +#ifdef __linux__ + int Lenght=strlen(String); // Lenght of the string + if (write(fd,String,Lenght)!=Lenght) // Write the string + return -1; // error while writing + return 1; // Write operation successfull +#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 + */ +char serialib::Write(const void *Buffer, const unsigned int NbBytes) +{ +#if defined (_WIN32) || defined( _WIN64) + DWORD dwBytesWritten; // Number of byte written + if(!WriteFile(hSerial, Buffer, NbBytes, &dwBytesWritten, NULL)) // Write data + return -1; // Error while writing + return 1; // Write operation successfull +#endif +#ifdef __linux__ + if (write (fd,Buffer,NbBytes)!=(ssize_t)NbBytes) // Write data + return -1; // Error while writing + return 1; // Write operation successfull +#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 + */ +char serialib::ReadChar(char *pByte,unsigned int TimeOut_ms) +{ +#if defined (_WIN32) || defined(_WIN64) + + DWORD dwBytesRead = 0; + timeouts.ReadTotalTimeoutConstant=TimeOut_ms; // Set the TimeOut + if(!SetCommTimeouts(hSerial, &timeouts)) // Write the parameters + return -1; // Error while writting the parameters + if(!ReadFile(hSerial,pByte, 1, &dwBytesRead, NULL)) // Read the byte + return -2; // Error while reading the byte + if (dwBytesRead==0) return 0; // Return 1 if the timeout is reached + return 1; // Success +#endif +#ifdef __linux__ + TimeOut Timer; // Timer used for timeout + Timer.InitTimer(); // Initialise the timer + 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 *String,char FinalChar,unsigned int MaxNbBytes) +{ + unsigned int NbBytes=0; // Number of bytes read + char ret; // Returned value from Read + while (NbBytes0 success, return the number of bytes read + \return 0 timeout is reached + \return -1 error while setting the Timeout + \return -2 error while reading the byte + \return -3 MaxNbBytes is reached + */ +int serialib::ReadString(char *String,char FinalChar,unsigned int MaxNbBytes,unsigned int TimeOut_ms) +{ + if (TimeOut_ms==0) + return ReadStringNoTimeOut(String,FinalChar,MaxNbBytes); + + unsigned int NbBytes=0; // Number of bytes read + char ret; // Returned value from Read + TimeOut Timer; // Timer used for timeout + long int TimeOutParam; + Timer.InitTimer(); // Initialize the timer + + while (NbBytes0) // If the parameter is higher than zero + { + ret=ReadChar(&String[NbBytes],TimeOutParam); // Wait for a byte on the serial link + if (ret==1) // If a byte has been read + { + + if (String[NbBytes]==FinalChar) // Check if it is the final char + { + String [++NbBytes]=0; // Yes : add the end character 0 + return NbBytes; // Return the number of bytes read + } + NbBytes++; // If not, just increase the number of bytes read + } + if (ret<0) return ret; // Error while reading : return the error number + } + if (Timer.ElapsedTime_ms()>TimeOut_ms) { // Timeout is reached + String[NbBytes]=0; // Add the end caracter + return 0; // Return 0 + } + } + return -3; // Buffer is full : 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 + \return 1 success, return the number of bytes read + \return 0 Timeout reached + \return -1 error while setting the Timeout + \return -2 error while reading the byte + */ +int serialib::Read (void *Buffer,unsigned int MaxNbBytes,unsigned int TimeOut_ms) +{ +#if defined (_WIN32) || defined(_WIN64) + DWORD dwBytesRead = 0; + timeouts.ReadTotalTimeoutConstant=(DWORD)TimeOut_ms; // Set the TimeOut + if(!SetCommTimeouts(hSerial, &timeouts)) // Write the parameters + return -1; // Error while writting the parameters + if(!ReadFile(hSerial,Buffer,(DWORD)MaxNbBytes,&dwBytesRead, NULL)) // Read the bytes from the serial device + return -2; // Error while reading the byte + if (dwBytesRead!=(DWORD)MaxNbBytes) return 0; // Return 0 if the timeout is reached + return 1; // Success +#endif +#ifdef __linux__ + TimeOut Timer; // Timer used for timeout + Timer.InitTimer(); // Initialise the timer + unsigned int NbByteRead=0; + while (Timer.ElapsedTime_ms()0) { // One or several byte(s) has been read on the device + NbByteRead+=Ret; // Increase the number of read bytes + if (NbByteRead>=MaxNbBytes) // Success : bytes has been read + return 1; + } + } + return 0; // Timeout reached, return 0 +#endif +} + + + + +// _________________________ +// ::: Special operation ::: + + + +/*! + \brief Empty receiver buffer (UNIX only) +*/ + +void serialib::FlushReceiver() +{ +#ifdef __linux__ + tcflush(fd,TCIFLUSH); +#endif +} + + + +/*! + \brief Return the number of bytes in the received buffer (UNIX only) + \return The number of bytes in the received buffer +*/ +int serialib::Peek() +{ + int Nbytes=0; +#ifdef __linux__ + ioctl(fd, FIONREAD, &Nbytes); +#endif + return Nbytes; +} + +// ****************************************** +// 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() +{ + gettimeofday(&PreviousTime, NULL); +} + +/*! + \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() +{ + struct timeval CurrentTime; + int sec,usec; + gettimeofday(&CurrentTime, NULL); // Get current time + sec=CurrentTime.tv_sec-PreviousTime.tv_sec; // Compute the number of second elapsed since last call + usec=CurrentTime.tv_usec-PreviousTime.tv_usec; // Compute + if (usec<0) { // If the previous usec is higher than the current one + usec=1000000-PreviousTime.tv_usec+CurrentTime.tv_usec; // Recompute the microseonds + sec--; // Substract one second + } + return sec*1000+usec/1000; +} + diff --git a/hardware/uart/serialib.h b/hardware/uart/serialib.h new file mode 100644 index 0000000..e5d3a75 --- /dev/null +++ b/hardware/uart/serialib.h @@ -0,0 +1,220 @@ +/*! +\file serialib.h +\brief Serial library to communicate throught serial port, or any device emulating a serial port. +\author Philippe Lucidarme (University of Angers) +\version 1.2 +\date 28 avril 2011 +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 + + +// Used for TimeOut operations +#include +// Include for windows +#if defined (_WIN32) || defined( _WIN64) + // Accessing to the serial port under Windows + #include +#endif + +// Include for Linux +#ifdef __linux__ + #include + #include + #include + #include + #include + #include + // File control definitions + #include + #include + #include +#endif + + + +/*! \class serialib + \brief This class can manage a serial port. The class allows basic operations (opening the connection, reading, writing data and closing the connection). + \example Example1.cpp + */ + + +class serialib +{ +public: + // Constructor of the class + serialib (); + + // Destructor + ~serialib (); + + + + //_________________________________________ + // ::: Configuration and initialization ::: + + + // Open a device + char Open (const char *Device,const unsigned int Bauds); + + // Close the current device + void Close(); + + + + //___________________________________________ + // ::: Read/Write operation on characters ::: + + + // Write a char + char WriteChar (char); + + // Read a char (with timeout) + char ReadChar (char *pByte,const unsigned int TimeOut_ms=0); + + + + //________________________________________ + // ::: Read/Write operation on strings ::: + + + // Write a string + char WriteString (const char *String); + // Read a string (with timeout) + int ReadString ( char *String, + char FinalChar, + unsigned int MaxNbBytes, + const unsigned int TimeOut_ms=0); + + + + // _____________________________________ + // ::: Read/Write operation on bytes ::: + + + // Write an array of bytes + char Write (const void *Buffer, const unsigned int NbBytes); + + // Read an array of byte (with timeout) + int Read (void *Buffer,unsigned int MaxNbBytes,const unsigned int TimeOut_ms=0); + + + // _________________________ + // ::: Special operation ::: + + + // Empty the received buffer + void FlushReceiver(); + + // Return the number of bytes in the received buffer + int Peek(); + +private: + // Read a string (no timeout) + int ReadStringNoTimeOut (char *String,char FinalChar,unsigned int MaxNbBytes); + + +#if defined (_WIN32) || defined( _WIN64) + HANDLE hSerial; + COMMTIMEOUTS timeouts; +#endif +#ifdef __linux__ + 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: + struct timeval PreviousTime; +}; + + + +/*! + \mainpage serialib class + + \brief + \htmlonly + + + + +
+ + + + +

[Download]

+
+
+ + +
+ + \endhtmlonly + + The class serialib offers simple access to the serial port devices for windows and linux. It can be used for any serial device (Built-in serial port, USB to RS232 converter, arduino board or any hardware using or emulating a serial port) + \image html serialib.png + The class can be used under Windows and Linux. + The class allows basic operations like : + - opening and closing connection + - reading data (characters, array of bytes or strings) + - writing data (characters, array of bytes or strings) + - non-blocking functions (based on timeout). + + + \author Philippe Lucidarme (University of Angers) + \date 1th may 2011 (Last update: 25th september 2012) + \version 1.2 + +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. +*/ + + + + +#endif // SERIALIB_H + diff --git a/hardware/uart/uartregaccessb.cpp b/hardware/uart/uartregaccessb.cpp new file mode 100644 index 0000000..a83ff70 --- /dev/null +++ b/hardware/uart/uartregaccessb.cpp @@ -0,0 +1,43 @@ +#include "uartregaccessb.h" + +#include "serialib.h" + + +UartRegsAccessB::UartRegsAccessB(std::string devName, int bauds, int readflag, int writeflag) +{ + m_serial.reset(new serialib()); + m_serial->Open(devName.c_str(), bauds); + this->readflag = readflag; + this->writeflag = writeflag; +} + +UartRegsAccessB::~UartRegsAccessB() +{ +} + +bool UartRegsAccessB::write(unsigned int addr, unsigned int val) +{ + std::lock_guard lck(mx_uart); + unsigned char* pdata = bufSend; + pdata[0] = writeflag; + pdata[1] = (unsigned char)addr; + *((unsigned int*)(pdata + 3)) = val; + m_serial->Write(bufSend, sizeof(bufSend)); + return true; +} + +bool UartRegsAccessB::read(unsigned int addr, unsigned int& val) +{ + std::lock_guard lck(mx_uart); + unsigned char *pdata = bufRecv; + pdata[0] = readflag; + pdata[1] = (unsigned char)addr; + m_serial->Write(bufRecv, 2); + if (m_serial->Read(bufRecv, 5, 500)) + { + val = *((unsigned int*)(bufRecv + 1)); + return true; + } + + return false; +} \ No newline at end of file diff --git a/hardware/uart/uartregaccessb.h b/hardware/uart/uartregaccessb.h new file mode 100644 index 0000000..4697018 --- /dev/null +++ b/hardware/uart/uartregaccessb.h @@ -0,0 +1,25 @@ +#pragma once +#include "regsaccess.h" +#include +#include +#include + +class serialib; + +class UartRegsAccessB : public IRegsAccess +{ +public: + UartRegsAccessB(std::string devName, int bauds, int readflag, int writeflag); + virtual ~UartRegsAccessB(); + + virtual bool read(unsigned int addr, unsigned int& val); + virtual bool write(unsigned int addr, unsigned int val); + +private: + int readflag; + int writeflag; + unsigned char bufSend[7]; + unsigned char bufRecv[5]; + std::shared_ptr m_serial; + std::mutex mx_uart; +}; \ No newline at end of file diff --git a/hardware/uart/uartregsaccess.cpp b/hardware/uart/uartregsaccess.cpp new file mode 100644 index 0000000..6765ff3 --- /dev/null +++ b/hardware/uart/uartregsaccess.cpp @@ -0,0 +1,36 @@ +#include "uartregsaccess.h" +#include "serialib.h" + +UartRegsAccess::UartRegsAccess(std::string devName, int bauds, int readflag, int writeflag) + : UartRegsAccessB(devName, bauds, readflag, writeflag) +{ +} + +UartRegsAccess::~UartRegsAccess() +{ +} + +bool UartRegsAccess::write(unsigned int addr, unsigned int val) +{ + unsigned int valt = val; + unsigned char* idata = (unsigned char*)&val; + unsigned char *idatat = (unsigned char *)&valt; + for(int i = 0; i < 4; i++) + idata[3 - i] = idatat[i]; + + return UartRegsAccessB::write(addr, val); +} + +bool UartRegsAccess::read(unsigned int addr, unsigned int& val) +{ + unsigned int valt = 0; + if (UartRegsAccessB::read(addr, valt)) + { + unsigned char *idata = (unsigned char *)&val; + unsigned char *idatat = (unsigned char *)&valt; + for (int i = 0; i < 4; i++) + idata[3 - i] = idatat[i]; + return true; + } + return false; +} \ No newline at end of file diff --git a/hardware/uart/uartregsaccess.h b/hardware/uart/uartregsaccess.h new file mode 100644 index 0000000..d6b2fba --- /dev/null +++ b/hardware/uart/uartregsaccess.h @@ -0,0 +1,12 @@ +#pragma once +#include "uartregaccessb.h" + +class UartRegsAccess : public UartRegsAccessB +{ +public: + UartRegsAccess(std::string devName, int bauds, int readflag, int writeflag); + virtual ~UartRegsAccess(); + + virtual bool read(unsigned int addr, unsigned int& val); + virtual bool write(unsigned int addr, unsigned int val); +}; \ No newline at end of file diff --git a/hardware/xmake.lua b/hardware/xmake.lua new file mode 100644 index 0000000..56256f5 --- /dev/null +++ b/hardware/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +target("hardware") + set_kind("static") + add_syslinks("pthread", "dl") + add_includedirs("../sdk") + add_files("*.cpp", "./cis/*.cpp", "./uart/*.cpp", "../sdk/base/*.c*", "../sdk/json/*.c*", "../sdk/sane_opt_json/*.c*") + --add_deps("gusb", "applog") + --add_rules("utils.bin2c",{linewidth = 32,extension = {".bin"}}) + --add_files("table.bin") + add_packages("sdk") + \ No newline at end of file diff --git a/scanner/async_scanner.cpp b/scanner/async_scanner.cpp index dfd9e9f..4936641 100644 --- a/scanner/async_scanner.cpp +++ b/scanner/async_scanner.cpp @@ -13,6 +13,7 @@ #include #include #include "scanner_const_opts.h" +#include @@ -59,14 +60,21 @@ async_scanner::async_scanner() : usb_(nullptr), cfg_mgr_(nullptr), scan_id_(0) cfg_mgr_ = new device_option(user, on_log); const_opts_ = new scanner_const_opts(); cfg_mgr_->add(const_opts_); + cfg_mgr_->add(cis_); - init(); usb_ = new async_usb_gadget(bulk_handle, on_connect); last_err_ = usb_->last_error(); } async_scanner::~async_scanner() { + if(cis_) + { + cis_->stop_scan(); + cis_->close(); + cis_->release(); + cis_ = nullptr; + } if(usb_) { usb_->stop(); @@ -151,6 +159,7 @@ dyn_mem_ptr async_scanner::handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, pac } void async_scanner::init(void) { + cis_ = new scanner_hw(); } dyn_mem_ptr async_scanner::handle_simple_roger(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required) diff --git a/scanner/async_scanner.h b/scanner/async_scanner.h index 1b793c0..2b8c079 100644 --- a/scanner/async_scanner.h +++ b/scanner/async_scanner.h @@ -16,12 +16,14 @@ class image_capture; class img_processor; class gb_json; class scanner_const_opts; +class scanner_hw; class async_scanner : public refer { - async_usb_gadget *usb_; - device_option *cfg_mgr_; - scanner_const_opts *const_opts_; + async_usb_gadget *usb_ = nullptr; + device_option *cfg_mgr_ = nullptr; + scanner_const_opts *const_opts_ = nullptr; + scanner_hw *cis_ = nullptr; MUTEX locker_; uint32_t img_cnt_; diff --git a/scanner/scanner_const_opts.cpp b/scanner/scanner_const_opts.cpp index 1b2cdd7..b82a8f0 100644 --- a/scanner/scanner_const_opts.cpp +++ b/scanner/scanner_const_opts.cpp @@ -12,8 +12,8 @@ #ifndef VER_MAIN #define VER_MAIN 2 #define VER_MINOR 0 -#define VER_DATE 20231218 -#define VER_BUILD 4 +#define VER_DATE 20231219 +#define VER_BUILD 1 #endif @@ -29,6 +29,7 @@ static std::string device_opt_json[] = { // scanner_const_opts scanner_const_opts::scanner_const_opts(const char* dev_path) : root_(dev_path) { + set_where("scanner_const_opts"); init(); } scanner_const_opts::~scanner_const_opts() diff --git a/scanner/scanner_const_opts.h b/scanner/scanner_const_opts.h index 150eb05..a076694 100644 --- a/scanner/scanner_const_opts.h +++ b/scanner/scanner_const_opts.h @@ -32,30 +32,30 @@ public: // "group": "关于", // "title": "USB-VID", // "desc": "设备制造商在USB组织的ID", -// "type": "int", +// "type": "string", // "fix-id": 34898, // "ui-pos": 10, // "auth": 0, // "readonly": true, -// "size": 4, +// "size": 16, // "auto": false, -// "cur": 0, -// "default": 0 +// "cur": "3072", +// "default": "3072" // }, // "dev-pid": { // "cat": "base", // "group": "关于", // "title": "USB-PID", // "desc": "设备在USB组织中的产品ID", -// "type": "int", +// "type": "string", // "fix-id": 34899, // "ui-pos": 11, // "auth": 0, // "readonly": true, -// "size": 4, +// "size": 16, // "auto": false, -// "cur": 0, -// "default": 0 +// "cur": "0306", +// "default": "0306" // }, // "dev-name": { // "cat": "base", @@ -97,7 +97,7 @@ public: // "ui-pos": 14, // "auth": 0, // "readonly": true, -// "size": 96, +// "size": 32, // "auto": false, // "ownread": true, // "cur": "GB20231201", @@ -113,7 +113,7 @@ public: // "ui-pos": 15, // "auth": 0, // "readonly": true, -// "size": 96, +// "size": 32, // "auto": false, // "ownread": true, // "cur": "G2393B0500", @@ -131,8 +131,8 @@ public: // "readonly": true, // "size": 4, // "auto": false, -// "cur": 0, -// "default": 0 +// "cur": 450000, +// "default": 450000 // }, // "ip-addr": { // "cat": "base", diff --git a/scanner/xmake.lua b/scanner/xmake.lua index 6c42f90..2f54ef9 100644 --- a/scanner/xmake.lua +++ b/scanner/xmake.lua @@ -3,10 +3,11 @@ add_rules("mode.debug", "mode.release") target("hgscanner") set_kind("binary") add_syslinks("pthread", "dl") - add_includedirs("../sdk", "../usb") + add_includedirs("../sdk", "../usb", "../sdk/imgprc/3rdsdk/include", "../hardware") add_files("*.cpp", "../sdk/base/*.c*", "../sdk/imgprc/*.c*", "../sdk/json/*.c*", "../sdk/sane_opt_json/*.c*") --add_deps("gusb", "applog") --add_rules("utils.bin2c",{linewidth = 32,extension = {".bin"}}) --add_files("table.bin") add_packages("sdk") - add_deps("usb") \ No newline at end of file + add_deps("usb") + add_deps("hardware") \ No newline at end of file diff --git a/sdk/base/packet.h b/sdk/base/packet.h index 50ea2d0..3eecb38 100644 --- a/sdk/base/packet.h +++ b/sdk/base/packet.h @@ -47,7 +47,7 @@ enum cancel_io enum ep0_req { USB_REQ_EP0_GET_PEER_CONFIG = 100, // get protocol version (PROTOCOL_VER), req = me, ind = 0, val = 0, len = sizeof(PEERCFG) - USB_REQ_EP0_GET_STATUS, // 获取各工作线程状态, return EP0REPLYSTATUS. req = me, ind = 0, val = 0, len = sizeof(EP0REPLYSTATUS) + USB_REQ_EP0_GET_STATUS, // 获取各工作线程状态, return EP0REPLYSTATUS. req = me, ind = 0, val = bool: whether write log, len = sizeof(EP0REPLYSTATUS) USB_REQ_EP0_CANCEL_IO, // 设置当前IO数据的有效性. req = me, ind = 0, val = 0, len = sizeof(uint32_t), discard IO data when data is CANCEL_IO_CANCEL // work-flow: write control with 'CANCEL_IO_CANCEL', write bulk with 1 byte, write control with not 'CANCEL_IO_CANCEL' to restore USB_REQ_EP0_SET_ENCRYPT, // 设置加密方式, req = me, ind = 0, val = 0, len = sizeof(PACK_BASE) diff --git a/sdk/base/utils.h b/sdk/base/utils.h index 52c53af..f01aef7 100644 --- a/sdk/base/utils.h +++ b/sdk/base/utils.h @@ -94,6 +94,17 @@ namespace utils bool run_get_message(HWND hwnd, UINT filter_min = 0, UINT filter_max = 0, std::function msghandler = std::function()); #endif + template + std::string format_string(const char* fmt, Args ... args) + { + size_t size = snprintf(nullptr, 0, fmt, args ...) + 2; + std::unique_ptr buf(new char[size]); + + snprintf(buf.get(), size, fmt, args ...); + + return buf.get(); + } + template void to_log(int level, const char* fmt, Args ... args) { diff --git a/sdk/sane/sane_ex.h b/sdk/sane/sane_ex.h index 2617738..db1c8e9 100644 --- a/sdk/sane/sane_ex.h +++ b/sdk/sane/sane_ex.h @@ -103,6 +103,7 @@ enum opt_visible_level // "visible" field }; // sane-standard-option-name defined by third-app +#define SANE_FULL_NAME(n) SANE_STD_OPT_NAME_##n // // PART I: 参数类型与华高一致,可直接通过改name字段为标准值实现 #define SANE_STD_OPT_NAME_RESTORE "restore" // OPTION_TITLE_HFMRSZ @@ -236,7 +237,22 @@ enum opt_visible_level // "visible" field #define SANE_STD_OPT_NAME_DUPLEX "duplex" // OPTION_TITLE_SMYM // END for sane-standard-option-name defined by third-app // -// + +// PART III: inner option on device +#define SANE_STD_OPT_NAME_CIS_BAUD "baud" +#define SANE_STD_OPT_NAME_CIS_DELAY "act-after" +#define SANE_STD_OPT_NAME_CIS_FRAME_H "frame-h" +#define SANE_STD_OPT_NAME_CIS_SAMPLE "sample" +#define SANE_STD_OPT_NAME_CIS_EXPO_FB "expo-fb" +#define SANE_STD_OPT_NAME_CIS_EXPO_FG "expo-fg" +#define SANE_STD_OPT_NAME_CIS_EXPO_FR "expo-fr" +#define SANE_STD_OPT_NAME_CIS_EXPO_BB "expo-bb" +#define SANE_STD_OPT_NAME_CIS_EXPO_BG "expo-bg" +#define SANE_STD_OPT_NAME_CIS_EXPO_BR "expo-br" +#define SANE_STD_OPT_NAME_CIS_GAIN_FRONT "gain-f" +#define SANE_STD_OPT_NAME_CIS_GAIN_BACK "gain-b" +#define SANE_STD_OPT_NAME_CIS_OFFSET_FRONT "off-f" +#define SANE_STD_OPT_NAME_CIS_OFFSET_BACK "off-b" // // 借鉴TWAIN协议固定ID的做法,定义SANE属性的固定ID - 这里与TWAIN中的ID保持一致,以方便TWAIN的调用 enum sane_option_id diff --git a/usb/usb_io.cpp b/usb/usb_io.cpp index dfeadff..637f177 100644 --- a/usb/usb_io.cpp +++ b/usb/usb_io.cpp @@ -285,7 +285,8 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_setup(dyn_mem_ptr data) lps->task_required_bytes = want_bytes_task_; lps->packets_to_sent = sent_que_.size(); lps->bytes_to_sent = want_bytes_in_; - utils::log_mem_info("threads status:", lps, sizeof(*lps), LOG_LEVEL_DEBUG); + if(pev->u.setup.wValue) + utils::log_mem_info("threads status:", lps, sizeof(*lps), LOG_LEVEL_DEBUG); } break; case USB_REQ_EP0_CANCEL_IO: diff --git a/xmake.lua b/xmake.lua index 97150e2..e87b2e9 100644 --- a/xmake.lua +++ b/xmake.lua @@ -64,7 +64,7 @@ target("conf") add_configfiles("config.h.in", {prefixdir = "header"}) add_includedirs("$(buildir)/config/header", { public = true }) -includes("usb", "scanner") +includes("usb", "hardware", "scanner") -- includes("regs", "deviceio", "motorboard", "capimage", "usb", "service", "scanner", "imgproc", "applog","scanservice","fpgaupdate","motorcontroller","display","testlcd","keymonitor","testkeymonitor","testdisplay","testwakeup")