添加硬件(FPGA)代码;工作状态是否记录进日志通过wValue!=0来判断

This commit is contained in:
gb 2023-12-19 15:27:16 +08:00
parent f9217b32c5
commit d878284efb
26 changed files with 2343 additions and 24 deletions

360
hardware/cis/FpgaComm.cpp Normal file
View File

@ -0,0 +1,360 @@
//
// Created by Nick on 2019/4/7.
//
#include "FpgaComm.h"
#include <thread>
#include "../uart/uartregsaccess.h"
#include <iostream>
#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);
}

203
hardware/cis/FpgaComm.h Normal file
View File

@ -0,0 +1,203 @@
#pragma once
#include <string>
#include <memory>
#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<IRegsAccess> m_regsAccess;
};

198
hardware/hardware.cpp Normal file

File diff suppressed because one or more lines are too long

326
hardware/hardware.h Normal file
View File

@ -0,0 +1,326 @@
// hardware drivers
//
// Contains: CIS, MotorBoard, ...
//
// Date: 2023-12-18
#include <sane_opt_json/base_opt.h>
#include <functional>
#include <base/packet.h>
#include <base/data.h>
#include <memory>
#include <map>
// 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<IMAGE_HANDLER_PROTO> img_handler_;
bool scanning_ = false;
bool auto_scan_ = false;
std::unique_ptr<FpgaComm> 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<std::string, std::function<void(void*)>> 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_PROTO> 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
// }
// }
// }

31
hardware/uart/DevUtil.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "DevUtil.h"
#include <fstream>
#include <base/utils.h>
#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);
}

94
hardware/uart/DevUtil.h Normal file
View File

@ -0,0 +1,94 @@
#pragma once
#include <string>
#include <fstream>
#include <memory>
#define G300
template <typename T>
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};
};

76
hardware/uart/Gpio.cpp Normal file
View File

@ -0,0 +1,76 @@
//
// Created by yingluo907 on 2019/4/11.
//
#include "Gpio.h"
#include <base/utils.h>
#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);
}

50
hardware/uart/Gpio.h Normal file
View File

@ -0,0 +1,50 @@
#pragma once
#include <string>
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);
};

View File

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

582
hardware/uart/serialib.cpp Normal file
View File

@ -0,0 +1,582 @@
/*!
\file serialib.cpp
\brief Class to manage the serial port
\author Philippe Lucidarme (University of Angers) <serialib@googlegroups.com>
\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()<TimeOut_ms || TimeOut_ms==0) // While Timeout is not reached
{
switch (read(fd,pByte,1)) { // Try to read a byte on the device
case 1 : return 1; // Read successfull
case -1 : return -2; // Error while reading
}
}
return 0;
#endif
}
/*!
\brief Read a string from the serial device (without TimeOut)
\param String : string read on the serial device
\param FinalChar : final char of the string
\param MaxNbBytes : maximum allowed number of bytes read
\return >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 (NbBytes<MaxNbBytes) // While the buffer is not full
{ // Read a byte with the restant time
ret=ReadChar(&String[NbBytes]);
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
}
return -3; // Buffer is full : return -3
}
/*!
\brief Read a string from the serial device (with timeout)
\param String : string read on the serial device
\param FinalChar : final char of the string
\param MaxNbBytes : maximum allowed number of bytes read
\param TimeOut_ms : delay of timeout before giving up the reading (optional)
\return >0 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 (NbBytes<MaxNbBytes) // While the buffer is not full
{ // Read a byte with the restant time
TimeOutParam=TimeOut_ms-Timer.ElapsedTime_ms(); // Compute the TimeOut for the call of ReadChar
if (TimeOutParam>0) // 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()<TimeOut_ms || TimeOut_ms==0) // While Timeout is not reached
{
unsigned char* Ptr=(unsigned char*)Buffer+NbByteRead; // Compute the position of the current byte
int Ret=read(fd,(void*)Ptr,MaxNbBytes-NbByteRead); // Try to read a byte on the device
if (Ret==-1) return -2; // Error while reading
if (Ret>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;
}

220
hardware/uart/serialib.h Normal file
View File

@ -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) <serialib@googlegroups.com>
\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 <sys/time.h>
// Include for windows
#if defined (_WIN32) || defined( _WIN64)
// Accessing to the serial port under Windows
#include <windows.h>
#endif
// Include for Linux
#ifdef __linux__
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <termios.h>
#include <string.h>
#include <iostream>
// File control definitions
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#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
<TABLE>
<TR><TD>
<a href="../serialibv1.2.zip" title="Download the serialib class">
<TABLE>
<TR><TD><IMG SRC="download.png" BORDER=0 WIDTH=100> </TD></TR>
<TR><TD><P ALIGN="center">[Download]</P> </TD></TR>
</TABLE>
</A>
</TD>
<TD>
<script type="text/javascript"><!--google_ad_client = "ca-pub-0665655683291467";
google_ad_slot = "0230365165";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</TD>
</TR>
</TABLE>
\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) <serialib@googlegroups.com>
\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

View File

@ -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<std::mutex> 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<std::mutex> 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;
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "regsaccess.h"
#include <string>
#include <memory>
#include <mutex>
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<serialib> m_serial;
std::mutex mx_uart;
};

View File

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

View File

@ -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);
};

12
hardware/xmake.lua Normal file
View File

@ -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")

View File

@ -13,6 +13,7 @@
#include <sane/sane_ex.h>
#include <huagao/hgscanner_error.h>
#include "scanner_const_opts.h"
#include <hardware.h>
@ -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)

View File

@ -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_;

View File

@ -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()

View File

@ -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",

View File

@ -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")
add_deps("usb")
add_deps("hardware")

View File

@ -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)

View File

@ -94,6 +94,17 @@ namespace utils
bool run_get_message(HWND hwnd, UINT filter_min = 0, UINT filter_max = 0, std::function<bool(MSG*, bool*)> msghandler = std::function<bool(MSG*, bool*)>());
#endif
template<typename ... Args>
std::string format_string(const char* fmt, Args ... args)
{
size_t size = snprintf(nullptr, 0, fmt, args ...) + 2;
std::unique_ptr<char[]> buf(new char[size]);
snprintf(buf.get(), size, fmt, args ...);
return buf.get();
}
template<typename ... Args>
void to_log(int level, const char* fmt, Args ... args)
{

View File

@ -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

View File

@ -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:

View File

@ -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")